[ovs-dev] [PATCH 2/5] netdev: Added netdev_send_batch function
Daniele Di Proietto
ddiproietto at vmware.com
Fri May 23 18:04:44 UTC 2014
The netdev_send_batch function allows netdevs to send packets
more efficiently. This will be useful for netdev-dpdk.
If a netdev does not implement send_batch, netdev_send_batch
calls send repeatedly.
Signed-off-by: Daniele Di Proietto <ddiproietto at vmware.com>
---
lib/netdev-bsd.c | 1 +
lib/netdev-dpdk.c | 1 +
lib/netdev-dummy.c | 1 +
lib/netdev-linux.c | 1 +
lib/netdev-provider.h | 13 +++++++++++++
lib/netdev-vport.c | 1 +
lib/netdev.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
lib/netdev.h | 1 +
8 files changed, 63 insertions(+)
diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 8dc33df..b7922ea 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -1550,6 +1550,7 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off,
NULL, /* get_tunnel_config */ \
\
netdev_bsd_send, \
+ NULL, /* send_batch */ \
netdev_bsd_send_wait, \
\
netdev_bsd_set_etheraddr, \
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index fd991ab..ee811eb 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -1122,6 +1122,7 @@ static struct netdev_class netdev_dpdk_class = {
NULL, /* get_tunnel_config */
netdev_dpdk_send, /* send */
+ NULL, /* send_batch */
NULL, /* send_wait */
netdev_dpdk_set_etheraddr,
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 501fb82..49ef12b 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1004,6 +1004,7 @@ static const struct netdev_class dummy_class = {
NULL, /* get_tunnel_config */
netdev_dummy_send, /* send */
+ NULL, /* send_batch */
NULL, /* send_wait */
netdev_dummy_set_etheraddr,
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index c1d9323..1d01b4a 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2735,6 +2735,7 @@ netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off,
NULL, /* get_tunnel_config */ \
\
netdev_linux_send, \
+ NULL, /* send_batch */ \
netdev_linux_send_wait, \
\
netdev_linux_set_etheraddr, \
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 37b9da3..2215eaa 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -270,6 +270,19 @@ struct netdev_class {
* working properly over 'netdev'.) */
int (*send)(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal);
+ /* Sends a batch of buffers on 'netdev'.
+ * This is useful for DPDK and netmap-like interfaces, where sending
+ * batches is more efficient than sending single buffers.
+ *
+ * The semantics are similar to 'send'.
+ *
+ * May return EOPNOTSUPP if a network device does not implement packet
+ * transmission through this interface. This function may be set to null
+ * if it would always return EOPNOTSUPP anyhow. (In this case
+ * netdev_send_batch will call netdev_send repeatedly.) */
+ int (*send_batch)(struct netdev *netdev, struct ofpbuf **buffers, int c,
+ bool may_steal);
+
/* Registers with the poll loop to wake up from the next call to
* poll_block() when the packet transmission queue for 'netdev' has
* sufficient room to transmit a packet with netdev_send().
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index c214bf7..21bb66c 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -767,6 +767,7 @@ get_stats(const struct netdev *netdev, struct netdev_stats *stats)
GET_TUNNEL_CONFIG, \
\
NULL, /* send */ \
+ NULL, /* send_batch*/ \
NULL, /* send_wait */ \
\
netdev_vport_set_etheraddr, \
diff --git a/lib/netdev.c b/lib/netdev.c
index dd800a4..c4c28b2 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -676,6 +676,50 @@ netdev_send(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal)
return error;
}
+/* Sends 'c' 'buffers' on 'netdev'. If 'netdev' supports batching, uses
+ * send_batch(), otherwise iterates through 'buffers' and uses send().
+ * Returns 0 if successful, otherwise a positive errno value.
+ *
+ * To retain ownership of 'buffer' caller can set may_steal to false.
+ *
+ * If any error occurs during the transmission of one buffer, the function
+ * stops and return the error. */
+int
+netdev_send_batch(struct netdev *netdev, struct ofpbuf **buffers, int c,
+ bool may_steal)
+{
+ int error;
+
+ error = (netdev->netdev_class->send_batch
+ ? netdev->netdev_class->send_batch(netdev, buffers, c, may_steal)
+ : EOPNOTSUPP);
+
+ if (error == EOPNOTSUPP) {
+ int i;
+
+ for (i = 0; i < c; i++) {
+ error = (netdev->netdev_class->send
+ ? netdev->netdev_class->send(netdev, buffers[i], may_steal)
+ : EOPNOTSUPP);
+ if (error) {
+ break;
+ }
+ }
+
+ if (error && may_steal) {
+ int j;
+
+ for (j = (error == EOPNOTSUPP) ? i : i+1; j < c; j++) {
+ ofpbuf_delete(buffers[j]);
+ }
+ }
+ }
+ if (!error) {
+ COVERAGE_INC(netdev_sent);
+ }
+ return error;
+}
+
/* Registers with the poll loop to wake up from the next call to poll_block()
* when the packet transmission queue has sufficient room to transmit a packet
* with netdev_send().
diff --git a/lib/netdev.h b/lib/netdev.h
index a4bd01a..dff516f 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -172,6 +172,7 @@ int netdev_rxq_drain(struct netdev_rxq *);
/* Packet transmission. */
int netdev_send(struct netdev *, struct ofpbuf *, bool may_steal);
+int netdev_send_batch(struct netdev *, struct ofpbuf **, int c, bool may_steal);
void netdev_send_wait(struct netdev *);
/* Hardware address. */
--
2.0.0.rc0
More information about the dev
mailing list