]> git.proxmox.com Git - mirror_ovs.git/commitdiff
netdev-linux: do not send packets to down tap ifaces.
authorFlavio Leitner <fbl@sysclose.org>
Thu, 18 Jan 2018 00:09:58 +0000 (22:09 -0200)
committerBen Pfaff <blp@ovn.org>
Mon, 22 Jan 2018 18:28:17 +0000 (10:28 -0800)
Today OVS pushes packets to the TAP interface ignoring its
current state. That works because the kernel will return -EIO
when it's not UP and OVS will just ignore that as it is not
an OVS issue.

However, it causes a huge impact when broadcasts happen when
using userspace datapath accelerated with DPDK (e.g.: action
NORMAL).  This patch improves the situation by checking the
TAP's interface state before issueing any syscall.

However, there might be use-cases moving interfaces to other
networking namespaces and in that case, OVS can't retrieve
the iface state (sets it to DOWN). That would stop the traffic
breaking the use-case. This patch relies on netlink notifications
to find out if the device is local or not. When it's local, the
device state is checked otherwise it will behave as before.

Signed-off-by: Flavio Leitner <fbl@sysclose.org>
Signed-off-by: Ben Pfaff <blp@ovn.org>
NEWS
lib/netdev-linux.c
vswitchd/vswitch.xml

diff --git a/NEWS b/NEWS
index fe1a01eea01c60149849915bff0751678c676154..e95a3c0a6bf48899126a64c203f7224bd2bbe55d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -38,6 +38,8 @@ v2.9.0 - xx xxx xxxx
        connection tracking entry.
      * New "ct-set-maxconns", "ct-get-maxconns", and "ct-get-nconns" commands
        for userspace datapath.
+   - No longer send packets to the Linux TAP device if it's DOWN unless it is
+     in another networking namespace.
    - DPDK:
      * Add support for DPDK v17.11
      * Add support for vHost IOMMU
index 37143b8df8ddad48b328677ab593fe31a19b1120..6dae7964a8959bca19f82b096192c71ec36a1bc9 100644 (file)
@@ -502,6 +502,8 @@ struct netdev_linux {
 
     /* For devices of class netdev_tap_class only. */
     int tap_fd;
+    bool present;               /* If the device is present in the namespace */
+    uint64_t tx_dropped;        /* tap device can drop if the iface is down */
 };
 
 struct netdev_rxq_linux {
@@ -750,8 +752,10 @@ netdev_linux_update(struct netdev_linux *dev,
             dev->ifindex = change->if_index;
             dev->cache_valid |= VALID_IFINDEX;
             dev->get_ifindex_error = 0;
+            dev->present = true;
         } else {
             netdev_linux_changed(dev, change->ifi_flags, 0);
+            dev->present = false;
         }
     } else if (rtnetlink_type_is_rtnlgrp_addr(change->nlmsg_type)) {
         /* Invalidates in4, in6. */
@@ -1234,6 +1238,17 @@ netdev_linux_tap_batch_send(struct netdev *netdev_,
 {
     struct netdev_linux *netdev = netdev_linux_cast(netdev_);
     struct dp_packet *packet;
+
+    /* The Linux tap driver returns EIO if the device is not up,
+     * so if the device is not up, don't waste time sending it.
+     * However, if the device is in another network namespace
+     * then OVS can't retrieve the state. In that case, send the
+     * packets anyway. */
+    if (netdev->present && !(netdev->ifi_flags & IFF_UP)) {
+        netdev->tx_dropped += dp_packet_batch_size(batch);
+        return 0;
+    }
+
     DP_PACKET_BATCH_FOR_EACH (packet, batch) {
         size_t size = dp_packet_size(packet);
         ssize_t retval;
@@ -1825,6 +1840,7 @@ netdev_tap_get_stats(const struct netdev *netdev_, struct netdev_stats *stats)
         stats->multicast           += dev_stats.multicast;
         stats->collisions          += dev_stats.collisions;
     }
+    stats->tx_dropped += netdev->tx_dropped;
     ovs_mutex_unlock(&netdev->mutex);
 
     return error;
index 61fb7b17fd19150fd71aebc6c8b8d73e8392c037..7e893256de6e0a969e110d58fa8eaa7e2fc0b43f 100644 (file)
           imprecisely for internal interfaces.</dd>
 
           <dt><code>tap</code></dt>
-          <dd>A TUN/TAP device managed by Open vSwitch.</dd>
+          <dd>
+            <p>
+              A TUN/TAP device managed by Open vSwitch.
+            </p>
+            <p>
+              Open vSwitch checks the interface state before send packets
+              to the device.  When it is <code>down</code>, the packets are
+              dropped and the tx_dropped statistic is updated accordingly.
+              Older versions of Open vSwitch did not check the interface state
+              and then the tx_packets was incremented along with tx_dropped.
+            </p>
+          </dd>
 
           <dt><code>geneve</code></dt>
           <dd>