On Fri, Nov 13, 2015 at 02:20:31PM +0900, Tetsuya Mukawa wrote: .... > +static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER; > + > +static rte_atomic16_t nb_started_ports; > +pthread_t session_th;
static? > + > +static struct rte_eth_link pmd_link = { > + .link_speed = 10000, > + .link_duplex = ETH_LINK_FULL_DUPLEX, > + .link_status = 0 > +}; > + > +static uint16_t > +eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) > +{ > + struct vhost_queue *r = q; > + uint16_t nb_rx = 0; > + > + if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0)) > + return 0; > + > + rte_atomic32_set(&r->while_queuing, 1); > + > + if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0)) > + goto out; > + > + /* Dequeue packets from guest TX queue */ > + nb_rx = rte_vhost_dequeue_burst(r->device, > + r->virtqueue_id, r->mb_pool, bufs, nb_bufs); > + > + r->rx_pkts += nb_rx; > + > +out: > + rte_atomic32_set(&r->while_queuing, 0); > + > + return nb_rx; > +} > + > +static uint16_t > +eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) > +{ > + struct vhost_queue *r = q; > + uint16_t i, nb_tx = 0; > + > + if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0)) > + return 0; > + > + rte_atomic32_set(&r->while_queuing, 1); > + > + if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0)) > + goto out; > + > + /* Enqueue packets to guest RX queue */ > + nb_tx = rte_vhost_enqueue_burst(r->device, > + r->virtqueue_id, bufs, nb_bufs); > + > + r->tx_pkts += nb_tx; > + r->err_pkts += nb_bufs - nb_tx; > + > + for (i = 0; likely(i < nb_tx); i++) > + rte_pktmbuf_free(bufs[i]); We should free upto nb_bufs here, but not nb_tx, right? > + > +out: > + rte_atomic32_set(&r->while_queuing, 0); > + > + return nb_tx; > +} > + > +static int > +eth_dev_configure(struct rte_eth_dev *dev __rte_unused) > +{ > + return 0; > +} > + > +static inline struct pmd_internal * > +find_internal_resource(char *ifname) > +{ > + int found = 0; > + struct pmd_internal *internal; > + > + if (ifname == NULL) > + return NULL; > + > + pthread_mutex_lock(&internal_list_lock); > + > + TAILQ_FOREACH(internal, &internals_list, next) { > + if (!strcmp(internal->iface_name, ifname)) { > + found = 1; > + break; > + } > + } > + > + pthread_mutex_unlock(&internal_list_lock); > + > + if (!found) > + return NULL; > + > + return internal; > +} > + ... > +static void *vhost_driver_session(void *param __rte_unused) static void * vhost_driver_session_start(..) > +{ > + static struct virtio_net_device_ops *vhost_ops; > + > + vhost_ops = rte_zmalloc(NULL, sizeof(*vhost_ops), 0); > + if (vhost_ops == NULL) > + rte_panic("Can't allocate memory\n"); Why not making them static? > + > + /* set vhost arguments */ > + vhost_ops->new_device = new_device; > + vhost_ops->destroy_device = destroy_device; > + if (rte_vhost_driver_pmd_callback_register(vhost_ops) < 0) > + rte_panic("Can't register callbacks\n"); > + > + /* start event handling */ > + rte_vhost_driver_session_start(); > + > + rte_free(vhost_ops); > + pthread_exit(0); > +} > + > +static void vhost_driver_session_start(void) ditto. > +{ > + int ret; > + > + ret = pthread_create(&session_th, > + NULL, vhost_driver_session, NULL); > + if (ret) > + rte_panic("Can't create a thread\n"); > +} > + > +static void vhost_driver_session_stop(void) Ditto. > +{ > + int ret; > + > + ret = pthread_cancel(session_th); > + if (ret) > + rte_panic("Can't cancel the thread\n"); > + > + ret = pthread_join(session_th, NULL); > + if (ret) > + rte_panic("Can't join the thread\n"); > +} > + > +static int > +eth_dev_start(struct rte_eth_dev *dev) ... > + internal->nb_rx_queues = queues; > + internal->nb_tx_queues = queues; > + internal->dev_name = strdup(name); > + if (internal->dev_name == NULL) > + goto error; > + internal->iface_name = strdup(iface_name); > + if (internal->iface_name == NULL) { > + free(internal->dev_name); > + goto error; > + } You still didn't resolve my comments from last email: if allocation failed here, internal->dev_name is not freed. > + > + pthread_mutex_lock(&internal_list_lock); > + TAILQ_INSERT_TAIL(&internals_list, internal, next); > + pthread_mutex_unlock(&internal_list_lock); > + ... > +static struct rte_driver pmd_vhost_drv = { > + .name = "eth_vhost", > + .type = PMD_VDEV, > + .init = rte_pmd_vhost_devinit, > + .uninit = rte_pmd_vhost_devuninit, > +}; > + > +struct > +virtio_net *rte_eth_vhost_portid2vdev(uint16_t port_id) struct virtio_net * rte_eth_vhost_portid2vdev() BTW, why making a speical eth API for virtio? This doesn't make too much sense to me. Besides those minor nits, this patch looks good to me. Thanks for the work! --yliu