summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorMitesh Kanjariya <mitesh@cumulusnetworks.com>2018-01-11 09:00:23 -0800
committerGitHub <noreply@github.com>2018-01-11 09:00:23 -0800
commit9bb77a5b3dec12a71ef816699e491e2b832343ec (patch)
treee046f33132343f975e28bfcf2b9999c69a1c70eb /zebra/zebra_rib.c
parent523cafc4181b4d9f26147d44f71ba0d9b7adef53 (diff)
parentc1240044fbf081bb7407b1449d3954e4b63fec9f (diff)
Merge branch 'master' into evpn-symmetric-routing
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c147
1 files changed, 73 insertions, 74 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 3ed3438cae..41e14459b1 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -385,10 +385,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
struct prefix p;
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
int resolved;
struct nexthop *newhop;
struct interface *ifp;
+ rib_dest_t *dest;
if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|| nexthop->type == NEXTHOP_TYPE_IPV6)
@@ -468,17 +469,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
&& !nh_resolve_via_default(p.family))
return 0;
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
-
- /* if the next hop is imported from another table, skip
- * it */
- if (match->type == ZEBRA_ROUTE_TABLE)
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ 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)
+ match = dest->selected_fib;
/* If there is no selected route or matched route is EGP, go up
tree. */
@@ -555,7 +551,7 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
struct prefix p;
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *newhop;
/* Lookup table. */
@@ -576,15 +572,14 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
rn = route_node_match(table, (struct prefix *)&p);
while (rn) {
+ rib_dest_t *dest;
+
route_unlock_node(rn);
- /* Pick up selected route. */
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ dest = rib_dest_from_rnode(rn);
+ 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
tree. */
@@ -691,8 +686,9 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *nexthop;
+ rib_dest_t *dest;
/* Lookup table. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
@@ -707,13 +703,11 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+ match = dest->selected_fib;
if (!match)
return NULL;
@@ -745,9 +739,10 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *match;
+ struct route_entry *match = NULL;
struct nexthop *nexthop;
int nexthops_active;
+ rib_dest_t *dest;
/* Lookup table. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
@@ -763,15 +758,13 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate,
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
/* Find out if a "selected" RR for the discovered RIB entry exists ever.
*/
- RNODE_FOREACH_RE (rn, match) {
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED))
- continue;
- if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB))
- break;
- }
+ if (dest && dest->selected_fib &&
+ !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
+ match = dest->selected_fib;
/* None such found :( */
if (!match)
@@ -1119,8 +1112,9 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
static void rib_uninstall(struct route_node *rn, struct route_entry *re)
{
rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
+ if (dest && dest->selected_fib == re) {
if (info->safi == SAFI_UNICAST)
hook_call(rib_update, rn, "rib_uninstall");
@@ -1131,7 +1125,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
if (zebra_rib_labeled_unicast(re))
zebra_mpls_lsp_uninstall(info->zvrf, rn, re);
- UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
}
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
@@ -1205,6 +1199,8 @@ int rib_gc_dest(struct route_node *rn)
static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *new)
{
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
+
hook_call(rib_update, rn, "new route selected");
/* Update real nexthop. This may actually determine if nexthop is active
@@ -1214,7 +1210,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
return;
}
- SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = new;
if (IS_ZEBRA_DEBUG_RIB) {
char buf[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, buf, sizeof(buf));
@@ -1235,6 +1231,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *old)
{
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
hook_call(rib_update, rn, "removing existing route");
/* Uninstall from kernel. */
@@ -1252,7 +1249,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
/* Update nexthop for route, reset changed flag. */
nexthop_active_update(rn, old, 1);
@@ -1267,6 +1264,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
struct nexthop *nexthop = NULL;
int nh_active = 0;
int installed = 1;
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
/*
* We have to install or update if a new route has been selected or
@@ -1333,7 +1331,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
/* Update for redistribution. */
if (installed)
- SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = new;
}
/*
@@ -1368,7 +1366,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
}
} else {
/*
@@ -1396,8 +1394,6 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
/* Update prior route. */
if (new != old) {
- UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB);
-
/* Set real nexthop. */
nexthop_active_update(rn, old, 1);
UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
@@ -1479,6 +1475,15 @@ static void rib_process(struct route_node *rn)
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn);
+ /*
+ * we can have rn's that have a NULL info pointer
+ * (dest). As such let's not let the deref happen
+ * additionally we know RNODE_FOREACH_RE_SAFE
+ * will not iterate so we are ok.
+ */
+ if (dest)
+ old_fib = dest->selected_fib;
+
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
@@ -1494,11 +1499,6 @@ static void rib_process(struct route_node *rn)
assert(old_selected == NULL);
old_selected = re;
}
- /* Currently in fib */
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) {
- assert(old_fib == NULL);
- old_fib = re;
- }
/* Skip deleted entries from selection */
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
@@ -2187,8 +2187,8 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
{
struct route_table *table;
struct route_node *rn;
- struct route_entry *re;
unsigned changed = 0;
+ rib_dest_t *dest;
if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) {
zlog_err("%s: zebra_vrf_table() returned NULL", __func__);
@@ -2202,6 +2202,7 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
/* Unlock node. */
route_unlock_node(rn);
+ dest = rib_dest_from_rnode(rn);
/* Check all RE entries. In case any changes have to be done, requeue
* the RN into RIBQ head. If the routing message about the new connected
* route (generated by the IP address we are going to assign very soon)
@@ -2210,20 +2211,17 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id)
* revalidation
* of the rest of the RE.
*/
- RNODE_FOREACH_RE (rn, re) {
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)
- && !RIB_SYSTEM_ROUTE(re)) {
- changed = 1;
- if (IS_ZEBRA_DEBUG_RIB) {
- char buf[PREFIX_STRLEN];
- zlog_debug(
- "%u:%s: freeing way for connected prefix",
- re->vrf_id,
- prefix2str(&rn->p, buf, sizeof(buf)));
- route_entry_dump(&rn->p, NULL, re);
- }
- rib_uninstall(rn, re);
+ if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) {
+ changed = 1;
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char buf[PREFIX_STRLEN];
+
+ zlog_debug("%u:%s: freeing way for connected prefix",
+ dest->selected_fib->vrf_id,
+ prefix2str(&rn->p, buf, sizeof(buf)));
+ route_entry_dump(&rn->p, NULL, dest->selected_fib);
}
+ rib_uninstall(rn, dest->selected_fib);
}
if (changed)
rib_queue_add(rn);
@@ -2330,6 +2328,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
struct route_entry *same = NULL;
struct nexthop *rtnh;
char buf2[INET6_ADDRSTRLEN];
+ rib_dest_t *dest;
assert(!src_p || afi == AFI_IP6);
@@ -2362,14 +2361,14 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
return;
}
+ dest = rib_dest_from_rnode(rn);
+ fib = dest->selected_fib;
+
/* Lookup same type route. */
RNODE_FOREACH_RE (rn, re) {
if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
continue;
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
- fib = re;
-
if (re->type != type)
continue;
if (re->instance != instance)
@@ -2432,8 +2431,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
- UNSET_FLAG(fib->status,
- ROUTE_ENTRY_SELECTED_FIB);
+ dest->selected_fib = NULL;
} else {
/* This means someone else, other than Zebra,
* has deleted
@@ -2501,7 +2499,7 @@ 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, 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)
+ u_int32_t mtu, uint8_t distance, route_tag_t tag)
{
struct route_entry *re;
struct nexthop *nexthop;
@@ -2518,6 +2516,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->vrf_id = vrf_id;
re->nexthop_num = 0;
re->uptime = time(NULL);
+ re->tag = tag;
/* Add nexthop. */
nexthop = nexthop_new();
@@ -2761,24 +2760,24 @@ void rib_close_table(struct route_table *table)
{
struct route_node *rn;
rib_table_info_t *info;
- struct route_entry *re;
+ rib_dest_t *dest;
if (!table)
return;
info = table->info;
- for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
- RNODE_FOREACH_RE (rn, re) {
- if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB))
- continue;
+ for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
+ dest = rib_dest_from_rnode(rn);
+ if (dest && dest->selected_fib) {
if (info->safi == SAFI_UNICAST)
hook_call(rib_update, rn, NULL);
- if (!RIB_SYSTEM_ROUTE(re))
- rib_uninstall_kernel(rn, re);
+ if (!RIB_SYSTEM_ROUTE(dest->selected_fib))
+ rib_uninstall_kernel(rn, dest->selected_fib);
}
+ }
}
/* Routing information base initialize. */