aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/lwtunnel.c
diff options
context:
space:
mode:
authorTom Herbert <tom@herbertland.com>2015-08-17 13:42:24 -0700
committerDavid S. Miller <davem@davemloft.net>2015-08-17 21:33:05 -0700
commit2536862311d2276454ddef9dc36d6551a4b400fd (patch)
tree7be7caf4f95bdd2c50749dc2d42319acbc250030 /net/core/lwtunnel.c
parentenic: Fix sparse warning in vnic_devcmd_init(). (diff)
downloadlinux-dev-2536862311d2276454ddef9dc36d6551a4b400fd.tar.xz
linux-dev-2536862311d2276454ddef9dc36d6551a4b400fd.zip
lwt: Add support to redirect dst.input
This patch adds the capability to redirect dst input in the same way that dst output is redirected by LWT. Also, save the original dst.input and and dst.out when setting up lwtunnel redirection. These can be called by the client as a pass- through. Signed-off-by: Tom Herbert <tom@herbertland.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/lwtunnel.c')
-rw-r--r--net/core/lwtunnel.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 5d6d8e3d450a..3331585174d9 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -241,3 +241,58 @@ int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
return __lwtunnel_output(sk, skb, lwtstate);
}
EXPORT_SYMBOL(lwtunnel_output);
+
+int __lwtunnel_input(struct sk_buff *skb,
+ struct lwtunnel_state *lwtstate)
+{
+ const struct lwtunnel_encap_ops *ops;
+ int ret = -EINVAL;
+
+ if (!lwtstate)
+ goto drop;
+
+ if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
+ lwtstate->type > LWTUNNEL_ENCAP_MAX)
+ return 0;
+
+ ret = -EOPNOTSUPP;
+ rcu_read_lock();
+ ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
+ if (likely(ops && ops->input))
+ ret = ops->input(skb);
+ rcu_read_unlock();
+
+ if (ret == -EOPNOTSUPP)
+ goto drop;
+
+ return ret;
+
+drop:
+ kfree_skb(skb);
+
+ return ret;
+}
+
+int lwtunnel_input6(struct sk_buff *skb)
+{
+ struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
+ struct lwtunnel_state *lwtstate = NULL;
+
+ if (rt)
+ lwtstate = rt->rt6i_lwtstate;
+
+ return __lwtunnel_input(skb, lwtstate);
+}
+EXPORT_SYMBOL(lwtunnel_input6);
+
+int lwtunnel_input(struct sk_buff *skb)
+{
+ struct rtable *rt = (struct rtable *)skb_dst(skb);
+ struct lwtunnel_state *lwtstate = NULL;
+
+ if (rt)
+ lwtstate = rt->rt_lwtstate;
+
+ return __lwtunnel_input(skb, lwtstate);
+}
+EXPORT_SYMBOL(lwtunnel_input);