diff options
author | Roopa Prabhu <roopa@cumulusnetworks.com> | 2015-07-21 04:43:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-21 13:39:04 -0400 |
commit | ffce41962ef64b8e685e5b621caf24bf381addd9 (patch) | |
tree | a731e4ae211389d6ab5f722177379975a918b54f /net/core/lwtunnel.c | |
parent | 19e42e45150672124b6a4341e2bc7982d247f0ac (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.c | 56 |
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 | ||
29 | struct lwtunnel_state *lwtunnel_state_alloc(int encap_len) | 30 | struct 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 | } |
179 | EXPORT_SYMBOL(lwtunnel_cmp_encap); | 180 | EXPORT_SYMBOL(lwtunnel_cmp_encap); |
181 | |||
182 | int __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 | |||
207 | drop: | ||
208 | kfree(skb); | ||
209 | |||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | int 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 | } | ||
223 | EXPORT_SYMBOL(lwtunnel_output6); | ||
224 | |||
225 | int 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 | } | ||
235 | EXPORT_SYMBOL(lwtunnel_output); | ||