On 12/18/24 14:44, Ilya Maximets wrote:
On 12/18/24 14:09, Maxime Coquelin wrote:


On 12/18/24 12:22, Kevin Traynor wrote:
On 17/12/2024 10:24, Maxime Coquelin wrote:
Hi Kevin,

On 12/6/24 21:26, Kevin Traynor wrote:
On 06/12/2024 15:58, Maxime Coquelin wrote:
This patch uses the new rte_vhost_driver_set_max_queue_num
API to set the maximum number of queue pairs supported by
the Vhost-user port.

This is required for VDUSE which needs to specify the
maximum number of queue pairs at creation time. Without it
128 queue pairs metadata would be allocated.

To configure it, a new 'vhost-max-queue-pairs' option is
introduced.

Signed-off-by: Maxime Coquelin <[email protected]>
Acked-by: Eelco Chaudron <[email protected]>
---

Note: depends on DPDK v24.11.

Changes in v4:
==============
- Change to vhost-queue-pairs-max to vhost-max-queue-pairs (Eelco)
- Remove mention to DPDK version in documentation (Eelco)
- Add missing parameter description in vswitch.xml (Eelco)
- Define min and max values for the new option (Maxime)
Changes in v3:
==============
- Introduce a new option to set the number of max queue pairs (Kevin)
- Add documentation for new option

Changes in v2:
==============
- Address checkpatch warnings.
---

Hi Maxime,

Testing with vhost-user backend with DPDK 24.11 worked well - in that it
called the API with the right number and didn't break anything :-)

A few comments on the code/docs below.

fyi - I initially tested on OVS main branch with 23.11 and I saw a loop
between the destroy_connection() callback triggering
netdev_dpdk_vhost_client_reconfigure(), repeat, etc when i started a VM
with 4 queues. So OVS having DPDK 24.11 support will need to be a
dependency I think (even aside from the experimental API issue).


Yes, I confirm 24.11 is also a functional dependency, as v23.11.2 miss
one fix that will be in upcoming v23.11.3:


As the 24.11 update patch is under review, we can just keep your
patchset for the main branch and make sure we apply in the correct order
(all going well - fingers crossed).


commit bc578c07f03ec3943fab88a5d156f28b98e1e652
Author: Maxime Coquelin <[email protected]>
Date:   Thu Oct 3 10:11:10 2024 +0200

       vhost: restrict set max queue pair API to VDUSE

       [ upstream commit e1808999d36bb2e136a649f4651f36030aa468f1 ]

       In order to avoid breaking Vhost-user live-migration, we want the
       rte_vhost_driver_set_max_queue_num API to only be effective with
       VDUSE.

       Furthermore, this API is only really needed for VDUSE where the
       device number of queues is defined by the backend. For Vhost-user,
       this is defined by the frontend (e.g. QEMU), so the advantages of
       restricting more the maximum number of queue pairs is limited to
       a small memory gain (a handful of pointers).

       Fixes: 4aa1f88ac13d ("vhost: add API to set max queue pairs")

       Reported-by: Yu Jiang <[email protected]>
       Signed-off-by: Maxime Coquelin <[email protected]>
       Acked-by: David Marchand <[email protected]>


thanks,
Kevin.

    Documentation/topics/dpdk/vhost-user.rst | 15 ++++++++++++
    lib/netdev-dpdk.c                        | 30 ++++++++++++++++++++++++
    vswitchd/vswitch.xml                     | 10 ++++++++
    3 files changed, 55 insertions(+)

diff --git a/Documentation/topics/dpdk/vhost-user.rst 
b/Documentation/topics/dpdk/vhost-user.rst
index 7bba08ac2..656f7f69f 100644
--- a/Documentation/topics/dpdk/vhost-user.rst
+++ b/Documentation/topics/dpdk/vhost-user.rst
@@ -375,6 +375,21 @@ Tx retries max can be set for vhost-user-client ports::
Configurable vhost tx retries are not supported with vhost-user ports. +vhost-user-client max queue pairs config
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For vhost-user-client interfaces using the VDUSE backend, the maximum umber of

typo number

+queue pairs the Virtio device will support can be set at port creation time. If
+not set, the default value is 1 queue pair. This value is ignored for
+Vhost-user backends.
+
+Maximum number of queue pairs can be set for vhost-user-client-ports::
+
+    $ ovs-vsctl add-port br0 vduse0 \
+        -- set Interface vduse0 type=dpdkvhostuserclient \
+            options:vhost-server-path=/dev/vduse/vduse0 \
+            options:vhost-max-queue-pairs=4
+
    .. _dpdk-testpmd:
