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>
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 63e326a..0746f0d 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -381,6 +381,7 @@
#define PEER_FLAG_DYNAMIC_CAPABILITY (1 << 5) /* dynamic capability */
#define PEER_FLAG_DISABLE_CONNECTED_CHECK (1 << 6) /* disable-connected-check */
#define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */
+#define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */
/* NSF mode (graceful restart) */
u_char nsf[AFI_MAX][SAFI_MAX];
@@ -814,6 +815,7 @@
#define BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK -30
#define BGP_ERR_NO_IBGP_WITH_TTLHACK -31
#define BGP_ERR_MAX -32
+#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS -33
extern struct bgp_master *bm;
@@ -941,7 +943,7 @@
extern int peer_allowas_in_set (struct peer *, afi_t, safi_t, int);
extern int peer_allowas_in_unset (struct peer *, afi_t, safi_t);
-extern int peer_local_as_set (struct peer *, as_t, int);
+extern int peer_local_as_set (struct peer *, as_t, int, int);
extern int peer_local_as_unset (struct peer *);
extern int peer_prefix_list_set (struct peer *, afi_t, safi_t, int, const char *);