On 29/04/2026 18:57, Eelco Chaudron wrote:
External email: Use caution opening links or attachments
On 1 Apr 2026, at 11:13, Eli Britstein wrote:
Refactor common functions from netdev-dpdk to be declared in
netdev-dpdk-private to be reused by netdev-doca.
Thanks for the refactor. See some comments below.
//Eelco
Signed-off-by: Eli Britstein <[email protected]>
---
lib/netdev-dpdk-private.h | 108 ++++++
lib/netdev-dpdk.c | 692 +++++++++++++++++++++-----------------
2 files changed, 492 insertions(+), 308 deletions(-)
diff --git a/lib/netdev-dpdk-private.h b/lib/netdev-dpdk-private.h
index 083ddacb3..1b33c27a4 100644
--- a/lib/netdev-dpdk-private.h
+++ b/lib/netdev-dpdk-private.h
@@ -64,6 +64,16 @@ extern const struct rte_eth_conf port_conf;
typedef uint16_t dpdk_port_t;
#define DPDK_PORT_ID_FMT "%"PRIu16
Add a comment.
/* Forward declarations. */
Ack
+struct dp_packet;
+struct dp_packet_batch;
+struct eth_addr;
+struct netdev;
+struct netdev_stats;
+struct rte_eth_xstat;
+struct rte_eth_xstat_name;
+struct smap;
+enum netdev_features;
+
/* Enums. */
/* Enum definitions. */
Ack, in the first refactor commit.
enum dpdk_hw_ol_features {
@@ -84,6 +94,11 @@ enum dpdk_hw_ol_features {
/* Structs. */
/* Structure definitions. */
Ack, in the first refactor commit.
+struct netdev_dpdk_watchdog_params {
+ struct ovs_mutex *mutex;
+ struct ovs_list *list;
+};
+
#ifndef NETDEV_DPDK_TX_Q_TYPE
#error "NETDEV_DPDK_TX_Q_TYPE must be defined before" \
"including netdev-dpdk-private.h"
I would move these #error directives to the top of the include file.
Ack, in the first refactor commit.
@@ -104,6 +119,12 @@ struct netdev_rxq_dpdk {
dpdk_port_t port_id;
};
+static inline struct netdev_rxq_dpdk *
+netdev_rxq_dpdk_cast(const struct netdev_rxq *rxq)
+{
+ return CONTAINER_OF(rxq, struct netdev_rxq_dpdk, up);
+}
+
I would move this down with the other cast function, and probably
call it netdev_dpdk_rxq_cast() for naming consistency.
Ack
struct netdev_dpdk_common {
PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
uint16_t port_id;
@@ -179,4 +200,91 @@ dpdk_dev_is_started(struct netdev_dpdk_common *common)
return started;
}
+/* Common functions shared between netdev-dpdk and netdev-doca. */
+
We are missing all lock annotations to the exported functions.
Here is a quick summary:
Missing OVS_REQUIRES(common->mutex);
netdev_dpdk_detect_hw_ol_features()
netdev_dpdk_update_netdev_flags()
netdev_dpdk_clear_xstats()
netdev_dpdk_configure_xstats()
netdev_dpdk_set_rxq_config()
netdev_dpdk_get_config_common()
netdev_dpdk_set_etheraddr__()
netdev_dpdk_update_flags__()
Missing OVS_REQUIRES(dpdk_mutex) (tricky):
netdev_dpdk_get_port_by_devargs()
netdev_dpdk_lookup_by_port_id__()
Should maybe have a OVS_EXCLUDED():
netdev_dpdk_get_status__()
Ack
+/* Type-independent helpers. */
+struct rte_mempool *netdev_dpdk_mp_create_pool(const char *pool_name,
+ uint32_t n_mbufs,
+ uint32_t mbuf_size,
+ int socket_id);
+uint32_t netdev_dpdk_buf_size(int mtu);
+size_t netdev_dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,
+ struct dp_packet_batch *batch);
+const char *netdev_dpdk_link_speed_to_str__(uint32_t link_speed);
Functions ending with __ are for internal-only use, so they should be
properly named when exported. netdev_dpdk_link_speed_to_str() does
not exist, so it can be used.
Ack
+void netdev_dpdk_mbuf_dump(const char *prefix, const char *message,
+ const struct rte_mbuf *mbuf);
+
+/* Functions operating on struct netdev_dpdk_common. */
+void netdev_dpdk_detect_hw_ol_features(struct netdev_dpdk_common *common,
+ const struct rte_eth_dev_info *info);
+void netdev_dpdk_build_port_conf(struct netdev_dpdk_common *common,
+ const struct rte_eth_dev_info *info,
+ struct rte_eth_conf *conf);
+void netdev_dpdk_check_link_status(struct netdev_dpdk_common *common);
+
+void *netdev_dpdk_watchdog(void *params);
+
+void netdev_dpdk_update_netdev_flags(struct netdev_dpdk_common *common);
+void netdev_dpdk_clear_xstats(struct netdev_dpdk_common *common);
+void netdev_dpdk_configure_xstats(struct netdev_dpdk_common *common);
+void netdev_dpdk_set_rxq_config(struct netdev_dpdk_common *common,
+ const struct smap *args);
+int netdev_dpdk_prep_hwol_batch(struct netdev_dpdk_common *common,
+ struct rte_mbuf **pkts, int pkt_cnt);
+int netdev_dpdk_filter_packet_len(struct netdev_dpdk_common *common,
+ struct rte_mbuf **pkts, int pkt_cnt);
+int netdev_dpdk_eth_tx_burst(struct netdev_dpdk_common *common,
+ dpdk_port_t port_id, int qid,
+ struct rte_mbuf **pkts, int cnt);
+void netdev_dpdk_get_config_common(struct netdev_dpdk_common *common,
+ struct smap *args);
+struct netdev_dpdk_common *
+netdev_dpdk_lookup_by_port_id__(dpdk_port_t port_id,
+ struct ovs_list *list);
Functions ending with __ are for internal-only use. Since this is now
exported, rename to netdev_dpdk_lookup_common_by_port_id() to remove
the suffix and clarify that it returns netdev_dpdk_common.
Ack
+dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs);
+
+/* Rxq ops shared between dpdk and doca. */
+struct netdev_rxq *netdev_dpdk_rxq_alloc(void);
+int netdev_dpdk_rxq_construct(struct netdev_rxq *rxq);
+void netdev_dpdk_rxq_destruct(struct netdev_rxq *rxq);
+void netdev_dpdk_rxq_dealloc(struct netdev_rxq *rxq);
+
+/* Netdev provider ops usable by both dpdk and doca. */
+
No new line needed here.
Ack
+int netdev_dpdk_get_numa_id(const struct netdev *netdev);
+int netdev_dpdk_set_tx_multiq(struct netdev *netdev, unsigned int n_txq);
+int netdev_dpdk_set_etheraddr__(struct netdev_dpdk_common *common,
+ const struct eth_addr mac);
Functions ending with __ are for internal-only use. Since this is now
exported, rename to netdev_dpdk_set_dev_etheraddr() or
netdev_dpdk_set_dpdk_etheraddr().
Ack
+int netdev_dpdk_update_flags(struct netdev *netdev,
+ enum netdev_flags off, enum netdev_flags on,
+ enum netdev_flags *old_flagsp);
+int netdev_dpdk_update_flags__(struct netdev_dpdk_common *common,
+ enum netdev_flags off, enum netdev_flags on,
+ enum netdev_flags *old_flagsp);
Same as above netdev_dpdk_update_dev_flags() or netdev_dpdk_update_dpdk_flags().
Ack
+int netdev_dpdk_set_etheraddr(struct netdev *netdev,
+ const struct eth_addr mac);
+int netdev_dpdk_get_etheraddr(const struct netdev *netdev,
+ struct eth_addr *mac);
+int netdev_dpdk_get_mtu(const struct netdev *netdev, int *mtup);
+int netdev_dpdk_get_ifindex(const struct netdev *netdev);
+int netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier);
+long long int netdev_dpdk_get_carrier_resets(const struct netdev *netdev);
+int netdev_dpdk_set_miimon(struct netdev *netdev, long long int interval);
+int netdev_dpdk_get_speed(const struct netdev *netdev, uint32_t *current,
+ uint32_t *max);
+int netdev_dpdk_get_features(const struct netdev *netdev,
+ enum netdev_features *current,
+ enum netdev_features *advertised,
+ enum netdev_features *supported,
+ enum netdev_features *peer);
+void netdev_dpdk_convert_xstats(struct netdev_stats *stats,
+ const struct rte_eth_xstat *xstats,
+ const struct rte_eth_xstat_name *names,
+ const unsigned int size);
+int netdev_dpdk_get_stats(const struct netdev *netdev,
+ struct netdev_stats *stats);
+int netdev_dpdk_get_status__(const struct netdev *netdev,
+ struct ovs_mutex *dev_mutex,
+ struct smap *args);
Functions ending with __ are for internal-only use. So you need a proper name
here.
Ack
+
#endif /* NETDEV_DPDK_PRIVATE_H */
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 2562eb4b4..dbf988de4 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -452,17 +452,11 @@ static void netdev_dpdk_vhost_destruct(struct netdev
*netdev);
static int netdev_dpdk_get_sw_custom_stats(const struct netdev *,
struct netdev_custom_stats *);
-static void netdev_dpdk_configure_xstats(struct netdev_dpdk_common *common);
-static void netdev_dpdk_clear_xstats(struct netdev_dpdk_common *common);
-
int netdev_dpdk_get_vid(const struct netdev_dpdk *dev);
struct ingress_policer *
netdev_dpdk_get_ingress_policer(const struct netdev_dpdk *dev);
-static void netdev_dpdk_mbuf_dump(const char *prefix, const char *message,
- const struct rte_mbuf *);
-
static bool
is_dpdk_class(const struct netdev_class *class)
{
@@ -479,8 +473,8 @@ is_dpdk_class(const struct netdev_class *class)
* behaviour, which reduces performance. To prevent this, use a buffer size
* that is closest to 'mtu', but which satisfies the aforementioned criteria.
*/
-static uint32_t
-dpdk_buf_size(int mtu)
+uint32_t
+netdev_dpdk_buf_size(int mtu)
{
return ROUND_UP(MTU_TO_MAX_FRAME_LEN(mtu), NETDEV_DPDK_MBUF_ALIGN)
+ RTE_PKTMBUF_HEADROOM;
@@ -630,6 +624,49 @@ dpdk_calculate_mbufs(struct netdev_dpdk *dev, int mtu)
return n_mbufs;
}
+struct rte_mempool *
+netdev_dpdk_mp_create_pool(const char *pool_name, uint32_t n_mbufs,
+ uint32_t mbuf_size, int socket_id)
Fix indentation.
Ack
+{
+ uint32_t mbuf_priv_data_len;
+ uint32_t aligned_mbuf_size;
+ struct rte_mempool *mp;
...
n_mbufs = dpdk_calculate_mbufs(dev, mtu);
do {
- /* Full DPDK memory pool name must be unique and cannot be
- * longer than RTE_MEMPOOL_NAMESIZE. Note that for the shared
- * mempool case this can result in one device using a mempool
- * which references a different device in it's name. However as
- * mempool names are hashed, the device name will not be readable
- * so this is not an issue for tasks such as debugging.
- */
ret = snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
"ovs%08x%02d%05d%07u",
hash, socket_id, mtu, n_mbufs);
The comment explaining why mempool names are allowed to reference a
different device was removed when the pool creation logic was extracted
into netdev_dpdk_mp_create_pool(). The snprintf call remains in
dpdk_mp_create(), but its context comment is gone. Should that
explanation be preserved here or moved into netdev_dpdk_mp_create_pool()?
Restored here.
@@ -684,38 +711,12 @@ dpdk_mp_create(struct netdev_dpdk *dev, int mtu)
dev->common.requested_n_rxq, dev->common.requested_n_txq,
RTE_CACHE_LINE_SIZE);
- /* The size of the mbuf's private area (i.e. area that holds OvS'
- * dp_packet data)*/
- mbuf_priv_data_len = sizeof(struct dp_packet) -
- sizeof(struct rte_mbuf);
- /* The size of the entire dp_packet. */
- pkt_size = sizeof(struct dp_packet) + mbuf_size;
- /* mbuf size, rounded up to cacheline size. */
- aligned_mbuf_size = ROUND_UP(pkt_size, RTE_CACHE_LINE_SIZE);
- /* If there is a size discrepancy, add padding to mbuf_priv_data_len.
- * This maintains mbuf size cache alignment, while also honoring RX
- * buffer alignment in the data portion of the mbuf. If this adjustment
- * is not made, there is a possiblity later on that for an element of
- * the mempool, buf, buf->data_len < (buf->buf_len - buf->data_off).
- * This is problematic in the case of multi-segment mbufs, particularly
- * when an mbuf segment needs to be resized (when [push|popp]ing a VLAN
- * header, for example.
- */
- mbuf_priv_data_len += (aligned_mbuf_size - pkt_size);
-
- dmp->mp = rte_pktmbuf_pool_create(mp_name, n_mbufs, MP_CACHE_SZ,
- mbuf_priv_data_len,
- mbuf_size,
- socket_id);
+ dmp->mp = netdev_dpdk_mp_create_pool(mp_name, n_mbufs, mbuf_size,
+ socket_id);
Alignment.
Ack
if (dmp->mp) {
VLOG_DBG("Allocated \"%s\" mempool with %u mbufs",
mp_name, n_mbufs);
- /* rte_pktmbuf_pool_create has done some initialization of the
- * rte_mbuf part of each dp_packet, while ovs_rte_pktmbuf_init
- * initializes some OVS specific fields of dp_packet.
- */
- rte_mempool_obj_iter(dmp->mp, ovs_rte_pktmbuf_init, NULL);
return dmp;
} else if (rte_errno == EEXIST) {
/* A mempool with the same name already exists. We just
@@ -821,7 +822,7 @@ static int
netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)
OVS_REQUIRES(dev->common.mutex)
{
- uint32_t buf_size = dpdk_buf_size(dev->common.requested_mtu);
+ uint32_t buf_size = netdev_dpdk_buf_size(dev->common.requested_mtu);
struct dpdk_mp *dmp;
int ret = 0;
@@ -866,8 +867,8 @@ netdev_dpdk_mempool_configure(struct netdev_dpdk *dev)
return ret;
}
-static void
-check_link_status(struct netdev_dpdk_common *common)
+void
+netdev_dpdk_check_link_status(struct netdev_dpdk_common *common)
{
struct rte_eth_link link;
@@ -902,21 +903,24 @@ check_link_status(struct netdev_dpdk_common *common)
}
}
-static void *
-dpdk_watchdog(void *dummy OVS_UNUSED)
+void *
+netdev_dpdk_watchdog(void *args_)
Should this be params like in the include file, or both arg?
both params_
{
+ struct netdev_dpdk_watchdog_params *params = args_;
...
}
-static int
-dpdk_eth_dev_port_config(struct netdev_dpdk_common *common,
- const struct rte_eth_dev_info *info,
- int n_rxq, int n_txq)
+void
+netdev_dpdk_detect_hw_ol_features(struct netdev_dpdk_common *common,
+ const struct rte_eth_dev_info *info)
Fix indentation.
Ack
+ OVS_REQUIRES(common->mutex)
{
- struct rte_eth_conf conf = port_conf;
...
+ }
+}
+
+void
+netdev_dpdk_build_port_conf(struct netdev_dpdk_common *common,
+ const struct rte_eth_dev_info *info,
+ struct rte_eth_conf *conf)
Fix indentations.
Ack
+{
/* As of DPDK 17.11.1 a few PMDs require to explicitly enable
* scatter to support jumbo RX.
...
- if (info.rx_offload_capa & RTE_ETH_RX_OFFLOAD_SCATTER) {
- dev->common.hw_ol_features |= NETDEV_RX_HW_SCATTER;
- } else {
- /* Do not warn on lack of scatter support */
The comment explaining why scatter offload suppresses its warning was
dropped when the code was moved into netdev_dpdk_detect_hw_ol_features().
Can it be restored to keep the asymmetry with the other VLOG_WARN calls
documented?
Good catch. Restored
- dev->common.hw_ol_features &= ~NETDEV_RX_HW_SCATTER;
- }
-
...
}
/* Return the first DPDK port id matching the devargs pattern. */
-static dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs)
+dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs)
Split on two lines while changing.
dpdk_port_t
netdev_dpdk_get_port_by_devargs(const char *devargs)
Ack
OVS_REQUIRES(dpdk_mutex)
{
dpdk_port_t port_id;
@@ -2058,8 +2095,8 @@ dpdk_eth_event_callback(dpdk_port_t port_id, enum
rte_eth_event_type type,
...
uint32_t ret;
- ret = rte_eth_tx_burst(dev->common.port_id, qid, pkts + nb_tx,
+ ret = rte_eth_tx_burst(port_id, qid, pkts + nb_tx,
nb_tx_prep - nb_tx);
This will fit on one line;
ret = rte_eth_tx_burst(port_id, qid, pkts + nb_tx, nb_tx_prep - nb_tx);
Ack
if (!ret) {
break;
@@ -2725,6 +2761,7 @@ netdev_dpdk_eth_tx_burst(struct netdev_dpdk *dev, int qid,
nb_tx += ret;
}
+out:
if (OVS_UNLIKELY(nb_tx != cnt)) {
/* Free buffers, which we couldn't transmit. */
rte_pktmbuf_free_bulk(&pkts[nb_tx], cnt - nb_tx);
@@ -2926,9 +2963,9 @@ netdev_dpdk_qos_run(struct netdev_dpdk *dev, struct
rte_mbuf **pkts,
return cnt;
}
-static int
-netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts,
- int pkt_cnt)
+int
+netdev_dpdk_filter_packet_len(struct netdev_dpdk_common *common,
+ struct rte_mbuf **pkts, int pkt_cnt)
{
int i = 0;
int cnt = 0;
@@ -2938,12 +2975,12 @@ netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev,
struct rte_mbuf **pkts,
* during the offloading preparation for performance reasons. */
for (i = 0; i < pkt_cnt; i++) {
pkt = pkts[i];
- if (OVS_UNLIKELY((pkt->pkt_len > dev->common.max_packet_len)
+ if (OVS_UNLIKELY((pkt->pkt_len > common->max_packet_len)
&& !pkt->tso_segsz)) {
VLOG_WARN_RL(&rl, "%s: Too big size %" PRIu32 " "
"max_packet_len %d",
As we change this anyway, the line above should fit on a single line.
Ack
- dev->common.up.name, pkt->pkt_len,
- dev->common.max_packet_len);
+ common->up.name, pkt->pkt_len,
+ common->max_packet_len);
rte_pktmbuf_free(pkt);
continue;
}
@@ -3111,8 +3148,8 @@ dpdk_copy_dp_packet_to_mbuf(struct rte_mempool *mp,
struct dp_packet *pkt_orig)
* DPDK memory.
*
* Returns the number of good packets in the batch. */
-static size_t
-dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,
+size_t
+netdev_dpdk_copy_batch_to_mbuf(struct netdev_dpdk_common *common,
struct dp_packet_batch *batch)
{
size_t i, size = dp_packet_batch_size(batch);
@@ -3157,13 +3194,13 @@ netdev_dpdk_common_send(struct netdev *netdev, struct
dp_packet_batch *batch,
/* Copy dp-packets to mbufs. */
if (OVS_UNLIKELY(need_copy)) {
- cnt = dpdk_copy_batch_to_mbuf(&dev->common, batch);
+ cnt = netdev_dpdk_copy_batch_to_mbuf(&dev->common, batch);
stats->tx_failure_drops += pkt_cnt - cnt;
pkt_cnt = cnt;
}
/* Drop oversized packets. */
- cnt = netdev_dpdk_filter_packet_len(dev, pkts, pkt_cnt);
+ cnt = netdev_dpdk_filter_packet_len(&dev->common, pkts, pkt_cnt);
stats->tx_mtu_exceeded_drops += pkt_cnt - cnt;
pkt_cnt = cnt;
@@ -3290,7 +3327,8 @@ netdev_dpdk_eth_send(struct netdev *netdev, int qid,
cnt = netdev_dpdk_common_send(netdev, batch, &stats);
- dropped = netdev_dpdk_eth_tx_burst(dev, qid, pkts, cnt);
+ dropped = netdev_dpdk_eth_tx_burst(&dev->common, dev->common.port_id,
+ qid, pkts, cnt);
Alignment.
Ack
stats.tx_failure_drops += dropped;
dropped += batch_cnt - cnt;
if (OVS_UNLIKELY(dropped)) {
@@ -3312,14 +3350,14 @@ netdev_dpdk_eth_send(struct netdev *netdev, int qid,
return 0;
}
-static int
-netdev_dpdk_set_etheraddr__(struct netdev_dpdk *dev, const struct eth_addr mac)
- OVS_REQUIRES(dev->common.mutex)
+int
+netdev_dpdk_set_etheraddr__(struct netdev_dpdk_common *common,
+ const struct eth_addr mac)
+ OVS_REQUIRES(common->mutex)
{
- struct netdev_dpdk_common *common = &dev->common;
int err = 0;
- if (dev->type == DPDK_DEV_ETH) {
+ if (common->port_id != DPDK_ETH_PORT_ID_INVALID) {
struct rte_ether_addr ea;
memcpy(ea.addr_bytes, mac.ea, ETH_ADDR_LEN);
@@ -3336,25 +3374,25 @@ netdev_dpdk_set_etheraddr__(struct netdev_dpdk *dev,
const struct eth_addr mac)
return err;
}
-static int
+int
netdev_dpdk_set_etheraddr(struct netdev *netdev, const struct eth_addr mac)
{
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+ struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
int err = 0;
- ovs_mutex_lock(&dev->common.mutex);
- if (!eth_addr_equals(dev->common.hwaddr, mac)) {
- err = netdev_dpdk_set_etheraddr__(dev, mac);
+ ovs_mutex_lock(&common->mutex);
+ if (!eth_addr_equals(common->hwaddr, mac)) {
+ err = netdev_dpdk_set_etheraddr__(common, mac);
if (!err) {
netdev_change_seq_changed(netdev);
}
}
- ovs_mutex_unlock(&dev->common.mutex);
+ ovs_mutex_unlock(&common->mutex);
return err;
}
-static int
+int
netdev_dpdk_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
@@ -3366,7 +3404,7 @@ netdev_dpdk_get_etheraddr(const struct netdev *netdev,
struct eth_addr *mac)
return 0;
}
-static int
+int
netdev_dpdk_get_mtu(const struct netdev *netdev, int *mtup)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
@@ -3711,7 +3749,7 @@ out:
return 0;
}
-static void
+void
netdev_dpdk_convert_xstats(struct netdev_stats *stats,
const struct rte_eth_xstat *xstats,
const struct rte_eth_xstat_name *names,
@@ -3754,10 +3792,10 @@ netdev_dpdk_convert_xstats(struct netdev_stats *stats,
#undef DPDK_XSTATS
}
-static int
+int
netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier);
Guess we no longer need this forward declaration, as its in the include file.
Ack
-static int
+int
netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
@@ -3767,6 +3805,12 @@ netdev_dpdk_get_stats(const struct netdev *netdev,
struct netdev_stats *stats)
netdev_dpdk_get_carrier(netdev, &gg);
ovs_mutex_lock(&common->mutex);
+ if (!dpdk_dev_is_started(common)) {
+ memset(stats, 0, sizeof *stats);
+ ovs_mutex_unlock(&common->mutex);
Don't like the inline unlock() pattern, but its already used below,
so lets keep it.
Ack
+ return 0;
+ }
+
struct rte_eth_xstat *rte_xstats = NULL;
struct rte_eth_xstat_name *rte_xstats_names = NULL;
int rte_xstats_len, rte_xstats_new_len, rte_xstats_ret;
@@ -3789,7 +3833,7 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct
netdev_stats *stats)
rte_xstats_names = xcalloc(rte_xstats_len, sizeof *rte_xstats_names);
rte_xstats = xcalloc(rte_xstats_len, sizeof *rte_xstats);
- /* Retreive xstats names */
+ /* Retrieve 'xstats' names. */
rte_xstats_new_len = rte_eth_xstats_get_names(common->port_id,
rte_xstats_names,
rte_xstats_len);
@@ -3798,7 +3842,7 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct
netdev_stats *stats)
common->port_id);
goto out;
}
- /* Retreive xstats values */
+ /* Retrieve 'xstats' values. */
memset(rte_xstats, 0xff, sizeof *rte_xstats * rte_xstats_len);
rte_xstats_ret = rte_eth_xstats_get(common->port_id, rte_xstats,
rte_xstats_len);
@@ -3937,7 +3981,7 @@ netdev_dpdk_get_sw_custom_stats(const struct netdev
*netdev,
return 0;
}
-static int
+int
netdev_dpdk_get_features(const struct netdev *netdev,
enum netdev_features *current,
enum netdev_features *advertised,
@@ -4002,7 +4046,7 @@ netdev_dpdk_get_features(const struct netdev *netdev,
return 0;
}
-static int
+int
netdev_dpdk_get_speed(const struct netdev *netdev, uint32_t *current,
uint32_t *max)
{
@@ -4013,7 +4057,12 @@ netdev_dpdk_get_speed(const struct netdev *netdev,
uint32_t *current,
ovs_mutex_lock(&common->mutex);
link = common->link;
- diag = rte_eth_dev_info_get(common->port_id, &dev_info);
+ if (dpdk_dev_is_started(common)) {
+ diag = rte_eth_dev_info_get(common->port_id, &dev_info);
+ } else {
+ memset(&dev_info, 0, sizeof dev_info);
+ diag = -ENODEV;
Got confused here, but the value is not returned, so we should be fine,
as the rte API also returns a negative value.
Right. removed.
+ }
ovs_mutex_unlock(&common->mutex);
*current = link.link_speed != RTE_ETH_SPEED_NUM_UNKNOWN
@@ -4158,7 +4207,7 @@ netdev_dpdk_set_policing(struct netdev* netdev, uint32_t
policer_rate,
return 0;
}
-static int
+int
netdev_dpdk_get_ifindex(const struct netdev *netdev)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
@@ -4173,13 +4222,13 @@ netdev_dpdk_get_ifindex(const struct netdev *netdev)
return ifindex;
}
-static int
+int
netdev_dpdk_get_carrier(const struct netdev *netdev, bool *carrier)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
ovs_mutex_lock(&common->mutex);
- check_link_status(common);
+ netdev_dpdk_check_link_status(common);
*carrier = common->link.link_status;
ovs_mutex_unlock(&common->mutex);
@@ -4205,7 +4254,7 @@ netdev_dpdk_vhost_get_carrier(const struct netdev
*netdev, bool *carrier)
return 0;
}
-static long long int
+long long int
netdev_dpdk_get_carrier_resets(const struct netdev *netdev)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
@@ -4218,21 +4267,19 @@ netdev_dpdk_get_carrier_resets(const struct netdev
*netdev)
return carrier_resets;
}
-static int
+int
netdev_dpdk_set_miimon(struct netdev *netdev OVS_UNUSED,
long long int interval OVS_UNUSED)
{
return EOPNOTSUPP;
}
-static int
-netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
+int
+netdev_dpdk_update_flags__(struct netdev_dpdk_common *common,
enum netdev_flags off, enum netdev_flags on,
enum netdev_flags *old_flagsp)
- OVS_REQUIRES(dev->common.mutex)
+ OVS_REQUIRES(common->mutex)
{
- struct netdev_dpdk_common *common = &dev->common;
-
if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
return EINVAL;
}
@@ -4245,9 +4292,8 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
return 0;
}
- if (dev->type == DPDK_DEV_ETH) {
-
- if ((dev->common.flags ^ *old_flagsp) & NETDEV_UP) {
+ if (common->port_id != DPDK_ETH_PORT_ID_INVALID) {
+ if ((common->flags ^ *old_flagsp) & NETDEV_UP) {
int err;
if (common->flags & NETDEV_UP) {
@@ -4272,6 +4318,8 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
netdev_change_seq_changed(&common->up);
} else {
+ struct netdev_dpdk *dev = netdev_dpdk_cast(&common->up);
+
The original code used dev->type == DPDK_DEV_ETH to distinguish ETH from
VHOST devices. The replacement condition, common->port_id !=
DPDK_ETH_PORT_ID_INVALID, relies on the assumption that VHOST devices
always carry DPDK_ETH_PORT_ID_INVALID and ETH devices never do. Looking
at vhost_common_construct(), it does pass DPDK_ETH_PORT_ID_INVALID, so
today the two conditions are equivalent. However, port_id is mutable; it
can transition to DPDK_ETH_PORT_ID_INVALID during a reset
(dpdk_eth_dev_init() sets new_port_id = DPDK_ETH_PORT_ID_INVALID on
failure). Can an ETH device temporarily carry DPDK_ETH_PORT_ID_INVALID
while a reset is in progress, causing netdev_dpdk_update_flags__() or
netdev_dpdk_set_etheraddr__() to take the VHOST branch by mistake?
Guess we might need to check all other cases where we use
DPDK_ETH_PORT_ID_INVALID instead of the dev->type.
I keep type in common and keep the checks on DPDK_DEV_ETH instead of
worrying about INVALID.
/* If DPDK_DEV_VHOST device's NETDEV_UP flag was changed and vhost is
* running then change netdev's change_seq to trigger link state
* update. */
@@ -4293,17 +4341,17 @@ netdev_dpdk_update_flags__(struct netdev_dpdk *dev,
return 0;
}
-static int
+int
netdev_dpdk_update_flags(struct netdev *netdev,
enum netdev_flags off, enum netdev_flags on,
enum netdev_flags *old_flagsp)
{
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+ struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
int error;
- ovs_mutex_lock(&dev->common.mutex);
- error = netdev_dpdk_update_flags__(dev, off, on, old_flagsp);
- ovs_mutex_unlock(&dev->common.mutex);
+ ovs_mutex_lock(&common->mutex);
+ error = netdev_dpdk_update_flags__(common, off, on, old_flagsp);
+ ovs_mutex_unlock(&common->mutex);
return error;
}
@@ -4378,7 +4426,7 @@ netdev_dpdk_vhost_user_get_status(const struct netdev
*netdev,
* Convert a given uint32_t link speed defined in DPDK to a string
* equivalent.
*/
-static const char *
+const char *
netdev_dpdk_link_speed_to_str__(uint32_t link_speed)
{
switch (link_speed) {
@@ -4398,31 +4446,28 @@ netdev_dpdk_link_speed_to_str__(uint32_t link_speed)
}
}
-static int
-netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)
+int
+netdev_dpdk_get_status__(const struct netdev *netdev,
+ struct ovs_mutex *dev_mutex,
+ struct smap *args)
{
struct netdev_dpdk_common *common = netdev_dpdk_common_cast(netdev);
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
struct rte_eth_dev_info dev_info;
- size_t rx_steer_flows_num;
- uint64_t rx_steer_flags;
uint32_t link_speed;
- int n_rxq;
int diag;
if (!rte_eth_dev_is_valid_port(common->port_id)) {
return ENODEV;
}
- ovs_mutex_lock(&dpdk_mutex);
+ ovs_assert(dev_mutex);
+
+ ovs_mutex_lock(dev_mutex);
ovs_mutex_lock(&common->mutex);
diag = rte_eth_dev_info_get(common->port_id, &dev_info);
link_speed = common->link.link_speed;
- rx_steer_flags = dev->rx_steer_flags;
- rx_steer_flows_num = dev->rx_steer_flows_num;
- n_rxq = netdev->n_rxq;
ovs_mutex_unlock(&common->mutex);
- ovs_mutex_unlock(&dpdk_mutex);
+ ovs_mutex_unlock(dev_mutex);
smap_add_format(args, "port_no", DPDK_PORT_ID_FMT, common->port_id);
smap_add_format(args, "numa_id", "%d",
@@ -4477,6 +4522,29 @@ netdev_dpdk_get_status(const struct netdev *netdev,
struct smap *args)
ETH_ADDR_ARGS(common->hwaddr));
}
+ return 0;
+}
+
+static int
+netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)
+{
+ struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+ size_t rx_steer_flows_num;
+ uint64_t rx_steer_flags;
+ int n_rxq;
+ int ret;
+
+ ret = netdev_dpdk_get_status__(netdev, &dpdk_mutex, args);
+ if (ret) {
+ return ret;
+ }
+
+ ovs_mutex_lock(&dev->common.mutex);
+ rx_steer_flags = dev->rx_steer_flags;
+ rx_steer_flows_num = dev->rx_steer_flows_num;
+ n_rxq = netdev->n_rxq;
+ ovs_mutex_unlock(&dev->common.mutex);
+
if (rx_steer_flags && !rx_steer_flows_num) {
smap_add(args, "rx-steering", "unsupported");
} else if (rx_steer_flags == DPDK_RX_STEER_LACP) {
@@ -4499,15 +4567,16 @@ netdev_dpdk_get_status(const struct netdev *netdev,
struct smap *args)
}
static void
-netdev_dpdk_set_admin_state__(struct netdev_dpdk *dev, bool admin_state)
- OVS_REQUIRES(dev->common.mutex)
+netdev_dpdk_set_admin_state__(struct netdev_dpdk_common *common,
+ bool admin_state)
+ OVS_REQUIRES(common->mutex)
{
enum netdev_flags old_flags;
if (admin_state) {
- netdev_dpdk_update_flags__(dev, 0, NETDEV_UP, &old_flags);
+ netdev_dpdk_update_flags__(common, 0, NETDEV_UP, &old_flags);
} else {
- netdev_dpdk_update_flags__(dev, NETDEV_UP, 0, &old_flags);
+ netdev_dpdk_update_flags__(common, NETDEV_UP, 0, &old_flags);
}
}
@@ -4530,11 +4599,12 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn,
int argc,
struct netdev *netdev = netdev_from_name(argv[1]);
if (netdev && is_dpdk_class(netdev->netdev_class)) {
- struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+ struct netdev_dpdk_common *common =
+ netdev_dpdk_common_cast(netdev);
My preference would be to split this up as we need two lines anyway.
So something like;
struct netdev_dpdk_common *common;
common = netdev_dpdk_common_cast(netdev);
ovs_mutex_lock(&common->mutex);
netdev_dpdk_set_admin_state__(common, up);
ovs_mutex_unlock(&common->mutex);
Ack
- ovs_mutex_lock(&dev->common.mutex);
- netdev_dpdk_set_admin_state__(dev, up);
- ovs_mutex_unlock(&dev->common.mutex);
+ ovs_mutex_lock(&common->mutex);
+ netdev_dpdk_set_admin_state__(common, up);
+ ovs_mutex_unlock(&common->mutex);
netdev_close(netdev);
} else {
@@ -4548,7 +4618,7 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn,
int argc,
ovs_mutex_lock(&dpdk_mutex);
LIST_FOR_EACH (dev, common.list_node, &dpdk_list) {
ovs_mutex_lock(&dev->common.mutex);
- netdev_dpdk_set_admin_state__(dev, up);
+ netdev_dpdk_set_admin_state__(&dev->common, up);
ovs_mutex_unlock(&dev->common.mutex);
}
ovs_mutex_unlock(&dpdk_mutex);
@@ -5144,9 +5214,14 @@ netdev_dpdk_class_init(void)
/* This function can be called for different classes. The initialization
* needs to be done only once */
if (ovsthread_once_start(&once)) {
+ static struct netdev_dpdk_watchdog_params watchdog_params = {
+ .mutex = &dpdk_mutex,
+ .list = &dpdk_list,
+ };
int ret;
- ovs_thread_create("dpdk_watchdog", dpdk_watchdog, NULL);
+ ovs_thread_create("dpdk_watchdog", netdev_dpdk_watchdog,
+ &watchdog_params);
unixctl_command_register("netdev-dpdk/set-admin-state",
"[netdev] up|down", 1, 2,
netdev_dpdk_set_admin_state, NULL);
@@ -6158,7 +6233,8 @@ retry:
dev->common.tx_q = NULL;
if (!eth_addr_equals(dev->common.hwaddr, dev->common.requested_hwaddr)) {
- err = netdev_dpdk_set_etheraddr__(dev, dev->common.requested_hwaddr);
+ err = netdev_dpdk_set_etheraddr__(&dev->common,
+ dev->common.requested_hwaddr);
if (err) {
goto out;
}
@@ -6676,7 +6752,7 @@ parse_user_mempools_list(const struct smap
*ovs_other_config)
user_mempools = xrealloc(user_mempools, (n_user_mempools + 1) *
sizeof(struct user_mempool_config));
- adj_mtu = FRAME_LEN_TO_MTU(dpdk_buf_size(mtu));
+ adj_mtu = FRAME_LEN_TO_MTU(netdev_dpdk_buf_size(mtu));
user_mempools[n_user_mempools].adj_mtu = adj_mtu;
user_mempools[n_user_mempools].socket_id = socket_id;
n_user_mempools++;
--
2.34.1
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev