BGP: Add option 'free bind'

The BGP 'free bind' option applies the IP_FREEBIND/IPV6_FREEBIND
socket option for the BGP listening socket.

Thanks to Alexander Zubkov for the idea.
This commit is contained in:
Ondrej Zajicek (work) 2022-01-09 02:40:58 +01:00
parent 87a02489f3
commit 60e9def9ef
4 changed files with 17 additions and 4 deletions

View file

@ -2412,6 +2412,12 @@ using the following configuration parameters:
same address family and using the same local port) should have set same address family and using the same local port) should have set
<cf/strict bind/, or none of them. Default: disabled. <cf/strict bind/, or none of them. Default: disabled.
<tag><label id="bgp-free-bind">free bind <m/switch/</tag>
Use IP_FREEBIND socket option for the listening socket, which allows
binding to an IP address not (yet) assigned to an interface. Note that
all BGP instances that share a listening socket should have the same
value of the <cf/freebind/ option. Default: disabled.
<tag><label id="bgp-check-link">check link <M>switch</M></tag> <tag><label id="bgp-check-link">check link <M>switch</M></tag>
BGP could use hardware link state into consideration. If enabled, BGP could use hardware link state into consideration. If enabled,
BIRD tracks the link state of the associated interface and when link BIRD tracks the link state of the associated interface and when link

View file

@ -157,6 +157,8 @@ bgp_open(struct bgp_proto *p)
ip_addr addr = p->cf->strict_bind ? p->cf->local_ip : ip_addr addr = p->cf->strict_bind ? p->cf->local_ip :
(p->ipv4 ? IPA_NONE4 : IPA_NONE6); (p->ipv4 ? IPA_NONE4 : IPA_NONE6);
uint port = p->cf->local_port; uint port = p->cf->local_port;
uint flags = p->cf->free_bind ? SKF_FREEBIND : 0;
uint flag_mask = SKF_FREEBIND;
/* FIXME: Add some global init? */ /* FIXME: Add some global init? */
if (!bgp_linpool) if (!bgp_linpool)
@ -165,8 +167,11 @@ bgp_open(struct bgp_proto *p)
/* We assume that cf->iface is defined iff cf->local_ip is link-local */ /* We assume that cf->iface is defined iff cf->local_ip is link-local */
WALK_LIST(bs, bgp_sockets) WALK_LIST(bs, bgp_sockets)
if (ipa_equal(bs->sk->saddr, addr) && (bs->sk->sport == port) && if (ipa_equal(bs->sk->saddr, addr) &&
(bs->sk->iface == ifa) && (bs->sk->vrf == p->p.vrf)) (bs->sk->sport == port) &&
(bs->sk->iface == ifa) &&
(bs->sk->vrf == p->p.vrf) &&
((bs->sk->flags & flag_mask) == flags))
{ {
bs->uc++; bs->uc++;
p->sock = bs; p->sock = bs;
@ -180,7 +185,7 @@ bgp_open(struct bgp_proto *p)
sk->sport = port; sk->sport = port;
sk->iface = ifa; sk->iface = ifa;
sk->vrf = p->p.vrf; sk->vrf = p->p.vrf;
sk->flags = 0; sk->flags = flags;
sk->tos = IP_PREC_INTERNET_CONTROL; sk->tos = IP_PREC_INTERNET_CONTROL;
sk->rbsize = BGP_RX_BUFFER_SIZE; sk->rbsize = BGP_RX_BUFFER_SIZE;
sk->tbsize = BGP_TX_BUFFER_SIZE; sk->tbsize = BGP_TX_BUFFER_SIZE;

View file

@ -86,6 +86,7 @@ struct bgp_config {
int peer_type; /* Internal or external BGP (BGP_PT_*, optional) */ 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 free_bind; /* Bind listening socket with SKF_FREEBIND */
int ttl_security; /* Enable TTL security [RFC 5082] */ int ttl_security; /* Enable TTL security [RFC 5082] */
int compare_path_lengths; /* Use path lengths when selecting best route */ int compare_path_lengths; /* Use path lengths when selecting best route */
int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */

View file

@ -31,7 +31,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG, STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL, SETS, LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL, SETS,
DYNAMIC, RANGE, NAME, DIGITS, BGP_AIGP, AIGP, ORIGINATE, COST, ENFORCE, DYNAMIC, RANGE, NAME, DIGITS, BGP_AIGP, AIGP, ORIGINATE, COST, ENFORCE,
FIRST) FIRST, FREE)
%type <i> bgp_nh %type <i> bgp_nh
%type <i32> bgp_afi %type <i32> bgp_afi
@ -155,6 +155,7 @@ bgp_proto:
} }
| bgp_proto DYNAMIC NAME DIGITS expr ';' { BGP_CFG->dynamic_name_digits = $5; if ($5>10) cf_error("Dynamic name digits must be at most 10"); } | bgp_proto DYNAMIC NAME DIGITS expr ';' { BGP_CFG->dynamic_name_digits = $5; if ($5>10) cf_error("Dynamic name digits must be at most 10"); }
| bgp_proto STRICT BIND bool ';' { BGP_CFG->strict_bind = $4; } | bgp_proto STRICT BIND bool ';' { BGP_CFG->strict_bind = $4; }
| bgp_proto FREE BIND bool ';' { BGP_CFG->free_bind = $4; }
| bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; } | bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
| bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; } | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; }
| bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; } | bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; }