From 54430df953d6c590e5f446530a21d18277eeda56 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 8 Sep 2022 19:41:02 +0200 Subject: [PATCH] BGP: Do not assume that all channels are struct bgp_channel In principle, the channel list is a list of parent struct proto and can contain general structures of type struct channel, That is useful e.g. for adding MPLS channels to BGP. --- nest/proto.c | 3 +++ proto/bgp/attrs.c | 8 ++++++++ proto/bgp/bgp.c | 39 +++++++++++++++++++++++++-------------- proto/bgp/bgp.h | 3 +++ proto/bgp/packets.c | 4 ++-- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/nest/proto.c b/nest/proto.c index 7074f73a..60a74964 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -829,6 +829,9 @@ static int reconfigure_type; /* Hack to propagate type info to channel_reconfig int channel_reconfigure(struct channel *c, struct channel_config *cf) { + /* Touched by reconfiguration */ + c->stale = 0; + /* FIXME: better handle these changes, also handle in_keep_filtered */ if ((c->table != cf->table->table) || (cf->ra_mode && (c->ra_mode != cf->ra_mode))) return 0; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index a56aeb19..1e234b16 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1725,6 +1725,10 @@ bgp_preexport(struct channel *C, rte *e) struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL; struct bgp_channel *c = (struct bgp_channel *) C; + /* Ignore non-BGP channels */ + if (C->channel != &channel_bgp) + return -1; + /* Reject our routes */ if (src == p) return -1; @@ -1922,6 +1926,10 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old) struct bgp_prefix *px; u32 path; + /* Ignore non-BGP channels */ + if (C->channel != &channel_bgp) + return; + if (new) { struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, tmp_linpool); diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index f07fcc16..e1e0d796 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -260,7 +260,7 @@ static inline struct bgp_channel * bgp_find_channel(struct bgp_proto *p, u32 afi) { struct bgp_channel *c; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) if (c->afi == afi) return c; @@ -586,7 +586,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) /* Summary state of ADD_PATH RX for active channels */ uint summary_add_path_rx = 0; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi); const struct bgp_af_caps *rem = bgp_find_af_caps(peer, c->afi); @@ -668,7 +668,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn) p->channel_count = num; p->summary_add_path_rx = summary_add_path_rx; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { if (c->c.disabled) continue; @@ -747,7 +747,7 @@ bgp_handle_graceful_restart(struct bgp_proto *p) p->gr_active_num = 0; struct bgp_channel *c; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { /* FIXME: perhaps check for channel state instead of disabled flag? */ if (c->c.disabled) @@ -842,7 +842,7 @@ bgp_graceful_restart_timeout(timer *t) if (p->llgr_ready) { struct bgp_channel *c; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { /* Channel is not in GR and is already flushed */ if (!c->gr_active) @@ -1394,6 +1394,10 @@ bgp_reload_routes(struct channel *C) struct bgp_proto *p = (void *) C->proto; struct bgp_channel *c = (void *) C; + /* Ignore non-BGP channels */ + if (C->channel != &channel_bgp) + return; + ASSERT(p->conn && (p->route_refresh || c->c.in_table)); if (c->c.in_table) @@ -1408,6 +1412,10 @@ bgp_feed_begin(struct channel *C, int initial) struct bgp_proto *p = (void *) C->proto; struct bgp_channel *c = (void *) C; + /* Ignore non-BGP channels */ + if (C->channel != &channel_bgp) + return; + /* This should not happen */ if (!p->conn) return; @@ -1433,6 +1441,10 @@ bgp_feed_end(struct channel *C) struct bgp_proto *p = (void *) C->proto; struct bgp_channel *c = (void *) C; + /* Ignore non-BGP channels */ + if (C->channel != &channel_bgp) + return; + /* This should not happen */ if (!p->conn) return; @@ -1547,7 +1559,7 @@ bgp_start(struct proto *P) if (p->p.gr_recovery && p->cf->gr_mode) { struct bgp_channel *c; - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) channel_graceful_restart_lock(&c->c); } @@ -1701,7 +1713,7 @@ bgp_init(struct proto_config *CF) /* Add all channels */ struct bgp_channel_config *cc; - WALK_LIST(cc, CF->channels) + BGP_CF_WALK_CHANNELS(cf, cc) proto_add_channel(P, &cc->c); return P; @@ -1847,7 +1859,7 @@ bgp_find_channel_config(struct bgp_config *cf, u32 afi) { struct bgp_channel_config *cc; - WALK_LIST(cc, cf->c.channels) + BGP_CF_WALK_CHANNELS(cf, cc) if (cc->afi == afi) return cc; @@ -1997,7 +2009,7 @@ bgp_postconfig(struct proto_config *CF) struct bgp_channel_config *cc; - WALK_LIST(cc, CF->channels) + BGP_CF_WALK_CHANNELS(cf, cc) { /* Handle undefined import filter */ if (cc->c.in_filter == FILTER_UNDEF) @@ -2104,20 +2116,16 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF) WALK_LIST(C, p->p.channels) C->stale = 1; - WALK_LIST(cc, new->c.channels) + BGP_CF_WALK_CHANNELS(new, cc) { C = (struct channel *) bgp_find_channel(p, cc->afi); same = proto_configure_channel(P, &C, &cc->c) && same; - - if (C) - C->stale = 0; } WALK_LIST_DELSAFE(C, C2, p->p.channels) if (C->stale) same = proto_configure_channel(P, &C, NULL) && same; - if (same && (p->start_state > BSS_PREPARE)) bgp_update_bfd(p, new->bfd); @@ -2562,6 +2570,9 @@ bgp_show_proto_info(struct proto *P) { channel_show_info(&c->c); + if (c->c.channel != &channel_bgp) + continue; + if (p->gr_active_num) cli_msg(-1006, " Neighbor GR: %s", bgp_gr_states[c->gr_active]); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 15a759fb..5d0e9791 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -485,6 +485,9 @@ struct bgp_parse_state { #define BGP_RX_BUFFER_EXT_SIZE 65535 #define BGP_TX_BUFFER_EXT_SIZE 65535 +#define BGP_CF_WALK_CHANNELS(P,C) WALK_LIST(C, P->c.channels) if (C->c.channel == &channel_bgp) +#define BGP_WALK_CHANNELS(P,C) WALK_LIST(C, P->p.channels) if (C->c.channel == &channel_bgp) + static inline int bgp_channel_is_ipv4(struct bgp_channel *c) { return BGP_AFI(c->afi) == BGP_AFI_IPV4; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 3aa62c39..fc23897d 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -262,7 +262,7 @@ bgp_prepare_capabilities(struct bgp_conn *conn) } /* Allocate and fill per-AF fields */ - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { ac = &caps->af_data[caps->af_count++]; ac->afi = c->afi; @@ -681,7 +681,7 @@ bgp_check_capabilities(struct bgp_conn *conn) /* This is partially overlapping with bgp_conn_enter_established_state(), but we need to run this just after we receive OPEN message */ - WALK_LIST(c, p->p.channels) + BGP_WALK_CHANNELS(p, c) { const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi); const struct bgp_af_caps *rem = bgp_find_af_caps(remote, c->afi);