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
|
<cf/local 10.0.0.1; local as 65000;/ are valid). This parameter is
|
||||||
mandatory.
|
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
|
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
|
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
|
automatically switch to IBGP. Alternatively, it is possible to specify
|
||||||
specified. Like <cf/local/ parameter, this parameter may also be used
|
just <cf/internal/ or </cf/external/ instead of AS number, in that case
|
||||||
multiple times with different sub-options. This parameter is mandatory.
|
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>
|
<tag><label id="bgp-iface">interface <m/string/</tag>
|
||||||
Define interface we should use for link-local BGP IPv6 sessions.
|
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))
|
if (ipa_zero(p->local_ip))
|
||||||
p->local_ip = conn->sk->saddr;
|
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 */
|
/* 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)
|
if (ipa_zero(p->link_addr) && p->neigh && p->neigh->iface && p->neigh->iface->llv6)
|
||||||
p->link_addr = p->neigh->iface->llv6->ip;
|
p->link_addr = p->neigh->iface->llv6->ip;
|
||||||
|
@ -1754,14 +1758,19 @@ void
|
||||||
bgp_postconfig(struct proto_config *CF)
|
bgp_postconfig(struct proto_config *CF)
|
||||||
{
|
{
|
||||||
struct bgp_config *cf = (void *) 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 */
|
/* Do not check templates at all */
|
||||||
if (cf->c.class == SYM_TEMPLATE)
|
if (cf->c.class == SYM_TEMPLATE)
|
||||||
return;
|
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 */
|
/* EBGP direct by default, IBGP multihop by default */
|
||||||
if (cf->multihop < 0)
|
if (cf->multihop < 0)
|
||||||
cf->multihop = internal ? 64 : 0;
|
cf->multihop = internal ? 64 : 0;
|
||||||
|
@ -1781,8 +1790,14 @@ bgp_postconfig(struct proto_config *CF)
|
||||||
if (ipa_zero(cf->remote_ip))
|
if (ipa_zero(cf->remote_ip))
|
||||||
cf_error("Neighbor must be configured");
|
cf_error("Neighbor must be configured");
|
||||||
|
|
||||||
if (!cf->remote_as)
|
if (!cf->remote_as && !cf->peer_type)
|
||||||
cf_error("Remote AS number must be set");
|
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) ||
|
if (!cf->iface && (ipa_is_link_local(cf->local_ip) ||
|
||||||
ipa_is_link_local(cf->remote_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, " 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 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)
|
if (p->gr_active_num)
|
||||||
cli_msg(-1006, " Neighbor graceful restart active");
|
cli_msg(-1006, " Neighbor graceful restart active");
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct bgp_config {
|
||||||
struct iface *iface; /* Interface for link-local addresses */
|
struct iface *iface; /* Interface for link-local addresses */
|
||||||
u16 local_port; /* Local listening port */
|
u16 local_port; /* Local listening port */
|
||||||
u16 remote_port; /* Neighbor destination 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 multihop; /* Number of hops if multihop */
|
||||||
int strict_bind; /* Bind listening socket to local address */
|
int strict_bind; /* Bind listening socket to local address */
|
||||||
int ttl_security; /* Enable TTL security [RFC 5082] */
|
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 */
|
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_NO 0
|
||||||
#define NH_ALL 1
|
#define NH_ALL 1
|
||||||
#define NH_IBGP 2
|
#define NH_IBGP 2
|
||||||
|
@ -237,6 +241,7 @@ struct bgp_conn {
|
||||||
u8 state; /* State of connection state machine */
|
u8 state; /* State of connection state machine */
|
||||||
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
|
u8 as4_session; /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
|
||||||
u8 ext_messages; /* Session uses extended message length */
|
u8 ext_messages; /* Session uses extended message length */
|
||||||
|
u32 received_as; /* ASN received in OPEN message */
|
||||||
|
|
||||||
struct bgp_caps *local_caps;
|
struct bgp_caps *local_caps;
|
||||||
struct bgp_caps *remote_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,
|
SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
|
||||||
GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
|
GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
|
||||||
STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
|
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 <i> bgp_nh
|
||||||
%type <i32> bgp_afi
|
%type <i32> bgp_afi
|
||||||
|
@ -82,6 +82,8 @@ bgp_nbr_opts:
|
||||||
/* empty */
|
/* empty */
|
||||||
| bgp_nbr_opts PORT expr { BGP_CFG->remote_port = $3; if (($3<1) || ($3>65535)) cf_error("Invalid port number"); }
|
| 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 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:
|
bgp_cease_mask:
|
||||||
|
|
|
@ -732,13 +732,18 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
|
||||||
if ((as4 != asn) && (asn != AS_TRANS))
|
if ((as4 != asn) && (asn != AS_TRANS))
|
||||||
log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);
|
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; }
|
{ as4 = htonl(as4); bgp_error(conn, 2, 2, (byte *) &as4, 4); return; }
|
||||||
|
|
||||||
|
conn->received_as = as4;
|
||||||
}
|
}
|
||||||
else
|
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; }
|
{ bgp_error(conn, 2, 2, pkt+20, 2); return; }
|
||||||
|
|
||||||
|
conn->received_as = asn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the other connection */
|
/* Check the other connection */
|
||||||
|
|
Loading…
Reference in a new issue