]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Fix to Tx S,G Join when SGRpt->Join state
authorChirag Shah <chirag@cumulusnetworks.com>
Fri, 12 May 2017 19:05:46 +0000 (12:05 -0700)
committerChirag Shah <chirag@cumulusnetworks.com>
Thu, 18 May 2017 21:36:25 +0000 (14:36 -0700)
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.

Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_join.c
pimd/pim_rpf.c
pimd/pim_upstream.c

index d46cc70b0684d335247bfe92bc55ed28beb0d389..6f5e8f14931727d932574140c6f8019a3f2c111d 100644 (file)
@@ -1287,7 +1287,7 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp)
  * we get End of Message
  */
 void
-pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join)
+pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone)
 {
   struct pim_ifchannel *child;
   struct listnode *ch_node;
@@ -1302,10 +1302,11 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t
   for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child))
     {
       /* Only *,G Join received and no (SG-RPT) prune.
+         eom = 1, only (W,G) join_alone is true, WC and RPT are set.
          Scan all S,G associated to G and if any SG-RPT
          remove the SG-RPT flag.
       */
-      if (join && (source_flags & PIM_RPT_BIT_MASK) &&
+      if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) &&
           (source_flags & PIM_WILDCARD_BIT_MASK))
         {
           if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
@@ -1316,25 +1317,13 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t
               if (up)
                 {
                   if (PIM_DEBUG_TRACE)
-                    zlog_debug ("%s: clearing SGRpt flag, add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str);
+                    zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s",
+                            __PRETTY_FUNCTION__, up->sg_str);
                   pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
+                  pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN);
                 }
             }
         }
-      /* Received SG-RPT Prune delete oif from S,G */
-      else if (join == 0 && (source_flags & PIM_RPT_BIT_MASK) &&
-               !(source_flags & PIM_WILDCARD_BIT_MASK))
-        {
-          struct pim_upstream *up = child->upstream;
-
-          PIM_IF_FLAG_SET_S_G_RPT(child->flags);
-          if (up)
-            {
-              if (PIM_DEBUG_TRACE)
-                zlog_debug ("%s: SGRpt Set, del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str);
-              pim_channel_del_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR);
-            }
-        }
 
       if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags))
         continue;
index 3ffb9190fb336eb50dbf20af9a11e9b76a6aa33f..4c804cc720dd90aa3d03f2cb3043a8e45c4ccfaa 100644 (file)
@@ -151,7 +151,7 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch);
 void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch);
 
 void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
-void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join);
+void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone);
 
 int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
 
index 828781a4670b511376491009154f30db7b00680d..2da0b993534f7e52e3d42136343c3b2088e1366d 100644 (file)
@@ -215,7 +215,8 @@ int pim_joinprune_recv(struct interface *ifp,
     uint16_t      msg_num_joined_sources;
     uint16_t      msg_num_pruned_sources;
     int           source;
-    struct        pim_ifchannel *ch = NULL;
+    struct        pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
+    uint8_t       starg_alone = 0;
 
     memset (&sg, 0, sizeof (struct prefix_sg));
     addr_offset = pim_parse_addr_group (&sg,
@@ -274,9 +275,10 @@ int pim_joinprune_recv(struct interface *ifp,
 
       if (sg.src.s_addr == INADDR_ANY)
         {
-          ch = pim_ifchannel_find (ifp, &sg);
-         if (ch)
-           pim_ifchannel_set_star_g_join_state (ch, 0, msg_source_flags, 1);
+          starg_alone = 1;
+          starg_ch = pim_ifchannel_find (ifp, &sg);
+         if (starg_ch)
+           pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone);
         }
     }
 
@@ -289,16 +291,33 @@ int pim_joinprune_recv(struct interface *ifp,
        return -8;
       }
 
-      buf += addr_offset;
+      sg_ch = pim_ifchannel_find (ifp, &sg);
 
+      buf += addr_offset;
+      starg_alone = 0;
       recv_prune(ifp, neigh, msg_holdtime,
                 msg_upstream_addr.u.prefix4,
                 &sg,
                 msg_source_flags);
+
+      /* Received SG-RPT Prune delete oif from specific S,G */
+      if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK)
+               && !(msg_source_flags & PIM_WILDCARD_BIT_MASK))
+        {
+          struct pim_upstream *up = sg_ch->upstream;
+          PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags);
+          if (up)
+            {
+              if (PIM_DEBUG_TRACE)
+                zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s",
+                     __PRETTY_FUNCTION__, up->sg_str);
+              pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR);
+            }
+        }
     }
-    if (ch)
-      pim_ifchannel_set_star_g_join_state (ch, 1, msg_source_flags, 0);
-    ch = NULL;
+    if (starg_ch)
+      pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone);
+    starg_ch = NULL;
   } /* scan groups */
 
   return 0;
@@ -502,6 +521,10 @@ int pim_joinprune_send(struct pim_rpf *rpf,
       packet_size += group_size;
       pim_msg_build_jp_groups (grp, group, group_size);
 
+      if (PIM_DEBUG_PIM_TRACE)
+        zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__,
+          rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes));
+
       grp = (struct pim_jp_groups *)curr_ptr;
       if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255)
         {
index f46ebfb979b4712360c78f2a85abc80d6c00e40e..d16106dec8033b636b91b936c231a5c44c57294f 100644 (file)
@@ -244,17 +244,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old,
         {
           return PIM_RPF_FAILURE;
         }
-   }
+    }
 
   rpf->rpf_addr.family = AF_INET;
   rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
-  if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) {
-    /* RPF'(S,G) not found */
-    zlog_debug("%s %s: RPF'%s not found: won't send join upstream",
+  if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA)
+    {
+      /* RPF'(S,G) not found */
+      zlog_debug("%s %s: RPF'%s not found: won't send join upstream",
               __FILE__, __PRETTY_FUNCTION__,
               up->sg_str);
-    /* warning only */
-  }
+      /* warning only */
+    }
 
   /* detect change in pim_nexthop */
   if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) {
index 6fadfc2f29a213bd486425167f24c57391c4855e..af9c3913a5906abe3b3db4e11b912b22f5ffd13a 100644 (file)
@@ -582,8 +582,9 @@ pim_upstream_switch(struct pim_upstream *up,
     if (old_state == PIM_UPSTREAM_JOINED)
       pim_msdp_up_join_state_changed(up);
 
-    /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT */
-    if (pim_upstream_is_sg_rpt(up) && up->parent)
+    /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP.
+       If I am RP for G then send S,G prune to its IIF. */
+    if (pim_upstream_is_sg_rpt(up) && up->parent && !I_am_RP(up->sg.grp))
       {
         if (PIM_DEBUG_PIM_TRACE_DETAIL)
           zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__,