datapath: Disable LRO from userspace instead of the kernel.
[sliver-openvswitch.git] / lib / dpif-linux.c
index 2bcf96e..da48c68 100644 (file)
@@ -60,6 +60,10 @@ enum { LRU_MAX_PORTS = 1024 };
 enum { LRU_MASK = LRU_MAX_PORTS - 1};
 BUILD_ASSERT_DECL(IS_POW2(LRU_MAX_PORTS));
 
+/* This ethtool flag was introduced in Linux 2.6.24, so it might be
+ * missing if we have old headers. */
+#define ETH_FLAG_LRO      (1 << 15)    /* LRO is enabled */
+
 struct dpif_linux_dp {
     /* Generic Netlink header. */
     uint8_t cmd;
@@ -308,6 +312,18 @@ dpif_linux_destroy(struct dpif *dpif_)
     return dpif_linux_dp_transact(&dp, NULL, NULL);
 }
 
+static void
+dpif_linux_run(struct dpif *dpif OVS_UNUSED)
+{
+    rtnetlink_link_notifier_run();
+}
+
+static void
+dpif_linux_wait(struct dpif *dpif OVS_UNUSED)
+{
+    rtnetlink_link_notifier_wait();
+}
+
 static int
 dpif_linux_get_stats(const struct dpif *dpif_, struct ovs_dp_stats *stats)
 {
@@ -381,6 +397,10 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
         request.options_len = options->size;
     }
 
+    if (request.type == OVS_VPORT_TYPE_NETDEV) {
+        netdev_linux_ethtool_set_flag(netdev, ETH_FLAG_LRO, "LRO", false);
+    }
+
     /* Loop until we find a port that isn't used. */
     do {
         request.port_no = dpif_linux_pop_port(dpif);
@@ -589,8 +609,6 @@ dpif_linux_port_poll_wait(const struct dpif *dpif_)
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     if (!sset_is_empty(&dpif->changed_ports) || dpif->change_error) {
         poll_immediate_wake();
-    } else {
-        rtnetlink_link_notifier_wait();
     }
 }
 
@@ -1048,8 +1066,8 @@ const struct dpif_class dpif_linux_class = {
     dpif_linux_open,
     dpif_linux_close,
     dpif_linux_destroy,
-    NULL,                       /* run */
-    NULL,                       /* wait */
+    dpif_linux_run,
+    dpif_linux_wait,
     dpif_linux_get_stats,
     dpif_linux_get_drop_frags,
     dpif_linux_set_drop_frags,