forked from Minki/linux
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>
This commit is contained in:
parent
19e42e4515
commit
ffce41962e
@ -69,6 +69,8 @@ int lwtunnel_fill_encap(struct sk_buff *skb,
|
||||
int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
|
||||
struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
|
||||
int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b);
|
||||
int lwtunnel_output(struct sock *sk, struct sk_buff *skb);
|
||||
int lwtunnel_output6(struct sock *sk, struct sk_buff *skb);
|
||||
|
||||
#else
|
||||
|
||||
@ -127,6 +129,16 @@ static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lwtunnel_output(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int lwtunnel_output6(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __NET_LWTUNNEL_H */
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <net/lwtunnel.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/ip6_fib.h>
|
||||
|
||||
struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
|
||||
{
|
||||
@ -177,3 +178,58 @@ int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_cmp_encap);
|
||||
|
||||
int __lwtunnel_output(struct sock *sk, 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->output))
|
||||
ret = ops->output(sk, skb);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (ret == -EOPNOTSUPP)
|
||||
goto drop;
|
||||
|
||||
return ret;
|
||||
|
||||
drop:
|
||||
kfree(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lwtunnel_output6(struct sock *sk, 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_output(sk, skb, lwtstate);
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_output6);
|
||||
|
||||
int lwtunnel_output(struct sock *sk, 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_output(sk, skb, lwtstate);
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_output);
|
||||
|
Loading…
Reference in New Issue
Block a user