require checking ethdev get return value
cover require checking ethdev get return value
Several places flagged by Coverity and Codeql are from code that calls rte_eth_dev_info_get() but does not check the return value. If rte_eth_dev_info_get() returns an error, the device info is garbage.
This patch series uses the function attribute to force code to check the result or there will be a compiler warning.
The series is ordered to fix the current warnings first before enabling it.
Stephen Hemminger (10):
app/test: remove redundant call
net/memif: check return value from rte_eth_dev_info_get
graph: check return value from rte_eth_dev_info_get examples/ethtool: handle devices without registers examples/l3fwd: check return value from ethdev info examples/ntb: always check return value examples/pipeline: check return value of ethdev functions examples/qos_sched: check return value from rte_eth_link_get
ethdev: check return value from rte_eth_dev_info_get
ethdev: require checking results of info_get functions
app/graph/ethdev.c | 20 ++++++++++++---- app/test/test_link_bonding_rssconf.c | 1 - drivers/net/memif/rte_eth_memif.c | 12 ++++++++-- examples/ethtool/lib/rte_ethtool.c | 6 ++--- examples/l3fwd-graph/main.c | 12 ++++++++-- examples/l3fwd/l3fwd_fib.c | 16 +++++++++---- examples/l3fwd/l3fwd_lpm.c | 14 ++++++++---- examples/ntb/ntb_fwd.c | 5 +++- examples/pipeline/cli.c | 7 +++--- examples/qos_sched/init.c | 13 +++++++++-- lib/ethdev/rte_class_eth.c | 4 +++- lib/ethdev/rte_ethdev.h | 34 +++++++++++++++++----------- 12 files changed, 103 insertions(+), 41 deletions(-)
Signature · 1 line
2.45.2
PATCH 1/10 app/test: remove redundant call
The patch to check return value of rte_eth_dev_info_get added a duplicate call in one spot.
--- app/test/test_link_bonding_rssconf.c | 1 - 1 file changed, 1 deletion(-)
app/test/test_link_bonding_rssconf.c +0 -1
@@ -616,7 +616,6 @@ test_setup(void) mac_addr.addr_bytes[5 ] =0x10 + port->port_id;rte_eth_dev_default_mac_addr_set (port->port_id, &mac_addr); -rte_eth_dev_info_get (port->port_id, &port->dev_info); retval =rte_eth_dev_info_get (port->port_id, &port->dev_info); TEST_ASSERT((retval == 0), "Error during getting device (port %u) info: %s\n",
Signature · 1 line
2.45.2
PATCH 2/10 net/memif: check return value from rte_eth_dev_info_get
In reply to Stephen HemmingerHandle errors from rte_eth_dev_info_get in the same manner as other places in this file.
--- drivers/net/memif/rte_eth_memif.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/net/memif/rte_eth_memif.c +10 -2
@@ -520,7 +520,10 @@ eth_memif_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)return 0 ;if (unlikely (ring ==NULL )) {/* Secondary process will attempt to request regions. */ -rte_eth_link_get (mq->in_port, &link); + ret =rte_eth_link_get (mq->in_port, &link); +if (ret <0 ) +MIF_LOG (ERR ,"Failed to get port %u link info: %s" , + mq->in_port,rte_strerror (-ret));return 0 ; }
@@ -864,8 +867,13 @@ eth_memif_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)if (unlikely ((pmd->flags Ð_MEMIF_FLAG_CONNECTED ) ==0 ))return 0 ;if (unlikely (ring ==NULL )) { +int ret; +/* Secondary process will attempt to request regions. */ -rte_eth_link_get (mq->in_port, &link); + ret =rte_eth_link_get (mq->in_port, &link); +if (ret <0 ) +MIF_LOG (ERR ,"Failed to get port %u link info: %s" , + mq->in_port,rte_strerror (-ret));return 0 ; }
Signature · 1 line
2.45.2
Re: [PATCH 02/10] net/memif: check return value from rte_eth_dev_info_get
Quoted 5 lines · Stephen Hemminger
Handle errors from
rte_eth_dev_info_getin the same manner as other places in this file.Signed-off-by Stephen Hemminger <[email protected]>
PATCH 3/10 graph: check return value from rte_eth_dev_info_get
In reply to Stephen HemmingerThe data in rte_eth_dev_info is undefined if rte_eth_dev_info_get returns an error. Handle the errors the same as previous error.
--- app/graph/ethdev.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
app/graph/ethdev.c +16 -4
@@ -219,10 +219,22 @@ ethdev_show(const char *name)if (rc <0 )return rc; -rte_eth_dev_info_get (port_id, &info); -rte_eth_stats_get (port_id, &stats); -rte_eth_macaddr_get (port_id, &addr); -rte_eth_link_get (port_id, &link); + rc =rte_eth_dev_info_get (port_id, &info); +if (rc <0 ) +return rc; + + rc =rte_eth_link_get (port_id, &link); +if (rc <0 ) +return rc; + + rc =rte_eth_stats_get (port_id, &stats); +if (rc <0 ) +return rc; + + rc =rte_eth_macaddr_get (port_id, &addr); +if (rc <0 ) +return rc; +rte_eth_dev_get_mtu (port_id, &mtu); length =strlen (conn->msg_out);
Signature · 1 line
2.45.2
PATCH 4/10 examples/ethtool: handle devices without registers
In reply to Stephen HemmingerIf device does not support reading registers then call to rte_eth_dev_get_reg_info will return an error. This fixes compiler warning when warn unused result is set.
--- examples/ethtool/lib/rte_ethtool.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
examples/ethtool/lib/rte_ethtool.c +2 -4
@@ -53,10 +53,8 @@ rte_ethtool_get_drvinfo(uint16_t port_id, struct ethtool_drvinfo *drvinfo) sizeof(drvinfo->bus_info));memset (®_info,0 ,sizeof (reg_info)); -rte_eth_dev_get_reg_info (port_id, ®_info); - n = reg_info.length; -if (n >0 ) - drvinfo->regdump_len = n; +if (rte_eth_dev_get_reg_info (port_id, ®_info) ==0 ) + drvinfo->regdump_len = reg_info.length;else drvinfo->regdump_len =0 ;
Signature · 1 line
2.45.2
PATCH 5/10 examples/l3fwd: check return value from ethdev info
In reply to Stephen HemmingerNeed to check return value from rte_eth_dev_info_get.
--- examples/l3fwd-graph/main.c | 12 ++++++++++-- examples/l3fwd/l3fwd_fib.c | 16 ++++++++++++---- examples/l3fwd/l3fwd_lpm.c | 14 ++++++++++---- 3 files changed, 32 insertions(+), 10 deletions(-)
examples/l3fwd-graph/main.c +10 -2
@@ -1088,7 +1088,10 @@ main(int argc, char **argv)printf ("Creating queues: nb_rxq=%d nb_txq=%u... " , nb_rx_queue, n_tx_queue); -rte_eth_dev_info_get (portid, &dev_info); + ret =rte_eth_dev_info_get (portid, &dev_info); +if (ret !=0 ) +rte_exit (EXIT_FAILURE , +"Unable to get info for port %u\n" , portid); ret =config_port_max_pkt_len (&local_port_conf, &dev_info);if (ret !=0 )
@@ -1220,7 +1223,12 @@ main(int argc, char **argv)printf ("rxq=%d,%d,%d " , portid, queueid, socketid);fflush (stdout); -rte_eth_dev_info_get (portid, &dev_info); + ret =rte_eth_dev_info_get (portid, &dev_info); +if (ret <0 ) +rte_exit (EXIT_FAILURE , +"rte_eth_dev_info_get: err=%d, port=%u\n" , + ret, portid); + rxq_conf = dev_info.default_rxconf; rxq_conf.offloads = port_conf.rxmode.offloads;if (!per_port_pool)
examples/l3fwd/l3fwd_fib.c +12 -4
@@ -675,8 +675,12 @@ setup_fib(const int socketid) enabled_port_mask) == 0)continue ; -rte_eth_dev_info_get (route_base_v4[i].if_out, - &dev_info); + ret =rte_eth_dev_info_get (route_base_v4[i].if_out, &dev_info); +if (ret <0 ) +rte_exit (EXIT_FAILURE , +"Unable to get device info for port %u\n" , + route_base_v4[i].if_out); + ret = rte_fib_add(ipv4_l3fwd_fib_lookup_struct[socketid], route_base_v4[i].ip, route_base_v4[i].depth,
@@ -729,8 +733,12 @@ setup_fib(const int socketid) enabled_port_mask) == 0)continue ; -rte_eth_dev_info_get (route_base_v6[i].if_out, - &dev_info); + ret =rte_eth_dev_info_get (route_base_v6[i].if_out, &dev_info); +if (ret <0 ) +rte_exit (EXIT_FAILURE , +"Unable to get device info for port %u\n" , + route_base_v6[i].if_out); + ret = rte_fib6_add(ipv6_l3fwd_fib_lookup_struct[socketid], route_base_v6[i].ip_8, route_base_v6[i].depth,
examples/l3fwd/l3fwd_lpm.c +10 -4
@@ -588,8 +588,11 @@ setup_lpm(const int socketid) enabled_port_mask) == 0)continue ; -rte_eth_dev_info_get (route_base_v4[i].if_out, - &dev_info); + ret =rte_eth_dev_info_get (route_base_v4[i].if_out, &dev_info); +if (ret <0 ) +rte_exit (EXIT_FAILURE ,"Unable to get device info for port %u\n" , + route_base_v4[i].if_out); + ret = rte_lpm_add(ipv4_l3fwd_lpm_lookup_struct[socketid], route_base_v4[i].ip, route_base_v4[i].depth,
@@ -632,8 +635,11 @@ setup_lpm(const int socketid) enabled_port_mask) == 0)continue ; -rte_eth_dev_info_get (route_base_v6[i].if_out, - &dev_info); + ret =rte_eth_dev_info_get (route_base_v6[i].if_out, &dev_info); +if (ret <0 ) +rte_exit (EXIT_FAILURE ,"Unable to get device info for port %u\n" , + route_base_v6[i].if_out); + ret = rte_lpm6_add(ipv6_l3fwd_lpm_lookup_struct[socketid], route_base_v6[i].ip_8, route_base_v6[i].depth,
Signature · 1 line
2.45.2
PATCH 6/10 examples/ntb: always check return value
In reply to Stephen HemmingerThe ethdev_info is only valid if rte_eth_dev_info_get returns success.
--- examples/ntb/ntb_fwd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
examples/ntb/ntb_fwd.c +4 -1
@@ -1285,7 +1285,10 @@ main(int argc, char **argv) eth_port_id =rte_eth_find_next (0 );if (eth_port_id <RTE_MAX_ETHPORTS ) { -rte_eth_dev_info_get (eth_port_id, ðdev_info); + ret =rte_eth_dev_info_get (eth_port_id, ðdev_info); +if (ret) +rte_exit (EXIT_FAILURE ,"Can't get info for port %u\n" , eth_port_id); + eth_pconf.rx_adv_conf.rss_conf.rss_hf &= ethdev_info.flow_type_rss_offloads; ret = rte_eth_dev_configure(eth_port_id, num_queues,
Signature · 1 line
2.45.2
PATCH 7/10 examples/pipeline: check return value of ethdev functions
In reply to Stephen HemmingerThe rte_eth_dev_info_get and rte_eth_link_get functions may return an error, and in that case the information structure is undefined. The port is valid check is not needed, that can be handled by rte_eth_dev_info_get checks.
--- examples/pipeline/cli.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
examples/pipeline/cli.c +4 -3
@@ -390,14 +390,15 @@ ethdev_show(uint16_t port_id, char **out, size_t *out_size)uint32_t length;uint16_t mtu =0 ; -if (!rte_eth_dev_is_valid_port (port_id)) +if (rte_eth_dev_info_get (port_id, &info) !=0 ) +return ; + +if (rte_eth_link_get (port_id, &link) !=0 )return ;rte_eth_dev_get_name_by_port (port_id, name); -rte_eth_dev_info_get (port_id, &info);rte_eth_stats_get (port_id, &stats);rte_eth_macaddr_get (port_id, &addr); -rte_eth_link_get (port_id, &link);rte_eth_dev_get_mtu (port_id, &mtu); snprintf(*out, *out_size,
Signature · 1 line
2.45.2
PATCH 8/10 examples/qos_sched: check return value from rte_eth_link_get
In reply to Stephen HemmingerThe return status of link is undefined if call to rte_eth_link_get returns an error.
--- examples/qos_sched/init.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
examples/qos_sched/init.c +11 -2
@@ -323,6 +323,7 @@ int app_init(void)uint32_t i;char ring_name[MAX_NAME_LEN ];char pool_name[MAX_NAME_LEN ]; +int ret;if (rte_eth_dev_count_avail () ==0 )rte_exit (EXIT_FAILURE ,"No Ethernet port - bye\n" );
@@ -368,12 +369,20 @@ int app_init(void)app_init_port (qos_conf[i].tx_port, qos_conf[i].mbuf_pool);memset (&link,0 ,sizeof (link)); -rte_eth_link_get (qos_conf[i].tx_port, &link); + ret =rte_eth_link_get (qos_conf[i].tx_port, &link); +if (ret <0 ) +rte_exit (EXIT_FAILURE , +"rte_eth_link_get: err=%d, port=%u: %s\n" , + ret, qos_conf[i].tx_port,rte_strerror (-ret));if (link.link_status ==0 )printf ("Waiting for link on port %u\n" , qos_conf[i].tx_port); +while (link.link_status ==0 && retry_count--) {rte_delay_ms (retry_delay); -rte_eth_link_get (qos_conf[i].tx_port, &link); + ret =rte_eth_link_get (qos_conf[i].tx_port, &link); +rte_exit (EXIT_FAILURE , +"rte_eth_link_get: err=%d, port=%u: %s\n" , + ret, qos_conf[i].tx_port,rte_strerror (-ret)); } qos_conf[i].sched_port =app_init_sched_port (qos_conf[i].tx_port, socket);
Signature · 1 line
2.45.2
PATCH 9/10 ethdev: check return value from rte_eth_dev_info_get
In reply to Stephen HemmingerThe mac compare must check return value from rte_eth_dev_info_get before using the dev_info information.
--- lib/ethdev/rte_class_eth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
lib/ethdev/rte_class_eth.c +3 -1
@@ -50,8 +50,10 @@ eth_mac_cmp(const char *key __rte_unused,if (rte_ether_unformat_addr (value, &mac) <0 )return -1 ;/* invalid devargs value */ +if (rte_eth_dev_info_get (data->port_id, &dev_info) !=0 ) +return -1 ;/* device mac address unavailable */ +/* Return 0 if devargs MAC is matching one of the device MACs. */ -rte_eth_dev_info_get (data->port_id, &dev_info);for (index =0 ; index < dev_info.max_mac_addrs; index++)if (rte_is_same_ether_addr (&mac, &data->mac_addrs[index]))return 0 ;
Signature · 1 line
2.45.2
Re: [PATCH 09/10] ethdev: check return value from rte_eth_dev_info_get
Quoted 5 lines · Stephen Hemminger
The mac compare must check return value from
rte_eth_dev_info_getbefore using thedev_infoinformation.Signed-off-by Stephen Hemminger <[email protected]>
PATCH 10/10 ethdev: require checking results of info_get functions
In reply to Stephen HemmingerWith functions that return a data structure, the application must check the return value since the data structure contents will be undefined in case of error.
--- lib/ethdev/rte_ethdev.h | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-)
lib/ethdev/rte_ethdev.h +21 -13
@@ -3058,7 +3058,8 @@ int rte_eth_allmulticast_get(uint16_t port_id);* - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ -int rte_eth_link_get (uint16_t port_id,struct rte_eth_link *link); +int rte_eth_link_get(uint16_t port_id, struct rte_eth_link *link) + __rte_warn_unused_result;/** * Retrieve the link status (up/down), the duplex mode (half/full),
@@ -3074,7 +3075,8 @@ int rte_eth_link_get(uint16_t port_id, struct rte_eth_link *link);* - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ -int rte_eth_link_get_nowait (uint16_t port_id,struct rte_eth_link *link); +int rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *link) + __rte_warn_unused_result;/** * @warning
@@ -3408,7 +3410,8 @@ int rte_eth_macaddrs_get(uint16_t port_id, struct rte_ether_addr *ma,* - (-ENODEV) if *port_id* invalid. * - (-EINVAL) if bad parameter. */ -int rte_eth_dev_info_get (uint16_t port_id,struct rte_eth_dev_info *dev_info); +int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info) + __rte_warn_unused_result;/** * @warning
@@ -3426,7 +3429,8 @@ int rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info);* - (-EINVAL) if bad parameter. */ __rte_experimental -int rte_eth_dev_conf_get(uint16_t port_id, struct rte_eth_conf *dev_conf); +int rte_eth_dev_conf_get(uint16_t port_id, struct rte_eth_conf *dev_conf) + __rte_warn_unused_result;/** * Retrieve the firmware version of a device.
@@ -3448,8 +3452,8 @@ int rte_eth_dev_conf_get(uint16_t port_id, struct rte_eth_conf *dev_conf);* - (>0) if *fw_size* is not enough to store firmware version, return * the size of the non truncated string. */ -int rte_eth_dev_fw_version_get (uint16_t port_id, -char *fw_version,size_t fw_size); +int rte_eth_dev_fw_version_get(uint16_t port_id, char *fw_version, size_t fw_size) + __rte_warn_unused_result;/** * Retrieve the supported packet types of an Ethernet device.
@@ -3491,7 +3495,9 @@ int rte_eth_dev_fw_version_get(uint16_t port_id,* - (-EINVAL) if bad parameter. */ int rte_eth_dev_get_supported_ptypes(uint16_t port_id, uint32_t ptype_mask, -uint32_t *ptypes,int num); + uint32_t *ptypes, int num) + __rte_warn_unused_result; +/** * Inform Ethernet device about reduced range of packet types to handle. *
@@ -5089,7 +5095,8 @@ int rte_eth_get_monitor_addr(uint16_t port_id, uint16_t queue_id,* - (-EIO) if device is removed. * - others depends on the specific operations implementation. */ -int rte_eth_dev_get_reg_info (uint16_t port_id,struct rte_dev_reg_info *info); +int rte_eth_dev_get_reg_info(uint16_t port_id, struct rte_dev_reg_info *info) + __rte_warn_unused_result;/** * Retrieve size of device EEPROM
@@ -5161,8 +5168,8 @@ int rte_eth_dev_set_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info);*/ __rte_experimental int -rte_eth_dev_get_module_info (uint16_t port_id, -struct rte_eth_dev_module_info *modinfo); +rte_eth_dev_get_module_info(uint16_t port_id, struct rte_eth_dev_module_info *modinfo) + __rte_warn_unused_result;/** * @warning
@@ -5185,8 +5192,8 @@ rte_eth_dev_get_module_info(uint16_t port_id,*/ __rte_experimental int -rte_eth_dev_get_module_eeprom (uint16_t port_id, -struct rte_dev_eeprom_info *info); +rte_eth_dev_get_module_eeprom(uint16_t port_id, struct rte_dev_eeprom_info *info) + __rte_warn_unused_result;/** * Set the list of multicast addresses to filter on an Ethernet device.
@@ -6839,7 +6846,8 @@ rte_eth_recycle_mbufs(uint16_t rx_port_id, uint16_t rx_queue_id,* - (-EINVAL) if bad parameter. */ __rte_experimental -int rte_eth_buffer_split_get_supported_hdr_ptypes(uint16_t port_id, uint32_t *ptypes, int num); +int rte_eth_buffer_split_get_supported_hdr_ptypes(uint16_t port_id, uint32_t *ptypes, int num) + __rte_warn_unused_result;/** * @warning
Signature · 1 line
2.45.2
Re: [PATCH 10/10] ethdev: require checking results of info_get functions
Quoted 6 lines · Stephen Hemminger
With functions that return a data structure, the application must check the return value since the data structure contents will be undefined in case of error.
Signed-off-by Stephen Hemminger <[email protected]>
Quoted 9 lines
From: Stephen Hemminger [mailto:[email protected]]
Sent: Friday, 4 October 2024 18.22Several places flagged by Coverity and Codeql are from code that calls
rte_eth_dev_info_get()but does not check the return value. Ifrte_eth_dev_info_get()returns an error, the device info is garbage.This patch series uses the function attribute to force code to check the result or there will be a compiler warning.
This is slow path, so no performance issues.
For the series,
Thomas Monjalon
AppliedQuoted 11 lines
Stephen Hemminger (10):
app/test: remove redundant call
net/memif: check return value fromrte_eth_dev_info_get
graph: check return value fromrte_eth_dev_info_getexamples/ethtool: handle devices without registers examples/l3fwd: check return value from ethdev info examples/ntb: always check return value examples/pipeline: check return value of ethdev functions examples/qos_sched: check return value fromrte_eth_link_get
ethdev: check return value fromrte_eth_dev_info_get
ethdev: require checking results ofinfo_getfunctions
Applied, thanks.