afi = family2afi(rn->p.family);
if (rmap_name)
ret = zebra_import_table_route_map_check(
- afi, re->type, re->instance, &rn->p, re->ng.nexthop,
+ afi, re->type, re->instance, &rn->p, re->ng->nexthop,
zvrf->vrf->vrf_id, re->tag, rmap_name);
if (ret != RMAP_PERMITMATCH) {
newre->nexthop_num = 0;
newre->uptime = monotime(NULL);
newre->instance = re->table;
- route_entry_copy_nexthops(newre, re->ng.nexthop);
+ newre->ng = nexthop_group_new();
+ route_entry_copy_nexthops(newre, re->ng->nexthop);
rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre);
prefix_copy(&p, &rn->p);
rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE,
- re->table, re->flags, &p, NULL, re->ng.nexthop,
+ re->table, re->flags, &p, NULL, re->ng->nexthop,
zvrf->table_id, re->metric, re->distance, false);
return 0;
struct re_list_item next;
/* Nexthop structure (from RIB) */
- struct nexthop_group ng;
+ struct nexthop_group *ng;
/* Nexthop group from FIB (optional) */
struct nexthop_group fib_ng;
if (re->fib_ng.nexthop)
return &(re->fib_ng);
else
- return &(re->ng);
+ return re->ng;
}
extern void zebra_vty_init(void);
re->nexthop_num = 0;
re->uptime = monotime(NULL);
re->tag = tag;
+ re->ng = nexthop_group_new();
for (;;) {
struct nexthop *nh = NULL;
zserv_nexthop_num_warn(__func__,
(const struct prefix *)&p,
re->nexthop_num);
- if (re->nexthop_num == 0)
+ if (re->nexthop_num == 0) {
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
- else
+ } else
rib_add_multipath(afi, SAFI_UNICAST, &p,
&src_p, re);
}
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
api.nexthop_num = re->nexthop_active_num;
}
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
+ for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
continue;
* nexthop we are looking up. Therefore, we will just iterate
* over the top chain of nexthops.
*/
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
+ for (nexthop = re->ng->nexthop; nexthop;
+ nexthop = nexthop->next)
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
num += zserv_encode_nexthop(s, nexthop);
re->flags = api.flags;
re->uptime = monotime(NULL);
re->vrf_id = vrf_id;
+ re->ng = nexthop_group_new();
+
if (api.tableid)
re->table = api.tableid;
else
"%s: received a route without nexthops for prefix %pFX from client %s",
__func__, &api.prefix,
zebra_route_string(client->proto));
+
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
return;
}
EC_ZEBRA_NEXTHOP_CREATION_FAILED,
"%s: Nexthops Specified: %d but we failed to properly create one",
__PRETTY_FUNCTION__, api.nexthop_num);
- nexthops_free(re->ng.nexthop);
+ nexthops_free(re->ng->nexthop);
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
return;
}
flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI,
"%s: Received SRC Prefix but afi is not v6",
__PRETTY_FUNCTION__);
- nexthops_free(re->ng.nexthop);
+ nexthops_free(re->ng->nexthop);
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
return;
}
ctx->u.rinfo.zd_safi = info->safi;
/* Copy nexthops; recursive info is included too */
- copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), re->ng.nexthop, NULL);
+ copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), re->ng->nexthop, NULL);
/* Ensure that the dplane's nexthops flags are clear. */
for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop))
if (re)
copy_nexthops(&(ctx->u.pw.nhg.nexthop),
- re->ng.nexthop, NULL);
+ re->ng->nexthop, NULL);
route_unlock_node(rn);
}
ri->rtm_type = RTN_UNICAST;
ri->metric = &re->metric;
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
if (ri->num_nhs >= zrouter.multipath_num)
break;
* Figure out the set of nexthops to be added to the message.
*/
num_nhs = 0;
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
if (num_nhs >= zrouter.multipath_num)
break;
* the label advertised by the recursive nexthop (plus we don't have the
* logic yet to push multiple labels).
*/
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
+ for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
/* Skip inactive and recursive entries. */
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
continue;
|| !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
continue;
- for (match_nh = match->ng.nexthop; match_nh;
+ for (match_nh = match->ng->nexthop; match_nh;
match_nh = match_nh->next) {
if (match->type == ZEBRA_ROUTE_CONNECT
|| nexthop->ifindex == match_nh->ifindex) {
break;
}
- if (!match || !match->ng.nexthop)
+ if (!match || !match->ng->nexthop)
return 0;
- nexthop->ifindex = match->ng.nexthop->ifindex;
+ nexthop->ifindex = match->ng->nexthop->ifindex;
return 1;
}
return -1;
found = false;
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
+ for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
for (rn = route_top(table); rn; rn = route_next(rn)) {
update = 0;
RNODE_FOREACH_RE (rn, re) {
- for (nexthop = re->ng.nexthop; nexthop;
+ for (nexthop = re->ng->nexthop; nexthop;
nexthop = nexthop->next) {
if (nexthop->nh_label_type != lsp_type)
continue;
lookup.vrf_id = re->vrf_id;
lookup.afi = afi;
- lookup.nhg = re->ng;
+ lookup.nhg = *re->ng;
nhe = hash_lookup(zrouter.nhgs, &lookup);
nhe->refcnt--;
if (match->type == ZEBRA_ROUTE_CONNECT) {
/* Directly point connected route. */
- newhop = match->ng.nexthop;
+ newhop = match->ng->nexthop;
if (newhop) {
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV6)
return 1;
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
resolved = 0;
- for (ALL_NEXTHOPS(match->ng, newhop)) {
+ for (ALL_NEXTHOPS_PTR(match->ng, newhop)) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
continue;
return resolved;
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
- for (ALL_NEXTHOPS(match->ng, newhop)) {
+ for (ALL_NEXTHOPS_PTR(match->ng, newhop)) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
continue;
re->nexthop_active_num = 0;
UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
- for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
+ for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
/* No protocol daemon provides src and so we're skipping
* tracking it */
prev_src = nexthop->rmap_src;
* Need to ensure that there's a label binding for all nexthops.
* Otherwise, ECMP for this route could render the pseudowire unusable.
*/
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
if (!nexthop->nh_label) {
if (IS_ZEBRA_DEBUG_PW)
zlog_debug("%s: unlabeled route for %s",
/* Add nexthop to the end of a rib node's nexthop list */
void route_entry_nexthop_add(struct route_entry *re, struct nexthop *nexthop)
{
- _nexthop_group_add_sorted(&re->ng, nexthop);
+ _nexthop_group_add_sorted(re->ng, nexthop);
re->nexthop_num++;
}
*/
void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh)
{
- assert(!re->ng.nexthop);
- copy_nexthops(&re->ng.nexthop, nh, NULL);
+ assert(!re->ng->nexthop);
+ copy_nexthops(&re->ng->nexthop, nh, NULL);
for (struct nexthop *nexthop = nh; nexthop; nexthop = nexthop->next)
re->nexthop_num++;
}
if (nexthop->prev)
nexthop->prev->next = nexthop->next;
else
- re->ng.nexthop = nexthop->next;
+ re->ng->nexthop = nexthop->next;
re->nexthop_num--;
}
if (re->type != ZEBRA_ROUTE_BGP)
return 0;
- for (ALL_NEXTHOPS(re->ng, nexthop))
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop))
if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
return 0;
srcdest_rnode_prefixes(rn, &p, &src_p);
if (info->safi != SAFI_UNICAST) {
- for (ALL_NEXTHOPS(re->ng, nexthop))
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
} else {
struct nexthop *prev;
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_DUPLICATE);
- for (ALL_NEXTHOPS(re->ng, prev)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, prev)) {
if (prev == nexthop)
break;
if (nexthop_same_firsthop(nexthop, prev)) {
if (!RIB_SYSTEM_ROUTE(old)) {
/* Clear old route's FIB flags */
- for (ALL_NEXTHOPS(old->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(old->ng, nexthop)) {
UNSET_FLAG(nexthop->flags,
NEXTHOP_FLAG_FIB);
}
if (info->safi != SAFI_UNICAST) {
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
- for (ALL_NEXTHOPS(re->ng, nexthop))
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
}
re->fib_ng.nexthop = NULL;
}
- for (ALL_NEXTHOPS(re->ng, nexthop))
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
/* Update real nexthop. This may actually determine if nexthop is active
* or not. */
- if (!nexthop_group_active_nexthop_num(&new->ng)) {
+ if (!nexthop_group_active_nexthop_num(new->ng)) {
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
return;
}
/* Update the nexthop; we could determine here that nexthop is
* inactive. */
- if (nexthop_group_active_nexthop_num(&new->ng))
+ if (nexthop_group_active_nexthop_num(new->ng))
nh_active = 1;
/* If nexthop is active, install the selected route, if
/* both are connected. are either loop or vrf? */
struct nexthop *nexthop = NULL;
- for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(alternate->ng, nexthop)) {
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, alternate->vrf_id);
return alternate;
}
- for (ALL_NEXTHOPS(current->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(current->ng, nexthop)) {
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, current->vrf_id);
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
- for (ALL_NEXTHOPS(re->ng, nhop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nhop)) {
if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
* that is actually installed.
*/
matched = true;
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
info = srcdest_rnode_table_info(rn);
zebra_nhg_release(info->afi, re);
- nexthops_free(re->ng.nexthop);
+ nexthops_free(re->ng->nexthop);
+ nexthop_group_delete(&re->ng);
nexthops_free(re->fib_ng.nexthop);
XFREE(MTYPE_RE, re);
zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
re->nexthop_num, re->nexthop_active_num);
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
/* Lookup table. */
table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table);
if (!table) {
+ nexthops_free(re->ng->nexthop);
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
return 0;
}
if (src_p)
apply_mask_ipv6(src_p);
- zebra_nhg_find(afi, &re->ng, re);
+ zebra_nhg_find(afi, re->ng, re);
/* Set default distance by route type. */
if (re->distance == 0)
re->distance = route_distance(re->type);
if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric)
continue;
- if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->ng.nexthop)
+ if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->ng->nexthop)
&& rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
if (rtnh->ifindex != nh->ifindex)
continue;
same = re;
break;
}
- for (ALL_NEXTHOPS(re->ng, rtnh))
+ for (ALL_NEXTHOPS_PTR(re->ng, rtnh))
/*
* No guarantee all kernel send nh with labels
* on delete.
if (allow_delete) {
UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */
- for (rtnh = fib->ng.nexthop; rtnh;
+ for (rtnh = fib->ng->nexthop; rtnh;
rtnh = rtnh->next)
UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
struct nexthop *tmp_nh;
- for (ALL_NEXTHOPS(re->ng, tmp_nh)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, tmp_nh)) {
struct ipaddr vtep_ip;
memset(&vtep_ip, 0, sizeof(struct ipaddr));
re->nexthop_num = 0;
re->uptime = monotime(NULL);
re->tag = tag;
+ re->ng = nexthop_group_new();
/* Add nexthop. */
nexthop = nexthop_new();
* this decision needs to be revisited
*/
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
- for (ALL_NEXTHOPS(re->ng, nexthop))
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
rib_uninstall_kernel(rn, re);
struct nexthop *nexthop;
if (re) {
- for (nexthop = re->ng.nexthop; nexthop;
+ for (nexthop = re->ng->nexthop; nexthop;
nexthop = nexthop->next) {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED);
}
route_map_result_t ret;
if (prn && re) {
- for (nexthop = re->ng.nexthop; nexthop;
+ for (nexthop = re->ng->nexthop; nexthop;
nexthop = nexthop->next) {
ret = zebra_nht_route_map_check(
afi, proto, &prn->p, zvrf, re, nexthop);
/* Just being SELECTED isn't quite enough - must
* have an installed nexthop to be useful.
*/
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
if (rnh_nexthop_valid(re, nexthop))
break;
}
break;
if (re->type == ZEBRA_ROUTE_NHRP) {
- for (nexthop = re->ng.nexthop; nexthop;
+ for (nexthop = re->ng->nexthop; nexthop;
nexthop = nexthop->next)
if (nexthop->type
== NEXTHOP_TYPE_IFINDEX)
return;
/* free RE and nexthops */
- nexthops_free(re->ng.nexthop);
+ nexthops_free(re->ng->nexthop);
+ nexthop_group_delete(&re->ng);
XFREE(MTYPE_RE, re);
}
state->metric = re->metric;
state->vrf_id = re->vrf_id;
state->status = re->status;
+ state->ng = nexthop_group_new();
- route_entry_copy_nexthops(state, re->ng.nexthop);
+ route_entry_copy_nexthops(state, re->ng->nexthop);
rnh->state = state;
}
if (r1->nexthop_num != r2->nexthop_num)
return 1;
- if (nexthop_group_hash(&r1->ng) != nexthop_group_hash(&r2->ng))
+ if (nexthop_group_hash(r1->ng) != nexthop_group_hash(r2->ng))
return 1;
return 0;
num = 0;
nump = stream_get_endp(s);
stream_putc(s, 0);
- for (ALL_NEXTHOPS(re->ng, nh))
+ for (ALL_NEXTHOPS_PTR(re->ng, nh))
if (rnh_nexthop_valid(re, nh)) {
stream_putl(s, nh->vrf_id);
stream_putc(s, nh->type);
if (rnh->state) {
vty_out(vty, " resolved via %s\n",
zebra_route_string(rnh->state->type));
- for (nexthop = rnh->state->ng.nexthop; nexthop;
+ for (nexthop = rnh->state->ng->nexthop; nexthop;
nexthop = nexthop->next)
print_nh(nexthop, vty);
} else
tm->tm_hour);
vty_out(vty, " ago\n");
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) {
char addrstr[32];
vty_out(vty, " %c%s",
if (is_fib)
nhg = rib_active_nhg(re);
else
- nhg = &(re->ng);
+ nhg = re->ng;
if (json) {
json_route = json_object_new_object();
fib_cnt[ZEBRA_ROUTE_TOTAL]++;
fib_cnt[re->type]++;
}
- for (nexthop = re->ng.nexthop; (!cnt && nexthop);
+ for (nexthop = re->ng->nexthop; (!cnt && nexthop);
nexthop = nexthop->next) {
cnt++;
rib_cnt[ZEBRA_ROUTE_TOTAL]++;