Commit 8e816df8 authored by Jesse Gross's avatar Jesse Gross Committed by David S. Miller

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: default avatarJesse Gross <jesse@nicira.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c30da497
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <net/dst_metadata.h> #include <net/dst_metadata.h>
#include <net/gro_cells.h>
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
#include <net/geneve.h> #include <net/geneve.h>
#include <net/protocol.h> #include <net/protocol.h>
...@@ -58,6 +59,7 @@ struct geneve_dev { ...@@ -58,6 +59,7 @@ struct geneve_dev {
struct list_head next; /* geneve's per namespace list */ struct list_head next; /* geneve's per namespace list */
__be16 dst_port; __be16 dst_port;
bool collect_md; bool collect_md;
struct gro_cells gro_cells;
}; };
struct geneve_sock { struct geneve_sock {
...@@ -199,7 +201,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) ...@@ -199,7 +201,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
stats->rx_bytes += skb->len; stats->rx_bytes += skb->len;
u64_stats_update_end(&stats->syncp); u64_stats_update_end(&stats->syncp);
netif_rx(skb); gro_cells_receive(&geneve->gro_cells, skb);
return; return;
drop: drop:
/* Consume bad packet */ /* Consume bad packet */
...@@ -209,14 +211,27 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) ...@@ -209,14 +211,27 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
/* Setup stats when device is created */ /* Setup stats when device is created */
static int geneve_init(struct net_device *dev) 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); dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
if (!dev->tstats) if (!dev->tstats)
return -ENOMEM; return -ENOMEM;
err = gro_cells_init(&geneve->gro_cells, dev);
if (err) {
free_percpu(dev->tstats);
return err;
}
return 0; return 0;
} }
static void geneve_uninit(struct net_device *dev) 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); free_percpu(dev->tstats);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment