mirror of
https://github.com/openvswitch/ovs
synced 2025-10-13 14:07:02 +00:00
netdev: Add support multiqueue recv.
new netdev type like DPDK can support multi-queue IO. Following patch Adds support for same. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Thomas Graf <tgraf@redhat.com>
This commit is contained in:
@@ -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,8 +697,10 @@ 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);
|
||||
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)",
|
||||
@@ -705,10 +708,13 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
|
||||
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,15 +1827,21 @@ pmd_load_queues(struct pmd_thread *f,
|
||||
|
||||
HMAP_FOR_EACH (port, node, &f->dp->ports) {
|
||||
if (netdev_is_pmd(port->netdev)) {
|
||||
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;
|
||||
poll_list[poll_cnt].port = port;
|
||||
poll_list[poll_cnt].rx = port->rxq[i];
|
||||
poll_cnt++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ovs_rwlock_unlock(&dp->port_rwlock);
|
||||
*ppoll_list = poll_list;
|
||||
@@ -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) {
|
||||
|
@@ -39,6 +39,8 @@ static inline void dp_packet_pad(struct ofpbuf *b)
|
||||
}
|
||||
}
|
||||
|
||||
#define NR_QUEUE 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -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.
|
||||
|
18
lib/netdev.c
18
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);
|
||||
|
@@ -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 *);
|
||||
|
Reference in New Issue
Block a user