summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c110
1 files changed, 86 insertions, 24 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 357f112821..c05d69a2dd 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -365,7 +365,7 @@ int is_zebra_valid_kernel_table(uint32_t table_id)
int is_zebra_main_routing_table(uint32_t table_id)
{
- if (table_id == RT_TABLE_MAIN)
+ if (table_id == rt_table_main_id)
return 1;
return 0;
}
@@ -428,18 +428,29 @@ int route_entry_update_nhe(struct route_entry *re,
done:
/* Detach / deref previous nhg */
- if (old_nhg)
+
+ if (old_nhg) {
+ /*
+ * Return true if we are deleting the previous NHE
+ * Note: we dont check the return value of the function anywhere
+ * except at rib_handle_nhg_replace().
+ */
+ if (old_nhg->refcnt == 1)
+ ret = 1;
+
zebra_nhg_decrement_ref(old_nhg);
+ }
return ret;
}
-void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
- struct nhg_hash_entry *new_entry)
+int rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
+ struct nhg_hash_entry *new_entry)
{
struct zebra_router_table *zrt;
struct route_node *rn;
struct route_entry *re, *next;
+ int ret = 0;
if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: replacing routes nhe (%u) OLD %p NEW %p",
@@ -451,10 +462,17 @@ void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (re->nhe && re->nhe == old_entry)
- route_entry_update_nhe(re, new_entry);
+ ret += route_entry_update_nhe(re,
+ new_entry);
}
}
}
+
+ /*
+ * if ret > 0, some previous re->nhe has freed the address to which
+ * old_entry is pointing.
+ */
+ return ret;
}
struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
@@ -1438,7 +1456,7 @@ static void zebra_rib_evaluate_mpls(struct route_node *rn)
*/
static bool rib_route_match_ctx(const struct route_entry *re,
const struct zebra_dplane_ctx *ctx,
- bool is_update)
+ bool is_update, bool async)
{
bool result = false;
@@ -1454,13 +1472,12 @@ static bool rib_route_match_ctx(const struct route_entry *re,
/* We use an extra test for statics, and another for
* kernel routes.
*/
- if (re->type == ZEBRA_ROUTE_STATIC &&
+ if (re->type == ZEBRA_ROUTE_STATIC && !async &&
(re->distance != dplane_ctx_get_old_distance(ctx) ||
re->tag != dplane_ctx_get_old_tag(ctx))) {
result = false;
} else if (re->type == ZEBRA_ROUTE_KERNEL &&
- re->metric !=
- dplane_ctx_get_old_metric(ctx)) {
+ re->metric != dplane_ctx_get_old_metric(ctx)) {
result = false;
}
}
@@ -1482,7 +1499,7 @@ static bool rib_route_match_ctx(const struct route_entry *re,
/* We use an extra test for statics, and another for
* kernel routes.
*/
- if (re->type == ZEBRA_ROUTE_STATIC &&
+ if (re->type == ZEBRA_ROUTE_STATIC && !async &&
(re->distance != dplane_ctx_get_distance(ctx) ||
re->tag != dplane_ctx_get_tag(ctx))) {
result = false;
@@ -1946,13 +1963,13 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
RNODE_FOREACH_RE(rn, rib) {
if (re == NULL) {
- if (rib_route_match_ctx(rib, ctx, false))
+ if (rib_route_match_ctx(rib, ctx, false, false))
re = rib;
}
/* Check for old route match */
if (is_update && (old_re == NULL)) {
- if (rib_route_match_ctx(rib, ctx, true /*is_update*/))
+ if (rib_route_match_ctx(rib, ctx, true, false))
old_re = rib;
}
@@ -2183,6 +2200,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_TC_FILTER_ADD:
case DPLANE_OP_TC_FILTER_DELETE:
case DPLANE_OP_TC_FILTER_UPDATE:
+ case DPLANE_OP_STARTUP_STAGE:
break;
}
@@ -2271,7 +2289,7 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
* info.
*/
RNODE_FOREACH_RE(rn, re) {
- if (rib_route_match_ctx(re, ctx, false /*!update*/))
+ if (rib_route_match_ctx(re, ctx, false, true))
break;
}
@@ -2706,6 +2724,8 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
return;
}
} else {
+ struct nexthop *tmp_nh;
+
/* Lookup nhe from route information */
nhe = zebra_nhg_rib_find_nhe(ere->re_nhe, ere->afi);
if (!nhe) {
@@ -2723,6 +2743,22 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
early_route_memory_free(ere);
return;
}
+ for (ALL_NEXTHOPS(nhe->nhg, tmp_nh)) {
+ if (CHECK_FLAG(tmp_nh->flags, NEXTHOP_FLAG_EVPN)) {
+ struct ipaddr vtep_ip = {};
+
+ if (ere->afi == AFI_IP) {
+ vtep_ip.ipa_type = IPADDR_V4;
+ vtep_ip.ipaddr_v4 = tmp_nh->gate.ipv4;
+ } else {
+ vtep_ip.ipa_type = IPADDR_V6;
+ vtep_ip.ipaddr_v6 = tmp_nh->gate.ipv6;
+ }
+ zebra_rib_queue_evpn_route_add(
+ re->vrf_id, &tmp_nh->rmac, &vtep_ip,
+ &ere->p);
+ }
+ }
}
/*
@@ -2824,8 +2860,13 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
rib_addnode(rn, re, 1);
/* Free implicit route.*/
- if (same)
+ if (same) {
+ rib_dest_t *dest = rn->info;
+
+ if (same == dest->selected_fib)
+ SET_FLAG(same->status, ROUTE_ENTRY_ROUTE_REPLACING);
rib_delnode(rn, same);
+ }
/* See if we can remove some RE entries that are queued for
* removal, but won't be considered in rib processing.
@@ -3232,12 +3273,26 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
return -1;
/* Invariant: at this point we always have rn->info set. */
- if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
- RIB_ROUTE_QUEUED(qindex))) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ /* A route node must only be in one sub-queue at a time. */
+ if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK)) {
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
+ /*
+ * curr_qindex_bitmask is power of 2, because a route node must only be in one sub-queue at a time,
+ * so for getting current sub-queue index from bitmask we may use part of classic msb function
+ * (find most significant set bit).
+ */
+ const uint32_t curr_qindex_bitmask = CHECK_FLAG(rib_dest_from_rnode(rn)->flags, MQ_BIT_MASK);
+ static const uint8_t pos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19,
+ 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
+
+ curr_qindex = pos[(uint32_t)(curr_qindex_bitmask * 0x077CB531UL) >> 27];
+
rnode_debug(rn, re->vrf_id,
"rn %p is already queued in sub-queue %s",
- (void *)rn, subqueue2str(qindex));
+ (void *)rn, subqueue2str(curr_qindex));
+ }
+
return -1;
}
@@ -3978,6 +4033,10 @@ void rib_delnode(struct route_node *rn, struct route_entry *re)
if (IS_ZEBRA_DEBUG_RIB)
rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing",
(void *)rn, (void *)re);
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ route_entry_dump(&rn->p, NULL, re);
+
SET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
afi = (rn->p.family == AF_INET)
@@ -4123,8 +4182,8 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
zclient_dump_route_flags(re->flags, flags_buf,
sizeof(flags_buf)),
_dump_re_status(re, status_buf, sizeof(status_buf)));
- zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
- nexthop_group_nexthop_num(&(re->nhe->nhg)),
+ zlog_debug("%s: tag == %u, nexthop_num == %u, nexthop_active_num == %u",
+ straddr, re->tag, nexthop_group_nexthop_num(&(re->nhe->nhg)),
nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
/* Dump nexthops */
@@ -4161,10 +4220,10 @@ static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
mq->size++;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- "Route %pFX(%u) queued for processing into sub-queue %s",
- &ere->p, ere->re->vrf_id,
- subqueue2str(META_QUEUE_EARLY_ROUTE));
+ zlog_debug("Route %pFX(%u) (%s) queued for processing into sub-queue %s",
+ &ere->p, ere->re->vrf_id,
+ ere->deletion ? "delete" : "add",
+ subqueue2str(META_QUEUE_EARLY_ROUTE));
return 0;
}
@@ -4859,6 +4918,9 @@ static void rib_process_dplane_results(struct event *thread)
case DPLANE_OP_GRE_SET:
case DPLANE_OP_NONE:
break;
+ case DPLANE_OP_STARTUP_STAGE:
+ zebra_ns_startup_continue(ctx);
+ break;
} /* Dispatch by op code */