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; 1101da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev); 1111a66a836SWilliam Tu static void erspan_build_header(struct sk_buff *skb, 112c69de58bSWilliam Tu u32 id, u32 index, 113a3222dc9SWilliam Tu bool truncate, bool is_ipv4); 114eb8ce741SPavel Emelyanov 115c7d03a00SAlexey Dobriyan static unsigned int ipgre_net_id __read_mostly; 116c7d03a00SAlexey Dobriyan static unsigned int gre_tap_net_id __read_mostly; 11784e54fe0SWilliam Tu static unsigned int erspan_net_id __read_mostly; 118eb8ce741SPavel Emelyanov 11932bbd879SStefano Brivio static int ipgre_err(struct sk_buff *skb, u32 info, 120bda7bb46SPravin B Shelar const struct tnl_ptk_info *tpi) 1211da177e4SLinus Torvalds { 1221da177e4SLinus Torvalds 123071f92d0SRami Rosen /* All the routers (except for Linux) return only 1241da177e4SLinus Torvalds 8 bytes of packet payload. It means, that precise relaying of 1251da177e4SLinus Torvalds ICMP in the real Internet is absolutely infeasible. 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds Moreover, Cisco "wise men" put GRE key to the third word 128c5441932SPravin B Shelar in GRE header. It makes impossible maintaining even soft 129c5441932SPravin B Shelar state for keyed GRE tunnels with enabled checksum. Tell 130c5441932SPravin B Shelar them "thank you". 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds Well, I wonder, rfc1812 was written by Cisco employee, 133bff52857Sstephen hemminger what the hell these idiots break standards established 134bff52857Sstephen hemminger by themselves??? 1351da177e4SLinus Torvalds */ 136c5441932SPravin B Shelar struct net *net = dev_net(skb->dev); 137c5441932SPravin B Shelar struct ip_tunnel_net *itn; 13896f5a846SEric Dumazet const struct iphdr *iph; 13988c7664fSArnaldo Carvalho de Melo const int type = icmp_hdr(skb)->type; 14088c7664fSArnaldo Carvalho de Melo const int code = icmp_hdr(skb)->code; 14120e1954fSEric Dumazet unsigned int data_len = 0; 1421da177e4SLinus Torvalds struct ip_tunnel *t; 143d2083287Sstephen hemminger 144bda7bb46SPravin B Shelar if (tpi->proto == htons(ETH_P_TEB)) 145c5441932SPravin B Shelar itn = net_generic(net, gre_tap_net_id); 14651dc63e3SHaishuang Yan else if (tpi->proto == htons(ETH_P_ERSPAN) || 14751dc63e3SHaishuang Yan tpi->proto == htons(ETH_P_ERSPAN2)) 14851dc63e3SHaishuang Yan itn = net_generic(net, erspan_net_id); 149c5441932SPravin B Shelar else 150c5441932SPravin B Shelar itn = net_generic(net, ipgre_net_id); 151c5441932SPravin B Shelar 152c0c0c50fSDuan Jiong iph = (const struct iphdr *)(icmp_hdr(skb) + 1); 153bda7bb46SPravin B Shelar t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 154bda7bb46SPravin B Shelar iph->daddr, iph->saddr, tpi->key); 155d2083287Sstephen hemminger 15651456b29SIan Morris if (!t) 15732bbd879SStefano Brivio return -ENOENT; 15832bbd879SStefano Brivio 15932bbd879SStefano Brivio switch (type) { 16032bbd879SStefano Brivio default: 16132bbd879SStefano Brivio case ICMP_PARAMETERPROB: 16232bbd879SStefano Brivio return 0; 16332bbd879SStefano Brivio 16432bbd879SStefano Brivio case ICMP_DEST_UNREACH: 16532bbd879SStefano Brivio switch (code) { 16632bbd879SStefano Brivio case ICMP_SR_FAILED: 16732bbd879SStefano Brivio case ICMP_PORT_UNREACH: 16832bbd879SStefano Brivio /* Impossible event. */ 16932bbd879SStefano Brivio return 0; 17032bbd879SStefano Brivio default: 17132bbd879SStefano Brivio /* All others are translated to HOST_UNREACH. 17232bbd879SStefano Brivio rfc2003 contains "deep thoughts" about NET_UNREACH, 17332bbd879SStefano Brivio I believe they are just ether pollution. --ANK 17432bbd879SStefano Brivio */ 17532bbd879SStefano Brivio break; 17632bbd879SStefano Brivio } 17732bbd879SStefano Brivio break; 17832bbd879SStefano Brivio 17932bbd879SStefano Brivio case ICMP_TIME_EXCEEDED: 18032bbd879SStefano Brivio if (code != ICMP_EXC_TTL) 18132bbd879SStefano Brivio return 0; 18232bbd879SStefano Brivio data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ 18332bbd879SStefano Brivio break; 18432bbd879SStefano Brivio 18532bbd879SStefano Brivio case ICMP_REDIRECT: 18632bbd879SStefano Brivio break; 18732bbd879SStefano Brivio } 18836393395SDavid S. Miller 1899b8c6d7bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 1909b8c6d7bSEric Dumazet if (tpi->proto == htons(ETH_P_IPV6) && 19120e1954fSEric Dumazet !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, 19220e1954fSEric Dumazet type, data_len)) 19332bbd879SStefano Brivio return 0; 1949b8c6d7bSEric Dumazet #endif 1959b8c6d7bSEric Dumazet 19636393395SDavid S. Miller if (t->parms.iph.daddr == 0 || 197f97c1e0cSJoe Perches ipv4_is_multicast(t->parms.iph.daddr)) 19832bbd879SStefano Brivio return 0; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 20132bbd879SStefano Brivio return 0; 2021da177e4SLinus Torvalds 203da6185d8SWei Yongjun if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 2041da177e4SLinus Torvalds t->err_count++; 2051da177e4SLinus Torvalds else 2061da177e4SLinus Torvalds t->err_count = 1; 2071da177e4SLinus Torvalds t->err_time = jiffies; 20832bbd879SStefano Brivio 20932bbd879SStefano Brivio return 0; 2109f57c67cSPravin B Shelar } 2119f57c67cSPravin B Shelar 2129f57c67cSPravin B Shelar static void gre_err(struct sk_buff *skb, u32 info) 2139f57c67cSPravin B Shelar { 2149f57c67cSPravin B Shelar /* All the routers (except for Linux) return only 2159f57c67cSPravin B Shelar * 8 bytes of packet payload. It means, that precise relaying of 2169f57c67cSPravin B Shelar * ICMP in the real Internet is absolutely infeasible. 2179f57c67cSPravin B Shelar * 2189f57c67cSPravin B Shelar * Moreover, Cisco "wise men" put GRE key to the third word 2199f57c67cSPravin B Shelar * in GRE header. It makes impossible maintaining even soft 2209f57c67cSPravin B Shelar * state for keyed 2219f57c67cSPravin B Shelar * GRE tunnels with enabled checksum. Tell them "thank you". 2229f57c67cSPravin B Shelar * 2239f57c67cSPravin B Shelar * Well, I wonder, rfc1812 was written by Cisco employee, 2249f57c67cSPravin B Shelar * what the hell these idiots break standards established 2259f57c67cSPravin B Shelar * by themselves??? 2269f57c67cSPravin B Shelar */ 2279f57c67cSPravin B Shelar 228e582615aSEric Dumazet const struct iphdr *iph = (struct iphdr *)skb->data; 2299f57c67cSPravin B Shelar const int type = icmp_hdr(skb)->type; 2309f57c67cSPravin B Shelar const int code = icmp_hdr(skb)->code; 2319f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 2329f57c67cSPravin B Shelar 233b0350d51SHaishuang Yan if (gre_parse_header(skb, &tpi, NULL, htons(ETH_P_IP), 234b0350d51SHaishuang Yan iph->ihl * 4) < 0) 2359f57c67cSPravin B Shelar return; 2369f57c67cSPravin B Shelar 2379f57c67cSPravin B Shelar if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { 2389f57c67cSPravin B Shelar ipv4_update_pmtu(skb, dev_net(skb->dev), info, 239d888f396SMaciej Żenczykowski skb->dev->ifindex, IPPROTO_GRE); 2409f57c67cSPravin B Shelar return; 2419f57c67cSPravin B Shelar } 2429f57c67cSPravin B Shelar if (type == ICMP_REDIRECT) { 2431042caa7SMaciej Żenczykowski ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 2441042caa7SMaciej Żenczykowski IPPROTO_GRE); 2459f57c67cSPravin B Shelar return; 2469f57c67cSPravin B Shelar } 2479f57c67cSPravin B Shelar 2489f57c67cSPravin B Shelar ipgre_err(skb, info, &tpi); 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 25184e54fe0SWilliam Tu static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, 25284e54fe0SWilliam Tu int gre_hdr_len) 25384e54fe0SWilliam Tu { 25484e54fe0SWilliam Tu struct net *net = dev_net(skb->dev); 25584e54fe0SWilliam Tu struct metadata_dst *tun_dst = NULL; 2561d7e2ed2SWilliam Tu struct erspan_base_hdr *ershdr; 25784e54fe0SWilliam Tu struct ip_tunnel_net *itn; 25884e54fe0SWilliam Tu struct ip_tunnel *tunnel; 25984e54fe0SWilliam Tu const struct iphdr *iph; 2603df19283SWilliam Tu struct erspan_md2 *md2; 2611d7e2ed2SWilliam Tu int ver; 26284e54fe0SWilliam Tu int len; 26384e54fe0SWilliam Tu 26484e54fe0SWilliam Tu itn = net_generic(net, erspan_net_id); 26584e54fe0SWilliam Tu 26684e54fe0SWilliam Tu iph = ip_hdr(skb); 2671d7e2ed2SWilliam Tu ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); 268c69de58bSWilliam Tu ver = ershdr->ver; 26984e54fe0SWilliam Tu 27084e54fe0SWilliam Tu tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, 27184e54fe0SWilliam Tu tpi->flags | TUNNEL_KEY, 27284e54fe0SWilliam Tu iph->saddr, iph->daddr, tpi->key); 27384e54fe0SWilliam Tu 27484e54fe0SWilliam Tu if (tunnel) { 2751d7e2ed2SWilliam Tu len = gre_hdr_len + erspan_hdr_len(ver); 2761d7e2ed2SWilliam Tu if (unlikely(!pskb_may_pull(skb, len))) 277ae3e1337SWilliam Tu return PACKET_REJECT; 2781d7e2ed2SWilliam Tu 27984e54fe0SWilliam Tu if (__iptunnel_pull_header(skb, 2801d7e2ed2SWilliam Tu len, 28184e54fe0SWilliam Tu htons(ETH_P_TEB), 28284e54fe0SWilliam Tu false, false) < 0) 28384e54fe0SWilliam Tu goto drop; 28484e54fe0SWilliam Tu 2851a66a836SWilliam Tu if (tunnel->collect_md) { 286492b67e2SLorenzo Bianconi struct erspan_metadata *pkt_md, *md; 2871a66a836SWilliam Tu struct ip_tunnel_info *info; 288492b67e2SLorenzo Bianconi unsigned char *gh; 2891a66a836SWilliam Tu __be64 tun_id; 2901a66a836SWilliam Tu __be16 flags; 2911a66a836SWilliam Tu 2921a66a836SWilliam Tu tpi->flags |= TUNNEL_KEY; 2931a66a836SWilliam Tu flags = tpi->flags; 2941a66a836SWilliam Tu tun_id = key32_to_tunnel_id(tpi->key); 2951a66a836SWilliam Tu 2961a66a836SWilliam Tu tun_dst = ip_tun_rx_dst(skb, flags, 2971a66a836SWilliam Tu tun_id, sizeof(*md)); 2981a66a836SWilliam Tu if (!tun_dst) 2991a66a836SWilliam Tu return PACKET_REJECT; 3001a66a836SWilliam Tu 301492b67e2SLorenzo Bianconi /* skb can be uncloned in __iptunnel_pull_header, so 302492b67e2SLorenzo Bianconi * old pkt_md is no longer valid and we need to reset 303492b67e2SLorenzo Bianconi * it 304492b67e2SLorenzo Bianconi */ 305492b67e2SLorenzo Bianconi gh = skb_network_header(skb) + 306492b67e2SLorenzo Bianconi skb_network_header_len(skb); 307492b67e2SLorenzo Bianconi pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len + 308492b67e2SLorenzo Bianconi sizeof(*ershdr)); 3091a66a836SWilliam Tu md = ip_tunnel_info_opts(&tun_dst->u.tun_info); 310f551c91dSWilliam Tu md->version = ver; 3113df19283SWilliam Tu md2 = &md->u.md2; 3123df19283SWilliam Tu memcpy(md2, pkt_md, ver == 1 ? ERSPAN_V1_MDSIZE : 3133df19283SWilliam Tu ERSPAN_V2_MDSIZE); 314f551c91dSWilliam Tu 3151a66a836SWilliam Tu info = &tun_dst->u.tun_info; 3161a66a836SWilliam Tu info->key.tun_flags |= TUNNEL_ERSPAN_OPT; 3171a66a836SWilliam Tu info->options_len = sizeof(*md); 3181a66a836SWilliam Tu } 3191a66a836SWilliam Tu 32084e54fe0SWilliam Tu skb_reset_mac_header(skb); 32184e54fe0SWilliam Tu ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 32284e54fe0SWilliam Tu return PACKET_RCVD; 32384e54fe0SWilliam Tu } 3245a64506bSHaishuang Yan return PACKET_REJECT; 3255a64506bSHaishuang Yan 32684e54fe0SWilliam Tu drop: 32784e54fe0SWilliam Tu kfree_skb(skb); 32884e54fe0SWilliam Tu return PACKET_RCVD; 32984e54fe0SWilliam Tu } 33084e54fe0SWilliam Tu 331125372faSJiri Benc static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 332125372faSJiri Benc struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) 3331da177e4SLinus Torvalds { 3342e15ea39SPravin B Shelar struct metadata_dst *tun_dst = NULL; 335b71d1d42SEric Dumazet const struct iphdr *iph; 3361da177e4SLinus Torvalds struct ip_tunnel *tunnel; 3371da177e4SLinus Torvalds 338eddc9ec5SArnaldo Carvalho de Melo iph = ip_hdr(skb); 339bda7bb46SPravin B Shelar tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, 340bda7bb46SPravin B Shelar iph->saddr, iph->daddr, tpi->key); 3411da177e4SLinus Torvalds 342d2083287Sstephen hemminger if (tunnel) { 343125372faSJiri Benc if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, 344125372faSJiri Benc raw_proto, false) < 0) 345244a797bSJiri Benc goto drop; 346244a797bSJiri Benc 347e271c7b4SJiri Benc if (tunnel->dev->type != ARPHRD_NONE) 3480e3da5bbSTimo Teräs skb_pop_mac_header(skb); 349e271c7b4SJiri Benc else 350e271c7b4SJiri Benc skb_reset_mac_header(skb); 3512e15ea39SPravin B Shelar if (tunnel->collect_md) { 352c29a70d2SPravin B Shelar __be16 flags; 353c29a70d2SPravin B Shelar __be64 tun_id; 3542e15ea39SPravin B Shelar 355c29a70d2SPravin B Shelar flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); 356d817f432SAmir Vadai tun_id = key32_to_tunnel_id(tpi->key); 357c29a70d2SPravin B Shelar tun_dst = ip_tun_rx_dst(skb, flags, tun_id, 0); 3582e15ea39SPravin B Shelar if (!tun_dst) 3592e15ea39SPravin B Shelar return PACKET_REJECT; 3602e15ea39SPravin B Shelar } 3612e15ea39SPravin B Shelar 3622e15ea39SPravin B Shelar ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); 363bda7bb46SPravin B Shelar return PACKET_RCVD; 3641da177e4SLinus Torvalds } 365125372faSJiri Benc return PACKET_NEXT; 366244a797bSJiri Benc 367244a797bSJiri Benc drop: 368244a797bSJiri Benc kfree_skb(skb); 369244a797bSJiri Benc return PACKET_RCVD; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 372125372faSJiri Benc static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, 373125372faSJiri Benc int hdr_len) 374125372faSJiri Benc { 375125372faSJiri Benc struct net *net = dev_net(skb->dev); 376125372faSJiri Benc struct ip_tunnel_net *itn; 377125372faSJiri Benc int res; 378125372faSJiri Benc 379125372faSJiri Benc if (tpi->proto == htons(ETH_P_TEB)) 380125372faSJiri Benc itn = net_generic(net, gre_tap_net_id); 381125372faSJiri Benc else 382125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 383125372faSJiri Benc 384125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); 385125372faSJiri Benc if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { 386125372faSJiri Benc /* ipgre tunnels in collect metadata mode should receive 387125372faSJiri Benc * also ETH_P_TEB traffic. 388125372faSJiri Benc */ 389125372faSJiri Benc itn = net_generic(net, ipgre_net_id); 390125372faSJiri Benc res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); 391125372faSJiri Benc } 392125372faSJiri Benc return res; 393125372faSJiri Benc } 394125372faSJiri Benc 3959f57c67cSPravin B Shelar static int gre_rcv(struct sk_buff *skb) 3969f57c67cSPravin B Shelar { 3979f57c67cSPravin B Shelar struct tnl_ptk_info tpi; 3989f57c67cSPravin B Shelar bool csum_err = false; 39995f5c64cSTom Herbert int hdr_len; 4009f57c67cSPravin B Shelar 4019f57c67cSPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 4029f57c67cSPravin B Shelar if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { 4039f57c67cSPravin B Shelar /* Looped back packet, drop it! */ 4049f57c67cSPravin B Shelar if (rt_is_output_route(skb_rtable(skb))) 4059f57c67cSPravin B Shelar goto drop; 4069f57c67cSPravin B Shelar } 4079f57c67cSPravin B Shelar #endif 4089f57c67cSPravin B Shelar 409e582615aSEric Dumazet hdr_len = gre_parse_header(skb, &tpi, &csum_err, htons(ETH_P_IP), 0); 410f132ae7cSJiri Benc if (hdr_len < 0) 41195f5c64cSTom Herbert goto drop; 41295f5c64cSTom Herbert 413f551c91dSWilliam Tu if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) || 414f551c91dSWilliam Tu tpi.proto == htons(ETH_P_ERSPAN2))) { 41584e54fe0SWilliam Tu if (erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 41684e54fe0SWilliam Tu return 0; 417dd8d5b8cSHaishuang Yan goto out; 41884e54fe0SWilliam Tu } 41984e54fe0SWilliam Tu 420244a797bSJiri Benc if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) 4219f57c67cSPravin B Shelar return 0; 4229f57c67cSPravin B Shelar 423dd8d5b8cSHaishuang Yan out: 4249f57c67cSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 4259f57c67cSPravin B Shelar drop: 4269f57c67cSPravin B Shelar kfree_skb(skb); 4279f57c67cSPravin B Shelar return 0; 4289f57c67cSPravin B Shelar } 4299f57c67cSPravin B Shelar 430c5441932SPravin B Shelar static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, 431c5441932SPravin B Shelar const struct iphdr *tnl_params, 432c5441932SPravin B Shelar __be16 proto) 433c5441932SPravin B Shelar { 434c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 435c5441932SPravin B Shelar 436c5441932SPravin B Shelar if (tunnel->parms.o_flags & TUNNEL_SEQ) 437c5441932SPravin B Shelar tunnel->o_seqno++; 438cef401deSEric Dumazet 439c5441932SPravin B Shelar /* Push GRE header. */ 440182a352dSTom Herbert gre_build_header(skb, tunnel->tun_hlen, 441182a352dSTom Herbert tunnel->parms.o_flags, proto, tunnel->parms.o_key, 442182a352dSTom Herbert htonl(tunnel->o_seqno)); 4431da177e4SLinus Torvalds 444bf3d6a8fSNicolas Dichtel ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); 4451da177e4SLinus Torvalds } 4461da177e4SLinus Torvalds 447aed069dfSAlexander Duyck static int gre_handle_offloads(struct sk_buff *skb, bool csum) 448b2acd1dcSPravin B Shelar { 4496fa79666SEdward Cree return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); 450b2acd1dcSPravin B Shelar } 451b2acd1dcSPravin B Shelar 452862a03c3SWilliam Tu static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, 453862a03c3SWilliam Tu __be16 proto) 454862a03c3SWilliam Tu { 45577a5196aSWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 456862a03c3SWilliam Tu struct ip_tunnel_info *tun_info; 457862a03c3SWilliam Tu const struct ip_tunnel_key *key; 458862a03c3SWilliam Tu int tunnel_hlen; 459962924faSwenxu __be16 flags; 460862a03c3SWilliam Tu 461862a03c3SWilliam Tu tun_info = skb_tunnel_info(skb); 462862a03c3SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 463862a03c3SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 464862a03c3SWilliam Tu goto err_free_skb; 465862a03c3SWilliam Tu 466862a03c3SWilliam Tu key = &tun_info->key; 467862a03c3SWilliam Tu tunnel_hlen = gre_calc_hlen(key->tun_flags); 468862a03c3SWilliam Tu 469962924faSwenxu if (skb_cow_head(skb, dev->needed_headroom)) 470962924faSwenxu goto err_free_skb; 4712e15ea39SPravin B Shelar 4722e15ea39SPravin B Shelar /* Push Tunnel header. */ 473aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM))) 474962924faSwenxu goto err_free_skb; 4752e15ea39SPravin B Shelar 47677a5196aSWilliam Tu flags = tun_info->key.tun_flags & 47777a5196aSWilliam Tu (TUNNEL_CSUM | TUNNEL_KEY | TUNNEL_SEQ); 478cba65321SDavid S. Miller gre_build_header(skb, tunnel_hlen, flags, proto, 47977a5196aSWilliam Tu tunnel_id_to_key32(tun_info->key.tun_id), 48015746394SColin Ian King (flags & TUNNEL_SEQ) ? htonl(tunnel->o_seqno++) : 0); 4812e15ea39SPravin B Shelar 482962924faSwenxu ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); 483039f5062SPravin B Shelar 4842e15ea39SPravin B Shelar return; 4852e15ea39SPravin B Shelar 4862e15ea39SPravin B Shelar err_free_skb: 4872e15ea39SPravin B Shelar kfree_skb(skb); 4882e15ea39SPravin B Shelar dev->stats.tx_dropped++; 4892e15ea39SPravin B Shelar } 4902e15ea39SPravin B Shelar 49120704bd1SXin Long static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) 4921a66a836SWilliam Tu { 4931a66a836SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 4941a66a836SWilliam Tu struct ip_tunnel_info *tun_info; 4951a66a836SWilliam Tu const struct ip_tunnel_key *key; 4961a66a836SWilliam Tu struct erspan_metadata *md; 4971a66a836SWilliam Tu bool truncate = false; 498962924faSwenxu __be16 proto; 4991a66a836SWilliam Tu int tunnel_hlen; 500f551c91dSWilliam Tu int version; 5011baf5ebfSWilliam Tu int nhoff; 502d5db21a3SWilliam Tu int thoff; 5031a66a836SWilliam Tu 5041a66a836SWilliam Tu tun_info = skb_tunnel_info(skb); 5051a66a836SWilliam Tu if (unlikely(!tun_info || !(tun_info->mode & IP_TUNNEL_INFO_TX) || 5061a66a836SWilliam Tu ip_tunnel_info_af(tun_info) != AF_INET)) 5071a66a836SWilliam Tu goto err_free_skb; 5081a66a836SWilliam Tu 5091a66a836SWilliam Tu key = &tun_info->key; 510256c87c1SPieter Jansen van Vuuren if (!(tun_info->key.tun_flags & TUNNEL_ERSPAN_OPT)) 511962924faSwenxu goto err_free_skb; 512f551c91dSWilliam Tu md = ip_tunnel_info_opts(tun_info); 513f551c91dSWilliam Tu if (!md) 514962924faSwenxu goto err_free_skb; 5151a66a836SWilliam Tu 5161a66a836SWilliam Tu /* ERSPAN has fixed 8 byte GRE header */ 517f551c91dSWilliam Tu version = md->version; 518f551c91dSWilliam Tu tunnel_hlen = 8 + erspan_hdr_len(version); 5191a66a836SWilliam Tu 520962924faSwenxu if (skb_cow_head(skb, dev->needed_headroom)) 521962924faSwenxu goto err_free_skb; 5221a66a836SWilliam Tu 5231a66a836SWilliam Tu if (gre_handle_offloads(skb, false)) 524962924faSwenxu goto err_free_skb; 5251a66a836SWilliam Tu 526f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 527f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 5281a66a836SWilliam Tu truncate = true; 5291a66a836SWilliam Tu } 5301a66a836SWilliam Tu 5311baf5ebfSWilliam Tu nhoff = skb_network_header(skb) - skb_mac_header(skb); 5321baf5ebfSWilliam Tu if (skb->protocol == htons(ETH_P_IP) && 5331baf5ebfSWilliam Tu (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff)) 5341baf5ebfSWilliam Tu truncate = true; 5351baf5ebfSWilliam Tu 536d5db21a3SWilliam Tu thoff = skb_transport_header(skb) - skb_mac_header(skb); 537d5db21a3SWilliam Tu if (skb->protocol == htons(ETH_P_IPV6) && 538d5db21a3SWilliam Tu (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)) 539d5db21a3SWilliam Tu truncate = true; 540d5db21a3SWilliam Tu 541f551c91dSWilliam Tu if (version == 1) { 542c69de58bSWilliam Tu erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), 5431d7e2ed2SWilliam Tu ntohl(md->u.index), truncate, true); 54420704bd1SXin Long proto = htons(ETH_P_ERSPAN); 545f551c91dSWilliam Tu } else if (version == 2) { 546c69de58bSWilliam Tu erspan_build_header_v2(skb, 547c69de58bSWilliam Tu ntohl(tunnel_id_to_key32(key->tun_id)), 548c69de58bSWilliam Tu md->u.md2.dir, 549c69de58bSWilliam Tu get_hwid(&md->u.md2), 550c69de58bSWilliam Tu truncate, true); 55120704bd1SXin Long proto = htons(ETH_P_ERSPAN2); 552f551c91dSWilliam Tu } else { 553962924faSwenxu goto err_free_skb; 554f551c91dSWilliam Tu } 5551a66a836SWilliam Tu 5561a66a836SWilliam Tu gre_build_header(skb, 8, TUNNEL_SEQ, 55720704bd1SXin Long proto, 0, htonl(tunnel->o_seqno++)); 5581a66a836SWilliam Tu 559962924faSwenxu ip_md_tunnel_xmit(skb, dev, IPPROTO_GRE, tunnel_hlen); 5601a66a836SWilliam Tu 5611a66a836SWilliam Tu return; 5621a66a836SWilliam Tu 5631a66a836SWilliam Tu err_free_skb: 5641a66a836SWilliam Tu kfree_skb(skb); 5651a66a836SWilliam Tu dev->stats.tx_dropped++; 5661a66a836SWilliam Tu } 5671a66a836SWilliam Tu 568fc4099f1SPravin B Shelar static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 569fc4099f1SPravin B Shelar { 570fc4099f1SPravin B Shelar struct ip_tunnel_info *info = skb_tunnel_info(skb); 571962924faSwenxu const struct ip_tunnel_key *key; 572fc4099f1SPravin B Shelar struct rtable *rt; 573fc4099f1SPravin B Shelar struct flowi4 fl4; 574fc4099f1SPravin B Shelar 575fc4099f1SPravin B Shelar if (ip_tunnel_info_af(info) != AF_INET) 576fc4099f1SPravin B Shelar return -EINVAL; 577fc4099f1SPravin B Shelar 578962924faSwenxu key = &info->key; 579962924faSwenxu ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, 580962924faSwenxu tunnel_id_to_key32(key->tun_id), key->tos, 0, 58124ba1440Swenxu skb->mark, skb_get_hash(skb)); 582962924faSwenxu rt = ip_route_output_key(dev_net(dev), &fl4); 583fc4099f1SPravin B Shelar if (IS_ERR(rt)) 584fc4099f1SPravin B Shelar return PTR_ERR(rt); 585fc4099f1SPravin B Shelar 586fc4099f1SPravin B Shelar ip_rt_put(rt); 587fc4099f1SPravin B Shelar info->key.u.ipv4.src = fl4.saddr; 588fc4099f1SPravin B Shelar return 0; 589fc4099f1SPravin B Shelar } 590fc4099f1SPravin B Shelar 591c5441932SPravin B Shelar static netdev_tx_t ipgre_xmit(struct sk_buff *skb, 592c5441932SPravin B Shelar struct net_device *dev) 593ee34c1ebSMichal Schmidt { 594c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 595c5441932SPravin B Shelar const struct iphdr *tnl_params; 596ee34c1ebSMichal Schmidt 597cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 598cb9f1b78SWillem de Bruijn goto free_skb; 599cb9f1b78SWillem de Bruijn 6002e15ea39SPravin B Shelar if (tunnel->collect_md) { 6012090714eSJiri Benc gre_fb_xmit(skb, dev, skb->protocol); 6022e15ea39SPravin B Shelar return NETDEV_TX_OK; 6032e15ea39SPravin B Shelar } 6042e15ea39SPravin B Shelar 605c5441932SPravin B Shelar if (dev->header_ops) { 606c5441932SPravin B Shelar /* Need space for new headers */ 607c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom - 6082bac7cb3SChen Gang (tunnel->hlen + sizeof(struct iphdr)))) 609c5441932SPravin B Shelar goto free_skb; 610ee34c1ebSMichal Schmidt 611c5441932SPravin B Shelar tnl_params = (const struct iphdr *)skb->data; 612cbb1e85fSDavid S. Miller 613c5441932SPravin B Shelar /* Pull skb since ip_tunnel_xmit() needs skb->data pointing 614c5441932SPravin B Shelar * to gre header. 615c5441932SPravin B Shelar */ 616c5441932SPravin B Shelar skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); 6178a0033a9STimo Teräs skb_reset_mac_header(skb); 618c5441932SPravin B Shelar } else { 619c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 620c5441932SPravin B Shelar goto free_skb; 621c5441932SPravin B Shelar 622c5441932SPravin B Shelar tnl_params = &tunnel->parms.iph; 623ee34c1ebSMichal Schmidt } 624e1a80002SHerbert Xu 625aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 626aed069dfSAlexander Duyck goto free_skb; 6278a0033a9STimo Teräs 628c5441932SPravin B Shelar __gre_xmit(skb, dev, tnl_params, skb->protocol); 629c5441932SPravin B Shelar return NETDEV_TX_OK; 630c5441932SPravin B Shelar 631c5441932SPravin B Shelar free_skb: 6323acfa1e7SEric Dumazet kfree_skb(skb); 633c5441932SPravin B Shelar dev->stats.tx_dropped++; 634c5441932SPravin B Shelar return NETDEV_TX_OK; 635ee34c1ebSMichal Schmidt } 636ee34c1ebSMichal Schmidt 63784e54fe0SWilliam Tu static netdev_tx_t erspan_xmit(struct sk_buff *skb, 63884e54fe0SWilliam Tu struct net_device *dev) 63984e54fe0SWilliam Tu { 64084e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 64184e54fe0SWilliam Tu bool truncate = false; 64220704bd1SXin Long __be16 proto; 64384e54fe0SWilliam Tu 644cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 645cb9f1b78SWillem de Bruijn goto free_skb; 646cb9f1b78SWillem de Bruijn 6471a66a836SWilliam Tu if (tunnel->collect_md) { 64820704bd1SXin Long erspan_fb_xmit(skb, dev); 6491a66a836SWilliam Tu return NETDEV_TX_OK; 6501a66a836SWilliam Tu } 6511a66a836SWilliam Tu 65284e54fe0SWilliam Tu if (gre_handle_offloads(skb, false)) 65384e54fe0SWilliam Tu goto free_skb; 65484e54fe0SWilliam Tu 65584e54fe0SWilliam Tu if (skb_cow_head(skb, dev->needed_headroom)) 65684e54fe0SWilliam Tu goto free_skb; 65784e54fe0SWilliam Tu 658f192970dSWilliam Tu if (skb->len > dev->mtu + dev->hard_header_len) { 659f192970dSWilliam Tu pskb_trim(skb, dev->mtu + dev->hard_header_len); 66084e54fe0SWilliam Tu truncate = true; 66184e54fe0SWilliam Tu } 66284e54fe0SWilliam Tu 66384e54fe0SWilliam Tu /* Push ERSPAN header */ 66420704bd1SXin Long if (tunnel->erspan_ver == 1) { 665c69de58bSWilliam Tu erspan_build_header(skb, ntohl(tunnel->parms.o_key), 666c69de58bSWilliam Tu tunnel->index, 667a3222dc9SWilliam Tu truncate, true); 66820704bd1SXin Long proto = htons(ETH_P_ERSPAN); 66920704bd1SXin Long } else if (tunnel->erspan_ver == 2) { 670c69de58bSWilliam Tu erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), 671f551c91dSWilliam Tu tunnel->dir, tunnel->hwid, 672f551c91dSWilliam Tu truncate, true); 67320704bd1SXin Long proto = htons(ETH_P_ERSPAN2); 67420704bd1SXin Long } else { 67502f99df1SWilliam Tu goto free_skb; 67620704bd1SXin Long } 677f551c91dSWilliam Tu 67884e54fe0SWilliam Tu tunnel->parms.o_flags &= ~TUNNEL_KEY; 67920704bd1SXin Long __gre_xmit(skb, dev, &tunnel->parms.iph, proto); 68084e54fe0SWilliam Tu return NETDEV_TX_OK; 68184e54fe0SWilliam Tu 68284e54fe0SWilliam Tu free_skb: 68384e54fe0SWilliam Tu kfree_skb(skb); 68484e54fe0SWilliam Tu dev->stats.tx_dropped++; 68584e54fe0SWilliam Tu return NETDEV_TX_OK; 68684e54fe0SWilliam Tu } 68784e54fe0SWilliam Tu 688c5441932SPravin B Shelar static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, 689c5441932SPravin B Shelar struct net_device *dev) 690c5441932SPravin B Shelar { 691c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 692ee34c1ebSMichal Schmidt 693cb9f1b78SWillem de Bruijn if (!pskb_inet_may_pull(skb)) 694cb9f1b78SWillem de Bruijn goto free_skb; 695cb9f1b78SWillem de Bruijn 6962e15ea39SPravin B Shelar if (tunnel->collect_md) { 6972090714eSJiri Benc gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); 6982e15ea39SPravin B Shelar return NETDEV_TX_OK; 6992e15ea39SPravin B Shelar } 7002e15ea39SPravin B Shelar 701aed069dfSAlexander Duyck if (gre_handle_offloads(skb, !!(tunnel->parms.o_flags & TUNNEL_CSUM))) 702aed069dfSAlexander Duyck goto free_skb; 703ee34c1ebSMichal Schmidt 704c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) 705c5441932SPravin B Shelar goto free_skb; 70642aa9162SHerbert Xu 707c5441932SPravin B Shelar __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_TEB)); 708c5441932SPravin B Shelar return NETDEV_TX_OK; 709c5441932SPravin B Shelar 710c5441932SPravin B Shelar free_skb: 7113acfa1e7SEric Dumazet kfree_skb(skb); 712c5441932SPravin B Shelar dev->stats.tx_dropped++; 713c5441932SPravin B Shelar return NETDEV_TX_OK; 71468c33163SPravin B Shelar } 715ee34c1ebSMichal Schmidt 716dd9d598cSXin Long static void ipgre_link_update(struct net_device *dev, bool set_mtu) 717dd9d598cSXin Long { 718dd9d598cSXin Long struct ip_tunnel *tunnel = netdev_priv(dev); 719dd9d598cSXin Long int len; 720dd9d598cSXin Long 721dd9d598cSXin Long len = tunnel->tun_hlen; 722dd9d598cSXin Long tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 723dd9d598cSXin Long len = tunnel->tun_hlen - len; 724dd9d598cSXin Long tunnel->hlen = tunnel->hlen + len; 725dd9d598cSXin Long 726dd9d598cSXin Long dev->needed_headroom = dev->needed_headroom + len; 727dd9d598cSXin Long if (set_mtu) 728dd9d598cSXin Long dev->mtu = max_t(int, dev->mtu - len, 68); 729dd9d598cSXin Long 730dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 731dd9d598cSXin Long if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 732dd9d598cSXin Long tunnel->encap.type == TUNNEL_ENCAP_NONE) { 733dd9d598cSXin Long dev->features |= NETIF_F_GSO_SOFTWARE; 734dd9d598cSXin Long dev->hw_features |= NETIF_F_GSO_SOFTWARE; 7351cc5954fSSabrina Dubroca } else { 7361cc5954fSSabrina Dubroca dev->features &= ~NETIF_F_GSO_SOFTWARE; 7371cc5954fSSabrina Dubroca dev->hw_features &= ~NETIF_F_GSO_SOFTWARE; 738dd9d598cSXin Long } 739dd9d598cSXin Long dev->features |= NETIF_F_LLTX; 7401cc5954fSSabrina Dubroca } else { 7411cc5954fSSabrina Dubroca dev->hw_features &= ~NETIF_F_GSO_SOFTWARE; 7421cc5954fSSabrina Dubroca dev->features &= ~(NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE); 743dd9d598cSXin Long } 744dd9d598cSXin Long } 745dd9d598cSXin Long 746c5441932SPravin B Shelar static int ipgre_tunnel_ioctl(struct net_device *dev, 747c5441932SPravin B Shelar struct ifreq *ifr, int cmd) 7481da177e4SLinus Torvalds { 7491da177e4SLinus Torvalds struct ip_tunnel_parm p; 750a0efab67SXin Long int err; 7511da177e4SLinus Torvalds 7521da177e4SLinus Torvalds if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) 753c5441932SPravin B Shelar return -EFAULT; 754a0efab67SXin Long 7556c734fb8SCong Wang if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { 7561da177e4SLinus Torvalds if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || 7571da177e4SLinus Torvalds p.iph.ihl != 5 || (p.iph.frag_off & htons(~IP_DF)) || 7586c734fb8SCong Wang ((p.i_flags | p.o_flags) & (GRE_VERSION | GRE_ROUTING))) 7591da177e4SLinus Torvalds return -EINVAL; 760c5441932SPravin B Shelar } 761a0efab67SXin Long 762c5441932SPravin B Shelar p.i_flags = gre_flags_to_tnl_flags(p.i_flags); 763c5441932SPravin B Shelar p.o_flags = gre_flags_to_tnl_flags(p.o_flags); 764c5441932SPravin B Shelar 765c5441932SPravin B Shelar err = ip_tunnel_ioctl(dev, &p, cmd); 766c5441932SPravin B Shelar if (err) 767c5441932SPravin B Shelar return err; 768c5441932SPravin B Shelar 769a0efab67SXin Long if (cmd == SIOCCHGTUNNEL) { 770a0efab67SXin Long struct ip_tunnel *t = netdev_priv(dev); 771a0efab67SXin Long 772a0efab67SXin Long t->parms.i_flags = p.i_flags; 773a0efab67SXin Long t->parms.o_flags = p.o_flags; 774a0efab67SXin Long 775a0efab67SXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 776a0efab67SXin Long ipgre_link_update(dev, true); 777a0efab67SXin Long } 778a0efab67SXin Long 77995f5c64cSTom Herbert p.i_flags = gre_tnl_flags_to_gre_flags(p.i_flags); 78095f5c64cSTom Herbert p.o_flags = gre_tnl_flags_to_gre_flags(p.o_flags); 781c5441932SPravin B Shelar 782c5441932SPravin B Shelar if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) 783c5441932SPravin B Shelar return -EFAULT; 784a0efab67SXin Long 7851da177e4SLinus Torvalds return 0; 7861da177e4SLinus Torvalds } 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds /* Nice toy. Unfortunately, useless in real life :-) 7891da177e4SLinus Torvalds It allows to construct virtual multiprotocol broadcast "LAN" 7901da177e4SLinus Torvalds over the Internet, provided multicast routing is tuned. 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds I have no idea was this bicycle invented before me, 7941da177e4SLinus Torvalds so that I had to set ARPHRD_IPGRE to a random value. 7951da177e4SLinus Torvalds I have an impression, that Cisco could make something similar, 7961da177e4SLinus Torvalds but this feature is apparently missing in IOS<=11.2(8). 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds I set up 10.66.66/24 and fec0:6666:6666::0/96 as virtual networks 7991da177e4SLinus Torvalds with broadcast 224.66.66.66. If you have access to mbone, play with me :-) 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds ping -t 255 224.66.66.66 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds If nobody answers, mbone does not work. 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds ip tunnel add Universe mode gre remote 224.66.66.66 local <Your_real_addr> ttl 255 8061da177e4SLinus Torvalds ip addr add 10.66.66.<somewhat>/24 dev Universe 8071da177e4SLinus Torvalds ifconfig Universe up 8081da177e4SLinus Torvalds ifconfig Universe add fe80::<Your_real_addr>/10 8091da177e4SLinus Torvalds ifconfig Universe add fec0:6666:6666::<Your_real_addr>/96 8101da177e4SLinus Torvalds ftp 10.66.66.66 8111da177e4SLinus Torvalds ... 8121da177e4SLinus Torvalds ftp fec0:6666:6666::193.233.7.65 8131da177e4SLinus Torvalds ... 8141da177e4SLinus Torvalds */ 8153b04dddeSStephen Hemminger static int ipgre_header(struct sk_buff *skb, struct net_device *dev, 8163b04dddeSStephen Hemminger unsigned short type, 8171507850bSEric Dumazet const void *daddr, const void *saddr, unsigned int len) 8181da177e4SLinus Torvalds { 8192941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 820c5441932SPravin B Shelar struct iphdr *iph; 821c5441932SPravin B Shelar struct gre_base_hdr *greh; 822c5441932SPravin B Shelar 823d58ff351SJohannes Berg iph = skb_push(skb, t->hlen + sizeof(*iph)); 824c5441932SPravin B Shelar greh = (struct gre_base_hdr *)(iph+1); 82595f5c64cSTom Herbert greh->flags = gre_tnl_flags_to_gre_flags(t->parms.o_flags); 826c5441932SPravin B Shelar greh->protocol = htons(type); 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 8291da177e4SLinus Torvalds 830c5441932SPravin B Shelar /* Set the source hardware address. */ 8311da177e4SLinus Torvalds if (saddr) 8321da177e4SLinus Torvalds memcpy(&iph->saddr, saddr, 4); 8336d55cb91STimo Teräs if (daddr) 8341da177e4SLinus Torvalds memcpy(&iph->daddr, daddr, 4); 8356d55cb91STimo Teräs if (iph->daddr) 83677a482bdSTimo Teräs return t->hlen + sizeof(*iph); 8371da177e4SLinus Torvalds 838c5441932SPravin B Shelar return -(t->hlen + sizeof(*iph)); 8391da177e4SLinus Torvalds } 8401da177e4SLinus Torvalds 8416a5f44d7STimo Teras static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 8426a5f44d7STimo Teras { 843b71d1d42SEric Dumazet const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 8446a5f44d7STimo Teras memcpy(haddr, &iph->saddr, 4); 8456a5f44d7STimo Teras return 4; 8466a5f44d7STimo Teras } 8476a5f44d7STimo Teras 8483b04dddeSStephen Hemminger static const struct header_ops ipgre_header_ops = { 8493b04dddeSStephen Hemminger .create = ipgre_header, 8506a5f44d7STimo Teras .parse = ipgre_header_parse, 8513b04dddeSStephen Hemminger }; 8523b04dddeSStephen Hemminger 8536a5f44d7STimo Teras #ifdef CONFIG_NET_IPGRE_BROADCAST 8541da177e4SLinus Torvalds static int ipgre_open(struct net_device *dev) 8551da177e4SLinus Torvalds { 8562941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 8571da177e4SLinus Torvalds 858f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr)) { 859cbb1e85fSDavid S. Miller struct flowi4 fl4; 860cbb1e85fSDavid S. Miller struct rtable *rt; 861cbb1e85fSDavid S. Miller 862b57708adSNicolas Dichtel rt = ip_route_output_gre(t->net, &fl4, 86378fbfd8aSDavid S. Miller t->parms.iph.daddr, 86478fbfd8aSDavid S. Miller t->parms.iph.saddr, 86578fbfd8aSDavid S. Miller t->parms.o_key, 86678fbfd8aSDavid S. Miller RT_TOS(t->parms.iph.tos), 86778fbfd8aSDavid S. Miller t->parms.link); 868b23dd4feSDavid S. Miller if (IS_ERR(rt)) 8691da177e4SLinus Torvalds return -EADDRNOTAVAIL; 870d8d1f30bSChangli Gao dev = rt->dst.dev; 8711da177e4SLinus Torvalds ip_rt_put(rt); 87251456b29SIan Morris if (!__in_dev_get_rtnl(dev)) 8731da177e4SLinus Torvalds return -EADDRNOTAVAIL; 8741da177e4SLinus Torvalds t->mlink = dev->ifindex; 875e5ed6399SHerbert Xu ip_mc_inc_group(__in_dev_get_rtnl(dev), t->parms.iph.daddr); 8761da177e4SLinus Torvalds } 8771da177e4SLinus Torvalds return 0; 8781da177e4SLinus Torvalds } 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds static int ipgre_close(struct net_device *dev) 8811da177e4SLinus Torvalds { 8822941a486SPatrick McHardy struct ip_tunnel *t = netdev_priv(dev); 883b8c26a33SStephen Hemminger 884f97c1e0cSJoe Perches if (ipv4_is_multicast(t->parms.iph.daddr) && t->mlink) { 8857fee0ca2SDenis V. Lunev struct in_device *in_dev; 886b57708adSNicolas Dichtel in_dev = inetdev_by_index(t->net, t->mlink); 8878723e1b4SEric Dumazet if (in_dev) 8881da177e4SLinus Torvalds ip_mc_dec_group(in_dev, t->parms.iph.daddr); 8891da177e4SLinus Torvalds } 8901da177e4SLinus Torvalds return 0; 8911da177e4SLinus Torvalds } 8921da177e4SLinus Torvalds #endif 8931da177e4SLinus Torvalds 894b8c26a33SStephen Hemminger static const struct net_device_ops ipgre_netdev_ops = { 895b8c26a33SStephen Hemminger .ndo_init = ipgre_tunnel_init, 896c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 897b8c26a33SStephen Hemminger #ifdef CONFIG_NET_IPGRE_BROADCAST 898b8c26a33SStephen Hemminger .ndo_open = ipgre_open, 899b8c26a33SStephen Hemminger .ndo_stop = ipgre_close, 900b8c26a33SStephen Hemminger #endif 901c5441932SPravin B Shelar .ndo_start_xmit = ipgre_xmit, 902b8c26a33SStephen Hemminger .ndo_do_ioctl = ipgre_tunnel_ioctl, 903c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 904c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 9051e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 906b8c26a33SStephen Hemminger }; 907b8c26a33SStephen Hemminger 9086b78f16eSEric Dumazet #define GRE_FEATURES (NETIF_F_SG | \ 9096b78f16eSEric Dumazet NETIF_F_FRAGLIST | \ 9106b78f16eSEric Dumazet NETIF_F_HIGHDMA | \ 9116b78f16eSEric Dumazet NETIF_F_HW_CSUM) 9126b78f16eSEric Dumazet 9131da177e4SLinus Torvalds static void ipgre_tunnel_setup(struct net_device *dev) 9141da177e4SLinus Torvalds { 915b8c26a33SStephen Hemminger dev->netdev_ops = &ipgre_netdev_ops; 9165a455275SNicolas Dichtel dev->type = ARPHRD_IPGRE; 917c5441932SPravin B Shelar ip_tunnel_setup(dev, ipgre_net_id); 918c5441932SPravin B Shelar } 9191da177e4SLinus Torvalds 920c5441932SPravin B Shelar static void __gre_tunnel_init(struct net_device *dev) 921c5441932SPravin B Shelar { 922c5441932SPravin B Shelar struct ip_tunnel *tunnel; 923c5441932SPravin B Shelar 924c5441932SPravin B Shelar tunnel = netdev_priv(dev); 92595f5c64cSTom Herbert tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags); 926c5441932SPravin B Shelar tunnel->parms.iph.protocol = IPPROTO_GRE; 927c5441932SPravin B Shelar 9284565e991STom Herbert tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; 9294565e991STom Herbert 930b57708adSNicolas Dichtel dev->features |= GRE_FEATURES; 9316b78f16eSEric Dumazet dev->hw_features |= GRE_FEATURES; 932c5441932SPravin B Shelar 933c5441932SPravin B Shelar if (!(tunnel->parms.o_flags & TUNNEL_SEQ)) { 934a0ca153fSAlexander Duyck /* TCP offload with GRE SEQ is not supported, nor 935a0ca153fSAlexander Duyck * can we support 2 levels of outer headers requiring 936a0ca153fSAlexander Duyck * an update. 937a0ca153fSAlexander Duyck */ 938a0ca153fSAlexander Duyck if (!(tunnel->parms.o_flags & TUNNEL_CSUM) || 939a0ca153fSAlexander Duyck (tunnel->encap.type == TUNNEL_ENCAP_NONE)) { 940c5441932SPravin B Shelar dev->features |= NETIF_F_GSO_SOFTWARE; 941c5441932SPravin B Shelar dev->hw_features |= NETIF_F_GSO_SOFTWARE; 942a0ca153fSAlexander Duyck } 943a0ca153fSAlexander Duyck 944c5441932SPravin B Shelar /* Can use a lockless transmit, unless we generate 945c5441932SPravin B Shelar * output sequences 946c5441932SPravin B Shelar */ 947c5441932SPravin B Shelar dev->features |= NETIF_F_LLTX; 948c5441932SPravin B Shelar } 9491da177e4SLinus Torvalds } 9501da177e4SLinus Torvalds 9511da177e4SLinus Torvalds static int ipgre_tunnel_init(struct net_device *dev) 9521da177e4SLinus Torvalds { 953c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 954c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 9551da177e4SLinus Torvalds 956c5441932SPravin B Shelar __gre_tunnel_init(dev); 9571da177e4SLinus Torvalds 958c5441932SPravin B Shelar memcpy(dev->dev_addr, &iph->saddr, 4); 959c5441932SPravin B Shelar memcpy(dev->broadcast, &iph->daddr, 4); 9601da177e4SLinus Torvalds 961c5441932SPravin B Shelar dev->flags = IFF_NOARP; 96202875878SEric Dumazet netif_keep_dst(dev); 963c5441932SPravin B Shelar dev->addr_len = 4; 9641da177e4SLinus Torvalds 965a64b04d8SJiri Benc if (iph->daddr && !tunnel->collect_md) { 9661da177e4SLinus Torvalds #ifdef CONFIG_NET_IPGRE_BROADCAST 967f97c1e0cSJoe Perches if (ipv4_is_multicast(iph->daddr)) { 9681da177e4SLinus Torvalds if (!iph->saddr) 9691da177e4SLinus Torvalds return -EINVAL; 9701da177e4SLinus Torvalds dev->flags = IFF_BROADCAST; 9713b04dddeSStephen Hemminger dev->header_ops = &ipgre_header_ops; 9721da177e4SLinus Torvalds } 9731da177e4SLinus Torvalds #endif 974a64b04d8SJiri Benc } else if (!tunnel->collect_md) { 9756a5f44d7STimo Teras dev->header_ops = &ipgre_header_ops; 976a64b04d8SJiri Benc } 9771da177e4SLinus Torvalds 978c5441932SPravin B Shelar return ip_tunnel_init(dev); 97960769a5dSEric Dumazet } 98060769a5dSEric Dumazet 9819f57c67cSPravin B Shelar static const struct gre_protocol ipgre_protocol = { 9829f57c67cSPravin B Shelar .handler = gre_rcv, 9839f57c67cSPravin B Shelar .err_handler = gre_err, 9841da177e4SLinus Torvalds }; 9851da177e4SLinus Torvalds 9862c8c1e72SAlexey Dobriyan static int __net_init ipgre_init_net(struct net *net) 98759a4c759SPavel Emelyanov { 988c5441932SPravin B Shelar return ip_tunnel_init_net(net, ipgre_net_id, &ipgre_link_ops, NULL); 98959a4c759SPavel Emelyanov } 99059a4c759SPavel Emelyanov 99164bc1781SEric Dumazet static void __net_exit ipgre_exit_batch_net(struct list_head *list_net) 99259a4c759SPavel Emelyanov { 99364bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, ipgre_net_id, &ipgre_link_ops); 99459a4c759SPavel Emelyanov } 99559a4c759SPavel Emelyanov 99659a4c759SPavel Emelyanov static struct pernet_operations ipgre_net_ops = { 99759a4c759SPavel Emelyanov .init = ipgre_init_net, 99864bc1781SEric Dumazet .exit_batch = ipgre_exit_batch_net, 999cfb8fbf2SEric W. Biederman .id = &ipgre_net_id, 1000c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 100159a4c759SPavel Emelyanov }; 10021da177e4SLinus Torvalds 1003a8b8a889SMatthias Schiffer static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[], 1004a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1005c19e654dSHerbert Xu { 1006c19e654dSHerbert Xu __be16 flags; 1007c19e654dSHerbert Xu 1008c19e654dSHerbert Xu if (!data) 1009c19e654dSHerbert Xu return 0; 1010c19e654dSHerbert Xu 1011c19e654dSHerbert Xu flags = 0; 1012c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1013c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 1014c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1015c19e654dSHerbert Xu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 1016c19e654dSHerbert Xu if (flags & (GRE_VERSION|GRE_ROUTING)) 1017c19e654dSHerbert Xu return -EINVAL; 1018c19e654dSHerbert Xu 1019946b636fSJiri Benc if (data[IFLA_GRE_COLLECT_METADATA] && 1020946b636fSJiri Benc data[IFLA_GRE_ENCAP_TYPE] && 1021946b636fSJiri Benc nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) 1022946b636fSJiri Benc return -EINVAL; 1023946b636fSJiri Benc 1024c19e654dSHerbert Xu return 0; 1025c19e654dSHerbert Xu } 1026c19e654dSHerbert Xu 1027a8b8a889SMatthias Schiffer static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[], 1028a8b8a889SMatthias Schiffer struct netlink_ext_ack *extack) 1029e1a80002SHerbert Xu { 1030e1a80002SHerbert Xu __be32 daddr; 1031e1a80002SHerbert Xu 1032e1a80002SHerbert Xu if (tb[IFLA_ADDRESS]) { 1033e1a80002SHerbert Xu if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 1034e1a80002SHerbert Xu return -EINVAL; 1035e1a80002SHerbert Xu if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 1036e1a80002SHerbert Xu return -EADDRNOTAVAIL; 1037e1a80002SHerbert Xu } 1038e1a80002SHerbert Xu 1039e1a80002SHerbert Xu if (!data) 1040e1a80002SHerbert Xu goto out; 1041e1a80002SHerbert Xu 1042e1a80002SHerbert Xu if (data[IFLA_GRE_REMOTE]) { 1043e1a80002SHerbert Xu memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4); 1044e1a80002SHerbert Xu if (!daddr) 1045e1a80002SHerbert Xu return -EINVAL; 1046e1a80002SHerbert Xu } 1047e1a80002SHerbert Xu 1048e1a80002SHerbert Xu out: 1049a8b8a889SMatthias Schiffer return ipgre_tunnel_validate(tb, data, extack); 1050e1a80002SHerbert Xu } 1051e1a80002SHerbert Xu 105284e54fe0SWilliam Tu static int erspan_validate(struct nlattr *tb[], struct nlattr *data[], 105384e54fe0SWilliam Tu struct netlink_ext_ack *extack) 105484e54fe0SWilliam Tu { 105584e54fe0SWilliam Tu __be16 flags = 0; 105684e54fe0SWilliam Tu int ret; 105784e54fe0SWilliam Tu 105884e54fe0SWilliam Tu if (!data) 105984e54fe0SWilliam Tu return 0; 106084e54fe0SWilliam Tu 106184e54fe0SWilliam Tu ret = ipgre_tap_validate(tb, data, extack); 106284e54fe0SWilliam Tu if (ret) 106384e54fe0SWilliam Tu return ret; 106484e54fe0SWilliam Tu 106584e54fe0SWilliam Tu /* ERSPAN should only have GRE sequence and key flag */ 10661a66a836SWilliam Tu if (data[IFLA_GRE_OFLAGS]) 106784e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); 10681a66a836SWilliam Tu if (data[IFLA_GRE_IFLAGS]) 106984e54fe0SWilliam Tu flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); 10701a66a836SWilliam Tu if (!data[IFLA_GRE_COLLECT_METADATA] && 10711a66a836SWilliam Tu flags != (GRE_SEQ | GRE_KEY)) 107284e54fe0SWilliam Tu return -EINVAL; 107384e54fe0SWilliam Tu 107484e54fe0SWilliam Tu /* ERSPAN Session ID only has 10-bit. Since we reuse 107584e54fe0SWilliam Tu * 32-bit key field as ID, check it's range. 107684e54fe0SWilliam Tu */ 107784e54fe0SWilliam Tu if (data[IFLA_GRE_IKEY] && 107884e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_IKEY])) & ~ID_MASK)) 107984e54fe0SWilliam Tu return -EINVAL; 108084e54fe0SWilliam Tu 108184e54fe0SWilliam Tu if (data[IFLA_GRE_OKEY] && 108284e54fe0SWilliam Tu (ntohl(nla_get_be32(data[IFLA_GRE_OKEY])) & ~ID_MASK)) 108384e54fe0SWilliam Tu return -EINVAL; 108484e54fe0SWilliam Tu 108584e54fe0SWilliam Tu return 0; 108684e54fe0SWilliam Tu } 108784e54fe0SWilliam Tu 108822a59be8SPhilip Prindeville static int ipgre_netlink_parms(struct net_device *dev, 10892e15ea39SPravin B Shelar struct nlattr *data[], 10902e15ea39SPravin B Shelar struct nlattr *tb[], 10919830ad4cSCraig Gallek struct ip_tunnel_parm *parms, 10929830ad4cSCraig Gallek __u32 *fwmark) 1093c19e654dSHerbert Xu { 109422a59be8SPhilip Prindeville struct ip_tunnel *t = netdev_priv(dev); 109522a59be8SPhilip Prindeville 10967bb82d92SHerbert Xu memset(parms, 0, sizeof(*parms)); 1097c19e654dSHerbert Xu 1098c19e654dSHerbert Xu parms->iph.protocol = IPPROTO_GRE; 1099c19e654dSHerbert Xu 1100c19e654dSHerbert Xu if (!data) 110122a59be8SPhilip Prindeville return 0; 1102c19e654dSHerbert Xu 1103c19e654dSHerbert Xu if (data[IFLA_GRE_LINK]) 1104c19e654dSHerbert Xu parms->link = nla_get_u32(data[IFLA_GRE_LINK]); 1105c19e654dSHerbert Xu 1106c19e654dSHerbert Xu if (data[IFLA_GRE_IFLAGS]) 1107c5441932SPravin B Shelar parms->i_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_IFLAGS])); 1108c19e654dSHerbert Xu 1109c19e654dSHerbert Xu if (data[IFLA_GRE_OFLAGS]) 1110c5441932SPravin B Shelar parms->o_flags = gre_flags_to_tnl_flags(nla_get_be16(data[IFLA_GRE_OFLAGS])); 1111c19e654dSHerbert Xu 1112c19e654dSHerbert Xu if (data[IFLA_GRE_IKEY]) 1113c19e654dSHerbert Xu parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); 1114c19e654dSHerbert Xu 1115c19e654dSHerbert Xu if (data[IFLA_GRE_OKEY]) 1116c19e654dSHerbert Xu parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); 1117c19e654dSHerbert Xu 1118c19e654dSHerbert Xu if (data[IFLA_GRE_LOCAL]) 111967b61f6cSJiri Benc parms->iph.saddr = nla_get_in_addr(data[IFLA_GRE_LOCAL]); 1120c19e654dSHerbert Xu 1121c19e654dSHerbert Xu if (data[IFLA_GRE_REMOTE]) 112267b61f6cSJiri Benc parms->iph.daddr = nla_get_in_addr(data[IFLA_GRE_REMOTE]); 1123c19e654dSHerbert Xu 1124c19e654dSHerbert Xu if (data[IFLA_GRE_TTL]) 1125c19e654dSHerbert Xu parms->iph.ttl = nla_get_u8(data[IFLA_GRE_TTL]); 1126c19e654dSHerbert Xu 1127c19e654dSHerbert Xu if (data[IFLA_GRE_TOS]) 1128c19e654dSHerbert Xu parms->iph.tos = nla_get_u8(data[IFLA_GRE_TOS]); 1129c19e654dSHerbert Xu 113022a59be8SPhilip Prindeville if (!data[IFLA_GRE_PMTUDISC] || nla_get_u8(data[IFLA_GRE_PMTUDISC])) { 113122a59be8SPhilip Prindeville if (t->ignore_df) 113222a59be8SPhilip Prindeville return -EINVAL; 1133c19e654dSHerbert Xu parms->iph.frag_off = htons(IP_DF); 113422a59be8SPhilip Prindeville } 11352e15ea39SPravin B Shelar 11362e15ea39SPravin B Shelar if (data[IFLA_GRE_COLLECT_METADATA]) { 11372e15ea39SPravin B Shelar t->collect_md = true; 1138e271c7b4SJiri Benc if (dev->type == ARPHRD_IPGRE) 1139e271c7b4SJiri Benc dev->type = ARPHRD_NONE; 11402e15ea39SPravin B Shelar } 114122a59be8SPhilip Prindeville 114222a59be8SPhilip Prindeville if (data[IFLA_GRE_IGNORE_DF]) { 114322a59be8SPhilip Prindeville if (nla_get_u8(data[IFLA_GRE_IGNORE_DF]) 114422a59be8SPhilip Prindeville && (parms->iph.frag_off & htons(IP_DF))) 114522a59be8SPhilip Prindeville return -EINVAL; 114622a59be8SPhilip Prindeville t->ignore_df = !!nla_get_u8(data[IFLA_GRE_IGNORE_DF]); 114722a59be8SPhilip Prindeville } 114822a59be8SPhilip Prindeville 11499830ad4cSCraig Gallek if (data[IFLA_GRE_FWMARK]) 11509830ad4cSCraig Gallek *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); 11519830ad4cSCraig Gallek 1152f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_VER]) { 1153f551c91dSWilliam Tu t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); 1154f551c91dSWilliam Tu 1155f551c91dSWilliam Tu if (t->erspan_ver != 1 && t->erspan_ver != 2) 1156f551c91dSWilliam Tu return -EINVAL; 1157f551c91dSWilliam Tu } 1158f551c91dSWilliam Tu 1159f551c91dSWilliam Tu if (t->erspan_ver == 1) { 116084e54fe0SWilliam Tu if (data[IFLA_GRE_ERSPAN_INDEX]) { 116184e54fe0SWilliam Tu t->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]); 116284e54fe0SWilliam Tu if (t->index & ~INDEX_MASK) 116384e54fe0SWilliam Tu return -EINVAL; 116484e54fe0SWilliam Tu } 1165f551c91dSWilliam Tu } else if (t->erspan_ver == 2) { 1166f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_DIR]) { 1167f551c91dSWilliam Tu t->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]); 1168f551c91dSWilliam Tu if (t->dir & ~(DIR_MASK >> DIR_OFFSET)) 1169f551c91dSWilliam Tu return -EINVAL; 1170f551c91dSWilliam Tu } 1171f551c91dSWilliam Tu if (data[IFLA_GRE_ERSPAN_HWID]) { 1172f551c91dSWilliam Tu t->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]); 1173f551c91dSWilliam Tu if (t->hwid & ~(HWID_MASK >> HWID_OFFSET)) 1174f551c91dSWilliam Tu return -EINVAL; 1175f551c91dSWilliam Tu } 1176f551c91dSWilliam Tu } 117784e54fe0SWilliam Tu 117822a59be8SPhilip Prindeville return 0; 1179c19e654dSHerbert Xu } 1180c19e654dSHerbert Xu 11814565e991STom Herbert /* This function returns true when ENCAP attributes are present in the nl msg */ 11824565e991STom Herbert static bool ipgre_netlink_encap_parms(struct nlattr *data[], 11834565e991STom Herbert struct ip_tunnel_encap *ipencap) 11844565e991STom Herbert { 11854565e991STom Herbert bool ret = false; 11864565e991STom Herbert 11874565e991STom Herbert memset(ipencap, 0, sizeof(*ipencap)); 11884565e991STom Herbert 11894565e991STom Herbert if (!data) 11904565e991STom Herbert return ret; 11914565e991STom Herbert 11924565e991STom Herbert if (data[IFLA_GRE_ENCAP_TYPE]) { 11934565e991STom Herbert ret = true; 11944565e991STom Herbert ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]); 11954565e991STom Herbert } 11964565e991STom Herbert 11974565e991STom Herbert if (data[IFLA_GRE_ENCAP_FLAGS]) { 11984565e991STom Herbert ret = true; 11994565e991STom Herbert ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]); 12004565e991STom Herbert } 12014565e991STom Herbert 12024565e991STom Herbert if (data[IFLA_GRE_ENCAP_SPORT]) { 12034565e991STom Herbert ret = true; 12043e97fa70SSabrina Dubroca ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]); 12054565e991STom Herbert } 12064565e991STom Herbert 12074565e991STom Herbert if (data[IFLA_GRE_ENCAP_DPORT]) { 12084565e991STom Herbert ret = true; 12093e97fa70SSabrina Dubroca ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]); 12104565e991STom Herbert } 12114565e991STom Herbert 12124565e991STom Herbert return ret; 12134565e991STom Herbert } 12144565e991STom Herbert 1215c5441932SPravin B Shelar static int gre_tap_init(struct net_device *dev) 1216e1a80002SHerbert Xu { 1217c5441932SPravin B Shelar __gre_tunnel_init(dev); 1218bec94d43Sstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1219d51711c0SXin Long netif_keep_dst(dev); 1220e1a80002SHerbert Xu 1221c5441932SPravin B Shelar return ip_tunnel_init(dev); 1222e1a80002SHerbert Xu } 1223e1a80002SHerbert Xu 1224c5441932SPravin B Shelar static const struct net_device_ops gre_tap_netdev_ops = { 1225c5441932SPravin B Shelar .ndo_init = gre_tap_init, 1226c5441932SPravin B Shelar .ndo_uninit = ip_tunnel_uninit, 1227c5441932SPravin B Shelar .ndo_start_xmit = gre_tap_xmit, 1228b8c26a33SStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 1229b8c26a33SStephen Hemminger .ndo_validate_addr = eth_validate_addr, 1230c5441932SPravin B Shelar .ndo_change_mtu = ip_tunnel_change_mtu, 1231c5441932SPravin B Shelar .ndo_get_stats64 = ip_tunnel_get_stats64, 12321e99584bSNicolas Dichtel .ndo_get_iflink = ip_tunnel_get_iflink, 1233fc4099f1SPravin B Shelar .ndo_fill_metadata_dst = gre_fill_metadata_dst, 1234b8c26a33SStephen Hemminger }; 1235b8c26a33SStephen Hemminger 123684e54fe0SWilliam Tu static int erspan_tunnel_init(struct net_device *dev) 123784e54fe0SWilliam Tu { 123884e54fe0SWilliam Tu struct ip_tunnel *tunnel = netdev_priv(dev); 123984e54fe0SWilliam Tu 124084e54fe0SWilliam Tu tunnel->tun_hlen = 8; 124184e54fe0SWilliam Tu tunnel->parms.iph.protocol = IPPROTO_GRE; 1242c122fda2SXin Long tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen + 1243f551c91dSWilliam Tu erspan_hdr_len(tunnel->erspan_ver); 124484e54fe0SWilliam Tu 124584e54fe0SWilliam Tu dev->features |= GRE_FEATURES; 124684e54fe0SWilliam Tu dev->hw_features |= GRE_FEATURES; 124784e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1248c84bed44SXin Long netif_keep_dst(dev); 124984e54fe0SWilliam Tu 125084e54fe0SWilliam Tu return ip_tunnel_init(dev); 125184e54fe0SWilliam Tu } 125284e54fe0SWilliam Tu 125384e54fe0SWilliam Tu static const struct net_device_ops erspan_netdev_ops = { 125484e54fe0SWilliam Tu .ndo_init = erspan_tunnel_init, 125584e54fe0SWilliam Tu .ndo_uninit = ip_tunnel_uninit, 125684e54fe0SWilliam Tu .ndo_start_xmit = erspan_xmit, 125784e54fe0SWilliam Tu .ndo_set_mac_address = eth_mac_addr, 125884e54fe0SWilliam Tu .ndo_validate_addr = eth_validate_addr, 125984e54fe0SWilliam Tu .ndo_change_mtu = ip_tunnel_change_mtu, 126084e54fe0SWilliam Tu .ndo_get_stats64 = ip_tunnel_get_stats64, 126184e54fe0SWilliam Tu .ndo_get_iflink = ip_tunnel_get_iflink, 126284e54fe0SWilliam Tu .ndo_fill_metadata_dst = gre_fill_metadata_dst, 126384e54fe0SWilliam Tu }; 126484e54fe0SWilliam Tu 1265e1a80002SHerbert Xu static void ipgre_tap_setup(struct net_device *dev) 1266e1a80002SHerbert Xu { 1267e1a80002SHerbert Xu ether_setup(dev); 1268cfddd4c3SXin Long dev->max_mtu = 0; 1269c5441932SPravin B Shelar dev->netdev_ops = &gre_tap_netdev_ops; 1270d13b161cSJiri Benc dev->priv_flags &= ~IFF_TX_SKB_SHARING; 1271f8c1b7ceSstephen hemminger dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 1272c5441932SPravin B Shelar ip_tunnel_setup(dev, gre_tap_net_id); 1273e1a80002SHerbert Xu } 1274e1a80002SHerbert Xu 1275c5441932SPravin B Shelar static int ipgre_newlink(struct net *src_net, struct net_device *dev, 12767a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[], 12777a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack) 1278c19e654dSHerbert Xu { 1279c5441932SPravin B Shelar struct ip_tunnel_parm p; 12804565e991STom Herbert struct ip_tunnel_encap ipencap; 12819830ad4cSCraig Gallek __u32 fwmark = 0; 128222a59be8SPhilip Prindeville int err; 12834565e991STom Herbert 12844565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 12854565e991STom Herbert struct ip_tunnel *t = netdev_priv(dev); 128622a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 12874565e991STom Herbert 12884565e991STom Herbert if (err < 0) 12894565e991STom Herbert return err; 12904565e991STom Herbert } 1291c19e654dSHerbert Xu 12929830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 129322a59be8SPhilip Prindeville if (err < 0) 129422a59be8SPhilip Prindeville return err; 12959830ad4cSCraig Gallek return ip_tunnel_newlink(dev, tb, &p, fwmark); 1296c19e654dSHerbert Xu } 1297c19e654dSHerbert Xu 1298c19e654dSHerbert Xu static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], 1299ad744b22SMatthias Schiffer struct nlattr *data[], 1300ad744b22SMatthias Schiffer struct netlink_ext_ack *extack) 1301c19e654dSHerbert Xu { 13029830ad4cSCraig Gallek struct ip_tunnel *t = netdev_priv(dev); 13034565e991STom Herbert struct ip_tunnel_encap ipencap; 13049830ad4cSCraig Gallek __u32 fwmark = t->fwmark; 1305dd9d598cSXin Long struct ip_tunnel_parm p; 130622a59be8SPhilip Prindeville int err; 13074565e991STom Herbert 13084565e991STom Herbert if (ipgre_netlink_encap_parms(data, &ipencap)) { 130922a59be8SPhilip Prindeville err = ip_tunnel_encap_setup(t, &ipencap); 13104565e991STom Herbert 13114565e991STom Herbert if (err < 0) 13124565e991STom Herbert return err; 13134565e991STom Herbert } 1314c19e654dSHerbert Xu 13159830ad4cSCraig Gallek err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); 131622a59be8SPhilip Prindeville if (err < 0) 131722a59be8SPhilip Prindeville return err; 1318dd9d598cSXin Long 1319dd9d598cSXin Long err = ip_tunnel_changelink(dev, tb, &p, fwmark); 1320dd9d598cSXin Long if (err < 0) 1321dd9d598cSXin Long return err; 1322dd9d598cSXin Long 1323dd9d598cSXin Long t->parms.i_flags = p.i_flags; 1324dd9d598cSXin Long t->parms.o_flags = p.o_flags; 1325dd9d598cSXin Long 1326dd9d598cSXin Long if (strcmp(dev->rtnl_link_ops->kind, "erspan")) 1327dd9d598cSXin Long ipgre_link_update(dev, !tb[IFLA_MTU]); 1328dd9d598cSXin Long 1329dd9d598cSXin Long return 0; 1330c19e654dSHerbert Xu } 1331c19e654dSHerbert Xu 1332c19e654dSHerbert Xu static size_t ipgre_get_size(const struct net_device *dev) 1333c19e654dSHerbert Xu { 1334c19e654dSHerbert Xu return 1335c19e654dSHerbert Xu /* IFLA_GRE_LINK */ 1336c19e654dSHerbert Xu nla_total_size(4) + 1337c19e654dSHerbert Xu /* IFLA_GRE_IFLAGS */ 1338c19e654dSHerbert Xu nla_total_size(2) + 1339c19e654dSHerbert Xu /* IFLA_GRE_OFLAGS */ 1340c19e654dSHerbert Xu nla_total_size(2) + 1341c19e654dSHerbert Xu /* IFLA_GRE_IKEY */ 1342c19e654dSHerbert Xu nla_total_size(4) + 1343c19e654dSHerbert Xu /* IFLA_GRE_OKEY */ 1344c19e654dSHerbert Xu nla_total_size(4) + 1345c19e654dSHerbert Xu /* IFLA_GRE_LOCAL */ 1346c19e654dSHerbert Xu nla_total_size(4) + 1347c19e654dSHerbert Xu /* IFLA_GRE_REMOTE */ 1348c19e654dSHerbert Xu nla_total_size(4) + 1349c19e654dSHerbert Xu /* IFLA_GRE_TTL */ 1350c19e654dSHerbert Xu nla_total_size(1) + 1351c19e654dSHerbert Xu /* IFLA_GRE_TOS */ 1352c19e654dSHerbert Xu nla_total_size(1) + 1353c19e654dSHerbert Xu /* IFLA_GRE_PMTUDISC */ 1354c19e654dSHerbert Xu nla_total_size(1) + 13554565e991STom Herbert /* IFLA_GRE_ENCAP_TYPE */ 13564565e991STom Herbert nla_total_size(2) + 13574565e991STom Herbert /* IFLA_GRE_ENCAP_FLAGS */ 13584565e991STom Herbert nla_total_size(2) + 13594565e991STom Herbert /* IFLA_GRE_ENCAP_SPORT */ 13604565e991STom Herbert nla_total_size(2) + 13614565e991STom Herbert /* IFLA_GRE_ENCAP_DPORT */ 13624565e991STom Herbert nla_total_size(2) + 13632e15ea39SPravin B Shelar /* IFLA_GRE_COLLECT_METADATA */ 13642e15ea39SPravin B Shelar nla_total_size(0) + 136522a59be8SPhilip Prindeville /* IFLA_GRE_IGNORE_DF */ 136622a59be8SPhilip Prindeville nla_total_size(1) + 13679830ad4cSCraig Gallek /* IFLA_GRE_FWMARK */ 13689830ad4cSCraig Gallek nla_total_size(4) + 136984e54fe0SWilliam Tu /* IFLA_GRE_ERSPAN_INDEX */ 137084e54fe0SWilliam Tu nla_total_size(4) + 1371f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_VER */ 1372f551c91dSWilliam Tu nla_total_size(1) + 1373f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_DIR */ 1374f551c91dSWilliam Tu nla_total_size(1) + 1375f551c91dSWilliam Tu /* IFLA_GRE_ERSPAN_HWID */ 1376f551c91dSWilliam Tu nla_total_size(2) + 1377c19e654dSHerbert Xu 0; 1378c19e654dSHerbert Xu } 1379c19e654dSHerbert Xu 1380c19e654dSHerbert Xu static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) 1381c19e654dSHerbert Xu { 1382c19e654dSHerbert Xu struct ip_tunnel *t = netdev_priv(dev); 1383c19e654dSHerbert Xu struct ip_tunnel_parm *p = &t->parms; 1384feaf5c79SLorenzo Bianconi __be16 o_flags = p->o_flags; 1385feaf5c79SLorenzo Bianconi 13862bdf700eSLorenzo Bianconi if (t->erspan_ver == 1 || t->erspan_ver == 2) { 13872bdf700eSLorenzo Bianconi if (!t->collect_md) 1388feaf5c79SLorenzo Bianconi o_flags |= TUNNEL_KEY; 1389c19e654dSHerbert Xu 13902bdf700eSLorenzo Bianconi if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver)) 13912bdf700eSLorenzo Bianconi goto nla_put_failure; 13922bdf700eSLorenzo Bianconi 13932bdf700eSLorenzo Bianconi if (t->erspan_ver == 1) { 13942bdf700eSLorenzo Bianconi if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index)) 13952bdf700eSLorenzo Bianconi goto nla_put_failure; 13962bdf700eSLorenzo Bianconi } else { 13972bdf700eSLorenzo Bianconi if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir)) 13982bdf700eSLorenzo Bianconi goto nla_put_failure; 13992bdf700eSLorenzo Bianconi if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid)) 14002bdf700eSLorenzo Bianconi goto nla_put_failure; 14012bdf700eSLorenzo Bianconi } 14022bdf700eSLorenzo Bianconi } 14032bdf700eSLorenzo Bianconi 1404f3756b79SDavid S. Miller if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || 140595f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_IFLAGS, 140695f5c64cSTom Herbert gre_tnl_flags_to_gre_flags(p->i_flags)) || 140795f5c64cSTom Herbert nla_put_be16(skb, IFLA_GRE_OFLAGS, 1408feaf5c79SLorenzo Bianconi gre_tnl_flags_to_gre_flags(o_flags)) || 1409f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || 1410f3756b79SDavid S. Miller nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || 1411930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || 1412930345eaSJiri Benc nla_put_in_addr(skb, IFLA_GRE_REMOTE, p->iph.daddr) || 1413f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TTL, p->iph.ttl) || 1414f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_TOS, p->iph.tos) || 1415f3756b79SDavid S. Miller nla_put_u8(skb, IFLA_GRE_PMTUDISC, 14169830ad4cSCraig Gallek !!(p->iph.frag_off & htons(IP_DF))) || 14179830ad4cSCraig Gallek nla_put_u32(skb, IFLA_GRE_FWMARK, t->fwmark)) 1418f3756b79SDavid S. Miller goto nla_put_failure; 14194565e991STom Herbert 14204565e991STom Herbert if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE, 14214565e991STom Herbert t->encap.type) || 14223e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT, 14234565e991STom Herbert t->encap.sport) || 14243e97fa70SSabrina Dubroca nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT, 14254565e991STom Herbert t->encap.dport) || 14264565e991STom Herbert nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS, 1427e1b2cb65STom Herbert t->encap.flags)) 14284565e991STom Herbert goto nla_put_failure; 14294565e991STom Herbert 143022a59be8SPhilip Prindeville if (nla_put_u8(skb, IFLA_GRE_IGNORE_DF, t->ignore_df)) 143122a59be8SPhilip Prindeville goto nla_put_failure; 143222a59be8SPhilip Prindeville 14332e15ea39SPravin B Shelar if (t->collect_md) { 14342e15ea39SPravin B Shelar if (nla_put_flag(skb, IFLA_GRE_COLLECT_METADATA)) 14352e15ea39SPravin B Shelar goto nla_put_failure; 14362e15ea39SPravin B Shelar } 14372e15ea39SPravin B Shelar 1438c19e654dSHerbert Xu return 0; 1439c19e654dSHerbert Xu 1440c19e654dSHerbert Xu nla_put_failure: 1441c19e654dSHerbert Xu return -EMSGSIZE; 1442c19e654dSHerbert Xu } 1443c19e654dSHerbert Xu 144484e54fe0SWilliam Tu static void erspan_setup(struct net_device *dev) 144584e54fe0SWilliam Tu { 144684581bdaSXin Long struct ip_tunnel *t = netdev_priv(dev); 144784581bdaSXin Long 144884e54fe0SWilliam Tu ether_setup(dev); 1449*0e141f75SHaishuang Yan dev->max_mtu = 0; 145084e54fe0SWilliam Tu dev->netdev_ops = &erspan_netdev_ops; 145184e54fe0SWilliam Tu dev->priv_flags &= ~IFF_TX_SKB_SHARING; 145284e54fe0SWilliam Tu dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 145384e54fe0SWilliam Tu ip_tunnel_setup(dev, erspan_net_id); 145484581bdaSXin Long t->erspan_ver = 1; 145584e54fe0SWilliam Tu } 145684e54fe0SWilliam Tu 1457c19e654dSHerbert Xu static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = { 1458c19e654dSHerbert Xu [IFLA_GRE_LINK] = { .type = NLA_U32 }, 1459c19e654dSHerbert Xu [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, 1460c19e654dSHerbert Xu [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, 1461c19e654dSHerbert Xu [IFLA_GRE_IKEY] = { .type = NLA_U32 }, 1462c19e654dSHerbert Xu [IFLA_GRE_OKEY] = { .type = NLA_U32 }, 14634d74f8baSPatrick McHardy [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, 14644d74f8baSPatrick McHardy [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, 1465c19e654dSHerbert Xu [IFLA_GRE_TTL] = { .type = NLA_U8 }, 1466c19e654dSHerbert Xu [IFLA_GRE_TOS] = { .type = NLA_U8 }, 1467c19e654dSHerbert Xu [IFLA_GRE_PMTUDISC] = { .type = NLA_U8 }, 14684565e991STom Herbert [IFLA_GRE_ENCAP_TYPE] = { .type = NLA_U16 }, 14694565e991STom Herbert [IFLA_GRE_ENCAP_FLAGS] = { .type = NLA_U16 }, 14704565e991STom Herbert [IFLA_GRE_ENCAP_SPORT] = { .type = NLA_U16 }, 14714565e991STom Herbert [IFLA_GRE_ENCAP_DPORT] = { .type = NLA_U16 }, 14722e15ea39SPravin B Shelar [IFLA_GRE_COLLECT_METADATA] = { .type = NLA_FLAG }, 147322a59be8SPhilip Prindeville [IFLA_GRE_IGNORE_DF] = { .type = NLA_U8 }, 14749830ad4cSCraig Gallek [IFLA_GRE_FWMARK] = { .type = NLA_U32 }, 147584e54fe0SWilliam Tu [IFLA_GRE_ERSPAN_INDEX] = { .type = NLA_U32 }, 1476f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_VER] = { .type = NLA_U8 }, 1477f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_DIR] = { .type = NLA_U8 }, 1478f551c91dSWilliam Tu [IFLA_GRE_ERSPAN_HWID] = { .type = NLA_U16 }, 1479c19e654dSHerbert Xu }; 1480c19e654dSHerbert Xu 1481c19e654dSHerbert Xu static struct rtnl_link_ops ipgre_link_ops __read_mostly = { 1482c19e654dSHerbert Xu .kind = "gre", 1483c19e654dSHerbert Xu .maxtype = IFLA_GRE_MAX, 1484c19e654dSHerbert Xu .policy = ipgre_policy, 1485c19e654dSHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1486c19e654dSHerbert Xu .setup = ipgre_tunnel_setup, 1487c19e654dSHerbert Xu .validate = ipgre_tunnel_validate, 1488c19e654dSHerbert Xu .newlink = ipgre_newlink, 1489c19e654dSHerbert Xu .changelink = ipgre_changelink, 1490c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1491c19e654dSHerbert Xu .get_size = ipgre_get_size, 1492c19e654dSHerbert Xu .fill_info = ipgre_fill_info, 14931728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1494c19e654dSHerbert Xu }; 1495c19e654dSHerbert Xu 1496e1a80002SHerbert Xu static struct rtnl_link_ops ipgre_tap_ops __read_mostly = { 1497e1a80002SHerbert Xu .kind = "gretap", 1498e1a80002SHerbert Xu .maxtype = IFLA_GRE_MAX, 1499e1a80002SHerbert Xu .policy = ipgre_policy, 1500e1a80002SHerbert Xu .priv_size = sizeof(struct ip_tunnel), 1501e1a80002SHerbert Xu .setup = ipgre_tap_setup, 1502e1a80002SHerbert Xu .validate = ipgre_tap_validate, 1503e1a80002SHerbert Xu .newlink = ipgre_newlink, 1504e1a80002SHerbert Xu .changelink = ipgre_changelink, 1505c5441932SPravin B Shelar .dellink = ip_tunnel_dellink, 1506e1a80002SHerbert Xu .get_size = ipgre_get_size, 1507e1a80002SHerbert Xu .fill_info = ipgre_fill_info, 15081728d4faSNicolas Dichtel .get_link_net = ip_tunnel_get_link_net, 1509e1a80002SHerbert Xu }; 1510e1a80002SHerbert Xu 151184e54fe0SWilliam Tu static struct rtnl_link_ops erspan_link_ops __read_mostly = { 151284e54fe0SWilliam Tu .kind = "erspan", 151384e54fe0SWilliam Tu .maxtype = IFLA_GRE_MAX, 151484e54fe0SWilliam Tu .policy = ipgre_policy, 151584e54fe0SWilliam Tu .priv_size = sizeof(struct ip_tunnel), 151684e54fe0SWilliam Tu .setup = erspan_setup, 151784e54fe0SWilliam Tu .validate = erspan_validate, 151884e54fe0SWilliam Tu .newlink = ipgre_newlink, 151984e54fe0SWilliam Tu .changelink = ipgre_changelink, 152084e54fe0SWilliam Tu .dellink = ip_tunnel_dellink, 152184e54fe0SWilliam Tu .get_size = ipgre_get_size, 152284e54fe0SWilliam Tu .fill_info = ipgre_fill_info, 152384e54fe0SWilliam Tu .get_link_net = ip_tunnel_get_link_net, 152484e54fe0SWilliam Tu }; 152584e54fe0SWilliam Tu 1526b2acd1dcSPravin B Shelar struct net_device *gretap_fb_dev_create(struct net *net, const char *name, 1527b2acd1dcSPravin B Shelar u8 name_assign_type) 1528b2acd1dcSPravin B Shelar { 1529b2acd1dcSPravin B Shelar struct nlattr *tb[IFLA_MAX + 1]; 1530b2acd1dcSPravin B Shelar struct net_device *dev; 1531106da663SNicolas Dichtel LIST_HEAD(list_kill); 1532b2acd1dcSPravin B Shelar struct ip_tunnel *t; 1533b2acd1dcSPravin B Shelar int err; 1534b2acd1dcSPravin B Shelar 1535b2acd1dcSPravin B Shelar memset(&tb, 0, sizeof(tb)); 1536b2acd1dcSPravin B Shelar 1537b2acd1dcSPravin B Shelar dev = rtnl_create_link(net, name, name_assign_type, 1538d0522f1cSDavid Ahern &ipgre_tap_ops, tb, NULL); 1539b2acd1dcSPravin B Shelar if (IS_ERR(dev)) 1540b2acd1dcSPravin B Shelar return dev; 1541b2acd1dcSPravin B Shelar 1542b2acd1dcSPravin B Shelar /* Configure flow based GRE device. */ 1543b2acd1dcSPravin B Shelar t = netdev_priv(dev); 1544b2acd1dcSPravin B Shelar t->collect_md = true; 1545b2acd1dcSPravin B Shelar 15467a3f4a18SMatthias Schiffer err = ipgre_newlink(net, dev, tb, NULL, NULL); 1547106da663SNicolas Dichtel if (err < 0) { 1548106da663SNicolas Dichtel free_netdev(dev); 1549106da663SNicolas Dichtel return ERR_PTR(err); 1550106da663SNicolas Dichtel } 15517e059158SDavid Wragg 15527e059158SDavid Wragg /* openvswitch users expect packet sizes to be unrestricted, 15537e059158SDavid Wragg * so set the largest MTU we can. 15547e059158SDavid Wragg */ 15557e059158SDavid Wragg err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); 15567e059158SDavid Wragg if (err) 15577e059158SDavid Wragg goto out; 15587e059158SDavid Wragg 1559da6f1da8SNicolas Dichtel err = rtnl_configure_link(dev, NULL); 1560da6f1da8SNicolas Dichtel if (err < 0) 1561da6f1da8SNicolas Dichtel goto out; 1562da6f1da8SNicolas Dichtel 1563b2acd1dcSPravin B Shelar return dev; 1564b2acd1dcSPravin B Shelar out: 1565106da663SNicolas Dichtel ip_tunnel_dellink(dev, &list_kill); 1566106da663SNicolas Dichtel unregister_netdevice_many(&list_kill); 1567b2acd1dcSPravin B Shelar return ERR_PTR(err); 1568b2acd1dcSPravin B Shelar } 1569b2acd1dcSPravin B Shelar EXPORT_SYMBOL_GPL(gretap_fb_dev_create); 1570b2acd1dcSPravin B Shelar 1571c5441932SPravin B Shelar static int __net_init ipgre_tap_init_net(struct net *net) 1572c5441932SPravin B Shelar { 15732e15ea39SPravin B Shelar return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0"); 1574c5441932SPravin B Shelar } 1575c5441932SPravin B Shelar 157664bc1781SEric Dumazet static void __net_exit ipgre_tap_exit_batch_net(struct list_head *list_net) 1577c5441932SPravin B Shelar { 157864bc1781SEric Dumazet ip_tunnel_delete_nets(list_net, gre_tap_net_id, &ipgre_tap_ops); 1579c5441932SPravin B Shelar } 1580c5441932SPravin B Shelar 1581c5441932SPravin B Shelar static struct pernet_operations ipgre_tap_net_ops = { 1582c5441932SPravin B Shelar .init = ipgre_tap_init_net, 158364bc1781SEric Dumazet .exit_batch = ipgre_tap_exit_batch_net, 1584c5441932SPravin B Shelar .id = &gre_tap_net_id, 1585c5441932SPravin B Shelar .size = sizeof(struct ip_tunnel_net), 1586c5441932SPravin B Shelar }; 15871da177e4SLinus Torvalds 158884e54fe0SWilliam Tu static int __net_init erspan_init_net(struct net *net) 158984e54fe0SWilliam Tu { 159084e54fe0SWilliam Tu return ip_tunnel_init_net(net, erspan_net_id, 159184e54fe0SWilliam Tu &erspan_link_ops, "erspan0"); 159284e54fe0SWilliam Tu } 159384e54fe0SWilliam Tu 159464bc1781SEric Dumazet static void __net_exit erspan_exit_batch_net(struct list_head *net_list) 159584e54fe0SWilliam Tu { 159664bc1781SEric Dumazet ip_tunnel_delete_nets(net_list, erspan_net_id, &erspan_link_ops); 159784e54fe0SWilliam Tu } 159884e54fe0SWilliam Tu 159984e54fe0SWilliam Tu static struct pernet_operations erspan_net_ops = { 160084e54fe0SWilliam Tu .init = erspan_init_net, 160164bc1781SEric Dumazet .exit_batch = erspan_exit_batch_net, 160284e54fe0SWilliam Tu .id = &erspan_net_id, 160384e54fe0SWilliam Tu .size = sizeof(struct ip_tunnel_net), 160484e54fe0SWilliam Tu }; 160584e54fe0SWilliam Tu 16061da177e4SLinus Torvalds static int __init ipgre_init(void) 16071da177e4SLinus Torvalds { 16081da177e4SLinus Torvalds int err; 16091da177e4SLinus Torvalds 1610058bd4d2SJoe Perches pr_info("GRE over IPv4 tunneling driver\n"); 16111da177e4SLinus Torvalds 1612cfb8fbf2SEric W. Biederman err = register_pernet_device(&ipgre_net_ops); 161359a4c759SPavel Emelyanov if (err < 0) 1614c2892f02SAlexey Dobriyan return err; 1615c2892f02SAlexey Dobriyan 1616c5441932SPravin B Shelar err = register_pernet_device(&ipgre_tap_net_ops); 1617c5441932SPravin B Shelar if (err < 0) 1618e3d0328cSWilliam Tu goto pnet_tap_failed; 1619c5441932SPravin B Shelar 162084e54fe0SWilliam Tu err = register_pernet_device(&erspan_net_ops); 162184e54fe0SWilliam Tu if (err < 0) 162284e54fe0SWilliam Tu goto pnet_erspan_failed; 162384e54fe0SWilliam Tu 16249f57c67cSPravin B Shelar err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); 1625c2892f02SAlexey Dobriyan if (err < 0) { 1626058bd4d2SJoe Perches pr_info("%s: can't add protocol\n", __func__); 1627c2892f02SAlexey Dobriyan goto add_proto_failed; 1628c2892f02SAlexey Dobriyan } 16297daa0004SPavel Emelyanov 1630c19e654dSHerbert Xu err = rtnl_link_register(&ipgre_link_ops); 1631c19e654dSHerbert Xu if (err < 0) 1632c19e654dSHerbert Xu goto rtnl_link_failed; 1633c19e654dSHerbert Xu 1634e1a80002SHerbert Xu err = rtnl_link_register(&ipgre_tap_ops); 1635e1a80002SHerbert Xu if (err < 0) 1636e1a80002SHerbert Xu goto tap_ops_failed; 1637e1a80002SHerbert Xu 163884e54fe0SWilliam Tu err = rtnl_link_register(&erspan_link_ops); 163984e54fe0SWilliam Tu if (err < 0) 164084e54fe0SWilliam Tu goto erspan_link_failed; 164184e54fe0SWilliam Tu 1642c5441932SPravin B Shelar return 0; 1643c19e654dSHerbert Xu 164484e54fe0SWilliam Tu erspan_link_failed: 164584e54fe0SWilliam Tu rtnl_link_unregister(&ipgre_tap_ops); 1646e1a80002SHerbert Xu tap_ops_failed: 1647e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 1648c19e654dSHerbert Xu rtnl_link_failed: 16499f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1650c2892f02SAlexey Dobriyan add_proto_failed: 165184e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 165284e54fe0SWilliam Tu pnet_erspan_failed: 1653c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1654e3d0328cSWilliam Tu pnet_tap_failed: 1655c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 1656c5441932SPravin B Shelar return err; 16571da177e4SLinus Torvalds } 16581da177e4SLinus Torvalds 1659db44575fSAlexey Kuznetsov static void __exit ipgre_fini(void) 16601da177e4SLinus Torvalds { 1661e1a80002SHerbert Xu rtnl_link_unregister(&ipgre_tap_ops); 1662c19e654dSHerbert Xu rtnl_link_unregister(&ipgre_link_ops); 166384e54fe0SWilliam Tu rtnl_link_unregister(&erspan_link_ops); 16649f57c67cSPravin B Shelar gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); 1665c5441932SPravin B Shelar unregister_pernet_device(&ipgre_tap_net_ops); 1666c2892f02SAlexey Dobriyan unregister_pernet_device(&ipgre_net_ops); 166784e54fe0SWilliam Tu unregister_pernet_device(&erspan_net_ops); 16681da177e4SLinus Torvalds } 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds module_init(ipgre_init); 16711da177e4SLinus Torvalds module_exit(ipgre_fini); 16721da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 16734d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gre"); 16744d74f8baSPatrick McHardy MODULE_ALIAS_RTNL_LINK("gretap"); 167584e54fe0SWilliam Tu MODULE_ALIAS_RTNL_LINK("erspan"); 16768909c9adSVasiliy Kulikov MODULE_ALIAS_NETDEV("gre0"); 1677c5441932SPravin B Shelar MODULE_ALIAS_NETDEV("gretap0"); 167884e54fe0SWilliam Tu MODULE_ALIAS_NETDEV("erspan0"); 1679