summaryrefslogtreecommitdiff
path: root/zebra/zebra_nb_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_nb_state.c')
-rw-r--r--zebra/zebra_nb_state.c84
1 files changed, 79 insertions, 5 deletions
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index 44a2d172f1..afbabe342c 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -221,12 +221,20 @@ const void *
lib_vrf_zebra_ribs_rib_route_get_next(struct nb_cb_get_next_args *args)
{
const struct zebra_router_table *zrt = args->parent_list_entry;
- const struct route_node *rn = args->list_entry;
+ struct route_node *rn = (struct route_node *)args->list_entry;
if (args->list_entry == NULL)
rn = route_top(zrt->table);
else
rn = srcdest_route_next((struct route_node *)rn);
+ /* Optimization: skip empty route nodes. */
+ while (rn && rn->info == NULL)
+ rn = route_next(rn);
+
+ /* Skip link-local routes. */
+ if (rn && rn->p.family == AF_INET6
+ && IN6_IS_ADDR_LINKLOCAL(&rn->p.u.prefix6))
+ return NULL;
return rn;
}
@@ -512,8 +520,9 @@ int lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_get_keys(
const void *lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_lookup_entry(
struct nb_cb_lookup_entry_args *args)
{
- /* TODO: implement me. */
- return NULL;
+ struct route_entry *re = (struct route_entry *)args->parent_list_entry;
+
+ return re->nhe;
}
/*
@@ -617,7 +626,72 @@ const void *
lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_frr_nexthops_nexthop_lookup_entry(
struct nb_cb_lookup_entry_args *args)
{
- /* TODO: implement me. */
+ struct nhg_hash_entry *nhe;
+ struct nexthop nexthop_lookup = {};
+ struct nexthop *nexthop;
+ const char *nh_type_str;
+
+ nhe = (struct nhg_hash_entry *)args->parent_list_entry;
+ nexthop_lookup.vrf_id = nhe->vrf_id;
+
+ /*
+ * Get nexthop type.
+ * TODO: use yang_str2enum() instead.
+ */
+ nh_type_str = args->keys->key[0];
+ if (strmatch(nh_type_str, "ifindex"))
+ nexthop_lookup.type = NEXTHOP_TYPE_IFINDEX;
+ else if (strmatch(nh_type_str, "ip4"))
+ nexthop_lookup.type = NEXTHOP_TYPE_IPV4;
+ else if (strmatch(nh_type_str, "ip4-ifindex"))
+ nexthop_lookup.type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ else if (strmatch(nh_type_str, "ip6"))
+ nexthop_lookup.type = NEXTHOP_TYPE_IPV6;
+ else if (strmatch(nh_type_str, "ip6-ifindex"))
+ nexthop_lookup.type = NEXTHOP_TYPE_IPV6_IFINDEX;
+ else if (strmatch(nh_type_str, "blackhole"))
+ nexthop_lookup.type = NEXTHOP_TYPE_BLACKHOLE;
+ else
+ /* unexpected */
+ return NULL;
+
+ /* Get nexthop address. */
+ switch (nexthop_lookup.type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ yang_str2ipv4(args->keys->key[1], &nexthop_lookup.gate.ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ yang_str2ipv6(args->keys->key[1], &nexthop_lookup.gate.ipv6);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
+
+ /* Get nexthop interface. */
+ switch (nexthop_lookup.type) {
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ case NEXTHOP_TYPE_IFINDEX:
+ nexthop_lookup.ifindex =
+ ifname2ifindex(args->keys->key[2], nhe->vrf_id);
+ break;
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
+
+ /* Lookup requested nexthop (ignore weight and metric). */
+ for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
+ nexthop_lookup.weight = nexthop->weight;
+ nexthop_lookup.src = nexthop->src;
+ if (nexthop_same_no_labels(&nexthop_lookup, nexthop))
+ return nexthop;
+ }
+
return NULL;
}
@@ -715,7 +789,7 @@ lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_frr_nexthops_nexthop_inte
struct nexthop *nexthop = (struct nexthop *)args->list_entry;
if (nexthop->ifindex)
- yang_data_new_string(
+ return yang_data_new_string(
args->xpath,
ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));