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.c199
1 files changed, 90 insertions, 109 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index dc61ea5e40..deb434bd35 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -291,13 +291,14 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
return nexthop;
}
-struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re)
+struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re,
+ enum blackhole_type bh_type)
{
struct nexthop *nexthop;
nexthop = nexthop_new();
nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
- SET_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE);
+ nexthop->bh_type = bh_type;
route_entry_nexthop_add(re, nexthop);
@@ -471,12 +472,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
continue;
}
- /* If the longest prefix match for the nexthop yields
- * a blackhole, mark it as inactive. */
- if (CHECK_FLAG(match->flags, ZEBRA_FLAG_BLACKHOLE)
- || CHECK_FLAG(match->flags, ZEBRA_FLAG_REJECT))
- return 0;
-
if (match->type == ZEBRA_ROUTE_CONNECT) {
/* Directly point connected route. */
newhop = match->nexthop;
@@ -488,41 +483,46 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
return 1;
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) {
resolved = 0;
- for (ALL_NEXTHOPS(match->nexthop, newhop))
- if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_FIB)
- && !CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_RECURSIVE)) {
- if (set) {
- SET_FLAG(
- nexthop->flags,
- NEXTHOP_FLAG_RECURSIVE);
- SET_FLAG(
- re->status,
- ROUTE_ENTRY_NEXTHOPS_CHANGED);
-
- nexthop_set_resolved(
- afi, newhop, nexthop);
- }
- resolved = 1;
+ for (ALL_NEXTHOPS(match->nexthop, newhop)) {
+ if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
+ continue;
+ if (!CHECK_FLAG(newhop->flags,
+ NEXTHOP_FLAG_FIB))
+ continue;
+ if (CHECK_FLAG(newhop->flags,
+ NEXTHOP_FLAG_RECURSIVE))
+ continue;
+
+ if (set) {
+ SET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE);
+ SET_FLAG(re->status,
+ ROUTE_ENTRY_NEXTHOPS_CHANGED);
+ nexthop_set_resolved(afi, newhop,
+ nexthop);
}
+ resolved = 1;
+ }
if (resolved && set)
re->nexthop_mtu = match->mtu;
return resolved;
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
- for (ALL_NEXTHOPS(match->nexthop, newhop))
- if (CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB)) {
- if (set) {
- SET_FLAG(
- nexthop->flags,
- NEXTHOP_FLAG_RECURSIVE);
+ for (ALL_NEXTHOPS(match->nexthop, newhop)) {
+ if (newhop->type == NEXTHOP_TYPE_BLACKHOLE)
+ continue;
+ if (!CHECK_FLAG(newhop->flags,
+ NEXTHOP_FLAG_FIB))
+ continue;
- nexthop_set_resolved(
- afi, newhop, nexthop);
- }
- resolved = 1;
+ if (set) {
+ SET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE);
+ nexthop_set_resolved(afi, newhop,
+ nexthop);
}
+ resolved = 1;
+ }
if (resolved && set)
re->nexthop_mtu = match->mtu;
return resolved;
@@ -2061,10 +2061,9 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr))
: "",
re->vrf_id);
- zlog_debug(
- "%s: refcnt == %lu, uptime == %lu, type == %u, instance == %d, table == %d",
- func, re->refcnt, (unsigned long)re->uptime, re->type,
- re->instance, re->table);
+ zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
+ func, (unsigned long)re->uptime, re->type, re->instance,
+ re->table);
zlog_debug(
"%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
func, re->metric, re->mtu, re->distance, re->flags, re->status);
@@ -2273,16 +2272,15 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
void rib_delete(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, union g_addr *gate,
- ifindex_t ifindex, u_int32_t table_id,
- u_int32_t metric)
+ struct prefix_ipv6 *src_p, const struct nexthop *nh,
+ u_int32_t table_id, u_int32_t metric)
{
struct route_table *table;
struct route_node *rn;
struct route_entry *re;
struct route_entry *fib = NULL;
struct route_entry *same = NULL;
- struct nexthop *nexthop;
+ struct nexthop *rtnh;
char buf2[INET6_ADDRSTRLEN];
assert(!src_p || afi == AFI_IP6);
@@ -2332,29 +2330,21 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
if (re->type == ZEBRA_ROUTE_KERNEL &&
re->metric != metric)
continue;
- if (re->type == ZEBRA_ROUTE_CONNECT && (nexthop = re->nexthop)
- && nexthop->type == NEXTHOP_TYPE_IFINDEX) {
- if (nexthop->ifindex != ifindex)
+ if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->nexthop)
+ && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
+ if (rtnh->ifindex != nh->ifindex)
continue;
- if (re->refcnt) {
- re->refcnt--;
- route_unlock_node(rn);
- route_unlock_node(rn);
- return;
- }
same = re;
break;
}
/* Make sure that the route found has the same gateway. */
else {
- if (gate == NULL) {
+ if (nh == NULL) {
same = re;
break;
}
- for (ALL_NEXTHOPS(re->nexthop, nexthop))
- if (IPV4_ADDR_SAME(&nexthop->gate.ipv4, &gate->ipv4)
- || IPV6_ADDR_SAME(&nexthop->gate.ipv6,
- gate)) {
+ for (ALL_NEXTHOPS(re->nexthop, rtnh))
+ if (nexthop_same_no_recurse(rtnh, nh)) {
same = re;
break;
}
@@ -2375,9 +2365,9 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
if (allow_delete) {
/* Unset flags. */
- for (nexthop = fib->nexthop; nexthop;
- nexthop = nexthop->next)
- UNSET_FLAG(nexthop->flags,
+ for (rtnh = fib->nexthop; rtnh;
+ rtnh = rtnh->next)
+ UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
UNSET_FLAG(fib->status,
@@ -2391,22 +2381,22 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
} else {
if (IS_ZEBRA_DEBUG_RIB) {
- if (gate)
+ if (nh)
rnode_debug(
rn, vrf_id,
"via %s ifindex %d type %d "
"doesn't exist in rib",
inet_ntop(
- family2afi(afi), gate,
- buf2,
+ family2afi(afi),
+ &nh->gate, buf2,
INET_ADDRSTRLEN), /* FIXME
*/
- ifindex, type);
+ nh->ifindex, type);
else
rnode_debug(
rn, vrf_id,
- "ifindex %d type %d doesn't exist in rib",
- ifindex, type);
+ "type %d doesn't exist in rib",
+ type);
}
route_unlock_node(rn);
return;
@@ -2423,15 +2413,14 @@ 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,
- union g_addr *gate, union g_addr *src, ifindex_t ifindex,
- u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
- u_char distance)
+ const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
+ u_int32_t mtu, u_char distance)
{
struct route_entry *re;
struct route_entry *same = NULL;
struct route_table *table;
struct route_node *rn;
- struct nexthop *nexthop;
+ struct nexthop *rtnh;
assert(!src_p || afi == AFI_IP6);
@@ -2480,13 +2469,16 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
break;
}
/* Duplicate system route comes in. */
- else if ((nexthop = re->nexthop)
- && nexthop->type == NEXTHOP_TYPE_IFINDEX
- && nexthop->ifindex == ifindex
- && !CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
- re->refcnt++;
+ rtnh = re->nexthop;
+ if (nexthop_same_no_recurse(rtnh, nh))
return 0;
- }
+ /*
+ * Nexthop is different. Remove the old route unless it's
+ * a link-local route.
+ */
+ else if (afi != AFI_IP6
+ || !IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
+ same = re;
}
/* Allocate new re structure. */
@@ -2503,29 +2495,14 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->nexthop_num = 0;
re->uptime = time(NULL);
- /* Nexthop settings. */
- if (gate) {
- if (afi == AFI_IP6) {
- if (ifindex)
- route_entry_nexthop_ipv6_ifindex_add(
- re, &gate->ipv6, ifindex);
- else
- route_entry_nexthop_ipv6_add(re, &gate->ipv6);
- } else {
- if (ifindex)
- route_entry_nexthop_ipv4_ifindex_add(
- re, &gate->ipv4, &src->ipv4, ifindex);
- else
- route_entry_nexthop_ipv4_add(re, &gate->ipv4,
- &src->ipv4);
- }
- } else
- route_entry_nexthop_ifindex_add(re, ifindex);
+ rtnh = nexthop_new();
+ *rtnh = *nh;
+ route_entry_nexthop_add(re, rtnh);
/* If this route is kernel route, set FIB flag to the route. */
if (RIB_SYSTEM_ROUTE(re))
- for (nexthop = re->nexthop; nexthop; nexthop = nexthop->next)
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ for (rtnh = re->nexthop; rtnh; rtnh = rtnh->next)
+ SET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB);
/* Link new rib to node.*/
if (IS_ZEBRA_DEBUG_RIB) {
@@ -2745,23 +2722,27 @@ unsigned long rib_score_proto(u_char proto, u_short instance)
void rib_close_table(struct route_table *table)
{
struct route_node *rn;
- rib_table_info_t *info = table->info;
+ rib_table_info_t *info;
struct route_entry *re;
- if (table)
- 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;
+ if (!table)
+ return;
- if (info->safi == SAFI_UNICAST)
- hook_call(rib_update, rn, NULL);
+ info = table->info;
- if (!RIB_SYSTEM_ROUTE(re))
- rib_uninstall_kernel(rn, re);
- }
+ 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;
+
+ if (info->safi == SAFI_UNICAST)
+ hook_call(rib_update, rn, NULL);
+
+ if (!RIB_SYSTEM_ROUTE(re))
+ rib_uninstall_kernel(rn, re);
+ }
}
/* Routing information base initialize. */