]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Allow (*,G) joins to join a (s,g) that pre-exists
authorDonald Sharp <sharpd@cumulusnetwroks.com>
Sat, 23 Jul 2016 10:01:55 +0000 (06:01 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:03 +0000 (20:26 -0500)
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_join.c
pimd/pim_upstream.c
pimd/pim_upstream.h

index b5ebfb5d9af9c37bfc3bfbcd68cdf998db6b3b98..c496b988ee53554d64e383c84aee8b1bdd380eea 100644 (file)
@@ -34,6 +34,8 @@
 #include "pim_iface.h"
 #include "pim_hello.h"
 #include "pim_ifchannel.h"
+#include "pim_rpf.h"
+#include "pim_rp.h"
 
 static void on_trace(const char *label,
                     struct interface *ifp, struct in_addr src)
@@ -76,6 +78,25 @@ static void recv_join(struct interface *ifp,
   /* Restart join expiry timer */
   pim_ifchannel_join_add(ifp, neigh->source_addr, upstream,
                         &sg, source_flags, holdtime);
+
+  if (I_am_RP (group) && source.s_addr == INADDR_ANY)
+    {
+      struct pim_upstream *up;
+
+      up = pim_upstream_find_non_any (&sg);
+
+      if (up)
+        {
+         zlog_debug("%s %s: Join(S,G)=%s from %s",
+                    __FILE__, __PRETTY_FUNCTION__,
+                    pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg));
+
+         pim_rp_set_upstream_addr (&up->upstream_addr, up->sg.u.sg.src);
+         pim_nexthop_lookup (&up->rpf.source_nexthop, up->upstream_addr, NULL);
+         pim_ifchannel_join_add (ifp, neigh->source_addr, upstream, &up->sg, source_flags, holdtime);
+        }
+    }
+
 }
 
 static void recv_prune(struct interface *ifp,
@@ -106,6 +127,22 @@ static void recv_prune(struct interface *ifp,
   }
   
   pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime);
+
+  if (I_am_RP (group) && source.s_addr == INADDR_ANY)
+    {
+      struct pim_upstream *up;
+
+      up = pim_upstream_find_non_any (&sg);
+
+      if (up)
+        {
+         zlog_debug("%s %s: Prune(S,G)=%s from %s",
+                    __FILE__, __PRETTY_FUNCTION__,
+                    pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg));
+         pim_ifchannel_prune (ifp, upstream, &up->sg, source_flags, holdtime);
+        }
+    }
+
 }
 
 int pim_joinprune_recv(struct interface *ifp,
index fc83acf7eaf6686acb3cb4b805ed7bbb2db22cc3..34e7d9a759aff96557545a8ee61e3b4449b0ffcb 100644 (file)
@@ -374,6 +374,27 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg,
   return up;
 }
 
+/*
+ * For a given sg, find any non * source
+ */
+struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg)
+{
+  struct listnode *up_node;
+  struct prefix any = *sg;
+  struct pim_upstream *up;
+
+  any.u.sg.src.s_addr = INADDR_ANY;
+
+  for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, up))
+    {
+      if ((any.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) &&
+          (up->sg.u.sg.src.s_addr != any.u.sg.src.s_addr))
+        return up;
+    }
+
+  return NULL;
+}
+
 struct pim_upstream *pim_upstream_find(struct prefix *sg)
 {
   struct listnode     *up_node;
index 18f302183a95efa51e4c8f6c03b782034f03878a..2fb193d42d9924147a73c147d0a972bff2b47735 100644 (file)
@@ -122,6 +122,7 @@ struct pim_upstream {
 void pim_upstream_free(struct pim_upstream *up);
 void pim_upstream_delete(struct pim_upstream *up);
 struct pim_upstream *pim_upstream_find (struct prefix *sg);
+struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg);
 struct pim_upstream *pim_upstream_add (struct prefix *sg,
                                      struct interface *ifp);
 void pim_upstream_del(struct pim_upstream *up);