]> git.puffer.fish Git - mirror/frr.git/commitdiff
PIM: prefix-list support for selecting RP
authorDaniel Walton <dwalton@cumulusnetworks.com>
Tue, 13 Sep 2016 19:41:33 +0000 (19:41 +0000)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Dec 2016 01:26:09 +0000 (20:26 -0500)
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: CCR-5173
Ticket: CM-12819

16 files changed:
pimd/pim_cmd.c
pimd/pim_join.c
pimd/pim_macro.c
pimd/pim_main.c
pimd/pim_memory.c
pimd/pim_memory.h
pimd/pim_mroute.c
pimd/pim_msg.c
pimd/pim_register.c
pimd/pim_rp.c
pimd/pim_rp.h
pimd/pim_upstream.c
pimd/pim_vty.c
pimd/pim_zebra.c
pimd/pimd.c
pimd/pimd.h

index fd4da29291b8b82aa21187633ad3568d14764085..9b58b891e10d1d0c72854e670ebb2f246c7426be 100644 (file)
@@ -25,6 +25,7 @@
 #include "if.h"
 #include "prefix.h"
 #include "zclient.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_mroute.h"
@@ -2439,27 +2440,52 @@ DEFUN (show_ip_ssmpingd,
 }
 
 static int
-pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
+pim_rp_cmd_worker (struct vty *vty, const char *rp, const char *group, const char *plist)
 {
   int result;
-  result = pim_rp_new (rp, group);
 
-  if (result == -1)
+  result = pim_rp_new (rp, group, plist);
+
+  if (result == PIM_MALLOC_FAIL)
+    {
+      vty_out (vty, "%% Out of memory%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (result == PIM_GROUP_BAD_ADDRESS)
+    {
+      vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (result == PIM_RP_BAD_ADDRESS)
     {
-      vty_out (vty, "%% Bad RP/group address specified: %s", rp);
+      vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
       return CMD_WARNING;
     }
 
-  if (result == -2)
+  if (result == PIM_RP_NO_PATH)
     {
-      vty_out (vty, "%% No Path to RP address specified: %s", rp);
-            return CMD_WARNING;
+      vty_out (vty, "%% No Path to RP address specified: %s%s", rp, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (result == PIM_GROUP_OVERLAP)
+    {
+      vty_out (vty, "%% Group range specified cannot overlap%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (result == PIM_GROUP_PFXLIST_OVERLAP)
+    {
+      vty_out (vty, "%% This group is already covered by a RP prefix-list%s", VTY_NEWLINE);
+      return CMD_WARNING;
     }
 
-  if (result == -3)
+  if (result == PIM_RP_PFXLIST_IN_USE)
     {
-      vty_out (vty, "%% Group range specified cannot overlap");
-      return CMD_ERR_NO_MATCH;
+      vty_out (vty, "%% The same prefix-list cannot be applied to multiple RPs%s", VTY_NEWLINE);
+      return CMD_WARNING;
     }
 
   return CMD_SUCCESS;
@@ -2526,23 +2552,43 @@ DEFUN (ip_pim_rp,
        "ip address of RP\n")
 {
   int idx_ipv4 = 3;
-  return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
+  return pim_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
+}
+
+DEFUN (ip_pim_rp_prefix_list,
+       ip_pim_rp_prefix_list_cmd,
+       "ip pim rp A.B.C.D prefix-list WORD",
+       IP_STR
+       "pim multicast routing\n"
+       "Rendevous Point\n"
+       "ip address of RP\n"
+       "group prefix-list filter\n"
+       "Name of a prefix-list\n")
+{
+  return pim_rp_cmd_worker (vty, argv[3]->arg, NULL, argv[5]->arg);
 }
 
 static int
-pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group)
+pim_no_rp_cmd_worker (struct vty *vty, const char *rp, const char *group,
+                      const char *plist)
 {
-  int result = pim_rp_del (rp, group);
+  int result = pim_rp_del (rp, group, plist);
+
+  if (result == PIM_GROUP_BAD_ADDRESS)
+    {
+      vty_out (vty, "%% Bad group address specified: %s%s", group, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
 
-  if (result == -1)
+  if (result == PIM_RP_BAD_ADDRESS)
     {
-      vty_out (vty, "%% Unable to Decode specified RP");
+      vty_out (vty, "%% Bad RP address specified: %s%s", rp, VTY_NEWLINE);
       return CMD_WARNING;
     }
 
-  if (result == -2)
+  if (result == PIM_RP_NOT_FOUND)
     {
-      vty_out (vty, "%% Unable to find specified RP");
+      vty_out (vty, "%% Unable to find specified RP%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
 
@@ -2559,7 +2605,21 @@ DEFUN (no_ip_pim_rp,
        "ip address of RP\n")
 {
   int idx_ipv4 = 4;
-  return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg);
+  return pim_no_rp_cmd_worker (vty, argv[idx_ipv4]->arg, argv[idx_ipv4 + 1]->arg, NULL);
+}
+
+DEFUN (no_ip_pim_rp_prefix_list,
+       no_ip_pim_rp_prefix_list_cmd,
+       "no ip pim rp A.B.C.D prefix-list WORD",
+       NO_STR
+       IP_STR
+       "pim multicast routing\n"
+       "Rendevous Point\n"
+       "ip address of RP\n"
+       "group prefix-list filter\n"
+       "Name of a prefix-list\n")
+{
+  return pim_no_rp_cmd_worker (vty, argv[4]->arg, NULL, argv[6]->arg);
 }
 
 DEFUN (ip_multicast_routing,
@@ -4821,6 +4881,8 @@ void pim_cmd_init()
   install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
   install_element (CONFIG_NODE, &ip_pim_rp_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_rp_cmd);
+  install_element (CONFIG_NODE, &ip_pim_rp_prefix_list_cmd);
+  install_element (CONFIG_NODE, &no_ip_pim_rp_prefix_list_cmd);
   install_element (CONFIG_NODE, &ip_pim_keep_alive_cmd);
   install_element (CONFIG_NODE, &no_ip_pim_keep_alive_cmd);
   install_element (CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
index 1f722e7637cae78ea810c7443909480290e2fd22..7bec6c7eca1d594d6dd24744743694f64f00eae2 100644 (file)
@@ -24,6 +24,8 @@
 #include "log.h"
 #include "prefix.h"
 #include "if.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_str.h"
index 4bcb62a90ecb02dd1249141d13183c10a73edc97..177de66673ffc8db625061e4b9c8b137ec962eec 100644 (file)
@@ -22,6 +22,9 @@
 #include <zebra.h>
 
 #include "log.h"
+#include "prefix.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pim_macro.h"
 #include "pimd.h"
index 53c7e092aa03f4bc9eb27fb7a8b7f85144b69c53..1ddc1eac54e1c76741da652dbff0c0ea4167ac2d 100644 (file)
@@ -45,6 +45,7 @@
 #include "pim_signals.h"
 #include "pim_zebra.h"
 #include "pim_msdp.h"
+#include "pim_rp.h"
 
 #ifdef PIM_ZCLIENT_DEBUG
 extern int zclient_debug;
@@ -208,6 +209,9 @@ int main(int argc, char** argv, char** envp) {
   vrf_init ();
   access_list_init();
   prefix_list_init ();
+  prefix_list_add_hook (pim_rp_prefix_list_update);
+  prefix_list_delete_hook (pim_rp_prefix_list_update);
+
   pim_route_map_init ();
   pim_init();
   pim_msdp_init ();
index 9994ea5d6bd219a632d7998f34e8eea3626c2e8f..219dd968168976babc908bb65179eec90d944d16 100644 (file)
@@ -40,3 +40,4 @@ DEFINE_MTYPE(PIMD, PIM_SSMPINGD,          "PIM sspimgd socket")
 DEFINE_MTYPE(PIMD, PIM_STATIC_ROUTE,      "PIM Static Route")
 DEFINE_MTYPE(PIMD, PIM_BR,                "PIM Bridge Router info")
 DEFINE_MTYPE(PIMD, PIM_RP,                "PIM RP info")
+DEFINE_MTYPE(PIMD, PIM_FILTER_NAME,       "PIM Filter Name")
index 3d3f14467bef0077a62d76ba592ce6a3707898be..fc0dd91f85bd053a3a0eb7f205f126fcc7c35d91 100644 (file)
@@ -39,5 +39,6 @@ DECLARE_MTYPE(PIM_SSMPINGD)
 DECLARE_MTYPE(PIM_STATIC_ROUTE)
 DECLARE_MTYPE(PIM_BR)
 DECLARE_MTYPE(PIM_RP)
+DECLARE_MTYPE(PIM_FILTER_NAME)
 
 #endif /* _QUAGGA_PIM_MEMORY_H */
index 1bd1b4457e0bfd59b76d71532481a5636bd9054a..1f64a6e299bebd440b50d2948997077efa853a23 100644 (file)
@@ -24,6 +24,8 @@
 #include "privs.h"
 #include "if.h"
 #include "prefix.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_rpf.h"
index 62e0bb1a3690959b6c7cf9b1be845a9bf8f7913e..0eadb5eb38574ab8bc0c7a6680490b1b8ad3c8a5 100644 (file)
@@ -23,6 +23,9 @@
 
 #include "if.h"
 #include "log.h"
+#include "prefix.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_vty.h"
index 4131c5ef019ebd9cf973ba9c659a907ec9e4c23a..ebc46f60ea866d2ec441b5c332b7f768095fcefe 100644 (file)
@@ -25,6 +25,8 @@
 #include "if.h"
 #include "thread.h"
 #include "prefix.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_mroute.h"
index daf825f6d824717e90f77ed9bc7c36840df7b1c5..78dc0e8550e983719e4c4ae0d144eba30724f28a 100644 (file)
@@ -28,6 +28,7 @@
 #include "memory.h"
 #include "vty.h"
 #include "vrf.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_vty.h"
@@ -44,6 +45,7 @@ struct rp_info
   struct prefix group;
   struct pim_rpf rp;
   int i_am_rp;
+  char *plist;
 };
 
 static struct list *qpim_rp_list = NULL;
@@ -70,6 +72,24 @@ pim_rp_list_cmp (void *v1, void *v2)
   if (rp1 && !rp2)
     return 1;
 
+  /*
+   * Sort by RP IP address
+   */
+  if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr)
+    return -1;
+
+  if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr)
+    return 1;
+
+  /*
+   * Sort by group IP address
+   */
+  if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr)
+    return -1;
+
+  if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr)
+    return 1;
+
   if (rp1 == tail)
     return 1;
 
@@ -106,8 +126,11 @@ pim_rp_free (void)
     list_free (qpim_rp_list);
 }
 
+/*
+ * Given an RP's prefix-list, return the RP's rp_info for that prefix-list
+ */
 static struct rp_info *
-pim_rp_find_exact (struct in_addr rp, struct prefix *group)
+pim_rp_find_prefix_list (struct in_addr rp, const char *plist)
 {
   struct listnode *node;
   struct rp_info *rp_info;
@@ -115,15 +138,40 @@ pim_rp_find_exact (struct in_addr rp, struct prefix *group)
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
     {
       if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr &&
-         prefix_same (&rp_info->group, group))
-       return rp_info;
+          rp_info->plist && strcmp(rp_info->plist, plist) == 0)
+        {
+          return rp_info;
+        }
     }
 
   return NULL;
 }
 
+/*
+ * Return true if plist is used by any rp_info
+ */
+static int
+pim_rp_prefix_list_used (const char *plist)
+{
+  struct listnode *node;
+  struct rp_info *rp_info;
+
+  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
+    {
+      if (rp_info->plist && strcmp(rp_info->plist, plist) == 0)
+        {
+          return 1;
+        }
+    }
+
+  return 0;
+}
+
+/*
+ * Given an RP's address, return the RP's rp_info that is an exact match for 'group'
+ */
 static struct rp_info *
-pim_rp_find_match (struct in_addr rp, struct prefix *group)
+pim_rp_find_exact (struct in_addr rp, struct prefix *group)
 {
   struct listnode *node;
   struct rp_info *rp_info;
@@ -131,28 +179,74 @@ pim_rp_find_match (struct in_addr rp, struct prefix *group)
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
     {
       if (rp.s_addr == rp_info->rp.rpf_addr.u.prefix4.s_addr &&
-          prefix_match (&rp_info->group, group))
+         prefix_same (&rp_info->group, group))
        return rp_info;
     }
 
   return NULL;
 }
 
+/*
+ * Given a group, return the rp_info for that group
+ */
 static struct rp_info *
 pim_rp_find_match_group (struct prefix *group)
 {
   struct listnode *node;
   struct rp_info *rp_info;
+  struct prefix_list *plist;
 
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
     {
-      if (prefix_match (&rp_info->group, group))
-       return rp_info;
+      if (rp_info->plist)
+        {
+          plist = prefix_list_lookup (AFI_IP, rp_info->plist);
+
+          if (plist && prefix_list_apply (plist, group) == PREFIX_PERMIT)
+            return rp_info;
+        }
+      else
+        {
+          if (prefix_match (&rp_info->group, group))
+            return rp_info;
+        }
     }
 
   return NULL;
 }
 
+/*
+ * When the user makes "ip pim rp" configuration changes or if they change the
+ * prefix-list(s) used by these statements we must tickle the upstream state
+ * for each group to make them re-lookup who their RP should be.
+ *
+ * This is a placeholder function for now.
+ */
+static void
+pim_rp_refresh_group_to_rp_mapping()
+{
+}
+
+void
+pim_rp_prefix_list_update (struct prefix_list *plist)
+{
+  struct listnode *node;
+  struct rp_info *rp_info;
+  int refresh_needed = 0;
+
+  for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
+    {
+      if (rp_info->plist && strcmp(rp_info->plist, prefix_list_name (plist)) == 0)
+        {
+          refresh_needed = 1;
+          break;
+        }
+    }
+
+  if (refresh_needed)
+    pim_rp_refresh_group_to_rp_mapping();
+}
+
 static void
 pim_rp_check_interfaces (struct rp_info *rp_info)
 {
@@ -172,19 +266,19 @@ pim_rp_check_interfaces (struct rp_info *rp_info)
 }
 
 int
-pim_rp_new (const char *rp, const char *group_range)
+pim_rp_new (const char *rp, const char *group_range, const char *plist)
 {
   int result;
   struct rp_info *rp_info;
   struct rp_info *rp_all;
   struct prefix group_all;
-
-  str2prefix ("224.0.0.0/4", &group_all);
-  rp_all = pim_rp_find_match_group(&group_all);
+  struct listnode *node, *nnode;
+  struct rp_info *tmp_rp_info;
+  char buffer[BUFSIZ];
 
   rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info));
-  if (!rp)
-    return -1;
+  if (!rp_info)
+    return PIM_MALLOC_FAIL;
 
   if (group_range == NULL)
     result = str2prefix ("224.0.0.0/4", &rp_info->group);
@@ -192,54 +286,147 @@ pim_rp_new (const char *rp, const char *group_range)
     result = str2prefix (group_range, &rp_info->group);
 
   if (!result)
-    return -1;
+    {
+      XFREE (MTYPE_PIM_RP, rp_info);
+      return PIM_GROUP_BAD_ADDRESS;
+    }
+
   rp_info->rp.rpf_addr.family = AF_INET;
   result = inet_pton (rp_info->rp.rpf_addr.family, rp, &rp_info->rp.rpf_addr.u.prefix4);
-  if (result <= 0)
-    return -1;
 
-  /*
-   * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
-   */
-  if (prefix_same (&rp_all->group, &rp_info->group) &&
-      pim_rpf_addr_is_inaddr_none (&rp_all->rp))
+  if (result <= 0)
     {
-      rp_all->rp.rpf_addr = rp_info->rp.rpf_addr;
       XFREE (MTYPE_PIM_RP, rp_info);
-      if (!pim_rp_setup ())
-        return -2;
-      pim_rp_check_interfaces (rp_all);
-      return 0;
+      return PIM_RP_BAD_ADDRESS;
     }
 
-  if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
+  if (plist)
     {
-      XFREE (MTYPE_PIM_RP, rp_info);
-      return 0;
-    }
+      /*
+       * Return if the prefix-list is already configured for this RP
+       */
+      if (pim_rp_find_prefix_list (rp_info->rp.rpf_addr.u.prefix4, plist))
+        {
+          XFREE (MTYPE_PIM_RP, rp_info);
+          return PIM_SUCCESS;
+        }
+
+      /*
+       * Barf if the prefix-list is already configured for an RP
+       */
+      if (pim_rp_prefix_list_used (plist))
+        {
+          XFREE (MTYPE_PIM_RP, rp_info);
+          return PIM_RP_PFXLIST_IN_USE;
+        }
+
+      /*
+       * Free any existing rp_info entries for this RP
+       */
+      for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info))
+        {
+          if (rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr)
+            {
+              if (tmp_rp_info->plist)
+                pim_rp_del (rp, NULL, tmp_rp_info->plist);
+              else
+                pim_rp_del (rp, prefix2str(&tmp_rp_info->group, buffer, BUFSIZ), NULL);
+            }
+        }
 
-  if (pim_rp_find_match (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
+      rp_info->plist = XSTRDUP(MTYPE_PIM_FILTER_NAME, plist);
+    }
+  else
     {
-      if (prefix_same (&group_all, &rp_info->group))
+      str2prefix ("224.0.0.0/4", &group_all);
+      rp_all = pim_rp_find_match_group(&group_all);
+
+      /*
+       * Barf if group is a non-multicast subnet
+       */
+      if (! prefix_match (&rp_all->group, &rp_info->group))
         {
-          return 0;
+          XFREE (MTYPE_PIM_RP, rp_info);
+          return PIM_GROUP_BAD_ADDRESS;
         }
 
-      XFREE (MTYPE_PIM_RP, rp_info);
-      return -3;
+      /*
+       * Remove any prefix-list rp_info entries for this RP
+       */
+      for (ALL_LIST_ELEMENTS (qpim_rp_list, node, nnode, tmp_rp_info))
+        {
+          if (tmp_rp_info->plist &&
+              rp_info->rp.rpf_addr.u.prefix4.s_addr == tmp_rp_info->rp.rpf_addr.u.prefix4.s_addr)
+            {
+              pim_rp_del (rp, NULL, tmp_rp_info->plist);
+            }
+        }
+
+      /*
+       * Take over the 224.0.0.0/4 group if the rp is INADDR_NONE
+       */
+      if (prefix_same (&rp_all->group, &rp_info->group) &&
+          pim_rpf_addr_is_inaddr_none (&rp_all->rp))
+        {
+          rp_all->rp.rpf_addr = rp_info->rp.rpf_addr;
+          XFREE (MTYPE_PIM_RP, rp_info);
+
+          if (!pim_rp_setup ())
+            return PIM_RP_NO_PATH;
+
+          pim_rp_check_interfaces (rp_all);
+          return PIM_SUCCESS;
+        }
+
+      /*
+       * Return if the group is already configured for this RP
+       */
+      if (pim_rp_find_exact (rp_info->rp.rpf_addr.u.prefix4, &rp_info->group))
+        {
+          XFREE (MTYPE_PIM_RP, rp_info);
+          return PIM_SUCCESS;
+        }
+
+      /*
+       * Barf if this group is already covered by some other RP
+       */
+      tmp_rp_info = pim_rp_find_match_group (&rp_info->group);
+
+      if (tmp_rp_info)
+        {
+          if (tmp_rp_info->plist)
+            {
+                XFREE (MTYPE_PIM_RP, rp_info);
+                return PIM_GROUP_PFXLIST_OVERLAP;
+            }
+          else
+            {
+              /*
+               * If the only RP that covers this group is an RP configured for
+               * 224.0.0.0/4 that is fine, ignore that one.  For all others
+               * though we must return PIM_GROUP_OVERLAP
+               */
+              if (! prefix_same (&group_all, &tmp_rp_info->group))
+                {
+                  XFREE (MTYPE_PIM_RP, rp_info);
+                  return PIM_GROUP_OVERLAP;
+                }
+            }
+        }
     }
 
   listnode_add_sort (qpim_rp_list, rp_info);
 
   if (!pim_rp_setup ())
-    return -2;
+    return PIM_RP_NO_PATH;
 
   pim_rp_check_interfaces (rp_info);
-  return 0;
+  pim_rp_refresh_group_to_rp_mapping();
+  return PIM_SUCCESS;
 }
 
 int
-pim_rp_del (const char *rp, const char *group_range)
+pim_rp_del (const char *rp, const char *group_range, const char *plist)
 {
   struct prefix group;
   struct in_addr rp_addr;
@@ -248,35 +435,46 @@ pim_rp_del (const char *rp, const char *group_range)
   struct rp_info *rp_all;
   int result;
 
-  str2prefix ("224.0.0.0/4", &g_all);
   if (group_range == NULL)
     result = str2prefix ("224.0.0.0/4", &group);
   else
     result = str2prefix (group_range, &group);
 
   if (!result)
-    return -1;
-
-  rp_all = pim_rp_find_match_group (&g_all);
+    return PIM_GROUP_BAD_ADDRESS;
 
   result = inet_pton (AF_INET, rp, &rp_addr);
   if (result <= 0)
-    return -1;
+    return PIM_RP_BAD_ADDRESS;
+
+  if (plist)
+    rp_info = pim_rp_find_prefix_list (rp_addr, plist);
+  else
+    rp_info = pim_rp_find_exact (rp_addr, &group);
 
-  rp_info = pim_rp_find_exact (rp_addr, &group);
   if (!rp_info)
-    return -2;
+    return PIM_RP_NOT_FOUND;
+
+  if (rp_info->plist)
+    {
+      XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
+      rp_info->plist = NULL;
+    }
+
+  str2prefix ("224.0.0.0/4", &g_all);
+  rp_all = pim_rp_find_match_group (&g_all);
 
   if (rp_all == rp_info)
     {
       rp_all->rp.rpf_addr.family = AF_INET;
       rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
       rp_all->i_am_rp = 0;
-      return 0;
+      return PIM_SUCCESS;
     }
 
   listnode_delete (qpim_rp_list, rp_info);
-  return 0;
+  pim_rp_refresh_group_to_rp_mapping();
+  return PIM_SUCCESS;
 }
 
 int
@@ -430,7 +628,8 @@ pim_rp_config_write (struct vty *vty)
 {
   struct listnode *node;
   struct rp_info *rp_info;
-  char buffer[32];
+  char rp_buffer[32];
+  char group_buffer[32];
   int count = 0;
 
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
@@ -438,13 +637,15 @@ pim_rp_config_write (struct vty *vty)
       if (pim_rpf_addr_is_inaddr_none (&rp_info->rp))
         continue;
 
-      if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp))
-        {
-         char buf[32];
-          vty_out(vty, "ip pim rp %s %s%s", inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, buffer, 32),
-                 prefix2str(&rp_info->group, buf, 32), VTY_NEWLINE);
-          count++;
-        }
+      if (rp_info->plist)
+        vty_out(vty, "ip pim rp %s prefix-list %s%s",
+                inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32),
+                rp_info->plist, VTY_NEWLINE);
+      else
+        vty_out(vty, "ip pim rp %s %s%s",
+                inet_ntop(AF_INET, &rp_info->rp.rpf_addr.u.prefix4, rp_buffer, 32),
+                prefix2str(&rp_info->group, group_buffer, 32), VTY_NEWLINE);
+      count++;
     }
 
   return count;
