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.c136
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,