]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '0bb04d5390f21b0c96fc4894ba5d5510c541f0ef' into HEAD
authorMaria Matejka <mq@ucw.cz>
Tue, 7 Feb 2023 13:27:23 +0000 (14:27 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 7 Feb 2023 13:27:23 +0000 (14:27 +0100)
15 files changed:
1  2 
lib/lists.c
nest/iface.c
nest/proto.c
nest/protocol.h
nest/rt-dev.c
proto/babel/babel.c
proto/bfd/bfd.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/ospf/ospf.c
proto/perf/perf.c
proto/radv/radv.c
proto/rip/rip.c
proto/static/static.c
sysdep/unix/krt.c

diff --cc lib/lists.c
Simple merge
diff --cc nest/iface.c
index fc896e2667c164240c30c8bb696f911be0d0520e,740c18789a40c516f0ca3f6785ca8d65a37e4452..c49ad95e6abfe6f0de4fb4fb56e0d3c69ffd7349
@@@ -140,7 -143,43 +143,45 @@@ if_copy(struct iface *to, struct iface 
    to->flags = from->flags | (to->flags & IF_TMP_DOWN);
    to->mtu = from->mtu;
    to->master_index = from->master_index;
-   to->master = from->master;
+   if_unlink(to->master);
+   if_link(to->master = from->master);
+ }
+ void
+ if_enqueue_notify_to(struct iface_notification x, struct iface_subscription *s)
+ {
+   switch (x.type) {
+     case IFNOT_ADDRESS:
+       if (!s->ifa_notify) return;
+       ifa_link(x.a);
+       break;
+     case IFNOT_INTERFACE:
+       if (!s->if_notify) return;
+       if_link(x.i);
+       break;
+     case IFNOT_NEIGHBOR:
+       if (!s->neigh_notify) return;
+       neigh_link(x.n);
+       break;
+     default:
+       bug("Unknown interface notification type: %d", x.type);
+   }
+   struct iface_notification *in = sl_alloc(iface_sub_slab);
+   *in = x;
++  debug("Enqueue notify %d/%p (%p) to %p\n", x.type, x.a, in, s);
++
+   ifnot_add_tail(&s->queue, in);
+   ev_schedule(&s->event);
+ }
+ void
+ if_enqueue_notify(struct iface_notification x)
+ {
+   WALK_TLIST(ifsub, s, &iface_sub_list)
+     if_enqueue_notify_to(x, s);
  }
  
  static inline void
@@@ -387,17 -436,54 +438,55 @@@ if_end_update(void
  }
  
  void
- if_flush_ifaces(struct proto *p)
+ if_link(struct iface *i)
+ {
+   if (i)
+     i->uc++;
+ }
+ void
+ if_unlink(struct iface *i)
+ {
+   if (i)
+     i->uc--;
+   /* TODO: Do some interface object cleanup */
+ }
+ static void
+ iface_notify_hook(void *_s)
  {
-   if (p->debug & D_EVENTS)
-     log(L_TRACE "%s: Flushing interfaces", p->name);
-   if_start_update();
-   if_end_update();
+   struct iface_subscription *s = _s;
+   while (!EMPTY_TLIST(ifnot, &s->queue))
+   {
+     struct iface_notification *n = THEAD(ifnot, &s->queue);
++    debug("Process notify %d/%p (%p) to %p\n", n->type, n->a, n, s);
+     switch (n->type) {
+       case IFNOT_ADDRESS:
+       ifa_send_notify(s, n->flags, n->a);
+       ifa_unlink(n->a);
+       break;
+       case IFNOT_INTERFACE:
+       if_send_notify(s, n->flags, n->i);
+       if_unlink(n->i);
+       break;
+       case IFNOT_NEIGHBOR:
+       s->neigh_notify(n->n);
+       neigh_unlink(n->n);
+       break;
+       default:
+       bug("Bad interface notification type: %d", n->type);
+     }
+     ifnot_rem_node(&s->queue, n);
+     sl_free(n);
+   }
  }
  
  /**
-  * if_feed_baby - advertise interfaces to a new protocol
-  * @p: protocol to feed
+  * iface_subscribe - request interface updates
+  * @s: subscription structure
   *
   * When a new protocol starts, this function sends it a series
   * of notifications about all existing interfaces.
@@@ -413,11 -504,45 +507,46 @@@ iface_subscribe(struct iface_subscripti
    DBG("Announcing interfaces to new protocol %s\n", p->name);
    WALK_LIST(i, iface_list)
      {
-       if_send_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
+       if_send_notify(s, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
+       struct ifa *a;
        if (i->flags & IF_UP)
        WALK_LIST(a, i->addrs)
-         ifa_send_notify(p, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
+         ifa_send_notify(s, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
+     }
+ }
+ /**
+  * iface_unsubscribe - unsubscribe from interface updates
+  * @s: subscription structure
+  */
+ void
+ iface_unsubscribe(struct iface_subscription *s)
+ {
+   ifsub_rem_node(&iface_sub_list, s);
+   ev_postpone(&s->event);
+   WALK_TLIST_DELSAFE(ifnot, n, &s->queue)
+   {
++    debug("Drop notify %d/%p (%p) to %p\n", n->type, n->a, n, s);
+     switch (n->type)
+     {
+       case IFNOT_ADDRESS:
+       ifa_unlink(n->a);
+       break;
+       case IFNOT_INTERFACE:
+       if_unlink(n->i);
+       break;
+       case IFNOT_NEIGHBOR:
+       neigh_unlink(n->n);
+       break;
+       default:
+       bug("Bad interface notification type: %d", n->type);
      }
+     ifnot_rem_node(&s->queue, n);
+     sl_free(n);
+   }
  }
  
  /**
@@@ -660,6 -787,24 +791,31 @@@ ifa_delete(struct ifa *a
        }
  }
  
+ void ifa_link(struct ifa *a)
+ {
+   if (a)
++  {
++    debug("ifa_link: %p %d\n", a, a->uc);
+     a->uc++;
++  }
+ }
+ void ifa_unlink(struct ifa *a)
+ {
+   if (!a)
+     return;
++  debug("ifa_unlink: %p %d\n", a, a->uc);
+   if (--a->uc)
+     return;
+   if_unlink(a->iface);
++#if DEBUGGING
++  memset(a, 0x5b, sizeof(struct ifa));
++#endif
+   mb_free(a);
+ }
  u32
  if_choose_router_id(struct iface_patt *mask, u32 old_id)
  {
diff --cc nest/proto.c
index bec3056063c34722e9cd7b0019ce71c2d1dfe4cf,39e8b9997d8dbd33d71985a4609b2fea28f14131..6e4b7d290fbffce4b1662e0c76ce5d82658794c2
@@@ -1131,19 -958,9 +1131,21 @@@ proto_configure_channel(struct proto *p
    return 1;
  }
  
 +static void
 +proto_cleanup(struct proto *p)
 +{
++  CALL(p->proto->cleanup, p);
++
 +  rfree(p->pool);
 +  p->pool = NULL;
 +
 +  p->active = 0;
 +  proto_log_state_change(p);
 +  proto_rethink_goal(p);
 +}
  
  static void
 -proto_event(void *ptr)
 +proto_loop_stopped(void *ptr)
  {
    struct proto *p = ptr;
  
@@@ -2047,26 -1840,20 +2049,26 @@@ static inline voi
  proto_do_start(struct proto *p)
  {
    p->active = 1;
 -  p->do_start = 1;
 -  ev_schedule(p->event);
 +
 +  rt_init_sources(&p->sources, p->name, proto_event_list(p));
 +  if (!p->sources.class)
 +    p->sources.class = &default_rte_owner_class;
 +
 +  if (!p->cf->late_if_feed)
-     if_feed_baby(p);
++    iface_subscribe(&p->iface_sub);
  }
  
  static void
  proto_do_up(struct proto *p)
  {
    if (!p->main_source)
 -  {
      p->main_source = rt_get_source(p, 0);
 -    rt_lock_source(p->main_source);
 -  }
 +    // Locked automaticaly
  
    proto_start_channels(p);
-     if_feed_baby(p);
 +
 +  if (p->cf->late_if_feed)
++    iface_subscribe(&p->iface_sub);
  }
  
  static inline void
@@@ -2098,7 -1884,8 +2100,6 @@@ static voi
  proto_do_down(struct proto *p)
  {
    p->down_code = 0;
-   neigh_prune();
 -  rfree(p->pool);
 -  p->pool = NULL;
  
    /* Shutdown is finished in the protocol event */
    if (proto_is_done(p))
diff --cc nest/protocol.h
index 101e092615f3df66da24fd9eaf963b7c78374bf4,6d5714a744eb836dffe846db393b4ecc83c8e338..fdd0373a98e87c6659fd962a008b8e569bcaaeef
@@@ -9,12 -9,11 +9,13 @@@
  #ifndef _BIRD_PROTOCOL_H_
  #define _BIRD_PROTOCOL_H_
  
- #include "lib/lists.h"
+ #include "lib/tlists.h"
  #include "lib/resource.h"
  #include "lib/event.h"
 -#include "nest/route.h"
+ #include "nest/iface.h"
 +#include "lib/settle.h"
 +#include "nest/rt.h"
 +#include "nest/limit.h"
  #include "conf/conf.h"
  
  struct iface;
@@@ -59,8 -77,10 +60,9 @@@ struct protocol 
    void (*dump)(struct proto *);                       /* Debugging dump */
    int (*start)(struct proto *);                       /* Start the instance */
    int (*shutdown)(struct proto *);            /* Stop the instance */
 -  void (*cleanup)(struct proto *);            /* Called after shutdown when protocol became hungry/down */
++  void (*cleanup)(struct proto *);            /* Cleanup the instance right before tearing it all down */
    void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
 -  void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
 -  int (*get_attr)(const struct eattr *, byte *buf, int buflen);       /* ASCIIfy dynamic attribute (returns GA_*) */
 +//  int (*get_attr)(const struct eattr *, byte *buf, int buflen);     /* ASCIIfy dynamic attribute (returns GA_*) */
    void (*show_proto_info)(struct proto *);    /* Show protocol info (for `show protocols all' command) */
    void (*copy_config)(struct proto_config *, struct proto_config *);  /* Copy config from given protocol instance */
  };
@@@ -126,10 -169,11 +128,12 @@@ struct proto 
    list channels;                      /* List of channels to rtables (struct channel) */
    struct channel *main_channel;               /* Primary channel */
    struct rte_src *main_source;                /* Primary route source */
 +  struct rte_owner sources;           /* Route source owner structure */
    struct iface *vrf;                  /* Related VRF instance, NULL if global */
+   TLIST_LIST(proto_neigh) neighbors;  /* List of neighbor structures */
+   struct iface_subscription iface_sub;        /* Interface notification subscription */
  
-   const char *name;                           /* Name of this instance (== cf->name) */
+   const char *name;                   /* Name of this instance (== cf->name) */
    u32 debug;                          /* Debugging flags */
    u32 mrtdump;                                /* MRTDump flags */
    uint active_channels;                       /* Number of active channels */
     *     feed_end     Notify channel about finish of route feeding.
     */
  
-   void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
-   void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
 -  void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old);
 +  void (*rt_notify)(struct proto *, struct channel *, const net_addr *net, struct rte *new, const struct rte *old);
-   void (*neigh_notify)(struct neighbor *neigh);
    int (*preexport)(struct channel *, struct rte *rt);
    void (*reload_routes)(struct channel *);
    void (*feed_begin)(struct channel *, int initial);