@@ -486,18 +687,25 @@ pim_rp_show_information (struct vty *vty)
   struct rp_info *rp_info;
   struct listnode *node;
 
-  vty_out (vty, "RP Addr           Group   Oif    I_am_RP%s", VTY_NEWLINE);
+  vty_out (vty, "RP address       group/prefix-list   OIF         I am RP%s", VTY_NEWLINE);
   for (ALL_LIST_ELEMENTS_RO (qpim_rp_list, node, rp_info))
     {
       if (!pim_rpf_addr_is_inaddr_none (&rp_info->rp))
         {
           char buf[48];
-          vty_out (vty, "%-10s  %-10s  %-10s%-10d%s",
-          inet_ntoa (rp_info->rp.rpf_addr.u.prefix4),
-                    prefix2str(&rp_info->group, buf, 48),
-                    rp_info->rp.source_nexthop.interface->name,
-                    rp_info->i_am_rp, VTY_NEWLINE);
+          vty_out (vty, "%-15s  ", inet_ntoa (rp_info->rp.rpf_addr.u.prefix4));
+
+          if (rp_info->plist)
+            vty_out (vty, "%-18s  ", rp_info->plist);
+          else
+            vty_out (vty, "%-18s  ", prefix2str(&rp_info->group, buf, 48));
+
+          vty_out (vty, "%-10s  ", rp_info->rp.source_nexthop.interface->name);
+
+          if (rp_info->i_am_rp)
+            vty_out (vty, "yes%s", VTY_NEWLINE);
+          else
+            vty_out (vty, "no%s", VTY_NEWLINE);
         }
     }
