Skip to content

Commit

Permalink
pimd: Do not allow to configure multicast on more than MAXVIF interfaces
Browse files Browse the repository at this point in the history
RCA: When configured more than 32(MAXVIS), the inerfaces that are configured
after 32nd interfaces have the value of MAXVIF.
This is used as index to access the free vif tracker of array size 32(MAXVIFS).
So the channel oil list pointer which is present as the next field in pim structure get corrupt, when updating free vif.
This gets accessed during rpf update resulting in crash.

Fix: Refrain from allocating mcast interface structure and throw config error when more than MAXVIFS are attempted to configure.
Max vif checks are exempted for vrf device and pimreg as vrf device will be the first interface and not expected to fail and pimreg has reserved vif.
vxlan tunnel termination device creation has this check and throw warning on max vif.
All other creation are through CLI.

Signed-off-by: Saravanan K <[email protected]>
  • Loading branch information
sarav511 committed Mar 17, 2020
1 parent 7f2ccbe commit ccf696e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 24 deletions.
75 changes: 53 additions & 22 deletions pimd/pim_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -7237,11 +7237,20 @@ DEFUN (no_ip_pim_ecmp_rebalance,
static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
{
struct pim_interface *pim_ifp;
struct pim_instance *pim;
uint8_t need_startup = 0;

pim_ifp = ifp->info;

if (!pim_ifp) {
pim = pim_get_pim_instance(ifp->vrf_id);
/* Limit mcast interfaces to number of vifs available */
if (pim->mcast_if_count == MAXVIFS) {
vty_out(vty,
"Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s\n",
MAXVIFS, ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
(void)pim_if_new(ifp, true, false, false, false);
need_startup = 1;
} else {
Expand Down Expand Up @@ -7991,13 +8000,21 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate,
return CMD_SUCCESS;
}

static int pim_cmd_interface_add(struct interface *ifp)
static int pim_cmd_interface_add(struct vty *vty, struct interface *ifp)
{
struct pim_interface *pim_ifp = ifp->info;
struct pim_instance *pim;

if (!pim_ifp)
if (!pim_ifp) {
pim = pim_get_pim_instance(ifp->vrf_id);
/* Limiting mcast interfaces to number of VIFs */
if (pim->mcast_if_count == MAXVIFS) {
vty_out(vty, "Max multicast interfaces(%d) reached.",
MAXVIFS);
return 0;
}
pim_ifp = pim_if_new(ifp, false, true, false, false);
else
} else
PIM_IF_DO_PIM(pim_ifp->options);

pim_if_addr_add_all(ifp);
Expand Down Expand Up @@ -8068,15 +8085,17 @@ DEFPY (interface_ip_pim_activeactive,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct pim_interface *pim_ifp;

if (!no && !pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM active-active on interface\n");
if (!no && !pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM active-active on interface %s\n",
ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}


if (PIM_DEBUG_MLAG)
zlog_debug("%sConfiguring PIM active-active on Interface: %s",
no ? "Un-":" ", ifp->name);
if (PIM_DEBUG_MLAG)
zlog_debug("%sConfiguring PIM active-active on Interface: %s",
no ? "Un-" : " ", ifp->name);

pim_ifp = ifp->info;
if (no)
Expand All @@ -8096,8 +8115,9 @@ DEFUN_HIDDEN (interface_ip_pim_ssm,
{
VTY_DECLVAR_CONTEXT(interface, ifp);

if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty, "Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}

Expand All @@ -8113,8 +8133,9 @@ static int interface_ip_pim_helper(struct vty *vty)

VTY_DECLVAR_CONTEXT(interface, ifp);

if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty, "Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}

Expand Down Expand Up @@ -8402,8 +8423,10 @@ DEFUN (interface_ip_pim_hello,
struct pim_interface *pim_ifp = ifp->info;

if (!pim_ifp) {
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING_CONFIG_FAILED;
}
}
Expand Down Expand Up @@ -9145,8 +9168,10 @@ DEFUN (ip_pim_bfd,
struct bfd_info *bfd_info = NULL;

if (!pim_ifp) {
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING;
}
}
Expand Down Expand Up @@ -9196,8 +9221,10 @@ DEFUN (ip_pim_bsm,
struct pim_interface *pim_ifp = ifp->info;

if (!pim_ifp) {
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING;
}
}
Expand Down Expand Up @@ -9240,8 +9267,10 @@ DEFUN (ip_pim_ucast_bsm,
struct pim_interface *pim_ifp = ifp->info;

if (!pim_ifp) {
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING;
}
}
Expand Down Expand Up @@ -9308,8 +9337,10 @@ DEFUN(
struct pim_interface *pim_ifp = ifp->info;

if (!pim_ifp) {
if (!pim_cmd_interface_add(ifp)) {
vty_out(vty, "Could not enable PIM SM on interface\n");
if (!pim_cmd_interface_add(vty, ifp)) {
vty_out(vty,
"Could not enable PIM SM on interface %s\n",
ifp->name);
return CMD_WARNING;
}
}
Expand Down
12 changes: 10 additions & 2 deletions pimd/pim_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_sock_reset(ifp);

pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
pim_ifp->pim->mcast_if_count++;

return pim_ifp;
}
Expand All @@ -209,6 +210,7 @@ void pim_if_delete(struct interface *ifp)
pim_neighbor_delete_all(ifp, "Interface removed from configuration");

pim_if_del_vif(ifp);
pim_ifp->pim->mcast_if_count--;

list_delete(&pim_ifp->igmp_socket_list);
list_delete(&pim_ifp->pim_neighbor_list);
Expand Down Expand Up @@ -1583,8 +1585,14 @@ int pim_ifp_create(struct interface *ifp)
}

if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME,
sizeof(PIM_VXLAN_TERM_DEV_NAME)))
pim_vxlan_add_term_dev(pim, ifp);
sizeof(PIM_VXLAN_TERM_DEV_NAME))) {
if (pim->mcast_if_count < MAXVIFS)
pim_vxlan_add_term_dev(pim, ifp);
else
zlog_warn(
"%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
__func__, ifp->name, MAXVIFS);
}

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions pimd/pim_instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)

pim_if_init(pim);

pim->mcast_if_count = 0;
pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;

Expand Down
1 change: 1 addition & 0 deletions pimd/pim_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ struct pim_instance {
struct route_table *rp_table;

int iface_vif_index[MAXVIFS];
int mcast_if_count;

struct rb_pim_oil_head channel_oil_head;

Expand Down

0 comments on commit ccf696e

Please sign in to comment.