diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 199 |
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. */ |
