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.c175
1 files changed, 72 insertions, 103 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index e47499b065..0e1df1cc35 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);
@@ -2814,6 +2781,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;