]> git.puffer.fish Git - mirror/frr.git/commitdiff
Implement BGP as-override feature
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:03:14 +0000 (18:03 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 01:03:14 +0000 (18:03 -0700)
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index b8bd71b993b907be053654ab4ae6046689f3d83a..450f5f52739a9be0d60700f6a1ec16bd68b47afc 100644 (file)
@@ -1146,6 +1146,58 @@ aspath_private_as_check (struct aspath *aspath)
   return 1;
 }
 
+/* Return True if the entire ASPATH consist of the specified ASN */
+int
+aspath_single_asn_check (struct aspath *aspath, as_t asn)
+{
+  struct assegment *seg;
+
+  if ( !(aspath && aspath->segments) )
+    return 0;
+
+  seg = aspath->segments;
+
+  while (seg)
+    {
+      int i;
+
+      for (i = 0; i < seg->length; i++)
+       {
+         if (seg->as[i] != asn)
+           return 0;
+       }
+      seg = seg->next;
+    }
+  return 1;
+}
+
+/* Replace all instances of the target ASN with our own ASN */
+struct aspath *
+aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn,
+                             as_t our_asn)
+{
+  struct aspath *new;
+  struct assegment *seg;
+
+  new = aspath_dup(aspath);
+  seg = new->segments;
+
+  while (seg)
+    {
+      int i;
+
+      for (i = 0; i < seg->length; i++)
+       {
+         if (seg->as[i] == target_asn)
+            seg->as[i] = our_asn;
+       }
+      seg = seg->next;
+    }
+
+  aspath_str_update(new);
+  return new;
+}
+
 /* Replace all private ASNs with our own ASN */
 struct aspath *
 aspath_replace_private_asns (struct aspath *aspath, as_t asn)
index 23b5da5ab24d3f97708bb86e8f160b181e28b2d5..8846949cb0e91fd3847ee1933b79707842157040 100644 (file)
@@ -97,6 +97,8 @@ extern void aspath_print_all_vty (struct vty *);
 extern unsigned int aspath_key_make (void *);
 extern int aspath_loop_check (struct aspath *, as_t);
 extern int aspath_private_as_check (struct aspath *);
+extern int aspath_single_asn_check (struct aspath *, as_t asn);
+extern struct aspath *aspath_replace_specific_asn (struct aspath *aspath, as_t target_asn, as_t our_asn);
 extern struct aspath *aspath_replace_private_asns(struct aspath *aspath, as_t asn);
 extern struct aspath *aspath_remove_private_asns (struct aspath *aspath);
 extern int aspath_firstas_check (struct aspath *, as_t);
index cb46c1cbaef8692ca08fdb3fcb20cb845dccbf1e..0dd9248a60e94c11e764bd47fb1c9cc793ee24f6 100644 (file)
@@ -899,6 +899,19 @@ bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
     }
 }
 
+/* If this is an EBGP peer with as-override */
+static void
+bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
+                     struct peer *peer, struct attr *attr)
+{
+  if (peer->sort == BGP_PEER_EBGP &&
+      peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
+    {
+      if (aspath_single_asn_check (attr->aspath, peer->as))
+        attr->aspath = aspath_replace_specific_asn (attr->aspath, peer->as, bgp->as);
+    }
+}
+
 static int
 bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
                    struct attr *attr, afi_t afi, safi_t safi)
@@ -1161,6 +1174,7 @@ bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
 #endif /* HAVE_IPV6 */
 
   bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
+  bgp_peer_as_override(bgp, afi, safi, peer, attr);
 
   /* Route map & unsuppress-map apply. */
   if (ROUTE_MAP_OUT_NAME (filter)
@@ -1368,6 +1382,7 @@ bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
 #endif /* HAVE_IPV6 */
 
   bgp_peer_remove_private_as(bgp, afi, safi, rsclient, attr);
+  bgp_peer_as_override(bgp, afi, safi, rsclient, attr);
 
   /* Route map & unsuppress-map apply. */
   if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) )
index 8b9d3c39d49099e250c3a05d347feef5c445a275..92c402db547bbc5052aec413937a52be3162cd28 100644 (file)
@@ -232,6 +232,9 @@ bgp_vty_return (struct vty *vty, int ret)
     case BGP_ERR_NO_IBGP_WITH_TTLHACK:
       str = "ttl-security only allowed for EBGP peers";
       break;
+    case BGP_ERR_AS_OVERRIDE:
+      str = "as-override cannot be configured for IBGP peers";
+      break;
     }
   if (str)
     {
@@ -2657,6 +2660,32 @@ DEFUN (no_neighbor_nexthop_self,
                                 PEER_FLAG_NEXTHOP_SELF|PEER_FLAG_NEXTHOP_SELF_ALL);
 }
 
