From e2d3a909548de5a7062f0caf7d7ef306128cb1a8 Mon Sep 17 00:00:00 2001 From: vivek Date: Sun, 18 Aug 2019 22:12:06 -0700 Subject: [PATCH] bgpd: Fix nexthop reg for IPv4 route exchange using GUA IPv6 peering In the case of IPv4 route exchange using GUA IPv6 peering, the route install into the FIB involves mapping the immediate next hop to an IPv4 link-local address and installing neighbor entries for this next hop address. To accomplish the latter, IPv6 Router Advertisements are exchanged (the next hop or peer must also have this enabled) and the RAs are dynamically initiated based on next hop resolution. However, in the case of a passive connection where the local system has not initiated anything, no NHT entry is created for the peer, hence RAs were not getting triggered. Address this by ensuring that a NHT entry is created even in this situation. This is done at the time the connection becomes established because the code has other assumptions that a NHT entry will be present only for the "configured" peer. The API to create the entry ensures there are no duplicates. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp --- bgpd/bgp_fsm.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 4348e6b240..c9c6fc157e 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -96,6 +96,21 @@ static int bgp_holdtime_timer(struct thread *); /* BGP FSM functions. */ static int bgp_start(struct peer *); +/* Register peer with NHT */ +static int bgp_peer_reg_with_nht(struct peer *peer) +{ + int connected = 0; + + if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 + && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) + && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) + connected = 1; + + return bgp_find_or_add_nexthop( + peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family), + NULL, peer, connected); +} + static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src) { /* Copy stats over. These are only the pre-established state stats */ @@ -293,6 +308,11 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) if (from_peer) peer_xfer_stats(peer, from_peer); + /* Register peer for NHT. This is to allow RAs to be enabled when + * needed, even on a passive connection. + */ + bgp_peer_reg_with_nht(peer); + bgp_reads_on(peer); bgp_writes_on(peer); thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0, @@ -1382,7 +1402,6 @@ static int bgp_connect_fail(struct peer *peer) int bgp_start(struct peer *peer) { int status; - int connected = 0; bgp_peer_conf_if_to_su_update(peer); @@ -1439,17 +1458,10 @@ int bgp_start(struct peer *peer) return -1; } - /* Register to be notified on peer up */ - if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 - && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) - && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - connected = 1; - else - connected = 0; - - if (!bgp_find_or_add_nexthop(peer->bgp, peer->bgp, - family2afi(peer->su.sa.sa_family), NULL, - peer, connected)) { + /* Register peer for NHT. If next hop is already resolved, proceed + * with connection setup, else wait. + */ + if (!bgp_peer_reg_with_nht(peer)) { if (bgp_zebra_num_connects()) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s [FSM] Waiting for NHT", -- 2.39.5