-  return;
 }
index c9dfa201f19ad2307364276ad1a22cc4f975803d..230f4f08ffed720a0b29d6b3214782c69bd01c04 100644 (file)
@@ -24,8 +24,9 @@
 void pim_rp_init (void);
 void pim_rp_free (void);
 
-int pim_rp_new (const char *rp, const char *group);
-int pim_rp_del (const char *rp, const char *group);
+int pim_rp_new (const char *rp, const char *group, const char *plist);
+int pim_rp_del (const char *rp, const char *group, const char *plist);
+void pim_rp_prefix_list_update (struct prefix_list *plist);
 
 int pim_rp_config_write (struct vty *vty);
 
index 66c5268f987fbf5617d79141ea884a0b3a14e7c5..7f1357783a066ab762596bd4b3e9d791298cbcfa 100644 (file)
@@ -28,6 +28,8 @@
 #include "memory.h"
 #include "thread.h"
 #include "linklist.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_pim.h"
index 85df83287b81e830c4cdf5ad2cd764adb6889ad4..3eb04d347e658306bf2414a1e3a09d4ac4852acb 100644 (file)
 
 #include "if.h"
 #include "linklist.h"
+#include "prefix.h"
+#include "vty.h"
 #include "vrf.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_vty.h"
index d4eb2d32521189e1cb0d1ea2cf2031b2ea4aef66..cfdc447fc3b1f50e1b7b025d0d1a3a6be39685d3 100644 (file)
@@ -29,6 +29,8 @@
 #include "zclient.h"
 #include "stream.h"
 #include "network.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_pim.h"
