Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[cascardo/linux.git] / net / core / lwtunnel.c
1 /*
2  * lwtunnel     Infrastructure for light weight tunnels like mpls
3  *
4  * Authors:     Roopa Prabhu, <roopa@cumulusnetworks.com>
5  *
6  *              This program is free software; you can redistribute it and/or
7  *              modify it under the terms of the GNU General Public License
8  *              as published by the Free Software Foundation; either version
9  *              2 of the License, or (at your option) any later version.
10  *
11  */
12
13 #include <linux/capability.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/kernel.h>
17 #include <linux/slab.h>
18 #include <linux/uaccess.h>
19 #include <linux/skbuff.h>
20 #include <linux/netdevice.h>
21 #include <linux/lwtunnel.h>
22 #include <linux/in.h>
23 #include <linux/init.h>
24 #include <linux/err.h>
25
26 #include <net/lwtunnel.h>
27 #include <net/rtnetlink.h>
28 #include <net/ip6_fib.h>
29
30 #ifdef CONFIG_MODULES
31
32 static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type)
33 {
34         /* Only lwt encaps implemented without using an interface for
35          * the encap need to return a string here.
36          */
37         switch (encap_type) {
38         case LWTUNNEL_ENCAP_MPLS:
39                 return "MPLS";
40         case LWTUNNEL_ENCAP_ILA:
41                 return "ILA";
42         case LWTUNNEL_ENCAP_IP6:
43         case LWTUNNEL_ENCAP_IP:
44         case LWTUNNEL_ENCAP_NONE:
45         case __LWTUNNEL_ENCAP_MAX:
46                 /* should not have got here */
47                 WARN_ON(1);
48                 break;
49         }
50         return NULL;
51 }
52
53 #endif /* CONFIG_MODULES */
54
55 struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
56 {
57         struct lwtunnel_state *lws;
58
59         lws = kzalloc(sizeof(*lws) + encap_len, GFP_ATOMIC);
60
61         return lws;
62 }
63 EXPORT_SYMBOL(lwtunnel_state_alloc);
64
65 static const struct lwtunnel_encap_ops __rcu *
66                 lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly;
67
68 int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops,
69                            unsigned int num)
70 {
71         if (num > LWTUNNEL_ENCAP_MAX)
72                 return -ERANGE;
73
74         return !cmpxchg((const struct lwtunnel_encap_ops **)
75                         &lwtun_encaps[num],
76                         NULL, ops) ? 0 : -1;
77 }
78 EXPORT_SYMBOL(lwtunnel_encap_add_ops);
79
80 int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
81                            unsigned int encap_type)
82 {
83         int ret;
84
85         if (encap_type == LWTUNNEL_ENCAP_NONE ||
86             encap_type > LWTUNNEL_ENCAP_MAX)
87                 return -ERANGE;
88
89         ret = (cmpxchg((const struct lwtunnel_encap_ops **)
90                        &lwtun_encaps[encap_type],
91                        ops, NULL) == ops) ? 0 : -1;
92
93         synchronize_net();
94
95         return ret;
96 }
97 EXPORT_SYMBOL(lwtunnel_encap_del_ops);
98
99 int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
100                          struct nlattr *encap, unsigned int family,
101                          const void *cfg, struct lwtunnel_state **lws)
102 {
103         const struct lwtunnel_encap_ops *ops;
104         int ret = -EINVAL;
105
106         if (encap_type == LWTUNNEL_ENCAP_NONE ||
107             encap_type > LWTUNNEL_ENCAP_MAX)
108                 return ret;
109
110         ret = -EOPNOTSUPP;
111         rcu_read_lock();
112         ops = rcu_dereference(lwtun_encaps[encap_type]);
113 #ifdef CONFIG_MODULES
114         if (!ops) {
115                 const char *encap_type_str = lwtunnel_encap_str(encap_type);
116
117                 if (encap_type_str) {
118                         rcu_read_unlock();
119                         request_module("rtnl-lwt-%s", encap_type_str);
120                         rcu_read_lock();
121                         ops = rcu_dereference(lwtun_encaps[encap_type]);
122                 }
123         }
124 #endif
125         if (likely(ops && ops->build_state))
126                 ret = ops->build_state(dev, encap, family, cfg, lws);
127         rcu_read_unlock();
128
129         return ret;
130 }
131 EXPORT_SYMBOL(lwtunnel_build_state);
132
133 int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
134 {
135         const struct lwtunnel_encap_ops *ops;
136         struct nlattr *nest;
137         int ret = -EINVAL;
138
139         if (!lwtstate)
140                 return 0;
141
142         if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
143             lwtstate->type > LWTUNNEL_ENCAP_MAX)
144                 return 0;
145
146         ret = -EOPNOTSUPP;
147         nest = nla_nest_start(skb, RTA_ENCAP);
148         rcu_read_lock();
149         ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
150         if (likely(ops && ops->fill_encap))
151                 ret = ops->fill_encap(skb, lwtstate);
152         rcu_read_unlock();
153
154         if (ret)
155                 goto nla_put_failure;
156         nla_nest_end(skb, nest);
157         ret = nla_put_u16(skb, RTA_ENCAP_TYPE, lwtstate->type);
158         if (ret)
159                 goto nla_put_failure;
160
161         return 0;
162
163 nla_put_failure:
164         nla_nest_cancel(skb, nest);
165
166         return (ret == -EOPNOTSUPP ? 0 : ret);
167 }
168 EXPORT_SYMBOL(lwtunnel_fill_encap);
169
170 int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate)
171 {
172         const struct lwtunnel_encap_ops *ops;
173         int ret = 0;
174
175         if (!lwtstate)
176                 return 0;
177
178         if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
179             lwtstate->type > LWTUNNEL_ENCAP_MAX)
180                 return 0;
181
182         rcu_read_lock();
183         ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
184         if (likely(ops && ops->get_encap_size))
185                 ret = nla_total_size(ops->get_encap_size(lwtstate));
186         rcu_read_unlock();
187
188         return ret;
189 }
190 EXPORT_SYMBOL(lwtunnel_get_encap_size);
191
192 int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
193 {
194         const struct lwtunnel_encap_ops *ops;
195         int ret = 0;
196
197         if (!a && !b)
198                 return 0;
199
200         if (!a || !b)
201                 return 1;
202
203         if (a->type != b->type)
204                 return 1;
205
206         if (a->type == LWTUNNEL_ENCAP_NONE ||
207             a->type > LWTUNNEL_ENCAP_MAX)
208                 return 0;
209
210         rcu_read_lock();
211         ops = rcu_dereference(lwtun_encaps[a->type]);
212         if (likely(ops && ops->cmp_encap))
213                 ret = ops->cmp_encap(a, b);
214         rcu_read_unlock();
215
216         return ret;
217 }
218 EXPORT_SYMBOL(lwtunnel_cmp_encap);
219
220 int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
221 {
222         struct dst_entry *dst = skb_dst(skb);
223         const struct lwtunnel_encap_ops *ops;
224         struct lwtunnel_state *lwtstate;
225         int ret = -EINVAL;
226
227         if (!dst)
228                 goto drop;
229         lwtstate = dst->lwtstate;
230
231         if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
232             lwtstate->type > LWTUNNEL_ENCAP_MAX)
233                 return 0;
234
235         ret = -EOPNOTSUPP;
236         rcu_read_lock();
237         ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
238         if (likely(ops && ops->output))
239                 ret = ops->output(net, sk, skb);
240         rcu_read_unlock();
241
242         if (ret == -EOPNOTSUPP)
243                 goto drop;
244
245         return ret;
246
247 drop:
248         kfree_skb(skb);
249
250         return ret;
251 }
252 EXPORT_SYMBOL(lwtunnel_output);
253
254 int lwtunnel_xmit(struct sk_buff *skb)
255 {
256         struct dst_entry *dst = skb_dst(skb);
257         const struct lwtunnel_encap_ops *ops;
258         struct lwtunnel_state *lwtstate;
259         int ret = -EINVAL;
260
261         if (!dst)
262                 goto drop;
263
264         lwtstate = dst->lwtstate;
265
266         if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
267             lwtstate->type > LWTUNNEL_ENCAP_MAX)
268                 return 0;
269
270         ret = -EOPNOTSUPP;
271         rcu_read_lock();
272         ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
273         if (likely(ops && ops->xmit))
274                 ret = ops->xmit(skb);
275         rcu_read_unlock();
276
277         if (ret == -EOPNOTSUPP)
278                 goto drop;
279
280         return ret;
281
282 drop:
283         kfree_skb(skb);
284
285         return ret;
286 }
287 EXPORT_SYMBOL(lwtunnel_xmit);
288
289 int lwtunnel_input(struct sk_buff *skb)
290 {
291         struct dst_entry *dst = skb_dst(skb);
292         const struct lwtunnel_encap_ops *ops;
293         struct lwtunnel_state *lwtstate;
294         int ret = -EINVAL;
295
296         if (!dst)
297                 goto drop;
298         lwtstate = dst->lwtstate;
299
300         if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
301             lwtstate->type > LWTUNNEL_ENCAP_MAX)
302                 return 0;
303
304         ret = -EOPNOTSUPP;
305         rcu_read_lock();
306         ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
307         if (likely(ops && ops->input))
308                 ret = ops->input(skb);
309         rcu_read_unlock();
310
311         if (ret == -EOPNOTSUPP)
312                 goto drop;
313
314         return ret;
315
316 drop:
317         kfree_skb(skb);
318
319         return ret;
320 }
321 EXPORT_SYMBOL(lwtunnel_input);