]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Do not allow to configure multicast on more than MAXVIF interfaces
authorsaravanank <saravanank@vmware.com>
Mon, 16 Mar 2020 05:42:56 +0000 (22:42 -0700)
committersaravanank <saravanank@vmware.com>
Tue, 17 Mar 2020 02:49:18 +0000 (19:49 -0700)
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 <saravanank@vmware.com>
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_instance.c
pimd/pim_instance.h

index abc154896731b8375790144ae1eb99b0ab219821..193dcb8fc048063a5db90beeb58ce4abcfb8a120 100644 (file)
@@ -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 {
@@ -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);
@@ -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)
@@ -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;
        }
 
@@ -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;
        }
 
@@ -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;
                }
        }
@@ -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;
                }
        }
@@ -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;
                }
        }
@@ -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;
                }
        }
@@ -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;
                }
        }
index cb31878e01516d08e47a89ab58076179c177a2ff..d05790d33e8109726697f547f4fb0f31e3580789 100644 (file)
@@ -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;
 }
@@ -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);
@@ -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;
 }
index 347b0fc28485d896a92fa3d7d68814665f535cea..f7a145202683d319f799362e181d04c5995d163e 100644 (file)
@@ -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;
 
index 7b1fd2e172fb64faf204ea7a293435dadd7e92b8..cd6c4d7f5cdf3e021c72c287863f82e610880bd9 100644 (file)
@@ -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;