+/* neighbor as-override */
+DEFUN (neighbor_as_override,
+       neighbor_as_override_cmd,
+       NEIGHBOR_CMD2 "as-override",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+                               bgp_node_safi (vty),
+                               PEER_FLAG_AS_OVERRIDE);
+}
+
+DEFUN (no_neighbor_as_override,
+       no_neighbor_as_override_cmd,
+       NO_NEIGHBOR_CMD2 "as-override",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Override ASNs in outbound updates if aspath equals remote-as\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+                                 bgp_node_safi (vty),
+                                 PEER_FLAG_AS_OVERRIDE);
+}
+
 /* neighbor remove-private-AS. */
 DEFUN (neighbor_remove_private_as,
        neighbor_remove_private_as_cmd,
@@ -8364,6 +8393,9 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
   else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
     vty_out (vty, "  Private AS numbers removed in updates to this neighbor%s", VTY_NEWLINE);
 
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
+    vty_out (vty, "  Override ASNs in outbound updates if aspath equals remote-as%s", VTY_NEWLINE);
+
   if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF) ||
       CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF_ALL))
     vty_out (vty, "  NEXT_HOP is always this router%s", VTY_NEWLINE);
@@ -10432,6 +10464,20 @@ bgp_vty_init (void)
   install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd);
   install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd);
 
+  /* "neighbor as-override" commands. */
+  install_element (BGP_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_NODE, &no_neighbor_as_override_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_as_override_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_as_override_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_as_override_cmd);
+  install_element (BGP_IPV6M_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd);
+
   /* "neighbor remove-private-AS" commands. */
   install_element (BGP_NODE, &neighbor_remove_private_as_cmd);
   install_element (BGP_NODE, &no_neighbor_remove_private_as_cmd);
index f6d06c0e659ad39505bf6e329acc3e716cdb4770..7df12326a81fbd71116ef86e96ea1a8550dc8045 100644 (file)
@@ -2664,6 +2664,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] =
     { PEER_FLAG_ORF_PREFIX_RM,            1, peer_change_reset },
     { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED,  0, peer_change_reset_out },
     { PEER_FLAG_NEXTHOP_SELF_ALL,         1, peer_change_reset_out },
+    { PEER_FLAG_AS_OVERRIDE,              1, peer_change_reset_out },
     { 0, 0, 0 }
   };
 
@@ -2907,6 +2908,11 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
       && peer_sort (peer) == BGP_PEER_IBGP)
     return BGP_ERR_REMOVE_PRIVATE_AS;
 
+  /* as-override is not allowed for IBGP peers */
+  if (flag & PEER_FLAG_AS_OVERRIDE
+      && peer_sort (peer) == BGP_PEER_IBGP)
+    return BGP_ERR_AS_OVERRIDE;
+
   /* When unset the peer-group member's flag we have to check
      peer-group configuration.  */
   if (! set && peer->af_group[afi][safi])
@@ -5473,6 +5479,11 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
         vty_out (vty, " neighbor %s remove-private-AS%s", addr, VTY_NEWLINE);
     }
 
+  /* as-override */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE) &&
+      !peer->af_group[afi][safi])
+    vty_out (vty, " neighbor %s as-override%s", addr, VTY_NEWLINE);
+
   /* send-community print. */
   if (! peer->af_group[afi][safi])
     {
index 743b8d78e7d688af39484192c25220f2510c8d44..14852293dd9169c6e5f31d842c2fe6c9c417c4e8 100644 (file)
@@ -489,6 +489,7 @@ struct peer
 #define PEER_FLAG_NEXTHOP_SELF_ALL          (1 << 17) /* next-hop-self all */
 #define PEER_FLAG_REMOVE_PRIVATE_AS_ALL     (1 << 18) /* remove-private-as all */
 #define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1 << 19) /* remove-private-as replace-as */
+#define PEER_FLAG_AS_OVERRIDE               (1 << 20) /* as-override */
 
   /* MD5 password */
   char *password;
@@ -910,7 +911,8 @@ enum bgp_clear_type
 #define BGP_ERR_NO_IBGP_WITH_TTLHACK           -31
 #define BGP_ERR_NO_INTERFACE_CONFIG             -32
 #define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS    -33
-#define BGP_ERR_MAX                            -34
+#define BGP_ERR_AS_OVERRIDE                     -34
+#define BGP_ERR_MAX                            -35
 
 extern struct bgp_master *bm;