forked from Mirror/frr
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:
parent
36b5b98fef
commit
46c2687c72
130
lib/mlag.c
130
lib/mlag.c
|
@ -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;
|
||||
}
|
||||
|
|
84
lib/mlag.h
84
lib/mlag.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
162
pimd/pim_mlag.c
162
pimd/pim_mlag.c
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue