new netdev type like DPDK can support multi-queue IO. Following patch Adds support for same.
Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- v1-v2: - rename nr_rx to n_rxq - Added comments. - use xrealloc, avoid second loop. --- lib/dpif-netdev.c | 66 ++++++++++++++++++++++++++++++++++--------------- lib/dpif-netdev.h | 2 ++ lib/netdev-provider.h | 5 ++++ lib/netdev.c | 18 ++++++++++++-- lib/netdev.h | 3 ++- 5 files changed, 71 insertions(+), 23 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 0af1916..d11c0d1 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -194,7 +194,7 @@ struct dp_netdev_port { odp_port_t port_no; struct netdev *netdev; struct netdev_saved_flags *sf; - struct netdev_rxq *rxq; + struct netdev_rxq **rxq; struct ovs_refcount ref_cnt; char *type; /* Port type as requested by user. */ }; @@ -675,6 +675,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type, enum netdev_flags flags; const char *open_type; int error; + int i; /* XXX reject devices already in some dp_netdev. */ @@ -696,19 +697,24 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type, port = xzalloc(sizeof *port); port->port_no = port_no; port->netdev = netdev; + port->rxq = xmalloc(sizeof *port->rxq * netdev_n_rxq(netdev)); port->type = xstrdup(type); - error = netdev_rxq_open(netdev, &port->rxq); - if (error - && !(error == EOPNOTSUPP && dpif_netdev_class_is_dummy(dp->class))) { - VLOG_ERR("%s: cannot receive packets on this network device (%s)", - devname, ovs_strerror(errno)); - netdev_close(netdev); - return error; + for (i = 0; i < netdev_n_rxq(netdev); i++) { + error = netdev_rxq_open(netdev, &port->rxq[i], i); + if (error + && !(error == EOPNOTSUPP && dpif_netdev_class_is_dummy(dp->class))) { + VLOG_ERR("%s: cannot receive packets on this network device (%s)", + devname, ovs_strerror(errno)); + netdev_close(netdev); + return error; + } } error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, &sf); if (error) { - netdev_rxq_close(port->rxq); + for (i = 0; i < netdev_n_rxq(netdev); i++) { + netdev_rxq_close(port->rxq[i]); + } netdev_close(netdev); free(port->rxq); free(port); @@ -817,9 +823,14 @@ static void port_unref(struct dp_netdev_port *port) { if (port && ovs_refcount_unref(&port->ref_cnt) == 1) { + int i; + netdev_close(port->netdev); netdev_restore_flags(port->sf); - netdev_rxq_close(port->rxq); + + for (i = 0; i < netdev_n_rxq(port->netdev); i++) { + netdev_rxq_close(port->rxq[i]); + } free(port->type); free(port); } @@ -1757,8 +1768,12 @@ dpif_netdev_run(struct dpif *dpif) ovs_rwlock_rdlock(&dp->port_rwlock); HMAP_FOR_EACH (port, node, &dp->ports) { - if (port->rxq && !netdev_is_pmd(port->netdev)) { - dp_netdev_process_rxq_port(dp, port, port->rxq); + if (!netdev_is_pmd(port->netdev)) { + int i; + + for (i = 0; i < netdev_n_rxq(port->netdev); i++) { + dp_netdev_process_rxq_port(dp, port, port->rxq[i]); + } } } @@ -1774,8 +1789,12 @@ dpif_netdev_wait(struct dpif *dpif) ovs_rwlock_rdlock(&dp->port_rwlock); HMAP_FOR_EACH (port, node, &dp->ports) { - if (port->rxq && !netdev_is_pmd(port->netdev)) { - netdev_rxq_wait(port->rxq); + if (!netdev_is_pmd(port->netdev)) { + int i; + + for (i = 0; i < netdev_n_rxq(port->netdev); i++) { + netdev_rxq_wait(port->rxq[i]); + } } } ovs_rwlock_unlock(&dp->port_rwlock); @@ -1783,6 +1802,7 @@ dpif_netdev_wait(struct dpif *dpif) struct rxq_poll { struct dp_netdev_port *port; + struct netdev_rxq *rx; }; static int @@ -1807,13 +1827,19 @@ pmd_load_queues(struct pmd_thread *f, HMAP_FOR_EACH (port, node, &f->dp->ports) { if (netdev_is_pmd(port->netdev)) { - if ((index % dp->n_pmd_threads) == id) { - poll_list = xrealloc(poll_list, sizeof *poll_list * (poll_cnt + 1)); + int i; + + for (i = 0; i < netdev_n_rxq(port->netdev); i++) { + if ((index % dp->n_pmd_threads) == id) { + poll_list = xrealloc(poll_list, sizeof *poll_list * (poll_cnt + 1)); - port_ref(port); - poll_list[poll_cnt++].port = port; + port_ref(port); + poll_list[poll_cnt].port = port; + poll_list[poll_cnt].rx = port->rxq[i]; + poll_cnt++; + } + index++; } - index++; } } @@ -1847,7 +1873,7 @@ reload: int i; for (i = 0; i < poll_cnt; i++) { - dp_netdev_process_rxq_port(dp, poll_list[i].port, poll_list[i].port->rxq); + dp_netdev_process_rxq_port(dp, poll_list[i].port, poll_list[i].rx); } if (lc++ > 1024) { diff --git a/lib/dpif-netdev.h b/lib/dpif-netdev.h index f844d84..4096785 100644 --- a/lib/dpif-netdev.h +++ b/lib/dpif-netdev.h @@ -39,6 +39,8 @@ static inline void dp_packet_pad(struct ofpbuf *b) } } +#define NR_QUEUE 1 + #ifdef __cplusplus } #endif diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 502e63b..9ed5dfa 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -39,6 +39,7 @@ struct netdev { this device. */ /* The following are protected by 'netdev_mutex' (internal to netdev.c). */ + int n_rxq; int ref_cnt; /* Times this devices was opened. */ struct shash_node *node; /* Pointer to element in global map. */ struct list saved_flags_list; /* Contains "struct netdev_saved_flags". */ @@ -59,6 +60,7 @@ void netdev_get_devices(const struct netdev_class *, * None of these members change during the lifetime of a struct netdev_rxq. */ struct netdev_rxq { struct netdev *netdev; /* Owns a reference to the netdev. */ + int queue_id; }; struct netdev *netdev_rxq_get_netdev(const struct netdev_rxq *); @@ -127,6 +129,9 @@ struct netdev *netdev_rxq_get_netdev(const struct netdev_rxq *); * implementation must not refer to base or derived state in the data * structure, because it has already been uninitialized. * + * If netdev support multi-queue IO then netdev->construct should set initialize + * netdev->n_rxq to number of queues. + * * Each "alloc" function allocates and returns a new instance of the respective * data structure. The "alloc" function is not given any information about the * use of the new data structure, so it cannot perform much initialization. diff --git a/lib/netdev.c b/lib/netdev.c index e39d06f..8fa0a9f 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -90,6 +90,12 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); static void restore_all_flags(void *aux OVS_UNUSED); void update_device_args(struct netdev *, const struct shash *args); +int +netdev_n_rxq(const struct netdev *netdev) +{ + return netdev->n_rxq; +} + bool netdev_is_pmd(const struct netdev *netdev) { @@ -333,6 +339,13 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) netdev->netdev_class = rc->class; netdev->name = xstrdup(name); netdev->node = shash_add(&netdev_shash, name, netdev); + + /* By default enable one rx queue per netdev. */ + if (netdev->netdev_class->rxq_alloc) { + netdev->n_rxq = 1; + } else { + netdev->n_rxq = 0; + } list_init(&netdev->saved_flags_list); error = rc->class->construct(netdev); @@ -514,15 +527,16 @@ netdev_parse_name(const char *netdev_name_, char **name, char **type) * Some kinds of network devices might not support receiving packets. This * function returns EOPNOTSUPP in that case.*/ int -netdev_rxq_open(struct netdev *netdev, struct netdev_rxq **rxp) +netdev_rxq_open(struct netdev *netdev, struct netdev_rxq **rxp, int id) OVS_EXCLUDED(netdev_mutex) { int error; - if (netdev->netdev_class->rxq_alloc) { + if (netdev->netdev_class->rxq_alloc && id < netdev->n_rxq) { struct netdev_rxq *rx = netdev->netdev_class->rxq_alloc(); if (rx) { rx->netdev = netdev; + rx->queue_id = id; error = netdev->netdev_class->rxq_construct(rx); if (!error) { ovs_mutex_lock(&netdev_mutex); diff --git a/lib/netdev.h b/lib/netdev.h index 0b8def9..432f327 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -134,6 +134,7 @@ void netdev_wait(void); void netdev_enumerate_types(struct sset *types); bool netdev_is_reserved_name(const char *name); +int netdev_n_rxq(const struct netdev *netdev); bool netdev_is_pmd(const struct netdev *netdev); /* Open and close. */ @@ -159,7 +160,7 @@ int netdev_set_mtu(const struct netdev *, int mtu); int netdev_get_ifindex(const struct netdev *); /* Packet reception. */ -int netdev_rxq_open(struct netdev *, struct netdev_rxq **); +int netdev_rxq_open(struct netdev *, struct netdev_rxq **, int id); void netdev_rxq_close(struct netdev_rxq *); const char *netdev_rxq_get_name(const struct netdev_rxq *); -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev