]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_rib.c
*: conform with COMMUNITY.md formatting rules, via 'make indent'
[mirror_frr.git] / zebra / zebra_rib.c
index b7b4a159dac58af7fac02465fabf15b7bf0b8fc0..8946c9c6b55b1670b8415b897a39dc6c85382c19 100644 (file)
@@ -86,6 +86,7 @@ static const struct {
                [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20},
                [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20},
                [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100},
+               [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150},
 
        /* no entry/default: 150 */
 };
@@ -212,13 +213,15 @@ void route_entry_nexthop_delete(struct route_entry *re, struct nexthop *nexthop)
 
 
 struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re,
-                                               ifindex_t ifindex)
+                                               ifindex_t ifindex,
+                                               vrf_id_t nh_vrf_id)
 {
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
        nexthop->type = NEXTHOP_TYPE_IFINDEX;
        nexthop->ifindex = ifindex;
+       nexthop->vrf_id = nh_vrf_id;
 
        route_entry_nexthop_add(re, nexthop);
 
@@ -227,12 +230,14 @@ struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re,
 
 struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re,
                                             struct in_addr *ipv4,
-                                            struct in_addr *src)
+                                            struct in_addr *src,
+                                            vrf_id_t nh_vrf_id)
 {
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
        nexthop->type = NEXTHOP_TYPE_IPV4;
+       nexthop->vrf_id = nh_vrf_id;
        nexthop->gate.ipv4 = *ipv4;
        if (src)
                nexthop->src.ipv4 = *src;
@@ -245,23 +250,25 @@ struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re,
 struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
                                                     struct in_addr *ipv4,
                                                     struct in_addr *src,
-                                                    ifindex_t ifindex)
+                                                    ifindex_t ifindex,
+                                                    vrf_id_t nh_vrf_id)
 {
        struct nexthop *nexthop;
        struct interface *ifp;
 
        nexthop = nexthop_new();
+       nexthop->vrf_id = nh_vrf_id;
        nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
        nexthop->gate.ipv4 = *ipv4;
        if (src)
                nexthop->src.ipv4 = *src;
        nexthop->ifindex = ifindex;
-       ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
+       ifp = if_lookup_by_index(nexthop->ifindex, nh_vrf_id);
        /*Pending: need to think if null ifp here is ok during bootup?
          There was a crash because ifp here was coming to be NULL */
        if (ifp)
-               if (connected_is_unnumbered(ifp) ||
-                   CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
+               if (connected_is_unnumbered(ifp)
+                   || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
                }
 
@@ -271,11 +278,13 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
 }
 
 struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re,
-                                            struct in6_addr *ipv6)
+                                            struct in6_addr *ipv6,
+                                            vrf_id_t nh_vrf_id)
 {
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
+       nexthop->vrf_id = nh_vrf_id;
        nexthop->type = NEXTHOP_TYPE_IPV6;
        nexthop->gate.ipv6 = *ipv6;
 
@@ -286,11 +295,13 @@ struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re,
 
 struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
                                                     struct in6_addr *ipv6,
-                                                    ifindex_t ifindex)
+                                                    ifindex_t ifindex,
+                                                    vrf_id_t nh_vrf_id)
 {
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
+       nexthop->vrf_id = nh_vrf_id;
        nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
        nexthop->gate.ipv6 = *ipv6;
        nexthop->ifindex = ifindex;
@@ -306,6 +317,7 @@ struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
        struct nexthop *nexthop;
 
        nexthop = nexthop_new();
+       nexthop->vrf_id = VRF_DEFAULT;
        nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
        nexthop->bh_type = bh_type;
 
@@ -322,6 +334,7 @@ static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop,
        resolved_hop = nexthop_new();
        SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ACTIVE);
 
+       resolved_hop->vrf_id = nexthop->vrf_id;
        switch (newhop->type) {
        case NEXTHOP_TYPE_IPV4:
        case NEXTHOP_TYPE_IPV4_IFINDEX:
@@ -403,8 +416,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
 
        if (set) {
                UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
-               zebra_deregister_rnh_static_nexthops(re->nh_vrf_id,
-                                                    nexthop->resolved, top);
                nexthops_free(nexthop->resolved);
                nexthop->resolved = NULL;
                re->nexthop_mtu = 0;
@@ -422,7 +433,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
         * address in the routing table.
         */
        if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
-               ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
+               ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
                if (ifp && connected_is_unnumbered(ifp)) {
                        if (if_is_operative(ifp))
                                return 1;
@@ -450,7 +461,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                break;
        }
        /* Lookup table.  */
-       table = zebra_vrf_table(afi, SAFI_UNICAST, re->nh_vrf_id);
+       table = zebra_vrf_table(afi, SAFI_UNICAST, nexthop->vrf_id);
        if (!table)
                return 0;
 
@@ -464,22 +475,22 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                 * host route.
                 */
                if (top && rn == top)
-                       if (((afi == AFI_IP) && (rn->p.prefixlen != 32)) ||
-                           ((afi == AFI_IP6) && (rn->p.prefixlen != 128)))
+                       if (((afi == AFI_IP) && (rn->p.prefixlen != 32))
+                           || ((afi == AFI_IP6) && (rn->p.prefixlen != 128)))
                                return 0;
 
                /* Pick up selected route. */
                /* However, do not resolve over default route unless explicitly
                 * allowed. */
                if (is_default_prefix(&rn->p)
-                   && !nh_resolve_via_default(p.family))
+                   && !rnh_resolve_via_default(p.family))
                        return 0;
 
                dest = rib_dest_from_rnode(rn);
-               if (dest && dest->selected_fib &&
-                   !CHECK_FLAG(dest->selected_fib->status,
-                               ROUTE_ENTRY_REMOVED) &&
-                   dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
+               if (dest && dest->selected_fib
+                   && !CHECK_FLAG(dest->selected_fib->status,
+                                  ROUTE_ENTRY_REMOVED)
+                   && dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
                        match = dest->selected_fib;
 
                /* If there is no selected route or matched route is EGP, go up
@@ -503,7 +514,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
                                        nexthop->ifindex = newhop->ifindex;
                        }
                        return 1;
-               } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
+               } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
                        resolved = 0;
                        for (ALL_NEXTHOPS(match->nexthop, newhop)) {
                                if (!CHECK_FLAG(newhop->flags,
@@ -583,8 +594,9 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
                route_unlock_node(rn);
 
                dest = rib_dest_from_rnode(rn);
-               if (dest && dest->selected_fib &&
-                   !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+               if (dest && dest->selected_fib
+                   && !CHECK_FLAG(dest->selected_fib->status,
+                                  ROUTE_ENTRY_REMOVED))
                        match = dest->selected_fib;
 
                /* If there is no selected route or matched route is EGP, go up
@@ -711,8 +723,8 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
        route_unlock_node(rn);
        dest = rib_dest_from_rnode(rn);
 
-       if (dest && dest->selected_fib &&
-           !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+       if (dest && dest->selected_fib
+           && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
                match = dest->selected_fib;
 
        if (!match)
@@ -768,8 +780,8 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
 
        /* Find out if a "selected" RR for the discovered RIB entry exists ever.
         */
-       if (dest && dest->selected_fib &&
-           !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+       if (dest && dest->selected_fib
+           && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
                match = dest->selected_fib;
 
        /* None such found :( */
@@ -838,7 +850,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
                family = 0;
        switch (nexthop->type) {
        case NEXTHOP_TYPE_IFINDEX:
-               ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
+               ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
                if (ifp && if_is_operative(ifp))
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
                else
@@ -867,7 +879,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
                        family = AFI_IP6;
                if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) {
                        ifp = if_lookup_by_index(nexthop->ifindex,
-                                                re->nh_vrf_id);
+                                                nexthop->vrf_id);
                        if (ifp && if_is_operative(ifp))
                                SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
                        else
@@ -910,8 +922,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
        memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
 
        /* It'll get set if required inside */
-       ret = zebra_route_map_check(family, re->type, p, nexthop, re->nh_vrf_id,
-                                   re->tag);
+       ret = zebra_route_map_check(family, re->type, p, nexthop,
+                                   nexthop->vrf_id, re->tag);
        if (ret == RMAP_DENYMATCH) {
                if (IS_ZEBRA_DEBUG_RIB) {
                        srcdest_rnode2str(rn, buf, sizeof(buf));
@@ -919,7 +931,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
                                "%u:%s: Filtering out with NH out %s due to route map",
                                re->vrf_id, buf,
                                ifindex2ifname(nexthop->ifindex,
-                                              re->nh_vrf_id));
+                                              nexthop->vrf_id));
                }
                UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
        }
@@ -1020,8 +1032,7 @@ void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
                        else
                                UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
                }
-               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
-                                        p, ZAPI_ROUTE_INSTALLED);
+               zsend_route_notify_owner(re, p, ZAPI_ROUTE_INSTALLED);
                break;
        case SOUTHBOUND_INSTALL_FAILURE:
                /*
@@ -1031,8 +1042,7 @@ void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p,
                 */
                dest->selected_fib = re;
 
-               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
-                                        p, ZAPI_ROUTE_FAIL_INSTALL);
+               zsend_route_notify_owner(re, p, ZAPI_ROUTE_FAIL_INSTALL);
                zlog_warn("%u:%s: Route install failed", re->vrf_id,
                          prefix2str(p, buf, sizeof(buf)));
                break;
@@ -1082,13 +1092,13 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
                struct nexthop *prev;
 
                for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
