pimd, lib: adding support for MLAG Message processing at PIM

This includes:
1. Defining message formats
2. Stream Decoding after receiving the message at PIM
3. Handling MLAG UP & Down Notifications

Signed-off-by: Satheesh Kumar K <sathk@cumulusnetworks.com>
This commit is contained in:
Satheesh Kumar K 2019-11-12 00:17:13 -08:00
parent 36b5b98fef
commit 46c2687c72
7 changed files with 411 additions and 4 deletions

View file

@ -39,3 +39,133 @@ char *mlag_role2str(enum mlag_role role, char *buf, size_t size)
return buf;
}
char *zebra_mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf,
size_t size)
{
switch (msg_type) {
case MLAG_REGISTER:
snprintf(buf, size, "Register");
break;
case MLAG_DEREGISTER:
snprintf(buf, size, "De-Register");
break;
case MLAG_MROUTE_ADD:
snprintf(buf, size, "Mroute add");
break;
case MLAG_MROUTE_DEL:
snprintf(buf, size, "Mroute del");
break;
case MLAG_DUMP:
snprintf(buf, size, "Mlag Replay");
break;
case MLAG_MROUTE_ADD_BULK:
snprintf(buf, size, "Mroute Add Batch");
break;
case MLAG_MROUTE_DEL_BULK:
snprintf(buf, size, "Mroute Del Batch");
break;
case MLAG_STATUS_UPDATE:
snprintf(buf, size, "Mlag Status");
break;
case MLAG_VXLAN_UPDATE:
snprintf(buf, size, "Mlag vxlan update");
break;
case MLAG_PEER_FRR_STATUS:
snprintf(buf, size, "Mlag Peer FRR Status");
break;
default:
snprintf(buf, size, "Unknown %d", msg_type);
break;
}
return buf;
}
int zebra_mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->msg_type);
STREAM_GETW(s, msg->data_len);
STREAM_GETW(s, msg->msg_cnt);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mroute_add(struct stream *s,
struct mlag_mroute_add *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
STREAM_GETL(s, msg->source_ip);
STREAM_GETL(s, msg->group_ip);
STREAM_GETL(s, msg->cost_to_rp);
STREAM_GETL(s, msg->owner_id);
STREAM_GETC(s, msg->am_i_dr);
STREAM_GETC(s, msg->am_i_dual_active);
STREAM_GETL(s, msg->vrf_id);
STREAM_GET(msg->intf_name, s, INTERFACE_NAMSIZ);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mroute_del(struct stream *s,
struct mlag_mroute_del *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
STREAM_GETL(s, msg->source_ip);
STREAM_GETL(s, msg->group_ip);
STREAM_GETL(s, msg->owner_id);
STREAM_GETL(s, msg->vrf_id);
STREAM_GET(msg->intf_name, s, INTERFACE_NAMSIZ);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mlag_status(struct stream *s, struct mlag_status *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->peerlink_rif, s, INTERFACE_NAMSIZ);
STREAM_GETL(s, msg->my_role);
STREAM_GETL(s, msg->peer_state);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_vxlan_update(struct stream *s, struct mlag_vxlan *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->anycast_ip);
STREAM_GETL(s, msg->local_ip);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_frr_status(struct stream *s,
struct mlag_frr_status *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->frr_state);
return 0;
stream_failure:
return -1;
}

View file

@ -26,6 +26,10 @@
extern "C" {
#endif
#include "lib/if.h"
#include "lib/vrf.h"
#include "lib/stream.h"
#define MLAG_BUF_LIMIT 2048
enum mlag_role {
@ -34,9 +38,26 @@ enum mlag_role {
MLAG_ROLE_SECONDARY
};
enum mlag_state {
MLAG_STATE_DOWN,
MLAG_STATE_RUNNING,
};
enum mlag_frr_state {
MLAG_FRR_STATE_NONE,
MLAG_FRR_STATE_DOWN,
MLAG_FRR_STATE_UP,
};
enum mlag_owner {
MLAG_OWNER_NONE,
MLAG_OWNER_INTERFACE,
MLAG_OWNER_VXLAN,
};
/*
* This message definition should match mlag.proto
* Beacuse mesasge registartion is based on this
* Because message registration is based on this
*/
enum mlag_msg_type {
MLAG_MSG_NONE = 0,
@ -53,8 +74,67 @@ enum mlag_msg_type {
MLAG_PEER_FRR_STATUS = 12,
};
extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
struct mlag_frr_status {
enum mlag_frr_state frr_state;
};
struct mlag_status {
char peerlink_rif[INTERFACE_NAMSIZ];
enum mlag_role my_role;
enum mlag_state peer_state;
};
#define MLAG_ROLE_STRSIZE 16
struct mlag_vxlan {
uint32_t anycast_ip;
uint32_t local_ip;
};
struct mlag_mroute_add {
char vrf_name[VRF_NAMSIZ];
uint32_t source_ip;
uint32_t group_ip;
uint32_t cost_to_rp;
enum mlag_owner owner_id;
bool am_i_dr;
bool am_i_dual_active;
vrf_id_t vrf_id;
char intf_name[INTERFACE_NAMSIZ];
};
struct mlag_mroute_del {
char vrf_name[VRF_NAMSIZ];
uint32_t source_ip;
uint32_t group_ip;
enum mlag_owner owner_id;
vrf_id_t vrf_id;
char intf_name[INTERFACE_NAMSIZ];
};
struct mlag_msg {
enum mlag_msg_type msg_type;
uint16_t data_len;
uint16_t msg_cnt;
uint8_t data[0];
}__attribute__((packed));
extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
extern char *zebra_mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf,
size_t size);
extern int zebra_mlag_lib_decode_mlag_hdr(struct stream *s,
struct mlag_msg *msg);
extern int zebra_mlag_lib_decode_mroute_add(struct stream *s,
struct mlag_mroute_add *msg);
extern int zebra_mlag_lib_decode_mroute_del(struct stream *s,
struct mlag_mroute_del *msg);
extern int zebra_mlag_lib_decode_mlag_status(struct stream *s,
struct mlag_status *msg);
extern int zebra_mlag_lib_decode_vxlan_update(struct stream *s,
struct mlag_vxlan *msg);
extern int zebra_mlag_lib_decode_frr_status(struct stream *s,
struct mlag_frr_status *msg);
#ifdef __cplusplus
}
#endif

View file

@ -2754,6 +2754,24 @@ void zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
zclient_send_message(client);
}
static void zclient_mlag_process_up(ZAPI_CALLBACK_ARGS)
{
if (zclient->mlag_process_up)
(*zclient->mlag_process_up)();
}
static void zclient_mlag_process_down(ZAPI_CALLBACK_ARGS)
{
if (zclient->mlag_process_down)
(*zclient->mlag_process_down)();
}
static void zclient_mlag_handle_msg(ZAPI_CALLBACK_ARGS)
{
if (zclient->mlag_handle_msg)
(*zclient->mlag_handle_msg)(zclient->ibuf, length);
}
/* Zebra client message read function. */
static int zclient_read(struct thread *thread)
{
@ -3048,6 +3066,15 @@ static int zclient_read(struct thread *thread)
(*zclient->vxlan_sg_del)(command, zclient, length,
vrf_id);
break;
case ZEBRA_MLAG_PROCESS_UP:
zclient_mlag_process_up(command, zclient, length, vrf_id);
break;
case ZEBRA_MLAG_PROCESS_DOWN:
zclient_mlag_process_down(command, zclient, length, vrf_id);
break;
case ZEBRA_MLAG_FORWARD_MSG:
zclient_mlag_handle_msg(command, zclient, length, vrf_id);
break;
default:
break;
}

View file

@ -178,6 +178,8 @@ typedef enum {
ZEBRA_VXLAN_SG_ADD,
ZEBRA_VXLAN_SG_DEL,
ZEBRA_VXLAN_SG_REPLAY,
ZEBRA_MLAG_PROCESS_UP,
ZEBRA_MLAG_PROCESS_DOWN,
ZEBRA_MLAG_CLIENT_REGISTER,
ZEBRA_MLAG_CLIENT_UNREGISTER,
ZEBRA_MLAG_FORWARD_MSG,
@ -275,6 +277,9 @@ struct zclient {
int (*iptable_notify_owner)(ZAPI_CALLBACK_ARGS);
int (*vxlan_sg_add)(ZAPI_CALLBACK_ARGS);
int (*vxlan_sg_del)(ZAPI_CALLBACK_ARGS);
int (*mlag_process_up)(void);
int (*mlag_process_down)(void);
int (*mlag_handle_msg)(struct stream *msg, int len);
};
/* Zebra API message flag. */

View file

@ -28,6 +28,165 @@
extern struct zclient *zclient;
/********************API to process PIM MLAG Data ************************/
static void pim_mlag_process_mlagd_state_change(struct mlag_status msg)
{
char buf[MLAG_ROLE_STRSIZE];
if (PIM_DEBUG_MLAG)
zlog_debug("%s: msg dump: my_role: %s, peer_state: %s",
__func__,
mlag_role2str(msg.my_role, buf, sizeof(buf)),
(msg.peer_state == MLAG_STATE_RUNNING ? "RUNNING"
: "DOWN"));
}
static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg)
{
if (PIM_DEBUG_MLAG)
zlog_debug(
"%s: msg dump: peer_frr_state: %s", __func__,
(msg.frr_state == MLAG_FRR_STATE_UP ? "UP" : "DOWN"));
}
static void pim_mlag_process_vxlan_update(struct mlag_vxlan *msg)
{
}
static void pim_mlag_process_mroute_add(struct mlag_mroute_add msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug(
"%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x cost: %u",
__func__, msg.vrf_name, msg.source_ip, msg.group_ip,
msg.cost_to_rp);
zlog_debug(
"owner_id: %d, DR: %d, Dual active: %d, vrf_id: 0x%x intf_name: %s",
msg.owner_id, msg.am_i_dr, msg.am_i_dual_active,
msg.vrf_id, msg.intf_name);
}
}
static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug(
"%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x ",
__func__, msg.vrf_name, msg.source_ip, msg.group_ip);
zlog_debug("owner_id: %d, vrf_id: 0x%x intf_name: %s",
msg.owner_id, msg.vrf_id, msg.intf_name);
}
}
int pim_zebra_mlag_handle_msg(struct stream *s, int len)
{
struct mlag_msg mlag_msg;
char buf[ZLOG_FILTER_LENGTH_MAX];
int rc = 0;
rc = zebra_mlag_lib_decode_mlag_hdr(s, &mlag_msg);
if (rc)
return (rc);
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received msg type: %s length: %d, bulk_cnt: %d",
__func__,
zebra_mlag_lib_msgid_to_str(mlag_msg.msg_type, buf,
sizeof(buf)),
mlag_msg.data_len, mlag_msg.msg_cnt);
switch (mlag_msg.msg_type) {
case MLAG_STATUS_UPDATE: {
struct mlag_status msg;
rc = zebra_mlag_lib_decode_mlag_status(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mlagd_state_change(msg);
} break;
case MLAG_PEER_FRR_STATUS: {
struct mlag_frr_status msg;
rc = zebra_mlag_lib_decode_frr_status(s, &msg);
if (rc)
return (rc);
pim_mlag_process_peer_frr_state_change(msg);
} break;
case MLAG_VXLAN_UPDATE: {
struct mlag_vxlan msg;
rc = zebra_mlag_lib_decode_vxlan_update(s, &msg);
if (rc)
return rc;
pim_mlag_process_vxlan_update(&msg);
} break;
case MLAG_MROUTE_ADD: {
struct mlag_mroute_add msg;
rc = zebra_mlag_lib_decode_mroute_add(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_add(msg);
} break;
case MLAG_MROUTE_DEL: {
struct mlag_mroute_del msg;
rc = zebra_mlag_lib_decode_mroute_del(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_del(msg);
} break;
case MLAG_MROUTE_ADD_BULK: {
struct mlag_mroute_add msg;
int i = 0;
for (i = 0; i < mlag_msg.msg_cnt; i++) {
rc = zebra_mlag_lib_decode_mroute_add(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_add(msg);
}
} break;
case MLAG_MROUTE_DEL_BULK: {
struct mlag_mroute_del msg;
int i = 0;
for (i = 0; i < mlag_msg.msg_cnt; i++) {
rc = zebra_mlag_lib_decode_mroute_del(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_del(msg);
}
} break;
default:
break;
}
return 0;
}
/****************End of PIM Mesasge processing handler********************/
int pim_zebra_mlag_process_up(void)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Up from Mlag", __func__);
return 0;
}
int pim_zebra_mlag_process_down(void)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Down from Mlag", __func__);
return 0;
}
static int pim_mlag_register_handler(struct thread *thread)
{
uint32_t bit_mask = 0;
@ -132,8 +291,7 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
__func__, "NULL");
pim_ifp->activeactive = false;
if (pim_ifp->pim)
pim_ifp->pim->inst_mlag_intf_cnt--;
pim_ifp->pim->inst_mlag_intf_cnt--;
router->pim_mlag_intf_cnt--;
if (PIM_DEBUG_MLAG)

View file

@ -34,4 +34,7 @@ extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);
extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp);
extern void pim_mlag_register(void);
extern void pim_mlag_deregister(void);
extern int pim_zebra_mlag_process_up(void);
extern int pim_zebra_mlag_process_down(void);
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
#endif

View file

@ -46,6 +46,7 @@
#include "pim_nht.h"
#include "pim_ssm.h"
#include "pim_vxlan.h"
#include "pim_mlag.h"
#undef PIM_DEBUG_IFADDR_DUMP
#define PIM_DEBUG_IFADDR_DUMP
@ -587,6 +588,9 @@ void pim_zebra_init(void)
zclient->nexthop_update = pim_parse_nexthop_update;
zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
zclient->mlag_process_up = pim_zebra_mlag_process_up;
zclient->mlag_process_down = pim_zebra_mlag_process_down;
zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
if (PIM_DEBUG_PIM_TRACE) {