DPDK in the Guest
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index dc52a2b56..a8b605113 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -19,6 +19,7 @@
#include <errno.h>
    #include <signal.h>
+#include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
@@ -153,6 +154,11 @@ typedef uint16_t dpdk_port_t;
    /* Legacy default value for vhost tx retries. */
    #define VHOST_ENQ_RETRY_DEF 8
+/* VDUSE-only, ignore for Vhost-user */
+#define VHOST_MAX_QUEUE_PAIRS_MIN 1
+#define VHOST_MAX_QUEUE_PAIRS_DEF VHOST_MAX_QUEUE_PAIRS_MIN
+#define VHOST_MAX_QUEUE_PAIRS_MAX 128
+
    #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
/* List of required flags advertised by the hardware that will be used
@@ -497,6 +503,9 @@ struct netdev_dpdk {
atomic_uint8_t vhost_tx_retries_max; + /* Ignored by DPDK for Vhost-user backends, only for VDUSE */
+        uint32_t vhost_max_queue_pairs;
+

I noticed this added a cacheline - perhaps we could use something
smaller and squash it in ?

/* --- cacheline 1 boundary (64 bytes) --- */
union {
        OVS_CACHE_LINE_MARKER cacheline1;        /*    64     1 */
        struct {
                struct ovs_mutex mutex;          /*    64    48 */
                struct dpdk_mp * dpdk_mp;        /*   112     8 */
                ovsrcu_index vid;                /*   120     4 */
                _Bool      vhost_reconfigured;   /*   124     1 */
                atomic_uint8_t vhost_tx_retries_max; /*   125     1 */

                /* XXX 2 bytes hole, try to pack */

                /* --- cacheline 2 boundary (128 bytes) --- */
                uint32_t   vhost_max_queue_pairs; /*   128     4 */
                uint8_t    virtio_features_state; /*   132     1 */
        };                                       /*    64    72 */
        uint8_t            pad55[128];           /*    64   128 */
};                                               /*    64   128 */
/* --- cacheline 3 boundary (192 bytes) --- */


Good catch, David already mentioned it to me off-list.
DPDK Vhost library only supports up to 128 queue pairs, so I think we
could use uint8_t type and so it would fit into the 1 byte hole.

Do you agree with this suggestion?


Yes, sounds good. It should be fine but you may want to confirm with
pahole as sometimes the comments can get stale.

Looks good with pahole:

          /* --- cacheline 1 boundary (64 bytes) --- */
          union {
                  OVS_CACHE_LINE_MARKER cacheline1;        /*    64     1 */
                  struct {
                          struct ovs_mutex mutex;          /*    64    48 */
                          struct dpdk_mp * dpdk_mp;        /*   112     8 */
                          ovsrcu_index vid;                /*   120     4 */
                          _Bool      vhost_reconfigured;   /*   124     1 */
                          atomic_uint8_t vhost_tx_retries_max; /*   125
    1 */
                          uint8_t    vhost_max_queue_pairs; /*   126     1 */
                          uint8_t    virtio_features_state; /*   127     1 */
                  };                                       /*    64    64 */
                  uint8_t            pad55[64];            /*    64    64 */
          };                                               /*    64    64 */
          /* --- cacheline 2 boundary (128 bytes) --- */


Why does it need to be in the first cache line?  It's not on the hot path, 
right?

Ok, what about moving it here (your reply can wait 2025 ;)):

        union {
                struct {
                        int        requested_mtu;        /*   704     4 */
                        int        requested_n_txq;      /*   708     4 */
                        int        user_n_rxq;           /*   712     4 */
                        int        requested_n_rxq;      /*   716     4 */
                        int        requested_rxq_size;   /*   720     4 */
                        int        requested_txq_size;   /*   724     4 */
                        int        rxq_size;             /*   728     4 */
                        int        txq_size;             /*   732     4 */
                        int        requested_socket_id;  /*   736     4 */
                        uint8_t    vhost_max_queue_pairs; /*   740     1 */

                        /* XXX 3 bytes hole, try to pack */

                        uint64_t   vhost_driver_flags;   /*   744     8 */
                        struct rte_eth_fc_conf fc_conf;  /*   752    20 */

                        /* XXX last struct has 2 bytes of padding */

/me goes back to PTO and Christmass preparations. :)

Enjoy your PTO,
Maxime



thanks,
Kevin.


            /* Flags for virtio features recovery mechanism. */
            uint8_t virtio_features_state;
@@ -1609,6 +1618,8 @@ vhost_common_construct(struct netdev *netdev) atomic_init(&dev->vhost_tx_retries_max, VHOST_ENQ_RETRY_DEF); + dev->vhost_max_queue_pairs = VHOST_MAX_QUEUE_PAIRS_DEF;
+
        return common_construct(netdev, DPDK_ETH_PORT_ID_INVALID,
                                DPDK_DEV_VHOST, socket_id);
    }