@@@ -336,8 -381,6 +337,14 @@@ void proto_notify_state(struct proto *p
   *    as a result of received ROUTE-REFRESH request).
   */
  
- { return (p->active_channels == 0) && (p->active_loops == 0) && (p->sources.uc == 0); }
 +static inline int proto_is_inactive(struct proto *p)
++{
++  return (p->active_channels == 0)
++      && (p->active_loops == 0)
++      && (p->sources.uc == 0)
++      && EMPTY_TLIST(proto_neigh, &p->neighbors)
++    ;
++}
  
  
  /*
diff --cc nest/rt-dev.c
Simple merge
index 4db7c66f0874fde0d89a2a0e07f376e985f97a36,151359220cc4b24db8dbf26220d3e0b705770980..c2de7599e9582afe6c5ca542e0658da54c36d9b6
@@@ -2438,11 -2424,11 +2438,11 @@@ babel_init(struct proto_config *CF
    proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
    proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
  
-   P->if_notify = babel_if_notify;
+   P->iface_sub.if_notify = babel_if_notify;
    P->rt_notify = babel_rt_notify;
    P->preexport = babel_preexport;
 -  P->rte_better = babel_rte_better;
 -  P->rte_igp_metric = babel_rte_igp_metric;
 +
 +  P->sources.class = &babel_rte_owner_class;
  
    return P;
  }
diff --cc proto/bfd/bfd.c
Simple merge
diff --cc proto/bgp/bgp.c
index c74b827358c738041f28a257f0108d78cc47cc5c,9c5d483a230b6527f7a5dde91f71002f063b915e..f350c8ca845d11b135f959b52d93cb3cb003ae83
@@@ -139,76 -143,33 +143,36 @@@ static void bgp_update_bfd(struct bgp_p
  
  static int bgp_incoming_connection(sock *sk, uint dummy UNUSED);
  static void bgp_listen_sock_err(sock *sk UNUSED, int err);
+ static void bgp_initiate_disable(struct bgp_proto *p, int err_val);
  
- /**
-  * bgp_open - open a BGP instance
-  * @p: BGP instance
-  *
-  * This function allocates and configures shared BGP resources, mainly listening
-  * sockets. Should be called as the last step during initialization (when lock
-  * is acquired and neighbor is ready). When error, caller should change state to
-  * PS_DOWN and return immediately.
-  */
- static int
- bgp_open(struct bgp_proto *p)
 +static void bgp_graceful_restart_feed(struct bgp_channel *c);
 +
 +
