summaryrefslogtreecommitdiff
path: root/bgpd/bgp_nht.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_nht.c')
-rw-r--r--bgpd/bgp_nht.c1188
1 files changed, 578 insertions, 610 deletions
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b0362b5537..c06aee6f90 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -46,7 +46,7 @@
extern struct zclient *zclient;
static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
- int is_bgp_static_route);
+ int is_bgp_static_route);
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
int is_bgp_static_route);
static void evaluate_paths(struct bgp_nexthop_cache *bnc);
@@ -54,510 +54,486 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p);
static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
int keep);
-static int
-bgp_isvalid_nexthop (struct bgp_nexthop_cache *bnc)
+static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
{
- return (bgp_zebra_num_connects() == 0 ||
- (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
+ return (bgp_zebra_num_connects() == 0
+ || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
}
-int
-bgp_find_nexthop (struct bgp_info *path, int connected)
+int bgp_find_nexthop(struct bgp_info *path, int connected)
{
- struct bgp_nexthop_cache *bnc = path->nexthop;
+ struct bgp_nexthop_cache *bnc = path->nexthop;
- if (!bnc)
- return 0;
+ if (!bnc)
+ return 0;
- /*
- * We are cheating here. Views have no associated underlying
- * ability to detect nexthops. So when we have a view
- * just tell everyone the nexthop is valid
- */
- if (path->peer && path->peer->bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
- return 1;
+ /*
+ * We are cheating here. Views have no associated underlying
+ * ability to detect nexthops. So when we have a view
+ * just tell everyone the nexthop is valid
+ */
+ if (path->peer && path->peer->bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+ return 1;
- if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
- return 0;
+ if (connected && !(CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)))
+ return 0;
- return (bgp_isvalid_nexthop(bnc));
+ return (bgp_isvalid_nexthop(bnc));
}
-static void
-bgp_unlink_nexthop_check (struct bgp_nexthop_cache *bnc)
+static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
{
- if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info)
- {
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[PREFIX2STR_BUFFER];
- zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
- bnc_str(bnc, buf, PREFIX2STR_BUFFER));
+ if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[PREFIX2STR_BUFFER];
+ zlog_debug("bgp_unlink_nexthop: freeing bnc %s",
+ bnc_str(bnc, buf, PREFIX2STR_BUFFER));
+ }
+ unregister_zebra_rnh(bnc,
+ CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
+ bnc->node->info = NULL;
+ bgp_unlock_node(bnc->node);
+ bnc->node = NULL;
+ bnc_free(bnc);
}
- unregister_zebra_rnh(bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
- bnc->node->info = NULL;
- bgp_unlock_node(bnc->node);
- bnc->node = NULL;
- bnc_free(bnc);
- }
}
-void
-bgp_unlink_nexthop (struct bgp_info *path)
+void bgp_unlink_nexthop(struct bgp_info *path)
{
- struct bgp_nexthop_cache *bnc = path->nexthop;
+ struct bgp_nexthop_cache *bnc = path->nexthop;
+
+ if (!bnc)
+ return;
- if (!bnc)
- return;
+ path_nh_map(path, NULL, 0);
- path_nh_map(path, NULL, 0);
-
- bgp_unlink_nexthop_check (bnc);
+ bgp_unlink_nexthop_check(bnc);
}
-void
-bgp_unlink_nexthop_by_peer (struct peer *peer)
+void bgp_unlink_nexthop_by_peer(struct peer *peer)
{
- struct prefix p;
- struct bgp_node *rn;
- struct bgp_nexthop_cache *bnc;
- afi_t afi = family2afi(peer->su.sa.sa_family);
-
- if (! sockunion2hostprefix (&peer->su, &p))
- return;
-
- rn = bgp_node_get (peer->bgp->nexthop_cache_table[afi], &p);
-
- if (!rn->info)
- return;
-
- bnc = rn->info;
-
- /* cleanup the peer reference */
- bnc->nht_info = NULL;
-
- bgp_unlink_nexthop_check (bnc);
+ struct prefix p;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ afi_t afi = family2afi(peer->su.sa.sa_family);
+
+ if (!sockunion2hostprefix(&peer->su, &p))
+ return;
+
+ rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
+
+ if (!rn->info)
+ return;
+
+ bnc = rn->info;
+
+ /* cleanup the peer reference */
+ bnc->nht_info = NULL;
+
+ bgp_unlink_nexthop_check(bnc);
}
-int
-bgp_find_or_add_nexthop (struct bgp *bgp, afi_t afi, struct bgp_info *ri,
- struct peer *peer, int connected)
+int bgp_find_or_add_nexthop(struct bgp *bgp, afi_t afi, struct bgp_info *ri,
+ struct peer *peer, int connected)
{
- struct bgp_node *rn;
- struct bgp_nexthop_cache *bnc;
- struct prefix p;
- int is_bgp_static_route = 0;
-
- if (ri)
- {
- is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) &&
- (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
-
- /* Since Extended Next-hop Encoding (RFC5549) support, we want to derive
- address-family from the next-hop. */
- if (!is_bgp_static_route)
- afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 : AFI_IP;
-
- /* This will return TRUE if the global IPv6 NH is a link local addr */
- if (make_prefix(afi, ri, &p) < 0)
- return 1;
- }
- else if (peer)
- {
- /* Don't register link local NH */
- if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr))
- return 1;
-
- if (! sockunion2hostprefix (&peer->su, &p))
- {
- if (BGP_DEBUG(nht, NHT))
- {
- zlog_debug("%s: Attempting to register with unknown AFI %d (not %d or %d)",
- __FUNCTION__, afi, AFI_IP, AFI_IP6);
- }
- return 0;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct prefix p;
+ int is_bgp_static_route = 0;
+
+ if (ri) {
+ is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP)
+ && (ri->sub_type == BGP_ROUTE_STATIC))
+ ? 1
+ : 0;
+
+ /* Since Extended Next-hop Encoding (RFC5549) support, we want
+ to derive
+ address-family from the next-hop. */
+ if (!is_bgp_static_route)
+ afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6
+ : AFI_IP;
+
+ /* This will return TRUE if the global IPv6 NH is a link local
+ * addr */
+ if (make_prefix(afi, ri, &p) < 0)
+ return 1;
+ } else if (peer) {
+ /* Don't register link local NH */
+ if (afi == AFI_IP6
+ && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
+ return 1;
+
+ if (!sockunion2hostprefix(&peer->su, &p)) {
+ if (BGP_DEBUG(nht, NHT)) {
+ zlog_debug(
+ "%s: Attempting to register with unknown AFI %d (not %d or %d)",
+ __FUNCTION__, afi, AFI_IP, AFI_IP6);
+ }
+ return 0;
+ }
+ } else
+ return 0;
+
+ if (is_bgp_static_route)
+ rn = bgp_node_get(bgp->import_check_table[afi], &p);
+ else
+ rn = bgp_node_get(bgp->nexthop_cache_table[afi], &p);
+
+ if (!rn->info) {
+ bnc = bnc_new();
+ rn->info = bnc;
+ bnc->node = rn;
+ bnc->bgp = bgp;
+ bgp_lock_node(rn);
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[PREFIX2STR_BUFFER];
+
+ zlog_debug("Allocated bnc %s peer %p",
+ bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer);
+ }
}
- }
- else
- return 0;
-
- if (is_bgp_static_route)
- rn = bgp_node_get (bgp->import_check_table[afi], &p);
- else
- rn = bgp_node_get (bgp->nexthop_cache_table[afi], &p);
-
- if (!rn->info)
- {
- bnc = bnc_new();
- rn->info = bnc;
- bnc->node = rn;
- bnc->bgp = bgp;
- bgp_lock_node(rn);
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[PREFIX2STR_BUFFER];
-
- zlog_debug("Allocated bnc %s peer %p",
- bnc_str(bnc, buf, PREFIX2STR_BUFFER), peer);
- }
- }
-
- bnc = rn->info;
- bgp_unlock_node (rn);
- if (is_bgp_static_route)
- {
- SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
-
- /* If we're toggling the type, re-register */
- if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
- !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
- {
- SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+
+ bnc = rn->info;
+ bgp_unlock_node(rn);
+ if (is_bgp_static_route) {
+ SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
+
+ /* If we're toggling the type, re-register */
+ if ((bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK))
+ && !CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)) {
+ SET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ } else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK))
+ && CHECK_FLAG(bnc->flags,
+ BGP_STATIC_ROUTE_EXACT_MATCH)) {
+ UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ }
}
- else if ((!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)) &&
- CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
- {
- UNSET_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ /* When nexthop is already known, but now requires 'connected'
+ * resolution,
+ * re-register it. The reverse scenario where the nexthop currently
+ * requires
+ * 'connected' resolution does not need a re-register (i.e., we treat
+ * 'connected-required' as an override) except in the scenario where
+ * this
+ * is actually a case of tracking a peer for connectivity (e.g., after
+ * disable connected-check).
+ * NOTE: We don't track the number of paths separately for 'connected-
+ * required' vs 'connected-not-required' as this change is not a common
+ * scenario.
+ */
+ else if (connected && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
+ } else if (peer && !connected
+ && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) {
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
}
- }
- /* When nexthop is already known, but now requires 'connected' resolution,
- * re-register it. The reverse scenario where the nexthop currently requires
- * 'connected' resolution does not need a re-register (i.e., we treat
- * 'connected-required' as an override) except in the scenario where this
- * is actually a case of tracking a peer for connectivity (e.g., after
- * disable connected-check).
- * NOTE: We don't track the number of paths separately for 'connected-
- * required' vs 'connected-not-required' as this change is not a common
- * scenario.
- */
- else if (connected && ! CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
- {
- SET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
- }
- else if (peer && !connected && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
- {
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
- }
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
- {
- bnc->flags |= BGP_NEXTHOP_REGISTERED;
- bnc->flags |= BGP_NEXTHOP_VALID;
- }
- else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
- register_zebra_rnh(bnc, is_bgp_static_route);
- if (ri && ri->nexthop != bnc)
- {
- /* Unlink from existing nexthop cache, if any. This will also free
- * the nexthop cache entry, if appropriate.
- */
- bgp_unlink_nexthop (ri);
-
- path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
-
- if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
- (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
- else if (ri->extra)
- ri->extra->igpmetric = 0;
- }
- else if (peer)
- bnc->nht_info = (void *)peer; /* NHT peer reference */
-
- /*
- * We are cheating here. Views have no associated underlying
- * ability to detect nexthops. So when we have a view
- * just tell everyone the nexthop is valid
- */
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
- return 1;
- else
- return (bgp_isvalid_nexthop(bnc));
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) {
+ bnc->flags |= BGP_NEXTHOP_REGISTERED;
+ bnc->flags |= BGP_NEXTHOP_VALID;
+ } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+ register_zebra_rnh(bnc, is_bgp_static_route);
+ if (ri && ri->nexthop != bnc) {
+ /* Unlink from existing nexthop cache, if any. This will also
+ * free
+ * the nexthop cache entry, if appropriate.
+ */
+ bgp_unlink_nexthop(ri);
+
+ path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */
+
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
+ (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
+ else if (ri->extra)
+ ri->extra->igpmetric = 0;
+ } else if (peer)
+ bnc->nht_info = (void *)peer; /* NHT peer reference */
+
+ /*
+ * We are cheating here. Views have no associated underlying
+ * ability to detect nexthops. So when we have a view
+ * just tell everyone the nexthop is valid
+ */
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+ return 1;
+ else
+ return (bgp_isvalid_nexthop(bnc));
}
-void
-bgp_delete_connected_nexthop (afi_t afi, struct peer *peer)
+void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
{
- struct bgp_node *rn;
- struct bgp_nexthop_cache *bnc;
- struct prefix p;
-
- if (!peer)
- return;
-
- /* We don't register link local address for NHT */
- if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&peer->su.sin6.sin6_addr))
- return;
-
- if (! sockunion2hostprefix (&peer->su, &p))
- return;
-
- rn = bgp_node_lookup(peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
- if (!rn || !rn->info)
- {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug("Cannot find connected NHT node for peer %s", peer->host);
- if (rn)
- bgp_unlock_node (rn);
- return;
- }
-
- bnc = rn->info;
- bgp_unlock_node(rn);
-
- if (bnc->nht_info != peer)
- {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug("Connected NHT %p node for peer %s points to %p",
- bnc, peer->host, bnc->nht_info);
- return;
- }
-
- bnc->nht_info = NULL;
-
- if (LIST_EMPTY(&(bnc->paths)))
- {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug("Freeing connected NHT node %p for peer %s",
- bnc, peer->host);
- unregister_zebra_rnh(bnc, 0);
- bnc->node->info = NULL;
- bgp_unlock_node(bnc->node);
- bnc_free(bnc);
- }
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct prefix p;
+
+ if (!peer)
+ return;
+
+ /* We don't register link local address for NHT */
+ if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
+ return;
+
+ if (!sockunion2hostprefix(&peer->su, &p))
+ return;
+
+ rn = bgp_node_lookup(
+ peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
+ if (!rn || !rn->info) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Cannot find connected NHT node for peer %s",
+ peer->host);
+ if (rn)
+ bgp_unlock_node(rn);
+ return;
+ }
+
+ bnc = rn->info;
+ bgp_unlock_node(rn);
+
+ if (bnc->nht_info != peer) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug(
+ "Connected NHT %p node for peer %s points to %p",
+ bnc, peer->host, bnc->nht_info);
+ return;
+ }
+
+ bnc->nht_info = NULL;
+
+ if (LIST_EMPTY(&(bnc->paths))) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Freeing connected NHT node %p for peer %s",
+ bnc, peer->host);
+ unregister_zebra_rnh(bnc, 0);
+ bnc->node->info = NULL;
+ bgp_unlock_node(bnc->node);
+ bnc_free(bnc);
+ }
}
-void
-bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
+void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
{
- struct stream *s;
- struct bgp_node *rn = NULL;
- struct bgp_nexthop_cache *bnc;
- struct nexthop *nexthop;
- struct nexthop *oldnh;
- struct nexthop *nhlist_head = NULL;
- struct nexthop *nhlist_tail = NULL;
- uint32_t metric;
- u_char nexthop_num;
- struct prefix p;
- int i;
- struct bgp *bgp;
-
- bgp = bgp_lookup_by_vrf_id (vrf_id);
- if (!bgp)
- {
- zlog_err("parse nexthop update: instance not found for vrf_id %d", vrf_id);
- return;
- }
-
- s = zclient->ibuf;
-
- memset(&p, 0, sizeof(struct prefix));
- p.family = stream_getw(s);
- p.prefixlen = stream_getc(s);
- switch (p.family)
- {
- case AF_INET:
- p.u.prefix4.s_addr = stream_get_ipv4 (s);
- break;
- case AF_INET6:
- stream_get(&p.u.prefix6, s, 16);
- break;
- default:
- break;
- }
-
- if (command == ZEBRA_NEXTHOP_UPDATE)
- rn = bgp_node_lookup(bgp->nexthop_cache_table[family2afi(p.family)], &p);
- else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
- rn = bgp_node_lookup(bgp->import_check_table[family2afi(p.family)], &p);
-
- if (!rn || !rn->info)
- {
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[PREFIX2STR_BUFFER];
- prefix2str(&p, buf, sizeof(buf));
- zlog_debug("parse nexthop update(%s): rn not found", buf);
+ struct stream *s;
+ struct bgp_node *rn = NULL;
+ struct bgp_nexthop_cache *bnc;
+ struct nexthop *nexthop;
+ struct nexthop *oldnh;
+ struct nexthop *nhlist_head = NULL;
+ struct nexthop *nhlist_tail = NULL;
+ uint32_t metric;
+ u_char nexthop_num;
+ struct prefix p;
+ int i;
+ struct bgp *bgp;
+
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp) {
+ zlog_err(
+ "parse nexthop update: instance not found for vrf_id %d",
+ vrf_id);
+ return;
}
- if (rn)
- bgp_unlock_node (rn);
- return;
- }
-
- bnc = rn->info;
- bgp_unlock_node (rn);
- bnc->last_update = bgp_clock();
- bnc->change_flags = 0;
- stream_getc (s); // Distance but not currently used
- metric = stream_getl (s);
- nexthop_num = stream_getc (s);
-
- /* debug print the input */
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[PREFIX2STR_BUFFER];
- prefix2str(&p, buf, sizeof (buf));
- zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)",
- vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num);
- }
-
- if (metric != bnc->metric)
- bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
-
- if(nexthop_num != bnc->nexthop_num)
- bnc->change_flags |= BGP_NEXTHOP_CHANGED;
-
- if (nexthop_num)
- {
- /* notify bgp fsm if nbr ip goes from invalid->valid */
- if (!bnc->nexthop_num)
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
-
- bnc->flags |= BGP_NEXTHOP_VALID;
- bnc->metric = metric;
- bnc->nexthop_num = nexthop_num;
-
- for (i = 0; i < nexthop_num; i++)
- {
- nexthop = nexthop_new();
- nexthop->type = stream_getc (s);
- switch (nexthop->type)
- {
- case NEXTHOP_TYPE_IPV4:
- nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
- nexthop->ifindex = stream_getl (s);
- break;
- case NEXTHOP_TYPE_IFINDEX:
- nexthop->ifindex = stream_getl (s);
- break;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
- nexthop->ifindex = stream_getl (s);
- break;
- case NEXTHOP_TYPE_IPV6:
- stream_get (&nexthop->gate.ipv6, s, 16);
- nexthop->ifindex = stream_getl (s);
- break;
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- stream_get (&nexthop->gate.ipv6, s, 16);
- nexthop->ifindex = stream_getl (s);
- break;
- default:
- /* do nothing */
- break;
- }
-
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[NEXTHOP_STRLEN];
- zlog_debug(" nhop via %s",
- nexthop2str (nexthop, buf, sizeof (buf)));
- }
-
- if (nhlist_tail)
- {
- nhlist_tail->next = nexthop;
- nhlist_tail = nexthop;
- }
- else
- {
- nhlist_tail = nexthop;
- nhlist_head = nexthop;
- }
-
- /* No need to evaluate the nexthop if we have already determined
- * that there has been a change.
- */
- if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
- continue;
-
- for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
- if (nexthop_same_no_recurse(oldnh, nexthop))
- break;
-
- if (!oldnh)
- bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+
+ s = zclient->ibuf;
+
+ memset(&p, 0, sizeof(struct prefix));
+ p.family = stream_getw(s);
+ p.prefixlen = stream_getc(s);
+ switch (p.family) {
+ case AF_INET:
+ p.u.prefix4.s_addr = stream_get_ipv4(s);
+ break;
+ case AF_INET6:
+ stream_get(&p.u.prefix6, s, 16);
+ break;
+ default:
+ break;
+ }
+
+ if (command == ZEBRA_NEXTHOP_UPDATE)
+ rn = bgp_node_lookup(
+ bgp->nexthop_cache_table[family2afi(p.family)], &p);
+ else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
+ rn = bgp_node_lookup(
+ bgp->import_check_table[family2afi(p.family)], &p);
+
+ if (!rn || !rn->info) {
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(&p, buf, sizeof(buf));
+ zlog_debug("parse nexthop update(%s): rn not found",
+ buf);
+ }
+ if (rn)
+ bgp_unlock_node(rn);
+ return;
}
- bnc_nexthop_free(bnc);
- bnc->nexthop = nhlist_head;
- }
- else
- {
- bnc->flags &= ~BGP_NEXTHOP_VALID;
- bnc->nexthop_num = nexthop_num;
-
- /* notify bgp fsm if nbr ip goes from valid->invalid */
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
-
- bnc_nexthop_free(bnc);
- bnc->nexthop = NULL;
- }
-
- evaluate_paths(bnc);
+
+ bnc = rn->info;
+ bgp_unlock_node(rn);
+ bnc->last_update = bgp_clock();
+ bnc->change_flags = 0;
+ stream_getc(s); // Distance but not currently used
+ metric = stream_getl(s);
+ nexthop_num = stream_getc(s);
+
+ /* debug print the input */
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[PREFIX2STR_BUFFER];
+ prefix2str(&p, buf, sizeof(buf));
+ zlog_debug(
+ "%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)",
+ vrf_id, buf, metric, bnc->metric, nexthop_num,
+ bnc->nexthop_num);
+ }
+
+ if (metric != bnc->metric)
+ bnc->change_flags |= BGP_NEXTHOP_METRIC_CHANGED;
+
+ if (nexthop_num != bnc->nexthop_num)
+ bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+
+ if (nexthop_num) {
+ /* notify bgp fsm if nbr ip goes from invalid->valid */
+ if (!bnc->nexthop_num)
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+
+ bnc->flags |= BGP_NEXTHOP_VALID;
+ bnc->metric = metric;
+ bnc->nexthop_num = nexthop_num;
+
+ for (i = 0; i < nexthop_num; i++) {
+ nexthop = nexthop_new();
+ nexthop->type = stream_getc(s);
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ nexthop->gate.ipv4.s_addr = stream_get_ipv4(s);
+ nexthop->ifindex = stream_getl(s);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ nexthop->ifindex = stream_getl(s);
+ break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ nexthop->gate.ipv4.s_addr = stream_get_ipv4(s);
+ nexthop->ifindex = stream_getl(s);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ stream_get(&nexthop->gate.ipv6, s, 16);
+ nexthop->ifindex = stream_getl(s);
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ stream_get(&nexthop->gate.ipv6, s, 16);
+ nexthop->ifindex = stream_getl(s);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[NEXTHOP_STRLEN];
+ zlog_debug(
+ " nhop via %s",
+ nexthop2str(nexthop, buf, sizeof(buf)));
+ }
+
+ if (nhlist_tail) {
+ nhlist_tail->next = nexthop;
+ nhlist_tail = nexthop;
+ } else {
+ nhlist_tail = nexthop;
+ nhlist_head = nexthop;
+ }
+
+ /* No need to evaluate the nexthop if we have already
+ * determined
+ * that there has been a change.
+ */
+ if (bnc->change_flags & BGP_NEXTHOP_CHANGED)
+ continue;
+
+ for (oldnh = bnc->nexthop; oldnh; oldnh = oldnh->next)
+ if (nexthop_same_no_recurse(oldnh, nexthop))
+ break;
+
+ if (!oldnh)
+ bnc->change_flags |= BGP_NEXTHOP_CHANGED;
+ }
+ bnc_nexthop_free(bnc);
+ bnc->nexthop = nhlist_head;
+ } else {
+ bnc->flags &= ~BGP_NEXTHOP_VALID;
+ bnc->nexthop_num = nexthop_num;
+
+ /* notify bgp fsm if nbr ip goes from valid->invalid */
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+
+ bnc_nexthop_free(bnc);
+ bnc->nexthop = NULL;
+ }
+
+ evaluate_paths(bnc);
}
/**
* make_prefix - make a prefix structure from the path (essentially
* path's node.
*/
-static int
-make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
+static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p)
{
- int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) &&
- (ri->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0;
-
- memset (p, 0, sizeof (struct prefix));
- switch (afi)
- {
- case AFI_IP:
- p->family = AF_INET;
- if (is_bgp_static)
- {
- p->u.prefix4 = ri->net->p.u.prefix4;
- p->prefixlen = ri->net->p.prefixlen;
- }
- else
- {
- p->u.prefix4 = ri->attr->nexthop;
- p->prefixlen = IPV4_MAX_BITLEN;
- }
- break;
- case AFI_IP6:
- /* We don't register link local NH */
- if (ri->attr->extra->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL
- || IN6_IS_ADDR_LINKLOCAL (&ri->attr->extra->mp_nexthop_global))
- return -1;
-
- p->family = AF_INET6;
-
- if (is_bgp_static)
- {
- p->u.prefix6 = ri->net->p.u.prefix6;
- p->prefixlen = ri->net->p.prefixlen;
- }
- else
- {
- p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
- p->prefixlen = IPV6_MAX_BITLEN;
- }
- break;
- default:
- if (BGP_DEBUG(nht, NHT))
- {
- zlog_debug("%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
- __FUNCTION__, afi, AFI_IP, AFI_IP6);
+ int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP)
+ && (ri->sub_type == BGP_ROUTE_STATIC))
+ ? 1
+ : 0;
+
+ memset(p, 0, sizeof(struct prefix));
+ switch (afi) {
+ case AFI_IP:
+ p->family = AF_INET;
+ if (is_bgp_static) {
+ p->u.prefix4 = ri->net->p.u.prefix4;
+ p->prefixlen = ri->net->p.prefixlen;
+ } else {
+ p->u.prefix4 = ri->attr->nexthop;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ }
+ break;
+ case AFI_IP6:
+ /* We don't register link local NH */
+ if (ri->attr->extra->mp_nexthop_len
+ != BGP_ATTR_NHLEN_IPV6_GLOBAL
+ || IN6_IS_ADDR_LINKLOCAL(
+ &ri->attr->extra->mp_nexthop_global))
+ return -1;
+
+ p->family = AF_INET6;
+
+ if (is_bgp_static) {
+ p->u.prefix6 = ri->net->p.u.prefix6;
+ p->prefixlen = ri->net->p.prefixlen;
+ } else {
+ p->u.prefix6 = ri->attr->extra->mp_nexthop_global;
+ p->prefixlen = IPV6_MAX_BITLEN;
+ }
+ break;
+ default:
+ if (BGP_DEBUG(nht, NHT)) {
+ zlog_debug(
+ "%s: Attempting to make prefix with unknown AFI %d (not %d or %d)",
+ __FUNCTION__, afi, AFI_IP, AFI_IP6);
+ }
+ break;
}
- break;
- }
- return 0;
+ return 0;
}
/**
@@ -569,58 +545,56 @@ make_prefix (int afi, struct bgp_info *ri, struct prefix *p)
* RETURNS:
* void.
*/
-static void
-sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
+static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
{
- struct stream *s;
- struct prefix *p;
- int ret;
-
- /* Check socket. */
- if (!zclient || zclient->sock < 0)
- return;
-
- /* Don't try to register if Zebra doesn't know of this instance. */
- if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
- return;
-
- p = &(bnc->node->p);
- s = zclient->obuf;
- stream_reset (s);
- zclient_create_header (s, command, bnc->bgp->vrf_id);
- if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ||
- CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
- stream_putc(s, 1);
- else
- stream_putc(s, 0);
-
- stream_putw(s, PREFIX_FAMILY(p));
- stream_putc(s, p->prefixlen);
- switch (PREFIX_FAMILY(p))
- {
- case AF_INET:
- stream_put_in_addr (s, &p->u.prefix4);
- break;
- case AF_INET6:
- stream_put(s, &(p->u.prefix6), 16);
- break;
- default:
- break;
- }
- stream_putw_at (s, 0, stream_get_endp (s));
-
- ret = zclient_send_message(zclient);
- /* TBD: handle the failure */
- if (ret < 0)
- zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
-
- if ((command == ZEBRA_NEXTHOP_REGISTER) ||
- (command == ZEBRA_IMPORT_ROUTE_REGISTER))
- SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- else if ((command == ZEBRA_NEXTHOP_UNREGISTER) ||
- (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
- UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
- return;
+ struct stream *s;
+ struct prefix *p;
+ int ret;
+
+ /* Check socket. */
+ if (!zclient || zclient->sock < 0)
+ return;
+
+ /* Don't try to register if Zebra doesn't know of this instance. */
+ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
+ return;
+
+ p = &(bnc->node->p);
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s, command, bnc->bgp->vrf_id);
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
+ || CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
+ stream_putc(s, 1);
+ else
+ stream_putc(s, 0);
+
+ stream_putw(s, PREFIX_FAMILY(p));
+ stream_putc(s, p->prefixlen);
+ switch (PREFIX_FAMILY(p)) {
+ case AF_INET:
+ stream_put_in_addr(s, &p->u.prefix4);
+ break;
+ case AF_INET6:
+ stream_put(s, &(p->u.prefix6), 16);
+ break;
+ default:
+ break;
+ }
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ ret = zclient_send_message(zclient);
+ /* TBD: handle the failure */
+ if (ret < 0)
+ zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
+
+ if ((command == ZEBRA_NEXTHOP_REGISTER)
+ || (command == ZEBRA_IMPORT_ROUTE_REGISTER))
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
+ || (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
+ return;
}
/**
@@ -631,16 +605,16 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
* RETURNS:
* void.
*/
-static void
-register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
+static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
+ int is_bgp_import_route)
{
- /* Check if we have already registered */
- if (bnc->flags & BGP_NEXTHOP_REGISTERED)
- return;
- if (is_bgp_import_route)
- sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
- else
- sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
+ /* Check if we have already registered */
+ if (bnc->flags & BGP_NEXTHOP_REGISTERED)
+ return;
+ if (is_bgp_import_route)
+ sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
+ else
+ sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
}
/**
@@ -650,17 +624,17 @@ register_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
* RETURNS:
* void.
*/
-static void
-unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
+static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
+ int is_bgp_import_route)
{
- /* Check if we have already registered */
- if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
- return;
-
- if (is_bgp_import_route)
- sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
- else
- sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
+ /* Check if we have already registered */
+ if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+ return;
+
+ if (is_bgp_import_route)
+ sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
+ else
+ sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
}
/**
@@ -670,75 +644,71 @@ unregister_zebra_rnh (struct bgp_nexthop_cache *bnc, int is_bgp_import_route)
* RETURNS:
* void.
*/
-static void
-evaluate_paths (struct bgp_nexthop_cache *bnc)
+static void evaluate_paths(struct bgp_nexthop_cache *bnc)
{
- struct bgp_node *rn;
- struct bgp_info *path;
- struct bgp *bgp = bnc->bgp;
- int afi;
- struct peer *peer = (struct peer *)bnc->nht_info;
-
- if (BGP_DEBUG(nht, NHT))
- {
- char buf[PREFIX2STR_BUFFER];
- bnc_str(bnc, buf, PREFIX2STR_BUFFER);
- zlog_debug("NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
- buf, bnc->flags, bnc->change_flags);
- }
-
- LIST_FOREACH(path, &(bnc->paths), nh_thread)
- {
- if (!(path->type == ZEBRA_ROUTE_BGP &&
- ((path->sub_type == BGP_ROUTE_NORMAL) ||
- (path->sub_type == BGP_ROUTE_STATIC))))
- continue;
-
- rn = path->net;
- afi = family2afi(rn->p.family);
-
- /* Path becomes valid/invalid depending on whether the nexthop
- * reachable/unreachable.
- */
- if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) !=
- (bgp_isvalid_nexthop(bnc) ? 1 : 0))
- {
- if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
- {
- bgp_aggregate_decrement (bgp, &rn->p, path,
- afi, SAFI_UNICAST);
- bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
- }
- else
- {
- bgp_info_set_flag (rn, path, BGP_INFO_VALID);
- bgp_aggregate_increment (bgp, &rn->p, path,
- afi, SAFI_UNICAST);
- }
+ struct bgp_node *rn;
+ struct bgp_info *path;
+ struct bgp *bgp = bnc->bgp;
+ int afi;
+ struct peer *peer = (struct peer *)bnc->nht_info;
+
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf[PREFIX2STR_BUFFER];
+ bnc_str(bnc, buf, PREFIX2STR_BUFFER);
+ zlog_debug(
+ "NH update for %s - flags 0x%x chgflags 0x%x - evaluate paths",
+ buf, bnc->flags, bnc->change_flags);
}
- /* Copy the metric to the path. Will be used for bestpath computation */
- if (bgp_isvalid_nexthop(bnc) && bnc->metric)
- (bgp_info_extra_get(path))->igpmetric = bnc->metric;
- else if (path->extra)
- path->extra->igpmetric = 0;
-
- if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ||
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
- SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
-
- bgp_process(bgp, rn, afi, SAFI_UNICAST);
- }
+ LIST_FOREACH(path, &(bnc->paths), nh_thread)
+ {
+ if (!(path->type == ZEBRA_ROUTE_BGP
+ && ((path->sub_type == BGP_ROUTE_NORMAL)
+ || (path->sub_type == BGP_ROUTE_STATIC))))
+ continue;
+
+ rn = path->net;
+ afi = family2afi(rn->p.family);
+
+ /* Path becomes valid/invalid depending on whether the nexthop
+ * reachable/unreachable.
+ */
+ if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0)
+ != (bgp_isvalid_nexthop(bnc) ? 1 : 0)) {
+ if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) {
+ bgp_aggregate_decrement(bgp, &rn->p, path, afi,
+ SAFI_UNICAST);
+ bgp_info_unset_flag(rn, path, BGP_INFO_VALID);
+ } else {
+ bgp_info_set_flag(rn, path, BGP_INFO_VALID);
+ bgp_aggregate_increment(bgp, &rn->p, path, afi,
+ SAFI_UNICAST);
+ }
+ }
+
+ /* Copy the metric to the path. Will be used for bestpath
+ * computation */
+ if (bgp_isvalid_nexthop(bnc) && bnc->metric)
+ (bgp_info_extra_get(path))->igpmetric = bnc->metric;
+ else if (path->extra)
+ path->extra->igpmetric = 0;
+
+ if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
+ || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
+ SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
+
+ bgp_process(bgp, rn, afi, SAFI_UNICAST);
+ }
- if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))
- {
- if (BGP_DEBUG(nht, NHT))
- zlog_debug("%s: Updating peer (%s) status with NHT", __FUNCTION__, peer->host);
- bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc));
- SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
- }
+ if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s: Updating peer (%s) status with NHT",
+ __FUNCTION__, peer->host);
+ bgp_fsm_nht_update(peer, bgp_isvalid_nexthop(bnc));
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+ }
- RESET_FLAG(bnc->change_flags);
+ RESET_FLAG(bnc->change_flags);
}
/**
@@ -749,19 +719,17 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
* make - if set, make the association. if unset, just break the existing
* association.
*/
-static void
-path_nh_map (struct bgp_info *path, struct bgp_nexthop_cache *bnc, int make)
+static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc,
+ int make)
{
- if (path->nexthop)
- {
- LIST_REMOVE(path, nh_thread);
- path->nexthop->path_count--;
- path->nexthop = NULL;
- }
- if (make)
- {
- LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
- path->nexthop = bnc;
- path->nexthop->path_count++;
- }
+ if (path->nexthop) {
+ LIST_REMOVE(path, nh_thread);
+ path->nexthop->path_count--;
+ path->nexthop = NULL;
+ }
+ if (make) {
+ LIST_INSERT_HEAD(&(bnc->paths), path, nh_thread);
+ path->nexthop = bnc;
+ path->nexthop->path_count++;
+ }
}