xref: /linux/net/ipv4/ip_gre.c (revision 5832c4a77d6931cebf9ba737129ae8f14b66ee1d)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	Linux NET3:	GRE over IP protocol decoder.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *	Authors: Alexey Kuznetsov (kuznet@ms2.inr.ac.ru)
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds 
8afd46503SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9afd46503SJoe Perches 
104fc268d2SRandy Dunlap #include <linux/capability.h>
111da177e4SLinus Torvalds #include <linux/module.h>
121da177e4SLinus Torvalds #include <linux/types.h>
131da177e4SLinus Torvalds #include <linux/kernel.h>
145a0e3ad6STejun Heo #include <linux/slab.h>
157c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
161da177e4SLinus Torvalds #include <linux/skbuff.h>
171da177e4SLinus Torvalds #include <linux/netdevice.h>
181da177e4SLinus Torvalds #include <linux/in.h>
191da177e4SLinus Torvalds #include <linux/tcp.h>
201da177e4SLinus Torvalds #include <linux/udp.h>
211da177e4SLinus Torvalds #include <linux/if_arp.h>
222e15ea39SPravin B Shelar #include <linux/if_vlan.h>
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/in6.h>
251da177e4SLinus Torvalds #include <linux/inetdevice.h>
261da177e4SLinus Torvalds #include <linux/igmp.h>
271da177e4SLinus Torvalds #include <linux/netfilter_ipv4.h>
28e1a80002SHerbert Xu #include <linux/etherdevice.h>
2946f25dffSKris Katterjohn #include <linux/if_ether.h>
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds #include <net/sock.h>
321da177e4SLinus Torvalds #include <net/ip.h>
331da177e4SLinus Torvalds #include <net/icmp.h>
341da177e4SLinus Torvalds #include <net/protocol.h>
35c5441932SPravin B Shelar #include <net/ip_tunnels.h>
361da177e4SLinus Torvalds #include <net/arp.h>
371da177e4SLinus Torvalds #include <net/checksum.h>
381da177e4SLinus Torvalds #include <net/dsfield.h>
391da177e4SLinus Torvalds #include <net/inet_ecn.h>
401da177e4SLinus Torvalds #include <net/xfrm.h>
4159a4c759SPavel Emelyanov #include <net/net_namespace.h>
4259a4c759SPavel Emelyanov #include <net/netns/generic.h>
43c19e654dSHerbert Xu #include <net/rtnetlink.h>
4400959adeSDmitry Kozlov #include <net/gre.h>
452e15ea39SPravin B Shelar #include <net/dst_metadata.h>
4684e54fe0SWilliam Tu #include <net/erspan.h>
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds /*
491da177e4SLinus Torvalds    Problems & solutions
501da177e4SLinus Torvalds    --------------------
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds    1. The most important issue is detecting local dead loops.
531da177e4SLinus Torvalds    They would cause complete host lockup in transmit, which
541da177e4SLinus Torvalds    would be "resolved" by stack overflow or, if queueing is enabled,
551da177e4SLinus Torvalds    with infinite looping in net_bh.
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds    We cannot track such dead loops during route installation,
581da177e4SLinus Torvalds    it is infeasible task. The most general solutions would be
591da177e4SLinus Torvalds    to keep skb->encapsulation counter (sort of local ttl),
606d0722a2SEric Dumazet    and silently drop packet when it expires. It is a good
61bff52857Sstephen hemminger    solution, but it supposes maintaining new variable in ALL
621da177e4SLinus Torvalds    skb, even if no tunneling is used.
631da177e4SLinus Torvalds 
646d0722a2SEric Dumazet    Current solution: xmit_recursion breaks dead loops. This is a percpu
656d0722a2SEric Dumazet    counter, since when we enter the first ndo_xmit(), cpu migration is
666d0722a2SEric Dumazet    forbidden. We force an exit if this counter reaches RECURSION_LIMIT
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds    2. Networking dead loops would not kill routers, but would really
691da177e4SLinus Torvalds    kill network. IP hop limit plays role of "t->recursion" in this case,
701da177e4SLinus Torvalds    if we copy it from packet being encapsulated to upper header.
711da177e4SLinus Torvalds    It is very good solution, but it introduces two problems:
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds    - Routing protocols, using packets with ttl=1 (OSPF, RIP2),
741da177e4SLinus Torvalds      do not work over tunnels.
751da177e4SLinus Torvalds    - traceroute does not work. I planned to relay ICMP from tunnel,
761da177e4SLinus Torvalds      so that this problem would be solved and traceroute output
771da177e4SLinus Torvalds      would even more informative. This idea appeared to be wrong:
781da177e4SLinus Torvalds      only Linux complies to rfc1812 now (yes, guys, Linux is the only
791da177e4SLinus Torvalds      true router now :-)), all routers (at least, in neighbourhood of mine)
801da177e4SLinus Torvalds      return only 8 bytes of payload. It is the end.
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds    Hence, if we want that OSPF worked or traceroute said something reasonable,
831da177e4SLinus Torvalds    we should search for another solution.
841da177e4SLinus Torvalds 
851da177e4SLinus Torvalds    One of them is to parse packet trying to detect inner encapsulation
861da177e4SLinus Torvalds    made by our node. It is difficult or even impossible, especially,
87bff52857Sstephen hemminger    taking into account fragmentation. TO be short, ttl is not solution at all.
881da177e4SLinus Torvalds 
891da177e4SLinus Torvalds    Current solution: The solution was UNEXPECTEDLY SIMPLE.
901da177e4SLinus Torvalds    We force DF flag on tunnels with preconfigured hop limit,
911da177e4SLinus Torvalds    that is ALL. :-) Well, it does not remove the problem completely,
921da177e4SLinus Torvalds    but exponential growth of network traffic is changed to linear
931da177e4SLinus Torvalds    (branches, that exceed pmtu are pruned) and tunnel mtu
94bff52857Sstephen hemminger    rapidly degrades to value <68, where looping stops.
951da177e4SLinus Torvalds    Yes, it is not good if there exists a router in the loop,
961da177e4SLinus Torvalds    which does not force DF, even when encapsulating packets have DF set.
971da177e4SLinus Torvalds    But it is not our problem! Nobody could accuse us, we made
981da177e4SLinus Torvalds    all that we could make. Even if it is your gated who injected
991da177e4SLinus Torvalds    fatal route to network, even if it were you who configured
1001da177e4SLinus Torvalds    fatal static route: you are innocent. :-)
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds    Alexey Kuznetsov.
1031da177e4SLinus Torvalds  */
1041da177e4SLinus Torvalds 
105eccc1bb8Sstephen hemminger static bool log_ecn_error = true;
106eccc1bb8Sstephen hemminger module_param(log_ecn_error, bool, 0644);
107eccc1bb8Sstephen hemminger MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
108eccc1bb8Sstephen hemminger 
109c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly;
110aab1e898SGuillaume Nault static const struct header_ops ipgre_header_ops;
111aab1e898SGuillaume Nault 
1121da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev);
1131a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb,
114c69de58bSWilliam Tu 				u32 id, u32 index,
115a3222dc9SWilliam Tu 				bool truncate, bool is_ipv4);
116eb8ce741SPavel Emelyanov 
117c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly;
118c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly;
11984e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly;
120eb8ce741SPavel Emelyanov 
12132bbd879SStefano Brivio static int ipgre_err(struct sk_buff *skb, u32 info,
122bda7bb46SPravin B Shelar 		     const struct tnl_ptk_info *tpi)
1231da177e4SLinus Torvalds {
1241da177e4SLinus Torvalds 
125071f92d0SRami Rosen 	/* All the routers (except for Linux) return only
1261da177e4SLinus Torvalds 	   8 bytes of packet payload. It means, that precise relaying of
1271da177e4SLinus Torvalds 	   ICMP in the real Internet is absolutely infeasible.
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 	   Moreover, Cisco "wise men" put GRE key to the third word
130c5441932SPravin B Shelar 	   in GRE header. It makes impossible maintaining even soft
131c5441932SPravin B Shelar 	   state for keyed GRE tunnels with enabled checksum. Tell
132c5441932SPravin B Shelar 	   them "thank you".
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	   Well, I wonder, rfc1812 was written by Cisco employee,
135bff52857Sstephen hemminger 	   what the hell these idiots break standards established
136bff52857Sstephen hemminger 	   by themselves???
1371da177e4SLinus Torvalds 	   */
138c5441932SPravin B Shelar 	struct net *net = dev_net(skb->dev);
139c5441932SPravin B Shelar 	struct ip_tunnel_net *itn;
14096f5a846SEric Dumazet 	const struct iphdr *iph;
14188c7664fSArnaldo Carvalho de Melo 	const int type = icmp_hdr(skb)->type;
14288c7664fSArnaldo Carvalho de Melo 	const int code = icmp_hdr(skb)->code;
14320e1954fSEric Dumazet 	unsigned int data_len = 0;
1441da177e4SLinus Torvalds 	struct ip_tunnel *t;
145d2083287Sstephen hemminger 
146bda7bb46SPravin B Shelar 	if (tpi->proto == htons(ETH_P_TEB))
147c5441932SPravin B Shelar 		itn = net_generic(net, gre_tap_net_id);
14851dc63e3SHaishuang Yan 	else if (tpi->proto == htons(ETH_P_ERSPAN) ||
14951dc63e3SHaishuang Yan 		 tpi->proto == htons(ETH_P_ERSPAN2))
15051dc63e3SHaishuang Yan 		itn = net_generic(net, erspan_net_id);
151c5441932SPravin B Shelar 	else
152c5441932SPravin B Shelar 		itn = net_generic(net, ipgre_net_id);
153c5441932SPravin B Shelar 
154c0c0c50fSDuan Jiong 	iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
155bda7bb46SPravin B Shelar 	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
156bda7bb46SPravin B Shelar 			     iph->daddr, iph->saddr, tpi->key);
157d2083287Sstephen hemminger 
15851456b29SIan Morris 	if (!t)
15932bbd879SStefano Brivio 		return -ENOENT;
16032bbd879SStefano Brivio 
16132bbd879SStefano Brivio 	switch (type) {
16232bbd879SStefano Brivio 	default:
16332bbd879SStefano Brivio 	case ICMP_PARAMETERPROB:
16432bbd879SStefano Brivio 		return 0;
16532bbd879SStefano Brivio 
16632bbd879SStefano Brivio 	case ICMP_DEST_UNREACH:
16732bbd879SStefano Brivio 		switch (code) {
16832bbd879SStefano Brivio 		case ICMP_SR_FAILED:
16932bbd879SStefano Brivio 		case ICMP_PORT_UNREACH:
17032bbd879SStefano Brivio 			/* Impossible event. */
17132bbd879SStefano Brivio 			return 0;
17232bbd879SStefano Brivio 		default:
17332bbd879SStefano Brivio 			/* All others are translated to HOST_UNREACH.
17432bbd879SStefano Brivio 			   rfc2003 contains "deep thoughts" about NET_UNREACH,
17532bbd879SStefano Brivio 			   I believe they are just ether pollution. --ANK
17632bbd879SStefano Brivio 			 */
17732bbd879SStefano Brivio 			break;
17832bbd879SStefano Brivio 		}
17932bbd879SStefano Brivio 		break;
18032bbd879SStefano Brivio 
18132bbd879SStefano Brivio 	case ICMP_TIME_EXCEEDED:
18232bbd879SStefano Brivio 		if (code != ICMP_EXC_TTL)
18332bbd879SStefano Brivio 			return 0;
18432bbd879SStefano Brivio 		data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
18532bbd879SStefano Brivio 		break;
18632bbd879SStefano Brivio 
18732bbd879SStefano Brivio 	case ICMP_REDIRECT:
18832bbd879SStefano Brivio 		break;
18932bbd879SStefano Brivio 	}
19036393395SDavid S. Miller 
1919b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6)
1929b8c6d7bSEric Dumazet 	if (tpi->proto == htons(ETH_P_IPV6) &&
19320e1954fSEric Dumazet 	    !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
19420e1954fSEric Dumazet 					type, data_len))
19532bbd879SStefano Brivio 		return 0;
1969b8c6d7bSEric Dumazet #endif
1979b8c6d7bSEric Dumazet 
19836393395SDavid S. Miller 	if (t->parms.iph.daddr == 0 ||
199f97c1e0cSJoe Perches 	    ipv4_is_multicast(t->parms.iph.daddr))
20032bbd879SStefano Brivio 		return 0;
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds 	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
20332bbd879SStefano Brivio 		return 0;
2041da177e4SLinus Torvalds 
205da6185d8SWei Yongjun 	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
2061da177e4SLinus Torvalds 		t->err_count++;
2071da177e4SLinus Torvalds 	else
2081da177e4SLinus Torvalds 		t->err_count = 1;
2091da177e4SLinus Torvalds 	t->err_time = jiffies;
21032bbd879SStefano Brivio 
21132bbd879SStefano Brivio 	return 0;
2129f57c67cSPravin B Shelar }
2139f57c67cSPravin B Shelar 
2149f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info)
2159f57c67cSPravin B Shelar {
2169f57c67cSPravin B Shelar 	/* All the routers (except for Linux) return only
2179f57c67cSPravin B Shelar 	 * 8 bytes of packet payload. It means, that precise relaying of
2189f57c67cSPravin B Shelar 	 * ICMP in the real Internet is absolutely infeasible.
2199f57c67cSPravin B Shelar 	 *
2209f57c67cSPravin B Shelar 	 * Moreover, Cisco "wise men" put GRE key to the third word
2219f57c67cSPravin B Shelar 	 * in GRE header. It makes impossible maintaining even soft
2229f57c67cSPravin B Shelar 	 * state for keyed
2239f57c67cSPravin B Shelar 	 * GRE tunnels with enabled checksum. Tell them "thank you".
2249f57c67cSPravin B Shelar 	 *
2259f57c67cSPravin B Shelar 	 * Well, I wonder, rfc1812 was written by Cisco employee,
2269f57c67cSPravin B Shelar 	 * what the hell these idiots break standards established
2279f57c67cSPravin B Shelar 	 * by themselves???
2289f57c67cSPravin B Shelar 	 */
2299f57c67cSPravin B Shelar 
230e582615aSEric Dumazet 	const struct iphdr *iph = (struct iphdr *)skb->data;
2319f57c67cSPravin B Shelar 	const int type = icmp_hdr(skb)->type;
2329f57c67cSPravin B Shelar 	const int code = icmp_hdr(skb)->code;
2339f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
2349f57c67cSPravin B Shelar 
235b0350d51SHaishuang Yan 	if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP),
236b0350d51SHaishuang Yan 			     iph->ihl * 4) < 0)
2379f57c67cSPravin B Shelar 		return;
2389f57c67cSPravin B Shelar 
2399f57c67cSPravin B Shelar 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
2409f57c67cSPravin B Shelar 		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
241d888f396SMaciej Żenczykowski 				 skb->dev->ifindex, IPPROTO_GRE);
2429f57c67cSPravin B Shelar 		return;
2439f57c67cSPravin B Shelar 	}
2449f57c67cSPravin B Shelar 	if (type == ICMP_REDIRECT) {
2451042caa7SMaciej Żenczykowski 		ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex,
2461042caa7SMaciej Żenczykowski 			      IPPROTO_GRE);
2479f57c67cSPravin B Shelar 		return;
2489f57c67cSPravin B Shelar 	}
2499f57c67cSPravin B Shelar 
2509f57c67cSPravin B Shelar 	ipgre_err(skb, info, &tpi);
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds 
253f989d546SWilliam Tu static bool is_erspan_type1(int gre_hdr_len)
254f989d546SWilliam Tu {
255f989d546SWilliam Tu 	/* Both ERSPAN type I (version 0) and type II (version 1) use
256f989d546SWilliam Tu 	 * protocol 0x88BE, but the type I has only 4-byte GRE header,
257f989d546SWilliam Tu 	 * while type II has 8-byte.
258f989d546SWilliam Tu 	 */
259f989d546SWilliam Tu 	return gre_hdr_len == 4;
260f989d546SWilliam Tu }
261f989d546SWilliam Tu 
26284e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
26384e54fe0SWilliam Tu 		      int gre_hdr_len)
26484e54fe0SWilliam Tu {
26584e54fe0SWilliam Tu 	struct net *net = dev_net(skb->dev);
26684e54fe0SWilliam Tu 	struct metadata_dst *tun_dst = NULL;
2671d7e2ed2SWilliam Tu 	struct erspan_base_hdr *ershdr;
268*5832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(flags);
26984e54fe0SWilliam Tu 	struct ip_tunnel_net *itn;
27084e54fe0SWilliam Tu 	struct ip_tunnel *tunnel;
27184e54fe0SWilliam Tu 	const struct iphdr *iph;
2723df19283SWilliam Tu 	struct erspan_md2 *md2;
2731d7e2ed2SWilliam Tu 	int ver;
27484e54fe0SWilliam Tu 	int len;
27584e54fe0SWilliam Tu 
276*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(flags, tpi->flags);
277*5832c4a7SAlexander Lobakin 
27884e54fe0SWilliam Tu 	itn = net_generic(net, erspan_net_id);
27984e54fe0SWilliam Tu 	iph = ip_hdr(skb);
280f989d546SWilliam Tu 	if (is_erspan_type1(gre_hdr_len)) {
281f989d546SWilliam Tu 		ver = 0;
282*5832c4a7SAlexander Lobakin 		__set_bit(IP_TUNNEL_NO_KEY_BIT, flags);
283*5832c4a7SAlexander Lobakin 		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, flags,
284f989d546SWilliam Tu 					  iph->saddr, iph->daddr, 0);
285f989d546SWilliam Tu 	} else {
2861d7e2ed2SWilliam Tu 		ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
287c69de58bSWilliam Tu 		ver = ershdr->ver;
288*5832c4a7SAlexander Lobakin 		__set_bit(IP_TUNNEL_KEY_BIT, flags);
289*5832c4a7SAlexander Lobakin 		tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, flags,
29084e54fe0SWilliam Tu 					  iph->saddr, iph->daddr, tpi->key);
291f989d546SWilliam Tu 	}
29284e54fe0SWilliam Tu 
29384e54fe0SWilliam Tu 	if (tunnel) {
294f989d546SWilliam Tu 		if (is_erspan_type1(gre_hdr_len))
295f989d546SWilliam Tu 			len = gre_hdr_len;
296f989d546SWilliam Tu 		else
2971d7e2ed2SWilliam Tu 			len = gre_hdr_len + erspan_hdr_len(ver);
298f989d546SWilliam Tu 
2991d7e2ed2SWilliam Tu 		if (unlikely(!pskb_may_pull(skb, len)))
300ae3e1337SWilliam Tu 			return PACKET_REJECT;
3011d7e2ed2SWilliam Tu 
30284e54fe0SWilliam Tu 		if (__iptunnel_pull_header(skb,
3031d7e2ed2SWilliam Tu 					   len,
30484e54fe0SWilliam Tu 					   htons(ETH_P_TEB),
30584e54fe0SWilliam Tu 					   false, false) < 0)
30684e54fe0SWilliam Tu 			goto drop;
30784e54fe0SWilliam Tu 
3081a66a836SWilliam Tu 		if (tunnel->collect_md) {
309492b67e2SLorenzo Bianconi 			struct erspan_metadata *pkt_md, *md;
3101a66a836SWilliam Tu 			struct ip_tunnel_info *info;
311492b67e2SLorenzo Bianconi 			unsigned char *gh;
3121a66a836SWilliam Tu 			__be64 tun_id;
3131a66a836SWilliam Tu 
314*5832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_KEY_BIT, tpi->flags);
315*5832c4a7SAlexander Lobakin 			ip_tunnel_flags_copy(flags, tpi->flags);
3161a66a836SWilliam Tu 			tun_id = key32_to_tunnel_id(tpi->key);
3171a66a836SWilliam Tu 
3181a66a836SWilliam Tu 			tun_dst = ip_tun_rx_dst(skb, flags,
3191a66a836SWilliam Tu 						tun_id, sizeof(*md));
3201a66a836SWilliam Tu 			if (!tun_dst)
3211a66a836SWilliam Tu 				return PACKET_REJECT;
3221a66a836SWilliam Tu 
323492b67e2SLorenzo Bianconi 			/* skb can be uncloned in __iptunnel_pull_header, so
324492b67e2SLorenzo Bianconi 			 * old pkt_md is no longer valid and we need to reset
325492b67e2SLorenzo Bianconi 			 * it
326492b67e2SLorenzo Bianconi 			 */
327492b67e2SLorenzo Bianconi 			gh = skb_network_header(skb) +
328492b67e2SLorenzo Bianconi 			     skb_network_header_len(skb);
329492b67e2SLorenzo Bianconi 			pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
330492b67e2SLorenzo Bianconi 							    sizeof(*ershdr));
3311a66a836SWilliam Tu 			md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
332f551c91dSWilliam Tu 			md->version = ver;
3333df19283SWilliam Tu 			md2 = &md->u.md2;
3343df19283SWilliam Tu 			memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE :
3353df19283SWilliam Tu 						       ERSPAN_V2_MDSIZE);
336f551c91dSWilliam Tu 
3371a66a836SWilliam Tu 			info = &tun_dst->u.tun_info;
338*5832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_ERSPAN_OPT_BIT,
339*5832c4a7SAlexander Lobakin 				  info->key.tun_flags);
3401a66a836SWilliam Tu 			info->options_len = sizeof(*md);
3411a66a836SWilliam Tu 		}
3421a66a836SWilliam Tu 
34384e54fe0SWilliam Tu 		skb_reset_mac_header(skb);
34484e54fe0SWilliam Tu 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
34584e54fe0SWilliam Tu 		return PACKET_RCVD;
34684e54fe0SWilliam Tu 	}
3475a64506bSHaishuang Yan 	return PACKET_REJECT;
3485a64506bSHaishuang Yan 
34984e54fe0SWilliam Tu drop:
35084e54fe0SWilliam Tu 	kfree_skb(skb);
35184e54fe0SWilliam Tu 	return PACKET_RCVD;
35284e54fe0SWilliam Tu }
35384e54fe0SWilliam Tu 
354125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
355125372faSJiri Benc 		       struct ip_tunnel_net *itn, int hdr_len, bool raw_proto)
3561da177e4SLinus Torvalds {
3572e15ea39SPravin B Shelar 	struct metadata_dst *tun_dst = NULL;
358b71d1d42SEric Dumazet 	const struct iphdr *iph;
3591da177e4SLinus Torvalds 	struct ip_tunnel *tunnel;
3601da177e4SLinus Torvalds 
361eddc9ec5SArnaldo Carvalho de Melo 	iph = ip_hdr(skb);
362bda7bb46SPravin B Shelar 	tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
363bda7bb46SPravin B Shelar 				  iph->saddr, iph->daddr, tpi->key);
3641da177e4SLinus Torvalds 
365d2083287Sstephen hemminger 	if (tunnel) {
366c0d59da7Swenxu 		const struct iphdr *tnl_params;
367c0d59da7Swenxu 
368125372faSJiri Benc 		if (__iptunnel_pull_header(skb, hdr_len, tpi->proto,
369125372faSJiri Benc 					   raw_proto, false) < 0)
370244a797bSJiri Benc 			goto drop;
371244a797bSJiri Benc 
372aab1e898SGuillaume Nault 		/* Special case for ipgre_header_parse(), which expects the
373aab1e898SGuillaume Nault 		 * mac_header to point to the outer IP header.
374aab1e898SGuillaume Nault 		 */
375aab1e898SGuillaume Nault 		if (tunnel->dev->header_ops == &ipgre_header_ops)
3760e3da5bbSTimo Teräs 			skb_pop_mac_header(skb);
377e271c7b4SJiri Benc 		else
378e271c7b4SJiri Benc 			skb_reset_mac_header(skb);
379c0d59da7Swenxu 
380c0d59da7Swenxu 		tnl_params = &tunnel->parms.iph;
381c0d59da7Swenxu 		if (tunnel->collect_md || tnl_params->daddr == 0) {
382*5832c4a7SAlexander Lobakin 			IP_TUNNEL_DECLARE_FLAGS(flags) = { };
383c29a70d2SPravin B Shelar 			__be64 tun_id;
3842e15ea39SPravin B Shelar 
385*5832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_CSUM_BIT, flags);
386*5832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_KEY_BIT, flags);
387*5832c4a7SAlexander Lobakin 			ip_tunnel_flags_and(flags, tpi->flags, flags);
388*5832c4a7SAlexander Lobakin 
389d817f432SAmir Vadai 			tun_id = key32_to_tunnel_id(tpi->key);
390c29a70d2SPravin B Shelar 			tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0);
3912e15ea39SPravin B Shelar 			if (!tun_dst)
3922e15ea39SPravin B Shelar 				return PACKET_REJECT;
3932e15ea39SPravin B Shelar 		}
3942e15ea39SPravin B Shelar 
3952e15ea39SPravin B Shelar 		ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error);
396bda7bb46SPravin B Shelar 		return PACKET_RCVD;
3971da177e4SLinus Torvalds 	}
398125372faSJiri Benc 	return PACKET_NEXT;
399244a797bSJiri Benc 
400244a797bSJiri Benc drop:
401244a797bSJiri Benc 	kfree_skb(skb);
402244a797bSJiri Benc 	return PACKET_RCVD;
4031da177e4SLinus Torvalds }
4041da177e4SLinus Torvalds 
405125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
406125372faSJiri Benc 		     int hdr_len)
407125372faSJiri Benc {
408125372faSJiri Benc 	struct net *net = dev_net(skb->dev);
409125372faSJiri Benc 	struct ip_tunnel_net *itn;
410125372faSJiri Benc 	int res;
411125372faSJiri Benc 
412125372faSJiri Benc 	if (tpi->proto == htons(ETH_P_TEB))
413125372faSJiri Benc 		itn = net_generic(net, gre_tap_net_id);
414125372faSJiri Benc 	else
415125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
416125372faSJiri Benc 
417125372faSJiri Benc 	res = __ipgre_rcv(skb, tpi, itn, hdr_len, false);
418125372faSJiri Benc 	if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) {
419125372faSJiri Benc 		/* ipgre tunnels in collect metadata mode should receive
420125372faSJiri Benc 		 * also ETH_P_TEB traffic.
421125372faSJiri Benc 		 */
422125372faSJiri Benc 		itn = net_generic(net, ipgre_net_id);
423125372faSJiri Benc 		res = __ipgre_rcv(skb, tpi, itn, hdr_len, true);
424125372faSJiri Benc 	}
425125372faSJiri Benc 	return res;
426125372faSJiri Benc }
427125372faSJiri Benc 
4289f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb)
4299f57c67cSPravin B Shelar {
4309f57c67cSPravin B Shelar 	struct tnl_ptk_info tpi;
4319f57c67cSPravin B Shelar 	bool csum_err = false;
43295f5c64cSTom Herbert 	int hdr_len;
4339f57c67cSPravin B Shelar 
4349f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST
4359f57c67cSPravin B Shelar 	if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
4369f57c67cSPravin B Shelar 		/* Looped back packet, drop it! */
4379f57c67cSPravin B Shelar 		if (rt_is_output_route(skb_rtable(skb)))
4389f57c67cSPravin B Shelar 			goto drop;
4399f57c67cSPravin B Shelar 	}
4409f57c67cSPravin B Shelar #endif
4419f57c67cSPravin B Shelar 
442e582615aSEric Dumazet 	hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0);
443f132ae7cSJiri Benc 	if (hdr_len < 0)
44495f5c64cSTom Herbert 		goto drop;
44595f5c64cSTom Herbert 
446f551c91dSWilliam Tu 	if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
447f551c91dSWilliam Tu 		     tpi.proto == htons(ETH_P_ERSPAN2))) {
44884e54fe0SWilliam Tu 		if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
44984e54fe0SWilliam Tu 			return 0;
450dd8d5b8cSHaishuang Yan 		goto out;
45184e54fe0SWilliam Tu 	}
45284e54fe0SWilliam Tu 
453244a797bSJiri Benc 	if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
4549f57c67cSPravin B Shelar 		return 0;
4559f57c67cSPravin B Shelar 
456dd8d5b8cSHaishuang Yan out:
4579f57c67cSPravin B Shelar 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
4589f57c67cSPravin B Shelar drop:
4599f57c67cSPravin B Shelar 	kfree_skb(skb);
4609f57c67cSPravin B Shelar 	return 0;
4619f57c67cSPravin B Shelar }
4629f57c67cSPravin B Shelar 
463c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
464c5441932SPravin B Shelar 		       const struct iphdr *tnl_params,
465c5441932SPravin B Shelar 		       __be16 proto)
466c5441932SPravin B Shelar {
467c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
468*5832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(flags);
469*5832c4a7SAlexander Lobakin 
470*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(flags, tunnel->parms.o_flags);
471cef401deSEric Dumazet 
472c5441932SPravin B Shelar 	/* Push GRE header. */
473182a352dSTom Herbert 	gre_build_header(skb, tunnel->tun_hlen,
474ff827bebSPeilin Ye 			 flags, proto, tunnel->parms.o_key,
475*5832c4a7SAlexander Lobakin 			 test_bit(IP_TUNNEL_SEQ_BIT, flags) ?
476*5832c4a7SAlexander Lobakin 			 htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0);
4771da177e4SLinus Torvalds 
478bf3d6a8fSNicolas Dichtel 	ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol);
4791da177e4SLinus Torvalds }
4801da177e4SLinus Torvalds 
481aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum)
482b2acd1dcSPravin B Shelar {
4836fa79666SEdward Cree 	return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
484b2acd1dcSPravin B Shelar }
485b2acd1dcSPravin B Shelar 
486862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
487862a03c3SWilliam Tu 			__be16 proto)
488862a03c3SWilliam Tu {
48977a5196aSWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
490*5832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(flags) = { };
491862a03c3SWilliam Tu 	struct ip_tunnel_info *tun_info;
492862a03c3SWilliam Tu 	const struct ip_tunnel_key *key;
493862a03c3SWilliam Tu 	int tunnel_hlen;
494862a03c3SWilliam Tu 
495862a03c3SWilliam Tu 	tun_info = skb_tunnel_info(skb);
496862a03c3SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
497862a03c3SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
498862a03c3SWilliam Tu 		goto err_free_skb;
499862a03c3SWilliam Tu 
500862a03c3SWilliam Tu 	key = &tun_info->key;
501862a03c3SWilliam Tu 	tunnel_hlen = gre_calc_hlen(key->tun_flags);
502862a03c3SWilliam Tu 
503962924faSwenxu 	if (skb_cow_head(skb, dev->needed_headroom))
504962924faSwenxu 		goto err_free_skb;
5052e15ea39SPravin B Shelar 
5062e15ea39SPravin B Shelar 	/* Push Tunnel header. */
507*5832c4a7SAlexander Lobakin 	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
508*5832c4a7SAlexander Lobakin 					      tunnel->parms.o_flags)))
509962924faSwenxu 		goto err_free_skb;
5102e15ea39SPravin B Shelar 
511*5832c4a7SAlexander Lobakin 	__set_bit(IP_TUNNEL_CSUM_BIT, flags);
512*5832c4a7SAlexander Lobakin 	__set_bit(IP_TUNNEL_KEY_BIT, flags);
513*5832c4a7SAlexander Lobakin 	__set_bit(IP_TUNNEL_SEQ_BIT, flags);
514*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_and(flags, tun_info->key.tun_flags, flags);
515*5832c4a7SAlexander Lobakin 
516cba65321SDavid S. Miller 	gre_build_header(skb, tunnel_hlen, flags, proto,
51777a5196aSWilliam Tu 			 tunnel_id_to_key32(tun_info->key.tun_id),
518*5832c4a7SAlexander Lobakin 			 test_bit(IP_TUNNEL_SEQ_BIT, flags) ?
519*5832c4a7SAlexander Lobakin 			 htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0);
5202e15ea39SPravin B Shelar 
521962924faSwenxu 	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
522039f5062SPravin B Shelar 
5232e15ea39SPravin B Shelar 	return;
5242e15ea39SPravin B Shelar 
5252e15ea39SPravin B Shelar err_free_skb:
5262e15ea39SPravin B Shelar 	kfree_skb(skb);
527c4794d22SEric Dumazet 	DEV_STATS_INC(dev, tx_dropped);
5282e15ea39SPravin B Shelar }
5292e15ea39SPravin B Shelar 
53020704bd1SXin Long static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
5311a66a836SWilliam Tu {
5321a66a836SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
533*5832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(flags) = { };
5341a66a836SWilliam Tu 	struct ip_tunnel_info *tun_info;
5351a66a836SWilliam Tu 	const struct ip_tunnel_key *key;
5361a66a836SWilliam Tu 	struct erspan_metadata *md;
5371a66a836SWilliam Tu 	bool truncate = false;
538962924faSwenxu 	__be16 proto;
5391a66a836SWilliam Tu 	int tunnel_hlen;
540f551c91dSWilliam Tu 	int version;
5411baf5ebfSWilliam Tu 	int nhoff;
5421a66a836SWilliam Tu 
5431a66a836SWilliam Tu 	tun_info = skb_tunnel_info(skb);
5441a66a836SWilliam Tu 	if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) ||
5451a66a836SWilliam Tu 		     ip_tunnel_info_af(tun_info) != AF_INET))
5461a66a836SWilliam Tu 		goto err_free_skb;
5471a66a836SWilliam Tu 
5481a66a836SWilliam Tu 	key = &tun_info->key;
549*5832c4a7SAlexander Lobakin 	if (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info->key.tun_flags))
550962924faSwenxu 		goto err_free_skb;
5512eb8d6d2SXin Long 	if (tun_info->options_len < sizeof(*md))
552962924faSwenxu 		goto err_free_skb;
5532eb8d6d2SXin Long 	md = ip_tunnel_info_opts(tun_info);
5541a66a836SWilliam Tu 
5551a66a836SWilliam Tu 	/* ERSPAN has fixed 8 byte GRE header */
556f551c91dSWilliam Tu 	version = md->version;
557f551c91dSWilliam Tu 	tunnel_hlen = 8 + erspan_hdr_len(version);
5581a66a836SWilliam Tu 
559962924faSwenxu 	if (skb_cow_head(skb, dev->needed_headroom))
560962924faSwenxu 		goto err_free_skb;
5611a66a836SWilliam Tu 
5621a66a836SWilliam Tu 	if (gre_handle_offloads(skb, false))
563962924faSwenxu 		goto err_free_skb;
5641a66a836SWilliam Tu 
565f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
56602d84f3eSYuanjun Gong 		if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
56702d84f3eSYuanjun Gong 			goto err_free_skb;
5681a66a836SWilliam Tu 		truncate = true;
5691a66a836SWilliam Tu 	}
5701a66a836SWilliam Tu 
5718e50ed77SEric Dumazet 	nhoff = skb_network_offset(skb);
5721baf5ebfSWilliam Tu 	if (skb->protocol == htons(ETH_P_IP) &&
5731baf5ebfSWilliam Tu 	    (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
5741baf5ebfSWilliam Tu 		truncate = true;
5751baf5ebfSWilliam Tu 
576301bd140SEric Dumazet 	if (skb->protocol == htons(ETH_P_IPV6)) {
577301bd140SEric Dumazet 		int thoff;
578301bd140SEric Dumazet 
579301bd140SEric Dumazet 		if (skb_transport_header_was_set(skb))
5808e50ed77SEric Dumazet 			thoff = skb_transport_offset(skb);
581301bd140SEric Dumazet 		else
582301bd140SEric Dumazet 			thoff = nhoff + sizeof(struct ipv6hdr);
583301bd140SEric Dumazet 		if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
584d5db21a3SWilliam Tu 			truncate = true;
585301bd140SEric Dumazet 	}
586d5db21a3SWilliam Tu 
587f551c91dSWilliam Tu 	if (version == 1) {
588c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
5891d7e2ed2SWilliam Tu 				    ntohl(md->u.index), truncate, true);
59020704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
591f551c91dSWilliam Tu 	} else if (version == 2) {
592c69de58bSWilliam Tu 		erspan_build_header_v2(skb,
593c69de58bSWilliam Tu 				       ntohl(tunnel_id_to_key32(key->tun_id)),
594c69de58bSWilliam Tu 				       md->u.md2.dir,
595c69de58bSWilliam Tu 				       get_hwid(&md->u.md2),
596c69de58bSWilliam Tu 				       truncate, true);
59720704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
598f551c91dSWilliam Tu 	} else {
599962924faSwenxu 		goto err_free_skb;
600f551c91dSWilliam Tu 	}
6011a66a836SWilliam Tu 
602*5832c4a7SAlexander Lobakin 	__set_bit(IP_TUNNEL_SEQ_BIT, flags);
603*5832c4a7SAlexander Lobakin 	gre_build_header(skb, 8, flags, proto, 0,
604*5832c4a7SAlexander Lobakin 			 htonl(atomic_fetch_inc(&tunnel->o_seqno)));
6051a66a836SWilliam Tu 
606962924faSwenxu 	ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen);
6071a66a836SWilliam Tu 
6081a66a836SWilliam Tu 	return;
6091a66a836SWilliam Tu 
6101a66a836SWilliam Tu err_free_skb:
6111a66a836SWilliam Tu 	kfree_skb(skb);
612c4794d22SEric Dumazet 	DEV_STATS_INC(dev, tx_dropped);
6131a66a836SWilliam Tu }
6141a66a836SWilliam Tu 
615fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
616fc4099f1SPravin B Shelar {
617fc4099f1SPravin B Shelar 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
618962924faSwenxu 	const struct ip_tunnel_key *key;
619fc4099f1SPravin B Shelar 	struct rtable *rt;
620fc4099f1SPravin B Shelar 	struct flowi4 fl4;
621fc4099f1SPravin B Shelar 
622fc4099f1SPravin B Shelar 	if (ip_tunnel_info_af(info) != AF_INET)
623fc4099f1SPravin B Shelar 		return -EINVAL;
624fc4099f1SPravin B Shelar 
625962924faSwenxu 	key = &info->key;
626962924faSwenxu 	ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
627f7716b31SGuillaume Nault 			    tunnel_id_to_key32(key->tun_id),
628db53cd3dSDavid Ahern 			    key->tos & ~INET_ECN_MASK, dev_net(dev), 0,
6297ec9fce4SEyal Birger 			    skb->mark, skb_get_hash(skb), key->flow_flags);
630962924faSwenxu 	rt = ip_route_output_key(dev_net(dev), &fl4);
631fc4099f1SPravin B Shelar 	if (IS_ERR(rt))
632fc4099f1SPravin B Shelar 		return PTR_ERR(rt);
633fc4099f1SPravin B Shelar 
634fc4099f1SPravin B Shelar 	ip_rt_put(rt);
635fc4099f1SPravin B Shelar 	info->key.u.ipv4.src = fl4.saddr;
636fc4099f1SPravin B Shelar 	return 0;
637fc4099f1SPravin B Shelar }
638fc4099f1SPravin B Shelar 
639c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
640c5441932SPravin B Shelar 			      struct net_device *dev)
641ee34c1ebSMichal Schmidt {
642c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
643c5441932SPravin B Shelar 	const struct iphdr *tnl_params;
644ee34c1ebSMichal Schmidt 
645cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
646cb9f1b78SWillem de Bruijn 		goto free_skb;
647cb9f1b78SWillem de Bruijn 
6482e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
6492090714eSJiri Benc 		gre_fb_xmit(skb, dev, skb->protocol);
6502e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
6512e15ea39SPravin B Shelar 	}
6522e15ea39SPravin B Shelar 
653c5441932SPravin B Shelar 	if (dev->header_ops) {
65480d875cfSShigeru Yoshida 		int pull_len = tunnel->hlen + sizeof(struct iphdr);
65580d875cfSShigeru Yoshida 
656fdafed45SCong Wang 		if (skb_cow_head(skb, 0))
657c5441932SPravin B Shelar 			goto free_skb;
658ee34c1ebSMichal Schmidt 
659c5441932SPravin B Shelar 		tnl_params = (const struct iphdr *)skb->data;
660cbb1e85fSDavid S. Miller 
66180d875cfSShigeru Yoshida 		if (!pskb_network_may_pull(skb, pull_len))
66280d875cfSShigeru Yoshida 			goto free_skb;
66380d875cfSShigeru Yoshida 
66480d875cfSShigeru Yoshida 		/* ip_tunnel_xmit() needs skb->data pointing to gre header. */
66580d875cfSShigeru Yoshida 		skb_pull(skb, pull_len);
6668a0033a9STimo Teräs 		skb_reset_mac_header(skb);
6678d21e996SWillem de Bruijn 
6688d21e996SWillem de Bruijn 		if (skb->ip_summed == CHECKSUM_PARTIAL &&
6698d21e996SWillem de Bruijn 		    skb_checksum_start(skb) < skb->data)
6708d21e996SWillem de Bruijn 			goto free_skb;
671c5441932SPravin B Shelar 	} else {
672c5441932SPravin B Shelar 		if (skb_cow_head(skb, dev->needed_headroom))
673c5441932SPravin B Shelar 			goto free_skb;
674c5441932SPravin B Shelar 
675c5441932SPravin B Shelar 		tnl_params = &tunnel->parms.iph;
676ee34c1ebSMichal Schmidt 	}
677e1a80002SHerbert Xu 
678*5832c4a7SAlexander Lobakin 	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
679*5832c4a7SAlexander Lobakin 					      tunnel->parms.o_flags)))
680aed069dfSAlexander Duyck 		goto free_skb;
6818a0033a9STimo Teräs 
682c5441932SPravin B Shelar 	__gre_xmit(skb, dev, tnl_params, skb->protocol);
683c5441932SPravin B Shelar 	return NETDEV_TX_OK;
684c5441932SPravin B Shelar 
685c5441932SPravin B Shelar free_skb:
6863acfa1e7SEric Dumazet 	kfree_skb(skb);
687c4794d22SEric Dumazet 	DEV_STATS_INC(dev, tx_dropped);
688c5441932SPravin B Shelar 	return NETDEV_TX_OK;
689ee34c1ebSMichal Schmidt }
690ee34c1ebSMichal Schmidt 
69184e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb,
69284e54fe0SWilliam Tu 			       struct net_device *dev)
69384e54fe0SWilliam Tu {
69484e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
69584e54fe0SWilliam Tu 	bool truncate = false;
69620704bd1SXin Long 	__be16 proto;
69784e54fe0SWilliam Tu 
698cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
699cb9f1b78SWillem de Bruijn 		goto free_skb;
700cb9f1b78SWillem de Bruijn 
7011a66a836SWilliam Tu 	if (tunnel->collect_md) {
70220704bd1SXin Long 		erspan_fb_xmit(skb, dev);
7031a66a836SWilliam Tu 		return NETDEV_TX_OK;
7041a66a836SWilliam Tu 	}
7051a66a836SWilliam Tu 
70684e54fe0SWilliam Tu 	if (gre_handle_offloads(skb, false))
70784e54fe0SWilliam Tu 		goto free_skb;
70884e54fe0SWilliam Tu 
70984e54fe0SWilliam Tu 	if (skb_cow_head(skb, dev->needed_headroom))
71084e54fe0SWilliam Tu 		goto free_skb;
71184e54fe0SWilliam Tu 
712f192970dSWilliam Tu 	if (skb->len > dev->mtu + dev->hard_header_len) {
713aa7cb378SYuanjun Gong 		if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
714aa7cb378SYuanjun Gong 			goto free_skb;
71584e54fe0SWilliam Tu 		truncate = true;
71684e54fe0SWilliam Tu 	}
71784e54fe0SWilliam Tu 
71884e54fe0SWilliam Tu 	/* Push ERSPAN header */
719f989d546SWilliam Tu 	if (tunnel->erspan_ver == 0) {
720f989d546SWilliam Tu 		proto = htons(ETH_P_ERSPAN);
721*5832c4a7SAlexander Lobakin 		__clear_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags);
722f989d546SWilliam Tu 	} else if (tunnel->erspan_ver == 1) {
723c69de58bSWilliam Tu 		erspan_build_header(skb, ntohl(tunnel->parms.o_key),
724c69de58bSWilliam Tu 				    tunnel->index,
725a3222dc9SWilliam Tu 				    truncate, true);
72620704bd1SXin Long 		proto = htons(ETH_P_ERSPAN);
72720704bd1SXin Long 	} else if (tunnel->erspan_ver == 2) {
728c69de58bSWilliam Tu 		erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
729f551c91dSWilliam Tu 				       tunnel->dir, tunnel->hwid,
730f551c91dSWilliam Tu 				       truncate, true);
73120704bd1SXin Long 		proto = htons(ETH_P_ERSPAN2);
73220704bd1SXin Long 	} else {
73302f99df1SWilliam Tu 		goto free_skb;
73420704bd1SXin Long 	}
735f551c91dSWilliam Tu 
736*5832c4a7SAlexander Lobakin 	__clear_bit(IP_TUNNEL_KEY_BIT, tunnel->parms.o_flags);
73720704bd1SXin Long 	__gre_xmit(skb, dev, &tunnel->parms.iph, proto);
73884e54fe0SWilliam Tu 	return NETDEV_TX_OK;
73984e54fe0SWilliam Tu 
74084e54fe0SWilliam Tu free_skb:
74184e54fe0SWilliam Tu 	kfree_skb(skb);
742c4794d22SEric Dumazet 	DEV_STATS_INC(dev, tx_dropped);
74384e54fe0SWilliam Tu 	return NETDEV_TX_OK;
74484e54fe0SWilliam Tu }
74584e54fe0SWilliam Tu 
746c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
747c5441932SPravin B Shelar 				struct net_device *dev)
748c5441932SPravin B Shelar {
749c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
750ee34c1ebSMichal Schmidt 
751cb9f1b78SWillem de Bruijn 	if (!pskb_inet_may_pull(skb))
752cb9f1b78SWillem de Bruijn 		goto free_skb;
753cb9f1b78SWillem de Bruijn 
7542e15ea39SPravin B Shelar 	if (tunnel->collect_md) {
7552090714eSJiri Benc 		gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
7562e15ea39SPravin B Shelar 		return NETDEV_TX_OK;
7572e15ea39SPravin B Shelar 	}
7582e15ea39SPravin B Shelar 
759*5832c4a7SAlexander Lobakin 	if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT,
760*5832c4a7SAlexander Lobakin 					      tunnel->parms.o_flags)))
761aed069dfSAlexander Duyck 		goto free_skb;
762ee34c1ebSMichal Schmidt 
763c5441932SPravin B Shelar 	if (skb_cow_head(skb, dev->needed_headroom))
764c5441932SPravin B Shelar 		goto free_skb;
76542aa9162SHerbert Xu 
766c5441932SPravin B Shelar 	__gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB));
767c5441932SPravin B Shelar 	return NETDEV_TX_OK;
768c5441932SPravin B Shelar 
769c5441932SPravin B Shelar free_skb:
7703acfa1e7SEric Dumazet 	kfree_skb(skb);
771c4794d22SEric Dumazet 	DEV_STATS_INC(dev, tx_dropped);
772c5441932SPravin B Shelar 	return NETDEV_TX_OK;
77368c33163SPravin B Shelar }
774ee34c1ebSMichal Schmidt 
775dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu)
776dd9d598cSXin Long {
777dd9d598cSXin Long 	struct ip_tunnel *tunnel = netdev_priv(dev);
778dd9d598cSXin Long 	int len;
779dd9d598cSXin Long 
780dd9d598cSXin Long 	len = tunnel->tun_hlen;
781dd9d598cSXin Long 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
782dd9d598cSXin Long 	len = tunnel->tun_hlen - len;
783dd9d598cSXin Long 	tunnel->hlen = tunnel->hlen + len;
784dd9d598cSXin Long 
785fdafed45SCong Wang 	if (dev->header_ops)
786fdafed45SCong Wang 		dev->hard_header_len += len;
787fdafed45SCong Wang 	else
788fdafed45SCong Wang 		dev->needed_headroom += len;
789fdafed45SCong Wang 
790dd9d598cSXin Long 	if (set_mtu)
791dd9d598cSXin Long 		dev->mtu = max_t(int, dev->mtu - len, 68);
792dd9d598cSXin Long 
793*5832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags) ||
794*5832c4a7SAlexander Lobakin 	    (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.o_flags) &&
795*5832c4a7SAlexander Lobakin 	     tunnel->encap.type != TUNNEL_ENCAP_NONE)) {
7961cc5954fSSabrina Dubroca 		dev->features &= ~NETIF_F_GSO_SOFTWARE;
7971cc5954fSSabrina Dubroca 		dev->hw_features &= ~NETIF_F_GSO_SOFTWARE;
7981cc5954fSSabrina Dubroca 	} else {
799020e8f60SPeilin Ye 		dev->features |= NETIF_F_GSO_SOFTWARE;
800020e8f60SPeilin Ye 		dev->hw_features |= NETIF_F_GSO_SOFTWARE;
801dd9d598cSXin Long 	}
802dd9d598cSXin Long }
803dd9d598cSXin Long 
804117aef12SAlexander Lobakin static int ipgre_tunnel_ctl(struct net_device *dev,
805117aef12SAlexander Lobakin 			    struct ip_tunnel_parm_kern *p,
806607259a6SChristoph Hellwig 			    int cmd)
8071da177e4SLinus Torvalds {
808*5832c4a7SAlexander Lobakin 	__be16 i_flags, o_flags;
809a0efab67SXin Long 	int err;
8101da177e4SLinus Torvalds 
811*5832c4a7SAlexander Lobakin 	if (!ip_tunnel_flags_is_be16_compat(p->i_flags) ||
812*5832c4a7SAlexander Lobakin 	    !ip_tunnel_flags_is_be16_compat(p->o_flags))
813*5832c4a7SAlexander Lobakin 		return -EOVERFLOW;
814*5832c4a7SAlexander Lobakin 
815*5832c4a7SAlexander Lobakin 	i_flags = ip_tunnel_flags_to_be16(p->i_flags);
816*5832c4a7SAlexander Lobakin 	o_flags = ip_tunnel_flags_to_be16(p->o_flags);
817*5832c4a7SAlexander Lobakin 
8186c734fb8SCong Wang 	if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) {
819607259a6SChristoph Hellwig 		if (p->iph.version != 4 || p->iph.protocol != IPPROTO_GRE ||
820607259a6SChristoph Hellwig 		    p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)) ||
821*5832c4a7SAlexander Lobakin 		    ((i_flags | o_flags) & (GRE_VERSION | GRE_ROUTING)))
8221da177e4SLinus Torvalds 			return -EINVAL;
823c5441932SPravin B Shelar 	}
824a0efab67SXin Long 
825*5832c4a7SAlexander Lobakin 	gre_flags_to_tnl_flags(p->i_flags, i_flags);
826*5832c4a7SAlexander Lobakin 	gre_flags_to_tnl_flags(p->o_flags, o_flags);
827c5441932SPravin B Shelar 
828607259a6SChristoph Hellwig 	err = ip_tunnel_ctl(dev, p, cmd);
829c5441932SPravin B Shelar 	if (err)
830c5441932SPravin B Shelar 		return err;
831c5441932SPravin B Shelar 
832a0efab67SXin Long 	if (cmd == SIOCCHGTUNNEL) {
833a0efab67SXin Long 		struct ip_tunnel *t = netdev_priv(dev);
834a0efab67SXin Long 
835*5832c4a7SAlexander Lobakin 		ip_tunnel_flags_copy(t->parms.i_flags, p->i_flags);
836*5832c4a7SAlexander Lobakin 		ip_tunnel_flags_copy(t->parms.o_flags, p->o_flags);
837a0efab67SXin Long 
838a0efab67SXin Long 		if (strcmp(dev->rtnl_link_ops->kind, "erspan"))
839a0efab67SXin Long 			ipgre_link_update(dev, true);
840a0efab67SXin Long 	}
841a0efab67SXin Long 
842*5832c4a7SAlexander Lobakin 	i_flags = gre_tnl_flags_to_gre_flags(p->i_flags);
843*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_from_be16(p->i_flags, i_flags);
844*5832c4a7SAlexander Lobakin 	o_flags = gre_tnl_flags_to_gre_flags(p->o_flags);
845*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_from_be16(p->o_flags, o_flags);
846*5832c4a7SAlexander Lobakin 
8471da177e4SLinus Torvalds 	return 0;
8481da177e4SLinus Torvalds }
8491da177e4SLinus Torvalds 
8501da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-)
8511da177e4SLinus Torvalds    It allows to construct virtual multiprotocol broadcast "LAN"
8521da177e4SLinus Torvalds    over the Internet, provided multicast routing is tuned.
8531da177e4SLinus Torvalds 
8541da177e4SLinus Torvalds 
8551da177e4SLinus Torvalds    I have no idea was this bicycle invented before me,
8561da177e4SLinus Torvalds    so that I had to set ARPHRD_IPGRE to a random value.
8571da177e4SLinus Torvalds    I have an impression, that Cisco could make something similar,
8581da177e4SLinus Torvalds    but this feature is apparently missing in IOS<=11.2(8).
8591da177e4SLinus Torvalds 
8601da177e4SLinus Torvalds    I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks
8611da177e4SLinus Torvalds    with broadcast 224.66.66.66. If you have access to mbone, play with me :-)
8621da177e4SLinus Torvalds 
8631da177e4SLinus Torvalds    ping -t 255 224.66.66.66
8641da177e4SLinus Torvalds 
8651da177e4SLinus Torvalds    If nobody answers, mbone does not work.
8661da177e4SLinus Torvalds 
8671da177e4SLinus Torvalds    ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255
8681da177e4SLinus Torvalds    ip addr add 10.66.66.<somewhat>/24 dev Universe
8691da177e4SLinus Torvalds    ifconfig Universe up
8701da177e4SLinus Torvalds    ifconfig Universe add fe80::<Your_real_addr>/10
8711da177e4SLinus Torvalds    ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96
8721da177e4SLinus Torvalds    ftp 10.66.66.66
8731da177e4SLinus Torvalds    ...
8741da177e4SLinus Torvalds    ftp fec0:6666:6666::193.233.7.65
8751da177e4SLinus Torvalds    ...
8761da177e4SLinus Torvalds  */
8773b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
8783b04dddeSStephen Hemminger 			unsigned short type,
8791507850bSEric Dumazet 			const void *daddr, const void *saddr, unsigned int len)
8801da177e4SLinus Torvalds {
8812941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
882c5441932SPravin B Shelar 	struct iphdr *iph;
883c5441932SPravin B Shelar 	struct gre_base_hdr *greh;
884c5441932SPravin B Shelar 
885d58ff351SJohannes Berg 	iph = skb_push(skb, t->hlen + sizeof(*iph));
886c5441932SPravin B Shelar 	greh = (struct gre_base_hdr *)(iph+1);
88795f5c64cSTom Herbert 	greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags);
888c5441932SPravin B Shelar 	greh->protocol = htons(type);
8891da177e4SLinus Torvalds 
8901da177e4SLinus Torvalds 	memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
8911da177e4SLinus Torvalds 
892c5441932SPravin B Shelar 	/* Set the source hardware address. */
8931da177e4SLinus Torvalds 	if (saddr)
8941da177e4SLinus Torvalds 		memcpy(&iph->saddr, saddr, 4);
8956d55cb91STimo Teräs 	if (daddr)
8961da177e4SLinus Torvalds 		memcpy(&iph->daddr, daddr, 4);
8976d55cb91STimo Teräs 	if (iph->daddr)
89877a482bdSTimo Teräs 		return t->hlen + sizeof(*iph);
8991da177e4SLinus Torvalds 
900c5441932SPravin B Shelar 	return -(t->hlen + sizeof(*iph));
9011da177e4SLinus Torvalds }
9021da177e4SLinus Torvalds 
9036a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
9046a5f44d7STimo Teras {
905b71d1d42SEric Dumazet 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
9066a5f44d7STimo Teras 	memcpy(haddr, &iph->saddr, 4);
9076a5f44d7STimo Teras 	return 4;
9086a5f44d7STimo Teras }
9096a5f44d7STimo Teras 
9103b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = {
9113b04dddeSStephen Hemminger 	.create	= ipgre_header,
9126a5f44d7STimo Teras 	.parse	= ipgre_header_parse,
9133b04dddeSStephen Hemminger };
9143b04dddeSStephen Hemminger 
9156a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST
9161da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev)
9171da177e4SLinus Torvalds {
9182941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
9191da177e4SLinus Torvalds 
920f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
921cbb1e85fSDavid S. Miller 		struct flowi4 fl4;
922cbb1e85fSDavid S. Miller 		struct rtable *rt;
923cbb1e85fSDavid S. Miller 
924b57708adSNicolas Dichtel 		rt = ip_route_output_gre(t->net, &fl4,
92578fbfd8aSDavid S. Miller 					 t->parms.iph.daddr,
92678fbfd8aSDavid S. Miller 					 t->parms.iph.saddr,
92778fbfd8aSDavid S. Miller 					 t->parms.o_key,
92878fbfd8aSDavid S. Miller 					 RT_TOS(t->parms.iph.tos),
92978fbfd8aSDavid S. Miller 					 t->parms.link);
930b23dd4feSDavid S. Miller 		if (IS_ERR(rt))
9311da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
932d8d1f30bSChangli Gao 		dev = rt->dst.dev;
9331da177e4SLinus Torvalds 		ip_rt_put(rt);
93451456b29SIan Morris 		if (!__in_dev_get_rtnl(dev))
9351da177e4SLinus Torvalds 			return -EADDRNOTAVAIL;
9361da177e4SLinus Torvalds 		t->mlink = dev->ifindex;
937e5ed6399SHerbert Xu 		ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr);
9381da177e4SLinus Torvalds 	}
9391da177e4SLinus Torvalds 	return 0;
9401da177e4SLinus Torvalds }
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev)
9431da177e4SLinus Torvalds {
9442941a486SPatrick McHardy 	struct ip_tunnel *t = netdev_priv(dev);
945b8c26a33SStephen Hemminger 
946f97c1e0cSJoe Perches 	if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) {
9477fee0ca2SDenis V. Lunev 		struct in_device *in_dev;
948b57708adSNicolas Dichtel 		in_dev = inetdev_by_index(t->net, t->mlink);
9498723e1b4SEric Dumazet 		if (in_dev)
9501da177e4SLinus Torvalds 			ip_mc_dec_group(in_dev, t->parms.iph.daddr);
9511da177e4SLinus Torvalds 	}
9521da177e4SLinus Torvalds 	return 0;
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds #endif
9551da177e4SLinus Torvalds 
956b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = {
957b8c26a33SStephen Hemminger 	.ndo_init		= ipgre_tunnel_init,
958c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
959b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST
960b8c26a33SStephen Hemminger 	.ndo_open		= ipgre_open,
961b8c26a33SStephen Hemminger 	.ndo_stop		= ipgre_close,
962b8c26a33SStephen Hemminger #endif
963c5441932SPravin B Shelar 	.ndo_start_xmit		= ipgre_xmit,
9643e7a1c7cSArnd Bergmann 	.ndo_siocdevprivate	= ip_tunnel_siocdevprivate,
965c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
96698d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
9671e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
968607259a6SChristoph Hellwig 	.ndo_tunnel_ctl		= ipgre_tunnel_ctl,
969b8c26a33SStephen Hemminger };
970b8c26a33SStephen Hemminger 
9716b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG |		\
9726b78f16eSEric Dumazet 		      NETIF_F_FRAGLIST |	\
9736b78f16eSEric Dumazet 		      NETIF_F_HIGHDMA |		\
9746b78f16eSEric Dumazet 		      NETIF_F_HW_CSUM)
9756b78f16eSEric Dumazet 
9761da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev)
9771da177e4SLinus Torvalds {
978b8c26a33SStephen Hemminger 	dev->netdev_ops		= &ipgre_netdev_ops;
9795a455275SNicolas Dichtel 	dev->type		= ARPHRD_IPGRE;
980c5441932SPravin B Shelar 	ip_tunnel_setup(dev, ipgre_net_id);
981c5441932SPravin B Shelar }
9821da177e4SLinus Torvalds 
983c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev)
984c5441932SPravin B Shelar {
985c5441932SPravin B Shelar 	struct ip_tunnel *tunnel;
986c5441932SPravin B Shelar 
987c5441932SPravin B Shelar 	tunnel = netdev_priv(dev);
98895f5c64cSTom Herbert 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
989c5441932SPravin B Shelar 	tunnel->parms.iph.protocol = IPPROTO_GRE;
990c5441932SPravin B Shelar 
9914565e991STom Herbert 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
992fdafed45SCong Wang 	dev->needed_headroom = tunnel->hlen + sizeof(tunnel->parms.iph);
9934565e991STom Herbert 
994020e8f60SPeilin Ye 	dev->features		|= GRE_FEATURES | NETIF_F_LLTX;
9956b78f16eSEric Dumazet 	dev->hw_features	|= GRE_FEATURES;
996c5441932SPravin B Shelar 
997020e8f60SPeilin Ye 	/* TCP offload with GRE SEQ is not supported, nor can we support 2
998020e8f60SPeilin Ye 	 * levels of outer headers requiring an update.
999a0ca153fSAlexander Duyck 	 */
1000*5832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags))
1001020e8f60SPeilin Ye 		return;
1002*5832c4a7SAlexander Lobakin 	if (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.o_flags) &&
1003*5832c4a7SAlexander Lobakin 	    tunnel->encap.type != TUNNEL_ENCAP_NONE)
1004020e8f60SPeilin Ye 		return;
1005020e8f60SPeilin Ye 
1006c5441932SPravin B Shelar 	dev->features |= NETIF_F_GSO_SOFTWARE;
1007c5441932SPravin B Shelar 	dev->hw_features |= NETIF_F_GSO_SOFTWARE;
1008a0ca153fSAlexander Duyck }
1009a0ca153fSAlexander Duyck 
10101da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev)
10111da177e4SLinus Torvalds {
1012c5441932SPravin B Shelar 	struct ip_tunnel *tunnel = netdev_priv(dev);
1013c5441932SPravin B Shelar 	struct iphdr *iph = &tunnel->parms.iph;
10141da177e4SLinus Torvalds 
1015c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
10161da177e4SLinus Torvalds 
10175a1b7e1aSJakub Kicinski 	__dev_addr_set(dev, &iph->saddr, 4);
1018c5441932SPravin B Shelar 	memcpy(dev->broadcast, &iph->daddr, 4);
10191da177e4SLinus Torvalds 
1020c5441932SPravin B Shelar 	dev->flags		= IFF_NOARP;
102102875878SEric Dumazet 	netif_keep_dst(dev);
1022c5441932SPravin B Shelar 	dev->addr_len		= 4;
10231da177e4SLinus Torvalds 
1024a64b04d8SJiri Benc 	if (iph->daddr && !tunnel->collect_md) {
10251da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST
1026f97c1e0cSJoe Perches 		if (ipv4_is_multicast(iph->daddr)) {
10271da177e4SLinus Torvalds 			if (!iph->saddr)
10281da177e4SLinus Torvalds 				return -EINVAL;
10291da177e4SLinus Torvalds 			dev->flags = IFF_BROADCAST;
10303b04dddeSStephen Hemminger 			dev->header_ops = &ipgre_header_ops;
1031fdafed45SCong Wang 			dev->hard_header_len = tunnel->hlen + sizeof(*iph);
1032fdafed45SCong Wang 			dev->needed_headroom = 0;
10331da177e4SLinus Torvalds 		}
10341da177e4SLinus Torvalds #endif
1035a64b04d8SJiri Benc 	} else if (!tunnel->collect_md) {
10366a5f44d7STimo Teras 		dev->header_ops = &ipgre_header_ops;
1037fdafed45SCong Wang 		dev->hard_header_len = tunnel->hlen + sizeof(*iph);
1038fdafed45SCong Wang 		dev->needed_headroom = 0;
1039a64b04d8SJiri Benc 	}
10401da177e4SLinus Torvalds 
1041c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
104260769a5dSEric Dumazet }
104360769a5dSEric Dumazet 
10449f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = {
10459f57c67cSPravin B Shelar 	.handler     = gre_rcv,
10469f57c67cSPravin B Shelar 	.err_handler = gre_err,
10471da177e4SLinus Torvalds };
10481da177e4SLinus Torvalds 
10492c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net)
105059a4c759SPavel Emelyanov {
1051c5441932SPravin B Shelar 	return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL);
105259a4c759SPavel Emelyanov }
105359a4c759SPavel Emelyanov 
10549b5b3637SEric Dumazet static void __net_exit ipgre_exit_batch_rtnl(struct list_head *list_net,
10559b5b3637SEric Dumazet 					     struct list_head *dev_to_kill)
105659a4c759SPavel Emelyanov {
10579b5b3637SEric Dumazet 	ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops,
10589b5b3637SEric Dumazet 			      dev_to_kill);
105959a4c759SPavel Emelyanov }
106059a4c759SPavel Emelyanov 
106159a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = {
106259a4c759SPavel Emelyanov 	.init = ipgre_init_net,
10639b5b3637SEric Dumazet 	.exit_batch_rtnl = ipgre_exit_batch_rtnl,
1064cfb8fbf2SEric W. Biederman 	.id   = &ipgre_net_id,
1065c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
106659a4c759SPavel Emelyanov };
10671da177e4SLinus Torvalds 
1068a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
1069a8b8a889SMatthias Schiffer 				 struct netlink_ext_ack *extack)
1070c19e654dSHerbert Xu {
1071c19e654dSHerbert Xu 	__be16 flags;
1072c19e654dSHerbert Xu 
1073c19e654dSHerbert Xu 	if (!data)
1074c19e654dSHerbert Xu 		return 0;
1075c19e654dSHerbert Xu 
1076c19e654dSHerbert Xu 	flags = 0;
1077c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1078c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
1079c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1080c19e654dSHerbert Xu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
1081c19e654dSHerbert Xu 	if (flags & (GRE_VERSION|GRE_ROUTING))
1082c19e654dSHerbert Xu 		return -EINVAL;
1083c19e654dSHerbert Xu 
1084946b636fSJiri Benc 	if (data[IFLA_GRE_COLLECT_METADATA] &&
1085946b636fSJiri Benc 	    data[IFLA_GRE_ENCAP_TYPE] &&
1086946b636fSJiri Benc 	    nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE)
1087946b636fSJiri Benc 		return -EINVAL;
1088946b636fSJiri Benc 
1089c19e654dSHerbert Xu 	return 0;
1090c19e654dSHerbert Xu }
1091c19e654dSHerbert Xu 
1092a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
1093a8b8a889SMatthias Schiffer 			      struct netlink_ext_ack *extack)
1094e1a80002SHerbert Xu {
1095e1a80002SHerbert Xu 	__be32 daddr;
1096e1a80002SHerbert Xu 
1097e1a80002SHerbert Xu 	if (tb[IFLA_ADDRESS]) {
1098e1a80002SHerbert Xu 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1099e1a80002SHerbert Xu 			return -EINVAL;
1100e1a80002SHerbert Xu 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1101e1a80002SHerbert Xu 			return -EADDRNOTAVAIL;
1102e1a80002SHerbert Xu 	}
1103e1a80002SHerbert Xu 
1104e1a80002SHerbert Xu 	if (!data)
1105e1a80002SHerbert Xu 		goto out;
1106e1a80002SHerbert Xu 
1107e1a80002SHerbert Xu 	if (data[IFLA_GRE_REMOTE]) {
1108e1a80002SHerbert Xu 		memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1109e1a80002SHerbert Xu 		if (!daddr)
1110e1a80002SHerbert Xu 			return -EINVAL;
1111e1a80002SHerbert Xu 	}
1112e1a80002SHerbert Xu 
1113e1a80002SHerbert Xu out:
1114a8b8a889SMatthias Schiffer 	return ipgre_tunnel_validate(tb, data, extack);
1115e1a80002SHerbert Xu }
1116e1a80002SHerbert Xu 
111784e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[],
111884e54fe0SWilliam Tu 			   struct netlink_ext_ack *extack)
111984e54fe0SWilliam Tu {
112084e54fe0SWilliam Tu 	__be16 flags = 0;
112184e54fe0SWilliam Tu 	int ret;
112284e54fe0SWilliam Tu 
112384e54fe0SWilliam Tu 	if (!data)
112484e54fe0SWilliam Tu 		return 0;
112584e54fe0SWilliam Tu 
112684e54fe0SWilliam Tu 	ret = ipgre_tap_validate(tb, data, extack);
112784e54fe0SWilliam Tu 	if (ret)
112884e54fe0SWilliam Tu 		return ret;
112984e54fe0SWilliam Tu 
113051fa960dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER] &&
113151fa960dSWilliam Tu 	    nla_get_u8(data[IFLA_GRE_ERSPAN_VER]) == 0)
1132f989d546SWilliam Tu 		return 0;
1133f989d546SWilliam Tu 
1134f989d546SWilliam Tu 	/* ERSPAN type II/III should only have GRE sequence and key flag */
11351a66a836SWilliam Tu 	if (data[IFLA_GRE_OFLAGS])
113684e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]);
11371a66a836SWilliam Tu 	if (data[IFLA_GRE_IFLAGS])
113884e54fe0SWilliam Tu 		flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]);
11391a66a836SWilliam Tu 	if (!data[IFLA_GRE_COLLECT_METADATA] &&
11401a66a836SWilliam Tu 	    flags != (GRE_SEQ | GRE_KEY))
114184e54fe0SWilliam Tu 		return -EINVAL;
114284e54fe0SWilliam Tu 
114384e54fe0SWilliam Tu 	/* ERSPAN Session ID only has 10-bit. Since we reuse
114484e54fe0SWilliam Tu 	 * 32-bit key field as ID, check it's range.
114584e54fe0SWilliam Tu 	 */
114684e54fe0SWilliam Tu 	if (data[IFLA_GRE_IKEY] &&
114784e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK))
114884e54fe0SWilliam Tu 		return -EINVAL;
114984e54fe0SWilliam Tu 
115084e54fe0SWilliam Tu 	if (data[IFLA_GRE_OKEY] &&
115184e54fe0SWilliam Tu 	    (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK))
115284e54fe0SWilliam Tu 		return -EINVAL;
115384e54fe0SWilliam Tu 
115484e54fe0SWilliam Tu 	return 0;
115584e54fe0SWilliam Tu }
115684e54fe0SWilliam Tu 
115722a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev,
11582e15ea39SPravin B Shelar 				struct nlattr *data[],
11592e15ea39SPravin B Shelar 				struct nlattr *tb[],
1160117aef12SAlexander Lobakin 				struct ip_tunnel_parm_kern *parms,
11619830ad4cSCraig Gallek 				__u32 *fwmark)
1162c19e654dSHerbert Xu {
116322a59be8SPhilip Prindeville 	struct ip_tunnel *t = netdev_priv(dev);
116422a59be8SPhilip Prindeville 
11657bb82d92SHerbert Xu 	memset(parms, 0, sizeof(*parms));
1166c19e654dSHerbert Xu 
1167c19e654dSHerbert Xu 	parms->iph.protocol = IPPROTO_GRE;
1168c19e654dSHerbert Xu 
1169c19e654dSHerbert Xu 	if (!data)
117022a59be8SPhilip Prindeville 		return 0;
1171c19e654dSHerbert Xu 
1172c19e654dSHerbert Xu 	if (data[IFLA_GRE_LINK])
1173c19e654dSHerbert Xu 		parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
1174c19e654dSHerbert Xu 
1175c19e654dSHerbert Xu 	if (data[IFLA_GRE_IFLAGS])
1176*5832c4a7SAlexander Lobakin 		gre_flags_to_tnl_flags(parms->i_flags,
1177*5832c4a7SAlexander Lobakin 				       nla_get_be16(data[IFLA_GRE_IFLAGS]));
1178c19e654dSHerbert Xu 
1179c19e654dSHerbert Xu 	if (data[IFLA_GRE_OFLAGS])
1180*5832c4a7SAlexander Lobakin 		gre_flags_to_tnl_flags(parms->o_flags,
1181*5832c4a7SAlexander Lobakin 				       nla_get_be16(data[IFLA_GRE_OFLAGS]));
1182c19e654dSHerbert Xu 
1183c19e654dSHerbert Xu 	if (data[IFLA_GRE_IKEY])
1184c19e654dSHerbert Xu 		parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
1185c19e654dSHerbert Xu 
1186c19e654dSHerbert Xu 	if (data[IFLA_GRE_OKEY])
1187c19e654dSHerbert Xu 		parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]);
1188c19e654dSHerbert Xu 
1189c19e654dSHerbert Xu 	if (data[IFLA_GRE_LOCAL])
119067b61f6cSJiri Benc 		parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]);
1191c19e654dSHerbert Xu 
1192c19e654dSHerbert Xu 	if (data[IFLA_GRE_REMOTE])
119367b61f6cSJiri Benc 		parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]);
1194c19e654dSHerbert Xu 
1195c19e654dSHerbert Xu 	if (data[IFLA_GRE_TTL])
1196c19e654dSHerbert Xu 		parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]);
1197c19e654dSHerbert Xu 
1198c19e654dSHerbert Xu 	if (data[IFLA_GRE_TOS])
1199c19e654dSHerbert Xu 		parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]);
1200c19e654dSHerbert Xu 
120122a59be8SPhilip Prindeville 	if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) {
120222a59be8SPhilip Prindeville 		if (t->ignore_df)
120322a59be8SPhilip Prindeville 			return -EINVAL;
1204c19e654dSHerbert Xu 		parms->iph.frag_off = htons(IP_DF);
120522a59be8SPhilip Prindeville 	}
12062e15ea39SPravin B Shelar 
12072e15ea39SPravin B Shelar 	if (data[IFLA_GRE_COLLECT_METADATA]) {
12082e15ea39SPravin B Shelar 		t->collect_md = true;
1209e271c7b4SJiri Benc 		if (dev->type == ARPHRD_IPGRE)
1210e271c7b4SJiri Benc 			dev->type = ARPHRD_NONE;
12112e15ea39SPravin B Shelar 	}
121222a59be8SPhilip Prindeville 
121322a59be8SPhilip Prindeville 	if (data[IFLA_GRE_IGNORE_DF]) {
121422a59be8SPhilip Prindeville 		if (nla_get_u8(data[IFLA_GRE_IGNORE_DF])
121522a59be8SPhilip Prindeville 		  && (parms->iph.frag_off & htons(IP_DF)))
121622a59be8SPhilip Prindeville 			return -EINVAL;
121722a59be8SPhilip Prindeville 		t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]);
121822a59be8SPhilip Prindeville 	}
121922a59be8SPhilip Prindeville 
12209830ad4cSCraig Gallek 	if (data[IFLA_GRE_FWMARK])
12219830ad4cSCraig Gallek 		*fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]);
12229830ad4cSCraig Gallek 
1223e1f8f78fSPetr Machata 	return 0;
1224e1f8f78fSPetr Machata }
1225e1f8f78fSPetr Machata 
1226e1f8f78fSPetr Machata static int erspan_netlink_parms(struct net_device *dev,
1227e1f8f78fSPetr Machata 				struct nlattr *data[],
1228e1f8f78fSPetr Machata 				struct nlattr *tb[],
1229117aef12SAlexander Lobakin 				struct ip_tunnel_parm_kern *parms,
1230e1f8f78fSPetr Machata 				__u32 *fwmark)
1231e1f8f78fSPetr Machata {
1232e1f8f78fSPetr Machata 	struct ip_tunnel *t = netdev_priv(dev);
1233e1f8f78fSPetr Machata 	int err;
1234e1f8f78fSPetr Machata 
1235e1f8f78fSPetr Machata 	err = ipgre_netlink_parms(dev, data, tb, parms, fwmark);
1236e1f8f78fSPetr Machata 	if (err)
1237e1f8f78fSPetr Machata 		return err;
123832ca98feSPetr Machata 	if (!data)
123932ca98feSPetr Machata 		return 0;
1240e1f8f78fSPetr Machata 
1241f551c91dSWilliam Tu 	if (data[IFLA_GRE_ERSPAN_VER]) {
1242f551c91dSWilliam Tu 		t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
1243f551c91dSWilliam Tu 
1244f989d546SWilliam Tu 		if (t->erspan_ver > 2)
1245f551c91dSWilliam Tu 			return -EINVAL;
1246f551c91dSWilliam Tu 	}
1247f551c91dSWilliam Tu 
1248f551c91dSWilliam Tu 	if (t->erspan_ver == 1) {
124984e54fe0SWilliam Tu 		if (data[IFLA_GRE_ERSPAN_INDEX]) {
125084e54fe0SWilliam Tu 			t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
125184e54fe0SWilliam Tu 			if (t->index & ~INDEX_MASK)
125284e54fe0SWilliam Tu 				return -EINVAL;
125384e54fe0SWilliam Tu 		}
1254f551c91dSWilliam Tu 	} else if (t->erspan_ver == 2) {
1255f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_DIR]) {
1256f551c91dSWilliam Tu 			t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
1257f551c91dSWilliam Tu 			if (t->dir & ~(DIR_MASK >> DIR_OFFSET))
1258f551c91dSWilliam Tu 				return -EINVAL;
1259f551c91dSWilliam Tu 		}
1260f551c91dSWilliam Tu 		if (data[IFLA_GRE_ERSPAN_HWID]) {
1261f551c91dSWilliam Tu 			t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
1262f551c91dSWilliam Tu 			if (t->hwid & ~(HWID_MASK >> HWID_OFFSET))
1263f551c91dSWilliam Tu 				return -EINVAL;
1264f551c91dSWilliam Tu 		}
1265f551c91dSWilliam Tu 	}
126684e54fe0SWilliam Tu 
126722a59be8SPhilip Prindeville 	return 0;
1268c19e654dSHerbert Xu }
1269c19e654dSHerbert Xu 
12704565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */
12714565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[],
12724565e991STom Herbert 				      struct ip_tunnel_encap *ipencap)
12734565e991STom Herbert {
12744565e991STom Herbert 	bool ret = false;
12754565e991STom Herbert 
12764565e991STom Herbert 	memset(ipencap, 0, sizeof(*ipencap));
12774565e991STom Herbert 
12784565e991STom Herbert 	if (!data)
12794565e991STom Herbert 		return ret;
12804565e991STom Herbert 
12814565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_TYPE]) {
12824565e991STom Herbert 		ret = true;
12834565e991STom Herbert 		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
12844565e991STom Herbert 	}
12854565e991STom Herbert 
12864565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_FLAGS]) {
12874565e991STom Herbert 		ret = true;
12884565e991STom Herbert 		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
12894565e991STom Herbert 	}
12904565e991STom Herbert 
12914565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_SPORT]) {
12924565e991STom Herbert 		ret = true;
12933e97fa70SSabrina Dubroca 		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
12944565e991STom Herbert 	}
12954565e991STom Herbert 
12964565e991STom Herbert 	if (data[IFLA_GRE_ENCAP_DPORT]) {
12974565e991STom Herbert 		ret = true;
12983e97fa70SSabrina Dubroca 		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
12994565e991STom Herbert 	}
13004565e991STom Herbert 
13014565e991STom Herbert 	return ret;
13024565e991STom Herbert }
13034565e991STom Herbert 
1304c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev)
1305e1a80002SHerbert Xu {
1306c5441932SPravin B Shelar 	__gre_tunnel_init(dev);
1307bec94d43Sstephen hemminger 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
1308d51711c0SXin Long 	netif_keep_dst(dev);
1309e1a80002SHerbert Xu 
1310c5441932SPravin B Shelar 	return ip_tunnel_init(dev);
1311e1a80002SHerbert Xu }
1312e1a80002SHerbert Xu 
1313c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = {
1314c5441932SPravin B Shelar 	.ndo_init		= gre_tap_init,
1315c5441932SPravin B Shelar 	.ndo_uninit		= ip_tunnel_uninit,
1316c5441932SPravin B Shelar 	.ndo_start_xmit		= gre_tap_xmit,
1317b8c26a33SStephen Hemminger 	.ndo_set_mac_address 	= eth_mac_addr,
1318b8c26a33SStephen Hemminger 	.ndo_validate_addr	= eth_validate_addr,
1319c5441932SPravin B Shelar 	.ndo_change_mtu		= ip_tunnel_change_mtu,
132098d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
13211e99584bSNicolas Dichtel 	.ndo_get_iflink		= ip_tunnel_get_iflink,
1322fc4099f1SPravin B Shelar 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
1323b8c26a33SStephen Hemminger };
1324b8c26a33SStephen Hemminger 
132584e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev)
132684e54fe0SWilliam Tu {
132784e54fe0SWilliam Tu 	struct ip_tunnel *tunnel = netdev_priv(dev);
132884e54fe0SWilliam Tu 
1329f989d546SWilliam Tu 	if (tunnel->erspan_ver == 0)
1330f989d546SWilliam Tu 		tunnel->tun_hlen = 4; /* 4-byte GRE hdr. */
1331f989d546SWilliam Tu 	else
1332f989d546SWilliam Tu 		tunnel->tun_hlen = 8; /* 8-byte GRE hdr. */
1333f989d546SWilliam Tu 
133484e54fe0SWilliam Tu 	tunnel->parms.iph.protocol = IPPROTO_GRE;
1335c122fda2SXin Long 	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
1336f551c91dSWilliam Tu 		       erspan_hdr_len(tunnel->erspan_ver);
133784e54fe0SWilliam Tu 
133884e54fe0SWilliam Tu 	dev->features		|= GRE_FEATURES;
133984e54fe0SWilliam Tu 	dev->hw_features	|= GRE_FEATURES;
134084e54fe0SWilliam Tu 	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
1341c84bed44SXin Long 	netif_keep_dst(dev);
134284e54fe0SWilliam Tu 
134384e54fe0SWilliam Tu 	return ip_tunnel_init(dev);
134484e54fe0SWilliam Tu }
134584e54fe0SWilliam Tu 
134684e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = {
134784e54fe0SWilliam Tu 	.ndo_init		= erspan_tunnel_init,
134884e54fe0SWilliam Tu 	.ndo_uninit		= ip_tunnel_uninit,
134984e54fe0SWilliam Tu 	.ndo_start_xmit		= erspan_xmit,
135084e54fe0SWilliam Tu 	.ndo_set_mac_address	= eth_mac_addr,
135184e54fe0SWilliam Tu 	.ndo_validate_addr	= eth_validate_addr,
135284e54fe0SWilliam Tu 	.ndo_change_mtu		= ip_tunnel_change_mtu,
135398d7fc46SHeiner Kallweit 	.ndo_get_stats64	= dev_get_tstats64,
135484e54fe0SWilliam Tu 	.ndo_get_iflink		= ip_tunnel_get_iflink,
135584e54fe0SWilliam Tu 	.ndo_fill_metadata_dst	= gre_fill_metadata_dst,
135684e54fe0SWilliam Tu };
135784e54fe0SWilliam Tu 
1358e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev)
1359e1a80002SHerbert Xu {
1360e1a80002SHerbert Xu 	ether_setup(dev);
1361cfddd4c3SXin Long 	dev->max_mtu = 0;
1362c5441932SPravin B Shelar 	dev->netdev_ops	= &gre_tap_netdev_ops;
1363d13b161cSJiri Benc 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1364f8c1b7ceSstephen hemminger 	dev->priv_flags	|= IFF_LIVE_ADDR_CHANGE;
1365c5441932SPravin B Shelar 	ip_tunnel_setup(dev, gre_tap_net_id);
1366e1a80002SHerbert Xu }
1367e1a80002SHerbert Xu 
1368e1f8f78fSPetr Machata static int
1369e1f8f78fSPetr Machata ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[])
1370c19e654dSHerbert Xu {
13714565e991STom Herbert 	struct ip_tunnel_encap ipencap;
13724565e991STom Herbert 
13734565e991STom Herbert 	if (ipgre_netlink_encap_parms(data, &ipencap)) {
13744565e991STom Herbert 		struct ip_tunnel *t = netdev_priv(dev);
1375e1f8f78fSPetr Machata 		int err = ip_tunnel_encap_setup(t, &ipencap);
13764565e991STom Herbert 
13774565e991STom Herbert 		if (err < 0)
13784565e991STom Herbert 			return err;
13794565e991STom Herbert 	}
1380c19e654dSHerbert Xu 
1381e1f8f78fSPetr Machata 	return 0;
1382e1f8f78fSPetr Machata }
1383e1f8f78fSPetr Machata 
1384e1f8f78fSPetr Machata static int ipgre_newlink(struct net *src_net, struct net_device *dev,
1385e1f8f78fSPetr Machata 			 struct nlattr *tb[], struct nlattr *data[],
1386e1f8f78fSPetr Machata 			 struct netlink_ext_ack *extack)
1387e1f8f78fSPetr Machata {
1388117aef12SAlexander Lobakin 	struct ip_tunnel_parm_kern p;
1389e1f8f78fSPetr Machata 	__u32 fwmark = 0;
1390e1f8f78fSPetr Machata 	int err;
1391e1f8f78fSPetr Machata 
1392e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1393e1f8f78fSPetr Machata 	if (err)
1394e1f8f78fSPetr Machata 		return err;
1395e1f8f78fSPetr Machata 
13969830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
139722a59be8SPhilip Prindeville 	if (err < 0)
139822a59be8SPhilip Prindeville 		return err;
13999830ad4cSCraig Gallek 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1400c19e654dSHerbert Xu }
1401c19e654dSHerbert Xu 
1402e1f8f78fSPetr Machata static int erspan_newlink(struct net *src_net, struct net_device *dev,
1403e1f8f78fSPetr Machata 			  struct nlattr *tb[], struct nlattr *data[],
1404e1f8f78fSPetr Machata 			  struct netlink_ext_ack *extack)
1405e1f8f78fSPetr Machata {
1406117aef12SAlexander Lobakin 	struct ip_tunnel_parm_kern p;
1407e1f8f78fSPetr Machata 	__u32 fwmark = 0;
1408e1f8f78fSPetr Machata 	int err;
1409e1f8f78fSPetr Machata 
1410e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1411e1f8f78fSPetr Machata 	if (err)
1412e1f8f78fSPetr Machata 		return err;
1413e1f8f78fSPetr Machata 
1414e1f8f78fSPetr Machata 	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
1415e1f8f78fSPetr Machata 	if (err)
1416e1f8f78fSPetr Machata 		return err;
1417e1f8f78fSPetr Machata 	return ip_tunnel_newlink(dev, tb, &p, fwmark);
1418e1f8f78fSPetr Machata }
1419e1f8f78fSPetr Machata 
1420c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[],
1421ad744b22SMatthias Schiffer 			    struct nlattr *data[],
1422ad744b22SMatthias Schiffer 			    struct netlink_ext_ack *extack)
1423c19e654dSHerbert Xu {
14249830ad4cSCraig Gallek 	struct ip_tunnel *t = netdev_priv(dev);
1425117aef12SAlexander Lobakin 	struct ip_tunnel_parm_kern p;
14269830ad4cSCraig Gallek 	__u32 fwmark = t->fwmark;
142722a59be8SPhilip Prindeville 	int err;
14284565e991STom Herbert 
1429e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1430e1f8f78fSPetr Machata 	if (err)
14314565e991STom Herbert 		return err;
1432c19e654dSHerbert Xu 
14339830ad4cSCraig Gallek 	err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark);
143422a59be8SPhilip Prindeville 	if (err < 0)
143522a59be8SPhilip Prindeville 		return err;
1436dd9d598cSXin Long 
1437dd9d598cSXin Long 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1438dd9d598cSXin Long 	if (err < 0)
1439dd9d598cSXin Long 		return err;
1440dd9d598cSXin Long 
1441*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(t->parms.i_flags, p.i_flags);
1442*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(t->parms.o_flags, p.o_flags);
1443dd9d598cSXin Long 
1444dd9d598cSXin Long 	ipgre_link_update(dev, !tb[IFLA_MTU]);
1445dd9d598cSXin Long 
1446dd9d598cSXin Long 	return 0;
1447c19e654dSHerbert Xu }
1448c19e654dSHerbert Xu 
1449e1f8f78fSPetr Machata static int erspan_changelink(struct net_device *dev, struct nlattr *tb[],
1450e1f8f78fSPetr Machata 			     struct nlattr *data[],
1451e1f8f78fSPetr Machata 			     struct netlink_ext_ack *extack)
1452e1f8f78fSPetr Machata {
1453e1f8f78fSPetr Machata 	struct ip_tunnel *t = netdev_priv(dev);
1454117aef12SAlexander Lobakin 	struct ip_tunnel_parm_kern p;
1455e1f8f78fSPetr Machata 	__u32 fwmark = t->fwmark;
1456e1f8f78fSPetr Machata 	int err;
1457e1f8f78fSPetr Machata 
1458e1f8f78fSPetr Machata 	err = ipgre_newlink_encap_setup(dev, data);
1459e1f8f78fSPetr Machata 	if (err)
1460e1f8f78fSPetr Machata 		return err;
1461e1f8f78fSPetr Machata 
1462e1f8f78fSPetr Machata 	err = erspan_netlink_parms(dev, data, tb, &p, &fwmark);
1463e1f8f78fSPetr Machata 	if (err < 0)
1464e1f8f78fSPetr Machata 		return err;
1465e1f8f78fSPetr Machata 
1466e1f8f78fSPetr Machata 	err = ip_tunnel_changelink(dev, tb, &p, fwmark);
1467e1f8f78fSPetr Machata 	if (err < 0)
1468e1f8f78fSPetr Machata 		return err;
1469e1f8f78fSPetr Machata 
1470*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(t->parms.i_flags, p.i_flags);
1471*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(t->parms.o_flags, p.o_flags);
1472e1f8f78fSPetr Machata 
1473e1f8f78fSPetr Machata 	return 0;
1474e1f8f78fSPetr Machata }
1475e1f8f78fSPetr Machata 
1476c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev)
1477c19e654dSHerbert Xu {
1478c19e654dSHerbert Xu 	return
1479c19e654dSHerbert Xu 		/* IFLA_GRE_LINK */
1480c19e654dSHerbert Xu 		nla_total_size(4) +
1481c19e654dSHerbert Xu 		/* IFLA_GRE_IFLAGS */
1482c19e654dSHerbert Xu 		nla_total_size(2) +
1483c19e654dSHerbert Xu 		/* IFLA_GRE_OFLAGS */
1484c19e654dSHerbert Xu 		nla_total_size(2) +
1485c19e654dSHerbert Xu 		/* IFLA_GRE_IKEY */
1486c19e654dSHerbert Xu 		nla_total_size(4) +
1487c19e654dSHerbert Xu 		/* IFLA_GRE_OKEY */
1488c19e654dSHerbert Xu 		nla_total_size(4) +
1489c19e654dSHerbert Xu 		/* IFLA_GRE_LOCAL */
1490c19e654dSHerbert Xu 		nla_total_size(4) +
1491c19e654dSHerbert Xu 		/* IFLA_GRE_REMOTE */
1492c19e654dSHerbert Xu 		nla_total_size(4) +
1493c19e654dSHerbert Xu 		/* IFLA_GRE_TTL */
1494c19e654dSHerbert Xu 		nla_total_size(1) +
1495c19e654dSHerbert Xu 		/* IFLA_GRE_TOS */
1496c19e654dSHerbert Xu 		nla_total_size(1) +
1497c19e654dSHerbert Xu 		/* IFLA_GRE_PMTUDISC */
1498c19e654dSHerbert Xu 		nla_total_size(1) +
14994565e991STom Herbert 		/* IFLA_GRE_ENCAP_TYPE */
15004565e991STom Herbert 		nla_total_size(2) +
15014565e991STom Herbert 		/* IFLA_GRE_ENCAP_FLAGS */
15024565e991STom Herbert 		nla_total_size(2) +
15034565e991STom Herbert 		/* IFLA_GRE_ENCAP_SPORT */
15044565e991STom Herbert 		nla_total_size(2) +
15054565e991STom Herbert 		/* IFLA_GRE_ENCAP_DPORT */
15064565e991STom Herbert 		nla_total_size(2) +
15072e15ea39SPravin B Shelar 		/* IFLA_GRE_COLLECT_METADATA */
15082e15ea39SPravin B Shelar 		nla_total_size(0) +
150922a59be8SPhilip Prindeville 		/* IFLA_GRE_IGNORE_DF */
151022a59be8SPhilip Prindeville 		nla_total_size(1) +
15119830ad4cSCraig Gallek 		/* IFLA_GRE_FWMARK */
15129830ad4cSCraig Gallek 		nla_total_size(4) +
151384e54fe0SWilliam Tu 		/* IFLA_GRE_ERSPAN_INDEX */
151484e54fe0SWilliam Tu 		nla_total_size(4) +
1515f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_VER */
1516f551c91dSWilliam Tu 		nla_total_size(1) +
1517f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_DIR */
1518f551c91dSWilliam Tu 		nla_total_size(1) +
1519f551c91dSWilliam Tu 		/* IFLA_GRE_ERSPAN_HWID */
1520f551c91dSWilliam Tu 		nla_total_size(2) +
1521c19e654dSHerbert Xu 		0;
1522c19e654dSHerbert Xu }
1523c19e654dSHerbert Xu 
1524c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
1525c19e654dSHerbert Xu {
1526c19e654dSHerbert Xu 	struct ip_tunnel *t = netdev_priv(dev);
1527117aef12SAlexander Lobakin 	struct ip_tunnel_parm_kern *p = &t->parms;
1528*5832c4a7SAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(o_flags);
1529*5832c4a7SAlexander Lobakin 
1530*5832c4a7SAlexander Lobakin 	ip_tunnel_flags_copy(o_flags, p->o_flags);
1531feaf5c79SLorenzo Bianconi 
1532f3756b79SDavid S. Miller 	if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
153395f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_IFLAGS,
153495f5c64cSTom Herbert 			 gre_tnl_flags_to_gre_flags(p->i_flags)) ||
153595f5c64cSTom Herbert 	    nla_put_be16(skb, IFLA_GRE_OFLAGS,
1536feaf5c79SLorenzo Bianconi 			 gre_tnl_flags_to_gre_flags(o_flags)) ||
1537f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
1538f3756b79SDavid S. Miller 	    nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
1539930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
1540930345eaSJiri Benc 	    nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) ||
1541f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) ||
1542f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) ||
1543f3756b79SDavid S. Miller 	    nla_put_u8(skb, IFLA_GRE_PMTUDISC,
15449830ad4cSCraig Gallek 		       !!(p->iph.frag_off & htons(IP_DF))) ||
15459830ad4cSCraig Gallek 	    nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark))
1546f3756b79SDavid S. Miller 		goto nla_put_failure;
15474565e991STom Herbert 
15484565e991STom Herbert 	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
15494565e991STom Herbert 			t->encap.type) ||
15503e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
15514565e991STom Herbert 			 t->encap.sport) ||
15523e97fa70SSabrina Dubroca 	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
15534565e991STom Herbert 			 t->encap.dport) ||
15544565e991STom Herbert 	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
1555e1b2cb65STom Herbert 			t->encap.flags))
15564565e991STom Herbert 		goto nla_put_failure;
15574565e991STom Herbert 
155822a59be8SPhilip Prindeville 	if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df))
155922a59be8SPhilip Prindeville 		goto nla_put_failure;
156022a59be8SPhilip Prindeville 
15612e15ea39SPravin B Shelar 	if (t->collect_md) {
15622e15ea39SPravin B Shelar 		if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA))
15632e15ea39SPravin B Shelar 			goto nla_put_failure;
15642e15ea39SPravin B Shelar 	}
15652e15ea39SPravin B Shelar 
1566c19e654dSHerbert Xu 	return 0;
1567c19e654dSHerbert Xu 
1568c19e654dSHerbert Xu nla_put_failure:
1569c19e654dSHerbert Xu 	return -EMSGSIZE;
1570c19e654dSHerbert Xu }
1571c19e654dSHerbert Xu 
1572ee496694SHangbin Liu static int erspan_fill_info(struct sk_buff *skb, const struct net_device *dev)
1573ee496694SHangbin Liu {
1574ee496694SHangbin Liu 	struct ip_tunnel *t = netdev_priv(dev);
1575ee496694SHangbin Liu 
1576ee496694SHangbin Liu 	if (t->erspan_ver <= 2) {
1577ee496694SHangbin Liu 		if (t->erspan_ver != 0 && !t->collect_md)
1578*5832c4a7SAlexander Lobakin 			__set_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags);
1579ee496694SHangbin Liu 
1580ee496694SHangbin Liu 		if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
1581ee496694SHangbin Liu 			goto nla_put_failure;
1582ee496694SHangbin Liu 
1583ee496694SHangbin Liu 		if (t->erspan_ver == 1) {
1584ee496694SHangbin Liu 			if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
1585ee496694SHangbin Liu 				goto nla_put_failure;
1586ee496694SHangbin Liu 		} else if (t->erspan_ver == 2) {
1587ee496694SHangbin Liu 			if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
1588ee496694SHangbin Liu 				goto nla_put_failure;
1589ee496694SHangbin Liu 			if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
1590ee496694SHangbin Liu 				goto nla_put_failure;
1591ee496694SHangbin Liu 		}
1592ee496694SHangbin Liu 	}
1593ee496694SHangbin Liu 
1594ee496694SHangbin Liu 	return ipgre_fill_info(skb, dev);
1595ee496694SHangbin Liu 
1596ee496694SHangbin Liu nla_put_failure:
1597ee496694SHangbin Liu 	return -EMSGSIZE;
1598ee496694SHangbin Liu }
1599ee496694SHangbin Liu 
160084e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev)
160184e54fe0SWilliam Tu {
160284581bdaSXin Long 	struct ip_tunnel *t = netdev_priv(dev);
160384581bdaSXin Long 
160484e54fe0SWilliam Tu 	ether_setup(dev);
16050e141f75SHaishuang Yan 	dev->max_mtu = 0;
160684e54fe0SWilliam Tu 	dev->netdev_ops = &erspan_netdev_ops;
160784e54fe0SWilliam Tu 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
160884e54fe0SWilliam Tu 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
160984e54fe0SWilliam Tu 	ip_tunnel_setup(dev, erspan_net_id);
161084581bdaSXin Long 	t->erspan_ver = 1;
161184e54fe0SWilliam Tu }
161284e54fe0SWilliam Tu 
1613c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
1614c19e654dSHerbert Xu 	[IFLA_GRE_LINK]		= { .type = NLA_U32 },
1615c19e654dSHerbert Xu 	[IFLA_GRE_IFLAGS]	= { .type = NLA_U16 },
1616c19e654dSHerbert Xu 	[IFLA_GRE_OFLAGS]	= { .type = NLA_U16 },
1617c19e654dSHerbert Xu 	[IFLA_GRE_IKEY]		= { .type = NLA_U32 },
1618c19e654dSHerbert Xu 	[IFLA_GRE_OKEY]		= { .type = NLA_U32 },
1619c593642cSPankaj Bharadiya 	[IFLA_GRE_LOCAL]	= { .len = sizeof_field(struct iphdr, saddr) },
1620c593642cSPankaj Bharadiya 	[IFLA_GRE_REMOTE]	= { .len = sizeof_field(struct iphdr, daddr) },
1621c19e654dSHerbert Xu 	[IFLA_GRE_TTL]		= { .type = NLA_U8 },
1622c19e654dSHerbert Xu 	[IFLA_GRE_TOS]		= { .type = NLA_U8 },
1623c19e654dSHerbert Xu 	[IFLA_GRE_PMTUDISC]	= { .type = NLA_U8 },
16244565e991STom Herbert 	[IFLA_GRE_ENCAP_TYPE]	= { .type = NLA_U16 },
16254565e991STom Herbert 	[IFLA_GRE_ENCAP_FLAGS]	= { .type = NLA_U16 },
16264565e991STom Herbert 	[IFLA_GRE_ENCAP_SPORT]	= { .type = NLA_U16 },
16274565e991STom Herbert 	[IFLA_GRE_ENCAP_DPORT]	= { .type = NLA_U16 },
16282e15ea39SPravin B Shelar 	[IFLA_GRE_COLLECT_METADATA]	= { .type = NLA_FLAG },
162922a59be8SPhilip Prindeville 	[IFLA_GRE_IGNORE_DF]	= { .type = NLA_U8 },
16309830ad4cSCraig Gallek 	[IFLA_GRE_FWMARK]	= { .type = NLA_U32 },
163184e54fe0SWilliam Tu 	[IFLA_GRE_ERSPAN_INDEX]	= { .type = NLA_U32 },
1632f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_VER]	= { .type = NLA_U8 },
1633f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_DIR]	= { .type = NLA_U8 },
1634f551c91dSWilliam Tu 	[IFLA_GRE_ERSPAN_HWID]	= { .type = NLA_U16 },
1635c19e654dSHerbert Xu };
1636c19e654dSHerbert Xu 
1637c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1638c19e654dSHerbert Xu 	.kind		= "gre",
1639c19e654dSHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1640c19e654dSHerbert Xu 	.policy		= ipgre_policy,
1641c19e654dSHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1642c19e654dSHerbert Xu 	.setup		= ipgre_tunnel_setup,
1643c19e654dSHerbert Xu 	.validate	= ipgre_tunnel_validate,
1644c19e654dSHerbert Xu 	.newlink	= ipgre_newlink,
1645c19e654dSHerbert Xu 	.changelink	= ipgre_changelink,
1646c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1647c19e654dSHerbert Xu 	.get_size	= ipgre_get_size,
1648c19e654dSHerbert Xu 	.fill_info	= ipgre_fill_info,
16491728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1650c19e654dSHerbert Xu };
1651c19e654dSHerbert Xu 
1652e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1653e1a80002SHerbert Xu 	.kind		= "gretap",
1654e1a80002SHerbert Xu 	.maxtype	= IFLA_GRE_MAX,
1655e1a80002SHerbert Xu 	.policy		= ipgre_policy,
1656e1a80002SHerbert Xu 	.priv_size	= sizeof(struct ip_tunnel),
1657e1a80002SHerbert Xu 	.setup		= ipgre_tap_setup,
1658e1a80002SHerbert Xu 	.validate	= ipgre_tap_validate,
1659e1a80002SHerbert Xu 	.newlink	= ipgre_newlink,
1660e1a80002SHerbert Xu 	.changelink	= ipgre_changelink,
1661c5441932SPravin B Shelar 	.dellink	= ip_tunnel_dellink,
1662e1a80002SHerbert Xu 	.get_size	= ipgre_get_size,
1663e1a80002SHerbert Xu 	.fill_info	= ipgre_fill_info,
16641728d4faSNicolas Dichtel 	.get_link_net	= ip_tunnel_get_link_net,
1665e1a80002SHerbert Xu };
1666e1a80002SHerbert Xu 
166784e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = {
166884e54fe0SWilliam Tu 	.kind		= "erspan",
166984e54fe0SWilliam Tu 	.maxtype	= IFLA_GRE_MAX,
167084e54fe0SWilliam Tu 	.policy		= ipgre_policy,
167184e54fe0SWilliam Tu 	.priv_size	= sizeof(struct ip_tunnel),
167284e54fe0SWilliam Tu 	.setup		= erspan_setup,
167384e54fe0SWilliam Tu 	.validate	= erspan_validate,
1674e1f8f78fSPetr Machata 	.newlink	= erspan_newlink,
1675e1f8f78fSPetr Machata 	.changelink	= erspan_changelink,
167684e54fe0SWilliam Tu 	.dellink	= ip_tunnel_dellink,
167784e54fe0SWilliam Tu 	.get_size	= ipgre_get_size,
1678ee496694SHangbin Liu 	.fill_info	= erspan_fill_info,
167984e54fe0SWilliam Tu 	.get_link_net	= ip_tunnel_get_link_net,
168084e54fe0SWilliam Tu };
168184e54fe0SWilliam Tu 
1682b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1683b2acd1dcSPravin B Shelar 					u8 name_assign_type)
1684b2acd1dcSPravin B Shelar {
1685b2acd1dcSPravin B Shelar 	struct nlattr *tb[IFLA_MAX + 1];
1686b2acd1dcSPravin B Shelar 	struct net_device *dev;
1687106da663SNicolas Dichtel 	LIST_HEAD(list_kill);
1688b2acd1dcSPravin B Shelar 	struct ip_tunnel *t;
1689b2acd1dcSPravin B Shelar 	int err;
1690b2acd1dcSPravin B Shelar 
1691b2acd1dcSPravin B Shelar 	memset(&tb, 0, sizeof(tb));
1692b2acd1dcSPravin B Shelar 
1693b2acd1dcSPravin B Shelar 	dev = rtnl_create_link(net, name, name_assign_type,
1694d0522f1cSDavid Ahern 			       &ipgre_tap_ops, tb, NULL);
1695b2acd1dcSPravin B Shelar 	if (IS_ERR(dev))
1696b2acd1dcSPravin B Shelar 		return dev;
1697b2acd1dcSPravin B Shelar 
1698b2acd1dcSPravin B Shelar 	/* Configure flow based GRE device. */
1699b2acd1dcSPravin B Shelar 	t = netdev_priv(dev);
1700b2acd1dcSPravin B Shelar 	t->collect_md = true;
1701b2acd1dcSPravin B Shelar 
17027a3f4a18SMatthias Schiffer 	err = ipgre_newlink(net, dev, tb, NULL, NULL);
1703106da663SNicolas Dichtel 	if (err < 0) {
1704106da663SNicolas Dichtel 		free_netdev(dev);
1705106da663SNicolas Dichtel 		return ERR_PTR(err);
1706106da663SNicolas Dichtel 	}
17077e059158SDavid Wragg 
17087e059158SDavid Wragg 	/* openvswitch users expect packet sizes to be unrestricted,
17097e059158SDavid Wragg 	 * so set the largest MTU we can.
17107e059158SDavid Wragg 	 */
17117e059158SDavid Wragg 	err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
17127e059158SDavid Wragg 	if (err)
17137e059158SDavid Wragg 		goto out;
17147e059158SDavid Wragg 
17151d997f10SHangbin Liu 	err = rtnl_configure_link(dev, NULL, 0, NULL);
1716da6f1da8SNicolas Dichtel 	if (err < 0)
1717da6f1da8SNicolas Dichtel 		goto out;
1718da6f1da8SNicolas Dichtel 
1719b2acd1dcSPravin B Shelar 	return dev;
1720b2acd1dcSPravin B Shelar out:
1721106da663SNicolas Dichtel 	ip_tunnel_dellink(dev, &list_kill);
1722106da663SNicolas Dichtel 	unregister_netdevice_many(&list_kill);
1723b2acd1dcSPravin B Shelar 	return ERR_PTR(err);
1724b2acd1dcSPravin B Shelar }
1725b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
1726b2acd1dcSPravin B Shelar 
1727c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net)
1728c5441932SPravin B Shelar {
17292e15ea39SPravin B Shelar 	return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
1730c5441932SPravin B Shelar }
1731c5441932SPravin B Shelar 
17329b5b3637SEric Dumazet static void __net_exit ipgre_tap_exit_batch_rtnl(struct list_head *list_net,
17339b5b3637SEric Dumazet 						 struct list_head *dev_to_kill)
1734c5441932SPravin B Shelar {
17359b5b3637SEric Dumazet 	ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops,
17369b5b3637SEric Dumazet 			      dev_to_kill);
1737c5441932SPravin B Shelar }
1738c5441932SPravin B Shelar 
1739c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = {
1740c5441932SPravin B Shelar 	.init = ipgre_tap_init_net,
17419b5b3637SEric Dumazet 	.exit_batch_rtnl = ipgre_tap_exit_batch_rtnl,
1742c5441932SPravin B Shelar 	.id   = &gre_tap_net_id,
1743c5441932SPravin B Shelar 	.size = sizeof(struct ip_tunnel_net),
1744c5441932SPravin B Shelar };
17451da177e4SLinus Torvalds 
174684e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net)
174784e54fe0SWilliam Tu {
174884e54fe0SWilliam Tu 	return ip_tunnel_init_net(net, erspan_net_id,
174984e54fe0SWilliam Tu 				  &erspan_link_ops, "erspan0");
175084e54fe0SWilliam Tu }
175184e54fe0SWilliam Tu 
17529b5b3637SEric Dumazet static void __net_exit erspan_exit_batch_rtnl(struct list_head *net_list,
17539b5b3637SEric Dumazet 					      struct list_head *dev_to_kill)
175484e54fe0SWilliam Tu {
17559b5b3637SEric Dumazet 	ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops,
17569b5b3637SEric Dumazet 			      dev_to_kill);
175784e54fe0SWilliam Tu }
175884e54fe0SWilliam Tu 
175984e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = {
176084e54fe0SWilliam Tu 	.init = erspan_init_net,
17619b5b3637SEric Dumazet 	.exit_batch_rtnl = erspan_exit_batch_rtnl,
176284e54fe0SWilliam Tu 	.id   = &erspan_net_id,
176384e54fe0SWilliam Tu 	.size = sizeof(struct ip_tunnel_net),
176484e54fe0SWilliam Tu };
176584e54fe0SWilliam Tu 
17661da177e4SLinus Torvalds static int __init ipgre_init(void)
17671da177e4SLinus Torvalds {
17681da177e4SLinus Torvalds 	int err;
17691da177e4SLinus Torvalds 
1770058bd4d2SJoe Perches 	pr_info("GRE over IPv4 tunneling driver\n");
17711da177e4SLinus Torvalds 
1772cfb8fbf2SEric W. Biederman 	err = register_pernet_device(&ipgre_net_ops);
177359a4c759SPavel Emelyanov 	if (err < 0)
1774c2892f02SAlexey Dobriyan 		return err;
1775c2892f02SAlexey Dobriyan 
1776c5441932SPravin B Shelar 	err = register_pernet_device(&ipgre_tap_net_ops);
1777c5441932SPravin B Shelar 	if (err < 0)
1778e3d0328cSWilliam Tu 		goto pnet_tap_failed;
1779c5441932SPravin B Shelar 
178084e54fe0SWilliam Tu 	err = register_pernet_device(&erspan_net_ops);
178184e54fe0SWilliam Tu 	if (err < 0)
178284e54fe0SWilliam Tu 		goto pnet_erspan_failed;
178384e54fe0SWilliam Tu 
17849f57c67cSPravin B Shelar 	err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
1785c2892f02SAlexey Dobriyan 	if (err < 0) {
1786058bd4d2SJoe Perches 		pr_info("%s: can't add protocol\n", __func__);
1787c2892f02SAlexey Dobriyan 		goto add_proto_failed;
1788c2892f02SAlexey Dobriyan 	}
17897daa0004SPavel Emelyanov 
1790c19e654dSHerbert Xu 	err = rtnl_link_register(&ipgre_link_ops);
1791c19e654dSHerbert Xu 	if (err < 0)
1792c19e654dSHerbert Xu 		goto rtnl_link_failed;
1793c19e654dSHerbert Xu 
1794e1a80002SHerbert Xu 	err = rtnl_link_register(&ipgre_tap_ops);
1795e1a80002SHerbert Xu 	if (err < 0)
1796e1a80002SHerbert Xu 		goto tap_ops_failed;
1797e1a80002SHerbert Xu 
179884e54fe0SWilliam Tu 	err = rtnl_link_register(&erspan_link_ops);
179984e54fe0SWilliam Tu 	if (err < 0)
180084e54fe0SWilliam Tu 		goto erspan_link_failed;
180184e54fe0SWilliam Tu 
1802c5441932SPravin B Shelar 	return 0;
1803c19e654dSHerbert Xu 
180484e54fe0SWilliam Tu erspan_link_failed:
180584e54fe0SWilliam Tu 	rtnl_link_unregister(&ipgre_tap_ops);
1806e1a80002SHerbert Xu tap_ops_failed:
1807e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
1808c19e654dSHerbert Xu rtnl_link_failed:
18099f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1810c2892f02SAlexey Dobriyan add_proto_failed:
181184e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
181284e54fe0SWilliam Tu pnet_erspan_failed:
1813c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1814e3d0328cSWilliam Tu pnet_tap_failed:
1815c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
1816c5441932SPravin B Shelar 	return err;
18171da177e4SLinus Torvalds }
18181da177e4SLinus Torvalds 
1819db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void)
18201da177e4SLinus Torvalds {
1821e1a80002SHerbert Xu 	rtnl_link_unregister(&ipgre_tap_ops);
1822c19e654dSHerbert Xu 	rtnl_link_unregister(&ipgre_link_ops);
182384e54fe0SWilliam Tu 	rtnl_link_unregister(&erspan_link_ops);
18249f57c67cSPravin B Shelar 	gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
1825c5441932SPravin B Shelar 	unregister_pernet_device(&ipgre_tap_net_ops);
1826c2892f02SAlexey Dobriyan 	unregister_pernet_device(&ipgre_net_ops);
182784e54fe0SWilliam Tu 	unregister_pernet_device(&erspan_net_ops);
18281da177e4SLinus Torvalds }
18291da177e4SLinus Torvalds 
18301da177e4SLinus Torvalds module_init(ipgre_init);
18311da177e4SLinus Torvalds module_exit(ipgre_fini);
1832b058a5d2SBreno Leitao MODULE_DESCRIPTION("IPv4 GRE tunnels over IP library");
18331da177e4SLinus Torvalds MODULE_LICENSE("GPL");
18344d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre");
18354d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap");
183684e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan");
18378909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0");
1838c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0");
183984e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0");
1840