2 * lwtunnel Infrastructure for light weight tunnels like mpls
4 * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com>
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.
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>
23 #include <linux/init.h>
24 #include <linux/err.h>
26 #include <net/lwtunnel.h>
27 #include <net/rtnetlink.h>
29 struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
31 struct lwtunnel_state *lws;
33 lws = kzalloc(sizeof(*lws) + encap_len, GFP_ATOMIC);
37 EXPORT_SYMBOL(lwtunnel_state_alloc);
39 const struct lwtunnel_encap_ops __rcu *
40 lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly;
42 int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops,
45 if (num > LWTUNNEL_ENCAP_MAX)
48 return !cmpxchg((const struct lwtunnel_encap_ops **)
52 EXPORT_SYMBOL(lwtunnel_encap_add_ops);
54 int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *ops,
55 unsigned int encap_type)
59 if (encap_type == LWTUNNEL_ENCAP_NONE ||
60 encap_type > LWTUNNEL_ENCAP_MAX)
63 ret = (cmpxchg((const struct lwtunnel_encap_ops **)
64 &lwtun_encaps[encap_type],
65 ops, NULL) == ops) ? 0 : -1;
71 EXPORT_SYMBOL(lwtunnel_encap_del_ops);
73 int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
74 struct nlattr *encap, struct lwtunnel_state **lws)
76 const struct lwtunnel_encap_ops *ops;
79 if (encap_type == LWTUNNEL_ENCAP_NONE ||
80 encap_type > LWTUNNEL_ENCAP_MAX)
85 ops = rcu_dereference(lwtun_encaps[encap_type]);
86 if (likely(ops && ops->build_state))
87 ret = ops->build_state(dev, encap, lws);
92 EXPORT_SYMBOL(lwtunnel_build_state);
94 int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
96 const struct lwtunnel_encap_ops *ops;
103 if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
104 lwtstate->type > LWTUNNEL_ENCAP_MAX)
108 nest = nla_nest_start(skb, RTA_ENCAP);
110 ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
111 if (likely(ops && ops->fill_encap))
112 ret = ops->fill_encap(skb, lwtstate);
116 goto nla_put_failure;
117 nla_nest_end(skb, nest);
118 ret = nla_put_u16(skb, RTA_ENCAP_TYPE, lwtstate->type);
120 goto nla_put_failure;
125 nla_nest_cancel(skb, nest);
127 return (ret == -EOPNOTSUPP ? 0 : ret);
129 EXPORT_SYMBOL(lwtunnel_fill_encap);
131 int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate)
133 const struct lwtunnel_encap_ops *ops;
139 if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
140 lwtstate->type > LWTUNNEL_ENCAP_MAX)
144 ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
145 if (likely(ops && ops->get_encap_size))
146 ret = nla_total_size(ops->get_encap_size(lwtstate));
151 EXPORT_SYMBOL(lwtunnel_get_encap_size);
153 int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
155 const struct lwtunnel_encap_ops *ops;
164 if (a->type != b->type)
167 if (a->type == LWTUNNEL_ENCAP_NONE ||
168 a->type > LWTUNNEL_ENCAP_MAX)
172 ops = rcu_dereference(lwtun_encaps[a->type]);
173 if (likely(ops && ops->cmp_encap))
174 ret = ops->cmp_encap(a, b);
179 EXPORT_SYMBOL(lwtunnel_cmp_encap);