Signed-off-by: wangyan4 <[email protected]>
---
lib/dpif-netdev-private-thread.h | 1 +
lib/dpif-netdev.c | 82 +++++++++++++++++++++++++-------
2 files changed, 66 insertions(+), 17 deletions(-)
diff --git a/lib/dpif-netdev-private-thread.h b/lib/dpif-netdev-private-thread.h
index 8715b3837..fea78c617 100644
--- a/lib/dpif-netdev-private-thread.h
+++ b/lib/dpif-netdev-private-thread.h
@@ -229,6 +229,7 @@ struct dp_netdev_pmd_thread {
/* Next time when PMD should try RCU quiescing. */
long long next_rcu_quiesce;
+ uint32_t pmd_id; /* pmd id of this pmd thread. */
};
#ifdef __cplusplus
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 2a529f272..a38d7cf79 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -463,12 +463,14 @@ struct dp_netdev_rxq {
enum txq_req_mode {
TXQ_REQ_MODE_THREAD,
TXQ_REQ_MODE_HASH,
+ TXQ_REQ_MODE_HASH_PER_THREAD
};
enum txq_mode {
TXQ_MODE_STATIC,
TXQ_MODE_XPS,
TXQ_MODE_XPS_HASH,
+ TXQ_MODE_XPS_HASH_PER_THREAD
};
/* A port in a netdev-based datapath. */
@@ -5410,6 +5412,8 @@ dpif_netdev_port_set_config(struct dpif *dpif, odp_port_t
port_no,
if (nullable_string_is_equal(tx_steering_mode, "hash")) {
txq_mode = TXQ_REQ_MODE_HASH;
+ } else if (nullable_string_is_equal(tx_steering_mode, "hash-per-thread")) {
+ txq_mode = TXQ_REQ_MODE_HASH_PER_THREAD;
} else {
txq_mode = TXQ_REQ_MODE_THREAD;
}
@@ -5541,7 +5545,43 @@ dp_netdev_pmd_flush_output_on_port(struct
dp_netdev_pmd_thread *pmd,
output_cnt = dp_packet_batch_size(&p->output_pkts);
ovs_assert(output_cnt > 0);
- if (p->port->txq_mode == TXQ_MODE_XPS_HASH) {
+ int pmd_cnt = cmap_count(&pmd->dp->poll_threads);
+ if (p->port->txq_mode == TXQ_MODE_XPS_HASH_PER_THREAD) {
+ int n_txq = netdev_n_txq(p->port->netdev);
+ /* for example 6 txq, ovs has 4 pmd
+ * pmd0 alloc txq 0,4 pmdid=0
+ * pmd1 alloc txq 1,5 pmdid=1
+ * pmd2 alloc txq 2 pmdid=2
+ * pmd3 alloc txq 3 pmdid=3*/
+ int ntxq_this_thread = n_txq / pmd_cnt + (pmd->pmd_id <
+ (n_txq % pmd_cnt) ? 1 : 0);
+
+ /* Re-batch per txq based on packet hash. */
+ struct dp_packet *packet;
+ DP_PACKET_BATCH_FOR_EACH (j, packet, &p->output_pkts) {
+ uint32_t hash;
+
+ if (OVS_LIKELY(dp_packet_rss_valid(packet))) {
+ hash = dp_packet_get_rss_hash(packet);
+ } else {
+ struct flow flow;
+
+ flow_extract(packet, &flow);
+ hash = flow_hash_5tuple(&flow, 0);
+ }
+ dp_packet_batch_add(&p->txq_pkts[hash % ntxq_this_thread], packet);
+ }
+
+ /* Flush batches of each Tx queues. */
+ for (i = 0; i < ntxq_this_thread; i++) {
+ if (dp_packet_batch_is_empty(&p->txq_pkts[i])) {
+ continue;
+ }
+ tx_qid = i * pmd_cnt + pmd->pmd_id;
+ netdev_send(p->port->netdev, tx_qid, &p->txq_pkts[i], true);
+ dp_packet_batch_init(&p->txq_pkts[i]);
+ }
+ } else if (p->port->txq_mode == TXQ_MODE_XPS_HASH) {
int n_txq = netdev_n_txq(p->port->netdev);
/* Re-batch per txq based on packet hash. */
@@ -6661,6 +6701,7 @@ reconfigure_pmd_threads(struct dp_netdev *dp)
}
/* Check for required new pmd threads */
+ uint32_t pmd_index = 0;
FOR_EACH_CORE_ON_DUMP(core, pmd_cores) {
pmd = dp_netdev_get_pmd(dp, core->core_id);
if (!pmd) {
@@ -6668,7 +6709,7 @@ reconfigure_pmd_threads(struct dp_netdev *dp)
pmd = xzalloc(sizeof *pmd);
dp_netdev_configure_pmd(pmd, dp, core->core_id, core->numa_id);
-
+ pmd->pmd_id = pmd_index;
ds_put_format(&name, "pmd-c%02d/id:", core->core_id);
pmd->thread = ovs_thread_create(ds_cstr(&name),
pmd_thread_main, pmd);
@@ -6724,6 +6765,24 @@ pmd_remove_stale_ports(struct dp_netdev *dp,
ovs_mutex_unlock(&pmd->port_mutex);
}
+static enum txq_mode get_current_txq_mode(struct dp_netdev_port *port,
+ int wanted_txqs)
+{
+ /* With a single queue, there is no point in using hash mode. */
+ if (port->txq_requested_mode == TXQ_REQ_MODE_HASH &&
+ netdev_n_txq(port->netdev) > 1) {
+ port->txq_mode = TXQ_MODE_XPS_HASH;
+ } else if (port->txq_requested_mode == TXQ_REQ_MODE_HASH_PER_THREAD &&
+ netdev_n_txq(port->netdev) >= wanted_txqs) {
+ return TXQ_MODE_XPS_HASH_PER_THREAD;
+ }
+ else if (netdev_n_txq(port->netdev) < wanted_txqs) {
+ port->txq_mode = TXQ_MODE_XPS;
+ } else {
+ port->txq_mode = TXQ_MODE_STATIC;
+ }
+}
+
/* Must be called each time a port is added/removed or the cmask changes.
* This creates and destroys pmd threads, reconfigures ports, opens their
* rxqs and assigns all rxqs/txqs to pmd threads. */
@@ -6764,11 +6823,7 @@ reconfigure_datapath(struct dp_netdev *dp)
* unnecessary. */
HMAP_FOR_EACH (port, node, &dp->ports) {
if (netdev_is_reconf_required(port->netdev)
- || ((port->txq_mode == TXQ_MODE_XPS)
- != (netdev_n_txq(port->netdev) < wanted_txqs))
- || ((port->txq_mode == TXQ_MODE_XPS_HASH)
- != (port->txq_requested_mode == TXQ_REQ_MODE_HASH
- && netdev_n_txq(port->netdev) > 1))) {
+ || port->txq_mode != get_current_txq_mode(port, wanted_txqs)) {
port->need_reconfigure = true;
}
}
@@ -6802,15 +6857,7 @@ reconfigure_datapath(struct dp_netdev *dp)
seq_change(dp->port_seq);
port_destroy(port);
} else {
- /* With a single queue, there is no point in using hash mode. */
- if (port->txq_requested_mode == TXQ_REQ_MODE_HASH &&
- netdev_n_txq(port->netdev) > 1) {
- port->txq_mode = TXQ_MODE_XPS_HASH;
- } else if (netdev_n_txq(port->netdev) < wanted_txqs) {
- port->txq_mode = TXQ_MODE_XPS;
- } else {
- port->txq_mode = TXQ_MODE_STATIC;
- }
+ port->txq_mode = get_current_txq_mode(port, wanted_txqs);
}
}
@@ -8066,7 +8113,8 @@ dp_netdev_add_port_tx_to_pmd(struct dp_netdev_pmd_thread
*pmd,
tx->flush_time = 0LL;
dp_packet_batch_init(&tx->output_pkts);
- if (tx->port->txq_mode == TXQ_MODE_XPS_HASH) {
+ if (tx->port->txq_mode == TXQ_MODE_XPS_HASH ||
+ tx->port->txq_mode == TXQ_MODE_XPS_HASH_PER_THREAD) {
int i, n_txq = netdev_n_txq(tx->port->netdev);
tx->txq_pkts = xzalloc(n_txq * sizeof *tx->txq_pkts);
--
2.39.2 (Apple Git-143)
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev