[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
On 2016/02/08 18:42, Ferruh Yigit wrote: > On Fri, Feb 05, 2016 at 03:28:37PM +0900, Tetsuya Mukawa wrote: >> On 2016/02/04 20:17, Ferruh Yigit wrote: >>> On Thu, Feb 04, 2016 at 04:26:31PM +0900, Tetsuya Mukawa wrote: >>> >>> Hi Tetsuya, >>> The patch introduces a new PMD. This PMD is implemented as thin wrapper of librte_vhost. It means librte_vhost is also needed to compile the PMD. The vhost messages will be handled only when a port is started. So start a port first, then invoke QEMU. The PMD has 2 parameters. - iface: The parameter is used to specify a path to connect to a virtio-net device. - queues: The parameter is used to specify the number of the queues virtio-net device has. (Default: 1) Here is an example. $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i To connect above testpmd, here is qemu command example. $ qemu-system-x86_64 \ -chardev socket,id=chr0,path=/tmp/sock0 \ -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ -device virtio-net-pci,netdev=net0,mq=on Signed-off-by: Tetsuya Mukawa >>> Please find some more comments, mostly minor nits, >>> >>> please feel free to add my ack for next version of this patch: >>> Acked-by: Ferruh Yigit >>> >>> <...> diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c new file mode 100644 index 000..b2305c2 --- /dev/null +++ b/drivers/net/vhost/rte_eth_vhost.c >>> <...> + +struct pmd_internal { + TAILQ_ENTRY(pmd_internal) next; + char *dev_name; + char *iface_name; + uint8_t port_id; >>> You can also get rid of port_id too, if you keep list of rte_eth_dev. >>> But this is not so important, keep as it is if you want to. >> Thank you so much for checking and good suggestions. >> I will follow your comments without below. >> + + volatile uint16_t once; +}; + >>> <...> + +static int +new_device(struct virtio_net *dev) +{ >>> <...> + + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { + vq = eth_dev->data->rx_queues[i]; + if (vq == NULL) >>> can vq be NULL? It is allocated in rx/tx_queue_setup() and there is already >>> a NULL check there? >> I doubt user may not setup all queues. >> In this case, we need above checking. >> + continue; + vq->device = dev; + vq->internal = internal; + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); + } + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { + vq = eth_dev->data->tx_queues[i]; + if (vq == NULL) + continue; >> Same here. >> + vq->device = dev; + vq->internal = internal; + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); + } + + dev->flags |= VIRTIO_DEV_RUNNING; + dev->priv = eth_dev; + eth_dev->data->dev_link.link_status = 1; + + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { + vq = eth_dev->data->rx_queues[i]; + if (vq == NULL) + continue; >> But we can remove this. > If in above loop, vq can be NULL because user not setup the queue, it will be > NULL in here too, isn't it? > Why we can remove NULL check here? Yes, you are right. Will fix it and submit again. Thanks, Tetsuya + rte_atomic32_set(>allow_queuing, 1); + } + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { + vq = eth_dev->data->tx_queues[i]; + if (vq == NULL) + continue; >> And this. >> >>> <...> + if (dev->data->rx_queues[i] == NULL) + continue; + vq = dev->data->rx_queues[i]; + stats->q_ipackets[i] = vq->rx_pkts; + rx_total += stats->q_ipackets[i]; + + stats->q_ibytes[i] = vq->rx_bytes; + rx_total_bytes += stats->q_ibytes[i]; + } + + for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && + i < dev->data->nb_tx_queues; i++) { + if (dev->data->tx_queues[i] == NULL) >>> more queue NULL check here, I am not sure if these are necessary >> Same here, in the case user doesn't setup all queues, I will leave this. >> >> Anyway, I will fix below code. >> - Manage ether devices list instead of internal structures list. >> - Remove needless NULL checking. >> - Replace "pthread_exit" to "return NULL". >> - Replace rte_panic to RTE_LOG, also add error handling. >> - Remove duplicated lines. >> - Remove needless casting. >> - Follow coding style. >> - Remove needless parenthesis. >> >> And leave below. >> - some NULL checking before accessing
[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
On Fri, Feb 05, 2016 at 03:28:37PM +0900, Tetsuya Mukawa wrote: > On 2016/02/04 20:17, Ferruh Yigit wrote: > > On Thu, Feb 04, 2016 at 04:26:31PM +0900, Tetsuya Mukawa wrote: > > > > Hi Tetsuya, > > > >> The patch introduces a new PMD. This PMD is implemented as thin wrapper > >> of librte_vhost. It means librte_vhost is also needed to compile the PMD. > >> The vhost messages will be handled only when a port is started. So start > >> a port first, then invoke QEMU. > >> > >> The PMD has 2 parameters. > >> - iface: The parameter is used to specify a path to connect to a > >>virtio-net device. > >> - queues: The parameter is used to specify the number of the queues > >>virtio-net device has. > >>(Default: 1) > >> > >> Here is an example. > >> $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i > >> > >> To connect above testpmd, here is qemu command example. > >> > >> $ qemu-system-x86_64 \ > >> > >> -chardev socket,id=chr0,path=/tmp/sock0 \ > >> -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ > >> -device virtio-net-pci,netdev=net0,mq=on > >> > >> Signed-off-by: Tetsuya Mukawa > > Please find some more comments, mostly minor nits, > > > > please feel free to add my ack for next version of this patch: > > Acked-by: Ferruh Yigit > > > > <...> > >> diff --git a/drivers/net/vhost/rte_eth_vhost.c > >> b/drivers/net/vhost/rte_eth_vhost.c > >> new file mode 100644 > >> index 000..b2305c2 > >> --- /dev/null > >> +++ b/drivers/net/vhost/rte_eth_vhost.c > > <...> > >> + > >> +struct pmd_internal { > >> + TAILQ_ENTRY(pmd_internal) next; > >> + char *dev_name; > >> + char *iface_name; > >> + uint8_t port_id; > > You can also get rid of port_id too, if you keep list of rte_eth_dev. > > But this is not so important, keep as it is if you want to. > > Thank you so much for checking and good suggestions. > I will follow your comments without below. > > >> + > >> + volatile uint16_t once; > >> +}; > >> + > > <...> > >> + > >> +static int > >> +new_device(struct virtio_net *dev) > >> +{ > > <...> > >> + > >> + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { > >> + vq = eth_dev->data->rx_queues[i]; > >> + if (vq == NULL) > > can vq be NULL? It is allocated in rx/tx_queue_setup() and there is already > > a NULL check there? > > I doubt user may not setup all queues. > In this case, we need above checking. > > > > >> + continue; > >> + vq->device = dev; > >> + vq->internal = internal; > >> + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); > >> + } > >> + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { > >> + vq = eth_dev->data->tx_queues[i]; > >> + if (vq == NULL) > >> + continue; > > Same here. > > >> + vq->device = dev; > >> + vq->internal = internal; > >> + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); > >> + } > >> + > >> + dev->flags |= VIRTIO_DEV_RUNNING; > >> + dev->priv = eth_dev; > >> + eth_dev->data->dev_link.link_status = 1; > >> + > >> + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { > >> + vq = eth_dev->data->rx_queues[i]; > >> + if (vq == NULL) > >> + continue; > > But we can remove this. If in above loop, vq can be NULL because user not setup the queue, it will be NULL in here too, isn't it? Why we can remove NULL check here? > > >> + rte_atomic32_set(>allow_queuing, 1); > >> + } > >> + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { > >> + vq = eth_dev->data->tx_queues[i]; > >> + if (vq == NULL) > >> + continue; > > And this. > > > <...> > >> + if (dev->data->rx_queues[i] == NULL) > >> + continue; > >> + vq = dev->data->rx_queues[i]; > >> + stats->q_ipackets[i] = vq->rx_pkts; > >> + rx_total += stats->q_ipackets[i]; > >> + > >> + stats->q_ibytes[i] = vq->rx_bytes; > >> + rx_total_bytes += stats->q_ibytes[i]; > >> + } > >> + > >> + for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && > >> + i < dev->data->nb_tx_queues; i++) { > >> + if (dev->data->tx_queues[i] == NULL) > > more queue NULL check here, I am not sure if these are necessary > > Same here, in the case user doesn't setup all queues, I will leave this. > > Anyway, I will fix below code. > - Manage ether devices list instead of internal structures list. > - Remove needless NULL checking. > - Replace "pthread_exit" to "return NULL". > - Replace rte_panic to RTE_LOG, also add error handling. > - Remove duplicated lines. > - Remove needless casting. > - Follow coding style. > - Remove needless parenthesis. > > And leave below. > - some NULL checking before accessing a queue. > > Tetsuya
[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
On 2016/02/05 15:35, Yuanhan Liu wrote: > On Fri, Feb 05, 2016 at 03:28:37PM +0900, Tetsuya Mukawa wrote: >> On 2016/02/04 20:17, Ferruh Yigit wrote: >>> On Thu, Feb 04, 2016 at 04:26:31PM +0900, Tetsuya Mukawa wrote: >>> >>> Hi Tetsuya, >>> The patch introduces a new PMD. This PMD is implemented as thin wrapper of librte_vhost. It means librte_vhost is also needed to compile the PMD. The vhost messages will be handled only when a port is started. So start a port first, then invoke QEMU. The PMD has 2 parameters. - iface: The parameter is used to specify a path to connect to a virtio-net device. - queues: The parameter is used to specify the number of the queues virtio-net device has. (Default: 1) Here is an example. $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i To connect above testpmd, here is qemu command example. $ qemu-system-x86_64 \ -chardev socket,id=chr0,path=/tmp/sock0 \ -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ -device virtio-net-pci,netdev=net0,mq=on Signed-off-by: Tetsuya Mukawa >>> Please find some more comments, mostly minor nits, >>> >>> please feel free to add my ack for next version of this patch: >>> Acked-by: Ferruh Yigit >>> >>> <...> diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c new file mode 100644 index 000..b2305c2 --- /dev/null +++ b/drivers/net/vhost/rte_eth_vhost.c >>> <...> + +struct pmd_internal { + TAILQ_ENTRY(pmd_internal) next; + char *dev_name; + char *iface_name; + uint8_t port_id; >>> You can also get rid of port_id too, if you keep list of rte_eth_dev. >>> But this is not so important, keep as it is if you want to. >> Thank you so much for checking and good suggestions. >> I will follow your comments without below. > You might need update the MAINTAINERS file as well. > > --yliu Sure thanks!
[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
On 2016/02/04 20:17, Ferruh Yigit wrote: > On Thu, Feb 04, 2016 at 04:26:31PM +0900, Tetsuya Mukawa wrote: > > Hi Tetsuya, > >> The patch introduces a new PMD. This PMD is implemented as thin wrapper >> of librte_vhost. It means librte_vhost is also needed to compile the PMD. >> The vhost messages will be handled only when a port is started. So start >> a port first, then invoke QEMU. >> >> The PMD has 2 parameters. >> - iface: The parameter is used to specify a path to connect to a >>virtio-net device. >> - queues: The parameter is used to specify the number of the queues >>virtio-net device has. >>(Default: 1) >> >> Here is an example. >> $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i >> >> To connect above testpmd, here is qemu command example. >> >> $ qemu-system-x86_64 \ >> >> -chardev socket,id=chr0,path=/tmp/sock0 \ >> -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ >> -device virtio-net-pci,netdev=net0,mq=on >> >> Signed-off-by: Tetsuya Mukawa > Please find some more comments, mostly minor nits, > > please feel free to add my ack for next version of this patch: > Acked-by: Ferruh Yigit > > <...> >> diff --git a/drivers/net/vhost/rte_eth_vhost.c >> b/drivers/net/vhost/rte_eth_vhost.c >> new file mode 100644 >> index 000..b2305c2 >> --- /dev/null >> +++ b/drivers/net/vhost/rte_eth_vhost.c > <...> >> + >> +struct pmd_internal { >> +TAILQ_ENTRY(pmd_internal) next; >> +char *dev_name; >> +char *iface_name; >> +uint8_t port_id; > You can also get rid of port_id too, if you keep list of rte_eth_dev. > But this is not so important, keep as it is if you want to. Thank you so much for checking and good suggestions. I will follow your comments without below. >> + >> +volatile uint16_t once; >> +}; >> + > <...> >> + >> +static int >> +new_device(struct virtio_net *dev) >> +{ > <...> >> + >> +for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { >> +vq = eth_dev->data->rx_queues[i]; >> +if (vq == NULL) > can vq be NULL? It is allocated in rx/tx_queue_setup() and there is already a > NULL check there? I doubt user may not setup all queues. In this case, we need above checking. > >> +continue; >> +vq->device = dev; >> +vq->internal = internal; >> +rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); >> +} >> +for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { >> +vq = eth_dev->data->tx_queues[i]; >> +if (vq == NULL) >> +continue; Same here. >> +vq->device = dev; >> +vq->internal = internal; >> +rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); >> +} >> + >> +dev->flags |= VIRTIO_DEV_RUNNING; >> +dev->priv = eth_dev; >> +eth_dev->data->dev_link.link_status = 1; >> + >> +for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { >> +vq = eth_dev->data->rx_queues[i]; >> +if (vq == NULL) >> +continue; But we can remove this. >> +rte_atomic32_set(>allow_queuing, 1); >> +} >> +for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { >> +vq = eth_dev->data->tx_queues[i]; >> +if (vq == NULL) >> +continue; And this. > <...> >> +if (dev->data->rx_queues[i] == NULL) >> +continue; >> +vq = dev->data->rx_queues[i]; >> +stats->q_ipackets[i] = vq->rx_pkts; >> +rx_total += stats->q_ipackets[i]; >> + >> +stats->q_ibytes[i] = vq->rx_bytes; >> +rx_total_bytes += stats->q_ibytes[i]; >> +} >> + >> +for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS && >> + i < dev->data->nb_tx_queues; i++) { >> +if (dev->data->tx_queues[i] == NULL) > more queue NULL check here, I am not sure if these are necessary Same here, in the case user doesn't setup all queues, I will leave this. Anyway, I will fix below code. - Manage ether devices list instead of internal structures list. - Remove needless NULL checking. - Replace "pthread_exit" to "return NULL". - Replace rte_panic to RTE_LOG, also add error handling. - Remove duplicated lines. - Remove needless casting. - Follow coding style. - Remove needless parenthesis. And leave below. - some NULL checking before accessing a queue. Tetsuya
[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
The patch introduces a new PMD. This PMD is implemented as thin wrapper of librte_vhost. It means librte_vhost is also needed to compile the PMD. The vhost messages will be handled only when a port is started. So start a port first, then invoke QEMU. The PMD has 2 parameters. - iface: The parameter is used to specify a path to connect to a virtio-net device. - queues: The parameter is used to specify the number of the queues virtio-net device has. (Default: 1) Here is an example. $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i To connect above testpmd, here is qemu command example. $ qemu-system-x86_64 \ -chardev socket,id=chr0,path=/tmp/sock0 \ -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ -device virtio-net-pci,netdev=net0,mq=on Signed-off-by: Tetsuya Mukawa --- config/common_linuxapp | 6 + doc/guides/nics/index.rst | 1 + doc/guides/rel_notes/release_2_3.rst| 3 + drivers/net/Makefile| 4 + drivers/net/vhost/Makefile | 62 ++ drivers/net/vhost/rte_eth_vhost.c | 898 drivers/net/vhost/rte_eth_vhost.h | 109 drivers/net/vhost/rte_pmd_vhost_version.map | 11 + mk/rte.app.mk | 6 + 9 files changed, 1100 insertions(+) create mode 100644 drivers/net/vhost/Makefile create mode 100644 drivers/net/vhost/rte_eth_vhost.c create mode 100644 drivers/net/vhost/rte_eth_vhost.h create mode 100644 drivers/net/vhost/rte_pmd_vhost_version.map diff --git a/config/common_linuxapp b/config/common_linuxapp index 74bc515..357b557 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -514,6 +514,12 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=n CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # +# Compile vhost PMD +# To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled. +# +CONFIG_RTE_LIBRTE_PMD_VHOST=y + +# #Compile Xen domain0 support # CONFIG_RTE_LIBRTE_XEN_DOM0=n diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst index 33c9cea..5819cdb 100644 --- a/doc/guides/nics/index.rst +++ b/doc/guides/nics/index.rst @@ -47,6 +47,7 @@ Network Interface Controller Drivers nfp szedata2 virtio +vhost vmxnet3 pcap_ring diff --git a/doc/guides/rel_notes/release_2_3.rst b/doc/guides/rel_notes/release_2_3.rst index 99de186..21a38c7 100644 --- a/doc/guides/rel_notes/release_2_3.rst +++ b/doc/guides/rel_notes/release_2_3.rst @@ -4,6 +4,9 @@ DPDK Release 2.3 New Features +* **Added vhost PMD.** + + Added virtual PMD that wraps librte_vhost. Resolved Issues --- diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6e4497e..4300b93 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -52,5 +52,9 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt +ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y) +DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost +endif # $(CONFIG_RTE_LIBRTE_VHOST) + include $(RTE_SDK)/mk/rte.sharelib.mk include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/drivers/net/vhost/Makefile b/drivers/net/vhost/Makefile new file mode 100644 index 000..f49a69b --- /dev/null +++ b/drivers/net/vhost/Makefile @@ -0,0 +1,62 @@ +# BSD LICENSE +# +# Copyright (c) 2010-2016 Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
[dpdk-dev] [PATCH v7 2/2] vhost: Add VHOST PMD
On Thu, Feb 04, 2016 at 04:26:31PM +0900, Tetsuya Mukawa wrote: Hi Tetsuya, > The patch introduces a new PMD. This PMD is implemented as thin wrapper > of librte_vhost. It means librte_vhost is also needed to compile the PMD. > The vhost messages will be handled only when a port is started. So start > a port first, then invoke QEMU. > > The PMD has 2 parameters. > - iface: The parameter is used to specify a path to connect to a >virtio-net device. > - queues: The parameter is used to specify the number of the queues >virtio-net device has. >(Default: 1) > > Here is an example. > $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=1' -- -i > > To connect above testpmd, here is qemu command example. > > $ qemu-system-x86_64 \ > > -chardev socket,id=chr0,path=/tmp/sock0 \ > -netdev vhost-user,id=net0,chardev=chr0,vhostforce,queues=1 \ > -device virtio-net-pci,netdev=net0,mq=on > > Signed-off-by: Tetsuya Mukawa Please find some more comments, mostly minor nits, please feel free to add my ack for next version of this patch: Acked-by: Ferruh Yigit <...> > diff --git a/drivers/net/vhost/rte_eth_vhost.c > b/drivers/net/vhost/rte_eth_vhost.c > new file mode 100644 > index 000..b2305c2 > --- /dev/null > +++ b/drivers/net/vhost/rte_eth_vhost.c <...> > + > +struct pmd_internal { > + TAILQ_ENTRY(pmd_internal) next; > + char *dev_name; > + char *iface_name; > + uint8_t port_id; You can also get rid of port_id too, if you keep list of rte_eth_dev. But this is not so important, keep as it is if you want to. > + > + volatile uint16_t once; > +}; > + <...> > + > +static int > +new_device(struct virtio_net *dev) > +{ <...> > + > + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { > + vq = eth_dev->data->rx_queues[i]; > + if (vq == NULL) can vq be NULL? It is allocated in rx/tx_queue_setup() and there is already a NULL check there? > + continue; > + vq->device = dev; > + vq->internal = internal; > + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); > + } > + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { > + vq = eth_dev->data->tx_queues[i]; > + if (vq == NULL) > + continue; > + vq->device = dev; > + vq->internal = internal; > + rte_vhost_enable_guest_notification(dev, vq->virtqueue_id, 0); > + } > + > + dev->flags |= VIRTIO_DEV_RUNNING; > + dev->priv = eth_dev; > + eth_dev->data->dev_link.link_status = 1; > + > + for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { > + vq = eth_dev->data->rx_queues[i]; > + if (vq == NULL) > + continue; > + rte_atomic32_set(>allow_queuing, 1); > + } > + for (i = 0; i < eth_dev->data->nb_tx_queues; i++) { > + vq = eth_dev->data->tx_queues[i]; > + if (vq == NULL) > + continue; > + rte_atomic32_set(>allow_queuing, 1); > + } > + > + RTE_LOG(INFO, PMD, "New connection established\n"); > + > + _rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC); > + > + return 0; > +} > + <...> > + > +static int > +vring_state_changed(struct virtio_net *dev, uint16_t vring, int enable) > +{ > + struct rte_vhost_vring_state *state; > + struct pmd_internal *internal; > +#ifdef RTE_LIBRTE_VHOST_NUMA > + int newnode, ret; > +#endif > + > + if (dev == NULL) { > + RTE_LOG(ERR, PMD, "Invalid argument\n"); > + return -1; > + } > + > + internal = find_internal_resource(dev->ifname); > + if (internal == NULL) { > + RTE_LOG(ERR, PMD, "Invalid interface name: %s\n", dev->ifname); > + return -1; > + } > + > + state = vring_states[internal->port_id]; > + if (!state) { > + RTE_LOG(ERR, PMD, "Unused port id: %d\n", internal->port_id); > + return -1; > + } > + > +#ifdef RTE_LIBRTE_VHOST_NUMA > + ret = get_mempolicy(, NULL, 0, dev, > + MPOL_F_NODE | MPOL_F_ADDR); > + if (ret < 0) { > + RTE_LOG(ERR, PMD, "Unknow numa node\n"); > + return -1; > + } > + > + rte_eth_devices[internal->port_id].data->numa_node = newnode; If you prefer to keep the list of device instead of list of internal data, can escape accessing global device array > +#endif > + rte_spinlock_lock(>lock); > + state->cur[vring] = enable; > + state->max_vring = RTE_MAX(vring, state->max_vring); > + rte_spinlock_unlock(>lock); > + > + RTE_LOG(INFO, PMD, "vring%u is %s\n", > + vring, enable ? "enabled" : "disabled"); > + > + _rte_eth_dev_callback_process(_eth_devices[internal->port_id], > + RTE_ETH_EVENT_QUEUE_STATE_CHANGE); > + > + return 0; > +} > +