summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2015-08-29 01:54:40 +0200
committerDavid S. Miller <davem@davemloft.net>2015-08-29 22:44:29 +0200
commit8e816df87997bb0c40122d5df621423b445c4fe6 (patch)
tree902d4f8cb0b72e64cfdf6604263fe0fb500c0fb6
parentopenvswitch: retain parsed IPv6 header fields in flow on error skipping exten... (diff)
downloadlinux-8e816df87997bb0c40122d5df621423b445c4fe6.tar.xz
linux-8e816df87997bb0c40122d5df621423b445c4fe6.zip
geneve: Use GRO cells infrastructure.
Geneve can benefit from GRO at the device level in a manner similar to other tunnels, especially as hardware offloads are still emerging. After this patch, aggregated frames are seen on the tunnel interface. Single stream throughput nearly doubles in ideal circumstances (on old hardware). Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/geneve.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 3908a22f23d1..68b0f0325fc7 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -16,6 +16,7 @@
#include <linux/etherdevice.h>
#include <linux/hash.h>
#include <net/dst_metadata.h>
+#include <net/gro_cells.h>
#include <net/rtnetlink.h>
#include <net/geneve.h>
#include <net/protocol.h>
@@ -58,6 +59,7 @@ struct geneve_dev {
struct list_head next; /* geneve's per namespace list */
__be16 dst_port;
bool collect_md;
+ struct gro_cells gro_cells;
};
struct geneve_sock {
@@ -199,7 +201,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
stats->rx_bytes += skb->len;
u64_stats_update_end(&stats->syncp);
- netif_rx(skb);
+ gro_cells_receive(&geneve->gro_cells, skb);
return;
drop:
/* Consume bad packet */
@@ -209,14 +211,27 @@ drop:
/* Setup stats when device is created */
static int geneve_init(struct net_device *dev)
{
+ struct geneve_dev *geneve = netdev_priv(dev);
+ int err;
+
dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
if (!dev->tstats)
return -ENOMEM;
+
+ err = gro_cells_init(&geneve->gro_cells, dev);
+ if (err) {
+ free_percpu(dev->tstats);
+ return err;
+ }
+
return 0;
}
static void geneve_uninit(struct net_device *dev)
{
+ struct geneve_dev *geneve = netdev_priv(dev);
+
+ gro_cells_destroy(&geneve->gro_cells);
free_percpu(dev->tstats);
}