]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Fix igmp(*,G) not influencing S,G mroutes
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 15 Aug 2016 11:28:36 +0000 (07:28 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:06 +0000 (20:26 -0500)
When we receive a (*,G) route decide if we
need to cause any output interfaces to be
added to any S,G route associated.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_ifchannel.c

index dcd9da64b6d0675588dfb848d7f4412a64ccf66e..b83f0072b45711c0c19caa49ba8e0fbc232dbcf5 100644 (file)
@@ -37,6 +37,7 @@
 #include "pim_join.h"
 #include "pim_rpf.h"
 #include "pim_macro.h"
+#include "pim_oil.h"
 
 /*
  * A (*,G) or a (*,*) is going away
@@ -773,6 +774,35 @@ void pim_ifchannel_local_membership_add(struct interface *ifp,
   ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
 
   zassert(!IFCHANNEL_NOINFO(ch));
+
+  if (sg->src.s_addr == INADDR_ANY)
+    {
+      struct pim_upstream *up = pim_upstream_find (sg);
+      struct pim_upstream *child;
+      struct listnode *up_node;
+
+      for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child))
+        {
+          if (child->parent == up)
+            {
+             if (PIM_DEBUG_EVENTS)
+               {
+                 char buff[100];
+
+                 strcpy (buff, pim_str_sg_dump (&up->sg));
+                 zlog_debug("%s %s: IGMP (S,G)=%s from %s",
+                            __FILE__, __PRETTY_FUNCTION__,
+                            buff, pim_str_sg_dump (sg));
+               }
+
+              if (pim_upstream_evaluate_join_desired (child))
+                {
+                  pim_channel_add_oif (child->channel_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
+                  pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
+                }
+            }
+        }
+    }
 }
 
 void pim_ifchannel_local_membership_del(struct interface *ifp,
@@ -794,6 +824,42 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
 
   ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
 
+  if (sg->src.s_addr == INADDR_ANY)
+    {
+      struct pim_upstream *up = pim_upstream_find (sg);
+      struct pim_upstream *child;
+      struct listnode *up_node;
+
+      for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, child))
+        {
+          if (child->parent == up)
+            {
+             struct channel_oil *c_oil = child->channel_oil;
+             struct pim_ifchannel *ch = pim_ifchannel_find (ifp, &child->sg);
+             struct pim_interface *pim_ifp = ifp->info;
+
+             if (PIM_DEBUG_EVENTS)
+               {
+                 char buff[100];
+                 strcpy (buff, pim_str_sg_dump (&up->sg));
+                 zlog_debug("%s %s: Prune(S,G)=%s from %s",
+                            __FILE__, __PRETTY_FUNCTION__,
+                            buff, pim_str_sg_dump (&child->sg));
+               }
+
+             if (!pim_upstream_evaluate_join_desired (child))
+               pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
+
+             /*
+              * If the S,G has no if channel and the c_oil still
+              * has output here then the *,G was supplying the implied
+              * if channel.  So remove it.
+               */
+             if (!ch && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
+               pim_channel_del_oif (c_oil, ifp, PIM_OIF_FLAG_PROTO_PIM);
+           }
+        }
+    }
   delete_on_noinfo(ch);
 }