]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_nht.c
Merge pull request #3087 from opensourcerouting/bfd-memleak
[mirror_frr.git] / bgpd / bgp_nht.c
index 3d2a4ee0dde9db8b1b1995d5ec758f6042214d1e..dd1ffe9f3bd4540132c3d42d1ee24b742e9adcf4 100644 (file)
@@ -97,7 +97,7 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
                }
                unregister_zebra_rnh(bnc,
                                     CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
-               bnc->node->info = NULL;
+               bgp_nexthop_set_node_info(bnc->node, NULL);
                bgp_unlock_node(bnc->node);
                bnc->node = NULL;
                bnc_free(bnc);
@@ -128,11 +128,10 @@ void bgp_unlink_nexthop_by_peer(struct peer *peer)
 
        rn = bgp_node_get(peer->bgp->nexthop_cache_table[afi], &p);
 
-       if (!rn->info)
+       bnc = bgp_nexthop_get_node_info(rn);
+       if (!bnc)
                return;
 
-       bnc = rn->info;
-
        /* cleanup the peer reference */
        bnc->nht_info = NULL;
 
@@ -191,9 +190,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
        else
                rn = bgp_node_get(bgp_nexthop->nexthop_cache_table[afi], &p);
 
-       if (!rn->info) {
+       bnc = bgp_nexthop_get_node_info(rn);
+       if (!bnc) {
                bnc = bnc_new();
-               rn->info = bnc;
+               bgp_nexthop_set_node_info(rn, bnc);
                bnc->node = rn;
                bnc->bgp = bgp_nexthop;
                bgp_lock_node(rn);
@@ -205,7 +205,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                }
        }
 
-       bnc = rn->info;
        bgp_unlock_node(rn);
        if (is_bgp_static_route) {
                SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
@@ -297,16 +296,21 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
 
        rn = bgp_node_lookup(
                peer->bgp->nexthop_cache_table[family2afi(p.family)], &p);
-       if (!rn || !rn->info) {
+       if (!rn) {
                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;
+       bnc = bgp_nexthop_get_node_info(rn);
+       if (!bnc) {
+               if (BGP_DEBUG(nht, NHT))
+                       zlog_debug("Cannot find connected NHT node for peer %s on route_node as expected",
+                                  peer->host);
+               bgp_unlock_node(rn);
+               return;
+       }
        bgp_unlock_node(rn);
 
        if (bnc->nht_info != peer) {
@@ -324,7 +328,7 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer)
                        zlog_debug("Freeing connected NHT node %p for peer %s",
                                   bnc, peer->host);
                unregister_zebra_rnh(bnc, 0);
-               bnc->node->info = NULL;
+               bgp_nexthop_set_node_info(bnc->node, NULL);
                bgp_unlock_node(bnc->node);
                bnc_free(bnc);
        }
@@ -367,19 +371,29 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
                        bgp->import_check_table[family2afi(nhr.prefix.family)],
                        &nhr.prefix);
 
-       if (!rn || !rn->info) {
+       if (!rn) {
                if (BGP_DEBUG(nht, NHT)) {
                        char buf[PREFIX2STR_BUFFER];
                        prefix2str(&nhr.prefix, buf, sizeof(buf));
                        zlog_debug("parse nexthop update(%s): rn not found",
                                   buf);
                }
-               if (rn)
-                       bgp_unlock_node(rn);
                return;
        }
 
-       bnc = rn->info;
+       bnc = bgp_nexthop_get_node_info(rn);
+       if (!bnc) {
+               if (BGP_DEBUG(nht, NHT)) {
+                       char buf[PREFIX2STR_BUFFER];
+
+                       prefix2str(&nhr.prefix, buf, sizeof(buf));
+                       zlog_debug("parse nexthop update(%s): bnc node info not found",
+                                  buf);
+               }
+               bgp_unlock_node(rn);
+               return;
+       }
+
        bgp_unlock_node(rn);
        bnc->last_update = bgp_clock();
        bnc->change_flags = 0;
@@ -401,6 +415,8 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
                bnc->change_flags |= BGP_NEXTHOP_CHANGED;
 
        if (nhr.nexthop_num) {
+               struct peer *peer = bnc->nht_info;
+
                /* notify bgp fsm if nbr ip goes from invalid->valid */
                if (!bnc->nexthop_num)
                        UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
@@ -416,6 +432,22 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
 
                        nexthop = nexthop_from_zapi_nexthop(&nhr.nexthops[i]);
 
+                       /*
+                        * Turn on RA for the v6 nexthops
+                        * we receive from bgp.  This is to allow us
+                        * to work with v4 routing over v6 nexthops
+                        */
+                       if (peer &&
+                           CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
+                           && nhr.prefix.family == AF_INET6) {
+                               struct interface *ifp;
+
+                               ifp = if_lookup_by_index(nexthop->ifindex,
+                                                        nexthop->vrf_id);
+                               zclient_send_interface_radv_req(
+                                       zclient, nexthop->vrf_id, ifp, true,
+                                       BGP_UNNUM_DEFAULT_RA_INTERVAL);
+                       }
                        /* There is at least one label-switched path */
                        if (nexthop->nh_label &&
                                nexthop->nh_label->num_labels) {
@@ -487,7 +519,7 @@ void bgp_cleanup_nexthops(struct bgp *bgp)
 
                for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
                     rn = bgp_route_next(rn)) {
-                       bnc = rn->info;
+                       bnc = bgp_nexthop_get_node_info(rn);
                        if (!bnc)
                                continue;