diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 136 |
1 files changed, 85 insertions, 51 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 0e1df1cc35..b31b6a1250 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -71,7 +71,7 @@ extern int allow_delete; /* Each route type's string and default distance value. */ static const struct { int key; - int distance; + uint8_t distance; uint8_t meta_q_map; } route_info[ZEBRA_ROUTE_MAX] = { [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 4}, @@ -98,6 +98,11 @@ static const struct { [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 3}, [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 2}, [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 4}, + [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 4}, + [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 4}, + [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 2}, + [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 4} + /* Any new route type added to zebra, should be mirrored here */ /* no entry/default: 150 */ }; @@ -161,8 +166,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) - || (table_id == zrouter.rtm_table_default)) + if (table_id == RT_TABLE_MAIN) return 1; return 0; } @@ -470,8 +474,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug( "\t%s: Interface %s is not unnumbered", - __PRETTY_FUNCTION__, - ifp ? ifp->name : "Unknown"); + __PRETTY_FUNCTION__, ifp->name); return 0; } } @@ -795,12 +798,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) return NULL; } -#define RIB_SYSTEM_ROUTE(R) \ - ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) - -#define RIB_KERNEL_ROUTE(R) \ - ((R)->type == ZEBRA_ROUTE_KERNEL) - /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored * in nexthop->flags field. The nexthop->ifindex will be updated @@ -959,7 +956,8 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re) * decision point. */ new_active = nexthop_active_check(rn, re, nexthop); - if (new_active && re->nexthop_active_num >= multipath_num) { + if (new_active + && re->nexthop_active_num >= zrouter.multipath_num) { UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); new_active = 0; } @@ -1172,7 +1170,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) */ static int rib_can_delete_dest(rib_dest_t *dest) { - if (dest->routes) { + if (re_list_first(&dest->routes)) { return 0; } @@ -1200,7 +1198,6 @@ static int rib_can_delete_dest(rib_dest_t *dest) void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) { rib_dest_t *dest = rib_dest_from_rnode(rn); - struct listnode *node, *nnode; struct rnh *rnh; /* @@ -1232,7 +1229,7 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq) * nht resolution and as such we need to call the * nexthop tracking evaluation code */ - for (ALL_LIST_ELEMENTS(dest->nht, node, nnode, rnh)) { + frr_each (rnh_list, &dest->nht, rnh) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id); struct prefix *p = &rnh->node->p; @@ -1308,7 +1305,7 @@ int rib_gc_dest(struct route_node *rn) zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence()); dest->rnode = NULL; - list_delete(&dest->nht); + rnh_list_fini(&dest->nht); XFREE(MTYPE_RIB_DEST, dest); rn->info = NULL; @@ -2353,7 +2350,7 @@ rib_dest_t *zebra_rib_create_dest(struct route_node *rn) rib_dest_t *dest; dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t)); - dest->nht = list_new(); + rnh_list_init(&dest->nht); route_lock_node(rn); /* rn route table reference */ rn->info = dest; dest->rnode = rn; @@ -2401,7 +2398,6 @@ rib_dest_t *zebra_rib_create_dest(struct route_node *rn) /* Add RE to head of the route node. */ static void rib_link(struct route_node *rn, struct route_entry *re, int process) { - struct route_entry *head; rib_dest_t *dest; afi_t afi; const char *rmap_name; @@ -2416,12 +2412,7 @@ static void rib_link(struct route_node *rn, struct route_entry *re, int process) dest = zebra_rib_create_dest(rn); } - head = dest->routes; - if (head) { - head->prev = re; - } - re->next = head; - dest->routes = re; + re_list_add_head(&dest->routes, re); afi = (rn->p.family == AF_INET) ? AFI_IP @@ -2471,14 +2462,7 @@ void rib_unlink(struct route_node *rn, struct route_entry *re) dest = rib_dest_from_rnode(rn); - if (re->next) - re->next->prev = re->prev; - - if (re->prev) - re->prev->next = re->next; - else { - dest->routes = re->next; - } + re_list_del(&dest->routes, re); if (dest->selected_fib == re) dest->selected_fib = NULL; @@ -2655,7 +2639,6 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; - unsigned changed = 0; rib_dest_t *dest; if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) { @@ -2682,7 +2665,6 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) * of the rest of the RE. */ if (dest->selected_fib) { - changed = 1; if (IS_ZEBRA_DEBUG_RIB) { char buf[PREFIX_STRLEN]; @@ -2692,9 +2674,8 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) route_entry_dump(&rn->p, NULL, dest->selected_fib); } rib_uninstall(rn, dest->selected_fib); - } - if (changed) rib_queue_add(rn); + } } int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, @@ -2874,7 +2855,11 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, break; } for (ALL_NEXTHOPS(re->ng, rtnh)) - if (nexthop_same_no_recurse(rtnh, nh)) { + /* + * No guarantee all kernel send nh with labels + * on delete. + */ + if (nexthop_same_no_labels(rtnh, nh)) { same = re; break; } @@ -3018,7 +3003,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, re->table = table_id; re->vrf_id = vrf_id; re->nexthop_num = 0; - re->uptime = time(NULL); + re->uptime = monotime(NULL); re->tag = tag; /* Add nexthop. */ @@ -3069,6 +3054,8 @@ void rib_update_table(struct route_table *table, rib_update_event_t event) continue; if (re->type != ZEBRA_ROUTE_STATIC) { + SET_FLAG(re->status, + ROUTE_ENTRY_CHANGED); rib_queue_add(rn); continue; } @@ -3082,8 +3069,11 @@ void rib_update_table(struct route_table *table, rib_update_event_t event) * gateway, NHT will * take care. */ - if (nh) + if (nh) { + SET_FLAG(re->status, + ROUTE_ENTRY_CHANGED); rib_queue_add(rn); + } } break; @@ -3093,8 +3083,12 @@ void rib_update_table(struct route_table *table, rib_update_event_t event) * protocol in * some cases (TODO). */ - if (rnode_to_ribs(rn)) + if (rnode_to_ribs(rn)) { + RNODE_FOREACH_RE_SAFE (rn, re, next) + SET_FLAG(re->status, + ROUTE_ENTRY_CHANGED); rib_queue_add(rn); + } break; default: @@ -3137,6 +3131,7 @@ void rib_sweep_table(struct route_table *table) for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { RNODE_FOREACH_RE_SAFE (rn, re, next) { + if (IS_ZEBRA_DEBUG_RIB) route_entry_dump(&rn->p, NULL, re); @@ -3147,6 +3142,14 @@ void rib_sweep_table(struct route_table *table) continue; /* + * If routes are older than startup_time then + * we know we read them in from the kernel. + * As such we can safely remove them. + */ + if (zrouter.startup_time < re->uptime) + continue; + + /* * So we are starting up and have received * routes from the kernel that we have installed * from a previous run of zebra but not cleaned @@ -3175,7 +3178,7 @@ void rib_sweep_table(struct route_table *table) } /* Sweep all RIB tables. */ -void rib_sweep_route(void) +int rib_sweep_route(struct thread *t) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -3189,6 +3192,8 @@ void rib_sweep_route(void) } zebra_router_sweep_route(); + + return 0; } /* Remove specific by protocol routes from 'table'. */ @@ -3219,18 +3224,23 @@ unsigned long rib_score_proto(uint8_t proto, unsigned short instance) { struct vrf *vrf; struct zebra_vrf *zvrf; + struct other_route_table *ort; unsigned long cnt = 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - cnt += rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP][SAFI_UNICAST]) - + rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + zvrf = vrf->info; + if (!zvrf) + continue; + + cnt += rib_score_proto_table(proto, instance, + zvrf->table[AFI_IP][SAFI_UNICAST]) + + rib_score_proto_table( + proto, instance, + zvrf->table[AFI_IP6][SAFI_UNICAST]); - cnt += zebra_router_score_proto(proto, instance); + frr_each(otable, &zvrf->other_tables, ort) cnt += + rib_score_proto_table(proto, instance, ort->table); + } return cnt; } @@ -3380,9 +3390,33 @@ static int rib_dplane_results(struct dplane_ctx_q *ctxlist) return 0; } +/* + * Ensure there are no empty slots in the route_info array. + * Every route type in zebra should be present there. + */ +static void check_route_info(void) +{ + int len = array_size(route_info); + + /* + * ZEBRA_ROUTE_SYSTEM is special cased since + * its key is 0 anyway. + * + * ZEBRA_ROUTE_ALL is also ignored. + */ + for (int i = 0; i < len; i++) { + if (i == ZEBRA_ROUTE_SYSTEM || i == ZEBRA_ROUTE_ALL) + continue; + assert(route_info[i].key); + assert(route_info[i].meta_q_map < MQ_SIZE); + } +} + /* Routing information base initialize. */ void rib_init(void) { + check_route_info(); + rib_queue_init(); /* Init dataplane, and register for results */ @@ -3451,7 +3485,7 @@ struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter) while (1) { while (iter->afi_safi_ix - < (int)ZEBRA_NUM_OF(afi_safis)) { + < (int)array_size(afi_safis)) { table = zebra_vrf_table( afi_safis[iter->afi_safi_ix].afi, afi_safis[iter->afi_safi_ix].safi, |