+ static inline int
+ bgp_setup_auth(struct bgp_proto *p, int enable)
  {
-   struct bgp_socket *bs = NULL;
-   struct iface *ifa = p->cf->strict_bind ? p->cf->iface : NULL;
-   ip_addr addr = p->cf->strict_bind ? p->cf->local_ip :
-     (p->ipv4 ? IPA_NONE4 : IPA_NONE6);
-   uint port = p->cf->local_port;
-   uint flags = p->cf->free_bind ? SKF_FREEBIND : 0;
-   uint flag_mask = SKF_FREEBIND;
-   /* We assume that cf->iface is defined iff cf->local_ip is link-local */
+   if (p->cf->password && p->listen.sock)
+   {
+     ip_addr prefix = p->cf->remote_ip;
+     int pxlen = -1;
  
-   WALK_LIST(bs, bgp_sockets)
-     if (ipa_equal(bs->sk->saddr, addr) &&
-       (bs->sk->sport == port) &&
-       (bs->sk->iface == ifa) &&
-       (bs->sk->vrf == p->p.vrf) &&
-       ((bs->sk->flags & flag_mask) == flags))
+     if (p->cf->remote_range)
      {
-       bs->uc++;
-       p->sock = bs;
-       return 0;
+       prefix = net_prefix(p->cf->remote_range);
+       pxlen = net_pxlen(p->cf->remote_range);
      }
  
-   sock *sk = sk_new(proto_pool);
-   sk->type = SK_TCP_PASSIVE;
-   sk->ttl = 255;
-   sk->saddr = addr;
-   sk->sport = port;
-   sk->iface = ifa;
-   sk->vrf = p->p.vrf;
-   sk->flags = flags;
-   sk->tos = IP_PREC_INTERNET_CONTROL;
-   sk->rbsize = BGP_RX_BUFFER_SIZE;
-   sk->tbsize = BGP_TX_BUFFER_SIZE;
-   sk->rx_hook = bgp_incoming_connection;
-   sk->err_hook = bgp_listen_sock_err;
-   if (sk_open(sk) < 0)
-     goto err;
-   bs = mb_allocz(proto_pool, sizeof(struct bgp_socket));
-   bs->sk = sk;
-   bs->uc = 1;
-   p->sock = bs;
-   sk->data = bs;
-   add_tail(&bgp_sockets, &bs->n);
+     int rv = sk_set_md5_auth(p->listen.sock->sk,
+                            p->cf->local_ip, prefix, pxlen, p->cf->iface,
+                            enable ? p->cf->password : NULL, p->cf->setkey);
  
-   return 0;
+     if (rv < 0)
+       sk_log_error(p->listen.sock->sk, p->p.name);
  
- err:
-   sk_log_error(sk, p->p.name);
-   log(L_ERR "%s: Cannot open listening socket", p->p.name);
-   rfree(sk);
-   return -1;
+     return rv;
+   }
+   else
+     return 0;
  }
  
  /**
diff --cc proto/bgp/bgp.h
index 6402921ae7e33ef31fa54cb86c7e5b01e00511d9,5f1a35ce1b1cd4d14bf173f30e230e25829ffb50..acd46f00fc84d7429ed02148a8974116054afd8e
@@@ -333,10 -343,9 +343,10 @@@ struct bgp_proto 
    struct bgp_conn incoming_conn;      /* Incoming connection we have neither accepted nor rejected yet */
    struct object_lock *lock;           /* Lock for neighbor connection */
    struct neighbor *neigh;             /* Neighbor entry corresponding to remote ip, NULL if multihop */
