BGP: Promiscuous ASN mode
Allow to specify just 'internal' or 'external' for remote neighbor instead of specific ASN. In the second case that means BGP peers with any non-local ASNs are accepted.
This commit is contained in:
parent
a22c3e5968
commit
23ee6b1cd6
5 changed files with 42 additions and 12 deletions
|
@ -2195,12 +2195,15 @@ using the following configuration parameters:
|
|||
<cf/local 10.0.0.1; local as 65000;/ are valid). This parameter is
|
||||
mandatory.
|
||||
|
||||
<tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/]</tag>
|
||||
<tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/] [internal|external]</tag>
|
||||
Define neighboring router this instance will be talking to and what AS
|
||||
it is located in. In case the neighbor is in the same AS as we are, we
|
||||
automatically switch to iBGP. Optionally, the remote port may also be
|
||||
specified. Like <cf/local/ parameter, this parameter may also be used
|
||||
multiple times with different sub-options. This parameter is mandatory.
|
||||
automatically switch to IBGP. Alternatively, it is possible to specify
|
||||
just <cf/internal/ or </cf/external/ instead of AS number, in that case
|
||||
either local AS number, or any external AS number is accepted.
|
||||
Optionally, the remote port may also be specified. Like <cf/local/
|
||||
parameter, this parameter may also be used multiple times with different
|
||||
sub-options. This parameter is mandatory.
|
||||
|
||||
<tag><label id="bgp-iface">interface <m/string/</tag>
|
||||
Define interface we should use for link-local BGP IPv6 sessions.
|
||||
|
|
|
@ -507,6 +507,10 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
|
|||
if (ipa_zero(p->local_ip))
|
||||
p->local_ip = conn->sk->saddr;
|
||||
|
||||
/* For promiscuous sessions */
|
||||
if (!p->remote_as)
|
||||
p->remote_as = conn->received_as;
|
||||
|
||||
/* In case of LLv6 is not valid during BGP start */
|
||||
if (ipa_zero(p->link_addr) && p->neigh && p->neigh->iface && p->neigh->iface->llv6)
|
||||
p->link_addr = p->neigh->iface->llv6->ip;
|
||||
|
@ -1754,14 +1758,19 @@ void
|
|||
bgp_postconfig(struct proto_config *CF)
|
||||
{
|
||||
struct bgp_config *cf = (void *) CF;
|
||||
int internal = (cf->local_as == cf->remote_as);
|
||||
int interior = internal || cf->confederation_member;
|
||||
|
||||
/* Do not check templates at all */
|
||||
if (cf->c.class == SYM_TEMPLATE)
|
||||
return;
|
||||
|
||||
|
||||
/* Handle undefined remote_as, zero should mean unspecified external */
|
||||
if (!cf->remote_as && (cf->peer_type == BGP_PT_INTERNAL))
|
||||
cf->remote_as = cf->local_as;
|
||||
|
||||
int internal = (cf->local_as == cf->remote_as);
|
||||
int interior = internal || cf->confederation_member;
|
||||
|
||||
/* EBGP direct by default, IBGP multihop by default */
|
||||
if (cf->multihop < 0)
|
||||
cf->multihop = internal ? 64 : 0;
|
||||
|
@ -1781,8 +1790,14 @@ bgp_postconfig(struct proto_config *CF)
|
|||
if (ipa_zero(cf->remote_ip))
|
||||
cf_error("Neighbor must be configured");
|
||||
|
||||
if (!cf->remote_as)
|
||||
cf_error("Remote AS number must be set");
|
||||
if (!cf->remote_as && !cf->peer_type)
|
||||
cf_error("Remote AS number (or peer type) must be set");
|
||||
|
||||
if ((cf->peer_type == BGP_PT_INTERNAL) && !internal)
|
||||
cf_error("IBGP cannot have different ASNs");
|
||||
|
||||
if ((cf->peer_type == BGP_PT_EXTERNAL) && internal)
|
||||
cf_error("EBGP cannot have the same ASNs");
|
||||
|
||||
if (!cf->iface && (ipa_is_link_local(cf->local_ip) ||
|
||||
ipa_is_link_local(cf->remote_ip)))
|
||||
|
@ -2242,7 +2257,7 @@ bgp_show_proto_info(struct proto *P)
|
|||
|
||||
cli_msg(-1006, " BGP state: %s", bgp_state_dsc(p));
|
||||
cli_msg(-1006, " Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
|
||||
cli_msg(-1006, " Neighbor AS: %u", p->cf->remote_as);
|
||||
cli_msg(-1006, " Neighbor AS: %u", p->cf->remote_as ?: p->remote_as);
|
||||
|
||||
if (p->gr_active_num)
|
||||
cli_msg(-1006, " Neighbor graceful restart active");
|
||||
|
|
|
@ -83,6 +83,7 @@ struct bgp_config {
|
|||
struct iface *iface; /* Interface for link-local addresses */
|
||||
u16 local_port; /* Local listening port */
|
||||
u16 remote_port; /* Neighbor destination port */
|
||||
int peer_type; /* Internal or external BGP (BGP_PT_*, optional) */
|
||||
int multihop; /* Number of hops if multihop */
|
||||
int strict_bind; /* Bind listening socket to local address */
|
||||
int ttl_security; /* Enable TTL security [RFC 5082] */
|
||||
|
@ -152,6 +153,9 @@ struct bgp_channel_config {
|
|||
struct rtable_config *igp_table_ip6; /* Table for recursive IPv6 next hop lookups */
|
||||
};
|
||||
|
||||
#define BGP_PT_INTERNAL 1
|
||||
#define BGP_PT_EXTERNAL 2
|
||||
|
||||
#define NH_NO 0
|
||||
#define NH_ALL 1
|
||||
#define NH_IBGP 2
|
||||
|
@ -237,6 +241,7 @@ struct bgp_conn {
|
|||
u8 state; /* State of connection state machine */
|
||||
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
|
||||
u8 ext_messages; /* Session uses extended message length */
|
||||
u32 received_as; /* ASN received in OPEN message */
|
||||
|
||||
struct bgp_caps *local_caps;
|
||||
struct bgp_caps *remote_caps;
|
||||
|
|
|
@ -29,7 +29,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
|
|||
SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
|
||||
GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
|
||||
STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
|
||||
LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY)
|
||||
LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL)
|
||||
|
||||
%type <i> bgp_nh
|
||||
%type <i32> bgp_afi
|
||||
|
@ -82,6 +82,8 @@ bgp_nbr_opts:
|
|||
/* empty */
|
||||
| bgp_nbr_opts PORT expr { BGP_CFG->remote_port = $3; if (($3<1) || ($3>65535)) cf_error("Invalid port number"); }
|
||||
| bgp_nbr_opts AS expr { BGP_CFG->remote_as = $3; }
|
||||
| bgp_nbr_opts INTERNAL { BGP_CFG->peer_type = BGP_PT_INTERNAL; }
|
||||
| bgp_nbr_opts EXTERNAL { BGP_CFG->peer_type = BGP_PT_EXTERNAL; }
|
||||
;
|
||||
|
||||
bgp_cease_mask:
|
||||
|
|
|
@ -732,13 +732,18 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
|
|||
if ((as4 != asn) && (asn != AS_TRANS))
|
||||
log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);
|
||||
|
||||
if (as4 != p->remote_as)
|
||||
/* When remote ASN is unspecified, it must be external one */
|
||||
if (p->remote_as ? (as4 != p->remote_as) : (as4 == p->local_as))
|
||||
{ as4 = htonl(as4); bgp_error(conn, 2, 2, (byte *) &as4, 4); return; }
|
||||
|
||||
conn->received_as = as4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (asn != p->remote_as)
|
||||
if (p->remote_as ? (asn != p->remote_as) : (asn == p->local_as))
|
||||
{ bgp_error(conn, 2, 2, pkt+20, 2); return; }
|
||||
|
||||
conn->received_as = asn;
|
||||
}
|
||||
|
||||
/* Check the other connection */
|
||||
|
|
Loading…
Reference in a new issue