[ovs-dev] [PATCH v4 3/3] netdev-dpdk: vHost client mode and reconnect

Loftus, Ciara ciara.loftus at intel.com
Mon Aug 15 15:13:01 UTC 2016


> 
> Thanks for the patch, I tried it and it makes possible to restart vswitchd and
> qemu.
> I believe that now vhost_server_id and vhost_client_id are not constant for
> the lifetime of the struct and must be protected with dev->mutex.
> The following incremental on top of your patch does that and remove extra
> parentheses from sizeof operator:
> 
> -    /* Identifiers used to distinguish vhost devices from each other. They do
> -     * not change during the lifetime of a struct netdev_dpdk. They can be
> read
> -     * without holding any mutex. */
> -    const char vhost_server_id[PATH_MAX];
> -    const char vhost_client_id[PATH_MAX];
> +    /* Identifiers used to distinguish vhost devices from each other. */
> +    char vhost_server_id[PATH_MAX];
> +    char vhost_client_id[PATH_MAX];
> 
>      /* In dpdk_list. */
>      struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);
> @@ -837,6 +835,7 @@ dpdk_dev_parse_name(const char dev_name[],
> const char prefix[],
>   * use */
>  static const char *
>  get_vhost_id(struct netdev_dpdk *dev)
> +    OVS_REQUIRES(dev->mutex)
>  {
>      return dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT ?
>             dev->vhost_client_id : dev->vhost_server_id;
> @@ -867,20 +866,20 @@ netdev_dpdk_vhost_construct(struct netdev
> *netdev)
>      /* Take the name of the vhost-user port and append it to the location
> where
>       * the socket is to be created, then register the socket.
>       */
> -    snprintf(CONST_CAST(char *, dev->vhost_server_id),
> -             sizeof(dev->vhost_server_id), "%s/%s", vhost_sock_dir, name);
> +    snprintf(dev->vhost_server_id, sizeof dev->vhost_server_id, "%s/%s",
> +             vhost_sock_dir, name);
> 
> -    err = rte_vhost_driver_register(get_vhost_id(dev),
> +    err = rte_vhost_driver_register(dev->vhost_server_id,
>                                      dev->vhost_driver_flags);
>      if (err) {
>          VLOG_ERR("vhost-user socket device setup failure for socket %s\n",
> -                 get_vhost_id(dev));
> +                 dev->vhost_server_id);
>      } else {
>          if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
>              /* OVS server mode - add this socket to list for deletion */
> -            fatal_signal_add_file_to_unlink(get_vhost_id(dev));
> +            fatal_signal_add_file_to_unlink(dev->vhost_server_id);
>              VLOG_INFO("Socket %s created for vhost-user port %s\n",
> -                      get_vhost_id(dev), name);
> +                      dev->vhost_server_id, name);
>          }
>          err = netdev_dpdk_init(netdev, -1, DPDK_DEV_VHOST);
>      }
> @@ -935,17 +934,19 @@ netdev_dpdk_destruct(struct netdev *netdev)
>   * try to acquire 'dpdk_mutex' and possibly 'dev->mutex'.  To avoid a
>   * deadlock, none of the mutexes must be held while calling this function. */
>  static int
> -dpdk_vhost_driver_unregister(struct netdev_dpdk *dev)
> +dpdk_vhost_driver_unregister(struct netdev_dpdk *dev OVS_UNUSED,
> +                             const char *vhost_id)
>      OVS_EXCLUDED(dpdk_mutex)
>      OVS_EXCLUDED(dev->mutex)
>  {
> -    return rte_vhost_driver_unregister(get_vhost_id(dev));
> +    return rte_vhost_driver_unregister(vhost_id);
>  }
> 
>  static void
>  netdev_dpdk_vhost_destruct(struct netdev *netdev)
>  {
>      struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> +    char *vhost_id;
> 
>      ovs_mutex_lock(&dpdk_mutex);
>      ovs_mutex_lock(&dev->mutex);
> @@ -967,15 +968,18 @@ netdev_dpdk_vhost_destruct(struct netdev
> *netdev)
>      ovs_list_remove(&dev->list_node);
>      dpdk_mp_put(dev->dpdk_mp);
> 
> +    vhost_id = xstrdup(get_vhost_id(dev));
> +
>      ovs_mutex_unlock(&dev->mutex);
>      ovs_mutex_unlock(&dpdk_mutex);
> 
> -    if (dpdk_vhost_driver_unregister(dev)) {
> -        VLOG_ERR("Unable to remove vhost-user socket %s",
> get_vhost_id(dev));
> +    if (dpdk_vhost_driver_unregister(dev, vhost_id)) {
> +        VLOG_ERR("Unable to remove vhost-user socket %s", vhost_id);
>      } else if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
>          /* OVS server mode - remove this socket from list for deletion */
> -        fatal_signal_remove_file_to_unlink(get_vhost_id(dev));
> +        fatal_signal_remove_file_to_unlink(vhost_id);
>      }
> +    free(vhost_id);
>  }
> 
>  static void
> @@ -2297,10 +2301,10 @@ new_device(int vid)
>      ovs_mutex_lock(&dpdk_mutex);
>      /* Add device to the vhost port with the same name as that passed down.
> */
>      LIST_FOR_EACH(dev, list_node, &dpdk_list) {
> +        ovs_mutex_lock(&dev->mutex);
>          if (strncmp(ifname, get_vhost_id(dev), IF_NAME_SZ) == 0) {
>              uint32_t qp_num = rte_vhost_get_queue_num(vid);
> 
> -            ovs_mutex_lock(&dev->mutex);
>              /* Get NUMA information */
>              newnode = rte_vhost_get_numa_node(vid);
>              if (newnode == -1) {
> @@ -2330,6 +2334,7 @@ new_device(int vid)
>              ovs_mutex_unlock(&dev->mutex);
>              break;
>          }
> +        ovs_mutex_unlock(&dev->mutex);
>      }
>      ovs_mutex_unlock(&dpdk_mutex);
> 
> @@ -2423,8 +2428,8 @@ vring_state_changed(int vid, uint16_t queue_id, int
> enable)
> 
>      ovs_mutex_lock(&dpdk_mutex);
>      LIST_FOR_EACH (dev, list_node, &dpdk_list) {
> +        ovs_mutex_lock(&dev->mutex);
>          if (strncmp(ifname, get_vhost_id(dev), IF_NAME_SZ) == 0) {
> -            ovs_mutex_lock(&dev->mutex);
>              if (enable) {
>                  dev->tx_q[qid].map = qid;
>              } else {
> @@ -2435,6 +2440,7 @@ vring_state_changed(int vid, uint16_t queue_id, int
> enable)
>              ovs_mutex_unlock(&dev->mutex);
>              break;
>          }
> +        ovs_mutex_unlock(&dev->mutex);
>      }
>      ovs_mutex_unlock(&dpdk_mutex);
> 
> @@ -2950,12 +2956,14 @@ netdev_dpdk_vhost_reconfigure(struct netdev
> *netdev)
>       */
>      if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)
>              && !(netdev_dpdk_get_vid(dev) >= 0)
> -            && dev->requested_vhost_client_path
>              && strlen(dev->requested_vhost_client_path)) {
>          /* Unregister server-mode device */
> -        ovs_mutex_unlock(&dpdk_mutex);
> +        char *vhost_id = xstrdup(get_vhost_id(dev));
> +
>          ovs_mutex_unlock(&dev->mutex);
> -        err = dpdk_vhost_driver_unregister(dev);
> +        ovs_mutex_unlock(&dpdk_mutex);
> +        err = dpdk_vhost_driver_unregister(dev, vhost_id);
> +        free(vhost_id);
>          ovs_mutex_lock(&dpdk_mutex);
>          ovs_mutex_lock(&dev->mutex);
>          if (err) {
> @@ -2964,8 +2972,7 @@ netdev_dpdk_vhost_reconfigure(struct netdev
> *netdev)
>          } else {
>              fatal_signal_remove_file_to_unlink(get_vhost_id(dev));
>              /* Create the new vhost_id using path specified */
> -            snprintf(CONST_CAST(char *, dev->vhost_client_id),
> -                     sizeof(dev->vhost_client_id),
> +            snprintf(dev->vhost_client_id, sizeof dev->vhost_client_id,
>                       "%s/%s", dev->requested_vhost_client_path, dev->up.name);
>              /* Register client-mode device */
>              err = rte_vhost_driver_register(dev->vhost_client_id,
> There was a misunderstanding about the interface.  I intended vhost-server-
> path to include the full path to the socket, not just the directory.  This is more
> inline with what qemu does.
> I believe there's also no need for the intermediate
> 'requested_vhost_client_path' if we use the full path.
> 
> If you agree with the comments, would you mind sending another version (I
> hope to be able to apply that)?
> I still believe we could adjust the user interface after branching, before
> release.

Thanks Daniele. I applied your incremental and added your Signed-off-by to the v5.
Thanks for clarifying what you want the vhost-server-path to reflect. This is also changed in the v5.

Thanks,
Ciara

> 
> Thanks,
> Daniele
> 
> 
> 2016-08-11 9:28 GMT-07:00 Ciara Loftus <ciara.loftus at intel.com>:
> Until now, vHost ports in OVS have only been able to operate in 'server'
> mode whereby OVS creates and manages the vHost socket and essentially
> acts as the vHost 'server'. With this commit a new mode, 'client' mode,
> is available. In this mode, OVS acts as the vHost 'client' and connects
> to the socket created and managed by QEMU which now acts as the vHost
> 'server'. This mode allows for reconnect capability, which allows a
> vHost port to resume normal connectivity in event of switch reset.
> 
> By default dpdkvhostuser ports still operate in 'server' mode. That is
> unless a valid 'vhost-server-path' is specified for that device like so:
> 
> ovs-vsctl set Interface <vhostportname>
> options:vhost-server-path=<path_to_socket_dir>
> 
> Once specified, the port stays in 'client' mode for the remainder of its
> lifetime.
> 
> QEMU v2.7.0+ is required when using OVS in vHost client mode and QEMU in
> vHost server mode.
> 
> Signed-off-by: Ciara Loftus <ciara.loftus at intel.com>
> ---
> v4:
> - Rebase
> - Remove vhost-driver-mode and allow per-interface flag.
> - Use 'vhost-server-path' option to enable client mode for the given
>   port and also to set the path for the client port.
> 
> v3:
> - Only restrict vhost_sock_dir if server mode
> 
> v2
> - Updated comments in vhost construct & destruct
> - Add check for server-mode before printing error when destruct is called
>   on a running VM
> - Fixed coding style/standards issues
> - Use strcmp instead of strncmp when processing 'vhost-driver-mode'
> ---
>  INSTALL.DPDK-ADVANCED.md |  34 +++++++++++++
>  NEWS                     |   1 +
>  lib/netdev-dpdk.c        | 130
> +++++++++++++++++++++++++++++++++++++++--------
>  vswitchd/vswitch.xml     |  10 ++++
>  4 files changed, 154 insertions(+), 21 deletions(-)
> 
> diff --git a/INSTALL.DPDK-ADVANCED.md b/INSTALL.DPDK-ADVANCED.md
> index 8d6cabc..6f03533 100755
> --- a/INSTALL.DPDK-ADVANCED.md
> +++ b/INSTALL.DPDK-ADVANCED.md
> @@ -568,6 +568,40 @@ For users wanting to do packet forwarding using
> kernel stack below are the steps
>         where `-L`: Changes the numbers of channels of the specified network
> device
>         and `combined`: Changes the number of multi-purpose channels.
> 
> +    4. OVS vHost client-mode & vHost reconnect (OPTIONAL)
> +
> +       By default, OVS DPDK acts as the vHost socket server for dpdkvhostuser
> +       ports and QEMU acts as the vHost client. This means OVS creates and
> +       manages the vHost socket and QEMU is the client which connects to the
> +       vHost server (OVS).  In QEMU v2.7 the option is available for QEMU to
> +       act as the vHost server meaning the roles can be reversed and OVS can
> +       become the vHost client. To enable client mode for a given
> +       dpdkvhostuserport, one must specify a valid 'vhost-server-path' like so:
> +
> +       ```
> +       ovs-vsctl set Interface <vhostportname> options:vhost-server-
> path=<dir>
> +       ```
> +
> +       Setting this value automatically switches the port to client mode (from
> +       OVS' perspective).
> +       'vhost-server-path' reflects the location the vHost socket
> 
> of the vHost socket
> 
> +       <vhostportname> resides in, or will reside in once QEMU is launched.
> +       The port remains in 'client' mode for the remainder of it's lifetime ie.
> +       it cannot be reverted back to server mode.
> +
> +       One must append ',server' to the 'chardev' arguments on the QEMU
> command
> +       line, to instruct QEMU to use vHost server mode for a given interface,
> +       like so:
> +
> +       ````
> +       -chardev socket,id=char0,path=<dir>/<vhostportname>,server
> +       ````
> +
> +       One benefit of using this mode is the ability for vHost ports to
> +       'reconnect' in event of the switch crashing or being brought down. Once
> +       it is brought back up, the vHost ports will reconnect automatically and
> +       normal service will resume.
> +
>    - VM Configuration with libvirt
> 
>      * change the user/group, access control policty and restart libvirtd.
> diff --git a/NEWS b/NEWS
> index 9f09e1c..99412ba 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -70,6 +70,7 @@ Post-v2.5.0
>         fragmentation or NAT support yet)
>       * Support for DPDK 16.07
>       * Remove dpdkvhostcuse port type.
> +     * OVS client mode for vHost and vHost reconnect (Requires QEMU 2.7)
>     - Increase number of registers to 16.
>     - ovs-benchmark: This utility has been removed due to lack of use and
>       bitrot.
> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
> index 4e4c74e..e480ce8 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -352,10 +352,11 @@ struct netdev_dpdk {
>      /* True if vHost device is 'up' and has been reconfigured at least once */
>      bool vhost_reconfigured;
> 
> -    /* Identifier used to distinguish vhost devices from each other.  It does
> -     * not change during the lifetime of a struct netdev_dpdk.  It can be read
> +    /* Identifiers used to distinguish vhost devices from each other. They do
> +     * not change during the lifetime of a struct netdev_dpdk. They can be
> read
>       * without holding any mutex. */
> -    const char vhost_id[PATH_MAX];
> +    const char vhost_server_id[PATH_MAX];
> +    const char vhost_client_id[PATH_MAX];
> 
>      /* In dpdk_list. */
>      struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);
> @@ -373,6 +374,12 @@ struct netdev_dpdk {
>      /* Socket ID detected when vHost device is brought up */
>      int requested_socket_id;
> 
> +    /* Directory where vHost client socket resides */
> +    char requested_vhost_client_path[PATH_MAX];
> +
> +    /* Denotes whether vHost port is client/server mode */
> +    uint64_t vhost_driver_flags;
> +
>      /* Ingress Policer */
>      OVSRCU_TYPE(struct ingress_policer *) ingress_policer;
>      uint32_t policer_rate;
> @@ -760,6 +767,8 @@ netdev_dpdk_init(struct netdev *netdev, unsigned
> int port_no,
>      dev->max_packet_len = MTU_TO_FRAME_LEN(dev->mtu);
>      ovsrcu_index_init(&dev->vid, -1);
>      dev->vhost_reconfigured = false;
> +    /* initialise vHost port in server mode */
> +    dev->vhost_driver_flags &= ~RTE_VHOST_USER_CLIENT;
> 
>      buf_size = dpdk_buf_size(dev->mtu);
>      dev->dpdk_mp = dpdk_mp_get(dev->socket_id,
> FRAME_LEN_TO_MTU(buf_size));
> @@ -824,13 +833,21 @@ dpdk_dev_parse_name(const char dev_name[],
> const char prefix[],
>      }
>  }
> 
> +/* Returns a pointer to the relevant vHost socket ID depending on the
> mode in
> + * use */
> +static const char *
> +get_vhost_id(struct netdev_dpdk *dev)
> +{
> +    return dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT ?
> +           dev->vhost_client_id : dev->vhost_server_id;
> +}
> +
>  static int
>  netdev_dpdk_vhost_construct(struct netdev *netdev)
>  {
>      struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
>      const char *name = netdev->name;
>      int err;
> -    uint64_t flags = 0;
> 
>      /* 'name' is appended to 'vhost_sock_dir' and used to create a socket in
>       * the file system. '/' or '\' would traverse directories, so they're not
> @@ -850,17 +867,21 @@ netdev_dpdk_vhost_construct(struct netdev
> *netdev)
>      /* Take the name of the vhost-user port and append it to the location
> where
>       * the socket is to be created, then register the socket.
>       */
> -    snprintf(CONST_CAST(char *, dev->vhost_id), sizeof dev->vhost_id,
> "%s/%s",
> -             vhost_sock_dir, name);
> +    snprintf(CONST_CAST(char *, dev->vhost_server_id),
> +             sizeof(dev->vhost_server_id), "%s/%s", vhost_sock_dir, name);
> 
> -    err = rte_vhost_driver_register(dev->vhost_id, flags);
> +    err = rte_vhost_driver_register(get_vhost_id(dev),
> +                                    dev->vhost_driver_flags);
>      if (err) {
>          VLOG_ERR("vhost-user socket device setup failure for socket %s\n",
> -                 dev->vhost_id);
> +                 get_vhost_id(dev));
>      } else {
> -        fatal_signal_add_file_to_unlink(dev->vhost_id);
> -        VLOG_INFO("Socket %s created for vhost-user port %s\n",
> -                  dev->vhost_id, name);
> +        if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
> +            /* OVS server mode - add this socket to list for deletion */
> +            fatal_signal_add_file_to_unlink(get_vhost_id(dev));
> +            VLOG_INFO("Socket %s created for vhost-user port %s\n",
> +                      get_vhost_id(dev), name);
> +        }
>          err = netdev_dpdk_init(netdev, -1, DPDK_DEV_VHOST);
>      }
> 
> @@ -918,7 +939,7 @@ dpdk_vhost_driver_unregister(struct netdev_dpdk
> *dev)
>      OVS_EXCLUDED(dpdk_mutex)
>      OVS_EXCLUDED(dev->mutex)
>  {
> -    return rte_vhost_driver_unregister(dev->vhost_id);
> +    return rte_vhost_driver_unregister(get_vhost_id(dev));
>  }
> 
>  static void
> @@ -930,12 +951,13 @@ netdev_dpdk_vhost_destruct(struct netdev
> *netdev)
>      ovs_mutex_lock(&dev->mutex);
> 
>      /* Guest becomes an orphan if still attached. */
> -    if (netdev_dpdk_get_vid(dev) >= 0) {
> +    if (netdev_dpdk_get_vid(dev) >= 0
> +        && !(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
>          VLOG_ERR("Removing port '%s' while vhost device still attached.",
>                   netdev->name);
>          VLOG_ERR("To restore connectivity after re-adding of port, VM on
> socket"
>                   " '%s' must be restarted.",
> -                 dev->vhost_id);
> +                 get_vhost_id(dev));
>      }
> 
>      free(ovsrcu_get_protected(struct ingress_policer *,
> @@ -949,9 +971,10 @@ netdev_dpdk_vhost_destruct(struct netdev
> *netdev)
>      ovs_mutex_unlock(&dpdk_mutex);
> 
>      if (dpdk_vhost_driver_unregister(dev)) {
> -        VLOG_ERR("Unable to remove vhost-user socket %s", dev->vhost_id);
> -    } else {
> -        fatal_signal_remove_file_to_unlink(dev->vhost_id);
> +        VLOG_ERR("Unable to remove vhost-user socket %s",
> get_vhost_id(dev));
> +    } else if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
> +        /* OVS server mode - remove this socket from list for deletion */
> +        fatal_signal_remove_file_to_unlink(get_vhost_id(dev));
>      }
>  }
> 
> @@ -1013,6 +1036,30 @@ netdev_dpdk_set_config(struct netdev *netdev,
> const struct smap *args)
>  }
> 
>  static int
> +netdev_dpdk_vhost_set_config(struct netdev *netdev, const struct smap
> *args)
> +{
> +    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> +    const char *path;
> +    struct stat s;
> +
> +    if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) {
> +        path = smap_get(args, "vhost-server-path");
> +        /* Request reconfigure if 'path':
> +         *  1. is non-NULL.
> +         *  2. represents a valid existing path.
> 
> I think we should drop this.  We want the port to be added even if the path is
> not there.  When qemu is started in will create the socket. (This is assuming
> that we change 'vhost-server-path' to include the full path to the socket)
> 
> +         *  3. hasn't already been requested ie. has changed since last call.
> +         */
> +        if (path && !stat(path, &s)
> +                && strcmp(path, dev->requested_vhost_client_path)) {
> +            strcpy(dev->requested_vhost_client_path, path);
> 
> I think this should be limited with
> 
> ovs_strlcpy(dev->requested_vhost_client_path, path, sizeof dev-
> >requested_vhost_client_path);
> 
> +            netdev_request_reconfigure(netdev);
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static int
>  netdev_dpdk_get_numa_id(const struct netdev *netdev)
>  {
>      struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> @@ -2226,7 +2273,7 @@ netdev_dpdk_remap_txqs(struct netdev_dpdk
> *dev)
>          }
>      }
> 
> -    VLOG_DBG("TX queue mapping for %s\n", dev->vhost_id);
> +    VLOG_DBG("TX queue mapping for %s\n", get_vhost_id(dev));
>      for (i = 0; i < total_txqs; i++) {
>          VLOG_DBG("%2d --> %2d", i, dev->tx_q[i].map);
>      }
> @@ -2250,7 +2297,7 @@ new_device(int vid)
>      ovs_mutex_lock(&dpdk_mutex);
>      /* Add device to the vhost port with the same name as that passed down.
> */
>      LIST_FOR_EACH(dev, list_node, &dpdk_list) {
> -        if (strncmp(ifname, dev->vhost_id, IF_NAME_SZ) == 0) {
> +        if (strncmp(ifname, get_vhost_id(dev), IF_NAME_SZ) == 0) {
>              uint32_t qp_num = rte_vhost_get_queue_num(vid);
> 
>              ovs_mutex_lock(&dev->mutex);
> @@ -2376,7 +2423,7 @@ vring_state_changed(int vid, uint16_t queue_id, int
> enable)
> 
>      ovs_mutex_lock(&dpdk_mutex);
>      LIST_FOR_EACH (dev, list_node, &dpdk_list) {
> -        if (strncmp(ifname, dev->vhost_id, IF_NAME_SZ) == 0) {
> +        if (strncmp(ifname, get_vhost_id(dev), IF_NAME_SZ) == 0) {
>              ovs_mutex_lock(&dev->mutex);
>              if (enable) {
>                  dev->tx_q[qid].map = qid;
> @@ -2895,6 +2942,47 @@ netdev_dpdk_vhost_reconfigure(struct netdev
> *netdev)
>          dev->vhost_reconfigured = true;
>      }
> 
> +    /* Configure vHost client mode if requested and if the following criteria
> +     * are met:
> +     *  1. Device is currently in 'server' mode.
> +     *  2. Device is currently not active.
> +     *  3. A valid path has been specified.
> +     */
> +    if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)
> +            && !(netdev_dpdk_get_vid(dev) >= 0)
> +            && dev->requested_vhost_client_path
> +            && strlen(dev->requested_vhost_client_path)) {
> +        /* Unregister server-mode device */
> +        ovs_mutex_unlock(&dpdk_mutex);
> +        ovs_mutex_unlock(&dev->mutex);
> +        err = dpdk_vhost_driver_unregister(dev);
> +        ovs_mutex_lock(&dpdk_mutex);
> +        ovs_mutex_lock(&dev->mutex);
> +        if (err) {
> +            VLOG_ERR("Unable to remove vhost-user socket %s",
> +                     get_vhost_id(dev));
> +        } else {
> +            fatal_signal_remove_file_to_unlink(get_vhost_id(dev));
> +            /* Create the new vhost_id using path specified */
> +            snprintf(CONST_CAST(char *, dev->vhost_client_id),
> +                     sizeof(dev->vhost_client_id),
> +                     "%s/%s", dev->requested_vhost_client_path, dev->up.name);
> +            /* Register client-mode device */
> +            err = rte_vhost_driver_register(dev->vhost_client_id,
> +                                            RTE_VHOST_USER_CLIENT);
> +            if (err) {
> +                VLOG_ERR("vhost-user device setup failure for device %s\n",
> +                        dev->vhost_client_id);
> +            } else {
> +                /* Configuration successful */
> +                dev->vhost_driver_flags |= RTE_VHOST_USER_CLIENT;
> +                VLOG_INFO("vHost User device '%s' changed to 'client' mode, "
> +                          "using client socket '%s'",
> +                           dev->up.name, get_vhost_id(dev));
> +            }
> +        }
> +    }
> +
>      ovs_mutex_unlock(&dev->mutex);
>      ovs_mutex_unlock(&dpdk_mutex);
> 
> @@ -3382,7 +3470,7 @@ static const struct netdev_class OVS_UNUSED
> dpdk_vhost_class =
>          "dpdkvhostuser",
>          netdev_dpdk_vhost_construct,
>          netdev_dpdk_vhost_destruct,
> -        NULL,
> +        netdev_dpdk_vhost_set_config,
>          NULL,
>          netdev_dpdk_vhost_send,
>          netdev_dpdk_vhost_get_carrier,
> diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
> index 63f0d89..02adf8a 100644
> --- a/vswitchd/vswitch.xml
> +++ b/vswitchd/vswitch.xml
> @@ -2366,6 +2366,16 @@
>            </ul>
>          </p>
>        </column>
> +
> +      <column name="options" key="vhost-server-path"
> +              type='{"type": "string"}'>
> +        <p>
> +          When specified, switches the given port permanently to 'client'
> +          mode. The value specifies the directory in which to find the sockets
> +          of vHost User client mode devices created by QEMU.
> +          Only supported by DPDK vHost interfaces.
> +        </p>
> +      </column>
>      </group>
> 
>      <group title="Interface Status">
> --
> 2.4.3
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list