From: Donald Sharp Date: Mon, 12 Apr 2021 18:16:30 +0000 (-0400) Subject: bgpd: Address LL peer not NHT when receiving connection attempt X-Git-Tag: base_8.0~122^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=refs%2Fpull%2F8456%2Fhead;p=mirror%2Ffrr.git bgpd: Address LL peer not NHT when receiving connection attempt The new LL code in: 8761cd6ddb5437767625f58c8e9cc3ccda7887ab Introduced the idea of the bgp unnumbered peers using interface up/down events to track the bgp peers nexthop. This code was not properly working when a connection was received from a peer in some circumstances. Effectively the connection from a peer was immediately skipping state transitions and FRR was never properly tracking the peers nexthop. When we receive the connection attempt, let's track the nexthop now. Signed-off-by: Donald Sharp --- diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 45a856a459..88c44fc984 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -101,7 +101,7 @@ static int bgp_delayopen_timer(struct thread *); static int bgp_start(struct peer *); /* Register peer with NHT */ -static int bgp_peer_reg_with_nht(struct peer *peer) +int bgp_peer_reg_with_nht(struct peer *peer) { int connected = 0; @@ -340,6 +340,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) * needed, even on a passive connection. */ bgp_peer_reg_with_nht(peer); + if (from_peer) + bgp_replace_nexthop_by_peer(from_peer, peer); bgp_reads_on(peer); bgp_writes_on(peer); diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index bcf697e153..12cbad3eb8 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -179,4 +179,5 @@ const char *print_peer_gr_mode(enum peer_mode pr_mode); const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd); const char *print_global_gr_mode(enum global_mode gl_mode); const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd); +int bgp_peer_reg_with_nht(struct peer *peer); #endif /* _QUAGGA_BGP_FSM_H */ diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 4821ce8ddb..8d9024e07c 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -569,6 +569,7 @@ static int bgp_accept(struct thread *thread) peer1->doppelganger = peer; peer->fd = bgp_sock; vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer)); + bgp_peer_reg_with_nht(peer); bgp_fsm_change_status(peer, Active); BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 9c8d7878c5..7ccfae4ba4 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -98,6 +98,31 @@ void bgp_unlink_nexthop(struct bgp_path_info *path) bgp_unlink_nexthop_check(bnc); } +void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to) +{ + struct prefix pp; + struct prefix pt; + struct bgp_nexthop_cache *bncp, *bnct; + afi_t afi; + + if (!sockunion2hostprefix(&from->su, &pp)) + return; + + afi = family2afi(pp.family); + bncp = bnc_find(&from->bgp->nexthop_cache_table[afi], &pp, 0); + + if (!sockunion2hostprefix(&to->su, &pt)) + return; + + bnct = bnc_find(&to->bgp->nexthop_cache_table[afi], &pt, 0); + + if (bnct != bncp) + return; + + if (bnct) + bnct->nht_info = to; +} + void bgp_unlink_nexthop_by_peer(struct peer *peer) { struct prefix p; @@ -273,8 +298,16 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric; else if (pi->extra) pi->extra->igpmetric = 0; - } else if (peer) - bnc->nht_info = (void *)peer; /* NHT peer reference */ + } else if (peer) { + /* + * Let's not accidently save the peer data for a peer + * we are going to throw away in a second or so. + * When we come back around we'll fix up this + * data properly in replace_nexthop_by_peer + */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) + bnc->nht_info = (void *)peer; /* NHT peer reference */ + } /* * We are cheating here. Views have no associated underlying diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index a1683e1511..9268b225ca 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -51,7 +51,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp_route, */ extern void bgp_unlink_nexthop(struct bgp_path_info *p); void bgp_unlink_nexthop_by_peer(struct peer *peer); - +void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to); /** * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected * nexthop entry. If no paths reference the nexthop, it will be unregistered