summaryrefslogtreecommitdiff
path: root/lib/netdev.c
diff options
context:
space:
mode:
authorDaniele Di Proietto <diproiettod@vmware.com>2016-11-15 15:40:49 -0800
committerDaniele Di Proietto <diproiettod@vmware.com>2017-01-15 19:25:11 -0800
commit57eebbb4c3151cdf4c56419c1fea15cfdf0acba4 (patch)
tree0e1e200ee7c638bbda271763718dba388c096e55 /lib/netdev.c
parentfebf4a7a8748311e76e462d6843dd6ccb9b4c5de (diff)
downloadopenvswitch-57eebbb4c3151cdf4c56419c1fea15cfdf0acba4.tar.gz
dpif-netdev: Don't try to output on a device without txqs.
Tunnel devices have 0 txqs and don't support netdev_send(). While netdev_send() simply returns EOPNOTSUPP, the XPS logic is still executed on output, and that might be confused by devices with no txqs. It seems better to have different structures in the fast path for ports that support netdev_{push,pop}_header (tunnel devices), and ports that support netdev_send. With this we can also remove a branch in netdev_send(). This is also necessary for a future commit, which starts DPDK devices without txqs. Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com> Acked-by: Ilya Maximets <i.maximets@samsung.com>
Diffstat (limited to 'lib/netdev.c')
-rw-r--r--lib/netdev.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/lib/netdev.c b/lib/netdev.c
index afc3818d4..18615fff7 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -117,6 +117,13 @@ netdev_is_pmd(const struct netdev *netdev)
return netdev->netdev_class->is_pmd;
}
+bool
+netdev_has_tunnel_push_pop(const struct netdev *netdev)
+{
+ return netdev->netdev_class->push_header
+ && netdev->netdev_class->pop_header;
+}
+
static void
netdev_initialize(void)
OVS_EXCLUDED(netdev_mutex)
@@ -692,6 +699,9 @@ netdev_set_tx_multiq(struct netdev *netdev, unsigned int n_txq)
* if a partial packet was transmitted or if a packet is too big or too small
* to transmit on the device.
*
+ * The caller must make sure that 'netdev' supports sending by making sure that
+ * 'netdev_n_txq(netdev)' returns >= 1.
+ *
* If the function returns a non-zero value, some of the packets might have
* been sent anyway.
*
@@ -716,11 +726,6 @@ int
netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
bool may_steal, bool concurrent_txq)
{
- if (!netdev->netdev_class->send) {
- dp_packet_delete_batch(batch, may_steal);
- return EOPNOTSUPP;
- }
-
int error = netdev->netdev_class->send(netdev, qid, batch, may_steal,
concurrent_txq);
if (!error) {
@@ -732,18 +737,17 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
return error;
}
+/* Pop tunnel header, build tunnel metadata and resize 'batch->packets'
+ * for further processing.
+ *
+ * The caller must make sure that 'netdev' support this operation by checking
+ * that netdev_has_tunnel_push_pop() returns true. */
void
netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *batch)
{
int i, n_cnt = 0;
struct dp_packet **buffers = batch->packets;
- if (!netdev->netdev_class->pop_header) {
- dp_packet_delete_batch(batch, true);
- batch->count = 0;
- return;
- }
-
for (i = 0; i < batch->count; i++) {
buffers[i] = netdev->netdev_class->pop_header(buffers[i]);
if (buffers[i]) {
@@ -781,6 +785,11 @@ int netdev_build_header(const struct netdev *netdev,
return EOPNOTSUPP;
}
+/* Push tunnel header (reading from tunnel metadata) and resize
+ * 'batch->packets' for further processing.
+ *
+ * The caller must make sure that 'netdev' support this operation by checking
+ * that netdev_has_tunnel_push_pop() returns true. */
int
netdev_push_header(const struct netdev *netdev,
struct dp_packet_batch *batch,
@@ -788,10 +797,6 @@ netdev_push_header(const struct netdev *netdev,
{
int i;
- if (!netdev->netdev_class->push_header) {
- return -EINVAL;
- }
-
for (i = 0; i < batch->count; i++) {
netdev->netdev_class->push_header(batch->packets[i], data);
pkt_metadata_init(&batch->packets[i]->md, u32_to_odp(data->out_port));