]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: implement admin distance
authorMaitane Zotes <maz@open.ch>
Mon, 17 Mar 2014 13:01:42 +0000 (14:01 +0100)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 20 Oct 2016 02:28:45 +0000 (22:28 -0400)
Until today the admin distance cannot be configured for any IPv6
routing protocol. This patch implements it for bgp.

Signed-off-by: Maitane Zotes <maz@open.ch>
Signed-off-by: Roman Hoog Antink <rha@open.ch>
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h

index afb37aeef6a8f6743234697358206cbf03a76da7..44377c36924a30931bda5919fb8a41a8295763df 100644 (file)
@@ -13995,7 +13995,7 @@ ALIAS (show_bgp_instance_neighbor_damp,
 
 #endif /* HAVE_IPV6 */
 
-struct bgp_table *bgp_distance_table;
+struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
 
 struct bgp_distance
 {
@@ -14023,12 +14023,17 @@ bgp_distance_set (struct vty *vty, const char *distance_str,
                   const char *ip_str, const char *access_list_str)
 {
   int ret;
-  struct prefix_ipv4 p;
+  afi_t afi;
+  safi_t safi;
+  struct prefix p;
   u_char distance;
   struct bgp_node *rn;
   struct bgp_distance *bdistance;
 
-  ret = str2prefix_ipv4 (ip_str, &p);
+  afi = bgp_node_afi (vty);
+  safi = bgp_node_safi (vty);
+
+  ret = str2prefix (ip_str, &p);
   if (ret == 0)
     {
       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
@@ -14038,7 +14043,7 @@ bgp_distance_set (struct vty *vty, const char *distance_str,
   distance = atoi (distance_str);
 
   /* Get BGP distance node. */
-  rn = bgp_node_get (bgp_distance_table, (struct prefix *) &p);
+  rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p);
   if (rn->info)
     {
       bdistance = rn->info;
@@ -14070,19 +14075,24 @@ bgp_distance_unset (struct vty *vty, const char *distance_str,
                     const char *ip_str, const char *access_list_str)
 {
   int ret;
+  afi_t afi;
+  safi_t safi;
+  struct prefix p;
   int distance;
-  struct prefix_ipv4 p;
   struct bgp_node *rn;
   struct bgp_distance *bdistance;
 
-  ret = str2prefix_ipv4 (ip_str, &p);
+  afi = bgp_node_afi (vty);
+  safi = bgp_node_safi (vty);
+
+  ret = str2prefix (ip_str, &p);
   if (ret == 0)
     {
       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
       return CMD_WARNING;
     }
 
-  rn = bgp_node_lookup (bgp_distance_table, (struct prefix *)&p);
+  rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p);
   if (! rn)
     {
       vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
@@ -14111,10 +14121,11 @@ bgp_distance_unset (struct vty *vty, const char *distance_str,
 
 /* Apply BGP information to distance method. */
 u_char
-bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
+bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi,
+                   safi_t safi, struct bgp *bgp)
 {
   struct bgp_node *rn;
-  struct prefix_ipv4 q;
+  struct prefix q;
   struct peer *peer;
   struct bgp_distance *bdistance;
   struct access_list *alist;
@@ -14123,21 +14134,11 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
   if (! bgp)
     return 0;
 
-  if (p->family != AF_INET)
-    return 0;
-
   peer = rinfo->peer;
 
-  if (peer->su.sa.sa_family != AF_INET)
-    return 0;
-
-  memset (&q, 0, sizeof (struct prefix_ipv4));
-  q.family = AF_INET;
-  q.prefix = peer->su.sin.sin_addr;
-  q.prefixlen = IPV4_MAX_BITLEN;
-
   /* Check source address. */
-  rn = bgp_node_match (bgp_distance_table, (struct prefix *) &q);
+  sockunion2hostprefix (&peer->su, &q);
+  rn = bgp_node_match (bgp_distance_table[afi][safi], &q);
   if (rn)
     {
       bdistance = rn->info;
@@ -14145,7 +14146,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
 
       if (bdistance->access_list)
        {
-         alist = access_list_lookup (AFI_IP, bdistance->access_list);
+         alist = access_list_lookup (afi, bdistance->access_list);
          if (alist && access_list_apply (alist, p) == FILTER_PERMIT)
            return bdistance->distance;
        }
@@ -14154,7 +14155,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
     }
 
   /* Backdoor check. */
-  rn = bgp_node_lookup (bgp->route[AFI_IP][SAFI_UNICAST], p);
+  rn = bgp_node_lookup (bgp->route[afi][safi], p);
   if (rn)
     {
       bgp_static = rn->info;
@@ -14162,8 +14163,8 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
 
       if (bgp_static->backdoor)
        {
-         if (bgp->distance_local)
-           return bgp->distance_local;
+         if (bgp->distance_local[afi][safi])
+           return bgp->distance_local[afi][safi];
          else
            return ZEBRA_IBGP_DISTANCE_DEFAULT;
        }
@@ -14171,14 +14172,14 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
 
   if (peer->sort == BGP_PEER_EBGP)
     {
-      if (bgp->distance_ebgp)
-       return bgp->distance_ebgp;
+      if (bgp->distance_ebgp[afi][safi])
+       return bgp->distance_ebgp[afi][safi];
       return ZEBRA_EBGP_DISTANCE_DEFAULT;
     }
   else
     {
-      if (bgp->distance_ibgp)
-       return bgp->distance_ibgp;
+      if (bgp->distance_ibgp[afi][safi])
+       return bgp->distance_ibgp[afi][safi];
       return ZEBRA_IBGP_DISTANCE_DEFAULT;
     }
 }
@@ -14193,12 +14194,16 @@ DEFUN (bgp_distance,
        "Distance for local routes\n")
 {
   struct bgp *bgp;
+  afi_t afi;
+  safi_t safi;
 
   bgp = vty->index;
+  afi = bgp_node_afi (vty);
+  safi = bgp_node_safi (vty);
 
-  bgp->distance_ebgp = atoi (argv[0]);
-  bgp->distance_ibgp = atoi (argv[1]);
-  bgp->distance_local = atoi (argv[2]);
+  bgp->distance_ebgp[afi][safi] = atoi (argv[0]);
+  bgp->distance_ibgp[afi][safi] = atoi (argv[1]);
+  bgp->distance_local[afi][safi] = atoi (argv[2]);
   return CMD_SUCCESS;
 }
 
@@ -14213,12 +14218,16 @@ DEFUN (no_bgp_distance,
        "Distance for local routes\n")
 {
   struct bgp *bgp;
+  afi_t afi;
+  safi_t safi;
 
   bgp = vty->index;
+  afi = bgp_node_afi (vty);
+  safi = bgp_node_safi (vty);
 
-  bgp->distance_ebgp= 0;
-  bgp->distance_ibgp = 0;
-  bgp->distance_local = 0;
+  bgp->distance_ebgp[afi][safi] = 0;
+  bgp->distance_ibgp[afi][safi] = 0;
+  bgp->distance_local[afi][safi] = 0;
   return CMD_SUCCESS;
 }
 
@@ -14277,6 +14286,54 @@ DEFUN (no_bgp_distance_source_access_list,
   return CMD_SUCCESS;
 }
 
+DEFUN (ipv6_bgp_distance_source,
+       ipv6_bgp_distance_source_cmd,
+       "distance <1-255> X:X::X:X/M",
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n")
+{
+  bgp_distance_set (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_bgp_distance_source,
+       no_ipv6_bgp_distance_source_cmd,
+       "no distance <1-255> X:X::X:X/M",
+       NO_STR
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n")
+{
+  bgp_distance_unset (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_bgp_distance_source_access_list,
+       ipv6_bgp_distance_source_access_list_cmd,
+       "distance <1-255> X:X::X:X/M WORD",
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  bgp_distance_set (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_bgp_distance_source_access_list,
+       no_ipv6_bgp_distance_source_access_list_cmd,
+       "no distance <1-255> X:X::X:X/M WORD",
+       NO_STR
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  bgp_distance_unset (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
 DEFUN (bgp_damp_set,
        bgp_damp_set_cmd,
        "bgp dampening <1-45> <1-20000> <1-20000> <1-255>",
@@ -14711,40 +14768,53 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp,
 }
 
 int
-bgp_config_write_distance (struct vty *vty, struct bgp *bgp)
+bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi,
+                          safi_t safi, int *write)
 {
   struct bgp_node *rn;
   struct bgp_distance *bdistance;
 
   /* Distance configuration. */
-  if (bgp->distance_ebgp
-      && bgp->distance_ibgp
-      && bgp->distance_local
-      && (bgp->distance_ebgp != ZEBRA_EBGP_DISTANCE_DEFAULT
-         || bgp->distance_ibgp != ZEBRA_IBGP_DISTANCE_DEFAULT
-         || bgp->distance_local != ZEBRA_IBGP_DISTANCE_DEFAULT))
-    vty_out (vty, " distance bgp %d %d %d%s",
-            bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local,
-            VTY_NEWLINE);
-  
-  for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn))
+  if (bgp->distance_ebgp[afi][safi]
+      && bgp->distance_ibgp[afi][safi]
+      && bgp->distance_local[afi][safi]
+      && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
+         || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
+         || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT))
+    {
+      bgp_config_write_family_header (vty, afi, safi, write);
+      vty_out (vty, "  distance bgp %d %d %d%s",
+              bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi],
+              bgp->distance_local[afi][safi], VTY_NEWLINE);
+    }
+
+  for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn;
+       rn = bgp_route_next (rn))
     if ((bdistance = rn->info) != NULL)
       {
-       vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance,
-                inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+       char buf[PREFIX_STRLEN];
+
+       bgp_config_write_family_header (vty, afi, safi, write);
+       vty_out (vty, "  distance %d %s %s%s", bdistance->distance,
+                prefix2str (&rn->p, buf, sizeof (buf)),
                 bdistance->access_list ? bdistance->access_list : "",
                 VTY_NEWLINE);
       }
 
-  return 0;
+  return *write;
 }
 
 /* Allocate routing table structure and install commands. */
 void
 bgp_route_init (void)
 {
+  afi_t afi;
+  safi_t safi;
+
   /* Init BGP distance table. */
-  bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST);
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      bgp_distance_table[afi][safi] = bgp_table_init (afi, safi);
 
   /* IPv4 BGP commands. */
   install_element (BGP_NODE, &bgp_table_map_cmd);
@@ -15178,6 +15248,34 @@ bgp_route_init (void)
   install_element (BGP_NODE, &no_bgp_distance_source_cmd);
   install_element (BGP_NODE, &bgp_distance_source_access_list_cmd);
   install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_distance_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_distance2_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_distance_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_distance2_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_distance_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_distance2_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV6M_NODE, &bgp_distance_cmd);
+  install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd);
+  install_element (BGP_IPV6M_NODE, &no_bgp_distance2_cmd);
+  install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
+  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
+  install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd);
+  install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd);
 
   install_element (BGP_NODE, &bgp_damp_set_cmd);
   install_element (BGP_NODE, &bgp_damp_set2_cmd);
@@ -15203,6 +15301,13 @@ bgp_route_init (void)
 void
 bgp_route_finish (void)
 {
-  bgp_table_unlock (bgp_distance_table);
-  bgp_distance_table = NULL;
+  afi_t afi;
+  safi_t safi;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+       bgp_table_unlock (bgp_distance_table[afi][safi]);
+       bgp_distance_table[afi][safi] = NULL;
+      }
 }
index 0dce5da5724a850d93ea1cef3d1a5e103160954a..bb06204689346731c1ca0241be10268ae9878ecc 100644 (file)
@@ -307,14 +307,14 @@ extern void bgp_add_eoiu_mark (struct bgp *);
 extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t,
                                        int *);
 extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
-extern int bgp_config_write_distance (struct vty *, struct bgp *);
+extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *);
 
 extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *,
                              afi_t, safi_t);
 extern void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *,
                              afi_t, safi_t);
 
-extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, struct bgp *);
+extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *);
 
 extern afi_t bgp_node_afi (struct vty *);
 extern safi_t bgp_node_safi (struct vty *);
index 11e888d7e9c54df3ee1562eaa10e63647ac46928..8ecd025397e8f3d59e03aaf2b1efb7478e49a9f3 100644 (file)
@@ -1367,8 +1367,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
           api.tag = tag;
         }
 
-      distance = bgp_distance_apply (p, info, bgp);
-
+      distance = bgp_distance_apply (p, info, afi, safi, bgp);
       if (distance)
        {
          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
@@ -1554,6 +1553,13 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
           api.tag = tag;
         }
 
+      distance = bgp_distance_apply (p, info, afi, safi, bgp);
+      if (distance)
+        {
+          SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+          api.distance = distance;
+        }
+
       if (p->family == AF_INET)
         {
           if (bgp_debug_zebra(p))
index 71c2c84e61bab553066cf0891b64e9e3cb0fb0c0..403468a6307412efac5de6876853bbd5d971591a 100644 (file)
@@ -7123,6 +7123,8 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
   struct peer_group *group;
   struct listnode *node, *nnode;
 
+  bgp_config_write_distance (vty, bgp, afi, safi, &write);
+
   bgp_config_write_network (vty, bgp, afi, safi, &write);
 
   bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
@@ -7371,9 +7373,6 @@ bgp_config_write (struct vty *vty)
            bgp_config_write_peer_global (vty, bgp, peer);
        }
 
-      /* Distance configuration. */
-      bgp_config_write_distance (vty, bgp);
-      
       /* listen range and limit for dynamic BGP neighbors */
       bgp_config_write_listen (vty, bgp);
 
index ee105201e88d46652e677a187883b650fbf25098..f6e85984943650f4f66107345ecbc7d31d8e7f31 100644 (file)
@@ -320,9 +320,9 @@ struct bgp
 #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5
 
   /* BGP distance configuration.  */
-  u_char distance_ebgp;
-  u_char distance_ibgp;
-  u_char distance_local;
+  u_char distance_ebgp[AFI_MAX][SAFI_MAX];
+  u_char distance_ibgp[AFI_MAX][SAFI_MAX];
+  u_char distance_local[AFI_MAX][SAFI_MAX];
   
   /* BGP default local-preference.  */
   u_int32_t default_local_pref;