Hi,

Thanks. A follow-up to update bgpd.texi would also be good!

--paul

On Fri, 11 Dec 2015, Donald Sharp wrote:

From: Daniel Walton <[email protected]>

Allow the replacement of a specific AS with another.

Signed-off-by: Daniel Walton <[email protected]>
---
bgpd/bgp_aspath.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgp_aspath.h |  2 ++
bgpd/bgp_route.c  | 15 +++++++++++++++
bgpd/bgp_vty.c    | 46 ++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgpd.c       | 11 +++++++++++
bgpd/bgpd.h       |  4 +++-
6 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 776f6e6..aace91b 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1167,6 +1167,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)
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 7280f31..134f1f6 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -98,6 +98,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);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f48cfed..ab81b72 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -915,6 +915,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)
@@ -1177,6 +1190,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)
@@ -1384,6 +1398,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) )
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index bdc149a..7bec815 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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)
    {
@@ -2636,6 +2639,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,
@@ -8256,6 +8285,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);
@@ -10331,6 +10363,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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index cc2abb5..78f9a2c 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2713,6 +2713,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 }
  };

@@ -2956,6 +2957,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])
@@ -5523,6 +5529,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])
    {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index ec73ae1..afe2b50 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -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;
@@ -907,7 +908,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;



--
Paul Jakma | [email protected] | @pjakma | Key ID: 0xD86BF79464A2FF6A
Fortune:
"He was a modest, good-humored boy.  It was Oxford that made him insufferable."

_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to