Skip to content

Commit

Permalink
ip6: show routes from all vrfs by default
Browse files Browse the repository at this point in the history
Be consistent with `show ip6 nexthop`, display routes from all VRFs by
default, unless a VRF id is specified. Change the default vrf_id
parameter in the request to UINT16_MAX (meaning "all vrfs").

Add a vrf_id attribute to struct gr_ip6_route and display it in the CLI.

Split route6_list to make counting and listing routes in mutliple VRFs
possible without too much code duplication.

Signed-off-by: Robin Jarry <robin@jarry.cc>
  • Loading branch information
rjarry committed Oct 30, 2024
1 parent fa80f9e commit 9c5f3b4
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 17 deletions.
1 change: 1 addition & 0 deletions modules/ip6/api/gr_ip6.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct gr_ip6_nh {
struct gr_ip6_route {
struct ip6_net dest;
struct rte_ipv6_addr nh;
uint16_t vrf_id;
};

#define GR_IP6_MODULE 0xfeed
Expand Down
8 changes: 5 additions & 3 deletions modules/ip6/cli/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ static cmd_status_t route6_del(const struct gr_api_client *c, const struct ec_pn
}

static cmd_status_t route6_list(const struct gr_api_client *c, const struct ec_pnode *p) {
struct gr_ip6_route_list_req req = {.vrf_id = UINT16_MAX};
struct libscols_table *table = scols_new_table();
const struct gr_ip6_route_list_resp *resp;
struct gr_ip6_route_list_req req = {0};
char dest[BUFSIZ], nh[BUFSIZ];
void *resp_ptr = NULL;

Expand All @@ -66,6 +66,7 @@ static cmd_status_t route6_list(const struct gr_api_client *c, const struct ec_p
}

resp = resp_ptr;
scols_table_new_column(table, "VRF", 0, 0);
scols_table_new_column(table, "DESTINATION", 0, 0);
scols_table_new_column(table, "NEXT_HOP", 0, 0);
scols_table_set_column_separator(table, " ");
Expand All @@ -75,8 +76,9 @@ static cmd_status_t route6_list(const struct gr_api_client *c, const struct ec_p
const struct gr_ip6_route *route = &resp->routes[i];
ip6_net_format(&route->dest, dest, sizeof(dest));
inet_ntop(AF_INET6, &route->nh, nh, sizeof(nh));
scols_line_set_data(line, 0, dest);
scols_line_set_data(line, 1, nh);
scols_line_sprintf(line, 0, "%u", route->vrf_id);
scols_line_set_data(line, 1, dest);
scols_line_set_data(line, 2, nh);
}

scols_print_table(table);
Expand Down
75 changes: 61 additions & 14 deletions modules/ip6/control/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,47 +251,94 @@ static struct api_out route6_get(const void *request, void **response) {
return api_out(0, sizeof(*resp));
}

static struct api_out route6_list(const void *request, void **response) {
const struct gr_ip6_route_list_req *req = request;
struct gr_ip6_route_list_resp *resp = NULL;
struct rte_fib6 *fib = get_fib6(req->vrf_id);
static int route6_count(uint16_t vrf_id) {
struct rte_ipv6_addr zero = RTE_IPV6_ADDR_UNSPEC;
struct rte_rib6_node *rn = NULL;
struct rte_ipv6_addr zero = {0};
struct gr_ip6_route *r;
struct rte_fib6 *fib;
struct rte_rib6 *rib;
size_t num, len;
uintptr_t nh_id;
int num;

fib = get_fib6(vrf_id);
if (fib == NULL)
return api_out(errno, 0);
return -errno;

rib = rte_fib6_get_rib(fib);

num = 0;
while ((rn = rte_rib6_get_nxt(rib, &zero, 0, rn, RTE_RIB6_GET_NXT_ALL)) != NULL)
num++;
// FIXME: remove this when rte_rib6_get_nxt returns a default route, if any is configured
// check if there is a default route configured
if (rte_rib6_lookup_exact(rib, &zero, 0) != NULL)
num++;

len = sizeof(*resp) + num * sizeof(struct gr_ip6_route);
if ((resp = calloc(1, len)) == NULL)
return api_out(ENOMEM, 0);
return num;
}

static void route6_rib_to_api(struct gr_ip6_route_list_resp *resp, uint16_t vrf_id) {
struct rte_ipv6_addr zero = RTE_IPV6_ADDR_UNSPEC;
struct rte_rib6_node *rn = NULL;
struct gr_ip6_route *r;
struct rte_fib6 *fib;
struct rte_rib6 *rib;
uintptr_t nh_id;

fib = get_fib6(vrf_id);
assert(fib != NULL);
rib = rte_fib6_get_rib(fib);

while ((rn = rte_rib6_get_nxt(rib, &zero, 0, rn, RTE_RIB6_GET_NXT_ALL)) != NULL) {
r = &resp->routes[resp->n_routes++];
rte_rib6_get_nh(rn, &nh_id);
rte_rib6_get_ip(rn, &r->dest.ip);
rte_rib6_get_depth(rn, &r->dest.prefixlen);
r->nh = nh_id_to_ptr(nh_id)->ip;
r->vrf_id = vrf_id;
}
// FIXME: remove this when rte_rib6_get_nxt returns a default route, if any is configured
// check if there is a default route configured
if ((rn = rte_rib6_lookup_exact(rib, &zero, 0)) != NULL) {
r = &resp->routes[resp->n_routes++];
rte_rib6_get_nh(rn, &nh_id);
memset(&r->dest, 0, sizeof(r->dest));
r->nh = nh_id_to_ptr(nh_id)->ip;
r->vrf_id = vrf_id;
}
}

static struct api_out route6_list(const void *request, void **response) {
const struct gr_ip6_route_list_req *req = request;
struct gr_ip6_route_list_resp *resp = NULL;
size_t num, len;
int n;

if (req->vrf_id == UINT16_MAX) {
num = 0;
for (uint16_t v = 0; v < IP6_MAX_VRFS; v++) {
if (vrf_fibs[v] == NULL)
continue;
if ((n = route6_count(v)) < 0)
return api_out(errno, 0);
num += n;
}
} else {
if ((n = route6_count(req->vrf_id)) < 0)
return api_out(errno, 0);
num = n;
}

len = sizeof(*resp) + num * sizeof(struct gr_ip6_route);
if ((resp = calloc(1, len)) == NULL)
return api_out(ENOMEM, 0);

if (req->vrf_id == UINT16_MAX) {
for (uint16_t v = 0; v < IP6_MAX_VRFS; v++) {
if (vrf_fibs[v] == NULL)
continue;
route6_rib_to_api(resp, v);
}
} else {
route6_rib_to_api(resp, req->vrf_id);
}

*response = resp;

return api_out(0, len);
Expand Down

0 comments on commit 9c5f3b4

Please sign in to comment.