summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/nexthop.c58
-rw-r--r--lib/nexthop.h19
-rw-r--r--tests/lib/test_nexthop_iter.c112
-rw-r--r--zebra/redistribute.c5
-rw-r--r--zebra/rib.h46
-rw-r--r--zebra/rt_netlink.c15
-rw-r--r--zebra/rt_socket.c12
-rw-r--r--zebra/zebra_fpm_netlink.c12
-rw-r--r--zebra/zebra_fpm_protobuf.c5
-rw-r--r--zebra/zebra_rib.c87
-rw-r--r--zebra/zebra_rnh.c9
-rw-r--r--zebra/zebra_vty.c24
12 files changed, 215 insertions, 189 deletions
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 725b52c052..e9ffea0a0e 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -135,7 +135,7 @@ nexthop_add (struct nexthop **target, struct nexthop *nexthop)
}
void
-copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
+copy_nexthops (struct nexthop **tnh, struct nexthop *nh, struct nexthop *rparent)
{
struct nexthop *nexthop;
struct nexthop *nh1;
@@ -143,18 +143,20 @@ copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
for (nh1 = nh; nh1; nh1 = nh1->next)
{
nexthop = nexthop_new();
- nexthop->flags = nh->flags;
- nexthop->type = nh->type;
nexthop->ifindex = nh->ifindex;
- memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
- memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
+ nexthop->type = nh->type;
+ nexthop->flags = nh->flags;
+ memcpy(&nexthop->gate, &nh->gate, sizeof(nh->gate));
+ memcpy(&nexthop->src, &nh->src, sizeof(nh->src));
+ memcpy(&nexthop->rmap_src, &nh->rmap_src, sizeof(nh->rmap_src));
+ nexthop->rparent = rparent;
if (nh->nh_label)
nexthop_add_labels (nexthop, nh->nh_label_type,
- nh->nh_label->num_labels, &nh->nh_label->label[0]);
+ nh->nh_label->num_labels, &nh->nh_label->label[0]);
nexthop_add(tnh, nexthop);
if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
- copy_nexthops(&nexthop->resolved, nh1->resolved);
+ copy_nexthops(&nexthop->resolved, nh1->resolved, nexthop);
}
}
@@ -241,3 +243,45 @@ nexthop2str (struct nexthop *nexthop, char *str, int size)
return str;
}
+
+/*
+ * Iteration step for ALL_NEXTHOPS macro:
+ * This is the tricky part. Check if `nexthop' has
+ * NEXTHOP_FLAG_RECURSIVE set. If yes, this implies that `nexthop' has
+ * at least one nexthop attached to `nexthop->resolved', which will be
+ * the next one.
+ *
+ * If NEXTHOP_FLAG_RECURSIVE is not set, `nexthop' will progress in its
+ * current chain. In case its current chain end is reached, it will move
+ * upwards in the recursion levels and progress there. Whenever a step
+ * forward in a chain is done, recursion will be checked again.
+ * In a nustshell, it's equivalent to a pre-traversal order assuming that
+ * left branch is 'resolved' and right branch is 'next':
+ * https://en.wikipedia.org/wiki/Tree_traversal#/media/File:Sorted_binary_tree_preorder.svg
+ */
+struct nexthop *
+nexthop_next(struct nexthop *nexthop)
+{
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ return nexthop->resolved;
+
+ if (nexthop->next)
+ return nexthop->next;
+
+ for (struct nexthop *par = nexthop->rparent; par; par = par->rparent)
+ if (par->next)
+ return par->next;
+
+ return NULL;
+}
+
+unsigned int
+nexthop_level(struct nexthop *nexthop)
+{
+ unsigned int rv = 0;
+
+ for (struct nexthop *par = nexthop->rparent; par; par = par->rparent)
+ rv++;
+
+ return rv;
+}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 8c9c801c91..e9d937f94b 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -81,8 +81,10 @@ struct nexthop
* If the nexthop struct needs to be resolved recursively,
* NEXTHOP_FLAG_RECURSIVE will be set in flags and the nexthops
* obtained by recursive resolution will be added to `resolved'.
- * Only one level of recursive resolution is currently supported. */
+ */
struct nexthop *resolved;
+ /* Recursive parent */
+ struct nexthop *rparent;
/* Type of label(s), if any */
enum lsp_types_t nh_label_type;
@@ -91,6 +93,17 @@ struct nexthop
struct nexthop_label *nh_label;
};
+/* The following for loop allows to iterate over the nexthop
+ * structure of routes.
+ *
+ * head: The pointer to the first nexthop in the chain.
+ *
+ * nexthop: The pointer to the current nexthop, either in the
+ * top-level chain or in a resolved chain.
+ */
+#define ALL_NEXTHOPS(head, nexthop) \
+ (nexthop) = (head); (nexthop); (nexthop) = nexthop_next(nexthop)
+
extern int zebra_rnh_ip_default_route;
extern int zebra_rnh_ipv6_default_route;
@@ -107,7 +120,7 @@ nh_resolve_via_default(int family)
struct nexthop *nexthop_new (void);
void nexthop_add (struct nexthop **target, struct nexthop *nexthop);
-void copy_nexthops (struct nexthop **tnh, struct nexthop *nh);
+void copy_nexthops (struct nexthop **tnh, struct nexthop *nh, struct nexthop *rparent);
void nexthop_free (struct nexthop *nexthop);
void nexthops_free (struct nexthop *nexthop);
@@ -119,4 +132,6 @@ extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2
extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2);
extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size);
+extern struct nexthop *nexthop_next(struct nexthop *nexthop);
+extern unsigned int nexthop_level(struct nexthop *nexthop);
#endif /*_LIB_NEXTHOP_H */
diff --git a/tests/lib/test_nexthop_iter.c b/tests/lib/test_nexthop_iter.c
index 77515386c7..18628ec163 100644
--- a/tests/lib/test_nexthop_iter.c
+++ b/tests/lib/test_nexthop_iter.c
@@ -1,6 +1,6 @@
/*
* Recursive Nexthop Iterator test.
- * This tests the ALL_NEXTHOPS_RO macro.
+ * This tests the ALL_NEXTHOPS macro.
*
* Copyright (C) 2012 by Open Source Routing.
* Copyright (C) 2012 by Internet Systems Consortium, Inc. ("ISC")
@@ -108,6 +108,29 @@ nexthop_chain_add_top(struct nexthop_chain *nc)
}
static void
+add_string_representation (char **repr, struct nexthop *nh)
+{
+ struct nexthop *parent;
+
+ /* add indentations first */
+ parent = nh->rparent;
+ while (parent)
+ {
+ str_appendf(repr, " ");
+ parent = parent->rparent;
+ }
+ str_appendf(repr, "%p\n", nh);
+}
+
+static void
+start_recursive_chain (struct nexthop_chain *nc, struct nexthop *nh)
+{
+ SET_FLAG(nc->current_top->flags, NEXTHOP_FLAG_RECURSIVE);
+ nc->current_top->resolved = nh;
+ nh->rparent = nc->current_top;
+ nc->current_recursive = nh;
+}
+static void
nexthop_chain_add_recursive(struct nexthop_chain *nc)
{
struct nexthop *nh;
@@ -120,36 +143,52 @@ nexthop_chain_add_recursive(struct nexthop_chain *nc)
{
nc->current_recursive->next = nh;
nh->prev = nc->current_recursive;
+ nh->rparent = nc->current_recursive->rparent;
nc->current_recursive = nh;
}
else
+ start_recursive_chain (nc, nh);
+
+ add_string_representation (&nc->repr, nh);
+}
+
+static void
+nexthop_chain_add_recursive_level(struct nexthop_chain *nc)
+{
+ struct nexthop *nh;
+
+ nh = calloc(sizeof(*nh), 1);
+ assert(nh);
+
+ assert(nc->current_top);
+ if (nc->current_recursive)
{
- SET_FLAG(nc->current_top->flags, NEXTHOP_FLAG_RECURSIVE);
- nc->current_top->resolved = nh;
+ SET_FLAG(nc->current_recursive->flags, NEXTHOP_FLAG_RECURSIVE);
+ nc->current_recursive->resolved = nh;
+ nh->rparent = nc->current_recursive;
nc->current_recursive = nh;
}
- str_appendf(&nc->repr, " %p\n", nh);
+ else
+ start_recursive_chain (nc, nh);
+
+ add_string_representation (&nc->repr, nh);
}
static void
+nexthop_clear_recursive (struct nexthop *tcur)
+{
+ if (!tcur)
+ return;
+ if (CHECK_FLAG(tcur->flags, NEXTHOP_FLAG_RECURSIVE))
+ nexthop_clear_recursive (tcur->resolved);
+ if (tcur->next)
+ nexthop_clear_recursive (tcur->next);
+ free (tcur);
+}
+static void
nexthop_chain_clear(struct nexthop_chain *nc)
{
- struct nexthop *tcur, *tnext;
-
- for (tcur = nc->head; tcur; tcur = tnext)
- {
- tnext = tcur->next;
- if (CHECK_FLAG(tcur->flags, NEXTHOP_FLAG_RECURSIVE))
- {
- struct nexthop *rcur, *rnext;
- for (rcur = tcur->resolved; rcur; rcur = rnext)
- {
- rnext = rcur->next;
- free(rcur);
- }
- }
- free(tcur);
- }
+ nexthop_clear_recursive (nc->head);
nc->head = nc->current_top = nc->current_recursive = NULL;
free(nc->repr);
nc->repr = NULL;
@@ -165,25 +204,19 @@ nexthop_chain_free(struct nexthop_chain *nc)
}
/* This function builds a string representation of
- * the nexthop chain using the ALL_NEXTHOPS_RO macro.
- * It verifies that the ALL_NEXTHOPS_RO macro iterated
+ * the nexthop chain using the ALL_NEXTHOPS macro.
+ * It verifies that the ALL_NEXTHOPS macro iterated
* correctly over the nexthop chain by comparing the
* generated representation with the expected representation.
*/
static void
nexthop_chain_verify_iter(struct nexthop_chain *nc)
{
- struct nexthop *nh, *tnh;
- int recursing;
+ struct nexthop *nh;
char *repr = NULL;
- for (ALL_NEXTHOPS_RO(nc->head, nh, tnh, recursing))
- {
- if (recursing)
- str_appendf(&repr, " %p\n", nh);
- else
- str_appendf(&repr, "%p\n", nh);
- }
+ for (ALL_NEXTHOPS(nc->head, nh))
+ add_string_representation (&repr, nh);
if (repr && verbose)
printf("===\n%s", repr);
@@ -234,6 +267,18 @@ test_run_first(void)
nexthop_chain_add_recursive(nc);
nexthop_chain_verify_iter(nc);
+ nexthop_chain_add_recursive_level(nc);
+ nexthop_chain_verify_iter(nc);
+
+ nexthop_chain_add_recursive(nc);
+ nexthop_chain_verify_iter(nc);
+
+ nexthop_chain_add_recursive(nc);
+ nexthop_chain_verify_iter(nc);
+
+ nexthop_chain_add_top(nc);
+ nexthop_chain_verify_iter(nc);
+
nexthop_chain_free(nc);
}
@@ -268,10 +313,13 @@ test_run_prng(void)
case 6:
case 7:
case 8:
- case 9:
if (nc->current_top)
nexthop_chain_add_recursive(nc);
break;
+ case 9:
+ if (nc->current_top)
+ nexthop_chain_add_recursive_level(nc);
+ break;
}
nexthop_chain_verify_iter(nc);
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 1b34e46ec4..be7da2565a 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -552,10 +552,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct route_entry *re, con
newre->nexthop_num = 0;
newre->uptime = time(NULL);
newre->instance = re->table;
-
- /* Assuming these routes are never recursive */
- for (nhop = re->nexthop; nhop; nhop = nhop->next)
- route_entry_copy_nexthops(newre, nhop);
+ route_entry_copy_nexthops(newre, re->nexthop);
rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, NULL, newre);
}
diff --git a/zebra/rib.h b/zebra/rib.h
index 88f2bf39ab..999266241a 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -178,52 +178,6 @@ typedef struct rib_dest_t_
#define RNODE_FOREACH_RE_SAFE(rn, re, next) \
RE_DEST_FOREACH_ROUTE_SAFE (rib_dest_from_rnode (rn), re, next)
-/* The following for loop allows to iterate over the nexthop
- * structure of routes.
- *
- * We have to maintain quite a bit of state:
- *
- * nexthop: The pointer to the current nexthop, either in the
- * top-level chain or in the resolved chain of ni.
- * tnexthop: The pointer to the current nexthop in the top-level
- * nexthop chain.
- * recursing: Information if nh currently is in the top-level chain
- * (0) or in a resolved chain (1).
- *
- * Initialization: Set `nexthop' and `tnexthop' to the head of the
- * top-level chain. As nexthop is in the top level chain, set recursing
- * to 0.
- *
- * Iteration check: Check that the `nexthop' pointer is not NULL.
- *
- * Iteration step: This is the tricky part. Check if `nexthop' has
- * NEXTHOP_FLAG_RECURSIVE set. If yes, this implies that `nexthop' is in
- * the top level chain and has at least one nexthop attached to
- * `nexthop->resolved'. As we want to descend into `nexthop->resolved',
- * set `recursing' to 1 and set `nexthop' to `nexthop->resolved'.
- * `tnexthop' is left alone in that case so we can remember which nexthop
- * in the top level chain we are currently handling.
- *
- * If NEXTHOP_FLAG_RECURSIVE is not set, `nexthop' will progress in its
- * current chain. If we are recursing, `nexthop' will be set to
- * `nexthop->next' and `tnexthop' will be left alone. If we are not
- * recursing, both `tnexthop' and `nexthop' will be set to `nexthop->next'
- * as we are progressing in the top level chain.
- * If we encounter `nexthop->next == NULL', we will clear the `recursing'
- * flag as we arived either at the end of the resolved chain or at the end
- * of the top level chain. In both cases, we set `tnexthop' and `nexthop'
- * to `tnexthop->next', progressing to the next position in the top-level
- * chain and possibly to its end marked by NULL.
- */
-#define ALL_NEXTHOPS_RO(head, nexthop, tnexthop, recursing) \
- (tnexthop) = (nexthop) = (head), (recursing) = 0; \
- (nexthop); \
- (nexthop) = CHECK_FLAG((nexthop)->flags, NEXTHOP_FLAG_RECURSIVE) \
- ? (((recursing) = 1), (nexthop)->resolved) \
- : ((nexthop)->next ? ((recursing) ? (nexthop)->next \
- : ((tnexthop) = (nexthop)->next)) \
- : (((recursing) = 0),((tnexthop) = (tnexthop)->next)))
-
#if defined (HAVE_RTADV)
/* Structure which hold status of router advertisement. */
struct rtadv
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 471f650588..b7e452a0bc 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1209,8 +1209,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
{
int bytelen;
struct sockaddr_nl snl;
- struct nexthop *nexthop = NULL, *tnexthop;
- int recursing;
+ struct nexthop *nexthop = NULL;
unsigned int nexthop_num;
int discard;
int family = PREFIX_FAMILY(p);
@@ -1302,7 +1301,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
if (discard)
{
if (cmd == RTM_NEWROUTE)
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
/* We shouldn't encounter recursive nexthops on discard routes,
* but it is probably better to handle that case correctly anyway.
@@ -1316,7 +1315,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
/* Count overall nexthops so we can decide whether to use singlepath
* or multipath case. */
nexthop_num = 0;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
@@ -1332,7 +1331,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
if (nexthop_num == 1 || multipath_num == 1)
{
nexthop_num = 0;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
{
@@ -1373,7 +1372,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
|| (cmd == RTM_DELROUTE
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
{
- routedesc = recursing ? "recursive, 1 hop" : "single hop";
+ routedesc = nexthop->rparent ? "recursive, 1 hop" : "single hop";
_netlink_route_debug(cmd, p, nexthop, routedesc, family, zvrf);
_netlink_route_build_singlepath(routedesc, bytelen,
@@ -1403,7 +1402,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
rtnh = RTA_DATA (rta);
nexthop_num = 0;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (nexthop_num >= multipath_num)
break;
@@ -1448,7 +1447,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct prefix *src_p,
|| (cmd == RTM_DELROUTE
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
{
- routedesc = recursing ? "recursive, multihop" : "multihop";
+ routedesc = nexthop->rparent ? "recursive, multihop" : "multihop";
nexthop_num++;
_netlink_route_debug(cmd, p, nexthop,
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 9859a31627..3ae09945b2 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -80,8 +80,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct route_entry *re)
struct sockaddr_mpls smpls;
#endif
union sockunion *smplsp = NULL;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
int nexthop_num = 0;
ifindex_t ifindex = 0;
int gate = 0;
@@ -106,7 +105,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct route_entry *re)
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
/* Make gateway. */
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
@@ -226,7 +225,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct route_entry *re)
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug ("%s: odd command %s for flags %d",
__func__, lookup_msg(rtm_type_str, cmd, NULL), nexthop->flags);
- } /* for (ALL_NEXTHOPS_RO(...))*/
+ } /* for (ALL_NEXTHOPS(...))*/
/* If there was no useful nexthop, then complain. */
if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL)
@@ -266,8 +265,7 @@ kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re)
{
struct sockaddr_in6 *mask;
struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
int nexthop_num = 0;
ifindex_t ifindex = 0;
int gate = 0;
@@ -289,7 +287,7 @@ kernel_rtm_ipv6 (int cmd, struct prefix *p, struct route_entry *re)
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
/* Make gateway. */
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index c5647debc3..d935826db2 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -154,8 +154,7 @@ typedef struct netlink_route_info_t_
* Returns TRUE if a nexthop was added, FALSE otherwise.
*/
static int
-netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop,
- int recursive)
+netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop)
{
netlink_nh_info_t nhi;
union g_addr *src;
@@ -166,7 +165,7 @@ netlink_route_info_add_nh (netlink_route_info_t *ri, struct nexthop *nexthop,
if (ri->num_nhs >= (int) ZEBRA_NUM_OF (ri->nhs))
return 0;
- nhi.recursive = recursive;
+ nhi.recursive = nexthop->rparent ? 1 : 0;
nhi.type = nexthop->type;
nhi.if_index = nexthop->ifindex;
@@ -233,8 +232,7 @@ static int
netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
rib_dest_t *dest, struct route_entry *re)
{
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
int discard;
memset (ri, 0, sizeof (*ri));
@@ -286,7 +284,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
if (discard)
return 1;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (ri->num_nhs >= multipath_num)
break;
@@ -299,7 +297,7 @@ netlink_route_info_fill (netlink_route_info_t *ri, int cmd,
|| (cmd == RTM_DELROUTE
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
{
- netlink_route_info_add_nh (ri, nexthop, recursing);
+ netlink_route_info_add_nh (ri, nexthop);
}
}
diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c
index 375fde921e..1e8af19ea7 100644
--- a/zebra/zebra_fpm_protobuf.c
+++ b/zebra/zebra_fpm_protobuf.c
@@ -145,8 +145,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
{
Fpm__AddRoute *msg;
int discard;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
uint num_nhs, u;
struct nexthop *nexthops[MULTIPATH_NUM];
@@ -195,7 +194,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest,
* Figure out the set of nexthops to be added to the message.
*/
num_nhs = 0;
- for (ALL_NEXTHOPS_RO (re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS (re->nexthop, nexthop))
{
if (num_nhs >= multipath_num)
break;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index c2af0a0d22..b07a0cf05d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -198,20 +198,10 @@ route_entry_nexthop_add (struct route_entry *re, struct nexthop *nexthop)
void
route_entry_copy_nexthops (struct route_entry *re, struct nexthop *nh)
{
- struct nexthop *nexthop;
-
- nexthop = nexthop_new();
- nexthop->flags = nh->flags;
- nexthop->type = nh->type;
- nexthop->ifindex = nh->ifindex;
- memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
- memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
- if (nh->nh_label)
- nexthop_add_labels (nexthop, nh->nh_label_type, nh->nh_label->num_labels,
- &nh->nh_label->label[0]);
- route_entry_nexthop_add(re, nexthop);
- if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
- copy_nexthops(&nexthop->resolved, nh->resolved);
+ assert(!re->nexthop);
+ copy_nexthops(&re->nexthop, nh, NULL);
+ for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next)
+ re->nexthop_num++;
}
/* Delete specified nexthop from the list. */
@@ -389,6 +379,7 @@ nexthop_set_resolved (afi_t afi, struct nexthop *newhop, struct nexthop *nexthop
resolved_hop->ifindex = newhop->ifindex;
}
+ resolved_hop->rparent = nexthop;
nexthop_add(&nexthop->resolved, resolved_hop);
}
@@ -403,8 +394,7 @@ nexthop_active (afi_t afi, struct route_entry *re, struct nexthop *nexthop, int
struct route_node *rn;
struct route_entry *match;
int resolved;
- struct nexthop *newhop, *tnewhop;
- int recursing = 0;
+ struct nexthop *newhop;
struct interface *ifp;
if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6)
@@ -528,7 +518,7 @@ nexthop_active (afi_t afi, struct route_entry *re, struct nexthop *nexthop, int
else if (CHECK_FLAG (re->flags, ZEBRA_FLAG_INTERNAL))
{
resolved = 0;
- for (newhop = match->nexthop; newhop; newhop = newhop->next)
+ for (ALL_NEXTHOPS(match->nexthop, newhop))
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB)
&& ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE))
{
@@ -546,7 +536,7 @@ nexthop_active (afi_t afi, struct route_entry *re, struct nexthop *nexthop, int
else if (re->type == ZEBRA_ROUTE_STATIC)
{
resolved = 0;
- for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
+ for (ALL_NEXTHOPS(match->nexthop, newhop))
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
{
if (set)
@@ -577,8 +567,7 @@ rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id,
struct route_table *table;
struct route_node *rn;
struct route_entry *match;
- struct nexthop *newhop, *tnewhop;
- int recursing;
+ struct nexthop *newhop;
/* Lookup table. */
table = zebra_vrf_table (afi, safi, vrf_id);
@@ -628,7 +617,7 @@ rib_match (afi_t afi, safi_t safi, vrf_id_t vrf_id,
if (match->type != ZEBRA_ROUTE_CONNECT)
{
int found = 0;
- for (ALL_NEXTHOPS_RO(match->nexthop, newhop, tnewhop, recursing))
+ for (ALL_NEXTHOPS(match->nexthop, newhop))
if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB))
{
found = 1;
@@ -724,8 +713,7 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
struct route_table *table;
struct route_node *rn;
struct route_entry *match;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
/* Lookup table. */
table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
@@ -754,8 +742,8 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p, vrf_id_t vrf_id)
if (match->type == ZEBRA_ROUTE_CONNECT)
return match;
-
- for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
+
+ for (ALL_NEXTHOPS(match->nexthop, nexthop))
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
return match;
@@ -781,8 +769,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
struct route_table *table;
struct route_node *rn;
struct route_entry *match;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
int nexthops_active;
/* Lookup table. */
@@ -818,7 +805,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
/* Ok, we have a cood candidate, let's check it's nexthop list... */
nexthops_active = 0;
- for (ALL_NEXTHOPS_RO(match->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(match->nexthop, nexthop))
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
{
nexthops_active = 1;
@@ -830,7 +817,7 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate,
inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN);
inet_ntop (AF_INET, &sockunion2ip(qgate), qgate_buf, INET_ADDRSTRLEN);
zlog_debug ("%s: qgate == %s, %s == %s", __func__,
- qgate_buf, recursing ? "rgate" : "gate", gate_buf);
+ qgate_buf, nexthop->rparent ? "rgate" : "gate", gate_buf);
}
}
@@ -1025,13 +1012,12 @@ nexthop_active_update (struct route_node *rn, struct route_entry *re, int set)
int
zebra_rib_labeled_unicast (struct route_entry *re)
{
- struct nexthop *nexthop = NULL, *tnexthop;
- int recursing;
+ struct nexthop *nexthop = NULL;
if (re->type != ZEBRA_ROUTE_BGP)
return 0;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
return 0;
@@ -1045,9 +1031,8 @@ int
rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_entry *old)
{
int ret = 0;
- struct nexthop *nexthop, *tnexthop;
+ struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
- int recursing;
struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id);
@@ -1055,7 +1040,7 @@ rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_
if (info->safi != SAFI_UNICAST)
{
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
return ret;
}
@@ -1071,7 +1056,7 @@ rib_install_kernel (struct route_node *rn, struct route_entry *re, struct route_
/* If install succeeds, update FIB flag for nexthops. */
if (!ret)
{
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
@@ -1091,9 +1076,8 @@ int
rib_uninstall_kernel (struct route_node *rn, struct route_entry *re)
{
int ret = 0;
- struct nexthop *nexthop, *tnexthop;
+ struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
- int recursing;
struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup (re->vrf_id);
@@ -1101,7 +1085,7 @@ rib_uninstall_kernel (struct route_node *rn, struct route_entry *re)
if (info->safi != SAFI_UNICAST)
{
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
return ret;
}
@@ -1114,7 +1098,7 @@ rib_uninstall_kernel (struct route_node *rn, struct route_entry *re)
ret = kernel_route_rib (p, src_p, re, NULL);
zvrf->removals++;
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
return ret;
@@ -1284,8 +1268,7 @@ static void
rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *old, struct route_entry *new)
{
- struct nexthop *nexthop = NULL, *tnexthop;
- int recursing;
+ struct nexthop *nexthop = NULL;
int nh_active = 0;
int installed = 1;
@@ -1403,7 +1386,7 @@ rib_process_update_fib (struct zebra_vrf *zvrf, struct route_node *rn,
{
int in_fib = 0;
- for (ALL_NEXTHOPS_RO(new->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(new->nexthop, nexthop))
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
{
in_fib = 1;
@@ -1634,13 +1617,11 @@ rib_process (struct route_node *rn)
/* Redistribute SELECTED entry */
if (old_selected != new_selected || selected_changed)
{
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
/* Check if we have a FIB route for the destination, otherwise,
* don't redistribute it */
- for (ALL_NEXTHOPS_RO(new_fib ? new_fib->nexthop : NULL, nexthop,
- tnexthop, recursing))
+ for (ALL_NEXTHOPS(new_fib ? new_fib->nexthop : NULL, nexthop))
{
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
{
@@ -2141,8 +2122,7 @@ void _route_entry_dump (const char * func,
bool is_srcdst = src_p && src_p->prefixlen;
char straddr[PREFIX_STRLEN];
char srcaddr[PREFIX_STRLEN];
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
zlog_debug ("%s: dumping RE entry %p for %s%s%s vrf %u", func, (const void *)re,
prefix2str(pp, straddr, sizeof(straddr)),
@@ -2177,14 +2157,14 @@ void _route_entry_dump (const char * func,
re->nexthop_active_num
);
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
inet_ntop (p->family, &nexthop->gate, straddr, INET6_ADDRSTRLEN);
zlog_debug
(
"%s: %s %s with flags %s%s%s",
func,
- (recursing ? " NH" : "NH"),
+ (nexthop->rparent ? " NH" : "NH"),
straddr,
(CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE) ? "ACTIVE " : ""),
(CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? "FIB " : ""),
@@ -2391,8 +2371,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
struct route_entry *re;
struct route_entry *fib = NULL;
struct route_entry *same = NULL;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
char buf2[INET6_ADDRSTRLEN];
assert(!src_p || afi == AFI_IP6);
@@ -2463,7 +2442,7 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
same = re;
break;
}
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
if (IPV4_ADDR_SAME (&nexthop->gate.ipv4, gate) ||
IPV6_ADDR_SAME (&nexthop->gate.ipv6, gate))
{
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 5dc504b41b..12bb19935b 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -420,12 +420,11 @@ zebra_rnh_eval_import_check_entry (vrf_id_t vrfid, int family, int force,
struct zserv *client;
char bufn[INET6_ADDRSTRLEN];
struct listnode *node;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
if (re && (rnh->state == NULL))
{
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
{
state_changed = 1;
@@ -831,7 +830,6 @@ static void
copy_state (struct rnh *rnh, struct route_entry *re, struct route_node *rn)
{
struct route_entry *state;
- struct nexthop *nh;
if (rnh->state)
{
@@ -846,8 +844,7 @@ copy_state (struct rnh *rnh, struct route_entry *re, struct route_node *rn)
state->type = re->type;
state->metric = re->metric;
- for (nh = re->nexthop; nh; nh = nh->next)
- route_entry_copy_nexthops(state, nh);
+ route_entry_copy_nexthops(state, re->nexthop);
rnh->state = state;
}
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 1b39383082..363c31283f 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -640,8 +640,7 @@ static void
vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
{
struct route_entry *re;
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
char buf[SRCDEST2STR_BUFFER];
struct zebra_vrf *zvrf;
@@ -712,13 +711,13 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast)
vty_out (vty, " ago%s", VTYNL);
}
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
- {
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
+ {
char addrstr[32];
vty_out (vty, " %c%s",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
- recursing ? " " : "");
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) ? '*' : ' ',
+ nexthop->rparent ? " " : "");
switch (nexthop->type)
{
@@ -798,8 +797,7 @@ static void
vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *re,
json_object *json)
{
- struct nexthop *nexthop, *tnexthop;
- int recursing;
+ struct nexthop *nexthop;
int len = 0;
char buf[SRCDEST2STR_BUFFER];
json_object *json_nexthops = NULL;
@@ -860,7 +858,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *r
json_object_string_add(json_route, "uptime", buf);
}
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
json_nexthop = json_object_new_object();
@@ -954,7 +952,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *r
}
/* Nexthop information. */
- for (ALL_NEXTHOPS_RO(re->nexthop, nexthop, tnexthop, recursing))
+ for (ALL_NEXTHOPS(re->nexthop, nexthop))
{
if (nexthop == re->nexthop)
{
@@ -977,9 +975,9 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct route_entry *r
}
else
vty_out (vty, " %c%*c",
- CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*' : ' ',
- len - 3 + (2 * recursing), ' ');
+ CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
+ ? '*' : ' ',
+ len - 3 + (2 * nexthop_level(nexthop)), ' ');
switch (nexthop->type)
{