mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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
					
				
					 2 changed files with 68 additions and 0 deletions
				
			
		| 
						 | 
					@ -69,6 +69,8 @@ int lwtunnel_fill_encap(struct sk_buff *skb,
 | 
				
			||||||
int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
 | 
					int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);
 | 
				
			||||||
struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
 | 
					struct lwtunnel_state *lwtunnel_state_alloc(int hdr_len);
 | 
				
			||||||
int lwtunnel_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b);
 | 
					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
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,6 +129,16 @@ static inline int lwtunnel_cmp_encap(struct lwtunnel_state *a,
 | 
				
			||||||
	return 0;
 | 
						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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __NET_LWTUNNEL_H */
 | 
					#endif /* __NET_LWTUNNEL_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <net/lwtunnel.h>
 | 
					#include <net/lwtunnel.h>
 | 
				
			||||||
#include <net/rtnetlink.h>
 | 
					#include <net/rtnetlink.h>
 | 
				
			||||||
 | 
					#include <net/ip6_fib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lwtunnel_state *lwtunnel_state_alloc(int encap_len)
 | 
					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;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(lwtunnel_cmp_encap);
 | 
					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 a new issue