-                       UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
+                       UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
                        for (ALL_NEXTHOPS(re->nexthop, prev)) {
                                if (prev == nexthop)
                                        break;
-                               if (nexthop_same_firsthop (nexthop, prev))
-                               {
-                                       SET_FLAG (nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
+                               if (nexthop_same_firsthop(nexthop, prev)) {
+                                       SET_FLAG(nexthop->flags,
+                                                NEXTHOP_FLAG_DUPLICATE);
                                        break;
                                }
                        }
@@ -1099,10 +1109,8 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
         * If this is a replace to a new RE let the originator of the RE
         * know that they've lost
         */
-       if (old && old != re)
-               zsend_route_notify_owner(old->type, old->instance,
-                                        old->vrf_id, p,
-                                        ZAPI_ROUTE_BETTER_ADMIN_WON);
+       if (old && (old != re) && (old->type != re->type))
+               zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON);
 
        /*
         * Make sure we update the FPM any time we send new information to
@@ -1137,7 +1145,8 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
         */
        hook_call(rib_update, rn, "uninstalling from kernel");
        kernel_route_rib(rn, p, src_p, re, NULL);
-       zvrf->removals++;
+       if (zvrf)
+               zvrf->removals++;
 
        return;
 }
@@ -2102,7 +2111,9 @@ void rib_unlink(struct route_node *rn, struct route_entry *re)
                dest->selected_fib = NULL;
 
        /* free RE and nexthops */
-       zebra_deregister_rnh_static_nexthops(re->vrf_id, re->nexthop, rn);
+       if (re->type == ZEBRA_ROUTE_STATIC)
+               zebra_deregister_rnh_static_nexthops(re->vrf_id, re->nexthop,
+                                                    rn);
        nexthops_free(re->nexthop);
        XFREE(MTYPE_RE, re);
 }
@@ -2329,8 +2340,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
                        continue;
                if (same->instance != re->instance)
                        continue;
-               if (same->type == ZEBRA_ROUTE_KERNEL &&
-                   same->metric != re->metric)
+               if (same->type == ZEBRA_ROUTE_KERNEL
+                   && same->metric != re->metric)
                        continue;
                /*
                 * We should allow duplicate connected routes because of
@@ -2426,8 +2437,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
                        continue;
                if (re->instance != instance)
                        continue;
-               if (re->type == ZEBRA_ROUTE_KERNEL &&
-                   re->metric != metric)
+               if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric)
                        continue;
                if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->nexthop)
                    && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
@@ -2522,9 +2532,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
        }
 
        if (same) {
-               if (fromkernel &&
-                   CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) &&
-                   !allow_delete) {
+               if (fromkernel && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)
+                   && !allow_delete) {
                        rib_install_kernel(rn, same, NULL);
                        route_unlock_node(rn);
 
@@ -2554,10 +2563,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
 }
 
 
-int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
-           int type, u_short instance, int flags, struct prefix *p,
-           struct prefix_ipv6 *src_p, const struct nexthop *nh,
-           u_int32_t table_id, u_int32_t metric,
+int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
+           int flags, struct prefix *p, struct prefix_ipv6 *src_p,
+           const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
            u_int32_t mtu, uint8_t distance, route_tag_t tag)
 {
        struct route_entry *re;
@@ -2573,7 +2581,6 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
        re->mtu = mtu;
        re->table = table_id;
        re->vrf_id = vrf_id;
-       re->nh_vrf_id = nh_vrf_id;
        re->nexthop_num = 0;
        re->uptime = time(NULL);
        re->tag = tag;
@@ -2602,9 +2609,8 @@ static void rib_update_table(struct route_table *table,
                 * has already been queued  we don't
                 * need to queue it up again
                 */
-               if (rn->info
-                   && CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
-                                 RIB_ROUTE_ANY_QUEUED))
+               if (rn->info && CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
+                                          RIB_ROUTE_ANY_QUEUED))
                        continue;
                switch (event) {
                case RIB_UPDATE_IF_CHANGE:
@@ -2621,10 +2627,10 @@ static void rib_update_table(struct route_table *table,
                        RNODE_FOREACH_RE_SAFE (rn, re, next) {
                                struct nexthop *nh;
 
-                               if (re->type != ZEBRA_ROUTE_SYSTEM &&
-                                   re->type != ZEBRA_ROUTE_KERNEL &&
-                                   re->type != ZEBRA_ROUTE_CONNECT &&
-                                   re->type != ZEBRA_ROUTE_STATIC)
+                               if (re->type != ZEBRA_ROUTE_SYSTEM
+                                   && re->type != ZEBRA_ROUTE_KERNEL
+                                   && re->type != ZEBRA_ROUTE_CONNECT
+                                   && re->type != ZEBRA_ROUTE_STATIC)
                                        continue;
 
                                if (re->type != ZEBRA_ROUTE_STATIC) {