diff options
| -rw-r--r-- | lib/nexthop.c | 58 | ||||
| -rw-r--r-- | lib/nexthop.h | 19 | ||||
| -rw-r--r-- | tests/lib/test_nexthop_iter.c | 112 | ||||
| -rw-r--r-- | zebra/redistribute.c | 5 | ||||
| -rw-r--r-- | zebra/rib.h | 46 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 15 | ||||
| -rw-r--r-- | zebra/rt_socket.c | 12 | ||||
| -rw-r--r-- | zebra/zebra_fpm_netlink.c | 12 | ||||
| -rw-r--r-- | zebra/zebra_fpm_protobuf.c | 5 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 87 | ||||
| -rw-r--r-- | zebra/zebra_rnh.c | 9 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 24 |
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) { |
