datapath: Add support for lwtunnel
[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(rt).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)
141 {
142         struct ip_tunnel *tunnel = netdev_priv(dev);
143         int t_hlen = tunnel->hlen + sizeof(struct iphdr);
144
145         if (new_mtu < 68 ||
146             new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
147                 return -EINVAL;
148         dev->mtu = new_mtu;
149         return 0;
150 }
151
152 static void ip_tunnel_dev_free(struct net_device *dev)
153 {
154 #ifdef HAVE_DEV_TSTATS
155         free_percpu(dev->tstats);
156 #endif
157         free_netdev(dev);
158 }
159
160 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
161 void rpl_ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
162 #else
163 void rpl_ip_tunnel_dellink(struct net_device *dev)
164 #endif
165 {
166         struct ip_tunnel *tunnel = netdev_priv(dev);
167         struct ip_tunnel_net *itn;
168
169         itn = net_generic(tunnel->net, tunnel->ip_tnl_net_id);
170
171         ip_tunnel_del(itn, netdev_priv(dev));
172 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
173         unregister_netdevice_queue(dev, head);
174 #endif
175 }
176
177 int rpl_ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
178                                   struct rtnl_link_ops *ops, char *devname)
179 {
180         struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
181
182         itn->collect_md_tun = NULL;
183         itn->rtnl_ops = ops;
184         return 0;
185 }
186
187 static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
188                               struct rtnl_link_ops *ops)
189 {
190         struct ip_tunnel *t;
191
192         t = rtnl_dereference(itn->collect_md_tun);
193         if (!t)
194                 return;
195         unregister_netdevice_queue(t->dev, head);
196 }
197
198 void rpl_ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
199 {
200         LIST_HEAD(list);
201
202         rtnl_lock();
203         ip_tunnel_destroy(itn, &list, ops);
204         unregister_netdevice_many(&list);
205         rtnl_unlock();
206 }
207
208 int rpl_ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
209                       struct ip_tunnel_parm *p)
210 {
211         struct ip_tunnel *nt;
212         struct net *net = dev_net(dev);
213         struct ip_tunnel_net *itn;
214         int mtu;
215         int err;
216
217         nt = netdev_priv(dev);
218         itn = net_generic(net, nt->ip_tnl_net_id);
219
220         if (nt->collect_md) {
221                 if (rtnl_dereference(itn->collect_md_tun))
222                         return -EEXIST;
223         } else {
224                 return -EOPNOTSUPP;
225         }
226
227         nt->net = net;
228         nt->parms = *p;
229         err = register_netdevice(dev);
230         if (err)
231                 goto out;
232
233         if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
234                 eth_hw_addr_random(dev);
235
236         mtu = ip_tunnel_bind_dev(dev);
237         if (!tb[IFLA_MTU])
238                 dev->mtu = mtu;
239
240         ip_tunnel_add(itn, nt);
241 out:
242         return err;
243 }
244
245 int rpl_ip_tunnel_init(struct net_device *dev)
246 {
247         struct ip_tunnel *tunnel = netdev_priv(dev);
248         struct iphdr *iph = &tunnel->parms.iph;
249
250         dev->destructor = ip_tunnel_dev_free;
251 #ifdef HAVE_DEV_TSTATS
252         dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
253         if (!dev->tstats)
254                 return -ENOMEM;
255 #endif
256         tunnel->dev = dev;
257         tunnel->net = dev_net(dev);
258         strcpy(tunnel->parms.name, dev->name);
259         iph->version            = 4;
260         iph->ihl                = 5;
261
262         if (tunnel->collect_md)
263                 dev->features |= NETIF_F_NETNS_LOCAL;
264
265         return 0;
266 }
267
268 void rpl_ip_tunnel_uninit(struct net_device *dev)
269 {
270         struct ip_tunnel *tunnel = netdev_priv(dev);
271         struct net *net = tunnel->net;
272         struct ip_tunnel_net *itn;
273
274         itn = net_generic(net, tunnel->ip_tnl_net_id);
275         ip_tunnel_del(itn, netdev_priv(dev));
276 }
277
278 /* Do least required initialization, rest of init is done in tunnel_init call */
279 void rpl_ip_tunnel_setup(struct net_device *dev, int net_id)
280 {
281         struct ip_tunnel *tunnel = netdev_priv(dev);
282
283         tunnel->ip_tnl_net_id = net_id;
284 }
285 #endif