index 94c8f20e9721accca150ad6d493adb4278e2a7fd..dff3f75aedd16fd158ce460fadbd7f4b009a10c8 100644 (file)
@@ -24,6 +24,9 @@
 #include "log.h"
 #include "memory.h"
 #include "if.h"
+#include "prefix.h"
+#include "vty.h"
+#include "plist.h"
 
 #include "pimd.h"
 #include "pim_cmd.h"
index f7a02f93761bc67d9f45b6747c90f041027b178a..46b3e5ce78e8715112d66bf66f86a543d833dc0b 100644 (file)
 #define PIM_MASK_STATIC              (1 << 17)
 #define PIM_MASK_PIM_REG             (1 << 18)
 
+
+/* PIM error codes */
+#define PIM_SUCCESS                0
+#define PIM_MALLOC_FAIL           -1
+#define PIM_GROUP_BAD_ADDRESS     -2
+#define PIM_GROUP_OVERLAP         -3
+#define PIM_GROUP_PFXLIST_OVERLAP -4
+#define PIM_RP_BAD_ADDRESS        -5
+#define PIM_RP_NO_PATH            -6
+#define PIM_RP_NOT_FOUND          -7
+#define PIM_RP_PFXLIST_IN_USE     -8
+
 const char *const PIM_ALL_SYSTEMS;
 const char *const PIM_ALL_ROUTERS;
 const char *const PIM_ALL_PIM_ROUTERS;