]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Fix interface pattern behavior with free bind mq-bgp-multilisten
authorMaria Matejka <mq@ucw.cz>
Thu, 28 Aug 2025 18:18:46 +0000 (20:18 +0200)
committerMaria Matejka <mq@ucw.cz>
Thu, 13 Nov 2025 10:59:33 +0000 (11:59 +0100)
In case of free bind, it makes no sense to check for addresses
on the interfaces.

Also added quite some documentation on how this all behaves
in different combinations of options.

doc/bird.sgml
proto/bgp/bgp.c
proto/bgp/config.Y

index ca039ef87b315c7a165b3da2514083f5ce351435..8d4c8c00fc9a6f8301480eecea1f021a91ab3a40 100644 (file)
@@ -3083,8 +3083,10 @@ protocol bgp [<name>] {
 
        This option requires <cf/strict bind/ to be on and creates a separate
        listening socket for every single interface matching the pattern. If the
-       local address is set, it also requires this exact address to be set
-       on that interface to create a listening socket.
+        local address is set, it also requires this exact address to be set on
+        that interface to create a listening socket.
+
+       Also see <cf/strict bind/ and <cf/free bind/.
 
        <tag><label id="bgp-onlink">onlink <m/switch/</tag>
        For a direct neighbor, the BGP session starts immediately without
@@ -3141,19 +3143,33 @@ protocol bgp [<name>] {
 
        <tag><label id="bgp-strict-bind">strict bind <m/switch/</tag>
        Specify whether BGP listening socket should be bound to a specific local
-       address (the same as the <cf/source address/) and associated interface,
+       address (the same as the <cf/source address/) and associated interface
        or to all addresses. Binding to a specific address could be useful in
        cases like running multiple BIRD instances on a machine, each using its
-       IP address. Note that listening sockets bound to a specific address and
-       to all addresses collide, therefore either all BGP protocols (of the
-       same address family and using the same local port) should have set
-       <cf/strict bind/, or none of them. Default: disabled.
+       IP address.
+
+       Note that listening sockets bound to a specific address and
+       to all addresses collide. Also listening sockets bound
+       to a specific interface and to all interfaces may behave weirdly.
+       Therefore, all BGP protocols (of the same address family and using
+       the same local port) should have set <cf/strict bind/, or none of them,
+       and in the same way, all should have a <cf/interface/ or <cf/interface range/
+       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.
+       value of the <cf/free bind/ option.
+
+       If <cf/interface range/ is set together with a local address
+       and <cf/free bind/ as well, it creates a free-bind listening socket
+       for every interface regardless of the assigned address. This is
+       an experimental feature.
+
+       Default: disabled.
 
        <tag><label id="bgp-check-link">check link <m>switch</m></tag>
        BGP could use hardware link state into consideration.  If enabled,
index d623eb4a88cff533f70aee79b2f804428cc18dda..0a68acb97343735b4d3e799e51b3c05d06bc56ef 100644 (file)
@@ -2059,7 +2059,7 @@ bgp_if_reload(struct bgp_proto *p, struct iface_patt *patt)
     if (old == new)
       continue;
 
-    if (ipa_zero(p->cf->local_ip))
+    if (ipa_zero(p->cf->local_ip) || p->cf->free_bind)
       bgp_iface_update(p, old ? IF_CHANGE_DOWN : IF_CHANGE_UP, iface);
     else
       WALK_LIST(a, iface->addrs)
@@ -2347,8 +2347,14 @@ bgp_start(struct proto *P)
   init_list(&p->listen);
 
   /* Setup interface notification hooks */
-  P->if_notify = (cf->ipatt && ipa_zero(cf->local_ip)) ? bgp_if_notify : NULL;
-  P->ifa_notify = (cf->ipatt && !ipa_zero(cf->local_ip)) ? bgp_ifa_notify : NULL;
+  P->if_notify = NULL;
+  P->ifa_notify = NULL;
+  if (cf->ipatt) {
+    if (ipa_zero(cf->local_ip) || cf->free_bind)
+      P->if_notify = bgp_if_notify;
+    else
+      P->ifa_notify = bgp_ifa_notify;
+  }
 
   /* Initialize TCP-AO keys */
   init_list(&p->ao.keys);
index da28de59608c72dc3494b357ba9761f1d4371c40..4ffc49f6743df58888be811881c636df1a926c53 100644 (file)
@@ -168,7 +168,7 @@ bgp_proto:
      BGP_CFG->remote_range = n;
    }
  | bgp_proto INTERFACE text ';' { BGP_CFG->iface = if_get_by_name($3); }
- | bgp_proto INTERFACE RANGE iface_patt ';' { BGP_CFG->ipatt =  this_ipatt; }
+ | bgp_proto INTERFACE RANGE iface_patt_init iface_patt_list_nopx ';' { BGP_CFG->ipatt = this_ipatt; }
  | bgp_proto ONLINK bool ';' { BGP_CFG->onlink = $3; }
  | bgp_proto RR CLUSTER ID idval ';' { BGP_CFG->rr_cluster_id = $5; }
  | bgp_proto RR CLIENT bool ';' { BGP_CFG->rr_client = $4; }