diff options
Diffstat (limited to 'zebra/zebra_rib.c')
| -rw-r--r-- | zebra/zebra_rib.c | 463 |
1 files changed, 78 insertions, 385 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index b0b58b738c..13418c509e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -348,10 +348,10 @@ nexthop_has_fib_child(struct nexthop *nexthop) /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ static int -nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, - struct route_node *top) +nexthop_active (afi_t afi, struct rib *rib, struct nexthop *nexthop, int set, + struct route_node *top) { - struct prefix_ipv4 p; + struct prefix p; struct route_table *table; struct route_node *rn; struct rib *match; @@ -361,7 +361,7 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, int recursing = 0; struct interface *ifp; - if (nexthop->type == NEXTHOP_TYPE_IPV4) + if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = 0; if (set) @@ -399,13 +399,25 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, } /* Make lookup prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = IPV4_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv4; - + memset (&p, 0, sizeof (struct prefix)); + switch (afi) + { + case AFI_IP: + p.family = AF_INET; + p.prefixlen = IPV4_MAX_PREFIXLEN; + p.u.prefix4 = nexthop->gate.ipv4; + break; + case AFI_IP6: + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_PREFIXLEN; + p.u.prefix6 = nexthop->gate.ipv6; + break; + default: + assert (afi != AFI_IP && afi != AFI_IP6); + break; + } /* Lookup table. */ - table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, rib->vrf_id); + table = zebra_vrf_table (afi, SAFI_UNICAST, rib->vrf_id); if (! table) return 0; @@ -458,9 +470,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, { /* Directly point connected route. */ newhop = match->nexthop; - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4) - nexthop->ifindex = newhop->ifindex; - + if (newhop) + { + if (nexthop->type == NEXTHOP_TYPE_IPV4 || + nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; + } return 1; } else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) @@ -492,6 +507,18 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; } } + if (newhop->type == NEXTHOP_TYPE_IPV6 + || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) + { + resolved_hop->type = newhop->type; + resolved_hop->gate.ipv6 = newhop->gate.ipv6; + + if (newhop->ifindex) + { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->ifindex = newhop->ifindex; + } + } /* If the resolving route is an interface route, * it means the gateway we are looking up is connected @@ -504,8 +531,16 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, if (newhop->type == NEXTHOP_TYPE_IFINDEX) { resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->gate.ipv4 = nexthop->gate.ipv4; + if (afi == AFI_IP) + { + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->gate.ipv4 = nexthop->gate.ipv4; + } + else if (afi == AFI_IP6) + { + resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + resolved_hop->gate.ipv6 = nexthop->gate.ipv6; + } resolved_hop->ifindex = newhop->ifindex; } @@ -542,151 +577,6 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; } } - - /* If the resolving route is an interface route, - * it means the gateway we are looking up is connected - * to that interface. (The actual network is _not_ onlink). - * Therefore, the resolved route should have the original - * gateway as nexthop as it is directly connected. - * - * On Linux, we have to set the onlink netlink flag because - * otherwise, the kernel won't accept the route. - */ - if (newhop->type == NEXTHOP_TYPE_IFINDEX) - { - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; - resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - resolved_hop->gate.ipv4 = nexthop->gate.ipv4; - resolved_hop->ifindex = newhop->ifindex; - } - - nexthop_add(&nexthop->resolved, resolved_hop); - } - resolved = 1; - } - if (resolved && set) - rib->nexthop_mtu = match->mtu; - return resolved; - } - else - { - return 0; - } - } - } - return 0; -} - -/* If force flag is not set, do not modify falgs at all for uninstall - the route from FIB. */ -static int -nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, - struct route_node *top) -{ - struct prefix_ipv6 p; - struct route_table *table; - struct route_node *rn; - struct rib *match; - int resolved; - struct nexthop *newhop, *tnewhop; - int recursing = 0; - struct nexthop *resolved_hop; - - if (nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = 0; - - if (set) - { - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - zebra_deregister_rnh_static_nexthops (rib->vrf_id, nexthop->resolved, top); - nexthops_free(nexthop->resolved); - nexthop->resolved = NULL; - } - - /* 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)) - return 0; - - /* Make lookup prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - p.prefixlen = IPV6_MAX_PREFIXLEN; - p.prefix = nexthop->gate.ipv6; - - /* Lookup table. */ - table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, rib->vrf_id); - if (! table) - return 0; - - rn = route_node_match (table, (struct prefix *) &p); - while (rn) - { - route_unlock_node (rn); - - /* If lookup self prefix return immediately. */ - if (rn == top) - return 0; - - /* Pick up selected route. */ - /* However, do not resolve over default route unless explicitly allowed. */ - if (is_default_prefix (&rn->p) && - !nh_resolve_via_default (p.family)) - return 0; - - RNODE_FOREACH_RIB (rn, match) - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->status, RIB_ENTRY_SELECTED_FIB)) - break; - } - - /* If there is no selected route or matched route is EGP, go up - tree. */ - if (! match) - { - do { - rn = rn->parent; - } while (rn && rn->info == NULL); - if (rn) - route_lock_node (rn); - } - else - { - /* 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; - - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6) - nexthop->ifindex = newhop->ifindex; - - return 1; - } - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) - { - resolved = 0; - for (newhop = match->nexthop; newhop; newhop = newhop->next) - 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(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); - - resolved_hop = nexthop_new(); - SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - /* See nexthop_active_ipv4 for a description how the - * resolved nexthop is constructed. */ if (newhop->type == NEXTHOP_TYPE_IPV6 || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { @@ -700,59 +590,37 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, } } + /* If the resolving route is an interface route, + * it means the gateway we are looking up is connected + * to that interface. (The actual network is _not_ onlink). + * Therefore, the resolved route should have the original + * gateway as nexthop as it is directly connected. + * + * On Linux, we have to set the onlink netlink flag because + * otherwise, the kernel won't accept the route. + */ if (newhop->type == NEXTHOP_TYPE_IFINDEX) { - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->gate.ipv6 = nexthop->gate.ipv6; - resolved_hop->ifindex = newhop->ifindex; - } - - nexthop_add(&nexthop->resolved, resolved_hop); - } - resolved = 1; - } - return resolved; - } - else if (rib->type == ZEBRA_ROUTE_STATIC) - { - resolved = 0; - for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing)) - if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)) - { - if (set) - { - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); - - resolved_hop = nexthop_new(); - SET_FLAG (resolved_hop->flags, NEXTHOP_FLAG_ACTIVE); - /* See nexthop_active_ipv4 for a description how the - * resolved nexthop is constructed. */ - if (newhop->type == NEXTHOP_TYPE_IPV6 - || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX) - { - resolved_hop->type = newhop->type; - resolved_hop->gate.ipv6 = newhop->gate.ipv6; - - if (newhop->ifindex) + resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (afi == AFI_IP) { - resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - resolved_hop->ifindex = newhop->ifindex; + resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + resolved_hop->gate.ipv4 = nexthop->gate.ipv4; } - } - - if (newhop->type == NEXTHOP_TYPE_IFINDEX) - { - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + else if (afi == AFI_IP6) + { resolved_hop->type = NEXTHOP_TYPE_IPV6_IFINDEX; resolved_hop->gate.ipv6 = nexthop->gate.ipv6; - resolved_hop->ifindex = newhop->ifindex; + } + resolved_hop->ifindex = newhop->ifindex; } nexthop_add(&nexthop->resolved, resolved_hop); } resolved = 1; } + if (resolved && set) + rib->nexthop_mtu = match->mtu; return resolved; } else @@ -1077,14 +945,14 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: family = AFI_IP; - if (nexthop_active_ipv4 (rib, nexthop, set, rn)) + if (nexthop_active (AFI_IP, rib, nexthop, set, 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_ipv6 (rib, nexthop, set, rn)) + if (nexthop_active (AFI_IP6, rib, nexthop, set, rn)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -1103,7 +971,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, } else { - if (nexthop_active_ipv6 (rib, nexthop, set, rn)) + if (nexthop_active (AFI_IP6, rib, nexthop, set, rn)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -1819,181 +1687,6 @@ rib_process (struct route_node *rn) } } -#if 0 - if (select && select == fib) - { - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p", - (void *)select, (void *)fib); - if (CHECK_FLAG (select->status, RIB_ENTRY_CHANGED)) - { - if (info->safi == SAFI_UNICAST) - zfpm_trigger_update (rn, "updating existing route"); - - /* Set real nexthop. */ - /* Need to check if any NHs are active to clear the - * the selected flag - */ - if (nexthop_active_update (rn, select, 1)) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d)", - vrf_id, buf, rn->p.prefixlen, rn, select, select->type); - if (! RIB_SYSTEM_ROUTE (select)) - { - /* Clear FIB flag if performing a replace, will get set again - * as part of install. - */ - for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - rib_install_kernel (rn, select, 1); - } - - /* assuming that the receiver knows how to dedup */ - redistribute_update (&rn->p, select, NULL); - } - else - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) " - "- nexthop inactive", - vrf_id, buf, rn->p.prefixlen, rn, select, select->type); - - /* Withdraw unreachable redistribute route */ - redistribute_delete(&rn->p, select); - - /* Do the uninstall here, if not done earlier. */ - if (! RIB_SYSTEM_ROUTE (select)) - rib_uninstall_kernel (rn, select); - UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); - } - UNSET_FLAG (select->status, RIB_ENTRY_CHANGED); - } - else if (! RIB_SYSTEM_ROUTE (select)) - { - /* Housekeeping code to deal with - race conditions in kernel with linux - netlink reporting interface up before IPv4 or IPv6 protocol - is ready to add routes. - This makes sure the routes are IN the kernel. - */ - - for (ALL_NEXTHOPS_RO(select->nexthop, nexthop, tnexthop, recursing)) - if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - installed = 1; - break; - } - if (! installed) - rib_install_kernel (rn, select, 0); - } - goto end; - } - - /* At this point we either haven't found the best RIB entry or it is - * different from what we currently intend to flag with SELECTED. In both - * cases, if a RIB block is present in FIB, it should be withdrawn. - */ - if (fib) - { - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, vrf_id, "Removing existing route, fib %p", (void *)fib); - - if (info->safi == SAFI_UNICAST) - zfpm_trigger_update (rn, "removing existing route"); - - /* If there's no route to replace this with, withdraw redistribute and - * uninstall from kernel. - */ - if (!select) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d)", - vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type); - - redistribute_delete(&rn->p, fib); - if (! RIB_SYSTEM_ROUTE (fib)) - rib_uninstall_kernel (rn, fib); - } - - UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); - - /* Set real nexthop. */ - nexthop_active_update (rn, fib, 1); - UNSET_FLAG(fib->status, RIB_ENTRY_CHANGED); - } - - /* Regardless of some RIB entry being SELECTED or not before, now we can - * tell, that if a new winner exists, FIB is still not updated with this - * data, but ready to be. - */ - if (select) - { - if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, "Adding route, select %p", (void *)select); - - if (info->safi == SAFI_UNICAST) - zfpm_trigger_update (rn, "new route selected"); - - /* Set real nexthop. */ - if (nexthop_active_update (rn, select, 1)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - if (fib) - zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d) " - "old %p (type %d)", vrf_id, buf, rn->p.prefixlen, rn, - select, select->type, fib, fib->type); - else - zlog_debug ("%u:%s/%d: Adding route rn %p, rib %p (type %d)", - vrf_id, buf, rn->p.prefixlen, rn, select, select->type); - } - - if (! RIB_SYSTEM_ROUTE (select)) - { - /* Clear FIB flag if performing a replace, will get set again - * as part of install. - */ - if (fib) - { - for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); - } - rib_install_kernel (rn, select, fib? 1 : 0); - } - else - { - /* Uninstall prior route here, if needed. */ - if (fib && !RIB_SYSTEM_ROUTE (fib)) - rib_uninstall_kernel (rn, fib); - } - - SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); - /* Unconditionally announce, this part is exercised by new routes */ - /* If we cannot add, for example route added is learnt by the */ - /* protocol we're trying to redistribute to, delete the redist */ - /* This is notified by setting the is_update to 1 */ - redistribute_update (&rn->p, select, fib); - } - else - { - /* Uninstall prior route here and do redist delete, if needed. */ - if (fib) - { - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) " - "- nexthop inactive", - vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type); - - if (!RIB_SYSTEM_ROUTE (fib)) - rib_uninstall_kernel (rn, fib); - redistribute_delete(&rn->p, fib); - } - } - UNSET_FLAG(select->status, RIB_ENTRY_CHANGED); - } -#endif - /* Remove all RIB entries queued for removal */ RNODE_FOREACH_RIB_SAFE (rn, rib, next) { @@ -2691,7 +2384,7 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, return ret; } -int +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) @@ -2710,7 +2403,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, /* Lookup table. */ table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id); if (! table) - return 0; + return; /* Apply mask. */ apply_mask (p); @@ -2734,7 +2427,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, vrf_id, dst_buf, (src_buf[0] != '\0') ? " from " : "", src_buf); - return ZEBRA_ERR_RTNOEXIST; + return; } /* Lookup same type route. */ @@ -2760,7 +2453,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, rib->refcnt--; route_unlock_node (rn); route_unlock_node (rn); - return 0; + return; } same = rib; break; @@ -2827,7 +2520,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, type); } route_unlock_node (rn); - return ZEBRA_ERR_RTNOEXIST; + return; } } @@ -2835,7 +2528,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, rib_delnode (rn, same); route_unlock_node (rn); - return 0; + return; } |
