@@ -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+
281406static 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