From: Maria Matejka Date: Tue, 7 Feb 2023 13:27:23 +0000 (+0100) Subject: Merge commit '0bb04d5390f21b0c96fc4894ba5d5510c541f0ef' into HEAD X-Git-Tag: v3.0-alpha1~49 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2fd889a3b95960311560a3796be5cdf92affcfc;p=thirdparty%2Fbird.git Merge commit '0bb04d5390f21b0c96fc4894ba5d5510c541f0ef' into HEAD --- a2fd889a3b95960311560a3796be5cdf92affcfc diff --cc nest/iface.c index fc896e266,740c18789..c49ad95e6 --- a/nest/iface.c +++ b/nest/iface.c @@@ -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 bec305606,39e8b9997..6e4b7d290 --- a/nest/proto.c +++ b/nest/proto.c @@@ -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 (p->cf->late_if_feed) - if_feed_baby(p); ++ 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 101e09261,6d5714a74..fdd0373a9 --- a/nest/protocol.h +++ b/nest/protocol.h @@@ -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/iface.h" -#include "nest/route.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 */ @@@ -167,10 -211,7 +171,7 @@@ * 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). */ +static inline int proto_is_inactive(struct proto *p) - { return (p->active_channels == 0) && (p->active_loops == 0) && (p->sources.uc == 0); } ++{ ++ return (p->active_channels == 0) ++ && (p->active_loops == 0) ++ && (p->sources.uc == 0) ++ && EMPTY_TLIST(proto_neigh, &p->neighbors) ++ ; ++} /* diff --cc proto/babel/babel.c index 4db7c66f0,151359220..c2de7599e --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@@ -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/bgp/bgp.c index c74b82735,9c5d483a2..f350c8ca8 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@@ -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); +static void bgp_graceful_restart_feed(struct bgp_channel *c); + + - /** - * 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 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 6402921ae,5f1a35ce1..acd46f00f --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@@ -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 */ diff --cc proto/rip/rip.c index b3a4e81e1,abbd83f2a..e9aaf7b15 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@@ -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; } diff --cc proto/static/static.c index 42fd20b7a,ba0984b50..82fbfe7a0 --- a/proto/static/static.c +++ b/proto/static/static.c @@@ -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;