diff options
| -rw-r--r-- | COMMUNITY.md | 30 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 14 | ||||
| -rw-r--r-- | lib/zclient.c | 2 | ||||
| -rw-r--r-- | lib/zebra.h | 2 | ||||
| -rw-r--r-- | nhrpd/nhrp_route.c | 2 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 267 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.h | 3 | ||||
| -rw-r--r-- | ospf6d/ospf6_route.c | 26 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.c | 27 | ||||
| -rw-r--r-- | ospfd/ospf_sr.c | 14 | ||||
| -rw-r--r-- | pimd/TODO | 372 | ||||
| -rw-r--r-- | sharpd/sharp_zebra.c | 1 | ||||
| -rw-r--r-- | tests/.gitignore | 4 | ||||
| -rw-r--r-- | tests/lib/test_ringbuf.py | 4 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 2 | ||||
| -rw-r--r-- | zebra/zserv.c | 10 |
16 files changed, 338 insertions, 442 deletions
diff --git a/COMMUNITY.md b/COMMUNITY.md index 0eee524d58..081f7ab3b8 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -492,6 +492,36 @@ In all cases, compatibility pieces should be marked with compiler/preprocessor annotations to print warnings at compile time, pointing to the appropriate update path. A `-Werror` build should fail if compatibility bits are used. +### Release Process/Schedule + +FRR employs a <MAJOR>.<MINOR>.<BUGFIX> versioning scheme. + +* MAJOR - Significant new features or multiple minor features + A example of a MAJOR feature is a New Routing Protocol +* MINOR - Smaller Features + A example of a MINOR feature is the addition of the BGP Shutdown feature. +* BUGFIX - Fixes for actual bugs and/or security issues. + +We will pull a new development branch for the next release every 4 months. +The current schedule is Feb/June/October 1. The decision for a MAJOR/MINOR +release is made at the time of branch pull based on what has been received +the previous 4 months. The branch name will be dev/MAJOR.MINOR. At +this point in time the master branch configure.ac and packaging systems +will be updated to reflect the next possible release name to allow +for easy distinguishing. Additionally the new dev branch will have +these files updated too. + +After one month the development branch will be renamed to +stable/MAJOR.MINOR. This process is not held up unless a crash or +security issue has been found and needs to be addressed. Issues +being fixed will not cause a delay. + +Bug fix releases are at 1 month intervals until next MAJOR.MINOR is +pulled. Then at that time as needed for issues filed. + +Security issues are fixed for 1 year minimum on old releases and +normal bug fixes for the current and previous release + ### Miscellaneous When in doubt, follow the guidelines in the Linux kernel style guide, or ask on diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1da6136428..029b3d4d36 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1026,14 +1026,14 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED || info->sub_type == BGP_ROUTE_AGGREGATE) { SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); - SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); /* Metric is currently based on the best-path only */ metric = info->attr->med; @@ -1054,6 +1054,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, else continue; + api_nh = &api.nexthops[valid_nh_count]; + api_nh->vrf_id = bgp->vrf_id; + if (nh_family == AF_INET) { struct in_addr *nexthop; @@ -1078,9 +1081,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, nexthop = &mpinfo_cp->attr->nexthop; - api_nh = &api.nexthops[valid_nh_count]; api_nh->gate.ipv4 = *nexthop; - api_nh->vrf_id = bgp->vrf_id; /* EVPN type-2 routes are programmed as onlink on l3-vni SVI */ @@ -1135,7 +1136,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, if (ifindex == 0) continue; - api_nh = &api.nexthops[valid_nh_count]; api_nh->gate.ipv6 = *nexthop; api_nh->ifindex = ifindex; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; @@ -1265,14 +1265,14 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE); if (peer->sort == BGP_PEER_IBGP) { - SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.flags, ZEBRA_FLAG_IBGP); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) || bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK)) - SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); if (bgp_debug_zebra(p)) { char buf[PREFIX_STRLEN]; diff --git a/lib/zclient.c b/lib/zclient.c index ad91eb504b..01d8838e1f 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1085,7 +1085,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) STREAM_GETC(s, api->message); STREAM_GETC(s, api->safi); if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE)) - stream_get(&(api->rmac), s, sizeof(struct ethaddr)); + STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr)); /* Prefix. */ STREAM_GETC(s, api->prefix.family); diff --git a/lib/zebra.h b/lib/zebra.h index b9a795d160..11bf764b63 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -402,7 +402,7 @@ extern const char *zserv_command_string(unsigned int command); #define strmatch(a,b) (!strcmp((a), (b))) /* Zebra message flags */ -#define ZEBRA_FLAG_INTERNAL 0x01 +#define ZEBRA_FLAG_ALLOW_RECURSION 0x01 #define ZEBRA_FLAG_SELFROUTE 0x02 #define ZEBRA_FLAG_IBGP 0x08 #define ZEBRA_FLAG_SELECTED 0x10 diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index d43aa4929e..8178a8b4b5 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -114,7 +114,7 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE); break; } - SET_FLAG(api.flags, ZEBRA_FLAG_INTERNAL); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 11f9e7c7b6..b52f1cef6c 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -204,26 +204,142 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, { struct ospf6_route *old_route; struct ospf6_path *ecmp_path, *o_path = NULL; - struct listnode *anode; + struct listnode *anode, *anext; struct listnode *nnode, *rnode, *rnext; struct ospf6_nexthop *nh, *rnh; char buf[PREFIX2STR_BUFFER]; bool route_found = false; + /* check for old entry match with new route origin, + * delete old entry. + */ for (old_route = old; old_route; old_route = old_route->next) { - if (ospf6_route_is_same(old_route, route) && - (old_route->path.type == route->path.type) && - (old_route->path.cost == route->path.cost) && - (old_route->path.u.cost_e2 == route->path.u.cost_e2)) { + bool route_updated = false; + + if (!ospf6_route_is_same(old_route, route) || + (old_route->path.type != route->path.type)) + continue; + + /* Current and New route has same origin, + * delete old entry. + */ + for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, + o_path)) { + /* Check old route path and route has same + * origin. + */ + if (o_path->area_id != route->path.area_id || + (memcmp(&(o_path)->origin, &(route)->path.origin, + sizeof(struct ospf6_ls_origin)) != 0)) + continue; + + /* Cost is not same then delete current path */ + if ((o_path->cost == route->path.cost) && + (o_path->u.cost_e2 == route->path.u.cost_e2)) + continue; if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { prefix2str(&old_route->prefix, buf, sizeof(buf)); - zlog_debug("%s: old route %s path cost %u [%u]", + zlog_debug("%s: route %s cost old %u new %u is not same, replace route", + __PRETTY_FUNCTION__, buf, + o_path->cost, route->path.cost); + } + + /* Remove selected current rout path's nh from + * effective nh list. + */ + for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) { + for (ALL_LIST_ELEMENTS(old_route->nh_list, + rnode, rnext, rnh)) { + if (!ospf6_nexthop_is_same(rnh, nh)) + continue; + listnode_delete(old_route->nh_list, + rnh); + ospf6_nexthop_delete(rnh); + route_updated = true; + } + } + + listnode_delete(old_route->paths, o_path); + ospf6_path_free(o_path); + + /* Current route's path (adv_router info) is similar + * to route being added. + * Replace current route's path with paths list head. + * Update FIB with effective NHs. + */ + if (listcount(old_route->paths)) { + if (old_route->path.origin.id == + route->path.origin.id && + old_route->path.origin.adv_router == + route->path.origin.adv_router) { + struct ospf6_path *h_path; + + h_path = (struct ospf6_path *) + listgetdata(listhead(old_route->paths)); + old_route->path.origin.type = + h_path->origin.type; + old_route->path.origin.id = + h_path->origin.id; + old_route->path.origin.adv_router = + h_path->origin.adv_router; + } + + if (route_updated) { + for (ALL_LIST_ELEMENTS(old_route->paths, + anode, anext, o_path)) { + ospf6_merge_nexthops( + old_route->nh_list, + o_path->nh_list); + } + /* Update RIB/FIB with effective + * nh_list + */ + if (ospf6->route_table->hook_add) + (*ospf6->route_table->hook_add) + (old_route); + break; + } + } else { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&old_route->prefix, buf, + sizeof(buf)); + zlog_debug("%s: route %s old cost %u new cost %u, delete old entry.", + __PRETTY_FUNCTION__, buf, + old_route->path.cost, + route->path.cost); + } + ospf6_route_remove(old_route, + ospf6->route_table); + break; + } + } + if (route_updated) + break; + } + + /* Add new route */ + for (old_route = old; old_route; old_route = old_route->next) { + + /* Current and New Route prefix or route type + * is not same skip this current node. + */ + if (!ospf6_route_is_same(old_route, route) || + (old_route->path.type != route->path.type)) + continue; + + /* Old Route and New Route have Equal Cost, Merge NHs */ + if ((old_route->path.cost == route->path.cost) && + (old_route->path.u.cost_e2 == route->path.u.cost_e2)) { + + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&old_route->prefix, buf, + sizeof(buf)); + zlog_debug("%s: old route %s path cost %u e2 %u", __PRETTY_FUNCTION__, buf, old_route->path.cost, - ospf6_route_is_same(old_route, - route)); + old_route->path.u.cost_e2); } route_found = true; /* check if this path exists already in @@ -232,9 +348,10 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, */ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) { - if ((o_path->origin.id == route->path.origin.id) - && (o_path->origin.adv_router == - route->path.origin.adv_router)) + if (o_path->area_id == route->path.area_id && + (memcmp(&(o_path)->origin, + &(route)->path.origin, + sizeof(struct ospf6_ls_origin)) == 0)) break; } /* If path is not found in old_route paths's list, @@ -262,12 +379,13 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { prefix2str(&route->prefix, buf, sizeof(buf)); - zlog_debug("%s: route %s another path added with nh %u, Paths %u", + zlog_debug("%s: route %s another path added with nh %u, effective paths %u nh %u", __PRETTY_FUNCTION__, buf, listcount(ecmp_path->nh_list), old_route->paths ? listcount(old_route->paths) - : 0); + : 0, + listcount(old_route->nh_list)); } } else { for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, @@ -313,6 +431,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, * route. */ ospf6_route_delete(route); + break; } } @@ -426,11 +545,12 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa) } -void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) +void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa, + struct ospf6_route *asbr_entry) { struct ospf6_as_external_lsa *external; struct prefix prefix; - struct ospf6_route *route, *nroute; + struct ospf6_route *route, *nroute, *route_to_del; char buf[PREFIX2STR_BUFFER]; external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END( @@ -445,6 +565,35 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) return; } + route_to_del = ospf6_route_create(); + route_to_del->type = OSPF6_DEST_TYPE_NETWORK; + route_to_del->prefix.family = AF_INET6; + route_to_del->prefix.prefixlen = external->prefix.prefix_length; + ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6, + &external->prefix); + + route_to_del->path.origin.type = lsa->header->type; + route_to_del->path.origin.id = lsa->header->id; + route_to_del->path.origin.adv_router = lsa->header->adv_router; + + if (asbr_entry) { + route_to_del->path.area_id = asbr_entry->path.area_id; + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) { + route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL2; + route_to_del->path.metric_type = 2; + route_to_del->path.cost = asbr_entry->path.cost; + route_to_del->path.u.cost_e2 = + OSPF6_ASBR_METRIC(external); + } else { + route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL1; + route_to_del->path.metric_type = 1; + route_to_del->path.cost = + asbr_entry->path.cost + + OSPF6_ASBR_METRIC(external); + route_to_del->path.u.cost_e2 = 0; + } + } + memset(&prefix, 0, sizeof(struct prefix)); prefix.family = AF_INET6; prefix.prefixlen = external->prefix.prefix_length; @@ -459,14 +608,25 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) return; } - for (ospf6_route_lock(route); - route && ospf6_route_is_prefix(&prefix, route); route = nroute) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&prefix, buf, sizeof(buf)); + zlog_debug("%s: Current route %s cost %u e2 %u, route to del cost %u e2 %u", + __PRETTY_FUNCTION__, buf, route->path.cost, + route->path.u.cost_e2, + route_to_del->path.cost, + route_to_del->path.u.cost_e2); + } + + for (ospf6_route_lock(route); route && + ospf6_route_is_prefix(&prefix, route); route = nroute) { nroute = ospf6_route_next(route); + if (route->type != OSPF6_DEST_TYPE_NETWORK) continue; - /* Route has multiple ECMP paths remove, - * matching path and update effective route's nh list. + /* Route has multiple ECMP paths, remove matching + * path. Update current route's effective nh list + * after removal of one of the path. */ if (listcount(route->paths) > 1) { struct listnode *anode, *anext; @@ -481,18 +641,36 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) */ for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) { - if (o_path->origin.type != lsa->header->type) - continue; - if (o_path->origin.id != lsa->header->id) + if ((o_path->origin.type != lsa->header->type) + || (o_path->origin.adv_router != + lsa->header->adv_router) || + (o_path->origin.id != lsa->header->id)) continue; - if (o_path->origin.adv_router != - lsa->header->adv_router) + + /* Compare LSA cost with current + * route info. + */ + if (!asbr_entry && (o_path->cost != + route_to_del->path.cost || + o_path->u.cost_e2 != + route_to_del->path.u.cost_e2)) { + if (IS_OSPF6_DEBUG_EXAMIN( + AS_EXTERNAL)) { + prefix2str(&prefix, buf, + sizeof(buf)); + zlog_debug( + "%s: route %s to delete is not same, cost %u del cost %u. skip", + __PRETTY_FUNCTION__, buf, + route->path.cost, + route_to_del->path.cost); + } continue; + } if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { prefix2str(&prefix, buf, sizeof(buf)); zlog_debug( - "%s: route %s path found with nh %u", + "%s: route %s path found with nh %u to remove.", __PRETTY_FUNCTION__, buf, listcount(o_path->nh_list)); } @@ -542,13 +720,13 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) listcount(route->nh_list)); } - /* Update RIB/FIB w/ effective nh_list */ + /* Update RIB/FIB with effective nh_list */ if (ospf6->route_table->hook_add) (*ospf6->route_table->hook_add)(route); - /* route's path is similar to lsa header, - * replace route's path with route's - * paths list head. + /* route's primary path is similar to LSA, + * replace route's primary path with + * route's paths list head. */ if (route->path.origin.id == lsa->header->id && route->path.origin.adv_router == @@ -568,12 +746,29 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) continue; } else { - if (route->path.origin.type != lsa->header->type) - continue; - if (route->path.origin.id != lsa->header->id) + /* Compare LSA origin and cost with current route info. + * if any check fails skip del this route node. + */ + if (asbr_entry && (!ospf6_route_is_same_origin(route, + route_to_del) || + (route->path.type != route_to_del->path.type) || + (route->path.cost != route_to_del->path.cost) || + (route->path.u.cost_e2 != + route_to_del->path.u.cost_e2))) { + if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { + prefix2str(&prefix, buf, sizeof(buf)); + zlog_debug("%s: route %s to delete is not same, cost %u del cost %u. skip", + __PRETTY_FUNCTION__, buf, + route->path.cost, + route_to_del->path.cost); + } continue; - if (route->path.origin.adv_router != - lsa->header->adv_router) + } + + if ((route->path.origin.type != lsa->header->type) || + (route->path.origin.adv_router != + lsa->header->adv_router) || + (route->path.origin.id != lsa->header->id)) continue; } if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { @@ -589,6 +784,8 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa) } if (route != NULL) ospf6_route_unlock(route); + + ospf6_route_delete(route_to_del); } void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry) @@ -622,7 +819,7 @@ void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry) type = htons(OSPF6_LSTYPE_AS_EXTERNAL); router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix); for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa)) - ospf6_asbr_lsa_remove(lsa); + ospf6_asbr_lsa_remove(lsa, asbr_entry); } diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h index cc4f0272aa..bd160a6456 100644 --- a/ospf6d/ospf6_asbr.h +++ b/ospf6d/ospf6_asbr.h @@ -71,7 +71,8 @@ struct ospf6_as_external_lsa { } extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa); -extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa); +extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa, + struct ospf6_route *asbr_entry); extern void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry); extern void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 19eb9a3fe6..ef0a093d13 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -469,6 +469,8 @@ int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb) if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { if (ra->path.u.cost_e2 != rb->path.u.cost_e2) return (ra->path.u.cost_e2 - rb->path.u.cost_e2); + else + return (ra->path.cost - rb->path.cost); } else { if (ra->path.cost != rb->path.cost) return (ra->path.cost - rb->path.cost); @@ -627,10 +629,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route, if (ospf6_route_is_identical(old, route)) { if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) zlog_debug( - "%s %p: route add %p: needless update of %p", + "%s %p: route add %p: needless update of %p old cost %u", ospf6_route_table_name(table), (void *)table, (void *)route, - (void *)old); + (void *)old, old->path.cost); else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) zlog_debug("%s: route add: needless update", ospf6_route_table_name(table)); @@ -645,9 +647,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route, } if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) - zlog_debug("%s %p: route add %p: update of %p", + zlog_debug("%s %p: route add %p cost %u: update of %p old cost %u", ospf6_route_table_name(table), (void *)table, - (void *)route, (void *)old); + (void *)route, route->path.cost, (void *)old, + old->path.cost); else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) zlog_debug("%s: route add: update", ospf6_route_table_name(table)); @@ -686,13 +689,14 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route, if (prev || next) { if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) zlog_debug( - "%s %p: route add %p: another path: prev %p, next %p node refcount %u", + "%s %p: route add %p cost %u: another path: prev %p, next %p node ref %u", ospf6_route_table_name(table), (void *)table, - (void *)route, (void *)prev, (void *)next, - node->lock); + (void *)route, route->path.cost, (void *)prev, + (void *)next, node->lock); else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) - zlog_debug("%s: route add: another path found", - ospf6_route_table_name(table)); + zlog_debug("%s: route add cost %u: another path found", + ospf6_route_table_name(table), + route->path.cost); if (prev == NULL) prev = next->prev; @@ -814,9 +818,9 @@ void ospf6_route_remove(struct ospf6_route *route, prefix2str(&route->prefix, buf, sizeof(buf)); if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) - zlog_debug("%s %p: route remove %p: %s refcount %u", + zlog_debug("%s %p: route remove %p: %s cost %u refcount %u", ospf6_route_table_name(table), (void *)table, - (void *)route, buf, route->lock); + (void *)route, buf, route->path.cost, route->lock); else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) zlog_debug("%s: route remove: %s", ospf6_route_table_name(table), buf); diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 25d968fb68..afe2d7397b 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -72,7 +72,7 @@ static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa) { switch (ntohs(lsa->header->type)) { case OSPF6_LSTYPE_AS_EXTERNAL: - ospf6_asbr_lsa_remove(lsa); + ospf6_asbr_lsa_remove(lsa, NULL); break; default: @@ -96,11 +96,16 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route) static void ospf6_top_brouter_hook_add(struct ospf6_route *route) { if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { - char buf[PREFIX2STR_BUFFER]; - - prefix2str(&route->prefix, buf, sizeof(buf)); - zlog_debug("%s: brouter %s add with nh count %u", - __PRETTY_FUNCTION__, buf, listcount(route->nh_list)); + uint32_t brouter_id; + char brouter_name[16]; + + brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, + sizeof(brouter_name)); + zlog_debug("%s: brouter %s add with adv router %x nh count %u", + __PRETTY_FUNCTION__, brouter_name, + route->path.origin.adv_router, + listcount(route->nh_list)); } ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix)); ospf6_asbr_lsentry_add(route); @@ -110,11 +115,15 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route) static void ospf6_top_brouter_hook_remove(struct ospf6_route *route) { if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) { - char buf[PREFIX2STR_BUFFER]; + uint32_t brouter_id; + char brouter_name[16]; - prefix2str(&route->prefix, buf, sizeof(buf)); + brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix); + inet_ntop(AF_INET, &brouter_id, brouter_name, + sizeof(brouter_name)); zlog_debug("%s: brouter %s del with nh count %u", - __PRETTY_FUNCTION__, buf, listcount(route->nh_list)); + __PRETTY_FUNCTION__, brouter_name, + listcount(route->nh_list)); } route->flag |= OSPF6_ROUTE_REMOVE; ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix)); diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index 2944c8b09a..fef77f574e 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -307,7 +307,8 @@ int ospf_sr_init(void) { int rc = -1; - zlog_info("SR (%s): Initialize SR Data Base", __func__); + if (IS_DEBUG_OSPF_SR) + zlog_info("SR (%s): Initialize SR Data Base", __func__); memset(&OspfSR, 0, sizeof(struct ospf_sr_db)); OspfSR.enabled = false; @@ -676,6 +677,7 @@ static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe) SET_FLAG(api.message, ZAPI_MESSAGE_LABEL); api_nh->labels[0] = nhlfe.label_out; api_nh->label_num = 1; + api_nh->vrf_id = VRF_DEFAULT; api.nexthop_num = 1; } @@ -1617,11 +1619,11 @@ static int ospf_sr_update_schedule(struct thread *t) monotime(&stop_time); - zlog_info( - "SR (%s): SPF Processing Time(usecs): %lld\n", - __func__, - (stop_time.tv_sec - start_time.tv_sec) * 1000000LL - + (stop_time.tv_usec - start_time.tv_usec)); + if (IS_DEBUG_OSPF_SR) + zlog_debug("SR (%s): SPF Processing Time(usecs): %lld\n", + __func__, + (stop_time.tv_sec - start_time.tv_sec) * 1000000LL + + (stop_time.tv_usec - start_time.tv_usec)); OspfSR.update = false; return 1; @@ -1,375 +1,21 @@ -T1 DONE Implement debug command - test pim receive join - -T2 DONE Implement debug command - test pim receive prune - -T3 DONE Per-interface Downstream (S,G) state machine - (RFC 4601 4.5.3. Receiving (S,G) Join/Prune Messages) - -T4 DONE Upstream (S,G) state machine - (RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages) - -T5 DONE Verify Data Packet Forwarding Rules - RFC 4601 4.2. Data Packet Forwarding Rules - RFC 4601 4.8.2. PIM-SSM-Only Routers - - Additionally, the Packet forwarding rules of Section 4.2 can be - simplified in a PIM-SSM-only router: - - iif is the incoming interface of the packet. - oiflist = NULL - if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) { - oiflist = inherited_olist(S,G) - } else if (iif is in inherited_olist(S,G)) { - send Assert(S,G) on iif - } - oiflist = oiflist (-) iif - forward packet on all interfaces in oiflist - - Macro: - inherited_olist(S,G) = - joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) - -T6 DONE Implement (S,G) Assert state machine (RFC 4601, section 4.6.1). - Changes in pim_ifchannel.ifassert_winner should trigger - pim_upstream_update_join_desired(). - Depends on TODO T27. - Depends on TODO T33. - See also CAVEAT C7. - See also: RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages - Transitions from Joined State - RPF'(S,G) changes due to an Assert - - http://www.hep.ucl.ac.uk/~ytl/multi-cast/pim-dm_01.html: - - The PIM Assert mechanism is used to shutoff duplicate flows onto - the same multiaccess network. Routers detect this condiction when - they receive an (S,G) packet via a multi-access interface that is - in the (S,G) OIL. This causes the routers to send Assert - Messages. - - Note that neighbors will not accept Join/Prune or Assert messages - from a router unless they have first heard a Hello message from that - router. Thus, if a router needs to send a Join/Prune or Assert - message on an interface on which it has not yet sent a Hello message - with the currently configured IP address, then it MUST immediately - send the relevant Hello message without waiting for the Hello Timer - to expire, followed by the Join/Prune or Assert message. - -T7 DONE Implement hello option: LAN Prune Delay - -T8 DONE Implement J/P_Override_Interval(I) - Depends on TODO T7. - See pim_ifchannel.c, pim_ifchannel_prune(), jp_override_interval. - -T9 DONE Detect change in IGMPv3 RPF interface/next-hop for S and update. - channel_oil vif index accordingly ? - Beware accidentaly adding looped MFC entries (IIF=OIF). - -T10 DONE React to (S,G) join directed to another upstream address. See - also: - - RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages - - If a router wishes to propagate a Join(S,G) upstream, it must also - watch for messages on its upstream interface from other routers on - that subnet, and these may modify its behavior. If it sees a - Join(S,G) to the correct upstream neighbor, it should suppress its - own Join(S,G). If it sees a Prune(S,G), Prune(S,G,rpt), or - Prune(*,G) to the correct upstream neighbor towards S, it should - be prepared to override that prune by scheduling a Join(S,G) to be - sent almost immediately. - -T11 DONE Review protocol modifications for SSM - (RFC 4601 4.8.1. Protocol Modifications for SSM Destination - Addresses) - -T12 DONE Review updates of RPF entries. - FIXME pim_upstream.c send_join(): - Currently only one upstream state is affected by detection of RPF change. - RPF change should affect all upstream states sharing the RPF cache. - -T13 DONE Check that RFC macros using S,G,RPF_interface(S) are actually - implemented with this strategy: - rpf_ifch=find_ifch(up->rpf->interface). - See pim_rpf.c pim_rpf_find_rpf_addr() for a correct example. - - $ grep -i macro pimd/*.c - pimd/pim_iface.c: RFC 4601: 4.1.6. State Summarization Macros - pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros - pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros - pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros - pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros - pimd/pim_ifchannel.c: Macro: - pimd/pim_rpf.c: RFC 4601: 4.1.6. State Summarization Macros - -T14 DONE Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. - See pim_mroute.c mroute_msg(). - -T15 DONE Interface command to statically join (S,G). - interface eth0 - ip igmp join-group 239.1.1.1 source 1.1.1.1 - -T16 DONE RPF'(S,G) lookup is not working for S reachable with default route. - See "RPF'(S,G) not found" in pim_rpf_update() from pim_rpf.c. - Zebra daemon RIB is not reflecting changes in kernel routes - accurately? - -T17 DONE Prevent CLI from creating bogus interfaces. - Example: - conf t - interface xxx - -T18 Consider reliable pim solution (refresh reduction) +T1 Consider reliable pim solution (refresh reduction) A Reliable Transport Mechanism for PIM http://tools.ietf.org/wg/pim/draft-ietf-pim-port/ PORT=PIM-Over-Reliable-Transport -T19 DONE Fix self as neighbor - See mailing list post: - http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html - -T20 DONE Fix debug message: "pim_neighbor_update: internal error: - trying to replace same prefix list" - See mailing list post: - http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html - -T21 DONE Clean-up PIM/IGMP interface mismatch debugging - See option PIM_CHECK_RECV_IFINDEX_SANITY in pimd/Makefile.am - See mailing list post: - http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00003.html - -T22 DONE IGMP must be protected against adding looped MFC entries - created by both source and receiver attached to the same - interface. - -T23 DONE libfrr crash after zclient_lookup_nexthop. - See mailing list post: - http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00008.html - -T24 DONE zserv may return recursive routes: - - nexthop type is set to ZEBRA_NEXTHOP_IPV4 - - ifindex is not reported - - calls expecting ifindex (fib_lookup_if_vif_index) are disrupted - See also this mailing list post: - [PATCH 21/21] Link detect and recursive routes - http://www.gossamer-threads.com/lists/quagga/dev/17564 - -T25 DONE Zclient nexthop lookup missing OSPF route to 1.1.1.1/32 - See also: - pim_zlookup.c zclient_lookup_nexthop misses OSPF 1.1.1.1/32 - zebra/zebra_vty.c show_ip_route_addr_cmd hits OSPF 1.1.1.1/32 - -T26 DONE Zebra daemon is marking recursive static route as inactive. - - FIXED: zebra daemon was incorrectly marking recursive routes - pointing to kernel routes as inactive: - zebra/zebra_rib.c nexthop_active_ipv4: - -- Original: - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) - -- Fixed: - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) || - match->type == ZEBRA_ROUTE_KERNEL) - - Old problem description: - - This prevents rib_match_ipv4 from returning its nexthop: - client: pim_zlookup.c zclient_read_nexthop - server: zebra/zserv.c zsend_ipv4_nexthop_lookup_v2 -> rib_match_ipv4 - - Kernel route is injected into zebra in zebra_rib.c rib_add_ipv4 - Examples: - rt_netlink.c:726: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); - rt_netlink.c:864: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); - - This patch didn't fix the issue: - [PATCH 21/21] Link detect and recursive routes - http://www.gossamer-threads.com/lists/quagga/dev/17564 - - See the example below for the route 2.2.2.2. - -bash# route add -host 1.1.1.1 gw 127.0.0.1 -bash# route add -host 2.2.2.2 gw 1.1.1.1 -bash# netstat -nvr -Kernel IP routing table -Destination Gateway Genmask Flags MSS Window irtt Iface -2.2.2.2 1.1.1.1 255.255.255.255 UGH 0 0 0 lo -1.1.1.1 127.0.0.1 255.255.255.255 UGH 0 0 0 lo -192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 -0.0.0.0 192.168.0.2 0.0.0.0 UG 0 0 0 eth0 -bash# - -zebra# sh ip route -Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, - I - ISIS, B - BGP, > - selected route, * - FIB route - -K>* 0.0.0.0/0 via 192.168.0.2, eth0 -K>* 1.1.1.1/32 via 127.0.0.1, lo -K * 2.2.2.2/32 via 1.1.1.1, lo inactive -C>* 127.0.0.0/8 is directly connected, lo -C>* 192.168.0.0/24 is directly connected, eth0 - -quagga-pimd-router# sh ip route 1.1.1.1 -Address NextHop Interface Metric Preference -1.1.1.1 127.0.0.1 lo 0 0 -quagga-pimd-router# -quagga-pimd-router# sh ip route 2.2.2.2 -Address NextHop Interface Metric Preference -2.2.2.2 192.168.0.2 eth0 0 0 -quagga-pimd-router# - -T27 DONE Implement debug command - test pim receive assert - See also TODO T6: (S,G) Assert state machine. - -T28 DONE Bad IPv4 address family=02 in Join/Prune dump - Reported by Andrew Lunn <andrew.lunn@ascom.ch> - - # 58-byte pim v2 Join/Prune dump - # ------------------------------ - # IPv4 address family=02 is wrong, correct IPv4 address family is 01 - # See http://www.iana.org/assignments/address-family-numbers - # - c8XX YY03 : ip src 200.xx.yy.3 - e000 000d : ip dst 224.0.0.13 - 9404 0000 : ip router alert option 148.4.0.0 - 2300 ab13 : pimv2,type=3 res=00 checksum=ab13 - 0200 : upstream family=02, encoding=00 - c8XX YY08 : upstream 200.xx.yy.8 - 0001 00d2 : res=00 groups=01 holdtime=00d2 - 0200 0020 : group family=02, encoding=00, res=00, mask_len=20 - ef01 0101 : group address 239.1.1.1 - 0001 0000 : joined=0001 pruned=0000 - 0200 0020 : source family=02, encoding=00, res=00, mask_len=20 - 0101 0101 : source address 1.1.1.1 - -T29 DONE Reset interface PIM-hello-sent counter when primary address changes - See pim_ifp->pim_ifstat_hello_sent - - RFC 4601: 4.3.1. Sending Hello Messages - - Thus, if a router needs to send a Join/Prune or Assert message on - an interface on which it has not yet sent a Hello message with the - currently configured IP address, then it MUST immediately send the - relevant Hello message without waiting for the Hello Timer to - expire, followed by the Join/Prune or Assert message. - -T30 DONE Run interface DR election when primary address changes - Reported by Andrew Lunn <andrew.lunn@ascom.ch> - See pim_if_dr_election(). - -T31 If an interface changes one of its secondary IP addresses, a Hello +T2 If an interface changes one of its secondary IP addresses, a Hello message with an updated Address_List option and a non-zero HoldTime should be sent immediately. See also detect_secondary_address_change See also CAVEAT C15. See also RFC 4601: 4.3.1. Sending Hello Messages -T32 FIXED Detection of interface primary address changes may fail when - there are multiple addresses. - See also CAVEAT C14. - - pim_find_primary_addr() should return interface primary address - from connected list. Currently it returns the first address. - - Zebra daemon "show int" is able to keep the primary address as - first address. - -T33 DONE Implement debug command: test pim receive upcall - See also TODO T6: (S,G) Assert state machine. - -T34 DONE assert_action_a1 - -T35 DONE Review macros depending on interface I. - - See also: grep ,I\) pimd/*.c - - For the case (S,G,I) check if I is either - 1) interface attached to this per-interface S,G state (don't think so) - or - 2) an arbitrary interface (most probably) - - For the arbitrary interface case (2), consider representing - interface ifp as its primary address (struct in_addr ifaddr). The - benefit is in_addr does not need to be dereferenced, so it does - not demand protection against crashes. - -T36 DONE React to zebra daemon link-detect up/down notification. - pim_ifp->primary_address is managed by detect_primary_address_change() - depending on to ifp->connected (managed by zebra_interface_address_read()). - -T37 DONE Review list of variables which may affect pim_upstream.c - pim_upstream_evaluate_join_desired(). - Call pim_upstream_update_join_desired() accordingly. - - See the order of invokation: - pim_if_dr_election(ifp); - pim_if_update_join_desired(pim_ifp); /* depends on DR */ - pim_if_update_could_assert(ifp); /* depends on DR */ - pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ - - join_desired depends on: - pim_ifp->primary_address - pim_ifp->pim_dr_addr - ch->ifassert_winner_metric - ch->ifassert_winner - ch->local_ifmembership - ch->ifjoin_state - ch->upstream->rpf.source_nexthop.mrib_metric_preference - ch->upstream->rpf.source_nexthop.mrib_route_metric - ch->upstream->rpf.source_nexthop.interface - -T38 DONE Detect change in AssertTrackingDesired(S,G,I) - - See the order of invokation: - dr_election: none - update_join_desired: depends on DR - update_tracking_desired: depends on DR, join_desired - - AssertTrackingDesired(S,G,I) depends on: - pim_ifp->primary_address - pim_ifp->pim_dr_addr - ch->local_ifmembership - ch->ifassert_winner - ch->ifjoin_state - ch->upstream->rpf.source_nexthop.interface - PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags) - -T39 DONE AssertTrackingDesired: flags is not matching evaluation - - # show ip pim assert-internal - CA: CouldAssert - ECA: Evaluate CouldAssert - ATD: AssertTrackingDesired - eATD: Evaluate AssertTrackingDesired - - Interface Address Source Group CA eCA ATD eATD - eth0 192.168.1.100 1.1.1.1 239.1.1.1 no no no yes - # - -T40 Lightweight MLDv2 +T3 Lightweight MLDv2 http://tools.ietf.org/html/draft-ietf-mboned-lightweight-igmpv3-mldv2-05 http://www.ietf.org/internet-drafts/draft-ietf-mboned-lightweight-igmpv3-mldv2-05.txt http://www.ietf.org/html.charters/mboned-charter.html -T41 DONE ssmping support - - See also: - http://www.venaas.no/multicast/ssmping/ - draft-ietf-mboned-ssmping-07 - http://tools.ietf.org/html/draft-ietf-mboned-ssmping-07 - - Example: - - debug ssmpingd - - conf t - ip ssmpingd 1.1.1.1 - - show ip ssmpingd - -T42 Static igmp join fails when loading config at boot time +T4 Static igmp join fails when loading config at boot time ! Wrong behavior seen at boot time: ! @@ -396,7 +42,7 @@ T42 Static igmp join fails when loading config at boot time eth0 200.202.112.3 2 2 0 0 0 0 lo 127.0.0.1 1 1 0 0 0 0 -T43 PIM Neighbor Reduction +T5 PIM Neighbor Reduction https://datatracker.ietf.org/doc/draft-wijnands-pim-neighbor-reduction/ "In a transit LAN (no directly connected source or receiver), many @@ -404,19 +50,19 @@ T43 PIM Neighbor Reduction a procedure to reduce the amount of neighbors established over a transit LAN." -T44 Single Stream Multicast Fast Reroute (SMFR) Method +T6 Single Stream Multicast Fast Reroute (SMFR) Method https://datatracker.ietf.org/doc/draft-liu-pim-single-stream-multicast-frr/ "This document proposes an IP multicast fast convergence method based on differentiating primary and backup PIM join." -T45 RFC5384 - The Join Attribute Format +T7 RFC5384 - The Join Attribute Format "This document describes a modification of the Join message that allows a node to associate attributes with a particular tree." -T46 PIM Multi-Topology ID (MT-ID) Join-Attribute +T8 PIM Multi-Topology ID (MT-ID) Join-Attribute http://tools.ietf.org/html/draft-cai-pim-mtid-00 - Depends on T45. + Depends on T7. "This draft introduces a new type of PIM Join Attribute used to encode the identity of the topology PIM uses for RPF." diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 3b22db20aa..f02ce4979c 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -169,6 +169,7 @@ void route_add(struct prefix *p, struct nexthop *nh) api.safi = SAFI_UNICAST; memcpy(&api.prefix, p, sizeof(*p)); + SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); api_nh = &api.nexthops[0]; diff --git a/tests/.gitignore b/tests/.gitignore index ab1d55b548..c2fe9c8890 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -24,10 +24,12 @@ __pycache__ /bgpd/test_ecommunity /bgpd/test_mp_attr /bgpd/test_mpath +/bgpd/test_packet /isisd/test_fuzz_isis_tlv /isisd/test_fuzz_isis_tlv_tests.h /isisd/test_isis_vertex_queue /lib/cli/test_cli +/lib/cli/test_cli_clippy.c /lib/cli/test_commands /lib/cli/test_commands_defun.c /lib/test_buffer @@ -38,6 +40,7 @@ __pycache__ /lib/test_memory /lib/test_nexthop_iter /lib/test_privs +/lib/test_ringbuf /lib/test_srcdest_table /lib/test_segv /lib/test_sig @@ -48,3 +51,4 @@ __pycache__ /lib/test_ttable /lib/test_zmq /ospf6d/test_lsdb +/ospf6d/test_lsdb_clippy.c diff --git a/tests/lib/test_ringbuf.py b/tests/lib/test_ringbuf.py index 860d872f86..5d994ddd7b 100644 --- a/tests/lib/test_ringbuf.py +++ b/tests/lib/test_ringbuf.py @@ -1,4 +1,6 @@ import frrtest -class TestRingbuf(frrtest.TestExitNonzero): +class TestRingbuf(frrtest.TestMultiOut): program = './test_ringbuf' + +TestRingbuf.exit_cleanly() diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5c316e077f..7f6c8aefa8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -514,7 +514,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, nexthop->ifindex = newhop->ifindex; } return 1; - } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_INTERNAL)) { + } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) { resolved = 0; for (ALL_NEXTHOPS(match->nexthop, newhop)) { if (!CHECK_FLAG(newhop->flags, diff --git a/zebra/zserv.c b/zebra/zserv.c index 98cb54f7b8..bca8a509d8 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1166,12 +1166,12 @@ static int zread_route_add(struct zserv *client, u_short length, switch (api_nh->type) { case NEXTHOP_TYPE_IFINDEX: nexthop = route_entry_nexthop_ifindex_add( - re, api_nh->ifindex, re->vrf_id); + re, api_nh->ifindex, api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV4: nexthop = route_entry_nexthop_ipv4_add( re, &api_nh->gate.ipv4, NULL, - re->vrf_id); + api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV4_IFINDEX: { @@ -1188,7 +1188,7 @@ static int zread_route_add(struct zserv *client, u_short length, nexthop = route_entry_nexthop_ipv4_ifindex_add( re, &api_nh->gate.ipv4, NULL, ifindex, - re->vrf_id); + api_nh->vrf_id); /* if this an EVPN route entry, program the nh as neigh @@ -1211,12 +1211,12 @@ static int zread_route_add(struct zserv *client, u_short length, } case NEXTHOP_TYPE_IPV6: nexthop = route_entry_nexthop_ipv6_add( - re, &api_nh->gate.ipv6, re->vrf_id); + re, &api_nh->gate.ipv6, api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV6_IFINDEX: nexthop = route_entry_nexthop_ipv6_ifindex_add( re, &api_nh->gate.ipv6, api_nh->ifindex, - re->vrf_id); + api_nh->vrf_id); break; case NEXTHOP_TYPE_BLACKHOLE: nexthop = route_entry_nexthop_blackhole_add( |
