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; 2685832c4a7SAlexander 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 2765832c4a7SAlexander Lobakin ip_tunnel_flags_copy(flags, tpi->flags); 2775832c4a7SAlexander 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; 2825832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_NO_KEY_BIT, flags); 2835832c4a7SAlexander Lobakin tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, flags, 284f989d546SWilliam Tu iph->saddr, iph->daddr, 0); 285f989d546SWilliam Tu } else { 28617af4205SEric Dumazet if (unlikely(!pskb_may_pull(skb, 28717af4205SEric Dumazet gre_hdr_len + sizeof(*ershdr)))) 28817af4205SEric Dumazet return PACKET_REJECT; 28917af4205SEric Dumazet 2901d7e2ed2SWilliam Tu ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); 291c69de58bSWilliam Tu ver = ershdr->ver; 29217af4205SEric Dumazet iph = ip_hdr(skb); 2935832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_KEY_BIT, flags); 2945832c4a7SAlexander Lobakin tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, flags, 29584e54fe0SWilliam Tu iph->saddr, iph->daddr, tpi->key); 296f989d546SWilliam Tu } 29784e54fe0SWilliam Tu 29884e54fe0SWilliam Tu if (tunnel) { 299f989d546SWilliam Tu if (is_erspan_type1(gre_hdr_len)) 300f989d546SWilliam Tu len = gre_hdr_len; 301f989d546SWilliam Tu else 3021d7e2ed2SWilliam Tu len = gre_hdr_len + erspan_hdr_len(ver); 303f989d546SWilliam Tu 3041d7e2ed2SWilliam Tu if (unlikely(!pskb_may_pull(skb, len))) 305ae3e1337SWilliam Tu return PACKET_REJECT; 3061d7e2ed2SWilliam Tu 30784e54fe0SWilliam Tu if (__iptunnel_pull_header(skb, 3081d7e2ed2SWilliam Tu len, 30984e54fe0SWilliam Tu htons(ETH_P_TEB), 31084e54fe0SWilliam Tu false, false) < 0) 31184e54fe0SWilliam Tu goto drop; 31284e54fe0SWilliam Tu 3131a66a836SWilliam Tu if (tunnel->collect_md) { 314492b67e2SLorenzo Bianconi struct erspan_metadata *pkt_md, *md; 3151a66a836SWilliam Tu struct ip_tunnel_info *info; 316492b67e2SLorenzo Bianconi unsigned char *gh; 3171a66a836SWilliam Tu __be64 tun_id; 3181a66a836SWilliam Tu 3195832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_KEY_BIT, tpi->flags); 3205832c4a7SAlexander Lobakin ip_tunnel_flags_copy(flags, tpi->flags); 3211a66a836SWilliam Tu tun_id = key32_to_tunnel_id(tpi->key); 3221a66a836SWilliam Tu 3231a66a836SWilliam Tu tun_dst = ip_tun_rx_dst(skb, flags, 3241a66a836SWilliam Tu tun_id, sizeof(*md)); 3251a66a836SWilliam Tu if (!tun_dst) 3261a66a836SWilliam Tu return PACKET_REJECT; 3271a66a836SWilliam Tu 328492b67e2SLorenzo Bianconi /* skb can be uncloned in __iptunnel_pull_header, so 329492b67e2SLorenzo Bianconi * old pkt_md is no longer valid and we need to reset 330492b67e2SLorenzo Bianconi * it 331492b67e2SLorenzo Bianconi */ 332492b67e2SLorenzo Bianconi gh = skb_network_header(skb) + 333492b67e2SLorenzo Bianconi skb_network_header_len(skb); 334492b67e2SLorenzo Bianconi pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len + 335492b67e2SLorenzo Bianconi sizeof(*ershdr)); 3361a66a836SWilliam Tu md = ip_tunnel_info_opts(&tun_dst->u.tun_info); 337f551c91dSWilliam Tu md->version = ver; 3383df19283SWilliam Tu md2 = &md->u.md2; 3393df19283SWilliam Tu memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : 3403df19283SWilliam Tu ERSPAN_V2_MDSIZE); 341f551c91dSWilliam Tu 3421a66a836SWilliam Tu info = &tun_dst->u.tun_info; 3435832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_ERSPAN_OPT_BIT, 3445832c4a7SAlexander Lobakin info->key.tun_flags); 3451a66a836SWilliam Tu info->options_len = sizeof(*md); 3461a66a836SWilliam Tu } 3471a66a836SWilliam Tu 34884e54fe0SWilliam Tu skb_reset_mac_header(skb); 34984e54fe0SWilliam Tu ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 35084e54fe0SWilliam Tu return PACKET_RCVD; 35184e54fe0SWilliam Tu } 3525a64506bSHaishuang Yan return PACKET_REJECT; 3535a64506bSHaishuang Yan 35484e54fe0SWilliam Tu drop: 35584e54fe0SWilliam Tu kfree_skb(skb); 35684e54fe0SWilliam Tu return PACKET_RCVD; 35784e54fe0SWilliam Tu } 35884e54fe0SWilliam Tu 359125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 360125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 3611da177e4SLinus Torvalds { 3622e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 363b71d1d42SEric Dumazet const struct iphdr *iph; 3641da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3651da177e4SLinus Torvalds 366eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 367bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 368bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3691da177e4SLinus Torvalds 370d2083287Sstephen hemminger if (tunnel) { 371c0d59da7Swenxu const struct iphdr *tnl_params; 372c0d59da7Swenxu 373125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 374125372faSJiri Benc raw_proto, false) < 0) 375244a797bSJiri Benc goto drop; 376244a797bSJiri Benc 377aab1e898SGuillaume Nault /* Special case for ipgre_header_parse(), which expects the 378aab1e898SGuillaume Nault * mac_header to point to the outer IP header. 379aab1e898SGuillaume Nault */ 380aab1e898SGuillaume Nault if (tunnel->dev->header_ops == &ipgre_header_ops) 3810e3da5bbSTimo Teräs skb_pop_mac_header(skb); 382e271c7b4SJiri Benc else 383e271c7b4SJiri Benc skb_reset_mac_header(skb); 384c0d59da7Swenxu 385c0d59da7Swenxu tnl_params = &tunnel->parms.iph; 386c0d59da7Swenxu if (tunnel->collect_md || tnl_params->daddr == 0) { 3875832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(flags) = { }; 388c29a70d2SPravin B Shelar __be64 tun_id; 3892e15ea39SPravin B Shelar 3905832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_CSUM_BIT, flags); 3915832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_KEY_BIT, flags); 3925832c4a7SAlexander Lobakin ip_tunnel_flags_and(flags, tpi->flags, flags); 3935832c4a7SAlexander Lobakin 394d817f432SAmir Vadai tun_id = key32_to_tunnel_id(tpi->key); 395c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 3962e15ea39SPravin B Shelar if (!tun_dst) 3972e15ea39SPravin B Shelar return PACKET_REJECT; 3982e15ea39SPravin B Shelar } 3992e15ea39SPravin B Shelar 4002e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 401bda7bb46SPravin B Shelar return PACKET_RCVD; 4021da177e4SLinus Torvalds } 403125372faSJiri Benc return PACKET_NEXT; 404244a797bSJiri Benc 405244a797bSJiri Benc drop: 406244a797bSJiri Benc kfree_skb(skb); 407244a797bSJiri Benc return PACKET_RCVD; 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 410125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 411125372faSJiri Benc int hdr_len) 412125372faSJiri Benc { 413125372faSJiri Benc struct net *net = dev_net(skb->dev); 414125372faSJiri Benc struct ip_tunnel_net *itn; 415125372faSJiri Benc int res; 416125372faSJiri Benc 417125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 418125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 419125372faSJiri Benc else 420125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 421125372faSJiri Benc 422125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 423125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 424125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 425125372faSJiri Benc * also ETH_P_TEB traffic. 426125372faSJiri Benc */ 427125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 428125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 429125372faSJiri Benc } 430125372faSJiri Benc return res; 431125372faSJiri Benc } 432125372faSJiri Benc 4339f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 4349f57c67cSPravin B Shelar { 4359f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 4369f57c67cSPravin B Shelar bool csum_err = false; 43795f5c64cSTom Herbert int hdr_len; 4389f57c67cSPravin B Shelar 4399f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 4409f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 4419f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 4429f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 4439f57c67cSPravin B Shelar goto drop; 4449f57c67cSPravin B Shelar } 4459f57c67cSPravin B Shelar #endif 4469f57c67cSPravin B Shelar 447e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 448f132ae7cSJiri Benc if (hdr_len < 0) 44995f5c64cSTom Herbert goto drop; 45095f5c64cSTom Herbert 451f551c91dSWilliam Tu if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || 452f551c91dSWilliam Tu tpi.proto == htons(ETH_P_ERSPAN2))) { 45384e54fe0SWilliam Tu if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 45484e54fe0SWilliam Tu return 0; 455dd8d5b8cSHaishuang Yan goto out; 45684e54fe0SWilliam Tu } 45784e54fe0SWilliam Tu 458244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 4599f57c67cSPravin B Shelar return 0; 4609f57c67cSPravin B Shelar 461dd8d5b8cSHaishuang Yan out: 4629f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 4639f57c67cSPravin B Shelar drop: 4649f57c67cSPravin B Shelar kfree_skb(skb); 4659f57c67cSPravin B Shelar return 0; 4669f57c67cSPravin B Shelar } 4679f57c67cSPravin B Shelar 468c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 469c5441932SPravin B Shelar const struct iphdr *tnl_params, 470c5441932SPravin B Shelar __be16 proto) 471c5441932SPravin B Shelar { 472c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 4735832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(flags); 4745832c4a7SAlexander Lobakin 4755832c4a7SAlexander Lobakin ip_tunnel_flags_copy(flags, tunnel->parms.o_flags); 476cef401deSEric Dumazet 477c5441932SPravin B Shelar /* Push GRE header. */ 478182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 479ff827bebSPeilin Ye flags, proto, tunnel->parms.o_key, 4805832c4a7SAlexander Lobakin test_bit(IP_TUNNEL_SEQ_BIT, flags) ? 4815832c4a7SAlexander Lobakin htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0); 4821da177e4SLinus Torvalds 483bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 486aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 487b2acd1dcSPravin B Shelar { 4886fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 489b2acd1dcSPravin B Shelar } 490b2acd1dcSPravin B Shelar 491862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 492862a03c3SWilliam Tu __be16 proto) 493862a03c3SWilliam Tu { 49477a5196aSWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 4955832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(flags) = { }; 496862a03c3SWilliam Tu struct ip_tunnel_info *tun_info; 497862a03c3SWilliam Tu const struct ip_tunnel_key *key; 498862a03c3SWilliam Tu int tunnel_hlen; 499862a03c3SWilliam Tu 500862a03c3SWilliam Tu tun_info = skb_tunnel_info(skb); 501862a03c3SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 502862a03c3SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 503862a03c3SWilliam Tu goto err_free_skb; 504862a03c3SWilliam Tu 505862a03c3SWilliam Tu key = &tun_info->key; 506862a03c3SWilliam Tu tunnel_hlen = gre_calc_hlen(key->tun_flags); 507862a03c3SWilliam Tu 508962924faSwenxu if (skb_cow_head(skb, dev->needed_headroom)) 509962924faSwenxu goto err_free_skb; 5102e15ea39SPravin B Shelar 5112e15ea39SPravin B Shelar /* Push Tunnel header. */ 5125832c4a7SAlexander Lobakin if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, 5135832c4a7SAlexander Lobakin tunnel->parms.o_flags))) 514962924faSwenxu goto err_free_skb; 5152e15ea39SPravin B Shelar 5165832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_CSUM_BIT, flags); 5175832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_KEY_BIT, flags); 5185832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_SEQ_BIT, flags); 5195832c4a7SAlexander Lobakin ip_tunnel_flags_and(flags, tun_info->key.tun_flags, flags); 5205832c4a7SAlexander Lobakin 521cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 52277a5196aSWilliam Tu tunnel_id_to_key32(tun_info->key.tun_id), 5235832c4a7SAlexander Lobakin test_bit(IP_TUNNEL_SEQ_BIT, flags) ? 5245832c4a7SAlexander Lobakin htonl(atomic_fetch_inc(&tunnel->o_seqno)) : 0); 5252e15ea39SPravin B Shelar 526962924faSwenxu ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); 527039f5062SPravin B Shelar 5282e15ea39SPravin B Shelar return; 5292e15ea39SPravin B Shelar 5302e15ea39SPravin B Shelar err_free_skb: 5312e15ea39SPravin B Shelar kfree_skb(skb); 532c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 5332e15ea39SPravin B Shelar } 5342e15ea39SPravin B Shelar 53520704bd1SXin Long static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) 5361a66a836SWilliam Tu { 5371a66a836SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 5385832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(flags) = { }; 5391a66a836SWilliam Tu struct ip_tunnel_info *tun_info; 5401a66a836SWilliam Tu const struct ip_tunnel_key *key; 5411a66a836SWilliam Tu struct erspan_metadata *md; 5421a66a836SWilliam Tu bool truncate = false; 543962924faSwenxu __be16 proto; 5441a66a836SWilliam Tu int tunnel_hlen; 545f551c91dSWilliam Tu int version; 5461baf5ebfSWilliam Tu int nhoff; 5471a66a836SWilliam Tu 5481a66a836SWilliam Tu tun_info = skb_tunnel_info(skb); 5491a66a836SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 5501a66a836SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 5511a66a836SWilliam Tu goto err_free_skb; 5521a66a836SWilliam Tu 5531a66a836SWilliam Tu key = &tun_info->key; 5545832c4a7SAlexander Lobakin if (!test_bit(IP_TUNNEL_ERSPAN_OPT_BIT, tun_info->key.tun_flags)) 555962924faSwenxu goto err_free_skb; 5562eb8d6d2SXin Long if (tun_info->options_len < sizeof(*md)) 557962924faSwenxu goto err_free_skb; 5582eb8d6d2SXin Long md = ip_tunnel_info_opts(tun_info); 5591a66a836SWilliam Tu 5601a66a836SWilliam Tu /* ERSPAN has fixed 8 byte GRE header */ 561f551c91dSWilliam Tu version = md->version; 562f551c91dSWilliam Tu tunnel_hlen = 8 + erspan_hdr_len(version); 5631a66a836SWilliam Tu 564962924faSwenxu if (skb_cow_head(skb, dev->needed_headroom)) 565962924faSwenxu goto err_free_skb; 5661a66a836SWilliam Tu 5671a66a836SWilliam Tu if (gre_handle_offloads(skb, false)) 568962924faSwenxu goto err_free_skb; 5691a66a836SWilliam Tu 570f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 57102d84f3eSYuanjun Gong if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) 57202d84f3eSYuanjun Gong goto err_free_skb; 5731a66a836SWilliam Tu truncate = true; 5741a66a836SWilliam Tu } 5751a66a836SWilliam Tu 5768e50ed77SEric Dumazet nhoff = skb_network_offset(skb); 5771baf5ebfSWilliam Tu if (skb->protocol == htons(ETH_P_IP) && 5781baf5ebfSWilliam Tu (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) 5791baf5ebfSWilliam Tu truncate = true; 5801baf5ebfSWilliam Tu 581301bd140SEric Dumazet if (skb->protocol == htons(ETH_P_IPV6)) { 582301bd140SEric Dumazet int thoff; 583301bd140SEric Dumazet 584301bd140SEric Dumazet if (skb_transport_header_was_set(skb)) 5858e50ed77SEric Dumazet thoff = skb_transport_offset(skb); 586301bd140SEric Dumazet else 587301bd140SEric Dumazet thoff = nhoff + sizeof(struct ipv6hdr); 588301bd140SEric Dumazet if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff) 589d5db21a3SWilliam Tu truncate = true; 590301bd140SEric Dumazet } 591d5db21a3SWilliam Tu 592f551c91dSWilliam Tu if (version == 1) { 593c69de58bSWilliam Tu erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), 5941d7e2ed2SWilliam Tu ntohl(md->u.index), truncate, true); 59520704bd1SXin Long proto = htons(ETH_P_ERSPAN); 596f551c91dSWilliam Tu } else if (version == 2) { 597c69de58bSWilliam Tu erspan_build_header_v2(skb, 598c69de58bSWilliam Tu ntohl(tunnel_id_to_key32(key->tun_id)), 599c69de58bSWilliam Tu md->u.md2.dir, 600c69de58bSWilliam Tu get_hwid(&md->u.md2), 601c69de58bSWilliam Tu truncate, true); 60220704bd1SXin Long proto = htons(ETH_P_ERSPAN2); 603f551c91dSWilliam Tu } else { 604962924faSwenxu goto err_free_skb; 605f551c91dSWilliam Tu } 6061a66a836SWilliam Tu 6075832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_SEQ_BIT, flags); 6085832c4a7SAlexander Lobakin gre_build_header(skb, 8, flags, proto, 0, 6095832c4a7SAlexander Lobakin htonl(atomic_fetch_inc(&tunnel->o_seqno))); 6101a66a836SWilliam Tu 611962924faSwenxu ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); 6121a66a836SWilliam Tu 6131a66a836SWilliam Tu return; 6141a66a836SWilliam Tu 6151a66a836SWilliam Tu err_free_skb: 6161a66a836SWilliam Tu kfree_skb(skb); 617c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 6181a66a836SWilliam Tu } 6191a66a836SWilliam Tu 620fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 621fc4099f1SPravin B Shelar { 622fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 623962924faSwenxu const struct ip_tunnel_key *key; 624fc4099f1SPravin B Shelar struct rtable *rt; 625fc4099f1SPravin B Shelar struct flowi4 fl4; 626fc4099f1SPravin B Shelar 627fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 628fc4099f1SPravin B Shelar return -EINVAL; 629fc4099f1SPravin B Shelar 630962924faSwenxu key = &info->key; 631962924faSwenxu ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, 632f7716b31SGuillaume Nault tunnel_id_to_key32(key->tun_id), 633db53cd3dSDavid Ahern key->tos & ~INET_ECN_MASK, dev_net(dev), 0, 6347ec9fce4SEyal Birger skb->mark, skb_get_hash(skb), key->flow_flags); 635962924faSwenxu rt = ip_route_output_key(dev_net(dev), &fl4); 636fc4099f1SPravin B Shelar if (IS_ERR(rt)) 637fc4099f1SPravin B Shelar return PTR_ERR(rt); 638fc4099f1SPravin B Shelar 639fc4099f1SPravin B Shelar ip_rt_put(rt); 640fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 641fc4099f1SPravin B Shelar return 0; 642fc4099f1SPravin B Shelar } 643fc4099f1SPravin B Shelar 644c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 645c5441932SPravin B Shelar struct net_device *dev) 646ee34c1ebSMichal Schmidt { 647c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 648c5441932SPravin B Shelar const struct iphdr *tnl_params; 649ee34c1ebSMichal Schmidt 650cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 651cb9f1b78SWillem de Bruijn goto free_skb; 652cb9f1b78SWillem de Bruijn 6532e15ea39SPravin B Shelar if (tunnel->collect_md) { 6542090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 6552e15ea39SPravin B Shelar return NETDEV_TX_OK; 6562e15ea39SPravin B Shelar } 6572e15ea39SPravin B Shelar 658c5441932SPravin B Shelar if (dev->header_ops) { 65980d875cfSShigeru Yoshida int pull_len = tunnel->hlen + sizeof(struct iphdr); 66080d875cfSShigeru Yoshida 661fdafed45SCong Wang if (skb_cow_head(skb, 0)) 662c5441932SPravin B Shelar goto free_skb; 663ee34c1ebSMichal Schmidt 664c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 665cbb1e85fSDavid S. Miller 66680d875cfSShigeru Yoshida if (!pskb_network_may_pull(skb, pull_len)) 66780d875cfSShigeru Yoshida goto free_skb; 66880d875cfSShigeru Yoshida 66980d875cfSShigeru Yoshida /* ip_tunnel_xmit() needs skb->data pointing to gre header. */ 67080d875cfSShigeru Yoshida skb_pull(skb, pull_len); 6718a0033a9STimo Teräs skb_reset_mac_header(skb); 6728d21e996SWillem de Bruijn 6738d21e996SWillem de Bruijn if (skb->ip_summed == CHECKSUM_PARTIAL && 6748d21e996SWillem de Bruijn skb_checksum_start(skb) < skb->data) 6758d21e996SWillem de Bruijn goto free_skb; 676c5441932SPravin B Shelar } else { 677c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 678c5441932SPravin B Shelar goto free_skb; 679c5441932SPravin B Shelar 680c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 681ee34c1ebSMichal Schmidt } 682e1a80002SHerbert Xu 6835832c4a7SAlexander Lobakin if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, 6845832c4a7SAlexander Lobakin tunnel->parms.o_flags))) 685aed069dfSAlexander Duyck goto free_skb; 6868a0033a9STimo Teräs 687c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 688c5441932SPravin B Shelar return NETDEV_TX_OK; 689c5441932SPravin B Shelar 690c5441932SPravin B Shelar free_skb: 6913acfa1e7SEric Dumazet kfree_skb(skb); 692c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 693c5441932SPravin B Shelar return NETDEV_TX_OK; 694ee34c1ebSMichal Schmidt } 695ee34c1ebSMichal Schmidt 69684e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb, 69784e54fe0SWilliam Tu struct net_device *dev) 69884e54fe0SWilliam Tu { 69984e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 70084e54fe0SWilliam Tu bool truncate = false; 70120704bd1SXin Long __be16 proto; 70284e54fe0SWilliam Tu 703cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 704cb9f1b78SWillem de Bruijn goto free_skb; 705cb9f1b78SWillem de Bruijn 7061a66a836SWilliam Tu if (tunnel->collect_md) { 70720704bd1SXin Long erspan_fb_xmit(skb, dev); 7081a66a836SWilliam Tu return NETDEV_TX_OK; 7091a66a836SWilliam Tu } 7101a66a836SWilliam Tu 71184e54fe0SWilliam Tu if (gre_handle_offloads(skb, false)) 71284e54fe0SWilliam Tu goto free_skb; 71384e54fe0SWilliam Tu 71484e54fe0SWilliam Tu if (skb_cow_head(skb, dev->needed_headroom)) 71584e54fe0SWilliam Tu goto free_skb; 71684e54fe0SWilliam Tu 717f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 718aa7cb378SYuanjun Gong if (pskb_trim(skb, dev->mtu + dev->hard_header_len)) 719aa7cb378SYuanjun Gong goto free_skb; 72084e54fe0SWilliam Tu truncate = true; 72184e54fe0SWilliam Tu } 72284e54fe0SWilliam Tu 72384e54fe0SWilliam Tu /* Push ERSPAN header */ 724f989d546SWilliam Tu if (tunnel->erspan_ver == 0) { 725f989d546SWilliam Tu proto = htons(ETH_P_ERSPAN); 7265832c4a7SAlexander Lobakin __clear_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags); 727f989d546SWilliam Tu } else if (tunnel->erspan_ver == 1) { 728c69de58bSWilliam Tu erspan_build_header(skb, ntohl(tunnel->parms.o_key), 729c69de58bSWilliam Tu tunnel->index, 730a3222dc9SWilliam Tu truncate, true); 73120704bd1SXin Long proto = htons(ETH_P_ERSPAN); 73220704bd1SXin Long } else if (tunnel->erspan_ver == 2) { 733c69de58bSWilliam Tu erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), 734f551c91dSWilliam Tu tunnel->dir, tunnel->hwid, 735f551c91dSWilliam Tu truncate, true); 73620704bd1SXin Long proto = htons(ETH_P_ERSPAN2); 73720704bd1SXin Long } else { 73802f99df1SWilliam Tu goto free_skb; 73920704bd1SXin Long } 740f551c91dSWilliam Tu 7415832c4a7SAlexander Lobakin __clear_bit(IP_TUNNEL_KEY_BIT, tunnel->parms.o_flags); 74220704bd1SXin Long __gre_xmit(skb, dev, &tunnel->parms.iph, proto); 74384e54fe0SWilliam Tu return NETDEV_TX_OK; 74484e54fe0SWilliam Tu 74584e54fe0SWilliam Tu free_skb: 74684e54fe0SWilliam Tu kfree_skb(skb); 747c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 74884e54fe0SWilliam Tu return NETDEV_TX_OK; 74984e54fe0SWilliam Tu } 75084e54fe0SWilliam Tu 751c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 752c5441932SPravin B Shelar struct net_device *dev) 753c5441932SPravin B Shelar { 754c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 755ee34c1ebSMichal Schmidt 756cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 757cb9f1b78SWillem de Bruijn goto free_skb; 758cb9f1b78SWillem de Bruijn 7592e15ea39SPravin B Shelar if (tunnel->collect_md) { 7602090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 7612e15ea39SPravin B Shelar return NETDEV_TX_OK; 7622e15ea39SPravin B Shelar } 7632e15ea39SPravin B Shelar 7645832c4a7SAlexander Lobakin if (gre_handle_offloads(skb, test_bit(IP_TUNNEL_CSUM_BIT, 7655832c4a7SAlexander Lobakin tunnel->parms.o_flags))) 766aed069dfSAlexander Duyck goto free_skb; 767ee34c1ebSMichal Schmidt 768c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 769c5441932SPravin B Shelar goto free_skb; 77042aa9162SHerbert Xu 771c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 772c5441932SPravin B Shelar return NETDEV_TX_OK; 773c5441932SPravin B Shelar 774c5441932SPravin B Shelar free_skb: 7753acfa1e7SEric Dumazet kfree_skb(skb); 776c4794d22SEric Dumazet DEV_STATS_INC(dev, tx_dropped); 777c5441932SPravin B Shelar return NETDEV_TX_OK; 77868c33163SPravin B Shelar } 779ee34c1ebSMichal Schmidt 780dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu) 781dd9d598cSXin Long { 782dd9d598cSXin Long struct ip_tunnel *tunnel = netdev_priv(dev); 783dd9d598cSXin Long int len; 784dd9d598cSXin Long 785dd9d598cSXin Long len = tunnel->tun_hlen; 786dd9d598cSXin Long tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 787dd9d598cSXin Long len = tunnel->tun_hlen - len; 788dd9d598cSXin Long tunnel->hlen = tunnel->hlen + len; 789dd9d598cSXin Long 790fdafed45SCong Wang if (dev->header_ops) 791fdafed45SCong Wang dev->hard_header_len += len; 792fdafed45SCong Wang else 793fdafed45SCong Wang dev->needed_headroom += len; 794fdafed45SCong Wang 795dd9d598cSXin Long if (set_mtu) 7961eb2cdedSEric Dumazet WRITE_ONCE(dev->mtu, max_t(int, dev->mtu - len, 68)); 797dd9d598cSXin Long 7985832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags) || 7995832c4a7SAlexander Lobakin (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.o_flags) && 8005832c4a7SAlexander Lobakin tunnel->encap.type != TUNNEL_ENCAP_NONE)) { 8011cc5954fSSabrina Dubroca dev->features &= ~NETIF_F_GSO_SOFTWARE; 8021cc5954fSSabrina Dubroca dev->hw_features &= ~NETIF_F_GSO_SOFTWARE; 8031cc5954fSSabrina Dubroca } else { 804020e8f60SPeilin Ye dev->features |= NETIF_F_GSO_SOFTWARE; 805020e8f60SPeilin Ye dev->hw_features |= NETIF_F_GSO_SOFTWARE; 806dd9d598cSXin Long } 807dd9d598cSXin Long } 808dd9d598cSXin Long 809117aef12SAlexander Lobakin static int ipgre_tunnel_ctl(struct net_device *dev, 810117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *p, 811607259a6SChristoph Hellwig int cmd) 8121da177e4SLinus Torvalds { 8135832c4a7SAlexander Lobakin __be16 i_flags, o_flags; 814a0efab67SXin Long int err; 8151da177e4SLinus Torvalds 8165832c4a7SAlexander Lobakin if (!ip_tunnel_flags_is_be16_compat(p->i_flags) || 8175832c4a7SAlexander Lobakin !ip_tunnel_flags_is_be16_compat(p->o_flags)) 8185832c4a7SAlexander Lobakin return -EOVERFLOW; 8195832c4a7SAlexander Lobakin 8205832c4a7SAlexander Lobakin i_flags = ip_tunnel_flags_to_be16(p->i_flags); 8215832c4a7SAlexander Lobakin o_flags = ip_tunnel_flags_to_be16(p->o_flags); 8225832c4a7SAlexander Lobakin 8236c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 824607259a6SChristoph Hellwig if (p->iph.version != 4 || p->iph.protocol != IPPROTO_GRE || 825607259a6SChristoph Hellwig p->iph.ihl != 5 || (p->iph.frag_off & htons(~IP_DF)) || 8265832c4a7SAlexander Lobakin ((i_flags | o_flags) & (GRE_VERSION | GRE_ROUTING))) 8271da177e4SLinus Torvalds return -EINVAL; 828c5441932SPravin B Shelar } 829a0efab67SXin Long 8305832c4a7SAlexander Lobakin gre_flags_to_tnl_flags(p->i_flags, i_flags); 8315832c4a7SAlexander Lobakin gre_flags_to_tnl_flags(p->o_flags, o_flags); 832c5441932SPravin B Shelar 833607259a6SChristoph Hellwig err = ip_tunnel_ctl(dev, p, cmd); 834c5441932SPravin B Shelar if (err) 835c5441932SPravin B Shelar return err; 836c5441932SPravin B Shelar 837a0efab67SXin Long if (cmd == SIOCCHGTUNNEL) { 838a0efab67SXin Long struct ip_tunnel *t = netdev_priv(dev); 839a0efab67SXin Long 8405832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.i_flags, p->i_flags); 8415832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.o_flags, p->o_flags); 842a0efab67SXin Long 843a0efab67SXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 844a0efab67SXin Long ipgre_link_update(dev, true); 845a0efab67SXin Long } 846a0efab67SXin Long 8475832c4a7SAlexander Lobakin i_flags = gre_tnl_flags_to_gre_flags(p->i_flags); 8485832c4a7SAlexander Lobakin ip_tunnel_flags_from_be16(p->i_flags, i_flags); 8495832c4a7SAlexander Lobakin o_flags = gre_tnl_flags_to_gre_flags(p->o_flags); 8505832c4a7SAlexander Lobakin ip_tunnel_flags_from_be16(p->o_flags, o_flags); 8515832c4a7SAlexander Lobakin 8521da177e4SLinus Torvalds return 0; 8531da177e4SLinus Torvalds } 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 8561da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 8571da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 8611da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 8621da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 8631da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 8661da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 8671da177e4SLinus Torvalds 8681da177e4SLinus Torvalds ping -t 255 224.66.66.66 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds If nobody answers, mbone does not work. 8711da177e4SLinus Torvalds 8721da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 8731da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 8741da177e4SLinus Torvalds ifconfig Universe up 8751da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 8761da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 8771da177e4SLinus Torvalds ftp 10.66.66.66 8781da177e4SLinus Torvalds ... 8791da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 8801da177e4SLinus Torvalds ... 8811da177e4SLinus Torvalds */ 8823b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 8833b04dddeSStephen Hemminger unsigned short type, 8841507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 8851da177e4SLinus Torvalds { 8862941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 887c5441932SPravin B Shelar struct iphdr *iph; 888c5441932SPravin B Shelar struct gre_base_hdr *greh; 889c5441932SPravin B Shelar 890d58ff351SJohannes Berg iph = skb_push(skb, t->hlen + sizeof(*iph)); 891c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 89295f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 893c5441932SPravin B Shelar greh->protocol = htons(type); 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 8961da177e4SLinus Torvalds 897c5441932SPravin B Shelar /* Set the source hardware address. */ 8981da177e4SLinus Torvalds if (saddr) 8991da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 9006d55cb91STimo Teräs if (daddr) 9011da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 9026d55cb91STimo Teräs if (iph->daddr) 90377a482bdSTimo Teräs return t->hlen + sizeof(*iph); 9041da177e4SLinus Torvalds 905c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds 9086a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 9096a5f44d7STimo Teras { 910b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 9116a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 9126a5f44d7STimo Teras return 4; 9136a5f44d7STimo Teras } 9146a5f44d7STimo Teras 9153b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 9163b04dddeSStephen Hemminger .create = ipgre_header, 9176a5f44d7STimo Teras .parse = ipgre_header_parse, 9183b04dddeSStephen Hemminger }; 9193b04dddeSStephen Hemminger 9206a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 9211da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 9221da177e4SLinus Torvalds { 9232941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 9241da177e4SLinus Torvalds 925f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 926cbb1e85fSDavid S. Miller struct flowi4 fl4; 927cbb1e85fSDavid S. Miller struct rtable *rt; 928cbb1e85fSDavid S. Miller 929b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 93078fbfd8aSDavid S. Miller t->parms.iph.daddr, 93178fbfd8aSDavid S. Miller t->parms.iph.saddr, 93278fbfd8aSDavid S. Miller t->parms.o_key, 93378fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 93478fbfd8aSDavid S. Miller t->parms.link); 935b23dd4feSDavid S. Miller if (IS_ERR(rt)) 9361da177e4SLinus Torvalds return -EADDRNOTAVAIL; 937d8d1f30bSChangli Gao dev = rt->dst.dev; 9381da177e4SLinus Torvalds ip_rt_put(rt); 93951456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 9401da177e4SLinus Torvalds return -EADDRNOTAVAIL; 9411da177e4SLinus Torvalds t->mlink = dev->ifindex; 942e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 9431da177e4SLinus Torvalds } 9441da177e4SLinus Torvalds return 0; 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 9481da177e4SLinus Torvalds { 9492941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 950b8c26a33SStephen Hemminger 951f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 9527fee0ca2SDenis V. Lunev struct in_device *in_dev; 953b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 9548723e1b4SEric Dumazet if (in_dev) 9551da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 9561da177e4SLinus Torvalds } 9571da177e4SLinus Torvalds return 0; 9581da177e4SLinus Torvalds } 9591da177e4SLinus Torvalds #endif 9601da177e4SLinus Torvalds 961b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 962b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 963c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 964b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 965b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 966b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 967b8c26a33SStephen Hemminger #endif 968c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 9693e7a1c7cSArnd Bergmann .ndo_siocdevprivate = ip_tunnel_siocdevprivate, 970c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 97198d7fc46SHeiner Kallweit .ndo_get_stats64 = dev_get_tstats64, 9721e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 973607259a6SChristoph Hellwig .ndo_tunnel_ctl = ipgre_tunnel_ctl, 974b8c26a33SStephen Hemminger }; 975b8c26a33SStephen Hemminger 9766b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 9776b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 9786b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 9796b78f16eSEric Dumazet NETIF_F_HW_CSUM) 9806b78f16eSEric Dumazet 9811da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 9821da177e4SLinus Torvalds { 983b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 9845a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 985c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 986c5441932SPravin B Shelar } 9871da177e4SLinus Torvalds 988c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 989c5441932SPravin B Shelar { 990c5441932SPravin B Shelar struct ip_tunnel *tunnel; 991c5441932SPravin B Shelar 992c5441932SPravin B Shelar tunnel = netdev_priv(dev); 99395f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 994c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 995c5441932SPravin B Shelar 9964565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 997fdafed45SCong Wang dev->needed_headroom = tunnel->hlen + sizeof(tunnel->parms.iph); 9984565e991STom Herbert 999*00d066a4SAlexander Lobakin dev->features |= GRE_FEATURES; 10006b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 1001c5441932SPravin B Shelar 1002020e8f60SPeilin Ye /* TCP offload with GRE SEQ is not supported, nor can we support 2 1003020e8f60SPeilin Ye * levels of outer headers requiring an update. 1004a0ca153fSAlexander Duyck */ 10055832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_SEQ_BIT, tunnel->parms.o_flags)) 1006020e8f60SPeilin Ye return; 10075832c4a7SAlexander Lobakin if (test_bit(IP_TUNNEL_CSUM_BIT, tunnel->parms.o_flags) && 10085832c4a7SAlexander Lobakin tunnel->encap.type != TUNNEL_ENCAP_NONE) 1009020e8f60SPeilin Ye return; 1010020e8f60SPeilin Ye 1011c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 1012c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 1013*00d066a4SAlexander Lobakin 1014*00d066a4SAlexander Lobakin dev->lltx = true; 1015a0ca153fSAlexander Duyck } 1016a0ca153fSAlexander Duyck 10171da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 10181da177e4SLinus Torvalds { 1019c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1020c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 10211da177e4SLinus Torvalds 1022c5441932SPravin B Shelar __gre_tunnel_init(dev); 10231da177e4SLinus Torvalds 10245a1b7e1aSJakub Kicinski __dev_addr_set(dev, &iph->saddr, 4); 1025c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 10261da177e4SLinus Torvalds 1027c5441932SPravin B Shelar dev->flags = IFF_NOARP; 102802875878SEric Dumazet netif_keep_dst(dev); 1029c5441932SPravin B Shelar dev->addr_len = 4; 10301da177e4SLinus Torvalds 1031a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 10321da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 1033f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 10341da177e4SLinus Torvalds if (!iph->saddr) 10351da177e4SLinus Torvalds return -EINVAL; 10361da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 10373b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 1038fdafed45SCong Wang dev->hard_header_len = tunnel->hlen + sizeof(*iph); 1039fdafed45SCong Wang dev->needed_headroom = 0; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds #endif 1042a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 10436a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 1044fdafed45SCong Wang dev->hard_header_len = tunnel->hlen + sizeof(*iph); 1045fdafed45SCong Wang dev->needed_headroom = 0; 1046a64b04d8SJiri Benc } 10471da177e4SLinus Torvalds 1048c5441932SPravin B Shelar return ip_tunnel_init(dev); 104960769a5dSEric Dumazet } 105060769a5dSEric Dumazet 10519f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 10529f57c67cSPravin B Shelar .handler = gre_rcv, 10539f57c67cSPravin B Shelar .err_handler = gre_err, 10541da177e4SLinus Torvalds }; 10551da177e4SLinus Torvalds 10562c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 105759a4c759SPavel Emelyanov { 1058c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 105959a4c759SPavel Emelyanov } 106059a4c759SPavel Emelyanov 10619b5b3637SEric Dumazet static void __net_exit ipgre_exit_batch_rtnl(struct list_head *list_net, 10629b5b3637SEric Dumazet struct list_head *dev_to_kill) 106359a4c759SPavel Emelyanov { 10649b5b3637SEric Dumazet ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops, 10659b5b3637SEric Dumazet dev_to_kill); 106659a4c759SPavel Emelyanov } 106759a4c759SPavel Emelyanov 106859a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 106959a4c759SPavel Emelyanov .init = ipgre_init_net, 10709b5b3637SEric Dumazet .exit_batch_rtnl = ipgre_exit_batch_rtnl, 1071cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 1072c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 107359a4c759SPavel Emelyanov }; 10741da177e4SLinus Torvalds 1075a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], 1076a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1077c19e654dSHerbert Xu { 1078c19e654dSHerbert Xu __be16 flags; 1079c19e654dSHerbert Xu 1080c19e654dSHerbert Xu if (!data) 1081c19e654dSHerbert Xu return 0; 1082c19e654dSHerbert Xu 1083c19e654dSHerbert Xu flags = 0; 1084c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1085c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 1086c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1087c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 1088c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 1089c19e654dSHerbert Xu return -EINVAL; 1090c19e654dSHerbert Xu 1091946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 1092946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 1093946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 1094946b636fSJiri Benc return -EINVAL; 1095946b636fSJiri Benc 1096c19e654dSHerbert Xu return 0; 1097c19e654dSHerbert Xu } 1098c19e654dSHerbert Xu 1099a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[], 1100a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1101e1a80002SHerbert Xu { 1102e1a80002SHerbert Xu __be32 daddr; 1103e1a80002SHerbert Xu 1104e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 1105e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 1106e1a80002SHerbert Xu return -EINVAL; 1107e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 1108e1a80002SHerbert Xu return -EADDRNOTAVAIL; 1109e1a80002SHerbert Xu } 1110e1a80002SHerbert Xu 1111e1a80002SHerbert Xu if (!data) 1112e1a80002SHerbert Xu goto out; 1113e1a80002SHerbert Xu 1114e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 1115e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 1116e1a80002SHerbert Xu if (!daddr) 1117e1a80002SHerbert Xu return -EINVAL; 1118e1a80002SHerbert Xu } 1119e1a80002SHerbert Xu 1120e1a80002SHerbert Xu out: 1121a8b8a889SMatthias Schiffer return ipgre_tunnel_validate(tb, data, extack); 1122e1a80002SHerbert Xu } 1123e1a80002SHerbert Xu 112484e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[], 112584e54fe0SWilliam Tu struct netlink_ext_ack *extack) 112684e54fe0SWilliam Tu { 112784e54fe0SWilliam Tu __be16 flags = 0; 112884e54fe0SWilliam Tu int ret; 112984e54fe0SWilliam Tu 113084e54fe0SWilliam Tu if (!data) 113184e54fe0SWilliam Tu return 0; 113284e54fe0SWilliam Tu 113384e54fe0SWilliam Tu ret = ipgre_tap_validate(tb, data, extack); 113484e54fe0SWilliam Tu if (ret) 113584e54fe0SWilliam Tu return ret; 113684e54fe0SWilliam Tu 113751fa960dSWilliam Tu if (data[IFLA_GRE_ERSPAN_VER] && 113851fa960dSWilliam Tu nla_get_u8(data[IFLA_GRE_ERSPAN_VER]) == 0) 1139f989d546SWilliam Tu return 0; 1140f989d546SWilliam Tu 1141f989d546SWilliam Tu /* ERSPAN type II/III should only have GRE sequence and key flag */ 11421a66a836SWilliam Tu if (data[IFLA_GRE_OFLAGS]) 114384e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 11441a66a836SWilliam Tu if (data[IFLA_GRE_IFLAGS]) 114584e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 11461a66a836SWilliam Tu if (!data[IFLA_GRE_COLLECT_METADATA] && 11471a66a836SWilliam Tu flags != (GRE_SEQ | GRE_KEY)) 114884e54fe0SWilliam Tu return -EINVAL; 114984e54fe0SWilliam Tu 115084e54fe0SWilliam Tu /* ERSPAN Session ID only has 10-bit. Since we reuse 115184e54fe0SWilliam Tu * 32-bit key field as ID, check it's range. 115284e54fe0SWilliam Tu */ 115384e54fe0SWilliam Tu if (data[IFLA_GRE_IKEY] && 115484e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) 115584e54fe0SWilliam Tu return -EINVAL; 115684e54fe0SWilliam Tu 115784e54fe0SWilliam Tu if (data[IFLA_GRE_OKEY] && 115884e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) 115984e54fe0SWilliam Tu return -EINVAL; 116084e54fe0SWilliam Tu 116184e54fe0SWilliam Tu return 0; 116284e54fe0SWilliam Tu } 116384e54fe0SWilliam Tu 116422a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev, 11652e15ea39SPravin B Shelar struct nlattr *data[], 11662e15ea39SPravin B Shelar struct nlattr *tb[], 1167117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms, 11689830ad4cSCraig Gallek __u32 *fwmark) 1169c19e654dSHerbert Xu { 117022a59be8SPhilip Prindeville struct ip_tunnel *t = netdev_priv(dev); 117122a59be8SPhilip Prindeville 11727bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 1173c19e654dSHerbert Xu 1174c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 1175c19e654dSHerbert Xu 1176c19e654dSHerbert Xu if (!data) 117722a59be8SPhilip Prindeville return 0; 1178c19e654dSHerbert Xu 1179c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 1180c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 1181c19e654dSHerbert Xu 1182c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 11835832c4a7SAlexander Lobakin gre_flags_to_tnl_flags(parms->i_flags, 11845832c4a7SAlexander Lobakin nla_get_be16(data[IFLA_GRE_IFLAGS])); 1185c19e654dSHerbert Xu 1186c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 11875832c4a7SAlexander Lobakin gre_flags_to_tnl_flags(parms->o_flags, 11885832c4a7SAlexander Lobakin nla_get_be16(data[IFLA_GRE_OFLAGS])); 1189c19e654dSHerbert Xu 1190c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 1191c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 1192c19e654dSHerbert Xu 1193c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 1194c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 1195c19e654dSHerbert Xu 1196c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 119767b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 1198c19e654dSHerbert Xu 1199c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 120067b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 1201c19e654dSHerbert Xu 1202c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 1203c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 1204c19e654dSHerbert Xu 1205c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 1206c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 1207c19e654dSHerbert Xu 120822a59be8SPhilip Prindeville if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { 120922a59be8SPhilip Prindeville if (t->ignore_df) 121022a59be8SPhilip Prindeville return -EINVAL; 1211c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 121222a59be8SPhilip Prindeville } 12132e15ea39SPravin B Shelar 12142e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 12152e15ea39SPravin B Shelar t->collect_md = true; 1216e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 1217e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 12182e15ea39SPravin B Shelar } 121922a59be8SPhilip Prindeville 122022a59be8SPhilip Prindeville if (data[IFLA_GRE_IGNORE_DF]) { 122122a59be8SPhilip Prindeville if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) 122222a59be8SPhilip Prindeville && (parms->iph.frag_off & htons(IP_DF))) 122322a59be8SPhilip Prindeville return -EINVAL; 122422a59be8SPhilip Prindeville t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); 122522a59be8SPhilip Prindeville } 122622a59be8SPhilip Prindeville 12279830ad4cSCraig Gallek if (data[IFLA_GRE_FWMARK]) 12289830ad4cSCraig Gallek *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); 12299830ad4cSCraig Gallek 1230e1f8f78fSPetr Machata return 0; 1231e1f8f78fSPetr Machata } 1232e1f8f78fSPetr Machata 1233e1f8f78fSPetr Machata static int erspan_netlink_parms(struct net_device *dev, 1234e1f8f78fSPetr Machata struct nlattr *data[], 1235e1f8f78fSPetr Machata struct nlattr *tb[], 1236117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *parms, 1237e1f8f78fSPetr Machata __u32 *fwmark) 1238e1f8f78fSPetr Machata { 1239e1f8f78fSPetr Machata struct ip_tunnel *t = netdev_priv(dev); 1240e1f8f78fSPetr Machata int err; 1241e1f8f78fSPetr Machata 1242e1f8f78fSPetr Machata err = ipgre_netlink_parms(dev, data, tb, parms, fwmark); 1243e1f8f78fSPetr Machata if (err) 1244e1f8f78fSPetr Machata return err; 124532ca98feSPetr Machata if (!data) 124632ca98feSPetr Machata return 0; 1247e1f8f78fSPetr Machata 1248f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_VER]) { 1249f551c91dSWilliam Tu t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); 1250f551c91dSWilliam Tu 1251f989d546SWilliam Tu if (t->erspan_ver > 2) 1252f551c91dSWilliam Tu return -EINVAL; 1253f551c91dSWilliam Tu } 1254f551c91dSWilliam Tu 1255f551c91dSWilliam Tu if (t->erspan_ver == 1) { 125684e54fe0SWilliam Tu if (data[IFLA_GRE_ERSPAN_INDEX]) { 125784e54fe0SWilliam Tu t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); 125884e54fe0SWilliam Tu if (t->index & ~INDEX_MASK) 125984e54fe0SWilliam Tu return -EINVAL; 126084e54fe0SWilliam Tu } 1261f551c91dSWilliam Tu } else if (t->erspan_ver == 2) { 1262f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_DIR]) { 1263f551c91dSWilliam Tu t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); 1264f551c91dSWilliam Tu if (t->dir & ~(DIR_MASK >> DIR_OFFSET)) 1265f551c91dSWilliam Tu return -EINVAL; 1266f551c91dSWilliam Tu } 1267f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_HWID]) { 1268f551c91dSWilliam Tu t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); 1269f551c91dSWilliam Tu if (t->hwid & ~(HWID_MASK >> HWID_OFFSET)) 1270f551c91dSWilliam Tu return -EINVAL; 1271f551c91dSWilliam Tu } 1272f551c91dSWilliam Tu } 127384e54fe0SWilliam Tu 127422a59be8SPhilip Prindeville return 0; 1275c19e654dSHerbert Xu } 1276c19e654dSHerbert Xu 12774565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 12784565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 12794565e991STom Herbert struct ip_tunnel_encap *ipencap) 12804565e991STom Herbert { 12814565e991STom Herbert bool ret = false; 12824565e991STom Herbert 12834565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 12844565e991STom Herbert 12854565e991STom Herbert if (!data) 12864565e991STom Herbert return ret; 12874565e991STom Herbert 12884565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 12894565e991STom Herbert ret = true; 12904565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 12914565e991STom Herbert } 12924565e991STom Herbert 12934565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 12944565e991STom Herbert ret = true; 12954565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 12964565e991STom Herbert } 12974565e991STom Herbert 12984565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 12994565e991STom Herbert ret = true; 13003e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 13014565e991STom Herbert } 13024565e991STom Herbert 13034565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 13044565e991STom Herbert ret = true; 13053e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 13064565e991STom Herbert } 13074565e991STom Herbert 13084565e991STom Herbert return ret; 13094565e991STom Herbert } 13104565e991STom Herbert 1311c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1312e1a80002SHerbert Xu { 1313c5441932SPravin B Shelar __gre_tunnel_init(dev); 1314bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1315d51711c0SXin Long netif_keep_dst(dev); 1316e1a80002SHerbert Xu 1317c5441932SPravin B Shelar return ip_tunnel_init(dev); 1318e1a80002SHerbert Xu } 1319e1a80002SHerbert Xu 1320c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1321c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1322c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1323c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1324b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1325b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1326c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 132798d7fc46SHeiner Kallweit .ndo_get_stats64 = dev_get_tstats64, 13281e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1329fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 1330b8c26a33SStephen Hemminger }; 1331b8c26a33SStephen Hemminger 133284e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev) 133384e54fe0SWilliam Tu { 133484e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 133584e54fe0SWilliam Tu 1336f989d546SWilliam Tu if (tunnel->erspan_ver == 0) 1337f989d546SWilliam Tu tunnel->tun_hlen = 4; /* 4-byte GRE hdr. */ 1338f989d546SWilliam Tu else 1339f989d546SWilliam Tu tunnel->tun_hlen = 8; /* 8-byte GRE hdr. */ 1340f989d546SWilliam Tu 134184e54fe0SWilliam Tu tunnel->parms.iph.protocol = IPPROTO_GRE; 1342c122fda2SXin Long tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + 1343f551c91dSWilliam Tu erspan_hdr_len(tunnel->erspan_ver); 134484e54fe0SWilliam Tu 134584e54fe0SWilliam Tu dev->features |= GRE_FEATURES; 134684e54fe0SWilliam Tu dev->hw_features |= GRE_FEATURES; 134784e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1348c84bed44SXin Long netif_keep_dst(dev); 134984e54fe0SWilliam Tu 135084e54fe0SWilliam Tu return ip_tunnel_init(dev); 135184e54fe0SWilliam Tu } 135284e54fe0SWilliam Tu 135384e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = { 135484e54fe0SWilliam Tu .ndo_init = erspan_tunnel_init, 135584e54fe0SWilliam Tu .ndo_uninit = ip_tunnel_uninit, 135684e54fe0SWilliam Tu .ndo_start_xmit = erspan_xmit, 135784e54fe0SWilliam Tu .ndo_set_mac_address = eth_mac_addr, 135884e54fe0SWilliam Tu .ndo_validate_addr = eth_validate_addr, 135984e54fe0SWilliam Tu .ndo_change_mtu = ip_tunnel_change_mtu, 136098d7fc46SHeiner Kallweit .ndo_get_stats64 = dev_get_tstats64, 136184e54fe0SWilliam Tu .ndo_get_iflink = ip_tunnel_get_iflink, 136284e54fe0SWilliam Tu .ndo_fill_metadata_dst = gre_fill_metadata_dst, 136384e54fe0SWilliam Tu }; 136484e54fe0SWilliam Tu 1365e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1366e1a80002SHerbert Xu { 1367e1a80002SHerbert Xu ether_setup(dev); 1368cfddd4c3SXin Long dev->max_mtu = 0; 1369c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1370d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 1371f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1372c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1373e1a80002SHerbert Xu } 1374e1a80002SHerbert Xu 1375e1f8f78fSPetr Machata static int 1376e1f8f78fSPetr Machata ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[]) 1377c19e654dSHerbert Xu { 13784565e991STom Herbert struct ip_tunnel_encap ipencap; 13794565e991STom Herbert 13804565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 13814565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 1382e1f8f78fSPetr Machata int err = ip_tunnel_encap_setup(t, &ipencap); 13834565e991STom Herbert 13844565e991STom Herbert if (err < 0) 13854565e991STom Herbert return err; 13864565e991STom Herbert } 1387c19e654dSHerbert Xu 1388e1f8f78fSPetr Machata return 0; 1389e1f8f78fSPetr Machata } 1390e1f8f78fSPetr Machata 1391e1f8f78fSPetr Machata static int ipgre_newlink(struct net *src_net, struct net_device *dev, 1392e1f8f78fSPetr Machata struct nlattr *tb[], struct nlattr *data[], 1393e1f8f78fSPetr Machata struct netlink_ext_ack *extack) 1394e1f8f78fSPetr Machata { 1395117aef12SAlexander Lobakin struct ip_tunnel_parm_kern p; 1396e1f8f78fSPetr Machata __u32 fwmark = 0; 1397e1f8f78fSPetr Machata int err; 1398e1f8f78fSPetr Machata 1399e1f8f78fSPetr Machata err = ipgre_newlink_encap_setup(dev, data); 1400e1f8f78fSPetr Machata if (err) 1401e1f8f78fSPetr Machata return err; 1402e1f8f78fSPetr Machata 14039830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 140422a59be8SPhilip Prindeville if (err < 0) 140522a59be8SPhilip Prindeville return err; 14069830ad4cSCraig Gallek return ip_tunnel_newlink(dev, tb, &p, fwmark); 1407c19e654dSHerbert Xu } 1408c19e654dSHerbert Xu 1409e1f8f78fSPetr Machata static int erspan_newlink(struct net *src_net, struct net_device *dev, 1410e1f8f78fSPetr Machata struct nlattr *tb[], struct nlattr *data[], 1411e1f8f78fSPetr Machata struct netlink_ext_ack *extack) 1412e1f8f78fSPetr Machata { 1413117aef12SAlexander Lobakin struct ip_tunnel_parm_kern p; 1414e1f8f78fSPetr Machata __u32 fwmark = 0; 1415e1f8f78fSPetr Machata int err; 1416e1f8f78fSPetr Machata 1417e1f8f78fSPetr Machata err = ipgre_newlink_encap_setup(dev, data); 1418e1f8f78fSPetr Machata if (err) 1419e1f8f78fSPetr Machata return err; 1420e1f8f78fSPetr Machata 1421e1f8f78fSPetr Machata err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); 1422e1f8f78fSPetr Machata if (err) 1423e1f8f78fSPetr Machata return err; 1424e1f8f78fSPetr Machata return ip_tunnel_newlink(dev, tb, &p, fwmark); 1425e1f8f78fSPetr Machata } 1426e1f8f78fSPetr Machata 1427c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1428ad744b22SMatthias Schiffer struct nlattr *data[], 1429ad744b22SMatthias Schiffer struct netlink_ext_ack *extack) 1430c19e654dSHerbert Xu { 14319830ad4cSCraig Gallek struct ip_tunnel *t = netdev_priv(dev); 1432117aef12SAlexander Lobakin struct ip_tunnel_parm_kern p; 14339830ad4cSCraig Gallek __u32 fwmark = t->fwmark; 143422a59be8SPhilip Prindeville int err; 14354565e991STom Herbert 1436e1f8f78fSPetr Machata err = ipgre_newlink_encap_setup(dev, data); 1437e1f8f78fSPetr Machata if (err) 14384565e991STom Herbert return err; 1439c19e654dSHerbert Xu 14409830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 144122a59be8SPhilip Prindeville if (err < 0) 144222a59be8SPhilip Prindeville return err; 1443dd9d598cSXin Long 1444dd9d598cSXin Long err = ip_tunnel_changelink(dev, tb, &p, fwmark); 1445dd9d598cSXin Long if (err < 0) 1446dd9d598cSXin Long return err; 1447dd9d598cSXin Long 14485832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.i_flags, p.i_flags); 14495832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.o_flags, p.o_flags); 1450dd9d598cSXin Long 1451dd9d598cSXin Long ipgre_link_update(dev, !tb[IFLA_MTU]); 1452dd9d598cSXin Long 1453dd9d598cSXin Long return 0; 1454c19e654dSHerbert Xu } 1455c19e654dSHerbert Xu 1456e1f8f78fSPetr Machata static int erspan_changelink(struct net_device *dev, struct nlattr *tb[], 1457e1f8f78fSPetr Machata struct nlattr *data[], 1458e1f8f78fSPetr Machata struct netlink_ext_ack *extack) 1459e1f8f78fSPetr Machata { 1460e1f8f78fSPetr Machata struct ip_tunnel *t = netdev_priv(dev); 1461117aef12SAlexander Lobakin struct ip_tunnel_parm_kern p; 1462e1f8f78fSPetr Machata __u32 fwmark = t->fwmark; 1463e1f8f78fSPetr Machata int err; 1464e1f8f78fSPetr Machata 1465e1f8f78fSPetr Machata err = ipgre_newlink_encap_setup(dev, data); 1466e1f8f78fSPetr Machata if (err) 1467e1f8f78fSPetr Machata return err; 1468e1f8f78fSPetr Machata 1469e1f8f78fSPetr Machata err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); 1470e1f8f78fSPetr Machata if (err < 0) 1471e1f8f78fSPetr Machata return err; 1472e1f8f78fSPetr Machata 1473e1f8f78fSPetr Machata err = ip_tunnel_changelink(dev, tb, &p, fwmark); 1474e1f8f78fSPetr Machata if (err < 0) 1475e1f8f78fSPetr Machata return err; 1476e1f8f78fSPetr Machata 14775832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.i_flags, p.i_flags); 14785832c4a7SAlexander Lobakin ip_tunnel_flags_copy(t->parms.o_flags, p.o_flags); 1479e1f8f78fSPetr Machata 1480e1f8f78fSPetr Machata return 0; 1481e1f8f78fSPetr Machata } 1482e1f8f78fSPetr Machata 1483c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1484c19e654dSHerbert Xu { 1485c19e654dSHerbert Xu return 1486c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1487c19e654dSHerbert Xu nla_total_size(4) + 1488c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1489c19e654dSHerbert Xu nla_total_size(2) + 1490c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1491c19e654dSHerbert Xu nla_total_size(2) + 1492c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1493c19e654dSHerbert Xu nla_total_size(4) + 1494c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1495c19e654dSHerbert Xu nla_total_size(4) + 1496c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1497c19e654dSHerbert Xu nla_total_size(4) + 1498c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1499c19e654dSHerbert Xu nla_total_size(4) + 1500c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1501c19e654dSHerbert Xu nla_total_size(1) + 1502c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1503c19e654dSHerbert Xu nla_total_size(1) + 1504c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1505c19e654dSHerbert Xu nla_total_size(1) + 15064565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 15074565e991STom Herbert nla_total_size(2) + 15084565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 15094565e991STom Herbert nla_total_size(2) + 15104565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 15114565e991STom Herbert nla_total_size(2) + 15124565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 15134565e991STom Herbert nla_total_size(2) + 15142e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 15152e15ea39SPravin B Shelar nla_total_size(0) + 151622a59be8SPhilip Prindeville /* IFLA_GRE_IGNORE_DF */ 151722a59be8SPhilip Prindeville nla_total_size(1) + 15189830ad4cSCraig Gallek /* IFLA_GRE_FWMARK */ 15199830ad4cSCraig Gallek nla_total_size(4) + 152084e54fe0SWilliam Tu /* IFLA_GRE_ERSPAN_INDEX */ 152184e54fe0SWilliam Tu nla_total_size(4) + 1522f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_VER */ 1523f551c91dSWilliam Tu nla_total_size(1) + 1524f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_DIR */ 1525f551c91dSWilliam Tu nla_total_size(1) + 1526f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_HWID */ 1527f551c91dSWilliam Tu nla_total_size(2) + 1528c19e654dSHerbert Xu 0; 1529c19e654dSHerbert Xu } 1530c19e654dSHerbert Xu 1531c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1532c19e654dSHerbert Xu { 1533c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1534117aef12SAlexander Lobakin struct ip_tunnel_parm_kern *p = &t->parms; 15355832c4a7SAlexander Lobakin IP_TUNNEL_DECLARE_FLAGS(o_flags); 15365832c4a7SAlexander Lobakin 15375832c4a7SAlexander Lobakin ip_tunnel_flags_copy(o_flags, p->o_flags); 1538feaf5c79SLorenzo Bianconi 1539f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 154095f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 154195f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 154295f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 1543feaf5c79SLorenzo Bianconi gre_tnl_flags_to_gre_flags(o_flags)) || 1544f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1545f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1546930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1547930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1548f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1549f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1550f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 15519830ad4cSCraig Gallek !!(p->iph.frag_off & htons(IP_DF))) || 15529830ad4cSCraig Gallek nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark)) 1553f3756b79SDavid S. Miller goto nla_put_failure; 15544565e991STom Herbert 15554565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 15564565e991STom Herbert t->encap.type) || 15573e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 15584565e991STom Herbert t->encap.sport) || 15593e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 15604565e991STom Herbert t->encap.dport) || 15614565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1562e1b2cb65STom Herbert t->encap.flags)) 15634565e991STom Herbert goto nla_put_failure; 15644565e991STom Herbert 156522a59be8SPhilip Prindeville if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df)) 156622a59be8SPhilip Prindeville goto nla_put_failure; 156722a59be8SPhilip Prindeville 15682e15ea39SPravin B Shelar if (t->collect_md) { 15692e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 15702e15ea39SPravin B Shelar goto nla_put_failure; 15712e15ea39SPravin B Shelar } 15722e15ea39SPravin B Shelar 1573c19e654dSHerbert Xu return 0; 1574c19e654dSHerbert Xu 1575c19e654dSHerbert Xu nla_put_failure: 1576c19e654dSHerbert Xu return -EMSGSIZE; 1577c19e654dSHerbert Xu } 1578c19e654dSHerbert Xu 1579ee496694SHangbin Liu static int erspan_fill_info(struct sk_buff *skb, const struct net_device *dev) 1580ee496694SHangbin Liu { 1581ee496694SHangbin Liu struct ip_tunnel *t = netdev_priv(dev); 1582ee496694SHangbin Liu 1583ee496694SHangbin Liu if (t->erspan_ver <= 2) { 1584ee496694SHangbin Liu if (t->erspan_ver != 0 && !t->collect_md) 15855832c4a7SAlexander Lobakin __set_bit(IP_TUNNEL_KEY_BIT, t->parms.o_flags); 1586ee496694SHangbin Liu 1587ee496694SHangbin Liu if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver)) 1588ee496694SHangbin Liu goto nla_put_failure; 1589ee496694SHangbin Liu 1590ee496694SHangbin Liu if (t->erspan_ver == 1) { 1591ee496694SHangbin Liu if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) 1592ee496694SHangbin Liu goto nla_put_failure; 1593ee496694SHangbin Liu } else if (t->erspan_ver == 2) { 1594ee496694SHangbin Liu if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir)) 1595ee496694SHangbin Liu goto nla_put_failure; 1596ee496694SHangbin Liu if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid)) 1597ee496694SHangbin Liu goto nla_put_failure; 1598ee496694SHangbin Liu } 1599ee496694SHangbin Liu } 1600ee496694SHangbin Liu 1601ee496694SHangbin Liu return ipgre_fill_info(skb, dev); 1602ee496694SHangbin Liu 1603ee496694SHangbin Liu nla_put_failure: 1604ee496694SHangbin Liu return -EMSGSIZE; 1605ee496694SHangbin Liu } 1606ee496694SHangbin Liu 160784e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev) 160884e54fe0SWilliam Tu { 160984581bdaSXin Long struct ip_tunnel *t = netdev_priv(dev); 161084581bdaSXin Long 161184e54fe0SWilliam Tu ether_setup(dev); 16120e141f75SHaishuang Yan dev->max_mtu = 0; 161384e54fe0SWilliam Tu dev->netdev_ops = &erspan_netdev_ops; 161484e54fe0SWilliam Tu dev->priv_flags &= ~IFF_TX_SKB_SHARING; 161584e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 161684e54fe0SWilliam Tu ip_tunnel_setup(dev, erspan_net_id); 161784581bdaSXin Long t->erspan_ver = 1; 161884e54fe0SWilliam Tu } 161984e54fe0SWilliam Tu 1620c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1621c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1622c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1623c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1624c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1625c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 1626c593642cSPankaj Bharadiya [IFLA_GRE_LOCAL] = { .len = sizeof_field(struct iphdr, saddr) }, 1627c593642cSPankaj Bharadiya [IFLA_GRE_REMOTE] = { .len = sizeof_field(struct iphdr, daddr) }, 1628c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1629c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1630c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 16314565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 16324565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 16334565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 16344565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 16352e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 163622a59be8SPhilip Prindeville [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, 16379830ad4cSCraig Gallek [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, 163884e54fe0SWilliam Tu [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, 1639f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, 1640f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, 1641f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, 1642c19e654dSHerbert Xu }; 1643c19e654dSHerbert Xu 1644c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1645c19e654dSHerbert Xu .kind = "gre", 1646c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1647c19e654dSHerbert Xu .policy = ipgre_policy, 1648c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1649c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1650c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1651c19e654dSHerbert Xu .newlink = ipgre_newlink, 1652c19e654dSHerbert Xu .changelink = ipgre_changelink, 1653c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1654c19e654dSHerbert Xu .get_size = ipgre_get_size, 1655c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 16561728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1657c19e654dSHerbert Xu }; 1658c19e654dSHerbert Xu 1659e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1660e1a80002SHerbert Xu .kind = "gretap", 1661e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1662e1a80002SHerbert Xu .policy = ipgre_policy, 1663e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1664e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1665e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1666e1a80002SHerbert Xu .newlink = ipgre_newlink, 1667e1a80002SHerbert Xu .changelink = ipgre_changelink, 1668c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1669e1a80002SHerbert Xu .get_size = ipgre_get_size, 1670e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 16711728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1672e1a80002SHerbert Xu }; 1673e1a80002SHerbert Xu 167484e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = { 167584e54fe0SWilliam Tu .kind = "erspan", 167684e54fe0SWilliam Tu .maxtype = IFLA_GRE_MAX, 167784e54fe0SWilliam Tu .policy = ipgre_policy, 167884e54fe0SWilliam Tu .priv_size = sizeof(struct ip_tunnel), 167984e54fe0SWilliam Tu .setup = erspan_setup, 168084e54fe0SWilliam Tu .validate = erspan_validate, 1681e1f8f78fSPetr Machata .newlink = erspan_newlink, 1682e1f8f78fSPetr Machata .changelink = erspan_changelink, 168384e54fe0SWilliam Tu .dellink = ip_tunnel_dellink, 168484e54fe0SWilliam Tu .get_size = ipgre_get_size, 1685ee496694SHangbin Liu .fill_info = erspan_fill_info, 168684e54fe0SWilliam Tu .get_link_net = ip_tunnel_get_link_net, 168784e54fe0SWilliam Tu }; 168884e54fe0SWilliam Tu 1689b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1690b2acd1dcSPravin B Shelar u8 name_assign_type) 1691b2acd1dcSPravin B Shelar { 1692b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1693b2acd1dcSPravin B Shelar struct net_device *dev; 1694106da663SNicolas Dichtel LIST_HEAD(list_kill); 1695b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1696b2acd1dcSPravin B Shelar int err; 1697b2acd1dcSPravin B Shelar 1698b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1699b2acd1dcSPravin B Shelar 1700b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1701d0522f1cSDavid Ahern &ipgre_tap_ops, tb, NULL); 1702b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1703b2acd1dcSPravin B Shelar return dev; 1704b2acd1dcSPravin B Shelar 1705b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1706b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1707b2acd1dcSPravin B Shelar t->collect_md = true; 1708b2acd1dcSPravin B Shelar 17097a3f4a18SMatthias Schiffer err = ipgre_newlink(net, dev, tb, NULL, NULL); 1710106da663SNicolas Dichtel if (err < 0) { 1711106da663SNicolas Dichtel free_netdev(dev); 1712106da663SNicolas Dichtel return ERR_PTR(err); 1713106da663SNicolas Dichtel } 17147e059158SDavid Wragg 17157e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 17167e059158SDavid Wragg * so set the largest MTU we can. 17177e059158SDavid Wragg */ 17187e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 17197e059158SDavid Wragg if (err) 17207e059158SDavid Wragg goto out; 17217e059158SDavid Wragg 17221d997f10SHangbin Liu err = rtnl_configure_link(dev, NULL, 0, NULL); 1723da6f1da8SNicolas Dichtel if (err < 0) 1724da6f1da8SNicolas Dichtel goto out; 1725da6f1da8SNicolas Dichtel 1726b2acd1dcSPravin B Shelar return dev; 1727b2acd1dcSPravin B Shelar out: 1728106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1729106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1730b2acd1dcSPravin B Shelar return ERR_PTR(err); 1731b2acd1dcSPravin B Shelar } 1732b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1733b2acd1dcSPravin B Shelar 1734c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1735c5441932SPravin B Shelar { 17362e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1737c5441932SPravin B Shelar } 1738c5441932SPravin B Shelar 17399b5b3637SEric Dumazet static void __net_exit ipgre_tap_exit_batch_rtnl(struct list_head *list_net, 17409b5b3637SEric Dumazet struct list_head *dev_to_kill) 1741c5441932SPravin B Shelar { 17429b5b3637SEric Dumazet ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops, 17439b5b3637SEric Dumazet dev_to_kill); 1744c5441932SPravin B Shelar } 1745c5441932SPravin B Shelar 1746c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1747c5441932SPravin B Shelar .init = ipgre_tap_init_net, 17489b5b3637SEric Dumazet .exit_batch_rtnl = ipgre_tap_exit_batch_rtnl, 1749c5441932SPravin B Shelar .id = &gre_tap_net_id, 1750c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1751c5441932SPravin B Shelar }; 17521da177e4SLinus Torvalds 175384e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net) 175484e54fe0SWilliam Tu { 175584e54fe0SWilliam Tu return ip_tunnel_init_net(net, erspan_net_id, 175684e54fe0SWilliam Tu &erspan_link_ops, "erspan0"); 175784e54fe0SWilliam Tu } 175884e54fe0SWilliam Tu 17599b5b3637SEric Dumazet static void __net_exit erspan_exit_batch_rtnl(struct list_head *net_list, 17609b5b3637SEric Dumazet struct list_head *dev_to_kill) 176184e54fe0SWilliam Tu { 17629b5b3637SEric Dumazet ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops, 17639b5b3637SEric Dumazet dev_to_kill); 176484e54fe0SWilliam Tu } 176584e54fe0SWilliam Tu 176684e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = { 176784e54fe0SWilliam Tu .init = erspan_init_net, 17689b5b3637SEric Dumazet .exit_batch_rtnl = erspan_exit_batch_rtnl, 176984e54fe0SWilliam Tu .id = &erspan_net_id, 177084e54fe0SWilliam Tu .size = sizeof(struct ip_tunnel_net), 177184e54fe0SWilliam Tu }; 177284e54fe0SWilliam Tu 17731da177e4SLinus Torvalds static int __init ipgre_init(void) 17741da177e4SLinus Torvalds { 17751da177e4SLinus Torvalds int err; 17761da177e4SLinus Torvalds 1777058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 17781da177e4SLinus Torvalds 1779cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 178059a4c759SPavel Emelyanov if (err < 0) 1781c2892f02SAlexey Dobriyan return err; 1782c2892f02SAlexey Dobriyan 1783c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1784c5441932SPravin B Shelar if (err < 0) 1785e3d0328cSWilliam Tu goto pnet_tap_failed; 1786c5441932SPravin B Shelar 178784e54fe0SWilliam Tu err = register_pernet_device(&erspan_net_ops); 178884e54fe0SWilliam Tu if (err < 0) 178984e54fe0SWilliam Tu goto pnet_erspan_failed; 179084e54fe0SWilliam Tu 17919f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1792c2892f02SAlexey Dobriyan if (err < 0) { 1793058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1794c2892f02SAlexey Dobriyan goto add_proto_failed; 1795c2892f02SAlexey Dobriyan } 17967daa0004SPavel Emelyanov 1797c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1798c19e654dSHerbert Xu if (err < 0) 1799c19e654dSHerbert Xu goto rtnl_link_failed; 1800c19e654dSHerbert Xu 1801e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1802e1a80002SHerbert Xu if (err < 0) 1803e1a80002SHerbert Xu goto tap_ops_failed; 1804e1a80002SHerbert Xu 180584e54fe0SWilliam Tu err = rtnl_link_register(&erspan_link_ops); 180684e54fe0SWilliam Tu if (err < 0) 180784e54fe0SWilliam Tu goto erspan_link_failed; 180884e54fe0SWilliam Tu 1809c5441932SPravin B Shelar return 0; 1810c19e654dSHerbert Xu 181184e54fe0SWilliam Tu erspan_link_failed: 181284e54fe0SWilliam Tu rtnl_link_unregister(&ipgre_tap_ops); 1813e1a80002SHerbert Xu tap_ops_failed: 1814e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1815c19e654dSHerbert Xu rtnl_link_failed: 18169f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1817c2892f02SAlexey Dobriyan add_proto_failed: 181884e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 181984e54fe0SWilliam Tu pnet_erspan_failed: 1820c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1821e3d0328cSWilliam Tu pnet_tap_failed: 1822c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1823c5441932SPravin B Shelar return err; 18241da177e4SLinus Torvalds } 18251da177e4SLinus Torvalds 1826db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 18271da177e4SLinus Torvalds { 1828e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1829c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 183084e54fe0SWilliam Tu rtnl_link_unregister(&erspan_link_ops); 18319f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1832c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1833c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 183484e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 18351da177e4SLinus Torvalds } 18361da177e4SLinus Torvalds 18371da177e4SLinus Torvalds module_init(ipgre_init); 18381da177e4SLinus Torvalds module_exit(ipgre_fini); 1839b058a5d2SBreno Leitao MODULE_DESCRIPTION("IPv4 GRE tunnels over IP library"); 18401da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 18414d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 18424d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 184384e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan"); 18448909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1845c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 184684e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0"); 1847