Skip to content

Commit

Permalink
lwtunnel: support dst output redirect function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Roopa Prabhu authored and David S. Miller committed Jul 21, 2015
1 parent 19e42e4 commit ffce419
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
12 changes: 12 additions & 0 deletions include/net/lwtunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 */
56 changes: 56 additions & 0 deletions net/core/lwtunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);

0 comments on commit ffce419

Please sign in to comment.