aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/lwtunnel.c
diff options
context:
space:
mode:
authorRoopa Prabhu <roopa@cumulusnetworks.com>2015-07-21 04:43:49 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-21 13:39:04 -0400
commitffce41962ef64b8e685e5b621caf24bf381addd9 (patch)
treea731e4ae211389d6ab5f722177379975a918b54f /net/core/lwtunnel.c
parent19e42e45150672124b6a4341e2bc7982d247f0ac (diff)
lwtunnel: support dst output redirect function
This patch introduces lwtunnel_output function to call corresponding lwtunnels output function to xmit the packet. It adds two variants lwtunnel_output and lwtunnel_output6 for ipv4 and ipv6 respectively today. But this is subject to change when lwtstate will reside in dst or dst_metadata (as per upstream discussions). Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/lwtunnel.c')
-rw-r--r--net/core/lwtunnel.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index d7ae3a235b4b..bb58826c708d 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -25,6 +25,7 @@
25 25
26#include <net/lwtunnel.h> 26#include <net/lwtunnel.h>
27#include <net/rtnetlink.h> 27#include <net/rtnetlink.h>
28#include <net/ip6_fib.h>
28 29
29struct lwtunnel_state *lwtunnel_state_alloc(int encap_len) 30struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
30{ 31{
@@ -177,3 +178,58 @@ int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
177 return ret; 178 return ret;
178} 179}
179EXPORT_SYMBOL(lwtunnel_cmp_encap); 180EXPORT_SYMBOL(lwtunnel_cmp_encap);
181
182int __lwtunnel_output(struct sock *sk, struct sk_buff *skb,
183 struct lwtunnel_state *lwtstate)
184{
185 const struct lwtunnel_encap_ops *ops;
186 int ret = -EINVAL;
187
188 if (!lwtstate)
189 goto drop;
190
191 if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
192 lwtstate->type > LWTUNNEL_ENCAP_MAX)
193 return 0;
194
195 ret = -EOPNOTSUPP;
196 rcu_read_lock();
197 ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
198 if (likely(ops && ops->output))
199 ret = ops->output(sk, skb);
200 rcu_read_unlock();
201
202 if (ret == -EOPNOTSUPP)
203 goto drop;
204
205 return ret;
206
207drop:
208 kfree(skb);
209
210 return ret;
211}
212
213int lwtunnel_output6(struct sock *sk, struct sk_buff *skb)
214{
215 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
216 struct lwtunnel_state *lwtstate = NULL;
217
218 if (rt)
219 lwtstate = rt->rt6i_lwtstate;
220
221 return __lwtunnel_output(sk, skb, lwtstate);
222}
223EXPORT_SYMBOL(lwtunnel_output6);
224
225int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
226{
227 struct rtable *rt = (struct rtable *)skb_dst(skb);
228 struct lwtunnel_state *lwtstate = NULL;
229
230 if (rt)
231 lwtstate = rt->rt_lwtstate;
232
233 return __lwtunnel_output(sk, skb, lwtstate);
234}
235EXPORT_SYMBOL(lwtunnel_output);