diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 193 |
1 files changed, 84 insertions, 109 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index e47499b065..4cf4c24060 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -24,7 +24,6 @@ #include "if.h" #include "linklist.h" #include "log.h" -#include "log_int.h" #include "memory.h" #include "mpls.h" #include "nexthop.h" @@ -403,10 +402,13 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, nexthop_add(&nexthop->resolved, resolved_hop); } -/* If force flag is not set, do not modify falgs at all for uninstall - the route from FIB. */ +/* + * Given a nexthop we need to properly recursively resolve + * the route. As such, do a table lookup to find and match + * if at all possible. Set the nexthop->ifindex as appropriate + */ static int nexthop_active(afi_t afi, struct route_entry *re, - struct nexthop *nexthop, bool set, + struct nexthop *nexthop, struct route_node *top) { struct prefix p; @@ -422,12 +424,10 @@ static int nexthop_active(afi_t afi, struct route_entry *re, || nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = 0; - if (set) { - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - nexthops_free(nexthop->resolved); - nexthop->resolved = NULL; - re->nexthop_mtu = 0; - } + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + nexthops_free(nexthop->resolved); + nexthop->resolved = NULL; + re->nexthop_mtu = 0; /* * If the kernel has sent us a route, then @@ -437,16 +437,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re, re->type == ZEBRA_ROUTE_SYSTEM) return 1; - /* Skip nexthops that have been filtered out due to route-map */ - /* The nexthops are specific to this route and so the same */ - /* nexthop for a different route may not have this flag set */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FILTERED)) { - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug("\t%s: Nexthop Filtered", - __PRETTY_FUNCTION__); - return 0; - } - /* * Check to see if we should trust the passed in information * for UNNUMBERED interfaces as that we won't find the GW @@ -581,17 +571,14 @@ static int nexthop_active(afi_t afi, struct route_entry *re, 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); - } + 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) + if (resolved) re->nexthop_mtu = match->mtu; if (!resolved && IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("\t%s: Recursion failed to find", @@ -607,15 +594,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re, NEXTHOP_FLAG_RECURSIVE)) continue; - if (set) { - SET_FLAG(nexthop->flags, - NEXTHOP_FLAG_RECURSIVE); - nexthop_set_resolved(afi, newhop, - nexthop); - } + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE); + nexthop_set_resolved(afi, newhop, nexthop); resolved = 1; } - if (resolved && set) + if (resolved) re->nexthop_mtu = match->mtu; if (!resolved && IS_ZEBRA_DEBUG_RIB_DETAILED) @@ -819,17 +803,15 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) /* 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. If the 4th parameter, 'set', is non-zero, - * nexthop->ifindex will be updated appropriately as well. - * An existing route map can turn (otherwise active) nexthop into inactive, but - * not vice versa. + * in nexthop->flags field. The nexthop->ifindex will be updated + * appropriately as well. An existing route map can turn + * (otherwise active) nexthop into inactive, but not vice versa. * * The return value is the final value of 'ACTIVE' flag. */ - static unsigned nexthop_active_check(struct route_node *rn, struct route_entry *re, - struct nexthop *nexthop, bool set) + struct nexthop *nexthop) { struct interface *ifp; route_map_result_t ret = RMAP_MATCH; @@ -857,14 +839,14 @@ static unsigned nexthop_active_check(struct route_node *rn, case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: family = AFI_IP; - if (nexthop_active(AFI_IP, re, nexthop, set, rn)) + if (nexthop_active(AFI_IP, re, nexthop, rn)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); break; case NEXTHOP_TYPE_IPV6: family = AFI_IP6; - if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + if (nexthop_active(AFI_IP6, re, nexthop, rn)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -881,7 +863,7 @@ static unsigned nexthop_active_check(struct route_node *rn, else UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } else { - if (nexthop_active(AFI_IP6, re, nexthop, set, rn)) + if (nexthop_active(AFI_IP6, re, nexthop, rn)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -946,25 +928,21 @@ static unsigned nexthop_active_check(struct route_node *rn, return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } -/* Iterate over all nexthops of the given RIB entry and refresh their +/* + * Iterate over all nexthops of the given RIB entry and refresh their * ACTIVE flag. re->nexthop_active_num is updated accordingly. If any * nexthop is found to toggle the ACTIVE flag, the whole re structure - * is flagged with ROUTE_ENTRY_CHANGED. The 4th 'set' argument is - * transparently passed to nexthop_active_check(). + * is flagged with ROUTE_ENTRY_CHANGED. * * Return value is the new number of active nexthops. */ - -static int nexthop_active_update(struct route_node *rn, struct route_entry *re, - bool set) +static int nexthop_active_update(struct route_node *rn, struct route_entry *re) { struct nexthop *nexthop; union g_addr prev_src; - unsigned int prev_active, new_active, old_num_nh; + unsigned int prev_active, new_active; ifindex_t prev_index; - old_num_nh = re->nexthop_active_num; - re->nexthop_active_num = 0; UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); @@ -980,7 +958,7 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re, * a multipath perpsective should not be a data plane * decision point. */ - new_active = nexthop_active_check(rn, re, nexthop, set); + new_active = nexthop_active_check(rn, re, nexthop); if (new_active && re->nexthop_active_num >= multipath_num) { UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); new_active = 0; @@ -996,19 +974,13 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re, || ((nexthop->type >= NEXTHOP_TYPE_IPV6 && nexthop->type < NEXTHOP_TYPE_BLACKHOLE) && !(IPV6_ADDR_SAME(&prev_src.ipv6, - &nexthop->rmap_src.ipv6)))) { + &nexthop->rmap_src.ipv6))) + || CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)) { SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); } } - if (old_num_nh != re->nexthop_active_num) - SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); - - if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) { - SET_FLAG(re->status, ROUTE_ENTRY_NEXTHOPS_CHANGED); - } - return re->nexthop_active_num; } @@ -1354,7 +1326,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active * or not. */ - if (!nexthop_active_update(rn, new, true)) { + if (!nexthop_group_active_nexthop_num(&new->ng)) { UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); return; } @@ -1401,8 +1373,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, * down, causing the kernel to delete routes without sending DELROUTE * notifications */ - if (!nexthop_active_update(rn, old, true) && - (RIB_KERNEL_ROUTE(old))) + if (RIB_KERNEL_ROUTE(old)) SET_FLAG(old->status, ROUTE_ENTRY_REMOVED); else UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); @@ -1424,7 +1395,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update the nexthop; we could determine here that nexthop is * inactive. */ - if (nexthop_active_update(rn, new, true)) + if (nexthop_group_active_nexthop_num(&new->ng)) nh_active = 1; /* If nexthop is active, install the selected route, if @@ -1509,11 +1480,8 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, } /* Update prior route. */ - if (new != old) { - /* Set real nexthop. */ - nexthop_active_update(rn, old, true); + if (new != old) UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); - } /* Clear changed flag. */ UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); @@ -1643,38 +1611,30 @@ static void rib_process(struct route_node *rn) /* Skip unreachable nexthop. */ /* This first call to nexthop_active_update is merely to - * determine if - * there's any change to nexthops associated with this RIB - * entry. Now, - * rib_process() can be invoked due to an external event such as - * link - * down or due to next-hop-tracking evaluation. In the latter - * case, + * determine if there's any change to nexthops associated + * with this RIB entry. Now, rib_process() can be invoked due + * to an external event such as link down or due to + * next-hop-tracking evaluation. In the latter case, * a decision has already been made that the NHs have changed. - * So, no - * need to invoke a potentially expensive call again. Further, - * since - * the change might be in a recursive NH which is not caught in - * the nexthop_active_update() code. Thus, we might miss changes - * to - * recursive NHs. + * So, no need to invoke a potentially expensive call again. + * Further, since the change might be in a recursive NH which + * is not caught in the nexthop_active_update() code. Thus, we + * might miss changes to recursive NHs. */ - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) - && !nexthop_active_update(rn, re, false)) { + if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) + && !nexthop_active_update(rn, re)) { if (re->type == ZEBRA_ROUTE_TABLE) { /* XXX: HERE BE DRAGONS!!!!! * In all honesty, I have not yet figured out - * what this part - * does or why the ROUTE_ENTRY_CHANGED test - * above is correct + * what this part does or why the + * ROUTE_ENTRY_CHANGED test above is correct * or why we need to delete a route here, and - * also not whether - * this concerns both selected and fib route, or - * only selected - * or only fib */ - /* This entry was denied by the 'ip protocol - * table' route-map, we - * need to delete it */ + * also not whether this concerns both selected + * and fib route, or only selected + * or only fib + * + * This entry was denied by the 'ip protocol + * table' route-map, we need to delete it */ if (re != old_selected) { if (IS_ZEBRA_DEBUG_RIB) zlog_debug( @@ -1751,10 +1711,8 @@ static void rib_process(struct route_node *rn) /* Update SELECTED entry */ if (old_selected != new_selected || selected_changed) { - if (new_selected && new_selected != new_fib) { - nexthop_active_update(rn, new_selected, true); + if (new_selected && new_selected != new_fib) UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); - } if (new_selected) SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); @@ -2613,8 +2571,8 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, INET6_ADDRSTRLEN); break; } - zlog_debug("%s: %s %s[%u] vrf %s(%u) with flags %s%s%s", func, - (nexthop->rparent ? " NH" : "NH"), straddr, + zlog_debug("%s: %s %s[%u] vrf %s(%u) with flags %s%s%s%s%s%s", + func, (nexthop->rparent ? " NH" : "NH"), straddr, nexthop->ifindex, vrf ? vrf->name : "Unknown", nexthop->vrf_id, (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE) @@ -2624,7 +2582,16 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, ? "FIB " : ""), (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) - ? "RECURSIVE" + ? "RECURSIVE " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK) + ? "ONLINK " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_MATCHED) + ? "MATCHED " + : ""), + (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE) + ? "DUPLICATE " : "")); } zlog_debug("%s: dump complete", func); @@ -2688,7 +2655,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))) { @@ -2715,7 +2681,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]; @@ -2725,9 +2690,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, @@ -2814,6 +2778,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, if (IS_ZEBRA_DEBUG_RIB_DETAILED) route_entry_dump(p, src_p, re); } + + SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); rib_addnode(rn, re, 1); ret = 1; @@ -3100,6 +3066,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; } @@ -3113,8 +3081,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; @@ -3124,8 +3095,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: |
