mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
Merge pull request #5839 from donaldsharp/upstream_merge
Upstream merge of missed MLAG code
This commit is contained in:
commit
7f6c322d50
@ -174,6 +174,13 @@ PIM interface commands allow you to configure an interface as either a Receiver
|
||||
or a interface that you would like to form pim neighbors on. If the interface
|
||||
is in a vrf, enter the interface command with the vrf keyword at the end.
|
||||
|
||||
.. index:: ip pim active-active
|
||||
.. clicmd:: ip pim active-active
|
||||
|
||||
Turn on pim active-active configuration for a Vxlan interface. This
|
||||
command will not do anything if you do not have the underlying ability
|
||||
of a mlag implementation.
|
||||
|
||||
.. index:: ip pim bfd
|
||||
.. clicmd:: ip pim bfd
|
||||
|
||||
@ -392,6 +399,11 @@ cause great confusion.
|
||||
|
||||
Display information about interfaces PIM is using.
|
||||
|
||||
.. index:: show ip pim mlag [vrf NAME] interface [detail|WORD] [json]
|
||||
.. clicmd:: show ip pim mlag [vrf NAME|all] interface [detail|WORD] [json]
|
||||
|
||||
Display mlag interface information.
|
||||
|
||||
.. index:: show ip pim [vrf NAME] join [A.B.C.D [A.B.C.D]] [json]
|
||||
.. clicmd:: show ip pim join
|
||||
|
||||
@ -404,6 +416,11 @@ cause great confusion.
|
||||
|
||||
Display information about PIM interface local-membership.
|
||||
|
||||
.. index:: show ip pim mlag summary [json]
|
||||
.. clicmd:: show ip pim mlag summary [json]
|
||||
|
||||
Display mlag information state that PIM is keeping track of.
|
||||
|
||||
.. index:: show ip pim neighbor
|
||||
.. clicmd:: show ip pim neighbor
|
||||
|
||||
|
28
lib/mlag.c
28
lib/mlag.c
@ -81,22 +81,33 @@ char *mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf, size_t size)
|
||||
}
|
||||
|
||||
|
||||
int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg)
|
||||
int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg,
|
||||
size_t *length)
|
||||
{
|
||||
if (s == NULL || msg == NULL)
|
||||
#define LIB_MLAG_HDR_LENGTH 8
|
||||
*length = stream_get_endp(s);
|
||||
|
||||
if (s == NULL || msg == NULL || *length < LIB_MLAG_HDR_LENGTH)
|
||||
return -1;
|
||||
|
||||
*length -= LIB_MLAG_HDR_LENGTH;
|
||||
|
||||
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 mlag_lib_decode_mroute_add(struct stream *s, struct mlag_mroute_add *msg)
|
||||
#define MLAG_MROUTE_ADD_LENGTH \
|
||||
(VRF_NAMSIZ + INTERFACE_NAMSIZ + 4 + 4 + 4 + 4 + 1 + 1 + 4)
|
||||
|
||||
int mlag_lib_decode_mroute_add(struct stream *s, struct mlag_mroute_add *msg,
|
||||
size_t *length)
|
||||
{
|
||||
if (s == NULL || msg == NULL)
|
||||
if (s == NULL || msg == NULL || *length < MLAG_MROUTE_ADD_LENGTH)
|
||||
return -1;
|
||||
|
||||
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
|
||||
@ -108,14 +119,18 @@ int mlag_lib_decode_mroute_add(struct stream *s, struct mlag_mroute_add *msg)
|
||||
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 mlag_lib_decode_mroute_del(struct stream *s, struct mlag_mroute_del *msg)
|
||||
#define MLAG_MROUTE_DEL_LENGTH (VRF_NAMSIZ + INTERFACE_NAMSIZ + 4 + 4 + 4 + 4)
|
||||
|
||||
int mlag_lib_decode_mroute_del(struct stream *s, struct mlag_mroute_del *msg,
|
||||
size_t *length)
|
||||
{
|
||||
if (s == NULL || msg == NULL)
|
||||
if (s == NULL || msg == NULL || *length < MLAG_MROUTE_DEL_LENGTH)
|
||||
return -1;
|
||||
|
||||
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
|
||||
@ -124,6 +139,7 @@ int mlag_lib_decode_mroute_del(struct stream *s, struct mlag_mroute_del *msg)
|
||||
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;
|
||||
|
@ -125,11 +125,14 @@ struct mlag_msg {
|
||||
extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
|
||||
extern char *mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf,
|
||||
size_t size);
|
||||
extern int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg);
|
||||
extern int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg,
|
||||
size_t *length);
|
||||
extern int mlag_lib_decode_mroute_add(struct stream *s,
|
||||
struct mlag_mroute_add *msg);
|
||||
struct mlag_mroute_add *msg,
|
||||
size_t *length);
|
||||
extern int mlag_lib_decode_mroute_del(struct stream *s,
|
||||
struct mlag_mroute_del *msg);
|
||||
struct mlag_mroute_del *msg,
|
||||
size_t *length);
|
||||
extern int mlag_lib_decode_mlag_status(struct stream *s,
|
||||
struct mlag_status *msg);
|
||||
extern int mlag_lib_decode_vxlan_update(struct stream *s,
|
||||
|
269
pimd/pim_cmd.c
269
pimd/pim_cmd.c
@ -909,7 +909,7 @@ static void igmp_show_interface_join(struct pim_instance *pim, struct vty *vty)
|
||||
|
||||
static void pim_show_interfaces_single(struct pim_instance *pim,
|
||||
struct vty *vty, const char *ifname,
|
||||
bool uj)
|
||||
bool mlag, bool uj)
|
||||
{
|
||||
struct in_addr ifaddr;
|
||||
struct interface *ifp;
|
||||
@ -952,6 +952,9 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
|
||||
if (!pim_ifp)
|
||||
continue;
|
||||
|
||||
if (mlag == true && pim_ifp->activeactive == false)
|
||||
continue;
|
||||
|
||||
if (strcmp(ifname, "detail") && strcmp(ifname, ifp->name))
|
||||
continue;
|
||||
|
||||
@ -1380,7 +1383,7 @@ static void igmp_show_statistics(struct pim_instance *pim, struct vty *vty,
|
||||
}
|
||||
|
||||
static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||
bool uj)
|
||||
bool mlag, bool uj)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct pim_interface *pim_ifp;
|
||||
@ -1400,6 +1403,9 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||
if (!pim_ifp)
|
||||
continue;
|
||||
|
||||
if (mlag == true && pim_ifp->activeactive == false)
|
||||
continue;
|
||||
|
||||
pim_nbrs = pim_ifp->pim_neighbor_list->count;
|
||||
pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
|
||||
fhr = 0;
|
||||
@ -4295,6 +4301,113 @@ DEFUN (show_ip_igmp_statistics,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_pim_mlag_summary,
|
||||
show_ip_pim_mlag_summary_cmd,
|
||||
"show ip pim mlag summary [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"MLAG\n"
|
||||
"status and stats\n"
|
||||
JSON_STR)
|
||||
{
|
||||
bool uj = use_json(argc, argv);
|
||||
char role_buf[MLAG_ROLE_STRSIZE];
|
||||
char addr_buf[INET_ADDRSTRLEN];
|
||||
|
||||
if (uj) {
|
||||
json_object *json = NULL;
|
||||
json_object *json_stat = NULL;
|
||||
|
||||
json = json_object_new_object();
|
||||
if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||
json_object_boolean_true_add(json, "mlagConnUp");
|
||||
if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||
json_object_boolean_true_add(json, "mlagPeerConnUp");
|
||||
if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||
json_object_boolean_true_add(json, "mlagPeerZebraUp");
|
||||
json_object_string_add(json, "mlagRole",
|
||||
mlag_role2str(router->mlag_role,
|
||||
role_buf, sizeof(role_buf)));
|
||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
json_object_string_add(json, "localVtepIp", addr_buf);
|
||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
json_object_string_add(json, "anycastVtepIp", addr_buf);
|
||||
json_object_string_add(json, "peerlinkRif",
|
||||
router->peerlink_rif);
|
||||
|
||||
json_stat = json_object_new_object();
|
||||
json_object_int_add(json_stat, "mlagConnFlaps",
|
||||
router->mlag_stats.mlagd_session_downs);
|
||||
json_object_int_add(json_stat, "mlagPeerConnFlaps",
|
||||
router->mlag_stats.peer_session_downs);
|
||||
json_object_int_add(json_stat, "mlagPeerZebraFlaps",
|
||||
router->mlag_stats.peer_zebra_downs);
|
||||
json_object_int_add(json_stat, "mrouteAddRx",
|
||||
router->mlag_stats.msg.mroute_add_rx);
|
||||
json_object_int_add(json_stat, "mrouteAddTx",
|
||||
router->mlag_stats.msg.mroute_add_tx);
|
||||
json_object_int_add(json_stat, "mrouteDelRx",
|
||||
router->mlag_stats.msg.mroute_del_rx);
|
||||
json_object_int_add(json_stat, "mrouteDelTx",
|
||||
router->mlag_stats.msg.mroute_del_tx);
|
||||
json_object_int_add(json_stat, "mlagStatusUpdates",
|
||||
router->mlag_stats.msg.mlag_status_updates);
|
||||
json_object_int_add(json_stat, "peerZebraStatusUpdates",
|
||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||
json_object_int_add(json_stat, "pimStatusUpdates",
|
||||
router->mlag_stats.msg.pim_status_updates);
|
||||
json_object_int_add(json_stat, "vxlanUpdates",
|
||||
router->mlag_stats.msg.vxlan_updates);
|
||||
json_object_object_add(json, "connStats", json_stat);
|
||||
|
||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
vty_out(vty, "MLAG daemon connection: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "MLAG peer state: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "Zebra peer state: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "MLAG role: %s\n",
|
||||
mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
|
||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
|
||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
|
||||
vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
|
||||
vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
|
||||
router->mlag_stats.mlagd_session_downs,
|
||||
router->mlag_stats.peer_session_downs,
|
||||
router->mlag_stats.peer_zebra_downs);
|
||||
vty_out(vty, "Message Statistics:\n");
|
||||
vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
|
||||
router->mlag_stats.msg.mroute_add_rx,
|
||||
router->mlag_stats.msg.mroute_add_tx);
|
||||
vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
|
||||
router->mlag_stats.msg.mroute_del_rx,
|
||||
router->mlag_stats.msg.mroute_del_tx);
|
||||
vty_out(vty, " peer zebra status updates: %d\n",
|
||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||
vty_out(vty, " PIM status updates: %d\n",
|
||||
router->mlag_stats.msg.pim_status_updates);
|
||||
vty_out(vty, " VxLAN updates: %d\n",
|
||||
router->mlag_stats.msg.vxlan_updates);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_pim_assert,
|
||||
show_ip_pim_assert_cmd,
|
||||
"show ip pim [vrf NAME] assert",
|
||||
@ -4377,10 +4490,11 @@ DEFUN (show_ip_pim_assert_winner_metric,
|
||||
|
||||
DEFUN (show_ip_pim_interface,
|
||||
show_ip_pim_interface_cmd,
|
||||
"show ip pim [vrf NAME] interface [detail|WORD] [json]",
|
||||
"show ip pim [mlag] [vrf NAME] interface [detail|WORD] [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"MLAG\n"
|
||||
VRF_CMD_HELP_STR
|
||||
"PIM interface information\n"
|
||||
"Detailed output\n"
|
||||
@ -4390,36 +4504,47 @@ DEFUN (show_ip_pim_interface,
|
||||
int idx = 2;
|
||||
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
|
||||
bool uj = use_json(argc, argv);
|
||||
bool mlag = false;
|
||||
|
||||
if (!vrf)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (argv_find(argv, argc, "mlag", &idx))
|
||||
mlag = true;
|
||||
|
||||
if (argv_find(argv, argc, "WORD", &idx)
|
||||
|| argv_find(argv, argc, "detail", &idx))
|
||||
pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, uj);
|
||||
pim_show_interfaces_single(vrf->info, vty, argv[idx]->arg, mlag,
|
||||
uj);
|
||||
else
|
||||
pim_show_interfaces(vrf->info, vty, uj);
|
||||
pim_show_interfaces(vrf->info, vty, mlag, uj);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_pim_interface_vrf_all,
|
||||
show_ip_pim_interface_vrf_all_cmd,
|
||||
"show ip pim vrf all interface [detail|WORD] [json]",
|
||||
"show ip pim [mlag] vrf all interface [detail|WORD] [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"MLAG\n"
|
||||
VRF_CMD_HELP_STR
|
||||
"PIM interface information\n"
|
||||
"Detailed output\n"
|
||||
"interface name\n"
|
||||
JSON_STR)
|
||||
{
|
||||
int idx = 6;
|
||||
int idx = 2;
|
||||
bool uj = use_json(argc, argv);
|
||||
struct vrf *vrf;
|
||||
bool first = true;
|
||||
bool mlag = false;
|
||||
|
||||
if (argv_find(argv, argc, "mlag", &idx))
|
||||
mlag = true;
|
||||
|
||||
idx = 6;
|
||||
if (uj)
|
||||
vty_out(vty, "{ ");
|
||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||
@ -4433,9 +4558,9 @@ DEFUN (show_ip_pim_interface_vrf_all,
|
||||
if (argv_find(argv, argc, "WORD", &idx)
|
||||
|| argv_find(argv, argc, "detail", &idx))
|
||||
pim_show_interfaces_single(vrf->info, vty,
|
||||
argv[idx]->arg, uj);
|
||||
argv[idx]->arg, mlag, uj);
|
||||
else
|
||||
pim_show_interfaces(vrf->info, vty, uj);
|
||||
pim_show_interfaces(vrf->info, vty, mlag, uj);
|
||||
}
|
||||
if (uj)
|
||||
vty_out(vty, "}\n");
|
||||
@ -4625,113 +4750,6 @@ DEFUN (show_ip_pim_local_membership,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ip_pim_mlag_summary,
|
||||
show_ip_pim_mlag_summary_cmd,
|
||||
"show ip pim mlag summary [json]",
|
||||
SHOW_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"MLAG\n"
|
||||
"status and stats\n"
|
||||
JSON_STR)
|
||||
{
|
||||
bool uj = use_json(argc, argv);
|
||||
char role_buf[MLAG_ROLE_STRSIZE];
|
||||
char addr_buf[INET_ADDRSTRLEN];
|
||||
|
||||
if (uj) {
|
||||
json_object *json = NULL;
|
||||
json_object *json_stat = NULL;
|
||||
|
||||
json = json_object_new_object();
|
||||
if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||
json_object_boolean_true_add(json, "mlagConnUp");
|
||||
if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||
json_object_boolean_true_add(json, "mlagPeerConnUp");
|
||||
if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||
json_object_boolean_true_add(json, "mlagPeerZebraUp");
|
||||
json_object_string_add(json, "mlagRole",
|
||||
mlag_role2str(router->mlag_role,
|
||||
role_buf, sizeof(role_buf)));
|
||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
json_object_string_add(json, "localVtepIp", addr_buf);
|
||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
json_object_string_add(json, "anycastVtepIp", addr_buf);
|
||||
json_object_string_add(json, "peerlinkRif",
|
||||
router->peerlink_rif);
|
||||
|
||||
json_stat = json_object_new_object();
|
||||
json_object_int_add(json_stat, "mlagConnFlaps",
|
||||
router->mlag_stats.mlagd_session_downs);
|
||||
json_object_int_add(json_stat, "mlagPeerConnFlaps",
|
||||
router->mlag_stats.peer_session_downs);
|
||||
json_object_int_add(json_stat, "mlagPeerZebraFlaps",
|
||||
router->mlag_stats.peer_zebra_downs);
|
||||
json_object_int_add(json_stat, "mrouteAddRx",
|
||||
router->mlag_stats.msg.mroute_add_rx);
|
||||
json_object_int_add(json_stat, "mrouteAddTx",
|
||||
router->mlag_stats.msg.mroute_add_tx);
|
||||
json_object_int_add(json_stat, "mrouteDelRx",
|
||||
router->mlag_stats.msg.mroute_del_rx);
|
||||
json_object_int_add(json_stat, "mrouteDelTx",
|
||||
router->mlag_stats.msg.mroute_del_tx);
|
||||
json_object_int_add(json_stat, "mlagStatusUpdates",
|
||||
router->mlag_stats.msg.mlag_status_updates);
|
||||
json_object_int_add(json_stat, "peerZebraStatusUpdates",
|
||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||
json_object_int_add(json_stat, "pimStatusUpdates",
|
||||
router->mlag_stats.msg.pim_status_updates);
|
||||
json_object_int_add(json_stat, "vxlanUpdates",
|
||||
router->mlag_stats.msg.vxlan_updates);
|
||||
json_object_object_add(json, "connStats", json_stat);
|
||||
|
||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||
json, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_free(json);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
vty_out(vty, "MLAG daemon connection: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "MLAG peer state: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "Zebra peer state: %s\n",
|
||||
(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
|
||||
? "up" : "down");
|
||||
vty_out(vty, "MLAG role: %s\n",
|
||||
mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
|
||||
inet_ntop(AF_INET, &router->local_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
|
||||
inet_ntop(AF_INET, &router->anycast_vtep_ip,
|
||||
addr_buf, INET_ADDRSTRLEN);
|
||||
vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
|
||||
vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
|
||||
vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
|
||||
router->mlag_stats.mlagd_session_downs,
|
||||
router->mlag_stats.peer_session_downs,
|
||||
router->mlag_stats.peer_zebra_downs);
|
||||
vty_out(vty, "Message Statistics:\n");
|
||||
vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
|
||||
router->mlag_stats.msg.mroute_add_rx,
|
||||
router->mlag_stats.msg.mroute_add_tx);
|
||||
vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
|
||||
router->mlag_stats.msg.mroute_del_rx,
|
||||
router->mlag_stats.msg.mroute_del_tx);
|
||||
vty_out(vty, " peer zebra status updates: %d\n",
|
||||
router->mlag_stats.msg.peer_zebra_status_updates);
|
||||
vty_out(vty, " PIM status updates: %d\n",
|
||||
router->mlag_stats.msg.pim_status_updates);
|
||||
vty_out(vty, " VxLAN updates: %d\n",
|
||||
router->mlag_stats.msg.vxlan_updates);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
|
||||
struct vty *vty, struct pim_upstream *up,
|
||||
char *src_str, char *grp_str, json_object *json)
|
||||
@ -8039,13 +8057,13 @@ DEFPY_HIDDEN (pim_test_sg_keepalive,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY_HIDDEN (interface_ip_pim_activeactive,
|
||||
interface_ip_pim_activeactive_cmd,
|
||||
"[no$no] ip pim active-active",
|
||||
NO_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
|
||||
DEFPY (interface_ip_pim_activeactive,
|
||||
interface_ip_pim_activeactive_cmd,
|
||||
"[no$no] ip pim active-active",
|
||||
NO_STR
|
||||
IP_STR
|
||||
PIM_STR
|
||||
"Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct pim_interface *pim_ifp;
|
||||
@ -8055,6 +8073,11 @@ DEFPY_HIDDEN (interface_ip_pim_activeactive,
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug("%sConfiguring PIM active-active on Interface: %s",
|
||||
no ? "Un-":" ", ifp->name);
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
if (no)
|
||||
pim_if_unconfigure_mlag_dualactive(pim_ifp);
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(options) ((options) &= ~PIM_IF_MASK_PIM_CAN_DISABLE_JOIN_SUPRESSION)
|
||||
|
||||
#define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr
|
||||
#define PIM_I_am_DualActive(pim_ifp) (pim_ifp)->activeactive == true
|
||||
|
||||
struct pim_iface_upstream_switch {
|
||||
struct in_addr address;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "pim_upstream.h"
|
||||
#include "pim_ssm.h"
|
||||
#include "pim_rp.h"
|
||||
#include "pim_mlag.h"
|
||||
|
||||
RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb, pim_ifchannel_compare);
|
||||
|
||||
@ -127,9 +128,29 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
|
||||
void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
struct pim_upstream *up;
|
||||
|
||||
pim_ifp = ch->interface->info;
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
zlog_debug("%s: ifchannel entry %s(%s) del start", __func__,
|
||||
ch->sg_str, ch->interface->name);
|
||||
|
||||
if (PIM_I_am_DualActive(pim_ifp)) {
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug(
|
||||
"%s: if-chnanel-%s is deleted from a Dual "
|
||||
"active Interface",
|
||||
__func__, ch->sg_str);
|
||||
/* Post Delete only if it is the last Dual-active Interface */
|
||||
if (ch->upstream->dualactive_ifchannel_count == 1) {
|
||||
pim_mlag_up_local_del(pim_ifp->pim, ch->upstream);
|
||||
PIM_UPSTREAM_FLAG_UNSET_MLAG_INTERFACE(
|
||||
ch->upstream->flags);
|
||||
}
|
||||
ch->upstream->dualactive_ifchannel_count--;
|
||||
}
|
||||
|
||||
if (ch->upstream->channel_oil) {
|
||||
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
|
||||
if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
|
||||
@ -181,14 +202,14 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
|
||||
listnode_delete(ch->upstream->ifchannels, ch);
|
||||
|
||||
pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
|
||||
up = ch->upstream;
|
||||
|
||||
/* upstream is common across ifchannels, check if upstream's
|
||||
ifchannel list is empty before deleting upstream_del
|
||||
ref count will take care of it.
|
||||
*/
|
||||
if (ch->upstream->ref_count > 0)
|
||||
pim_upstream_del(pim_ifp->pim, ch->upstream, __func__);
|
||||
up = pim_upstream_del(pim_ifp->pim, ch->upstream, __func__);
|
||||
|
||||
else {
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
@ -217,6 +238,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
|
||||
ch->sg_str);
|
||||
|
||||
XFREE(MTYPE_PIM_IFCHANNEL, ch);
|
||||
|
||||
if (up)
|
||||
pim_upstream_update_join_desired(pim_ifp->pim, up);
|
||||
}
|
||||
|
||||
void pim_ifchannel_delete_all(struct interface *ifp)
|
||||
@ -586,9 +610,27 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
|
||||
else
|
||||
PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags);
|
||||
|
||||
/*
|
||||
* advertise MLAG Data to MLAG peer
|
||||
*/
|
||||
if (PIM_I_am_DualActive(pim_ifp)) {
|
||||
up->dualactive_ifchannel_count++;
|
||||
/* Sync once for upstream */
|
||||
if (up->dualactive_ifchannel_count == 1) {
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(up->flags);
|
||||
pim_mlag_up_local_add(pim_ifp->pim, up);
|
||||
}
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug(
|
||||
"%s: New Dual active if-chnanel is added to upstream:%s "
|
||||
"count:%d, flags:0x%x",
|
||||
__func__, up->sg_str,
|
||||
up->dualactive_ifchannel_count, up->flags);
|
||||
}
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
zlog_debug("%s: ifchannel %s is created ", __func__,
|
||||
ch->sg_str);
|
||||
zlog_debug("%s: ifchannel %s(%s) is created ", __func__,
|
||||
ch->sg_str, ch->interface->name);
|
||||
|
||||
return ch;
|
||||
}
|
||||
@ -1073,6 +1115,9 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
|
||||
}
|
||||
}
|
||||
|
||||
/* vxlan term mroutes use ipmr-lo as local member to
|
||||
* pull down multicast vxlan tunnel traffic
|
||||
*/
|
||||
up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
|
||||
PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
|
||||
ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
|
||||
|
@ -157,6 +157,7 @@ int pim_macro_ch_lost_assert(const struct pim_ifchannel *ch)
|
||||
int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ch->interface->info;
|
||||
bool mlag_active = false;
|
||||
|
||||
if (!pim_ifp) {
|
||||
zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s",
|
||||
@ -172,9 +173,21 @@ int pim_macro_chisin_pim_include(const struct pim_ifchannel *ch)
|
||||
if (ch->ifassert_winner.s_addr == pim_ifp->primary_address.s_addr)
|
||||
return 1; /* true */
|
||||
|
||||
/*
|
||||
* When we have a activeactive interface we need to signal
|
||||
* that this interface is interesting to the upstream
|
||||
* decision to JOIN *if* we are syncing over the interface
|
||||
*/
|
||||
if (pim_ifp->activeactive) {
|
||||
struct pim_upstream *up = ch->upstream;
|
||||
|
||||
if (PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
|
||||
mlag_active = true;
|
||||
}
|
||||
|
||||
return (
|
||||
/* I_am_DR( I ) ? */
|
||||
PIM_I_am_DR(pim_ifp) &&
|
||||
(PIM_I_am_DR(pim_ifp) || mlag_active) &&
|
||||
/* lost_assert(S,G,I) == false ? */
|
||||
(!pim_macro_ch_lost_assert(ch)));
|
||||
}
|
||||
|
127
pimd/pim_mlag.c
127
pimd/pim_mlag.c
@ -32,6 +32,76 @@ extern struct zclient *zclient;
|
||||
|
||||
#define PIM_MLAG_METADATA_LEN 4
|
||||
|
||||
/*********************ACtual Data processing *****************************/
|
||||
/* TBD: There can be duplicate updates to FIB***/
|
||||
#define PIM_MLAG_ADD_OIF_TO_OIL(ch, ch_oil) \
|
||||
do { \
|
||||
if (PIM_DEBUG_MLAG) \
|
||||
zlog_debug( \
|
||||
"%s: add Dual-active Interface to %s " \
|
||||
"to oil:%s", \
|
||||
__func__, ch->interface->name, ch->sg_str); \
|
||||
pim_channel_add_oif(ch_oil, ch->interface, \
|
||||
PIM_OIF_FLAG_PROTO_IGMP, __func__); \
|
||||
} while (0)
|
||||
|
||||
#define PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil) \
|
||||
do { \
|
||||
if (PIM_DEBUG_MLAG) \
|
||||
zlog_debug( \
|
||||
"%s: del Dual-active Interface to %s " \
|
||||
"to oil:%s", \
|
||||
__func__, ch->interface->name, ch->sg_str); \
|
||||
pim_channel_del_oif(ch_oil, ch->interface, \
|
||||
PIM_OIF_FLAG_PROTO_IGMP, __func__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void pim_mlag_calculate_df_for_ifchannels(struct pim_upstream *up,
|
||||
bool is_df)
|
||||
{
|
||||
struct listnode *chnode;
|
||||
struct listnode *chnextnode;
|
||||
struct pim_ifchannel *ch;
|
||||
struct pim_interface *pim_ifp = NULL;
|
||||
struct channel_oil *ch_oil = NULL;
|
||||
|
||||
ch_oil = (up) ? up->channel_oil : NULL;
|
||||
|
||||
if (!ch_oil)
|
||||
return;
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug("%s: Calculating DF for Dual active if-channel%s",
|
||||
__func__, up->sg_str);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
|
||||
pim_ifp = (ch->interface) ? ch->interface->info : NULL;
|
||||
if (!pim_ifp || !PIM_I_am_DualActive(pim_ifp))
|
||||
continue;
|
||||
|
||||
if (is_df)
|
||||
PIM_MLAG_ADD_OIF_TO_OIL(ch, ch_oil);
|
||||
else
|
||||
PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil);
|
||||
}
|
||||
}
|
||||
|
||||
static void pim_mlag_inherit_mlag_flags(struct pim_upstream *up, bool is_df)
|
||||
{
|
||||
struct listnode *listnode;
|
||||
struct pim_upstream *child;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(up->sources, listnode, child)) {
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_PEER(child->flags);
|
||||
if (is_df)
|
||||
PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(child->flags);
|
||||
else
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags);
|
||||
pim_mlag_calculate_df_for_ifchannels(child, is_df);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************* pim upstream sync **************************/
|
||||
/* Update DF role for the upstream entry and return true on role change */
|
||||
bool pim_mlag_up_df_role_update(struct pim_instance *pim,
|
||||
@ -59,6 +129,15 @@ bool pim_mlag_up_df_role_update(struct pim_instance *pim,
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(up->flags);
|
||||
|
||||
|
||||
/*
|
||||
* This Upstream entry synced to peer Because of Dual-active
|
||||
* Interface configuration
|
||||
*/
|
||||
if (PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)) {
|
||||
pim_mlag_calculate_df_for_ifchannels(up, is_df);
|
||||
pim_mlag_inherit_mlag_flags(up, is_df);
|
||||
}
|
||||
|
||||
/* If the DF role has changed check if ipmr-lo needs to be
|
||||
* muted/un-muted. Active-Active devices and vxlan termination
|
||||
* devices (ipmr-lo) are suppressed on the non-DF.
|
||||
@ -91,7 +170,8 @@ static bool pim_mlag_up_df_role_elect(struct pim_instance *pim,
|
||||
uint32_t local_cost;
|
||||
bool rv;
|
||||
|
||||
if (!pim_up_mlag_is_local(up))
|
||||
if (!pim_up_mlag_is_local(up)
|
||||
&& !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
|
||||
return false;
|
||||
|
||||
/* We are yet to rx a status update from the local MLAG daemon so
|
||||
@ -316,14 +396,6 @@ static void pim_mlag_up_peer_del_all(void)
|
||||
list_delete(&temp);
|
||||
}
|
||||
|
||||
static int pim_mlag_signal_zpthread(void)
|
||||
{
|
||||
/* XXX - This is a temporary stub; the MLAG thread code is planned for
|
||||
* a separate commit
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Send upstream entry to the local MLAG daemon (which will subsequently
|
||||
* send it to the peer MLAG switch).
|
||||
*/
|
||||
@ -429,7 +501,8 @@ static void pim_mlag_up_local_replay(void)
|
||||
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
|
||||
pim = vrf->info;
|
||||
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
||||
if (pim_up_mlag_is_local(up))
|
||||
if (pim_up_mlag_is_local(up)
|
||||
|| PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
|
||||
pim_mlag_up_local_add_send(pim, up);
|
||||
}
|
||||
}
|
||||
@ -450,7 +523,9 @@ static void pim_mlag_up_local_reeval(bool mlagd_send, const char *reason_code)
|
||||
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
|
||||
pim = vrf->info;
|
||||
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
|
||||
if (!pim_up_mlag_is_local(up))
|
||||
if (!pim_up_mlag_is_local(up)
|
||||
&& !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(
|
||||
up->flags))
|
||||
continue;
|
||||
/* if role changes re-send to peer */
|
||||
if (pim_mlag_up_df_role_elect(pim, up) &&
|
||||
@ -694,8 +769,9 @@ 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;
|
||||
size_t length;
|
||||
|
||||
rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg);
|
||||
rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg, &length);
|
||||
if (rc)
|
||||
return (rc);
|
||||
|
||||
@ -734,7 +810,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)
|
||||
case MLAG_MROUTE_ADD: {
|
||||
struct mlag_mroute_add msg;
|
||||
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg, &length);
|
||||
if (rc)
|
||||
return (rc);
|
||||
pim_mlag_process_mroute_add(msg);
|
||||
@ -742,7 +818,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)
|
||||
case MLAG_MROUTE_DEL: {
|
||||
struct mlag_mroute_del msg;
|
||||
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg, &length);
|
||||
if (rc)
|
||||
return (rc);
|
||||
pim_mlag_process_mroute_del(msg);
|
||||
@ -752,8 +828,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg, &length);
|
||||
if (rc)
|
||||
return (rc);
|
||||
pim_mlag_process_mroute_add(msg);
|
||||
@ -764,8 +839,7 @@ int pim_zebra_mlag_handle_msg(struct stream *s, int len)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg, &length);
|
||||
if (rc)
|
||||
return (rc);
|
||||
pim_mlag_process_mroute_del(msg);
|
||||
@ -784,6 +858,12 @@ int pim_zebra_mlag_process_up(void)
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug("%s: Received Process-Up from Mlag", __func__);
|
||||
|
||||
/*
|
||||
* Incase of local MLAG restart, PIM needs to replay all the data
|
||||
* since MLAG is empty.
|
||||
*/
|
||||
router->connected_to_mlag = true;
|
||||
router->mlag_flags |= PIM_MLAGF_LOCAL_CONN_UP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -876,7 +956,7 @@ static int pim_mlag_deregister_handler(struct thread *thread)
|
||||
void pim_mlag_deregister(void)
|
||||
{
|
||||
/* if somebody still interested in the MLAG channel skip de-reg */
|
||||
if (router->pim_mlag_intf_cnt)
|
||||
if (router->pim_mlag_intf_cnt || pim_vxlan_do_mlag_reg())
|
||||
return;
|
||||
|
||||
/* not registered; nothing do */
|
||||
@ -894,10 +974,6 @@ void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
|
||||
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
|
||||
return;
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug("%s: Configuring active-active on Interface: %s",
|
||||
__func__, "NULL");
|
||||
|
||||
pim_ifp->activeactive = true;
|
||||
if (pim_ifp->pim)
|
||||
pim_ifp->pim->inst_mlag_intf_cnt++;
|
||||
@ -923,10 +999,6 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
|
||||
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
|
||||
return;
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug("%s: UnConfiguring active-active on Interface: %s",
|
||||
__func__, "NULL");
|
||||
|
||||
pim_ifp->activeactive = false;
|
||||
pim_ifp->pim->inst_mlag_intf_cnt--;
|
||||
|
||||
@ -943,6 +1015,7 @@ void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
|
||||
* De-register to Zebra
|
||||
*/
|
||||
pim_mlag_deregister();
|
||||
pim_mlag_param_reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,15 +32,22 @@ extern void pim_instance_mlag_init(struct pim_instance *pim);
|
||||
extern void pim_instance_mlag_terminate(struct pim_instance *pim);
|
||||
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);
|
||||
|
||||
/* pm_zpthread.c */
|
||||
extern int pim_mlag_signal_zpthread(void);
|
||||
extern void pim_zpthread_init(void);
|
||||
extern void pim_zpthread_terminate(void);
|
||||
|
||||
extern void pim_mlag_register(void);
|
||||
extern void pim_mlag_deregister(void);
|
||||
extern void pim_mlag_up_local_add(struct pim_instance *pim,
|
||||
struct pim_upstream *upstream);
|
||||
struct pim_upstream *upstream);
|
||||
extern void pim_mlag_up_local_del(struct pim_instance *pim,
|
||||
struct pim_upstream *upstream);
|
||||
struct pim_upstream *upstream);
|
||||
extern bool pim_mlag_up_df_role_update(struct pim_instance *pim,
|
||||
struct pim_upstream *up, bool is_df, const char *reason);
|
||||
struct pim_upstream *up, bool is_df,
|
||||
const char *reason);
|
||||
#endif
|
||||
|
@ -443,6 +443,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
|
||||
{
|
||||
const struct ip *ip_hdr = (const struct ip *)buf;
|
||||
struct pim_interface *pim_ifp;
|
||||
struct pim_instance *pim;
|
||||
struct pim_ifchannel *ch;
|
||||
struct pim_upstream *up;
|
||||
struct prefix_sg star_g;
|
||||
@ -465,16 +466,18 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
|
||||
|
||||
star_g = sg;
|
||||
star_g.src.s_addr = INADDR_ANY;
|
||||
#if 0
|
||||
ch = pim_ifchannel_find(ifp, &star_g);
|
||||
if (ch)
|
||||
{
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
zlog_debug ("WRVIFWHOLE (*,G)=%s found ifchannel on interface %s",
|
||||
pim_str_sg_dump (&star_g), ifp->name);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
pim = pim_ifp->pim;
|
||||
/*
|
||||
* If the incoming interface is the pimreg, then
|
||||
* we know the callback is associated with a pim register
|
||||
* packet and there is nothing to do here as that
|
||||
* normal pim processing will see the packet and allow
|
||||
* us to do the right thing.
|
||||
*/
|
||||
if (ifp == pim->regiface) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
up = pim_upstream_find(pim_ifp->pim, &sg);
|
||||
if (up) {
|
||||
@ -502,8 +505,17 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
|
||||
* the pimreg period, so I believe we can ignore this packet
|
||||
*/
|
||||
if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) {
|
||||
// No if channel, but upstream we are at the RP.
|
||||
if (pim_nexthop_lookup(pim_ifp->pim, &source,
|
||||
/*
|
||||
* No if channel, but upstream we are at the RP.
|
||||
*
|
||||
* This could be a anycast RP too and we may
|
||||
* not have received a register packet from
|
||||
* the source here at all. So gracefully
|
||||
* bow out of doing a nexthop lookup and
|
||||
* setting the SPTBIT to true
|
||||
*/
|
||||
if (up->upstream_register.s_addr != INADDR_ANY &&
|
||||
pim_nexthop_lookup(pim_ifp->pim, &source,
|
||||
up->upstream_register, 0)) {
|
||||
pim_register_stop_send(source.interface, &sg,
|
||||
pim_ifp->primary_address,
|
||||
|
@ -33,9 +33,6 @@
|
||||
#include "pim_time.h"
|
||||
#include "pim_vxlan.h"
|
||||
|
||||
// struct list *pim_channel_oil_list = NULL;
|
||||
// struct hash *pim_channel_oil_hash = NULL;
|
||||
|
||||
static void pim_channel_update_mute(struct channel_oil *c_oil);
|
||||
|
||||
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
||||
@ -174,7 +171,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
|
||||
}
|
||||
|
||||
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
||||
const char *name)
|
||||
const char *name)
|
||||
{
|
||||
if (PIM_DEBUG_MROUTE) {
|
||||
struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
|
||||
@ -496,6 +493,23 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
|
||||
}
|
||||
}
|
||||
|
||||
if (PIM_DEBUG_MROUTE) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
pim_inet4_dump("<group?>",
|
||||
channel_oil->oil.mfcc_mcastgrp,
|
||||
group_str, sizeof(group_str));
|
||||
pim_inet4_dump("<source?>",
|
||||
channel_oil->oil.mfcc_origin, source_str,
|
||||
sizeof(source_str));
|
||||
zlog_debug(
|
||||
"%s(%s): (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d added to 0x%x",
|
||||
__func__, caller, source_str, group_str,
|
||||
proto_mask, oif->name,
|
||||
pim_ifp->mroute_vif_index,
|
||||
channel_oil
|
||||
->oif_flags[pim_ifp->mroute_vif_index]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ void pim_channel_oil_change_iif(struct pim_instance *pim,
|
||||
struct channel_oil *c_oil, int input_vif_index,
|
||||
const char *name);
|
||||
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
||||
const char *name);
|
||||
const char *name);
|
||||
|
||||
int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
|
||||
uint32_t proto_mask, const char *caller);
|
||||
@ -146,6 +146,6 @@ void pim_channel_update_oif_mute(struct channel_oil *c_oil,
|
||||
|
||||
void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
|
||||
void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
|
||||
struct interface *oif, const char *caller);
|
||||
struct interface *oif, const char *caller);
|
||||
|
||||
#endif /* PIM_OIL_H */
|
||||
|
@ -57,6 +57,7 @@
|
||||
static void join_timer_stop(struct pim_upstream *up);
|
||||
static void
|
||||
pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);
|
||||
static bool pim_upstream_sg_running_proc(struct pim_upstream *up);
|
||||
|
||||
/*
|
||||
* A (*,G) or a (*,*) is going away
|
||||
@ -141,6 +142,18 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,
|
||||
if (up)
|
||||
listnode_add(up->sources, child);
|
||||
|
||||
/*
|
||||
* In case parent is MLAG entry copy the data to child
|
||||
*/
|
||||
if (up && PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)) {
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(child->flags);
|
||||
if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags))
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags);
|
||||
else
|
||||
PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(
|
||||
child->flags);
|
||||
}
|
||||
|
||||
return up;
|
||||
}
|
||||
|
||||
@ -853,9 +866,23 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
|
||||
up->ifchannels = list_new();
|
||||
up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
|
||||
|
||||
if (up->sg.src.s_addr != INADDR_ANY)
|
||||
if (up->sg.src.s_addr != INADDR_ANY) {
|
||||
wheel_add_item(pim->upstream_sg_wheel, up);
|
||||
|
||||
/* Inherit the DF role from the parent (*, G) entry for
|
||||
* VxLAN BUM groups
|
||||
*/
|
||||
if (up->parent
|
||||
&& PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->parent->flags)
|
||||
&& PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->parent->flags)) {
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(up->flags);
|
||||
if (PIM_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"upstream %s inherited mlag non-df flag from parent",
|
||||
up->sg_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)
|
||||
|| PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)) {
|
||||
pim_upstream_fill_static_iif(up, incoming);
|
||||
@ -885,24 +912,12 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
|
||||
}
|
||||
}
|
||||
|
||||
/* If (S, G) inherit the MLAG_VXLAN from the parent
|
||||
* (*, G) entry.
|
||||
*/
|
||||
if ((up->sg.src.s_addr != INADDR_ANY) &&
|
||||
up->parent &&
|
||||
PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->parent->flags) &&
|
||||
!PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags)) {
|
||||
PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(up->flags);
|
||||
if (PIM_DEBUG_VXLAN)
|
||||
zlog_debug("upstream %s inherited mlag vxlan flag from parent",
|
||||
up->sg_str);
|
||||
}
|
||||
|
||||
/* send the entry to the MLAG peer */
|
||||
/* XXX - duplicate send is possible here if pim_rpf_update
|
||||
* successfully resolved the nexthop
|
||||
*/
|
||||
if (pim_up_mlag_is_local(up))
|
||||
if (pim_up_mlag_is_local(up)
|
||||
|| PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))
|
||||
pim_mlag_up_local_add(pim, up);
|
||||
|
||||
if (PIM_DEBUG_PIM_TRACE) {
|
||||
@ -917,7 +932,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
|
||||
|
||||
uint32_t pim_up_mlag_local_cost(struct pim_upstream *up)
|
||||
{
|
||||
if (!(pim_up_mlag_is_local(up)))
|
||||
if (!(pim_up_mlag_is_local(up))
|
||||
&& !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
|
||||
return router->infinite_assert_metric.route_metric;
|
||||
|
||||
if ((up->rpf.source_nexthop.interface ==
|
||||
@ -1438,6 +1454,11 @@ static int pim_upstream_keep_alive_timer(struct thread *t)
|
||||
|
||||
up = THREAD_ARG(t);
|
||||
|
||||
/* pull the stats and re-check */
|
||||
if (pim_upstream_sg_running_proc(up))
|
||||
/* kat was restarted because of new activity */
|
||||
return 0;
|
||||
|
||||
pim_upstream_keep_alive_timer_proc(up);
|
||||
return 0;
|
||||
}
|
||||
@ -1751,6 +1772,7 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
|
||||
up->sg_str);
|
||||
|
||||
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
||||
struct pim_interface *pim_ifp;
|
||||
if (!ifp->info)
|
||||
continue;
|
||||
|
||||
@ -1764,6 +1786,12 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
|
||||
if (!ch && !starch)
|
||||
continue;
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
if (PIM_I_am_DualActive(pim_ifp)
|
||||
&& PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)
|
||||
&& (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)
|
||||
|| !PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags)))
|
||||
continue;
|
||||
if (pim_upstream_evaluate_join_desired_interface(up, ch,
|
||||
starch)) {
|
||||
int flag = PIM_OIF_FLAG_PROTO_PIM;
|
||||
@ -1943,39 +1971,14 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code to check and see if we've received packets on a S,G mroute
|
||||
* and if so to set the SPT bit appropriately
|
||||
*/
|
||||
static void pim_upstream_sg_running(void *arg)
|
||||
static bool pim_upstream_sg_running_proc(struct pim_upstream *up)
|
||||
{
|
||||
struct pim_upstream *up = (struct pim_upstream *)arg;
|
||||
struct pim_instance *pim = up->channel_oil->pim;
|
||||
bool rv = false;
|
||||
struct pim_instance *pim = up->pim;
|
||||
|
||||
// No packet can have arrived here if this is the case
|
||||
if (!up->channel_oil->installed) {
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
zlog_debug("%s: %s%s is not installed in mroute",
|
||||
__func__, up->sg_str, pim->vrf->name);
|
||||
return;
|
||||
}
|
||||
if (!up->channel_oil->installed)
|
||||
return rv;
|
||||
|
||||
/*
|
||||
* This is a bit of a hack
|
||||
* We've noted that we should rescan but
|
||||
* we've missed the window for doing so in
|
||||
* pim_zebra.c for some reason. I am
|
||||
* only doing this at this point in time
|
||||
* to get us up and working for the moment
|
||||
*/
|
||||
if (up->channel_oil->oil_inherited_rescan) {
|
||||
if (PIM_DEBUG_PIM_TRACE)
|
||||
zlog_debug(
|
||||
"%s: Handling unscanned inherited_olist for %s[%s]",
|
||||
__func__, up->sg_str, pim->vrf->name);
|
||||
pim_upstream_inherited_olist_decide(pim, up);
|
||||
up->channel_oil->oil_inherited_rescan = 0;
|
||||
}
|
||||
pim_mroute_update_counters(up->channel_oil);
|
||||
|
||||
// Have we seen packets?
|
||||
@ -1989,7 +1992,7 @@ static void pim_upstream_sg_running(void *arg)
|
||||
up->channel_oil->cc.pktcnt,
|
||||
up->channel_oil->cc.lastused / 100);
|
||||
}
|
||||
return;
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (pim_upstream_kat_start_ok(up)) {
|
||||
@ -2007,14 +2010,55 @@ static void pim_upstream_sg_running(void *arg)
|
||||
pim_upstream_fhr_kat_start(up);
|
||||
}
|
||||
pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
|
||||
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
|
||||
rv = true;
|
||||
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
|
||||
pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
|
||||
rv = true;
|
||||
}
|
||||
|
||||
if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
|
||||
(up->rpf.source_nexthop.interface)) {
|
||||
pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
|
||||
}
|
||||
return;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Code to check and see if we've received packets on a S,G mroute
|
||||
* and if so to set the SPT bit appropriately
|
||||
*/
|
||||
static void pim_upstream_sg_running(void *arg)
|
||||
{
|
||||
struct pim_upstream *up = (struct pim_upstream *)arg;
|
||||
struct pim_instance *pim = up->channel_oil->pim;
|
||||
|
||||
// No packet can have arrived here if this is the case
|
||||
if (!up->channel_oil->installed) {
|
||||
if (PIM_DEBUG_TRACE)
|
||||
zlog_debug("%s: %s%s is not installed in mroute",
|
||||
__func__, up->sg_str, pim->vrf->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a bit of a hack
|
||||
* We've noted that we should rescan but
|
||||
* we've missed the window for doing so in
|
||||
* pim_zebra.c for some reason. I am
|
||||
* only doing this at this point in time
|
||||
* to get us up and working for the moment
|
||||
*/
|
||||
if (up->channel_oil->oil_inherited_rescan) {
|
||||
if (PIM_DEBUG_TRACE)
|
||||
zlog_debug(
|
||||
"%s: Handling unscanned inherited_olist for %s[%s]",
|
||||
__func__, up->sg_str, pim->vrf->name);
|
||||
pim_upstream_inherited_olist_decide(pim, up);
|
||||
up->channel_oil->oil_inherited_rescan = 0;
|
||||
}
|
||||
|
||||
pim_upstream_sg_running_proc(up);
|
||||
}
|
||||
|
||||
void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
|
||||
|
@ -237,6 +237,8 @@ struct pim_upstream {
|
||||
struct channel_oil *channel_oil;
|
||||
struct list *sources;
|
||||
struct list *ifchannels;
|
||||
/* Counter for Dual active ifchannels*/
|
||||
uint32_t dualactive_ifchannel_count;
|
||||
|
||||
enum pim_upstream_state join_state;
|
||||
enum pim_reg_state reg_state;
|
||||
|
@ -117,6 +117,11 @@ int pim_debug_config_write(struct vty *vty)
|
||||
++writes;
|
||||
}
|
||||
|
||||
if (PIM_DEBUG_MLAG) {
|
||||
vty_out(vty, "debug pim mlag\n");
|
||||
++writes;
|
||||
}
|
||||
|
||||
if (PIM_DEBUG_BSM) {
|
||||
vty_out(vty, "debug pim bsm\n");
|
||||
++writes;
|
||||
|
@ -284,6 +284,7 @@ static void pim_vxlan_orig_mr_up_iif_update(struct pim_vxlan_sg *vxlan_sg)
|
||||
static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
|
||||
{
|
||||
struct pim_upstream *up;
|
||||
struct pim_interface *term_ifp;
|
||||
int flags = 0;
|
||||
struct prefix nht_p;
|
||||
struct pim_instance *pim = vxlan_sg->pim;
|
||||
@ -345,6 +346,11 @@ static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
|
||||
pim_upstream_update_use_rpt(up, false /*update_mroute*/);
|
||||
pim_upstream_ref(up, flags, __func__);
|
||||
vxlan_sg->up = up;
|
||||
term_ifp = pim_vxlan_get_term_ifp(pim);
|
||||
/* mute termination device on origination mroutes */
|
||||
if (term_ifp)
|
||||
pim_channel_update_oif_mute(up->channel_oil,
|
||||
term_ifp);
|
||||
pim_vxlan_orig_mr_up_iif_update(vxlan_sg);
|
||||
/* mute pimreg on origination mroutes */
|
||||
if (pim->regiface)
|
||||
|
225
pimd/pim_zpthread.c
Normal file
225
pimd/pim_zpthread.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* PIM for Quagga
|
||||
* Copyright (C) 2008 Everton da Silva Marques
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; see the file COPYING; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include <lib/log.h>
|
||||
#include <lib/lib_errors.h>
|
||||
|
||||
#include "pimd.h"
|
||||
#include "pim_mlag.h"
|
||||
#include "pim_zebra.h"
|
||||
|
||||
extern struct zclient *zclient;
|
||||
|
||||
#define PIM_MLAG_POST_LIMIT 100
|
||||
|
||||
int32_t mlag_bulk_cnt;
|
||||
|
||||
static void pim_mlag_zebra_fill_header(enum mlag_msg_type msg_type)
|
||||
{
|
||||
uint32_t fill_msg_type = msg_type;
|
||||
uint16_t data_len;
|
||||
uint16_t msg_cnt = 1;
|
||||
|
||||
if (msg_type == MLAG_MSG_NONE)
|
||||
return;
|
||||
|
||||
switch (msg_type) {
|
||||
case MLAG_REGISTER:
|
||||
case MLAG_DEREGISTER:
|
||||
data_len = sizeof(struct mlag_msg);
|
||||
break;
|
||||
case MLAG_MROUTE_ADD:
|
||||
data_len = sizeof(struct mlag_mroute_add);
|
||||
fill_msg_type = MLAG_MROUTE_ADD_BULK;
|
||||
break;
|
||||
case MLAG_MROUTE_DEL:
|
||||
data_len = sizeof(struct mlag_mroute_del);
|
||||
fill_msg_type = MLAG_MROUTE_DEL_BULK;
|
||||
break;
|
||||
default:
|
||||
data_len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
stream_reset(router->mlag_stream);
|
||||
/* ADD Hedaer */
|
||||
stream_putl(router->mlag_stream, fill_msg_type);
|
||||
/*
|
||||
* In case of Bulk actual size & msg_cnt will be updated
|
||||
* just before writing onto zebra
|
||||
*/
|
||||
stream_putw(router->mlag_stream, data_len);
|
||||
stream_putw(router->mlag_stream, msg_cnt);
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug(":%s: msg_type: %d/%d len %d",
|
||||
__func__, msg_type, fill_msg_type, data_len);
|
||||
}
|
||||
|
||||
static void pim_mlag_zebra_flush_buffer(void)
|
||||
{
|
||||
uint32_t msg_type;
|
||||
|
||||
/* Stream had bulk messages update the Hedaer */
|
||||
if (mlag_bulk_cnt > 1) {
|
||||
/*
|
||||
* No need to reset the pointer, below api reads from data[0]
|
||||
*/
|
||||
STREAM_GETL(router->mlag_stream, msg_type);
|
||||
if (msg_type == MLAG_MROUTE_ADD_BULK) {
|
||||
stream_putw_at(
|
||||
router->mlag_stream, 4,
|
||||
(mlag_bulk_cnt * sizeof(struct mlag_mroute_add)));
|
||||
stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
|
||||
} else if (msg_type == MLAG_MROUTE_DEL_BULK) {
|
||||
stream_putw_at(
|
||||
router->mlag_stream, 4,
|
||||
(mlag_bulk_cnt * sizeof(struct mlag_mroute_del)));
|
||||
stream_putw_at(router->mlag_stream, 6, mlag_bulk_cnt);
|
||||
} else {
|
||||
flog_err(EC_LIB_ZAPI_ENCODE,
|
||||
"unknown bulk message type %d bulk_count %d",
|
||||
msg_type, mlag_bulk_cnt);
|
||||
stream_reset(router->mlag_stream);
|
||||
mlag_bulk_cnt = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
zclient_send_mlag_data(zclient, router->mlag_stream);
|
||||
stream_failure:
|
||||
stream_reset(router->mlag_stream);
|
||||
mlag_bulk_cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only ROUTE add & Delete will be bulked.
|
||||
* Buffer will be flushed, when
|
||||
* 1) there were no messages in the queue
|
||||
* 2) Curr_msg_type != prev_msg_type
|
||||
*/
|
||||
|
||||
static void pim_mlag_zebra_check_for_buffer_flush(uint32_t curr_msg_type,
|
||||
uint32_t prev_msg_type)
|
||||
{
|
||||
/* First Message, keep bulking */
|
||||
if (prev_msg_type == MLAG_MSG_NONE) {
|
||||
mlag_bulk_cnt = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/*msg type is route add & delete, keep bulking */
|
||||
if (curr_msg_type == prev_msg_type
|
||||
&& (curr_msg_type == MLAG_MROUTE_ADD
|
||||
|| curr_msg_type == MLAG_MROUTE_DEL)) {
|
||||
mlag_bulk_cnt++;
|
||||
return;
|
||||
}
|
||||
|
||||
pim_mlag_zebra_flush_buffer();
|
||||
}
|
||||
|
||||
/*
|
||||
* Thsi thread reads the clients data from the Gloabl queue and encodes with
|
||||
* protobuf and pass on to the MLAG socket.
|
||||
*/
|
||||
static int pim_mlag_zthread_handler(struct thread *event)
|
||||
{
|
||||
struct stream *read_s;
|
||||
uint32_t wr_count = 0;
|
||||
uint32_t prev_msg_type = MLAG_MSG_NONE;
|
||||
uint32_t curr_msg_type = MLAG_MSG_NONE;
|
||||
|
||||
router->zpthread_mlag_write = NULL;
|
||||
wr_count = stream_fifo_count_safe(router->mlag_fifo);
|
||||
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug(":%s: Processing MLAG write, %d messages in queue",
|
||||
__func__, wr_count);
|
||||
|
||||
if (wr_count == 0)
|
||||
return 0;
|
||||
|
||||
for (wr_count = 0; wr_count < PIM_MLAG_POST_LIMIT; wr_count++) {
|
||||
/* FIFO is empty,wait for teh message to be add */
|
||||
if (stream_fifo_count_safe(router->mlag_fifo) == 0)
|
||||
break;
|
||||
|
||||
read_s = stream_fifo_pop_safe(router->mlag_fifo);
|
||||
if (!read_s) {
|
||||
zlog_debug(":%s: Got a NULL Messages, some thing wrong",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
STREAM_GETL(read_s, curr_msg_type);
|
||||
/*
|
||||
* Check for Buffer Overflow,
|
||||
* MLAG Can't process more than 'PIM_MLAG_BUF_LIMIT' bytes
|
||||
*/
|
||||
if (router->mlag_stream->endp + read_s->endp + ZEBRA_HEADER_SIZE
|
||||
> MLAG_BUF_LIMIT)
|
||||
pim_mlag_zebra_flush_buffer();
|
||||
|
||||
pim_mlag_zebra_check_for_buffer_flush(curr_msg_type,
|
||||
prev_msg_type);
|
||||
|
||||
/*
|
||||
* First message to Buffer, fill the Header
|
||||
*/
|
||||
if (router->mlag_stream->endp == 0)
|
||||
pim_mlag_zebra_fill_header(curr_msg_type);
|
||||
|
||||
/*
|
||||
* add the data now
|
||||
*/
|
||||
stream_put(router->mlag_stream, read_s->data + read_s->getp,
|
||||
read_s->endp - read_s->getp);
|
||||
|
||||
stream_free(read_s);
|
||||
prev_msg_type = curr_msg_type;
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
/*
|
||||
* we are here , because
|
||||
* 1. Queue might be empty
|
||||
* 2. we crossed the max Q Read limit
|
||||
* In any acse flush the buffer towards zebra
|
||||
*/
|
||||
pim_mlag_zebra_flush_buffer();
|
||||
|
||||
if (wr_count >= PIM_MLAG_POST_LIMIT)
|
||||
pim_mlag_signal_zpthread();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pim_mlag_signal_zpthread(void)
|
||||
{
|
||||
if (router->master) {
|
||||
if (PIM_DEBUG_MLAG)
|
||||
zlog_debug(":%s: Scheduling PIM MLAG write Thread",
|
||||
__func__);
|
||||
thread_add_event(router->master, pim_mlag_zthread_handler, NULL,
|
||||
0, &router->zpthread_mlag_write);
|
||||
}
|
||||
return (0);
|
||||
}
|
@ -102,6 +102,8 @@ void pim_router_init(void)
|
||||
router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
|
||||
router->register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
|
||||
router->vrf_id = VRF_DEFAULT;
|
||||
router->pim_mlag_intf_cnt = 0;
|
||||
router->connected_to_mlag = false;
|
||||
}
|
||||
|
||||
void pim_router_terminate(void)
|
||||
|
@ -34,6 +34,7 @@ pimd_libpim_a_SOURCES = \
|
||||
pimd/pim_jp_agg.c \
|
||||
pimd/pim_macro.c \
|
||||
pimd/pim_memory.c \
|
||||
pimd/pim_mlag.c \
|
||||
pimd/pim_mroute.c \
|
||||
pimd/pim_msdp.c \
|
||||
pimd/pim_msdp_packet.c \
|
||||
@ -62,7 +63,7 @@ pimd_libpim_a_SOURCES = \
|
||||
pimd/pim_zebra.c \
|
||||
pimd/pim_zlookup.c \
|
||||
pimd/pim_vxlan.c \
|
||||
pimd/pim_mlag.c \
|
||||
pimd/pim_zpthread.c \
|
||||
pimd/pimd.c \
|
||||
# end
|
||||
|
||||
@ -88,6 +89,7 @@ noinst_HEADERS += \
|
||||
pimd/pim_jp_agg.h \
|
||||
pimd/pim_macro.h \
|
||||
pimd/pim_memory.h \
|
||||
pimd/pim_mlag.h \
|
||||
pimd/pim_mroute.h \
|
||||
pimd/pim_msdp.h \
|
||||
pimd/pim_msdp_packet.h \
|
||||
@ -115,7 +117,6 @@ noinst_HEADERS += \
|
||||
pimd/pim_zebra.h \
|
||||
pimd/pim_zlookup.h \
|
||||
pimd/pim_vxlan.h \
|
||||
pimd/pim_mlag.h \
|
||||
pimd/pim_vxlan_instance.h \
|
||||
pimd/pimd.h \
|
||||
pimd/mtracebis_netlink.h \
|
||||
|
@ -667,14 +667,17 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
int n_len = 0;
|
||||
int rc = 0;
|
||||
char buf[ZLOG_FILTER_LENGTH_MAX];
|
||||
size_t length;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MLAG)
|
||||
zlog_debug("%s: Entering..", __func__);
|
||||
|
||||
rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg);
|
||||
rc = mlag_lib_decode_mlag_hdr(s, &mlag_msg, &length);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
memset(tmp_buf, 0, ZEBRA_MLAG_BUF_LIMIT);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MLAG)
|
||||
zlog_debug("%s: Mlag ProtoBuf encoding of message:%s, len:%d",
|
||||
__func__,
|
||||
@ -688,9 +691,10 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
ZebraMlagMrouteAdd pay_load = ZEBRA_MLAG_MROUTE_ADD__INIT;
|
||||
uint32_t vrf_name_len = 0;
|
||||
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg, &length);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vrf_name_len = strlen(msg.vrf_name) + 1;
|
||||
pay_load.vrf_name = XMALLOC(MTYPE_MLAG_PBUF, vrf_name_len);
|
||||
strlcpy(pay_load.vrf_name, msg.vrf_name, vrf_name_len);
|
||||
@ -720,7 +724,7 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
ZebraMlagMrouteDel pay_load = ZEBRA_MLAG_MROUTE_DEL__INIT;
|
||||
uint32_t vrf_name_len = 0;
|
||||
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg, &length);
|
||||
if (rc)
|
||||
return rc;
|
||||
vrf_name_len = strlen(msg.vrf_name) + 1;
|
||||
@ -749,18 +753,18 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
ZebraMlagMrouteAddBulk Bulk_msg =
|
||||
ZEBRA_MLAG_MROUTE_ADD_BULK__INIT;
|
||||
ZebraMlagMrouteAdd **pay_load = NULL;
|
||||
int i;
|
||||
bool cleanup = false;
|
||||
uint32_t i, actual;
|
||||
|
||||
Bulk_msg.n_mroute_add = mlag_msg.msg_cnt;
|
||||
pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteAdd *)
|
||||
* mlag_msg.msg_cnt);
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
|
||||
|
||||
uint32_t vrf_name_len = 0;
|
||||
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_add(s, &msg, &length);
|
||||
if (rc) {
|
||||
cleanup = true;
|
||||
break;
|
||||
@ -796,8 +800,17 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
tmp_buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
|
||||
for (i = 0; i < actual; i++) {
|
||||
/*
|
||||
* The mlag_lib_decode_mroute_add can
|
||||
* fail to properly decode and cause nothing
|
||||
* to be allocated. Prevent a crash
|
||||
*/
|
||||
if (!pay_load[i])
|
||||
continue;
|
||||
|
||||
if (pay_load[i]->vrf_name)
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
|
||||
if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
|
||||
&& pay_load[i]->intf_name)
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
|
||||
@ -812,18 +825,18 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
ZebraMlagMrouteDelBulk Bulk_msg =
|
||||
ZEBRA_MLAG_MROUTE_DEL_BULK__INIT;
|
||||
ZebraMlagMrouteDel **pay_load = NULL;
|
||||
int i;
|
||||
bool cleanup = false;
|
||||
uint32_t i, actual;
|
||||
|
||||
Bulk_msg.n_mroute_del = mlag_msg.msg_cnt;
|
||||
pay_load = XMALLOC(MTYPE_MLAG_PBUF, sizeof(ZebraMlagMrouteDel *)
|
||||
* mlag_msg.msg_cnt);
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
for (i = 0, actual = 0; i < mlag_msg.msg_cnt; i++, actual++) {
|
||||
|
||||
uint32_t vrf_name_len = 0;
|
||||
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg);
|
||||
rc = mlag_lib_decode_mroute_del(s, &msg, &length);
|
||||
if (rc) {
|
||||
cleanup = true;
|
||||
break;
|
||||
@ -858,8 +871,17 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
tmp_buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < mlag_msg.msg_cnt; i++) {
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
|
||||
for (i = 0; i < actual; i++) {
|
||||
/*
|
||||
* The mlag_lib_decode_mroute_add can
|
||||
* fail to properly decode and cause nothing
|
||||
* to be allocated. Prevent a crash
|
||||
*/
|
||||
if (!pay_load[i])
|
||||
continue;
|
||||
|
||||
if (pay_load[i]->vrf_name)
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->vrf_name);
|
||||
if (pay_load[i]->owner_id == MLAG_OWNER_INTERFACE
|
||||
&& pay_load[i]->intf_name)
|
||||
XFREE(MTYPE_MLAG_PBUF, pay_load[i]->intf_name);
|
||||
@ -915,6 +937,15 @@ int zebra_mlag_protobuf_encode_client_data(struct stream *s, uint32_t *msg_type)
|
||||
return len;
|
||||
}
|
||||
|
||||
static void zebra_fill_protobuf_msg(struct stream *s, char *name, int len)
|
||||
{
|
||||
int str_len = strlen(name) + 1;
|
||||
|
||||
stream_put(s, name, str_len);
|
||||
/* Fill the rest with Null Character for aligning */
|
||||
stream_put(s, NULL, len - str_len);
|
||||
}
|
||||
|
||||
int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
uint32_t len)
|
||||
{
|
||||
@ -966,7 +997,8 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
/* No Batching */
|
||||
stream_putw(s, MLAG_MSG_NO_BATCH);
|
||||
/* Actual Data */
|
||||
stream_put(s, msg->peerlink, INTERFACE_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->peerlink,
|
||||
INTERFACE_NAMSIZ);
|
||||
stream_putl(s, msg->my_role);
|
||||
stream_putl(s, msg->peer_state);
|
||||
zebra_mlag_status_update__free_unpacked(msg, NULL);
|
||||
@ -1003,7 +1035,7 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
/* No Batching */
|
||||
stream_putw(s, MLAG_MSG_NO_BATCH);
|
||||
/* Actual Data */
|
||||
stream_put(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
|
||||
stream_putl(s, msg->source_ip);
|
||||
stream_putl(s, msg->group_ip);
|
||||
@ -1013,7 +1045,8 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
stream_putc(s, msg->am_i_dual_active);
|
||||
stream_putl(s, msg->vrf_id);
|
||||
if (msg->owner_id == MLAG_OWNER_INTERFACE)
|
||||
stream_put(s, msg->intf_name, INTERFACE_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
else
|
||||
stream_put(s, NULL, INTERFACE_NAMSIZ);
|
||||
zebra_mlag_mroute_add__free_unpacked(msg, NULL);
|
||||
@ -1032,15 +1065,15 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
/* No Batching */
|
||||
stream_putw(s, MLAG_MSG_NO_BATCH);
|
||||
/* Actual Data */
|
||||
stream_put(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
|
||||
stream_putl(s, msg->source_ip);
|
||||
stream_putl(s, msg->group_ip);
|
||||
stream_putl(s, msg->group_ip);
|
||||
stream_putl(s, msg->owner_id);
|
||||
stream_putl(s, msg->vrf_id);
|
||||
if (msg->owner_id == MLAG_OWNER_INTERFACE)
|
||||
stream_put(s, msg->intf_name, INTERFACE_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
else
|
||||
stream_put(s, NULL, INTERFACE_NAMSIZ);
|
||||
zebra_mlag_mroute_del__free_unpacked(msg, NULL);
|
||||
@ -1067,7 +1100,8 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
|
||||
msg = Bulk_msg->mroute_add[i];
|
||||
|
||||
stream_put(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->vrf_name,
|
||||
VRF_NAMSIZ);
|
||||
stream_putl(s, msg->source_ip);
|
||||
stream_putl(s, msg->group_ip);
|
||||
stream_putl(s, msg->cost_to_rp);
|
||||
@ -1076,8 +1110,9 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
stream_putc(s, msg->am_i_dual_active);
|
||||
stream_putl(s, msg->vrf_id);
|
||||
if (msg->owner_id == MLAG_OWNER_INTERFACE)
|
||||
stream_put(s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(
|
||||
s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
else
|
||||
stream_put(s, NULL, INTERFACE_NAMSIZ);
|
||||
}
|
||||
@ -1106,14 +1141,16 @@ int zebra_mlag_protobuf_decode_message(struct stream *s, uint8_t *data,
|
||||
|
||||
msg = Bulk_msg->mroute_del[i];
|
||||
|
||||
stream_put(s, msg->vrf_name, VRF_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(s, msg->vrf_name,
|
||||
VRF_NAMSIZ);
|
||||
stream_putl(s, msg->source_ip);
|
||||
stream_putl(s, msg->group_ip);
|
||||
stream_putl(s, msg->owner_id);
|
||||
stream_putl(s, msg->vrf_id);
|
||||
if (msg->owner_id == MLAG_OWNER_INTERFACE)
|
||||
stream_put(s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
zebra_fill_protobuf_msg(
|
||||
s, msg->intf_name,
|
||||
INTERFACE_NAMSIZ);
|
||||
else
|
||||
stream_put(s, NULL, INTERFACE_NAMSIZ);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ extern uint32_t mlag_rd_buf_offset;
|
||||
|
||||
static inline void zebra_mlag_reset_read_buffer(void)
|
||||
{
|
||||
memset(mlag_wr_buffer, 0, ZEBRA_MLAG_BUF_LIMIT);
|
||||
mlag_rd_buf_offset = 0;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,8 @@ static int zebra_mlag_read(struct thread *thread)
|
||||
uint32_t h_msglen;
|
||||
uint32_t tot_len, curr_len = mlag_rd_buf_offset;
|
||||
|
||||
zrouter.mlag_info.t_read = NULL;
|
||||
|
||||
/*
|
||||
* Received message in sock_stream looks like below
|
||||
* | len-1 (4 Bytes) | payload-1 (len-1) |
|
||||
@ -157,8 +159,6 @@ static int zebra_mlag_read(struct thread *thread)
|
||||
static int zebra_mlag_connect(struct thread *thread)
|
||||
{
|
||||
struct sockaddr_un svr = {0};
|
||||
struct ucred ucred;
|
||||
socklen_t len = 0;
|
||||
|
||||
/* Reset the Timer-running flag */
|
||||
zrouter.mlag_info.timer_running = false;
|
||||
@ -182,11 +182,8 @@ static int zebra_mlag_connect(struct thread *thread)
|
||||
&zrouter.mlag_info.t_read);
|
||||
return 0;
|
||||
}
|
||||
len = sizeof(struct ucred);
|
||||
ucred.pid = getpid();
|
||||
|
||||
set_nonblocking(mlag_socket);
|
||||
setsockopt(mlag_socket, SOL_SOCKET, SO_PEERCRED, &ucred, len);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_MLAG)
|
||||
zlog_debug("%s: Connection with MLAG is established ",
|
||||
|
Loading…
Reference in New Issue
Block a user