-   struct bgp_socket *sock;            /* Shared listening socket */
+   struct bgp_listen_request listen;   /* Shared listening socket */
    struct bfd_request *bfd_req;                /* BFD request, if BFD is used */
    struct birdsock *postponed_sk;      /* Postponed incoming socket for dynamic BGP */
 +  event *uncork_ev;                   /* Uncork event in case of congestion */
    struct bgp_stats stats;             /* BGP statistics */
    btime last_established;             /* Last time of enter/leave of established state */
    btime last_rx_update;                       /* Last time of RX update */
Simple merge
Simple merge
Simple merge
diff --cc proto/rip/rip.c
index b3a4e81e15a7fb55615ed069a4fd7c124a56763d,abbd83f2a1c1eab673003d1cbd70873e4ae704cd..e9aaf7b15901417d3fc14a2f48349cdb6ab469b2
@@@ -1156,11 -1135,12 +1156,11 @@@ rip_init(struct proto_config *CF
  
    P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
  
-   P->if_notify = rip_if_notify;
+   P->iface_sub.if_notify = rip_if_notify;
    P->rt_notify = rip_rt_notify;
-   P->neigh_notify = rip_neigh_notify;
+   P->iface_sub.neigh_notify = rip_neigh_notify;
    P->reload_routes = rip_reload_routes;
 -  P->rte_better = rip_rte_better;
 -  P->rte_igp_metric = rip_rte_igp_metric;
 +  P->sources.class = &rip_rte_owner_class;
  
    return P;
  }
index 42fd20b7ac52f6a0b05293df7a1a7b272a1bf3ff,ba0984b50538ee7d6165bfe6d45eaf64e0864b84..82fbfe7a016f676838f99d1128ae61bc60c300e2
@@@ -460,9 -463,10 +460,9 @@@ static_init(struct proto_config *CF
  
    P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
  
-   P->neigh_notify = static_neigh_notify;
+   P->iface_sub.neigh_notify = static_neigh_notify;
    P->reload_routes = static_reload_routes;
 -  P->rte_better = static_rte_better;
 -  P->rte_mergable = static_rte_mergable;
 +  P->sources.class = &static_rte_owner_class;
  
    if (cf->igp_table_ip4)
      p->igp_table_ip4 = cf->igp_table_ip4->table;
Simple merge