A new subnode under router bgp command has been created: vrf <>.
This enhancement permits creating a VRF instance specific to VRF.
Then it permits setting specific configuration to vrf entity.
This is the case for route distinguisher, but also route target.
vrf <NAME>
 rd <route distinguisher name>
 no rd <RD name>
 rt import <RT list>
 rt export <RT list>
 rt both <RT list>
 no rt import <>
 no rt export <>
 no rt both <>
 exit
no vrf <NAME>

Currently, this is necessary to manually set route distinguisher.

Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp_route.c |   3 +
 bgpd/bgp_vty.c   | 252 ++++++++++++++++++++++++++++++++++++++-----------------
 bgpd/bgpd.c      | 126 ++++++++++++++++++++++------
 bgpd/bgpd.h      |  14 +++-
 4 files changed, 291 insertions(+), 104 deletions(-)

diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index eb0c9e50094f..c4236fab481b 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1528,6 +1528,9 @@ bgp_process_announce_selected (struct peer *peer, struct 
bgp_info *selected,
 void bgp_vrf_clean_tables (struct bgp_vrf *vrf)
 {
   afi_t afi;
+
+  if (vrf->rib == NULL || vrf->route == NULL)
+    return;
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     {
       struct bgp_info *ri, *ri_next;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 63a7b5bfdcf6..4080438b06a0 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9893,57 +9893,86 @@ bgp_config_write_redistribute (struct vty *vty, struct 
bgp *bgp, afi_t afi,
 
 DEFUN (bgp_vrf,
        bgp_vrf_cmd,
-       "vrf rd WORD",
-       "BGP VPN VRF\n"
-       "Route Distinguisher\n"
-       "Route Distinguisher\n"
+       "vrf WORD",
+       "BGP VRF\n"
+       "VRF Name\n"
 )
 {
   struct bgp *bgp = vty->index;
   struct bgp_vrf *vrf;
-  struct prefix_rd prd;
+  if ( (vrf = bgp_vrf_lookup_per_name (bgp, argv[0], 1)) == NULL)
+    return CMD_ERR_NO_MATCH;
+  vty->index_sub = vrf;
+  vty->node = BGP_VRF_NODE;
 
-  if (! str2prefix_rd (argv[0], &prd))
-    {
-      vty_out (vty, "%% Invalid RD '%s'%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  return CMD_SUCCESS;
+}
+DEFUN (no_bgp_vrf,
+       no_bgp_vrf_cmd,
+       "no vrf WORD",
+       NO_STR
+       "BGP VRF\n"
+       "VRF Name\n"
+)
+{
+  struct bgp *bgp = vty->index;
+  struct bgp_vrf *vrf;
 
-  vrf = bgp_vrf_lookup (bgp, &prd);
-  if (vrf)
+  vrf = bgp_vrf_lookup_per_name (bgp, argv[0], 0);
+  if (! vrf)
     {
-      vty_out (vty, "%% VRF with RD '%s' already exists%s", argv[0], 
VTY_NEWLINE);
+      vty_out (vty, "%% No VRF with name '%s'%s", argv[0], VTY_NEWLINE);
       return CMD_WARNING;
     }
+  bgp_vrf_delete (vrf);
+  return CMD_SUCCESS;
+}
 
-  bgp_vrf_create (bgp, &prd);
+DEFUN (exit_bgp_vrf,
+       exit_bgp_vrf_cmd,
+       "exit-bgp-vrf",
+       "Exit from BGP vrf configuration mode\n")
+{
+  if (vty->node == BGP_VRF_NODE)
+    vty->node = BGP_NODE;
   return CMD_SUCCESS;
 }
 
-DEFUN (bgp_vrf_exports,
-       bgp_vrf_exports_cmd,
-       "vrf rd WORD exports .LINE",
-       "BGP VPN VRF\n"
+DEFUN (bgp_vrf_rd,
+       bgp_vrf_rd_cmd,
+       "rd WORD",
        "Route Distinguisher\n"
-       "Route Distinguisher\n"
-       "Export RT values\n"
-       "Export RT values\n"
+       "Route Distinguisher Name\n"
 )
 {
   struct bgp *bgp = vty->index;
-  struct bgp_vrf *vrf;
+  struct bgp_vrf *vrf = vty->index_sub;
   struct prefix_rd prd;
-  struct ecommunity *ecom = NULL;
-  int fail = 0, i;
-  char *rts = NULL, *rts_ptr;
 
   if (! str2prefix_rd (argv[0], &prd))
     {
       vty_out (vty, "%% Invalid RD '%s'%s", argv[0], VTY_NEWLINE);
-      fail++;
+      return CMD_WARNING;
     }
+  bgp_vrf_update_rd (bgp, vrf, &prd);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_vrf_rt_export,
+       bgp_vrf_rt_export_cmd,
+       "rt export .LINE",
+       "Route Target\n"
+       "Export RT values\n"
+       "Export RT values\n"
+)
+{
+  struct bgp_vrf *vrf = vty->index_sub;
+  struct ecommunity *ecom = NULL;
+  int fail = 0, i;
+  char *rts = NULL, *rts_ptr;
+
   /* forge export list */
-  i = 1;
+  i = 0;
   rts = XCALLOC(MTYPE_TMP,2048);
   rts_ptr = rts;
   while(i < argc)
@@ -9963,44 +9992,27 @@ DEFUN (bgp_vrf_exports,
   if (fail)
     return CMD_WARNING;
 
-  vrf = bgp_vrf_lookup (bgp, &prd);
-  if (! vrf)
-    {
-      ecommunity_free (&ecom);
-      vty_out (vty, "%% No VRF with RD '%s'%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
   ecom = ecommunity_intern (ecom);
   bgp_vrf_rt_export_set (vrf, ecom);
   ecommunity_unintern (&ecom);
   return CMD_SUCCESS;
 }
 
-DEFUN (bgp_vrf_imports,
-       bgp_vrf_imports_cmd,
-       "vrf rd WORD imports .LINE",
-       "BGP VPN VRF\n"
-       "Route Distinguisher\n"
-       "Route Distinguisher\n"
+DEFUN (bgp_vrf_rt_import,
+       bgp_vrf_rt_import_cmd,
+       "rt import .LINE",
+       "Route Target\n"
        "Import RT values\n"
        "Import RT values\n"
 )
 {
-  struct bgp *bgp = vty->index;
-  struct bgp_vrf *vrf;
-  struct prefix_rd prd;
+  struct bgp_vrf *vrf = vty->index_sub;
   struct ecommunity *ecom = NULL;
   int fail = 0, i;
   char *rts = NULL, *rts_ptr;
 
-  if (! str2prefix_rd (argv[0], &prd))
-    {
-      vty_out (vty, "%% Invalid RD '%s'%s", argv[0], VTY_NEWLINE);
-      fail++;
-    }
   /* forge export list */
-  i = 1;
+  i = 0;
   rts = XCALLOC(MTYPE_TMP,2048);
   rts_ptr = rts;
   while(i < argc)
@@ -10020,46 +10032,111 @@ DEFUN (bgp_vrf_imports,
   if (fail)
     return CMD_WARNING;
 
-  vrf = bgp_vrf_lookup (bgp, &prd);
-  if (! vrf)
-    {
-      ecommunity_free (&ecom);
-      vty_out (vty, "%% No VRF with RD '%s'%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
   ecom = ecommunity_intern (ecom);
   bgp_vrf_rt_import_set (vrf, ecom);
   ecommunity_unintern (&ecom);
   return CMD_SUCCESS;
 }
 
-DEFUN (no_bgp_vrf,
-       no_bgp_vrf_cmd,
-       "no vrf rd WORD",
-       NO_STR
-       "BGP VPN VRF\n"
-       "Route Distinguisher\n"
-       "Route Distinguisher\n"
+DEFUN (bgp_vrf_rt_both,
+       bgp_vrf_rt_both_cmd,
+       "rt both .LINE",
+       "Route Target\n"
+       "Import and Export RT values\n"
+       "Import and Export RT values\n"
 )
 {
-  struct bgp *bgp = vty->index;
-  struct bgp_vrf *vrf;
-  struct prefix_rd prd;
+  struct bgp_vrf *vrf = vty->index_sub;
+  struct ecommunity *ecom = NULL, *ecom1;
+  int fail = 0, i;
+  char *rts = NULL, *rts_ptr;
 
-  if (! str2prefix_rd (argv[0], &prd))
+  /* forge export list */
+  i = 0;
+  rts = XCALLOC(MTYPE_TMP,2048);
+  rts_ptr = rts;
+  while(i < argc)
     {
-      vty_out (vty, "%% Invalid RD '%s'%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
+      rts_ptr += sprintf(rts_ptr, "rt %s ",argv[i]);
+      i++;
     }
-
-  vrf = bgp_vrf_lookup (bgp, &prd);
-  if (! vrf)
+  /* convert list of ecoms string into ecom struct */
+  ecom = ecommunity_str2com (rts, ECOMMUNITY_ROUTE_TARGET, 1);
+  if (! ecom)
     {
-      vty_out (vty, "%% No VRF with RD '%s'%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
+      vty_out (vty, "%% Invalid RT '%s'%s", argv[1], VTY_NEWLINE);
+      fail++;
     }
-  bgp_vrf_delete (vrf);
+  if (rts)
+    XFREE (MTYPE_TMP, rts);
+  if (fail)
+    return CMD_WARNING;
+
+  ecom1 = ecommunity_intern (ecom);
+  bgp_vrf_rt_import_set (vrf, ecom1);
+  ecommunity_unintern (&ecom1);
+
+  ecom1 = ecommunity_intern (ecom);
+  bgp_vrf_rt_export_set (vrf, ecom1);
+  ecommunity_unintern (&ecom1);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_vrf_rt_import,
+       no_bgp_vrf_rt_import_cmd,
+       "no rt import",
+       NO_STR
+       "Route Target\n"
+       "Import values\n"
+)
+{
+  struct bgp_vrf *vrf = vty->index_sub;
+
+  bgp_vrf_rt_import_unset (vrf);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_vrf_rt_export,
+       no_bgp_vrf_rt_export_cmd,
+       "no rt export",
+       NO_STR
+       "Route Target\n"
+       "Export RT values\n"
+)
+{
+  struct bgp_vrf *vrf = vty->index_sub;
+
+  bgp_vrf_rt_export_unset (vrf);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_vrf_rt_both,
+       no_bgp_vrf_rt_both_cmd,
+       "no rt both",
+       NO_STR
+       "Route Target\n"
+       "Import and Export RT values\n"
+)
+{
+  struct bgp_vrf *vrf = vty->index_sub;
+
+  bgp_vrf_rt_export_unset (vrf);
+  bgp_vrf_rt_import_unset (vrf);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_vrf_rd,
+       no_bgp_vrf_rd_cmd,
+       "no rd WORD",
+       NO_STR
+       "BGP Route Distinguisher\n"
+       "Route Distinguisher\n"
+)
+{
+  struct bgp_vrf *vrf = vty->index_sub;
+
+  bgp_vrf_delete_rd (vrf);
   return CMD_SUCCESS;
 }
 
@@ -10127,6 +10204,14 @@ static struct cmd_node bgp_encapv6_node =
   1
 };
 
+/* VRF node. */
+static struct cmd_node bgp_vrf_node =
+{
+  BGP_VRF_NODE,
+  "%s(bgp-vrf)# ",
+  1
+};
+
 static void community_list_vty (void);
 
 void
@@ -10142,6 +10227,7 @@ bgp_vty_init (void)
   install_node (&bgp_vpnv6_node, NULL);
   install_node (&bgp_encap_node, NULL);
   install_node (&bgp_encapv6_node, NULL);
+  install_node (&bgp_vrf_node, NULL);
 
   /* Install default VTY commands to new nodes.  */
   install_default (BGP_NODE);
@@ -10153,11 +10239,19 @@ bgp_vty_init (void)
   install_default (BGP_VPNV6_NODE);
   install_default (BGP_ENCAP_NODE);
   install_default (BGP_ENCAPV6_NODE);
+  install_default (BGP_VRF_NODE);
   
   install_element (BGP_NODE, &bgp_vrf_cmd);
-  install_element (BGP_NODE, &bgp_vrf_exports_cmd);
-  install_element (BGP_NODE, &bgp_vrf_imports_cmd);
   install_element (BGP_NODE, &no_bgp_vrf_cmd);
+  install_element (BGP_VRF_NODE, &bgp_vrf_rd_cmd);
+  install_element (BGP_VRF_NODE, &no_bgp_vrf_rd_cmd);
+  install_element (BGP_VRF_NODE, &bgp_vrf_rt_export_cmd);
+  install_element (BGP_VRF_NODE, &bgp_vrf_rt_import_cmd);
+  install_element (BGP_VRF_NODE, &bgp_vrf_rt_both_cmd);
+  install_element (BGP_VRF_NODE, &no_bgp_vrf_rt_import_cmd);
+  install_element (BGP_VRF_NODE, &no_bgp_vrf_rt_export_cmd);
+  install_element (BGP_VRF_NODE, &no_bgp_vrf_rt_both_cmd);
+  install_element (BGP_VRF_NODE, &exit_bgp_vrf_cmd);
 
   /* "bgp multiple-instance" commands. */
   install_element (CONFIG_NODE, &bgp_multiple_instance_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 5725730d9454..450371efd243 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2091,28 +2091,30 @@ bgp_rt_hash_dealloc (struct bgp_rt_sub *rt_sub)
 }
 
 struct bgp_vrf *
-bgp_vrf_lookup (struct bgp *bgp, struct prefix_rd *outbound_rd)
+bgp_vrf_lookup_per_name (struct bgp *bgp, const char *name, int create)
 {
+  afi_t afi;
   struct listnode *node;
   struct bgp_vrf *vrf;
+  unsigned int len;
 
+  if (!name)
+    return NULL;
+  len = strlen(name);
   for (ALL_LIST_ELEMENTS_RO(bgp->vrfs, node, vrf))
-    if (!memcmp (outbound_rd->val, vrf->outbound_rd.val, 8))
-      return vrf;
-  return NULL;
-}
-
-struct bgp_vrf *
-bgp_vrf_create (struct bgp *bgp, struct prefix_rd *outbound_rd)
-{
-  struct bgp_vrf *vrf;
-  afi_t afi;
-
-  if ( (vrf = XCALLOC (MTYPE_BGP_VRF, sizeof (struct bgp_vrf))) == NULL)
+    {
+      if (strlen (vrf->name) != len)
+        continue;
+      if (0 == strcmp (vrf->name, name))
+        break;
+    }
+  if (vrf || create == 0)
+    return vrf;
+  if ((vrf = XCALLOC (MTYPE_BGP_VRF, sizeof (struct bgp_vrf))) == NULL)
     return NULL;
-
   vrf->bgp = bgp;
-  vrf->outbound_rd = *outbound_rd;
+  vrf->name = strdup (name);
+  vrf->flag |= BGP_VRF_RD_UNSET;
 
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     {
@@ -2126,6 +2128,49 @@ bgp_vrf_create (struct bgp *bgp, struct prefix_rd 
*outbound_rd)
   return vrf;
 }
 
+struct bgp_vrf *
+bgp_vrf_lookup_per_rn (struct bgp *bgp, int afi, struct bgp_node *vrf_rn)
+{
+  struct listnode *node;
+  struct bgp_vrf *vrf;
+
+  if(bgp_node_table (vrf_rn)->type != BGP_TABLE_VRF)
+    return NULL;
+  for (ALL_LIST_ELEMENTS_RO(bgp->vrfs, node, vrf))
+    if(vrf->rib[afi] == bgp_node_table (vrf_rn))
+      {
+        return vrf;
+      }
+  return NULL;
+}
+
+struct bgp_vrf *
+bgp_vrf_lookup (struct bgp *bgp, struct prefix_rd *outbound_rd)
+{
+  struct listnode *node;
+  struct bgp_vrf *vrf;
+
+  for (ALL_LIST_ELEMENTS_RO(bgp->vrfs, node, vrf))
+    if (!memcmp (outbound_rd->val, vrf->outbound_rd.val, 8))
+      return vrf;
+  return NULL;
+}
+
+struct bgp_vrf *
+bgp_vrf_update_rd (struct bgp *bgp, struct bgp_vrf *vrf, struct prefix_rd 
*outbound_rd)
+{
+  if (!vrf)
+    {
+      char vrf_rd_str[RD_ADDRSTRLEN];
+      prefix_rd2str (outbound_rd, vrf_rd_str, sizeof (vrf_rd_str));
+      if ( (vrf = bgp_vrf_lookup_per_name (bgp, vrf_rd_str, 1)) == NULL)
+        return NULL;
+    }
+  vrf->flag &= ~BGP_VRF_RD_UNSET;
+  vrf->outbound_rd = *outbound_rd;
+  return vrf;
+}
+
 static struct ecommunity * ecommunity_reintern (struct ecommunity *ecom)
 {
   assert (ecom->refcnt > 0);
@@ -2134,6 +2179,13 @@ static struct ecommunity * ecommunity_reintern (struct 
ecommunity *ecom)
 }
 
 void
+bgp_vrf_rt_export_unset (struct bgp_vrf *vrf)
+{
+  if (vrf->rt_export)
+    ecommunity_unintern (&vrf->rt_export);
+}
+
+void
 bgp_vrf_rt_export_set (struct bgp_vrf *vrf, struct ecommunity *rt_export)
 {
   if (vrf->rt_export)
@@ -2142,7 +2194,7 @@ bgp_vrf_rt_export_set (struct bgp_vrf *vrf, struct 
ecommunity *rt_export)
   vrf->rt_export = ecommunity_reintern (rt_export);
 }
 
-static void
+void
 bgp_vrf_rt_import_unset (struct bgp_vrf *vrf)
 {
   size_t i;
@@ -2191,21 +2243,41 @@ bgp_vrf_rt_import_set (struct bgp_vrf *vrf, struct 
ecommunity *rt_import)
     bgp_vrf_apply_new_imports (vrf, afi);
 }
 
-static void
-bgp_vrf_delete_int (void *arg)
+/* delete RD <> command as well as RD export/import 
+ * and RIB table associated
+ */
+void
+bgp_vrf_delete_rd (struct bgp_vrf *vrf)
 {
-  struct bgp_vrf *vrf = arg;
   char vrf_rd_str[RD_ADDRSTRLEN];
 
+  if (!vrf)
+    return;
+
   prefix_rd2str(&vrf->outbound_rd, vrf_rd_str, sizeof(vrf_rd_str));
-  zlog_info ("deleting vrf %s", vrf_rd_str);
+  zlog_info ("deleting rd %s", vrf_rd_str);
 
   bgp_vrf_clean_tables (vrf);
 
   bgp_vrf_rt_import_unset (vrf);
   if (vrf->rt_export)
     ecommunity_unintern (&vrf->rt_export);
+  return;
+}
 
+static void
+bgp_vrf_delete_int (void *arg)
+{
+  struct bgp_vrf *vrf = arg;
+  char vrf_rd_str[RD_ADDRSTRLEN];
+
+  prefix_rd2str(&vrf->outbound_rd, vrf_rd_str, sizeof(vrf_rd_str));
+  zlog_info ("deleting vrf %s", vrf_rd_str);
+
+  bgp_vrf_delete_rd (vrf);
+
+  if (vrf->name)
+    free (vrf->name);
   XFREE (MTYPE_BGP_VRF, vrf);
 }
 
@@ -5790,14 +5862,19 @@ bgp_config_write (struct vty *vty)
         char *str_p, *str2_p;
         for (ALL_LIST_ELEMENTS_RO(bgp->vrfs, node, vrf))
           {
-            str_p = prefix_rd2str(&(vrf->outbound_rd), rdstr, RD_ADDRSTRLEN);
-            vty_out(vty, " vrf rd %s%s", str_p == NULL?"<err>":str_p, 
VTY_NEWLINE);
+            vty_out(vty, " vrf %s%s", vrf->name, VTY_NEWLINE);
+            /* an RD has been configured */
+            if (!(vrf->flag & BGP_VRF_RD_UNSET))
+              {
+                str_p = prefix_rd2str(&(vrf->outbound_rd), rdstr, 
RD_ADDRSTRLEN);
+                vty_out(vty, "  rd %s%s", str_p == NULL?"<err>":str_p, 
VTY_NEWLINE);
+              }
             if(vrf->rt_import)
               {
                 str2_p = ecommunity_ecom2str (vrf->rt_import, 
ECOMMUNITY_FORMAT_ROUTE_MAP);
                 if(str2_p)
                   {
-                    vty_out(vty, " vrf rd %s import %s%s", str_p == 
NULL?"<err>":str_p, str2_p, VTY_NEWLINE);
+                    vty_out(vty, "  rt import %s%s", str2_p, VTY_NEWLINE);
                     XFREE (MTYPE_ECOMMUNITY_STR, str2_p);
                   }
               }
@@ -5806,10 +5883,11 @@ bgp_config_write (struct vty *vty)
                 str2_p = ecommunity_ecom2str (vrf->rt_export, 
ECOMMUNITY_FORMAT_ROUTE_MAP);
                 if(str2_p)
                   {
-                    vty_out(vty, " vrf rd %s export %s%s", str_p == 
NULL?"<err>":str_p, str2_p, VTY_NEWLINE);
+                    vty_out(vty, "  rt export %s%s", str2_p, VTY_NEWLINE);
                     XFREE (MTYPE_ECOMMUNITY_STR, str2_p);
                   }
               }
+            vty_out (vty, " exit%s", VTY_NEWLINE);
           }
       }
       /* maximum-paths */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 15245ceeb8d2..c81466e85205 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -31,6 +31,8 @@ typedef u_int32_t as_t;
 typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
 typedef u_int16_t bgp_size_t;
 
+struct bgp_node;
+
 /* BGP router distinguisher value.  */
 #define BGP_RD_SIZE                8
 
@@ -208,6 +210,7 @@ struct bgp_vrf
 {
   struct bgp *bgp;
 
+  char *name;
   /* RD used for route advertisements */
   struct prefix_rd outbound_rd;
 
@@ -221,6 +224,10 @@ struct bgp_vrf
   /* Static route configuration.  */
   struct bgp_table *route[AFI_MAX];
 
+  /* internal flag */
+#define BGP_VRF_RD_UNSET 1
+  uint16_t flag;
+
 };
 
 /* BGP peer-group support. */
@@ -1033,11 +1040,16 @@ extern int peer_ttl_security_hops_set (struct peer *, 
int);
 extern int peer_ttl_security_hops_unset (struct peer *);
 
 extern void bgp_scan_finish (void);
-extern struct bgp_vrf *bgp_vrf_create (struct bgp *bgp, struct prefix_rd 
*outbound_rd);
+extern void bgp_vrf_delete_rd (struct bgp_vrf *vrf);
+extern struct bgp_vrf *bgp_vrf_update_rd (struct bgp *bgp, struct bgp_vrf 
*vrf, struct prefix_rd *outbound_rd);
 extern struct bgp_vrf *bgp_vrf_lookup (struct bgp *bgp, struct prefix_rd 
*outbound_rd);
+extern struct bgp_vrf *bgp_vrf_lookup_per_name (struct bgp *bgp, const char 
*name, int create);
+extern struct bgp_vrf *bgp_vrf_lookup_per_rn (struct bgp *bgp, int afi, struct 
bgp_node *vrf_rn);
 extern void bgp_vrf_delete (struct bgp_vrf *vrf);
 extern void bgp_vrf_rt_export_set (struct bgp_vrf *vrf, struct ecommunity 
*rt_export);
 extern void bgp_vrf_rt_import_set (struct bgp_vrf *vrf, struct ecommunity 
*rt_import);
 extern void bgp_vrf_clean_tables (struct bgp_vrf *vrf);
+extern void bgp_vrf_rt_import_unset (struct bgp_vrf *vrf);
+extern void bgp_vrf_rt_export_unset (struct bgp_vrf *vrf);
 
 #endif /* _QUAGGA_BGPD_H */
-- 
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to