Skip to content

Commit 1082673

Browse files
committed
infra: expose per interface stats via telemetry socket
Output snippet: --> /grout/iface { "/grout/iface": { "p0": { "name": "p0", "id": 1, "type": "port", "mtu": 1500, "flags": [ "up", "running" ], "mode": "l3", "vrf_id": 0, "statistics": { "rx_packets": 3, "rx_bytes": 1169, "tx_packets": 3, "tx_bytes": 150 "rx_missed": 0, "tx_errors": 0, "rx_good_packets": 3, "tx_good_packets": 3, "rx_good_bytes": 1169, "tx_good_bytes": 180, "rx_multicast_packets": 3, "rx_broadcast_packets": 1, "rx_unknown_protocol_packets": 4, "tx_unicast_packets": 3, "mac_remote_errors": 1, "rx_size_256_to_511_packets": 4, "tx_size_64_packets": 3 } } } } Signed-off-by: Spoorthi K <spk@redhat.com>
1 parent 9f716b3 commit 1082673

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

modules/infra/api/gr_infra.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,36 @@ struct gr_infra_cpu_affinity_set_req {
309309

310310
// struct gr_infra_cpu_affinity_set_resp { };
311311

312+
// Helper function to convert iface type enum to string
313+
static inline const char *iface_type_to_str(gr_iface_type_t type) {
314+
switch (type) {
315+
case GR_IFACE_TYPE_UNDEF:
316+
return "undef";
317+
case GR_IFACE_TYPE_LOOPBACK:
318+
return "loopback";
319+
case GR_IFACE_TYPE_PORT:
320+
return "port";
321+
case GR_IFACE_TYPE_VLAN:
322+
return "vlan";
323+
case GR_IFACE_TYPE_IPIP:
324+
return "ipip";
325+
case GR_IFACE_TYPE_COUNT:
326+
break;
327+
}
328+
return "?";
329+
}
330+
331+
// Helper function to convert iface mode enum to string
332+
static inline const char *iface_mode_to_str(gr_iface_mode_t mode) {
333+
switch (mode) {
334+
case GR_IFACE_MODE_L3:
335+
return "l3";
336+
case GR_IFACE_MODE_L1_XC:
337+
return "l1-xc";
338+
case GR_IFACE_MODE_COUNT:
339+
break;
340+
}
341+
return "?";
342+
}
343+
312344
#endif

modules/infra/api/stats.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,131 @@ telemetry_sw_stats_get(const char * /*cmd*/, const char * /*params*/, struct rte
278278
return -1;
279279
}
280280

281+
static int
282+
telemetry_ifaces_info_get(const char * /*cmd*/, const char * /*params*/, struct rte_tel_data *d) {
283+
struct iface *iface = NULL;
284+
285+
rte_tel_data_start_dict(d);
286+
287+
while ((iface = iface_next(GR_IFACE_TYPE_UNDEF, iface)) != NULL) {
288+
if (iface->type != GR_IFACE_TYPE_LOOPBACK) {
289+
struct rte_tel_data *iface_container = rte_tel_data_alloc();
290+
if (iface_container == NULL) {
291+
goto err;
292+
}
293+
rte_tel_data_start_dict(iface_container);
294+
295+
rte_tel_data_add_dict_string(iface_container, "name", iface->name);
296+
rte_tel_data_add_dict_uint(iface_container, "id", iface->id);
297+
rte_tel_data_add_dict_string(
298+
iface_container, "type", iface_type_to_str(iface->type)
299+
);
300+
rte_tel_data_add_dict_uint(iface_container, "mtu", iface->mtu);
301+
302+
struct rte_tel_data *flags_array = rte_tel_data_alloc();
303+
if (flags_array == NULL) {
304+
rte_tel_data_free(iface_container);
305+
goto err;
306+
}
307+
rte_tel_data_start_array(flags_array, RTE_TEL_STRING_VAL);
308+
if (iface->flags & GR_IFACE_F_UP)
309+
rte_tel_data_add_array_string(flags_array, "up");
310+
if (iface->state & GR_IFACE_S_RUNNING)
311+
rte_tel_data_add_array_string(flags_array, "running");
312+
rte_tel_data_add_dict_container(iface_container, "flags", flags_array, 0);
313+
314+
rte_tel_data_add_dict_string(
315+
iface_container, "mode", iface_mode_to_str(iface->mode)
316+
);
317+
rte_tel_data_add_dict_uint(iface_container, "vrf_id", iface->vrf_id);
318+
319+
struct rte_tel_data *stats_container = rte_tel_data_alloc();
320+
if (stats_container == NULL) {
321+
rte_tel_data_free(iface_container);
322+
goto err;
323+
}
324+
rte_tel_data_start_dict(stats_container);
325+
326+
// Software stats
327+
struct iface_stats *sw_stats = iface_get_stats(iface->id);
328+
if (sw_stats != NULL) {
329+
uint64_t rx_pkts = 0, rx_bytes = 0, tx_pkts = 0, tx_bytes = 0;
330+
for (int i = 0; i < RTE_MAX_LCORE; i++) {
331+
rx_pkts += sw_stats->rx_packets[i];
332+
rx_bytes += sw_stats->rx_bytes[i];
333+
tx_pkts += sw_stats->tx_packets[i];
334+
tx_bytes += sw_stats->tx_bytes[i];
335+
}
336+
rte_tel_data_add_dict_uint(stats_container, "rx_packets", rx_pkts);
337+
rte_tel_data_add_dict_uint(stats_container, "rx_bytes", rx_bytes);
338+
rte_tel_data_add_dict_uint(stats_container, "tx_packets", tx_pkts);
339+
rte_tel_data_add_dict_uint(stats_container, "tx_bytes", tx_bytes);
340+
}
341+
342+
// Get hardware stats for physical ports.
343+
if (iface->type == GR_IFACE_TYPE_PORT) {
344+
struct iface_info_port *port = (struct
345+
iface_info_port *)iface->info;
346+
347+
struct rte_eth_stats eth_stats;
348+
if (rte_eth_stats_get(port->port_id, &eth_stats) == 0) {
349+
rte_tel_data_add_dict_uint(
350+
stats_container, "rx_missed", eth_stats.imissed
351+
);
352+
rte_tel_data_add_dict_uint(
353+
stats_container, "tx_errors", eth_stats.oerrors
354+
);
355+
}
356+
357+
int ret = rte_eth_xstats_get(port->port_id, NULL, 0);
358+
if (ret > 0) {
359+
unsigned num = ret;
360+
struct rte_eth_xstat *xstats = calloc(num, sizeof(*xstats));
361+
struct rte_eth_xstat_name *names = calloc(
362+
num, sizeof(*names)
363+
);
364+
if (xstats != NULL && names != NULL
365+
&& rte_eth_xstats_get_names(port->port_id, names, num)
366+
== (int)num
367+
&& rte_eth_xstats_get(port->port_id, xstats, num)
368+
== (int)num) {
369+
for (unsigned i = 0; i < num; i++) {
370+
if (xstats[i].value > 0) {
371+
rte_tel_data_add_dict_uint(
372+
stats_container,
373+
names[i].name,
374+
xstats[i].value
375+
);
376+
}
377+
}
378+
}
379+
free(xstats);
380+
free(names);
381+
}
382+
383+
if (rte_tel_data_add_dict_container(
384+
iface_container, "statistics", stats_container, 0
385+
)
386+
!= 0) {
387+
rte_tel_data_free(stats_container);
388+
rte_tel_data_free(iface_container);
389+
goto err;
390+
}
391+
}
392+
393+
if (rte_tel_data_add_dict_container(d, iface->name, iface_container, 0)
394+
!= 0) {
395+
rte_tel_data_free(iface_container);
396+
goto err;
397+
}
398+
}
399+
}
400+
return 0;
401+
402+
err:
403+
return -1;
404+
}
405+
281406
static struct gr_api_handler stats_get_handler = {
282407
.name = "stats get",
283408
.request_type = GR_INFRA_STATS_GET,
@@ -298,4 +423,9 @@ RTE_INIT(infra_stats_init) {
298423
telemetry_sw_stats_get,
299424
"Returns statistics of each graph node. No parameters"
300425
);
426+
rte_telemetry_register_cmd(
427+
"/grout/iface",
428+
telemetry_ifaces_info_get,
429+
"Returns information per interface. No parameters"
430+
);
301431
}

0 commit comments

Comments
 (0)