@@ -2491,6 +2502,7 @@ netdev_dpdk_vhost_client_set_config(struct netdev *netdev,
        struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
        const char *path;
        int max_tx_retries, cur_max_tx_retries;
+    uint32_t max_queue_pairs;
ovs_mutex_lock(&dev->mutex);
        if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
@@ -2498,6 +2510,15 @@ netdev_dpdk_vhost_client_set_config(struct netdev 
*netdev,
            if (!nullable_string_is_equal(path, dev->vhost_id)) {
                free(dev->vhost_id);
                dev->vhost_id = nullable_xstrdup(path);
+
+            max_queue_pairs = smap_get_int(args, "vhost-max-queue-pairs",
+                                           VHOST_MAX_QUEUE_PAIRS_DEF);
+            if (max_queue_pairs < VHOST_MAX_QUEUE_PAIRS_MIN
+                || max_queue_pairs > VHOST_MAX_QUEUE_PAIRS_MAX) {
+                max_queue_pairs = VHOST_MAX_QUEUE_PAIRS_DEF;
+            }
+            dev->vhost_max_queue_pairs = max_queue_pairs;
+
                netdev_request_reconfigure(netdev);
            }
        }
@@ -2514,6 +2535,7 @@ netdev_dpdk_vhost_client_set_config(struct netdev *netdev,
            VLOG_INFO("Max Tx retries for vhost device '%s' set to %d",
                      netdev_get_name(netdev), max_tx_retries);
        }
+
        ovs_mutex_unlock(&dev->mutex);
return 0;
@@ -6400,6 +6422,14 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev 
*netdev)
                goto unlock;
            }
+ err = rte_vhost_driver_set_max_queue_num(dev->vhost_id,
+                                                 dev->vhost_max_queue_pairs);

The log below is printed:

2024-12-06T18:28:51Z|00100|dpdk|INFO|VHOST_CONFIG: (/tmp/vhost0) Setting
max queue pairs to 1

It's kind of true, but it could be confusing when using vhost-user
backend. Maybe we should add an OVS info log before or after as a
reminder that the max queue pairs setting is only valid for VDUSE backend.

Yes, that's unfortunate that I added a log in
rte_vhost_driver_set_max_queue_num(), but only at DEBUG level:

+       if (!vsocket->is_vduse) {
+               VHOST_CONFIG_LOG(path, DEBUG,
+                               "Keeping %u max queue pairs for
Vhost-user backend",
+                               VHOST_MAX_QUEUE_PAIRS);
+               goto unlock_exit;
+       }

I can indeed a log before calling the API to avoid the confusion:

"Setting max queue pairs, only effective with VDUSE backends"


+        if (err) {
+            VLOG_ERR("rte_vhost_driver_set_max_queue_num failed for "
+                    "vhost-user client port: %s\n", dev->up.name);
+            goto unlock;
+        }
+
            err = rte_vhost_driver_start(dev->vhost_id);
            if (err) {
                VLOG_ERR("rte_vhost_driver_start failed for vhost user "
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 36cb4e495..0b5c5dcd6 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -3520,6 +3520,16 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch 
options:peer=p1 \
            </p>
          </column>
+ <column name="options" key="vhost-max-queue-pairs"
+              type='{"type": "integer", "minInteger" : 1, "maxInteger": 128}'>

I already mention the max value is 128, so uint8_t will be enough for
vhost_max_queue_pairs field.

+        <p>
+          The value specifies the maximum number of queue pairs supported by
+          a vHost device. This is ignored for Vhost-user backends, only VDUSE
+          is supported.
+          Only supported by dpdkvhsotuserclient interfaces.

typo dpdkvhostuserclient

good catch, will fix.


+        </p>

It would be good to state the default here (like tx-retries-max below)

Indeed, will add in nex revision.


+      </column>
+
          <column name="options" key="tx-retries-max"
                  type='{"type": "integer", "minInteger": 0, "maxInteger": 32}'>
            <p>


Thanks for the review,
Maxime



_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev



_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to