1c5441932SPravin B Shelar /* 2c5441932SPravin B Shelar * Copyright (c) 2013 Nicira, Inc. 3c5441932SPravin B Shelar * 4c5441932SPravin B Shelar * This program is free software; you can redistribute it and/or 5c5441932SPravin B Shelar * modify it under the terms of version 2 of the GNU General Public 6c5441932SPravin B Shelar * License as published by the Free Software Foundation. 7c5441932SPravin B Shelar * 8c5441932SPravin B Shelar * This program is distributed in the hope that it will be useful, but 9c5441932SPravin B Shelar * WITHOUT ANY WARRANTY; without even the implied warranty of 10c5441932SPravin B Shelar * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11c5441932SPravin B Shelar * General Public License for more details. 12c5441932SPravin B Shelar * 13c5441932SPravin B Shelar * You should have received a copy of the GNU General Public License 14c5441932SPravin B Shelar * along with this program; if not, write to the Free Software 15c5441932SPravin B Shelar * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16c5441932SPravin B Shelar * 02110-1301, USA 17c5441932SPravin B Shelar */ 18c5441932SPravin B Shelar 19c5441932SPravin B Shelar #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20c5441932SPravin B Shelar 21c5441932SPravin B Shelar #include <linux/capability.h> 22c5441932SPravin B Shelar #include <linux/module.h> 23c5441932SPravin B Shelar #include <linux/types.h> 24c5441932SPravin B Shelar #include <linux/kernel.h> 25c5441932SPravin B Shelar #include <linux/slab.h> 26c5441932SPravin B Shelar #include <linux/uaccess.h> 27c5441932SPravin B Shelar #include <linux/skbuff.h> 28c5441932SPravin B Shelar #include <linux/netdevice.h> 29c5441932SPravin B Shelar #include <linux/in.h> 30c5441932SPravin B Shelar #include <linux/tcp.h> 31c5441932SPravin B Shelar #include <linux/udp.h> 32c5441932SPravin B Shelar #include <linux/if_arp.h> 33c5441932SPravin B Shelar #include <linux/mroute.h> 34c5441932SPravin B Shelar #include <linux/init.h> 35c5441932SPravin B Shelar #include <linux/in6.h> 36c5441932SPravin B Shelar #include <linux/inetdevice.h> 37c5441932SPravin B Shelar #include <linux/igmp.h> 38c5441932SPravin B Shelar #include <linux/netfilter_ipv4.h> 39c5441932SPravin B Shelar #include <linux/etherdevice.h> 40c5441932SPravin B Shelar #include <linux/if_ether.h> 41c5441932SPravin B Shelar #include <linux/if_vlan.h> 42c5441932SPravin B Shelar #include <linux/rculist.h> 4327d79f3bSSachin Kamat #include <linux/err.h> 44c5441932SPravin B Shelar 45c5441932SPravin B Shelar #include <net/sock.h> 46c5441932SPravin B Shelar #include <net/ip.h> 47c5441932SPravin B Shelar #include <net/icmp.h> 48c5441932SPravin B Shelar #include <net/protocol.h> 49c5441932SPravin B Shelar #include <net/ip_tunnels.h> 50c5441932SPravin B Shelar #include <net/arp.h> 51c5441932SPravin B Shelar #include <net/checksum.h> 52c5441932SPravin B Shelar #include <net/dsfield.h> 53c5441932SPravin B Shelar #include <net/inet_ecn.h> 54c5441932SPravin B Shelar #include <net/xfrm.h> 55c5441932SPravin B Shelar #include <net/net_namespace.h> 56c5441932SPravin B Shelar #include <net/netns/generic.h> 57c5441932SPravin B Shelar #include <net/rtnetlink.h> 5856328486STom Herbert #include <net/udp.h> 59c5441932SPravin B Shelar 60c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 61c5441932SPravin B Shelar #include <net/ipv6.h> 62c5441932SPravin B Shelar #include <net/ip6_fib.h> 63c5441932SPravin B Shelar #include <net/ip6_route.h> 64c5441932SPravin B Shelar #endif 65c5441932SPravin B Shelar 66967680e0SDuan Jiong static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) 67c5441932SPravin B Shelar { 68c5441932SPravin B Shelar return hash_32((__force u32)key ^ (__force u32)remote, 69c5441932SPravin B Shelar IP_TNL_HASH_BITS); 70c5441932SPravin B Shelar } 71c5441932SPravin B Shelar 726c7e7610SEric Dumazet static void __tunnel_dst_set(struct ip_tunnel_dst *idst, 7395cb5745SDmitry Popov struct dst_entry *dst, __be32 saddr) 747d442fabSTom Herbert { 757d442fabSTom Herbert struct dst_entry *old_dst; 767d442fabSTom Herbert 776c7e7610SEric Dumazet dst_clone(dst); 786c7e7610SEric Dumazet old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); 797d442fabSTom Herbert dst_release(old_dst); 8095cb5745SDmitry Popov idst->saddr = saddr; 817d442fabSTom Herbert } 827d442fabSTom Herbert 83a35165caSEric Dumazet static noinline void tunnel_dst_set(struct ip_tunnel *t, 8495cb5745SDmitry Popov struct dst_entry *dst, __be32 saddr) 857d442fabSTom Herbert { 86a35165caSEric Dumazet __tunnel_dst_set(raw_cpu_ptr(t->dst_cache), dst, saddr); 877d442fabSTom Herbert } 887d442fabSTom Herbert 896c7e7610SEric Dumazet static void tunnel_dst_reset(struct ip_tunnel *t) 907d442fabSTom Herbert { 9195cb5745SDmitry Popov tunnel_dst_set(t, NULL, 0); 927d442fabSTom Herbert } 937d442fabSTom Herbert 94cf71d2bcSNicolas Dichtel void ip_tunnel_dst_reset_all(struct ip_tunnel *t) 959a4aa9afSTom Herbert { 969a4aa9afSTom Herbert int i; 979a4aa9afSTom Herbert 989a4aa9afSTom Herbert for_each_possible_cpu(i) 9995cb5745SDmitry Popov __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0); 1009a4aa9afSTom Herbert } 101cf71d2bcSNicolas Dichtel EXPORT_SYMBOL(ip_tunnel_dst_reset_all); 1029a4aa9afSTom Herbert 10395cb5745SDmitry Popov static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, 10495cb5745SDmitry Popov u32 cookie, __be32 *saddr) 1057d442fabSTom Herbert { 10695cb5745SDmitry Popov struct ip_tunnel_dst *idst; 1077d442fabSTom Herbert struct dst_entry *dst; 1087d442fabSTom Herbert 1097d442fabSTom Herbert rcu_read_lock(); 110a35165caSEric Dumazet idst = raw_cpu_ptr(t->dst_cache); 11195cb5745SDmitry Popov dst = rcu_dereference(idst->dst); 112f8864972SEric Dumazet if (dst && !atomic_inc_not_zero(&dst->__refcnt)) 113f8864972SEric Dumazet dst = NULL; 114b045d37bSEric Dumazet if (dst) { 11595cb5745SDmitry Popov if (!dst->obsolete || dst->ops->check(dst, cookie)) { 11695cb5745SDmitry Popov *saddr = idst->saddr; 11795cb5745SDmitry Popov } else { 1187d442fabSTom Herbert tunnel_dst_reset(t); 119f8864972SEric Dumazet dst_release(dst); 120f8864972SEric Dumazet dst = NULL; 1217d442fabSTom Herbert } 122b045d37bSEric Dumazet } 123b045d37bSEric Dumazet rcu_read_unlock(); 124b045d37bSEric Dumazet return (struct rtable *)dst; 1257d442fabSTom Herbert } 1267d442fabSTom Herbert 127c5441932SPravin B Shelar static bool ip_tunnel_key_match(const struct ip_tunnel_parm *p, 128c5441932SPravin B Shelar __be16 flags, __be32 key) 129c5441932SPravin B Shelar { 130c5441932SPravin B Shelar if (p->i_flags & TUNNEL_KEY) { 131c5441932SPravin B Shelar if (flags & TUNNEL_KEY) 132c5441932SPravin B Shelar return key == p->i_key; 133c5441932SPravin B Shelar else 134c5441932SPravin B Shelar /* key expected, none present */ 135c5441932SPravin B Shelar return false; 136c5441932SPravin B Shelar } else 137c5441932SPravin B Shelar return !(flags & TUNNEL_KEY); 138c5441932SPravin B Shelar } 139c5441932SPravin B Shelar 140c5441932SPravin B Shelar /* Fallback tunnel: no source, no destination, no key, no options 141c5441932SPravin B Shelar 142c5441932SPravin B Shelar Tunnel hash table: 143c5441932SPravin B Shelar We require exact key match i.e. if a key is present in packet 144c5441932SPravin B Shelar it will match only tunnel with the same key; if it is not present, 145c5441932SPravin B Shelar it will match only keyless tunnel. 146c5441932SPravin B Shelar 147c5441932SPravin B Shelar All keysless packets, if not matched configured keyless tunnels 148c5441932SPravin B Shelar will match fallback tunnel. 149c5441932SPravin B Shelar Given src, dst and key, find appropriate for input tunnel. 150c5441932SPravin B Shelar */ 151c5441932SPravin B Shelar struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, 152c5441932SPravin B Shelar int link, __be16 flags, 153c5441932SPravin B Shelar __be32 remote, __be32 local, 154c5441932SPravin B Shelar __be32 key) 155c5441932SPravin B Shelar { 156c5441932SPravin B Shelar unsigned int hash; 157c5441932SPravin B Shelar struct ip_tunnel *t, *cand = NULL; 158c5441932SPravin B Shelar struct hlist_head *head; 159c5441932SPravin B Shelar 160967680e0SDuan Jiong hash = ip_tunnel_hash(key, remote); 161c5441932SPravin B Shelar head = &itn->tunnels[hash]; 162c5441932SPravin B Shelar 163c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 164c5441932SPravin B Shelar if (local != t->parms.iph.saddr || 165c5441932SPravin B Shelar remote != t->parms.iph.daddr || 166c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 167c5441932SPravin B Shelar continue; 168c5441932SPravin B Shelar 169c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 170c5441932SPravin B Shelar continue; 171c5441932SPravin B Shelar 172c5441932SPravin B Shelar if (t->parms.link == link) 173c5441932SPravin B Shelar return t; 174c5441932SPravin B Shelar else 175c5441932SPravin B Shelar cand = t; 176c5441932SPravin B Shelar } 177c5441932SPravin B Shelar 178c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 179c5441932SPravin B Shelar if (remote != t->parms.iph.daddr || 180e0056593SDmitry Popov t->parms.iph.saddr != 0 || 181c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 182c5441932SPravin B Shelar continue; 183c5441932SPravin B Shelar 184c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 185c5441932SPravin B Shelar continue; 186c5441932SPravin B Shelar 187c5441932SPravin B Shelar if (t->parms.link == link) 188c5441932SPravin B Shelar return t; 189c5441932SPravin B Shelar else if (!cand) 190c5441932SPravin B Shelar cand = t; 191c5441932SPravin B Shelar } 192c5441932SPravin B Shelar 193967680e0SDuan Jiong hash = ip_tunnel_hash(key, 0); 194c5441932SPravin B Shelar head = &itn->tunnels[hash]; 195c5441932SPravin B Shelar 196c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 197e0056593SDmitry Popov if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && 198e0056593SDmitry Popov (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) 199e0056593SDmitry Popov continue; 200e0056593SDmitry Popov 201e0056593SDmitry Popov if (!(t->dev->flags & IFF_UP)) 202c5441932SPravin B Shelar continue; 203c5441932SPravin B Shelar 204c5441932SPravin B Shelar if (!ip_tunnel_key_match(&t->parms, flags, key)) 205c5441932SPravin B Shelar continue; 206c5441932SPravin B Shelar 207c5441932SPravin B Shelar if (t->parms.link == link) 208c5441932SPravin B Shelar return t; 209c5441932SPravin B Shelar else if (!cand) 210c5441932SPravin B Shelar cand = t; 211c5441932SPravin B Shelar } 212c5441932SPravin B Shelar 213c5441932SPravin B Shelar if (flags & TUNNEL_NO_KEY) 214c5441932SPravin B Shelar goto skip_key_lookup; 215c5441932SPravin B Shelar 216c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 217c5441932SPravin B Shelar if (t->parms.i_key != key || 218e0056593SDmitry Popov t->parms.iph.saddr != 0 || 219e0056593SDmitry Popov t->parms.iph.daddr != 0 || 220c5441932SPravin B Shelar !(t->dev->flags & IFF_UP)) 221c5441932SPravin B Shelar continue; 222c5441932SPravin B Shelar 223c5441932SPravin B Shelar if (t->parms.link == link) 224c5441932SPravin B Shelar return t; 225c5441932SPravin B Shelar else if (!cand) 226c5441932SPravin B Shelar cand = t; 227c5441932SPravin B Shelar } 228c5441932SPravin B Shelar 229c5441932SPravin B Shelar skip_key_lookup: 230c5441932SPravin B Shelar if (cand) 231c5441932SPravin B Shelar return cand; 232c5441932SPravin B Shelar 233c5441932SPravin B Shelar if (itn->fb_tunnel_dev && itn->fb_tunnel_dev->flags & IFF_UP) 234c5441932SPravin B Shelar return netdev_priv(itn->fb_tunnel_dev); 235c5441932SPravin B Shelar 236c5441932SPravin B Shelar 237c5441932SPravin B Shelar return NULL; 238c5441932SPravin B Shelar } 239c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_lookup); 240c5441932SPravin B Shelar 241c5441932SPravin B Shelar static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, 242c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 243c5441932SPravin B Shelar { 244c5441932SPravin B Shelar unsigned int h; 245c5441932SPravin B Shelar __be32 remote; 2466d608f06SSteffen Klassert __be32 i_key = parms->i_key; 247c5441932SPravin B Shelar 248c5441932SPravin B Shelar if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) 249c5441932SPravin B Shelar remote = parms->iph.daddr; 250c5441932SPravin B Shelar else 251c5441932SPravin B Shelar remote = 0; 252c5441932SPravin B Shelar 2536d608f06SSteffen Klassert if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI)) 2546d608f06SSteffen Klassert i_key = 0; 2556d608f06SSteffen Klassert 2566d608f06SSteffen Klassert h = ip_tunnel_hash(i_key, remote); 257c5441932SPravin B Shelar return &itn->tunnels[h]; 258c5441932SPravin B Shelar } 259c5441932SPravin B Shelar 260c5441932SPravin B Shelar static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t) 261c5441932SPravin B Shelar { 262c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, &t->parms); 263c5441932SPravin B Shelar 264c5441932SPravin B Shelar hlist_add_head_rcu(&t->hash_node, head); 265c5441932SPravin B Shelar } 266c5441932SPravin B Shelar 267c5441932SPravin B Shelar static void ip_tunnel_del(struct ip_tunnel *t) 268c5441932SPravin B Shelar { 269c5441932SPravin B Shelar hlist_del_init_rcu(&t->hash_node); 270c5441932SPravin B Shelar } 271c5441932SPravin B Shelar 272c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_find(struct ip_tunnel_net *itn, 273c5441932SPravin B Shelar struct ip_tunnel_parm *parms, 274c5441932SPravin B Shelar int type) 275c5441932SPravin B Shelar { 276c5441932SPravin B Shelar __be32 remote = parms->iph.daddr; 277c5441932SPravin B Shelar __be32 local = parms->iph.saddr; 278c5441932SPravin B Shelar __be32 key = parms->i_key; 2795ce54af1SDmitry Popov __be16 flags = parms->i_flags; 280c5441932SPravin B Shelar int link = parms->link; 281c5441932SPravin B Shelar struct ip_tunnel *t = NULL; 282c5441932SPravin B Shelar struct hlist_head *head = ip_bucket(itn, parms); 283c5441932SPravin B Shelar 284c5441932SPravin B Shelar hlist_for_each_entry_rcu(t, head, hash_node) { 285c5441932SPravin B Shelar if (local == t->parms.iph.saddr && 286c5441932SPravin B Shelar remote == t->parms.iph.daddr && 287c5441932SPravin B Shelar link == t->parms.link && 2885ce54af1SDmitry Popov type == t->dev->type && 2895ce54af1SDmitry Popov ip_tunnel_key_match(&t->parms, flags, key)) 290c5441932SPravin B Shelar break; 291c5441932SPravin B Shelar } 292c5441932SPravin B Shelar return t; 293c5441932SPravin B Shelar } 294c5441932SPravin B Shelar 295c5441932SPravin B Shelar static struct net_device *__ip_tunnel_create(struct net *net, 296c5441932SPravin B Shelar const struct rtnl_link_ops *ops, 297c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 298c5441932SPravin B Shelar { 299c5441932SPravin B Shelar int err; 300c5441932SPravin B Shelar struct ip_tunnel *tunnel; 301c5441932SPravin B Shelar struct net_device *dev; 302c5441932SPravin B Shelar char name[IFNAMSIZ]; 303c5441932SPravin B Shelar 304c5441932SPravin B Shelar if (parms->name[0]) 305c5441932SPravin B Shelar strlcpy(name, parms->name, IFNAMSIZ); 306c5441932SPravin B Shelar else { 30754a5d382SPravin B Shelar if (strlen(ops->kind) > (IFNAMSIZ - 3)) { 308c5441932SPravin B Shelar err = -E2BIG; 309c5441932SPravin B Shelar goto failed; 310c5441932SPravin B Shelar } 311c5441932SPravin B Shelar strlcpy(name, ops->kind, IFNAMSIZ); 312c5441932SPravin B Shelar strncat(name, "%d", 2); 313c5441932SPravin B Shelar } 314c5441932SPravin B Shelar 315c5441932SPravin B Shelar ASSERT_RTNL(); 316c835a677STom Gundersen dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); 317c5441932SPravin B Shelar if (!dev) { 318c5441932SPravin B Shelar err = -ENOMEM; 319c5441932SPravin B Shelar goto failed; 320c5441932SPravin B Shelar } 321c5441932SPravin B Shelar dev_net_set(dev, net); 322c5441932SPravin B Shelar 323c5441932SPravin B Shelar dev->rtnl_link_ops = ops; 324c5441932SPravin B Shelar 325c5441932SPravin B Shelar tunnel = netdev_priv(dev); 326c5441932SPravin B Shelar tunnel->parms = *parms; 3275e6700b3SNicolas Dichtel tunnel->net = net; 328c5441932SPravin B Shelar 329c5441932SPravin B Shelar err = register_netdevice(dev); 330c5441932SPravin B Shelar if (err) 331c5441932SPravin B Shelar goto failed_free; 332c5441932SPravin B Shelar 333c5441932SPravin B Shelar return dev; 334c5441932SPravin B Shelar 335c5441932SPravin B Shelar failed_free: 336c5441932SPravin B Shelar free_netdev(dev); 337c5441932SPravin B Shelar failed: 338c5441932SPravin B Shelar return ERR_PTR(err); 339c5441932SPravin B Shelar } 340c5441932SPravin B Shelar 3417d442fabSTom Herbert static inline void init_tunnel_flow(struct flowi4 *fl4, 342c5441932SPravin B Shelar int proto, 343c5441932SPravin B Shelar __be32 daddr, __be32 saddr, 344c5441932SPravin B Shelar __be32 key, __u8 tos, int oif) 345c5441932SPravin B Shelar { 346c5441932SPravin B Shelar memset(fl4, 0, sizeof(*fl4)); 347c5441932SPravin B Shelar fl4->flowi4_oif = oif; 348c5441932SPravin B Shelar fl4->daddr = daddr; 349c5441932SPravin B Shelar fl4->saddr = saddr; 350c5441932SPravin B Shelar fl4->flowi4_tos = tos; 351c5441932SPravin B Shelar fl4->flowi4_proto = proto; 352c5441932SPravin B Shelar fl4->fl4_gre_key = key; 353c5441932SPravin B Shelar } 354c5441932SPravin B Shelar 355c5441932SPravin B Shelar static int ip_tunnel_bind_dev(struct net_device *dev) 356c5441932SPravin B Shelar { 357c5441932SPravin B Shelar struct net_device *tdev = NULL; 358c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 359c5441932SPravin B Shelar const struct iphdr *iph; 360c5441932SPravin B Shelar int hlen = LL_MAX_HEADER; 361c5441932SPravin B Shelar int mtu = ETH_DATA_LEN; 362c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 363c5441932SPravin B Shelar 364c5441932SPravin B Shelar iph = &tunnel->parms.iph; 365c5441932SPravin B Shelar 366c5441932SPravin B Shelar /* Guess output device to choose reasonable mtu and needed_headroom */ 367c5441932SPravin B Shelar if (iph->daddr) { 368c5441932SPravin B Shelar struct flowi4 fl4; 369c5441932SPravin B Shelar struct rtable *rt; 370c5441932SPravin B Shelar 3717d442fabSTom Herbert init_tunnel_flow(&fl4, iph->protocol, iph->daddr, 3727d442fabSTom Herbert iph->saddr, tunnel->parms.o_key, 3737d442fabSTom Herbert RT_TOS(iph->tos), tunnel->parms.link); 3747d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 3757d442fabSTom Herbert 376c5441932SPravin B Shelar if (!IS_ERR(rt)) { 377c5441932SPravin B Shelar tdev = rt->dst.dev; 37895cb5745SDmitry Popov tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); 379c5441932SPravin B Shelar ip_rt_put(rt); 380c5441932SPravin B Shelar } 381c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) 382c5441932SPravin B Shelar dev->flags |= IFF_POINTOPOINT; 383c5441932SPravin B Shelar } 384c5441932SPravin B Shelar 385c5441932SPravin B Shelar if (!tdev && tunnel->parms.link) 3866c742e71SNicolas Dichtel tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); 387c5441932SPravin B Shelar 388c5441932SPravin B Shelar if (tdev) { 389c5441932SPravin B Shelar hlen = tdev->hard_header_len + tdev->needed_headroom; 390c5441932SPravin B Shelar mtu = tdev->mtu; 391c5441932SPravin B Shelar } 392c5441932SPravin B Shelar dev->iflink = tunnel->parms.link; 393c5441932SPravin B Shelar 394c5441932SPravin B Shelar dev->needed_headroom = t_hlen + hlen; 395c5441932SPravin B Shelar mtu -= (dev->hard_header_len + t_hlen); 396c5441932SPravin B Shelar 397c5441932SPravin B Shelar if (mtu < 68) 398c5441932SPravin B Shelar mtu = 68; 399c5441932SPravin B Shelar 400c5441932SPravin B Shelar return mtu; 401c5441932SPravin B Shelar } 402c5441932SPravin B Shelar 403c5441932SPravin B Shelar static struct ip_tunnel *ip_tunnel_create(struct net *net, 404c5441932SPravin B Shelar struct ip_tunnel_net *itn, 405c5441932SPravin B Shelar struct ip_tunnel_parm *parms) 406c5441932SPravin B Shelar { 4074929fd8cSJulia Lawall struct ip_tunnel *nt; 408c5441932SPravin B Shelar struct net_device *dev; 409c5441932SPravin B Shelar 410c5441932SPravin B Shelar BUG_ON(!itn->fb_tunnel_dev); 411c5441932SPravin B Shelar dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms); 412c5441932SPravin B Shelar if (IS_ERR(dev)) 4136dd3c9ecSFlorian Westphal return ERR_CAST(dev); 414c5441932SPravin B Shelar 415c5441932SPravin B Shelar dev->mtu = ip_tunnel_bind_dev(dev); 416c5441932SPravin B Shelar 417c5441932SPravin B Shelar nt = netdev_priv(dev); 418c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 419c5441932SPravin B Shelar return nt; 420c5441932SPravin B Shelar } 421c5441932SPravin B Shelar 422c5441932SPravin B Shelar int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, 423c5441932SPravin B Shelar const struct tnl_ptk_info *tpi, bool log_ecn_error) 424c5441932SPravin B Shelar { 4258f84985fSLi RongQing struct pcpu_sw_netstats *tstats; 426c5441932SPravin B Shelar const struct iphdr *iph = ip_hdr(skb); 427c5441932SPravin B Shelar int err; 428c5441932SPravin B Shelar 429c5441932SPravin B Shelar #ifdef CONFIG_NET_IPGRE_BROADCAST 430c5441932SPravin B Shelar if (ipv4_is_multicast(iph->daddr)) { 431c5441932SPravin B Shelar tunnel->dev->stats.multicast++; 432c5441932SPravin B Shelar skb->pkt_type = PACKET_BROADCAST; 433c5441932SPravin B Shelar } 434c5441932SPravin B Shelar #endif 435c5441932SPravin B Shelar 436c5441932SPravin B Shelar if ((!(tpi->flags&TUNNEL_CSUM) && (tunnel->parms.i_flags&TUNNEL_CSUM)) || 437c5441932SPravin B Shelar ((tpi->flags&TUNNEL_CSUM) && !(tunnel->parms.i_flags&TUNNEL_CSUM))) { 438c5441932SPravin B Shelar tunnel->dev->stats.rx_crc_errors++; 439c5441932SPravin B Shelar tunnel->dev->stats.rx_errors++; 440c5441932SPravin B Shelar goto drop; 441c5441932SPravin B Shelar } 442c5441932SPravin B Shelar 443c5441932SPravin B Shelar if (tunnel->parms.i_flags&TUNNEL_SEQ) { 444c5441932SPravin B Shelar if (!(tpi->flags&TUNNEL_SEQ) || 445c5441932SPravin B Shelar (tunnel->i_seqno && (s32)(ntohl(tpi->seq) - tunnel->i_seqno) < 0)) { 446c5441932SPravin B Shelar tunnel->dev->stats.rx_fifo_errors++; 447c5441932SPravin B Shelar tunnel->dev->stats.rx_errors++; 448c5441932SPravin B Shelar goto drop; 449c5441932SPravin B Shelar } 450c5441932SPravin B Shelar tunnel->i_seqno = ntohl(tpi->seq) + 1; 451c5441932SPravin B Shelar } 452c5441932SPravin B Shelar 453e96f2e7cSYing Cai skb_reset_network_header(skb); 454e96f2e7cSYing Cai 455c5441932SPravin B Shelar err = IP_ECN_decapsulate(iph, skb); 456c5441932SPravin B Shelar if (unlikely(err)) { 457c5441932SPravin B Shelar if (log_ecn_error) 458c5441932SPravin B Shelar net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", 459c5441932SPravin B Shelar &iph->saddr, iph->tos); 460c5441932SPravin B Shelar if (err > 1) { 461c5441932SPravin B Shelar ++tunnel->dev->stats.rx_frame_errors; 462c5441932SPravin B Shelar ++tunnel->dev->stats.rx_errors; 463c5441932SPravin B Shelar goto drop; 464c5441932SPravin B Shelar } 465c5441932SPravin B Shelar } 466c5441932SPravin B Shelar 467c5441932SPravin B Shelar tstats = this_cpu_ptr(tunnel->dev->tstats); 468c5441932SPravin B Shelar u64_stats_update_begin(&tstats->syncp); 469c5441932SPravin B Shelar tstats->rx_packets++; 470c5441932SPravin B Shelar tstats->rx_bytes += skb->len; 471c5441932SPravin B Shelar u64_stats_update_end(&tstats->syncp); 472c5441932SPravin B Shelar 47381b9eab5SAlexei Starovoitov skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(tunnel->dev))); 47481b9eab5SAlexei Starovoitov 4753d7b46cdSPravin B Shelar if (tunnel->dev->type == ARPHRD_ETHER) { 4763d7b46cdSPravin B Shelar skb->protocol = eth_type_trans(skb, tunnel->dev); 4773d7b46cdSPravin B Shelar skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); 4783d7b46cdSPravin B Shelar } else { 4793d7b46cdSPravin B Shelar skb->dev = tunnel->dev; 4803d7b46cdSPravin B Shelar } 48164261f23SNicolas Dichtel 482c5441932SPravin B Shelar gro_cells_receive(&tunnel->gro_cells, skb); 483c5441932SPravin B Shelar return 0; 484c5441932SPravin B Shelar 485c5441932SPravin B Shelar drop: 486c5441932SPravin B Shelar kfree_skb(skb); 487c5441932SPravin B Shelar return 0; 488c5441932SPravin B Shelar } 489c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_rcv); 490c5441932SPravin B Shelar 49156328486STom Herbert static int ip_encap_hlen(struct ip_tunnel_encap *e) 49256328486STom Herbert { 49356328486STom Herbert switch (e->type) { 49456328486STom Herbert case TUNNEL_ENCAP_NONE: 49556328486STom Herbert return 0; 49656328486STom Herbert case TUNNEL_ENCAP_FOU: 49756328486STom Herbert return sizeof(struct udphdr); 49856328486STom Herbert default: 49956328486STom Herbert return -EINVAL; 50056328486STom Herbert } 50156328486STom Herbert } 50256328486STom Herbert 50356328486STom Herbert int ip_tunnel_encap_setup(struct ip_tunnel *t, 50456328486STom Herbert struct ip_tunnel_encap *ipencap) 50556328486STom Herbert { 50656328486STom Herbert int hlen; 50756328486STom Herbert 50856328486STom Herbert memset(&t->encap, 0, sizeof(t->encap)); 50956328486STom Herbert 51056328486STom Herbert hlen = ip_encap_hlen(ipencap); 51156328486STom Herbert if (hlen < 0) 51256328486STom Herbert return hlen; 51356328486STom Herbert 51456328486STom Herbert t->encap.type = ipencap->type; 51556328486STom Herbert t->encap.sport = ipencap->sport; 51656328486STom Herbert t->encap.dport = ipencap->dport; 51756328486STom Herbert t->encap.flags = ipencap->flags; 51856328486STom Herbert 51956328486STom Herbert t->encap_hlen = hlen; 52056328486STom Herbert t->hlen = t->encap_hlen + t->tun_hlen; 52156328486STom Herbert 52256328486STom Herbert return 0; 52356328486STom Herbert } 52456328486STom Herbert EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup); 52556328486STom Herbert 52656328486STom Herbert static int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, 52756328486STom Herbert size_t hdr_len, u8 *protocol, struct flowi4 *fl4) 52856328486STom Herbert { 52956328486STom Herbert struct udphdr *uh; 53056328486STom Herbert __be16 sport; 53156328486STom Herbert bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM); 53256328486STom Herbert int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 53356328486STom Herbert 53456328486STom Herbert skb = iptunnel_handle_offloads(skb, csum, type); 53556328486STom Herbert 53656328486STom Herbert if (IS_ERR(skb)) 53756328486STom Herbert return PTR_ERR(skb); 53856328486STom Herbert 53956328486STom Herbert /* Get length and hash before making space in skb */ 54056328486STom Herbert 54156328486STom Herbert sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev), 54256328486STom Herbert skb, 0, 0, false); 54356328486STom Herbert 54456328486STom Herbert skb_push(skb, hdr_len); 54556328486STom Herbert 54656328486STom Herbert skb_reset_transport_header(skb); 54756328486STom Herbert uh = udp_hdr(skb); 54856328486STom Herbert 54956328486STom Herbert uh->dest = e->dport; 55056328486STom Herbert uh->source = sport; 55156328486STom Herbert uh->len = htons(skb->len); 55256328486STom Herbert uh->check = 0; 55356328486STom Herbert udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb, 55456328486STom Herbert fl4->saddr, fl4->daddr, skb->len); 55556328486STom Herbert 55656328486STom Herbert *protocol = IPPROTO_UDP; 55756328486STom Herbert 55856328486STom Herbert return 0; 55956328486STom Herbert } 56056328486STom Herbert 56156328486STom Herbert int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t, 56256328486STom Herbert u8 *protocol, struct flowi4 *fl4) 56356328486STom Herbert { 56456328486STom Herbert switch (t->encap.type) { 56556328486STom Herbert case TUNNEL_ENCAP_NONE: 56656328486STom Herbert return 0; 56756328486STom Herbert case TUNNEL_ENCAP_FOU: 56856328486STom Herbert return fou_build_header(skb, &t->encap, t->encap_hlen, 56956328486STom Herbert protocol, fl4); 57056328486STom Herbert default: 57156328486STom Herbert return -EINVAL; 57256328486STom Herbert } 57356328486STom Herbert } 57456328486STom Herbert EXPORT_SYMBOL(ip_tunnel_encap); 57556328486STom Herbert 57623a3647bSPravin B Shelar static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, 57723a3647bSPravin B Shelar struct rtable *rt, __be16 df) 57823a3647bSPravin B Shelar { 57923a3647bSPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 5808c91e162SAlexander Duyck int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; 58123a3647bSPravin B Shelar int mtu; 58223a3647bSPravin B Shelar 58323a3647bSPravin B Shelar if (df) 58423a3647bSPravin B Shelar mtu = dst_mtu(&rt->dst) - dev->hard_header_len 58523a3647bSPravin B Shelar - sizeof(struct iphdr) - tunnel->hlen; 58623a3647bSPravin B Shelar else 58723a3647bSPravin B Shelar mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; 58823a3647bSPravin B Shelar 58923a3647bSPravin B Shelar if (skb_dst(skb)) 59023a3647bSPravin B Shelar skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); 59123a3647bSPravin B Shelar 59223a3647bSPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) { 59323a3647bSPravin B Shelar if (!skb_is_gso(skb) && 59423a3647bSPravin B Shelar (df & htons(IP_DF)) && mtu < pkt_size) { 59523a3647bSPravin B Shelar memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 59623a3647bSPravin B Shelar icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); 59723a3647bSPravin B Shelar return -E2BIG; 59823a3647bSPravin B Shelar } 59923a3647bSPravin B Shelar } 60023a3647bSPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 60123a3647bSPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) { 60223a3647bSPravin B Shelar struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); 60323a3647bSPravin B Shelar 60423a3647bSPravin B Shelar if (rt6 && mtu < dst_mtu(skb_dst(skb)) && 60523a3647bSPravin B Shelar mtu >= IPV6_MIN_MTU) { 60623a3647bSPravin B Shelar if ((tunnel->parms.iph.daddr && 60723a3647bSPravin B Shelar !ipv4_is_multicast(tunnel->parms.iph.daddr)) || 60823a3647bSPravin B Shelar rt6->rt6i_dst.plen == 128) { 60923a3647bSPravin B Shelar rt6->rt6i_flags |= RTF_MODIFIED; 61023a3647bSPravin B Shelar dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); 61123a3647bSPravin B Shelar } 61223a3647bSPravin B Shelar } 61323a3647bSPravin B Shelar 61423a3647bSPravin B Shelar if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && 61523a3647bSPravin B Shelar mtu < pkt_size) { 61623a3647bSPravin B Shelar icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); 61723a3647bSPravin B Shelar return -E2BIG; 61823a3647bSPravin B Shelar } 61923a3647bSPravin B Shelar } 62023a3647bSPravin B Shelar #endif 62123a3647bSPravin B Shelar return 0; 62223a3647bSPravin B Shelar } 62323a3647bSPravin B Shelar 624c5441932SPravin B Shelar void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, 62556328486STom Herbert const struct iphdr *tnl_params, u8 protocol) 626c5441932SPravin B Shelar { 627c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 628c5441932SPravin B Shelar const struct iphdr *inner_iph; 629c5441932SPravin B Shelar struct flowi4 fl4; 630c5441932SPravin B Shelar u8 tos, ttl; 631c5441932SPravin B Shelar __be16 df; 632b045d37bSEric Dumazet struct rtable *rt; /* Route to the other host */ 633c5441932SPravin B Shelar unsigned int max_headroom; /* The extra header space needed */ 634c5441932SPravin B Shelar __be32 dst; 6350e6fbc5bSPravin B Shelar int err; 63622fb22eaSTimo Teräs bool connected; 637c5441932SPravin B Shelar 638c5441932SPravin B Shelar inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 63922fb22eaSTimo Teräs connected = (tunnel->parms.iph.daddr != 0); 640c5441932SPravin B Shelar 641c5441932SPravin B Shelar dst = tnl_params->daddr; 642c5441932SPravin B Shelar if (dst == 0) { 643c5441932SPravin B Shelar /* NBMA tunnel */ 644c5441932SPravin B Shelar 645c5441932SPravin B Shelar if (skb_dst(skb) == NULL) { 646c5441932SPravin B Shelar dev->stats.tx_fifo_errors++; 647c5441932SPravin B Shelar goto tx_error; 648c5441932SPravin B Shelar } 649c5441932SPravin B Shelar 650c5441932SPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) { 651c5441932SPravin B Shelar rt = skb_rtable(skb); 652c5441932SPravin B Shelar dst = rt_nexthop(rt, inner_iph->daddr); 653c5441932SPravin B Shelar } 654c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 655c5441932SPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) { 656c5441932SPravin B Shelar const struct in6_addr *addr6; 657c5441932SPravin B Shelar struct neighbour *neigh; 658c5441932SPravin B Shelar bool do_tx_error_icmp; 659c5441932SPravin B Shelar int addr_type; 660c5441932SPravin B Shelar 661c5441932SPravin B Shelar neigh = dst_neigh_lookup(skb_dst(skb), 662c5441932SPravin B Shelar &ipv6_hdr(skb)->daddr); 663c5441932SPravin B Shelar if (neigh == NULL) 664c5441932SPravin B Shelar goto tx_error; 665c5441932SPravin B Shelar 666c5441932SPravin B Shelar addr6 = (const struct in6_addr *)&neigh->primary_key; 667c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 668c5441932SPravin B Shelar 669c5441932SPravin B Shelar if (addr_type == IPV6_ADDR_ANY) { 670c5441932SPravin B Shelar addr6 = &ipv6_hdr(skb)->daddr; 671c5441932SPravin B Shelar addr_type = ipv6_addr_type(addr6); 672c5441932SPravin B Shelar } 673c5441932SPravin B Shelar 674c5441932SPravin B Shelar if ((addr_type & IPV6_ADDR_COMPATv4) == 0) 675c5441932SPravin B Shelar do_tx_error_icmp = true; 676c5441932SPravin B Shelar else { 677c5441932SPravin B Shelar do_tx_error_icmp = false; 678c5441932SPravin B Shelar dst = addr6->s6_addr32[3]; 679c5441932SPravin B Shelar } 680c5441932SPravin B Shelar neigh_release(neigh); 681c5441932SPravin B Shelar if (do_tx_error_icmp) 682c5441932SPravin B Shelar goto tx_error_icmp; 683c5441932SPravin B Shelar } 684c5441932SPravin B Shelar #endif 685c5441932SPravin B Shelar else 686c5441932SPravin B Shelar goto tx_error; 6877d442fabSTom Herbert 6887d442fabSTom Herbert connected = false; 689c5441932SPravin B Shelar } 690c5441932SPravin B Shelar 691c5441932SPravin B Shelar tos = tnl_params->tos; 692c5441932SPravin B Shelar if (tos & 0x1) { 693c5441932SPravin B Shelar tos &= ~0x1; 6947d442fabSTom Herbert if (skb->protocol == htons(ETH_P_IP)) { 695c5441932SPravin B Shelar tos = inner_iph->tos; 6967d442fabSTom Herbert connected = false; 6977d442fabSTom Herbert } else if (skb->protocol == htons(ETH_P_IPV6)) { 698c5441932SPravin B Shelar tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); 6997d442fabSTom Herbert connected = false; 7007d442fabSTom Herbert } 701c5441932SPravin B Shelar } 702c5441932SPravin B Shelar 7037d442fabSTom Herbert init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, 7047d442fabSTom Herbert tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); 7057d442fabSTom Herbert 70656328486STom Herbert if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 70756328486STom Herbert goto tx_error; 70856328486STom Herbert 70995cb5745SDmitry Popov rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL; 7107d442fabSTom Herbert 7117d442fabSTom Herbert if (!rt) { 7127d442fabSTom Herbert rt = ip_route_output_key(tunnel->net, &fl4); 7137d442fabSTom Herbert 714c5441932SPravin B Shelar if (IS_ERR(rt)) { 715c5441932SPravin B Shelar dev->stats.tx_carrier_errors++; 716c5441932SPravin B Shelar goto tx_error; 717c5441932SPravin B Shelar } 7187d442fabSTom Herbert if (connected) 71995cb5745SDmitry Popov tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); 7207d442fabSTom Herbert } 7217d442fabSTom Herbert 7220e6fbc5bSPravin B Shelar if (rt->dst.dev == dev) { 723c5441932SPravin B Shelar ip_rt_put(rt); 724c5441932SPravin B Shelar dev->stats.collisions++; 725c5441932SPravin B Shelar goto tx_error; 726c5441932SPravin B Shelar } 727c5441932SPravin B Shelar 72823a3647bSPravin B Shelar if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) { 729c5441932SPravin B Shelar ip_rt_put(rt); 730c5441932SPravin B Shelar goto tx_error; 731c5441932SPravin B Shelar } 732c5441932SPravin B Shelar 733c5441932SPravin B Shelar if (tunnel->err_count > 0) { 734c5441932SPravin B Shelar if (time_before(jiffies, 735c5441932SPravin B Shelar tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { 736c5441932SPravin B Shelar tunnel->err_count--; 737c5441932SPravin B Shelar 73811c21a30SDuan Jiong memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 739c5441932SPravin B Shelar dst_link_failure(skb); 740c5441932SPravin B Shelar } else 741c5441932SPravin B Shelar tunnel->err_count = 0; 742c5441932SPravin B Shelar } 743c5441932SPravin B Shelar 744d4a71b15SPravin B Shelar tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); 745c5441932SPravin B Shelar ttl = tnl_params->ttl; 746c5441932SPravin B Shelar if (ttl == 0) { 747c5441932SPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) 748c5441932SPravin B Shelar ttl = inner_iph->ttl; 749c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 750c5441932SPravin B Shelar else if (skb->protocol == htons(ETH_P_IPV6)) 751c5441932SPravin B Shelar ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit; 752c5441932SPravin B Shelar #endif 753c5441932SPravin B Shelar else 754c5441932SPravin B Shelar ttl = ip4_dst_hoplimit(&rt->dst); 755c5441932SPravin B Shelar } 756c5441932SPravin B Shelar 75723a3647bSPravin B Shelar df = tnl_params->frag_off; 75823a3647bSPravin B Shelar if (skb->protocol == htons(ETH_P_IP)) 75923a3647bSPravin B Shelar df |= (inner_iph->frag_off&htons(IP_DF)); 76023a3647bSPravin B Shelar 7610e6fbc5bSPravin B Shelar max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) 762*7371e022STom Herbert + rt->dst.header_len + ip_encap_hlen(&tunnel->encap); 7633e08f4a7SSteffen Klassert if (max_headroom > dev->needed_headroom) 764c5441932SPravin B Shelar dev->needed_headroom = max_headroom; 7653e08f4a7SSteffen Klassert 766c5441932SPravin B Shelar if (skb_cow_head(skb, dev->needed_headroom)) { 767586d5fc8SDmitry Popov ip_rt_put(rt); 768c5441932SPravin B Shelar dev->stats.tx_dropped++; 7693acfa1e7SEric Dumazet kfree_skb(skb); 770c5441932SPravin B Shelar return; 771c5441932SPravin B Shelar } 772c5441932SPravin B Shelar 773aad88724SEric Dumazet err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol, 774d4a71b15SPravin B Shelar tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); 7750e6fbc5bSPravin B Shelar iptunnel_xmit_stats(err, &dev->stats, dev->tstats); 776c5441932SPravin B Shelar 777c5441932SPravin B Shelar return; 778c5441932SPravin B Shelar 779c5441932SPravin B Shelar #if IS_ENABLED(CONFIG_IPV6) 780c5441932SPravin B Shelar tx_error_icmp: 781c5441932SPravin B Shelar dst_link_failure(skb); 782c5441932SPravin B Shelar #endif 783c5441932SPravin B Shelar tx_error: 784c5441932SPravin B Shelar dev->stats.tx_errors++; 7853acfa1e7SEric Dumazet kfree_skb(skb); 786c5441932SPravin B Shelar } 787c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_xmit); 788c5441932SPravin B Shelar 789c5441932SPravin B Shelar static void ip_tunnel_update(struct ip_tunnel_net *itn, 790c5441932SPravin B Shelar struct ip_tunnel *t, 791c5441932SPravin B Shelar struct net_device *dev, 792c5441932SPravin B Shelar struct ip_tunnel_parm *p, 793c5441932SPravin B Shelar bool set_mtu) 794c5441932SPravin B Shelar { 795c5441932SPravin B Shelar ip_tunnel_del(t); 796c5441932SPravin B Shelar t->parms.iph.saddr = p->iph.saddr; 797c5441932SPravin B Shelar t->parms.iph.daddr = p->iph.daddr; 798c5441932SPravin B Shelar t->parms.i_key = p->i_key; 799c5441932SPravin B Shelar t->parms.o_key = p->o_key; 800c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 801c5441932SPravin B Shelar memcpy(dev->dev_addr, &p->iph.saddr, 4); 802c5441932SPravin B Shelar memcpy(dev->broadcast, &p->iph.daddr, 4); 803c5441932SPravin B Shelar } 804c5441932SPravin B Shelar ip_tunnel_add(itn, t); 805c5441932SPravin B Shelar 806c5441932SPravin B Shelar t->parms.iph.ttl = p->iph.ttl; 807c5441932SPravin B Shelar t->parms.iph.tos = p->iph.tos; 808c5441932SPravin B Shelar t->parms.iph.frag_off = p->iph.frag_off; 809c5441932SPravin B Shelar 810c5441932SPravin B Shelar if (t->parms.link != p->link) { 811c5441932SPravin B Shelar int mtu; 812c5441932SPravin B Shelar 813c5441932SPravin B Shelar t->parms.link = p->link; 814c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 815c5441932SPravin B Shelar if (set_mtu) 816c5441932SPravin B Shelar dev->mtu = mtu; 817c5441932SPravin B Shelar } 818cf71d2bcSNicolas Dichtel ip_tunnel_dst_reset_all(t); 819c5441932SPravin B Shelar netdev_state_change(dev); 820c5441932SPravin B Shelar } 821c5441932SPravin B Shelar 822c5441932SPravin B Shelar int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) 823c5441932SPravin B Shelar { 824c5441932SPravin B Shelar int err = 0; 8258c923ce2SNicolas Dichtel struct ip_tunnel *t = netdev_priv(dev); 8268c923ce2SNicolas Dichtel struct net *net = t->net; 8278c923ce2SNicolas Dichtel struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); 828c5441932SPravin B Shelar 829c5441932SPravin B Shelar BUG_ON(!itn->fb_tunnel_dev); 830c5441932SPravin B Shelar switch (cmd) { 831c5441932SPravin B Shelar case SIOCGETTUNNEL: 8328c923ce2SNicolas Dichtel if (dev == itn->fb_tunnel_dev) { 833c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 834c5441932SPravin B Shelar if (t == NULL) 835c5441932SPravin B Shelar t = netdev_priv(dev); 8368c923ce2SNicolas Dichtel } 837c5441932SPravin B Shelar memcpy(p, &t->parms, sizeof(*p)); 838c5441932SPravin B Shelar break; 839c5441932SPravin B Shelar 840c5441932SPravin B Shelar case SIOCADDTUNNEL: 841c5441932SPravin B Shelar case SIOCCHGTUNNEL: 842c5441932SPravin B Shelar err = -EPERM; 843c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 844c5441932SPravin B Shelar goto done; 845c5441932SPravin B Shelar if (p->iph.ttl) 846c5441932SPravin B Shelar p->iph.frag_off |= htons(IP_DF); 8477c8e6b9cSDmitry Popov if (!(p->i_flags & VTI_ISVTI)) { 848c5441932SPravin B Shelar if (!(p->i_flags & TUNNEL_KEY)) 849c5441932SPravin B Shelar p->i_key = 0; 850c5441932SPravin B Shelar if (!(p->o_flags & TUNNEL_KEY)) 851c5441932SPravin B Shelar p->o_key = 0; 8527c8e6b9cSDmitry Popov } 853c5441932SPravin B Shelar 854c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 855c5441932SPravin B Shelar 856d61746b2SSteffen Klassert if (cmd == SIOCADDTUNNEL) { 857d61746b2SSteffen Klassert if (!t) { 858c5441932SPravin B Shelar t = ip_tunnel_create(net, itn, p); 859ee30ef4dSDuan Jiong err = PTR_ERR_OR_ZERO(t); 8606dd3c9ecSFlorian Westphal break; 8616dd3c9ecSFlorian Westphal } 862d61746b2SSteffen Klassert 863d61746b2SSteffen Klassert err = -EEXIST; 864d61746b2SSteffen Klassert break; 865d61746b2SSteffen Klassert } 866c5441932SPravin B Shelar if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { 867c5441932SPravin B Shelar if (t != NULL) { 868c5441932SPravin B Shelar if (t->dev != dev) { 869c5441932SPravin B Shelar err = -EEXIST; 870c5441932SPravin B Shelar break; 871c5441932SPravin B Shelar } 872c5441932SPravin B Shelar } else { 873c5441932SPravin B Shelar unsigned int nflags = 0; 874c5441932SPravin B Shelar 875c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 876c5441932SPravin B Shelar nflags = IFF_BROADCAST; 877c5441932SPravin B Shelar else if (p->iph.daddr) 878c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 879c5441932SPravin B Shelar 880c5441932SPravin B Shelar if ((dev->flags^nflags)&(IFF_POINTOPOINT|IFF_BROADCAST)) { 881c5441932SPravin B Shelar err = -EINVAL; 882c5441932SPravin B Shelar break; 883c5441932SPravin B Shelar } 884c5441932SPravin B Shelar 885c5441932SPravin B Shelar t = netdev_priv(dev); 886c5441932SPravin B Shelar } 887c5441932SPravin B Shelar } 888c5441932SPravin B Shelar 889c5441932SPravin B Shelar if (t) { 890c5441932SPravin B Shelar err = 0; 891c5441932SPravin B Shelar ip_tunnel_update(itn, t, dev, p, true); 8926dd3c9ecSFlorian Westphal } else { 8936dd3c9ecSFlorian Westphal err = -ENOENT; 8946dd3c9ecSFlorian Westphal } 895c5441932SPravin B Shelar break; 896c5441932SPravin B Shelar 897c5441932SPravin B Shelar case SIOCDELTUNNEL: 898c5441932SPravin B Shelar err = -EPERM; 899c5441932SPravin B Shelar if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 900c5441932SPravin B Shelar goto done; 901c5441932SPravin B Shelar 902c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) { 903c5441932SPravin B Shelar err = -ENOENT; 904c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); 905c5441932SPravin B Shelar if (t == NULL) 906c5441932SPravin B Shelar goto done; 907c5441932SPravin B Shelar err = -EPERM; 908c5441932SPravin B Shelar if (t == netdev_priv(itn->fb_tunnel_dev)) 909c5441932SPravin B Shelar goto done; 910c5441932SPravin B Shelar dev = t->dev; 911c5441932SPravin B Shelar } 912c5441932SPravin B Shelar unregister_netdevice(dev); 913c5441932SPravin B Shelar err = 0; 914c5441932SPravin B Shelar break; 915c5441932SPravin B Shelar 916c5441932SPravin B Shelar default: 917c5441932SPravin B Shelar err = -EINVAL; 918c5441932SPravin B Shelar } 919c5441932SPravin B Shelar 920c5441932SPravin B Shelar done: 921c5441932SPravin B Shelar return err; 922c5441932SPravin B Shelar } 923c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); 924c5441932SPravin B Shelar 925c5441932SPravin B Shelar int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) 926c5441932SPravin B Shelar { 927c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 928c5441932SPravin B Shelar int t_hlen = tunnel->hlen + sizeof(struct iphdr); 929c5441932SPravin B Shelar 930c5441932SPravin B Shelar if (new_mtu < 68 || 931c5441932SPravin B Shelar new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) 932c5441932SPravin B Shelar return -EINVAL; 933c5441932SPravin B Shelar dev->mtu = new_mtu; 934c5441932SPravin B Shelar return 0; 935c5441932SPravin B Shelar } 936c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); 937c5441932SPravin B Shelar 938c5441932SPravin B Shelar static void ip_tunnel_dev_free(struct net_device *dev) 939c5441932SPravin B Shelar { 940c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 941c5441932SPravin B Shelar 942c5441932SPravin B Shelar gro_cells_destroy(&tunnel->gro_cells); 9439a4aa9afSTom Herbert free_percpu(tunnel->dst_cache); 944c5441932SPravin B Shelar free_percpu(dev->tstats); 945c5441932SPravin B Shelar free_netdev(dev); 946c5441932SPravin B Shelar } 947c5441932SPravin B Shelar 948c5441932SPravin B Shelar void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) 949c5441932SPravin B Shelar { 950c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 951c5441932SPravin B Shelar struct ip_tunnel_net *itn; 952c5441932SPravin B Shelar 9536c742e71SNicolas Dichtel itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id); 954c5441932SPravin B Shelar 955c5441932SPravin B Shelar if (itn->fb_tunnel_dev != dev) { 956c5441932SPravin B Shelar ip_tunnel_del(netdev_priv(dev)); 957c5441932SPravin B Shelar unregister_netdevice_queue(dev, head); 958c5441932SPravin B Shelar } 959c5441932SPravin B Shelar } 960c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_dellink); 961c5441932SPravin B Shelar 962d3b6f614SEric Dumazet int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, 963c5441932SPravin B Shelar struct rtnl_link_ops *ops, char *devname) 964c5441932SPravin B Shelar { 965c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); 966c5441932SPravin B Shelar struct ip_tunnel_parm parms; 9676261d983Sstephen hemminger unsigned int i; 968c5441932SPravin B Shelar 9696261d983Sstephen hemminger for (i = 0; i < IP_TNL_HASH_SIZE; i++) 9706261d983Sstephen hemminger INIT_HLIST_HEAD(&itn->tunnels[i]); 971c5441932SPravin B Shelar 972c5441932SPravin B Shelar if (!ops) { 973c5441932SPravin B Shelar itn->fb_tunnel_dev = NULL; 974c5441932SPravin B Shelar return 0; 975c5441932SPravin B Shelar } 9766261d983Sstephen hemminger 977c5441932SPravin B Shelar memset(&parms, 0, sizeof(parms)); 978c5441932SPravin B Shelar if (devname) 979c5441932SPravin B Shelar strlcpy(parms.name, devname, IFNAMSIZ); 980c5441932SPravin B Shelar 981c5441932SPravin B Shelar rtnl_lock(); 982c5441932SPravin B Shelar itn->fb_tunnel_dev = __ip_tunnel_create(net, ops, &parms); 983ea857f28SDan Carpenter /* FB netdevice is special: we have one, and only one per netns. 984ea857f28SDan Carpenter * Allowing to move it to another netns is clearly unsafe. 985ea857f28SDan Carpenter */ 98667013282SSteffen Klassert if (!IS_ERR(itn->fb_tunnel_dev)) { 987ea857f28SDan Carpenter itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; 98878ff4be4SSteffen Klassert itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); 98967013282SSteffen Klassert ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); 99067013282SSteffen Klassert } 991b4de77adSDan Carpenter rtnl_unlock(); 992c5441932SPravin B Shelar 99327d79f3bSSachin Kamat return PTR_ERR_OR_ZERO(itn->fb_tunnel_dev); 994c5441932SPravin B Shelar } 995c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init_net); 996c5441932SPravin B Shelar 9976c742e71SNicolas Dichtel static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head, 9986c742e71SNicolas Dichtel struct rtnl_link_ops *ops) 999c5441932SPravin B Shelar { 10006c742e71SNicolas Dichtel struct net *net = dev_net(itn->fb_tunnel_dev); 10016c742e71SNicolas Dichtel struct net_device *dev, *aux; 1002c5441932SPravin B Shelar int h; 1003c5441932SPravin B Shelar 10046c742e71SNicolas Dichtel for_each_netdev_safe(net, dev, aux) 10056c742e71SNicolas Dichtel if (dev->rtnl_link_ops == ops) 10066c742e71SNicolas Dichtel unregister_netdevice_queue(dev, head); 10076c742e71SNicolas Dichtel 1008c5441932SPravin B Shelar for (h = 0; h < IP_TNL_HASH_SIZE; h++) { 1009c5441932SPravin B Shelar struct ip_tunnel *t; 1010c5441932SPravin B Shelar struct hlist_node *n; 1011c5441932SPravin B Shelar struct hlist_head *thead = &itn->tunnels[h]; 1012c5441932SPravin B Shelar 1013c5441932SPravin B Shelar hlist_for_each_entry_safe(t, n, thead, hash_node) 10146c742e71SNicolas Dichtel /* If dev is in the same netns, it has already 10156c742e71SNicolas Dichtel * been added to the list by the previous loop. 10166c742e71SNicolas Dichtel */ 10176c742e71SNicolas Dichtel if (!net_eq(dev_net(t->dev), net)) 1018c5441932SPravin B Shelar unregister_netdevice_queue(t->dev, head); 1019c5441932SPravin B Shelar } 1020c5441932SPravin B Shelar } 1021c5441932SPravin B Shelar 10226c742e71SNicolas Dichtel void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops) 1023c5441932SPravin B Shelar { 1024c5441932SPravin B Shelar LIST_HEAD(list); 1025c5441932SPravin B Shelar 1026c5441932SPravin B Shelar rtnl_lock(); 10276c742e71SNicolas Dichtel ip_tunnel_destroy(itn, &list, ops); 1028c5441932SPravin B Shelar unregister_netdevice_many(&list); 1029c5441932SPravin B Shelar rtnl_unlock(); 1030c5441932SPravin B Shelar } 1031c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_delete_net); 1032c5441932SPravin B Shelar 1033c5441932SPravin B Shelar int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], 1034c5441932SPravin B Shelar struct ip_tunnel_parm *p) 1035c5441932SPravin B Shelar { 1036c5441932SPravin B Shelar struct ip_tunnel *nt; 1037c5441932SPravin B Shelar struct net *net = dev_net(dev); 1038c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1039c5441932SPravin B Shelar int mtu; 1040c5441932SPravin B Shelar int err; 1041c5441932SPravin B Shelar 1042c5441932SPravin B Shelar nt = netdev_priv(dev); 1043c5441932SPravin B Shelar itn = net_generic(net, nt->ip_tnl_net_id); 1044c5441932SPravin B Shelar 1045c5441932SPravin B Shelar if (ip_tunnel_find(itn, p, dev->type)) 1046c5441932SPravin B Shelar return -EEXIST; 1047c5441932SPravin B Shelar 10485e6700b3SNicolas Dichtel nt->net = net; 1049c5441932SPravin B Shelar nt->parms = *p; 1050c5441932SPravin B Shelar err = register_netdevice(dev); 1051c5441932SPravin B Shelar if (err) 1052c5441932SPravin B Shelar goto out; 1053c5441932SPravin B Shelar 1054c5441932SPravin B Shelar if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) 1055c5441932SPravin B Shelar eth_hw_addr_random(dev); 1056c5441932SPravin B Shelar 1057c5441932SPravin B Shelar mtu = ip_tunnel_bind_dev(dev); 1058c5441932SPravin B Shelar if (!tb[IFLA_MTU]) 1059c5441932SPravin B Shelar dev->mtu = mtu; 1060c5441932SPravin B Shelar 1061c5441932SPravin B Shelar ip_tunnel_add(itn, nt); 1062c5441932SPravin B Shelar 1063c5441932SPravin B Shelar out: 1064c5441932SPravin B Shelar return err; 1065c5441932SPravin B Shelar } 1066c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_newlink); 1067c5441932SPravin B Shelar 1068c5441932SPravin B Shelar int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[], 1069c5441932SPravin B Shelar struct ip_tunnel_parm *p) 1070c5441932SPravin B Shelar { 10716c742e71SNicolas Dichtel struct ip_tunnel *t; 1072c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 10736c742e71SNicolas Dichtel struct net *net = tunnel->net; 1074c5441932SPravin B Shelar struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); 1075c5441932SPravin B Shelar 1076c5441932SPravin B Shelar if (dev == itn->fb_tunnel_dev) 1077c5441932SPravin B Shelar return -EINVAL; 1078c5441932SPravin B Shelar 1079c5441932SPravin B Shelar t = ip_tunnel_find(itn, p, dev->type); 1080c5441932SPravin B Shelar 1081c5441932SPravin B Shelar if (t) { 1082c5441932SPravin B Shelar if (t->dev != dev) 1083c5441932SPravin B Shelar return -EEXIST; 1084c5441932SPravin B Shelar } else { 10856c742e71SNicolas Dichtel t = tunnel; 1086c5441932SPravin B Shelar 1087c5441932SPravin B Shelar if (dev->type != ARPHRD_ETHER) { 1088c5441932SPravin B Shelar unsigned int nflags = 0; 1089c5441932SPravin B Shelar 1090c5441932SPravin B Shelar if (ipv4_is_multicast(p->iph.daddr)) 1091c5441932SPravin B Shelar nflags = IFF_BROADCAST; 1092c5441932SPravin B Shelar else if (p->iph.daddr) 1093c5441932SPravin B Shelar nflags = IFF_POINTOPOINT; 1094c5441932SPravin B Shelar 1095c5441932SPravin B Shelar if ((dev->flags ^ nflags) & 1096c5441932SPravin B Shelar (IFF_POINTOPOINT | IFF_BROADCAST)) 1097c5441932SPravin B Shelar return -EINVAL; 1098c5441932SPravin B Shelar } 1099c5441932SPravin B Shelar } 1100c5441932SPravin B Shelar 1101c5441932SPravin B Shelar ip_tunnel_update(itn, t, dev, p, !tb[IFLA_MTU]); 1102c5441932SPravin B Shelar return 0; 1103c5441932SPravin B Shelar } 1104c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_changelink); 1105c5441932SPravin B Shelar 1106c5441932SPravin B Shelar int ip_tunnel_init(struct net_device *dev) 1107c5441932SPravin B Shelar { 1108c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1109c5441932SPravin B Shelar struct iphdr *iph = &tunnel->parms.iph; 11101c213bd2SWANG Cong int err; 1111c5441932SPravin B Shelar 1112c5441932SPravin B Shelar dev->destructor = ip_tunnel_dev_free; 11131c213bd2SWANG Cong dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 1114c5441932SPravin B Shelar if (!dev->tstats) 1115c5441932SPravin B Shelar return -ENOMEM; 1116c5441932SPravin B Shelar 11179a4aa9afSTom Herbert tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); 11189a4aa9afSTom Herbert if (!tunnel->dst_cache) { 11199a4aa9afSTom Herbert free_percpu(dev->tstats); 11209a4aa9afSTom Herbert return -ENOMEM; 11219a4aa9afSTom Herbert } 11229a4aa9afSTom Herbert 1123c5441932SPravin B Shelar err = gro_cells_init(&tunnel->gro_cells, dev); 1124c5441932SPravin B Shelar if (err) { 11259a4aa9afSTom Herbert free_percpu(tunnel->dst_cache); 1126c5441932SPravin B Shelar free_percpu(dev->tstats); 1127c5441932SPravin B Shelar return err; 1128c5441932SPravin B Shelar } 1129c5441932SPravin B Shelar 1130c5441932SPravin B Shelar tunnel->dev = dev; 11316c742e71SNicolas Dichtel tunnel->net = dev_net(dev); 1132c5441932SPravin B Shelar strcpy(tunnel->parms.name, dev->name); 1133c5441932SPravin B Shelar iph->version = 4; 1134c5441932SPravin B Shelar iph->ihl = 5; 1135c5441932SPravin B Shelar 1136c5441932SPravin B Shelar return 0; 1137c5441932SPravin B Shelar } 1138c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_init); 1139c5441932SPravin B Shelar 1140c5441932SPravin B Shelar void ip_tunnel_uninit(struct net_device *dev) 1141c5441932SPravin B Shelar { 1142c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 11436c742e71SNicolas Dichtel struct net *net = tunnel->net; 1144c5441932SPravin B Shelar struct ip_tunnel_net *itn; 1145c5441932SPravin B Shelar 1146c5441932SPravin B Shelar itn = net_generic(net, tunnel->ip_tnl_net_id); 1147c5441932SPravin B Shelar /* fb_tunnel_dev will be unregisted in net-exit call. */ 1148c5441932SPravin B Shelar if (itn->fb_tunnel_dev != dev) 1149c5441932SPravin B Shelar ip_tunnel_del(netdev_priv(dev)); 11507d442fabSTom Herbert 1151cf71d2bcSNicolas Dichtel ip_tunnel_dst_reset_all(tunnel); 1152c5441932SPravin B Shelar } 1153c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_uninit); 1154c5441932SPravin B Shelar 1155c5441932SPravin B Shelar /* Do least required initialization, rest of init is done in tunnel_init call */ 1156c5441932SPravin B Shelar void ip_tunnel_setup(struct net_device *dev, int net_id) 1157c5441932SPravin B Shelar { 1158c5441932SPravin B Shelar struct ip_tunnel *tunnel = netdev_priv(dev); 1159c5441932SPravin B Shelar tunnel->ip_tnl_net_id = net_id; 1160c5441932SPravin B Shelar } 1161c5441932SPravin B Shelar EXPORT_SYMBOL_GPL(ip_tunnel_setup); 1162c5441932SPravin B Shelar 1163c5441932SPravin B Shelar MODULE_LICENSE("GPL"); 1164