]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '39258b502' into 299-mq-bgp-async-listen
authorMaria Matejka <mq@ucw.cz>
Thu, 13 Nov 2025 15:50:00 +0000 (16:50 +0100)
committerMaria Matejka <mq@ucw.cz>
Thu, 13 Nov 2025 15:50:00 +0000 (16:50 +0100)
1  2 
doc/bird.sgml
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y

diff --cc doc/bird.sgml
Simple merge
diff --cc proto/bgp/bgp.c
index 1711c411cc58ca5f05660ca169337486eb810bbf,ee043036c942b0a07f741cbd38d9831bea4695ad..0147b6f3d78e85533222b3773f8fa107f455ef92
@@@ -196,39 -159,22 +196,44 @@@ static void bgp_restart_route_refresh(v
  static int
  bgp_open(struct bgp_proto *p)
  {
 -  /* We assume that cf->iface is defined iff cf->local_ip is link-local */
+   /* Interface-patterned listening sockets are created from the
+    * interface notifier. By default, listen to nothing. */
+   if (p->cf->ipatt)
+     return 0;
 +  /* Set parameters of the listening socket
 +   *
 +   * If strict_bind is set, we need local_ip and maybe also iface. Mandatory if
 +   * local_ip is link-local. If strict_bind is not set, we bind to all addresses
 +   * of that family and match the local IP later when accepting the connection. */
 +
    struct bgp_listen_request *req = mb_allocz(p->p.pool, sizeof *req);
 -  req->params = (struct bgp_socket_params) {
 -    .iface = p->cf->strict_bind ? p->cf->iface : NULL,
 -    .vrf = p->p.vrf,
 -    .addr = p->cf->strict_bind ? p->cf->local_ip :
 -      (p->ipv4 ? IPA_NONE4 : IPA_NONE6),
 -    .port = p->cf->local_port,
 -    .flags = p->cf->free_bind ? SKF_FREEBIND : 0,
 -  };
 +  struct bgp_socket_params *par = &req->params;
 +
 +  par->iface = p->cf->strict_bind ? p->cf->iface : NULL;
 +  par->vrf = p->p.vrf;
 +  par->addr = p->cf->strict_bind ? p->cf->local_ip :
 +    (p->ipv4 ? IPA_NONE4 : IPA_NONE6);
 +  par->port = p->cf->local_port;
 +  par->flags = p->cf->free_bind ? SKF_FREEBIND : 0;
 +
 +  /* Set parameters of the accepted socket */
 +  req->local_ip = p->cf->local_ip;
 +  req->iface = p->cf->iface;
 +  req->remote_ip = p->remote_ip;
 +  req->remote_range = p->cf->remote_range;
 +
 +  /* Initialize the incoming socket queue */
 +  init_list(&req->incoming_sockets);
 +
 +  BGP_TRACE(D_EVENTS, "Requesting listen socket at %I%J port %u", req->params.addr, req->params.iface, req->params.port);
 +
 +  if (bgp_is_dynamic(p))
 +    callback_init(&req->incoming_connection, bgp_incoming_connection_dynamic, &main_birdloop);
 +  else
 +    callback_init(&req->incoming_connection, bgp_incoming_connection_single, p->p.loop);
  
 +  req->p = p;
    return bgp_listen_open(p, req);
  }
  
@@@ -316,30 -234,24 +321,32 @@@ bgp_listen_open(struct bgp_proto *p, st
    sk->data = bs;
    req->sock = bs;
  
 -  init_list(&bs->requests);
 -  add_tail(&bs->requests, &req->sn);
 +  init_list(&bsp->requests);
 +  add_tail(&bsp->requests, &req->sn);
 +  add_tail(&bl->sockets, &bs->n);
  
 -  add_tail(&p->listen, &req->pn);
 -  add_tail(&bgp_sockets, &bs->n);
 +  bgp_listen_debug(p, &req->params, "create: %p", bs);
 +  birdloop_leave(loop);
  
+   bgp_listen_debug(p, &req->params, "create: %p", bs);
    return 0;
 +}
  
 -err:
 -  sk_log_error(sk, p->p.name);
 -  log(L_ERR "%s: Cannot open listening socket", p->p.name);
 -  rfree(sk);
 -  return -1;
 +static void
 +bgp_listen_done(void *_bs)
 +{
 +  /* Loop finishing must be done from the main loop */
 +  ASSERT_DIE(birdloop_inside(&main_birdloop));
 +  BGP_LISTEN_LOCK(bl);
 +
 +  /* The loop finisher must at least once enter the loop to ensure
 +   * that the requestor is done */
 +  BGP_SOCKET_LOCKED((bgp_socket *) _bs, bsp)
 +    ;
 +
 +  /* Everything related is allocated from the loop's pool */
 +  birdloop_free(((bgp_socket *) _bs)->loop);
  }
  
  static void
@@@ -1166,16 -1036,15 +1173,18 @@@ bgp_spawn(struct bgp_proto *pp, struct 
    cfg_mem = NULL;
  
    /* Just pass remote_ip to bgp_init() */
-   ((struct bgp_config *) sym->proto)->remote_ip = sk->daddr;
+   struct bgp_config *cf = SKIP_BACK(struct bgp_config, c, sym->proto);
+   cf->remote_ip = sk->daddr;
+   cf->iface = sk->iface;
  
 -  struct bgp_proto *p = SKIP_BACK(struct bgp_proto, p, proto_spawn(sym->proto, 0));
 +  /* Create the protocol disabled initially */
 +  SKIP_BACK_DECLARE(struct bgp_proto, p, p, proto_spawn(sym->proto, 1));
 +
 +  /* Pass the socket */
    p->postponed_sk = sk;
 -  rmove(sk, p->p.pool);
  
 -  return 0;
 +  /* And enable the protocol */
 +  proto_enable(&p->p);
  }
  
  void
@@@ -2173,6 -1892,66 +2182,66 @@@ bgp_start_neighbor(struct bgp_proto *p
    bgp_initiate(p);
  }
  
 -  if ((ps == PS_DOWN) || (ps == PS_STOP))
+ static void
+ bgp_iface_update(struct bgp_proto *p, uint flags, struct iface *i)
+ {
+   int ps = p->p.proto_state;
+   ASSERT_DIE(p->cf->ipatt);
+   ASSERT_DIE(p->cf->strict_bind);
++  if ((ps == PS_DOWN_XX) || (ps == PS_FLUSH) || (ps == PS_STOP))
+     return;
+   if (!iface_patt_match(p->cf->ipatt, i, NULL))
+     return;
+   struct bgp_socket_params params = {
+     .iface = i,
+     .vrf = p->p.vrf,
+     .addr = p->cf->local_ip,
+     .port = p->cf->local_port,
+     .flags = p->cf->free_bind ? SKF_FREEBIND : 0,
+   };
+   if (flags & IF_CHANGE_UP)
+   {
+     struct bgp_listen_request *req = mb_allocz(p->p.pool, sizeof *req);
+     req->params = params;
+     bgp_listen_open(p, req);
+   }
+   if (flags & IF_CHANGE_DOWN)
+   {
+     struct bgp_listen_request *req; node *nxt;
+     WALK_LIST2(req, nxt, p->listen, pn)
+       if (bgp_socket_match(&req->params, &params))
+       {
+       bgp_listen_close(p, req);
+       mb_free(req);
+       break;
+       }
+   }
+ }
+ static void
+ bgp_if_notify(struct proto *P, uint flags, struct iface *i)
+ {
+   struct bgp_proto *p = (struct bgp_proto *) P;
+   ASSERT_DIE(ipa_zero(p->cf->local_ip));
+   bgp_iface_update(p, flags, i);
+ }
+ static void
+ bgp_ifa_notify(struct proto *P, uint flags, struct ifa *i)
+ {
+   struct bgp_proto *p = (struct bgp_proto *) P;
+   ASSERT_DIE(!ipa_zero(p->cf->local_ip));
+   if (ipa_equal(i->ip, p->cf->local_ip))
+     bgp_iface_update(p, flags, i->iface);
+ }
  static void
  bgp_neigh_notify(neighbor *n)
  {
@@@ -2742,8 -2388,9 +2811,11 @@@ bgp_init(struct proto_config *CF
    p->remote_ip = cf->remote_ip;
    p->remote_as = cf->remote_as;
  
 -  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->postponed_sk = NULL;
 +
++  P->iface_sub.if_notify = (cf->ipatt && ipa_zero(cf->local_ip)) ? bgp_if_notify : NULL;
++  P->iface_sub.ifa_notify = (cf->ipatt && !ipa_zero(cf->local_ip)) ? bgp_ifa_notify : NULL;
    /* Hack: We use cf->remote_ip just to pass remote_ip from bgp_spawn() */
    if (cf->c.parent)
      cf->remote_ip = IPA_NONE;
diff --cc proto/bgp/bgp.h
Simple merge
Simple merge