summaryrefslogtreecommitdiff
path: root/bgpd/bgpd.c
diff options
context:
space:
mode:
authorAndrew Certain <certain@amazon.com>2012-11-07 23:50:07 +0000
committerDavid Lamparter <equinox@opensourcerouting.org>2012-11-30 21:10:00 +0100
commit9d3f9705d8b386ccf006c106967c700141e5d049 (patch)
tree9edfe2653741fa0f49ffef15bd66f5a522dcd025 /bgpd/bgpd.c
parent3b96b78136d04ddb7e39d86577cad75acb25237a (diff)
bgpd: add replace-as modifier for BGP neighbor
Added replace-as modifier for BGP neighbors when using local-as. If the replace-as modifier is specified, only the replacement AS as specified by the local-as modifier is prepended to the AS_PATH, not the process's AS. In bgp_attr.c, I decided that if (peer->change_local_as) { /* If replace-as is specified, we only use the change_local_as when advertising routes. */ if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) { aspath = aspath_add_seq (aspath, peer->local_as); } aspath = aspath_add_seq (aspath, peer->change_local_as); } else { aspath = aspath_add_seq (aspath, peer->local_as); } was clearer than the alternative that didn't duplicate the prepending of the process's AS: /* First, append the process local AS unless we have an alternate local_as * and we're replacing it (as opposed to just prepending it). */ if (! (peer->change_local_as && CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) ) { aspath = aspath_add_seq (aspath, peer->local_as); } if (peer->change_local_as) aspath = aspath_add_seq (aspath, peer->change_local_as); } But I could be convinced otherwise. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'bgpd/bgpd.c')
-rw-r--r--bgpd/bgpd.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 69c8c0a3..908bdd94 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -962,6 +962,7 @@ peer_as_change (struct peer *peer, as_t as)
{
peer->change_local_as = 0;
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
}
}
@@ -1830,6 +1831,7 @@ peer_group_bind (struct bgp *bgp, union sockunion *su,
{
group->conf->change_local_as = 0;
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
}
}
@@ -3405,7 +3407,7 @@ peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
}
int
-peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
+peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
{
struct bgp *bgp = peer->bgp;
struct peer_group *group;
@@ -3421,9 +3423,14 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
if (peer_group_active (peer))
return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+ if (peer->as == as)
+ return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
+
if (peer->change_local_as == as &&
((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
- || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
+ || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
+ ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
+ || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
return 0;
peer->change_local_as = as;
@@ -3432,6 +3439,11 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
else
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ if (replace_as)
+ SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ else
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
if (peer->status == Established)
@@ -3455,6 +3467,11 @@ peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
else
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ if (replace_as)
+ SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+ else
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
+
if (peer->status == Established)
{
peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
@@ -3482,6 +3499,7 @@ peer_local_as_unset (struct peer *peer)
peer->change_local_as = 0;
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
@@ -3502,6 +3520,7 @@ peer_local_as_unset (struct peer *peer)
{
peer->change_local_as = 0;
UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+ UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
if (peer->status == Established)
{
@@ -4770,10 +4789,12 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
/* local-as. */
if (peer->change_local_as)
if (! peer_group_active (peer))
- vty_out (vty, " neighbor %s local-as %u%s%s", addr,
+ vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
peer->change_local_as,
CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
- " no-prepend" : "", VTY_NEWLINE);
+ " no-prepend" : "",
+ CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
+ " replace-as" : "", VTY_NEWLINE);
/* Description. */
if (peer->desc)