]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: fix OIL not removed after IGMP prune 5880/head
authorSarita Patra <saritap@vmware.com>
Mon, 2 Mar 2020 08:55:22 +0000 (00:55 -0800)
committerSarita Patra <saritap@vmware.com>
Tue, 17 Mar 2020 04:54:34 +0000 (21:54 -0700)
Issue: Client1------LHR-----(int-1)RP(int-2)------client2
Client2 send IGMP join for group G.
Client1 send IGMP join for group G.
verify show ip mroute in RP, will have 2 OIL.
Client2 send IGMP leave.
Verify show ip mroute in RP, will still have 2.

Root cause: When RP receives IGMP join from client2, it creates
a (s,g) channel oil and add the interface int-2 into oil list and
set the flag PIM_OIF_FLAG_PROTO_IGMP to int-2
Client1 send IGMP join, LHR will send a (*,G) join to RP. RP will
add the interface int-1 into the oil list of (s,g) channel_oil and
will set the flag PIM_OIF_FLAG_PROTO_IGMP and PIM_OIF_FLAG_PROTO_PIM
to the int-1 and set PIM_OIF_FLAG_PROTO_PIM to int-2 as well. It is
happening because of the pim_upstream_inherited_olist_decide() and
forward_on() get all the oil and update the flag wrongly.
So now when client 2 sends IGMP prune, RP will not remove the int-2
from oil list since both PIM_OIF_FLAG_PROTO_PIM & PIM_OIF_FLAG_PROTO_IGMP
are set, it just unset the flag PIM_OIF_FLAG_PROTO_IGMP.

Fix: Introduced new flags in if_channel, PIM_IF_FLAG_MASK_PROTO_PIM
& PIM_IF_FLAG_MASK_PROTO_IGMP. If a if_channel is created because of
pim join or pim (s,g,rpt) prune received, then set the flag
PIM_IF_FLAG_MASK_PROTO_PIM. If a if_channel is created becuase of IGMP
join received, then set the flag PIM_IF_FLAG_MASK_PROTO_IGMP.
When an interface needs to be added into the oil list check if
PIM_IF_FLAG_MASK_PROTO_PIM or PIM_IF_FLAG_MASK_PROTO_IGMP is set, then
update oil flag accordingly.

Signed-off-by: Sarita Patra <saritap@vmware.com>
pimd/pim_cmd.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_upstream.c
pimd/pim_zebra.c

index abc154896731b8375790144ae1eb99b0ab219821..cf3637c4f4561b7d0f236701be3cef7ceb791d6f 100644 (file)
@@ -1706,7 +1706,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
                        pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
                if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags))
                        json_object_int_add(json_row, "SGRpt", 1);
-
+               if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+                       json_object_int_add(json_row, "protocolPim", 1);
+               if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+                       json_object_int_add(json_row, "protocolIgmp", 1);
                json_object_object_get_ex(json_iface, ch_grp_str, &json_grp);
                if (!json_grp) {
                        json_grp = json_object_new_object();
index 44d4ee7192bd1b62610b198d31ab238dd31d35db..70e06ccc4e83591366fbec69873aa33e1da02c23 100644 (file)
@@ -628,6 +628,12 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
                                up->dualactive_ifchannel_count, up->flags);
        }
 
+       if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
+               PIM_IF_FLAG_SET_PROTO_PIM(ch->flags);
+
+       if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+               PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags);
+
        if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("%s: ifchannel %s(%s) is created ", __func__,
                           ch->sg_str, ch->interface->name);
index 3d5cbd8ecf8d91784af611443962434a5004042b..425622b79ed3b8afd04065cf19253f4a20a7fbd2 100644 (file)
@@ -69,13 +69,30 @@ struct pim_assert_metric {
 #define PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(flags) ((flags) &= ~PIM_IF_FLAG_MASK_ASSERT_TRACKING_DESIRED)
 
 /*
- * Flat to tell us if the ifchannel is (S,G,rpt)
+ * Flag to tell us if the ifchannel is (S,G,rpt)
  */
 #define PIM_IF_FLAG_MASK_S_G_RPT         (1 << 2)
 #define PIM_IF_FLAG_TEST_S_G_RPT(flags)  ((flags) & PIM_IF_FLAG_MASK_S_G_RPT)
 #define PIM_IF_FLAG_SET_S_G_RPT(flags)   ((flags) |= PIM_IF_FLAG_MASK_S_G_RPT)
 #define PIM_IF_FLAG_UNSET_S_G_RPT(flags) ((flags) &= ~PIM_IF_FLAG_MASK_S_G_RPT)
 
+/*
+ * Flag to tell us if the ifchannel is proto PIM
+ */
+#define PIM_IF_FLAG_MASK_PROTO_PIM (1 << 3)
+#define PIM_IF_FLAG_TEST_PROTO_PIM(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_PIM)
+#define PIM_IF_FLAG_SET_PROTO_PIM(flags) ((flags) |= PIM_IF_FLAG_MASK_PROTO_PIM)
+#define PIM_IF_FLAG_UNSET_PROTO_PIM(flags)                                     \
+       ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_PIM)
+/*
+ * Flag to tell us if the ifchannel is proto IGMP
+ */
+#define PIM_IF_FLAG_MASK_PROTO_IGMP (1 << 4)
+#define PIM_IF_FLAG_TEST_PROTO_IGMP(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_IGMP)
+#define PIM_IF_FLAG_SET_PROTO_IGMP(flags)                                      \
+       ((flags) |= PIM_IF_FLAG_MASK_PROTO_IGMP)
+#define PIM_IF_FLAG_UNSET_PROTO_IGMP(flags)                                    \
+       ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_IGMP)
 /*
   Per-interface (S,G) state
 */
index efa58c1b1fe39b4cfdc70cdc4dac1678e655312d..07f8315a19903296e32e3bed0aac3c889f6a3ec7 100644 (file)
@@ -1794,10 +1794,16 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
                        continue;
                if (pim_upstream_evaluate_join_desired_interface(up, ch,
                                                                 starch)) {
-                       int flag = PIM_OIF_FLAG_PROTO_PIM;
+                       int flag = 0;
 
                        if (!ch)
                                flag = PIM_OIF_FLAG_PROTO_STAR;
+                       else {
+                               if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
+                                       flag = PIM_OIF_FLAG_PROTO_IGMP;
+                               if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+                                       flag |= PIM_OIF_FLAG_PROTO_PIM;
+                       }
 
                        pim_channel_add_oif(up->channel_oil, ifp, flag,
                                        __func__);
index e791500ede49f29a047756f70d7b03d8fd92c025..8355c2099d350d0425051fe936486b46df5f3410 100644 (file)
@@ -835,7 +835,7 @@ void igmp_source_forward_stop(struct igmp_source *source)
 void pim_forward_start(struct pim_ifchannel *ch)
 {
        struct pim_upstream *up = ch->upstream;
-       uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
+       uint32_t mask = 0;
 
        if (PIM_DEBUG_PIM_TRACE) {
                char source_str[INET_ADDRSTRLEN];
@@ -853,9 +853,12 @@ void pim_forward_start(struct pim_ifchannel *ch)
                           inet_ntoa(up->upstream_addr));
        }
 
-       if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+       if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags))
                mask = PIM_OIF_FLAG_PROTO_IGMP;
 
+       if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags))
+               mask |= PIM_OIF_FLAG_PROTO_PIM;
+
        pim_channel_add_oif(up->channel_oil, ch->interface,
                        mask, __func__);
 }