#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>
struct list_head next; /* geneve's per namespace list */
__be16 dst_port;
bool collect_md;
+ struct gro_cells gro_cells;
};
struct geneve_sock {
if (ip_tunnel_collect_metadata() || gs->collect_md) {
__be16 flags;
- void *opts;
flags = TUNNEL_KEY | TUNNEL_GENEVE_OPT |
(gnvh->oam ? TUNNEL_OAM : 0) |
gnvh->opt_len * 4);
if (!tun_dst)
goto drop;
-
/* Update tunnel dst according to Geneve options. */
- opts = ip_tunnel_info_opts(&tun_dst->u.tun_info,
- gnvh->opt_len * 4);
- memcpy(opts, gnvh->options, gnvh->opt_len * 4);
+ ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
+ gnvh->options, gnvh->opt_len * 4);
} else {
/* Drop packets w/ critical options,
* since we don't support any...
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 */
/* 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);
}
netdev_dbg(dev, "no tunnel metadata\n");
goto tx_error;
}
+ if (info && ip_tunnel_info_af(info) != AF_INET)
+ goto tx_error;
}
rt = geneve_get_rt(skb, dev, &fl4, info);
tunnel_id_to_vni(key->tun_id, vni);
if (key->tun_flags & TUNNEL_GENEVE_OPT)
- opts = ip_tunnel_info_opts(info, info->options_len);
+ opts = ip_tunnel_info_opts(info);
udp_csum = !!(key->tun_flags & TUNNEL_CSUM);
err = geneve_build_skb(rt, skb, key->tun_flags, vni,