datapath: Drop support for kernel older than 3.10
[cascardo/ovs.git] / datapath / linux / compat / ip_tunnel.c
1 /*
2  * Copyright (c) 2013 Nicira, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * General Public License for more details.
12  *
13  */
14
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17 #include <linux/capability.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/kernel.h>
21 #include <linux/kconfig.h>
22 #include <linux/slab.h>
23 #include <linux/uaccess.h>
24 #include <linux/skbuff.h>
25 #include <linux/netdevice.h>
26 #include <linux/in.h>
27 #include <linux/tcp.h>
28 #include <linux/udp.h>
29 #include <linux/if_arp.h>
30 #include <linux/mroute.h>
31 #include <linux/init.h>
32 #include <linux/in6.h>
33 #include <linux/inetdevice.h>
34 #include <linux/igmp.h>
35 #include <linux/netfilter_ipv4.h>
36 #include <linux/etherdevice.h>
37 #include <linux/if_ether.h>
38 #include <linux/if_vlan.h>
39 #include <linux/rculist.h>
40 #include <linux/err.h>
41
42 #include <net/sock.h>
43 #include <net/ip.h>
44 #include <net/icmp.h>
45 #include <net/protocol.h>
46 #include <net/ip_tunnels.h>
47 #include <net/arp.h>
48 #include <net/checksum.h>
49 #include <net/dsfield.h>
50 #include <net/inet_ecn.h>
51 #include <net/xfrm.h>
52 #include <net/net_namespace.h>
53 #include <net/netns/generic.h>
54 #include <net/rtnetlink.h>
55 #include <net/udp.h>
56
57 #if IS_ENABLED(CONFIG_IPV6)
58 #include <net/ipv6.h>
59 #include <net/ip6_fib.h>
60 #include <net/ip6_route.h>
61 #endif
62
63 #include "compat.h"
64
65 #ifndef HAVE_METADATA_DST
66 static void ip_tunnel_add(struct ip_tunnel_net *itn, struct ip_tunnel *t)
67 {
68         if (t->collect_md)
69                 rcu_assign_pointer(itn->collect_md_tun, t);
70         else
71                 WARN_ONCE(1, "%s: collect md not set\n", t->dev->name);
72 }
73
74 static void ip_tunnel_del(struct ip_tunnel_net *itn, struct ip_tunnel *t)
75 {
76         if (t->collect_md)
77                 rcu_assign_pointer(itn->collect_md_tun, NULL);
78 }
79
80 static inline void init_tunnel_flow(struct flowi4 *fl4,
81                                     int proto,
82                                     __be32 daddr, __be32 saddr,
83                                     __be32 key, __u8 tos, int oif)
84 {
85         memset(fl4, 0, sizeof(*fl4));
86         fl4->flowi4_oif = oif;
87         fl4->daddr = daddr;
88         fl4->saddr = saddr;
89         fl4->flowi4_tos = tos;
90         fl4->flowi4_proto = proto;
91         fl4->fl4_gre_key = key;
92 }
93
94 static int ip_tunnel_bind_dev(struct net_device *dev)
95 {
96         struct net_device *tdev = NULL;
97         struct ip_tunnel *tunnel = netdev_priv(dev);
98         const struct iphdr *iph;
99         int hlen = LL_MAX_HEADER;
100         int mtu = ETH_DATA_LEN;
101         int t_hlen = tunnel->hlen + sizeof(struct iphdr);
102
103         iph = &tunnel->parms.iph;
104
105         /* Guess output device to choose reasonable mtu and needed_headroom */
106         if (iph->daddr) {
107                 struct flowi4 fl4;
108                 struct rtable *rt;
109
110                 init_tunnel_flow(&fl4, iph->protocol, iph->daddr,
111                                  iph->saddr, tunnel->parms.o_key,
112                                  RT_TOS(iph->tos), tunnel->parms.link);
113                 rt = ip_route_output_key(tunnel->net, &fl4);
114
115                 if (!IS_ERR(rt)) {
116                         tdev = rt->dst.dev;
117                         ip_rt_put(rt);
118                 }
119                 if (dev->type != ARPHRD_ETHER)
120                         dev->flags |= IFF_POINTOPOINT;
121         }
122
123         if (!tdev && tunnel->parms.link)
124                 tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link);
125
126         if (tdev) {
127                 hlen = tdev->hard_header_len + tdev->needed_headroom;
128                 mtu = tdev->mtu;
129         }
130
131         dev->needed_headroom = t_hlen + hlen;
132         mtu -= (dev->hard_header_len + t_hlen);
133
134         if (mtu < 68)
135                 mtu = 68;
136
137         return mtu;
138 }
139
140 int rpl___ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
141 {
142         struct ip_tunnel *tunnel = netdev_priv(dev);
143         int t_hlen = tunnel->hlen + sizeof(struct iphdr);
144         int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
145
146         if (new_mtu < 68)
147                 return -EINVAL;
148
149         if (new_mtu > max_mtu) {
150                 if (strict)
151                         return -EINVAL;
152
153                 new_mtu = max_mtu;
154         }
155
156         dev->mtu = new_mtu;
157         return 0;
158 }
159
160 int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
161 {
162         return rpl___ip_tunnel_change_mtu(dev, new_mtu, true);
163 }
164
165 static void ip_tunnel_dev_free(struct net_device *dev)
166 {
167         free_percpu(dev->tstats);
168         free_netdev(dev);
169 }
170
171 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
172 void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
173 #else
174 void rpl_ip_tunnel_dellink(struct net_device *dev)
175 #endif
176 {
177         struct ip_tunnel *tunnel = netdev_priv(dev);
178         struct ip_tunnel_net *itn;
179
180         itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
181
182         ip_tunnel_del(itn, netdev_priv(dev));
183 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
184         unregister_netdevice_queue(dev, head);
185 #endif
186 }
187
188 int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
189                                   struct rtnl_link_ops *ops, char *devname)
190 {
191         struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
192
193         itn->collect_md_tun = NULL;
194         itn->rtnl_ops = ops;
195         return 0;
196 }
197
198 static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
199                               struct rtnl_link_ops *ops)
200 {
201         struct ip_tunnel *t;
202
203         t = rtnl_dereference(itn->collect_md_tun);
204         if (!t)
205                 return;
206         unregister_netdevice_queue(t->dev, head);
207 }
208
209 void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
210 {
211         LIST_HEAD(list);
212
213         rtnl_lock();
214         ip_tunnel_destroy(itn, &list, ops);
215         unregister_netdevice_many(&list);
216         rtnl_unlock();
217 }
218
219 int rpl_ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
220                       struct ip_tunnel_parm *p)
221 {
222         struct ip_tunnel *nt;
223         struct net *net = dev_net(dev);
224         struct ip_tunnel_net *itn;
225         int mtu;
226         int err;
227
228         nt = netdev_priv(dev);
229         itn = net_generic(net, nt->ip_tnl_net_id);
230
231         if (nt->collect_md) {
232                 if (rtnl_dereference(itn->collect_md_tun))
233                         return -EEXIST;
234         } else {
235                 return -EOPNOTSUPP;
236         }
237
238         nt->net = net;
239         nt->parms = *p;
240         err = register_netdevice(dev);
241         if (err)
242                 goto out;
243
244         if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
245                 eth_hw_addr_random(dev);
246
247         mtu = ip_tunnel_bind_dev(dev);
248         if (!tb[IFLA_MTU])
249                 dev->mtu = mtu;
250
251         ip_tunnel_add(itn, nt);
252 out:
253         return err;
254 }
255
256 int rpl_ip_tunnel_init(struct net_device *dev)
257 {
258         struct ip_tunnel *tunnel = netdev_priv(dev);
259         struct iphdr *iph = &tunnel->parms.iph;
260
261         dev->destructor = ip_tunnel_dev_free;
262         dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
263         if (!dev->tstats)
264                 return -ENOMEM;
265         tunnel->dev = dev;
266         tunnel->net = dev_net(dev);
267         strcpy(tunnel->parms.name, dev->name);
268         iph->version            = 4;
269         iph->ihl                = 5;
270
271         if (tunnel->collect_md)
272                 dev->features |= NETIF_F_NETNS_LOCAL;
273
274         return 0;
275 }
276
277 void rpl_ip_tunnel_uninit(struct net_device *dev)
278 {
279         struct ip_tunnel *tunnel = netdev_priv(dev);
280         struct net *net = tunnel->net;
281         struct ip_tunnel_net *itn;
282
283         itn = net_generic(net, tunnel->ip_tnl_net_id);
284         ip_tunnel_del(itn, netdev_priv(dev));
285 }
286
287 /* Do least required initialization, rest of init is done in tunnel_init call */
288 void rpl_ip_tunnel_setup(struct net_device *dev, int net_id)
289 {
290         struct ip_tunnel *tunnel = netdev_priv(dev);
291
292         tunnel->ip_tnl_net_id = net_id;
293 }
294
295 int rpl_ip_tunnel_get_iflink(const struct net_device *dev)
296 {
297         struct ip_tunnel *tunnel = netdev_priv(dev);
298
299         return tunnel->parms.link;
300 }
301
302 struct net *rpl_ip_tunnel_get_link_net(const struct net_device *dev)
303 {
304         struct ip_tunnel *tunnel = netdev_priv(dev);
305
306         return tunnel->net;
307 }
308
309 #endif