This commit adds a new API to the 'struct netdev_class' which allows user to configure the number of tx queues and rx queues of 'netdev'. Upcoming patches will use this function to set multiple tx/rx queues when adding the netdev to dpif-netdev.
Currently, only netdev-dpdk module implements this function. Signed-off-by: Alex Wang <al...@nicira.com> --- PATCH -> V4: - move this hidden patch forward. --- lib/netdev-bsd.c | 1 + lib/netdev-dpdk.c | 46 +++++++++++++++++++++++++++++++++++++--------- lib/netdev-dummy.c | 1 + lib/netdev-linux.c | 1 + lib/netdev-provider.h | 10 ++++++++++ lib/netdev-vport.c | 1 + lib/netdev.c | 25 +++++++++++++++++++++++++ lib/netdev.h | 1 + 8 files changed, 77 insertions(+), 9 deletions(-) diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index 32c04a3..20b4718 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -1563,6 +1563,7 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off, NULL, /* set_config */ \ NULL, /* get_tunnel_config */ \ NULL, /* get_numa_id */ \ + NULL, /* set_multiq */ \ \ netdev_bsd_send, \ netdev_bsd_send_wait, \ diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 4f9c5c2..d11c070 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -399,13 +399,14 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev) OVS_REQUIRES(dpdk_mutex) return ENODEV; } - diag = rte_eth_dev_configure(dev->port_id, NR_QUEUE, NR_QUEUE, &port_conf); + diag = rte_eth_dev_configure(dev->port_id, dev->up.n_rxq, dev->up.n_txq, + &port_conf); if (diag) { VLOG_ERR("eth dev config error %d",diag); return -diag; } - for (i = 0; i < NR_QUEUE; i++) { + for (i = 0; i < dev->up.n_txq; i++) { diag = rte_eth_tx_queue_setup(dev->port_id, i, NIC_PORT_TX_Q_SIZE, dev->socket_id, &tx_conf); if (diag) { @@ -414,7 +415,7 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev) OVS_REQUIRES(dpdk_mutex) } } - for (i = 0; i < NR_QUEUE; i++) { + for (i = 0; i < dev->up.n_rxq; i++) { diag = rte_eth_rx_queue_setup(dev->port_id, i, NIC_PORT_RX_Q_SIZE, dev->socket_id, &rx_conf, dev->dpdk_mp->mp); @@ -491,12 +492,12 @@ netdev_dpdk_init(struct netdev *netdev_, unsigned int port_no) OVS_REQUIRES(dpdk goto unlock; } + netdev_->n_txq = NR_QUEUE; + netdev_->n_rxq = NR_QUEUE; err = dpdk_eth_dev_init(netdev); if (err) { goto unlock; } - netdev_->n_txq = NR_QUEUE; - netdev_->n_rxq = NR_QUEUE; list_push_back(&dpdk_list, &netdev->list_node); @@ -590,6 +591,26 @@ netdev_dpdk_get_numa_id(const struct netdev *netdev_) return netdev->socket_id; } +/* Sets the number of tx queues and rx queues for the dpdk interface. + * If the configuration fails, do not try restoring its old configuration + * and just returns the error. */ +static int +netdev_dpdk_set_multiq(struct netdev *netdev_, unsigned int n_txq, + unsigned int n_rxq) +{ + struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_); + int err = 0; + + ovs_mutex_lock(&netdev->mutex); + rte_eth_dev_stop(netdev->port_id); + netdev->up.n_txq = MAX(n_txq, NR_QUEUE); + netdev->up.n_rxq = MAX(n_rxq, NR_QUEUE); + err = dpdk_eth_dev_init(netdev); + ovs_mutex_unlock(&netdev->mutex); + + return err; +} + static struct netdev_rxq * netdev_dpdk_rxq_alloc(void) { @@ -687,7 +708,11 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets, struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); int nb_rx; - dpdk_queue_flush(dev, rxq_->queue_id); + /* There is only one tx queue for this core. Do not flush other + * queueus. */ + if (rxq_->queue_id == rte_lcore_id()) { + dpdk_queue_flush(dev, rxq_->queue_id); + } nb_rx = rte_eth_rx_burst(rx->port_id, rxq_->queue_id, (struct rte_mbuf **) packets, @@ -1339,7 +1364,7 @@ unlock_dpdk: return err; } -#define NETDEV_DPDK_CLASS(NAME, INIT, CONSTRUCT) \ +#define NETDEV_DPDK_CLASS(NAME, INIT, CONSTRUCT, MULTIQ) \ { \ NAME, \ INIT, /* init */ \ @@ -1354,6 +1379,7 @@ unlock_dpdk: NULL, /* netdev_dpdk_set_config */ \ NULL, /* get_tunnel_config */ \ netdev_dpdk_get_numa_id, /* get_numa_id */ \ + MULTIQ, /* set_multiq */ \ \ netdev_dpdk_send, /* send */ \ NULL, /* send_wait */ \ @@ -1441,13 +1467,15 @@ const struct netdev_class dpdk_class = NETDEV_DPDK_CLASS( "dpdk", dpdk_class_init, - netdev_dpdk_construct); + netdev_dpdk_construct, + netdev_dpdk_set_multiq); const struct netdev_class dpdk_ring_class = NETDEV_DPDK_CLASS( "dpdkr", NULL, - netdev_dpdk_ring_construct); + netdev_dpdk_ring_construct, + NULL); void netdev_dpdk_register(void) diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 1334a67..e0df0b9 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -1045,6 +1045,7 @@ static const struct netdev_class dummy_class = { netdev_dummy_set_config, NULL, /* get_tunnel_config */ NULL, /* get_numa_id */ + NULL, /* set_multiq */ netdev_dummy_send, /* send */ NULL, /* send_wait */ diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index e311122..531999e 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -2751,6 +2751,7 @@ netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off, NULL, /* set_config */ \ NULL, /* get_tunnel_config */ \ NULL, /* get_numa_id */ \ + NULL, /* set_multiq */ \ \ netdev_linux_send, \ netdev_linux_send_wait, \ diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index c08ef35..c92afff 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -258,6 +258,16 @@ struct netdev_class { * such info, returns NETDEV_NUMA_UNSPEC. */ int (*get_numa_id)(const struct netdev *netdev); + /* Configures the number of tx queues and rx queues of 'netdev'. + * Return 0 if successful, otherwise a positive errno value. + * + * On error, the tx queue and rx queue configuration is indeterminant. + * Caller should make decision on whether to restore the previous or + * the default configuration. Also, caller must make sure there is no + * other thread accessing the queues at the same time. */ + int (*set_multiq)(struct netdev *netdev, unsigned int n_txq, + unsigned int n_rxq); + /* Sends buffers on 'netdev'. * Returns 0 if successful (for every buffer), otherwise a positive errno * value. Returns EAGAIN without blocking if one or more packets cannot be diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 6ab90bf..91689e7 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -776,6 +776,7 @@ get_stats(const struct netdev *netdev, struct netdev_stats *stats) SET_CONFIG, \ GET_TUNNEL_CONFIG, \ NULL, /* get_numa_id */ \ + NULL, /* set_multiq */ \ \ NULL, /* send */ \ NULL, /* send_wait */ \ diff --git a/lib/netdev.c b/lib/netdev.c index 0d065e7..7e5a748 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -663,6 +663,31 @@ netdev_rxq_drain(struct netdev_rxq *rx) : 0); } +/* Configures the number of tx queues and rx queues of 'netdev'. + * Return 0 if successful, otherwise a positive errno value. + * + * On error, the tx queue and rx queue configuration is indeterminant. + * Caller should make decision on whether to restore the previous or + * the default configuration. Also, caller must make sure there is no + * other thread accessing the queues at the same time. */ +int +netdev_set_multiq(struct netdev *netdev, unsigned int n_txq, + unsigned int n_rxq) +{ + int error; + + error = (netdev->netdev_class->set_multiq + ? netdev->netdev_class->set_multiq(netdev, n_txq, n_rxq) + : EOPNOTSUPP); + + if (error != EOPNOTSUPP) { + VLOG_DBG_RL(&rl, "failed to set tx/rx queue for network device %s:" + "%s", netdev_get_name(netdev), ovs_strerror(error)); + } + + return error; +} + /* Sends 'buffers' on 'netdev'. Returns 0 if successful (for every packet), * otherwise a positive errno value. Returns EAGAIN without blocking if * at least one the packets cannot be queued immediately. Returns EMSGSIZE diff --git a/lib/netdev.h b/lib/netdev.h index c6249c4..33668b4 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -162,6 +162,7 @@ const char *netdev_get_type_from_name(const char *); int netdev_get_mtu(const struct netdev *, int *mtup); int netdev_set_mtu(const struct netdev *, int mtu); int netdev_get_ifindex(const struct netdev *); +int netdev_set_multiq(struct netdev *, unsigned int n_txq, unsigned int n_rxq); /* Packet reception. */ int netdev_rxq_open(struct netdev *, struct netdev_rxq **, int id); -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev