]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Allow SPT switchover
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 23 Mar 2017 01:07:57 +0000 (21:07 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 5 Apr 2017 16:38:12 +0000 (12:38 -0400)
This allows SPT switchover for S,G upon receipt of packets
on the LHR.

1) When we create a *,G from a IGMP Group Report, install
the *,G route with the pimreg device on the OIL.

2) When a packet hits the LHR that matches the *,G, we will
get a WHOLEPKT callback from the kernel and if we cannot
find the S,G, that means we have matched it on the LHR via
the *,G mroute.  Create the S,G start the KAT and run
inherited_olist.

3) When the S,G times out, safely remove the S,G via
the KAT expiry

4) When the *,G is removed, remove any S,G associated
with it via the LHR flag.

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

index e6b4ba92a90810a2538178b31f068bf04546e6c0..e1697960e488ca2f85d873546ace9b63492fea6d 100644 (file)
@@ -1006,6 +1006,7 @@ pim_ifchannel_local_membership_add(struct interface *ifp,
              pim_upstream_switch (child, PIM_UPSTREAM_JOINED);
            }
         }
+      pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_IGMP);
     }
 
   return 1;
index 2fb243b9bdbf91958f1a9f7c05d6d715c50ec0ac..cfbd07ede094deef383959b67df300c1369f1eff 100644 (file)
@@ -200,6 +200,23 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf)
 
   up = pim_upstream_find(&sg);
   if (!up) {
+    struct prefix_sg star = sg;
+    star.src.s_addr = INADDR_ANY;
+
+    up = pim_upstream_find(&star);
+
+    if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags))
+      {
+       up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__);
+       pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time);
+       pim_upstream_inherited_olist (up);
+       pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+
+       if (PIM_DEBUG_MROUTE)
+         zlog_debug ("%s: Creating %s upstream on LHR",
+                     __PRETTY_FUNCTION__, up->sg_str);
+        return 0;
+      }
     if (PIM_DEBUG_MROUTE_DETAIL) {
       zlog_debug("%s: Unable to find upstream channel WHOLEPKT%s",
                 __PRETTY_FUNCTION__, pim_str_sg_dump (&sg));
index 172d0d21c985f97086f3165d39880e510f0499ea..3e81aaf496f0269c0b8971c86334e5b8d8bdf4be 100644 (file)
@@ -198,7 +198,20 @@ pim_upstream_del(struct pim_upstream *up, const char *name)
   upstream_channel_oil_detach(up);
 
   if (up->sources)
-    list_delete (up->sources);
+    {
+      struct listnode *node, *nnode;
+      struct pim_upstream *child;
+      for (ALL_LIST_ELEMENTS (up->sources, node, nnode, child))
+       {
+         if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags))
+           {
+             PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags);
+             pim_upstream_del(child, __PRETTY_FUNCTION__);
+           }
+       }
+
+      list_delete (up->sources);
+    }
   up->sources = NULL;
 
   /*
@@ -1083,26 +1096,31 @@ pim_upstream_keep_alive_timer (struct thread *t)
   up->t_ka_timer = NULL;
 
   if (I_am_RP (up->sg.grp))
-  {
-    pim_br_clear_pmbr (&up->sg);
-    /*
-     * We need to do more here :)
-     * But this is the start.
-     */
-  }
+    {
+      pim_br_clear_pmbr (&up->sg);
+      /*
+       * We need to do more here :)
+       * But this is the start.
+       */
+    }
 
   /* source is no longer active - pull the SA from MSDP's cache */
   pim_msdp_sa_local_del(&up->sg);
 
   /* if entry was created because of activity we need to deref it */
   if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
-  {
-    pim_upstream_fhr_kat_expiry(up);
-    if (PIM_DEBUG_TRACE)
-      zlog_debug ("kat expired on %s; remove stream reference", up->sg_str);
-    PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
-    pim_upstream_del(up, __PRETTY_FUNCTION__);
-  }
+    {
+      pim_upstream_fhr_kat_expiry(up);
+      if (PIM_DEBUG_TRACE)
+       zlog_debug ("kat expired on %s; remove stream reference", up->sg_str);
+      PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
+      pim_upstream_del(up, __PRETTY_FUNCTION__);
+    }
+  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
+    {
+      PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
+      pim_upstream_del(up, __PRETTY_FUNCTION__);
+    }
 
   return 0;
 }
@@ -1633,25 +1651,28 @@ pim_upstream_sg_running (void *arg)
       return;
     }
 
-  if (pim_upstream_kat_start_ok(up)) {
-    /* Add a source reference to the stream if
-     * one doesn't already exist */
-    if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
+  if (pim_upstream_kat_start_ok(up))
     {
-      if (PIM_DEBUG_TRACE)
-        zlog_debug ("source reference created on kat restart %s", up->sg_str);
+      /* Add a source reference to the stream if
+       * one doesn't already exist */
+      if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags))
+       {
+         if (PIM_DEBUG_TRACE)
+           zlog_debug ("source reference created on kat restart %s", up->sg_str);
 
-      pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM);
-      PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
-      pim_upstream_fhr_kat_start(up);
+         pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM);
+         PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
+         pim_upstream_fhr_kat_start(up);
+       }
+      pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
     }
+  else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
     pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
-  }
 
   if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE)
-  {
-    pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
-  }
+    {
+      pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
+    }
   return;
 }
 
index 6f7556f323e84746950a8312036ecf7e93b20c7f..94bc5a55b91c6480da2b7aae76991ddeebe818a3 100644 (file)
@@ -34,6 +34,8 @@
 #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM              (1 << 5)
 #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP                (1 << 6)
 #define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE       (1 << 7)
+#define PIM_UPSTREAM_FLAG_MASK_SRC_LHR                 (1 << 8)
+#define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF
 
 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -43,6 +45,7 @@
 #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -52,6 +55,7 @@
 #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -61,6 +65,7 @@
 #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
 #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
 #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
+#define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
 
 enum pim_upstream_state {
   PIM_UPSTREAM_NOTJOINED,