forked from mirrors/linux
		
	net: Add a xfrm validate function to validate_xmit_skb
When we do IPsec offloading, we need a fallback for packets that were targeted to be IPsec offloaded but rerouted to a device that does not support IPsec offload. For that we add a function that checks the offloading features of the sending device and and flags the requirement of a fallback before it calls the IPsec output function. The IPsec output function adds the IPsec trailer and does encryption if needed. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:
		
							parent
							
								
									b3859c8ebf
								
							
						
					
					
						commit
						f6e27114a6
					
				
					 3 changed files with 38 additions and 0 deletions
				
			
		| 
						 | 
					@ -1862,6 +1862,7 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_XFRM_OFFLOAD
 | 
					#ifdef CONFIG_XFRM_OFFLOAD
 | 
				
			||||||
void __net_init xfrm_dev_init(void);
 | 
					void __net_init xfrm_dev_init(void);
 | 
				
			||||||
 | 
					int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
 | 
				
			||||||
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 | 
					int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 | 
				
			||||||
		       struct xfrm_user_offload *xuo);
 | 
							       struct xfrm_user_offload *xuo);
 | 
				
			||||||
bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
 | 
					bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
 | 
				
			||||||
| 
						 | 
					@ -1890,6 +1891,11 @@ static inline void __net_init xfrm_dev_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo)
 | 
					static inline int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, struct xfrm_user_offload *xuo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2972,6 +2972,9 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device
 | 
				
			||||||
		    __skb_linearize(skb))
 | 
							    __skb_linearize(skb))
 | 
				
			||||||
			goto out_kfree_skb;
 | 
								goto out_kfree_skb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (validate_xmit_xfrm(skb, features))
 | 
				
			||||||
 | 
								goto out_kfree_skb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If packet is not checksummed and device does not
 | 
							/* If packet is not checksummed and device does not
 | 
				
			||||||
		 * support checksumming for this protocol, complete
 | 
							 * support checksumming for this protocol, complete
 | 
				
			||||||
		 * checksumming here.
 | 
							 * checksumming here.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,35 @@
 | 
				
			||||||
#include <net/xfrm.h>
 | 
					#include <net/xfrm.h>
 | 
				
			||||||
#include <linux/notifier.h>
 | 
					#include <linux/notifier.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct xfrm_state *x;
 | 
				
			||||||
 | 
						struct xfrm_offload *xo = xfrm_offload(skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (skb_is_gso(skb))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xo) {
 | 
				
			||||||
 | 
							x = skb->sp->xvec[skb->sp->len - 1];
 | 
				
			||||||
 | 
							if (xo->flags & XFRM_GRO || x->xso.flags & XFRM_OFFLOAD_INBOUND)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							x->outer_mode->xmit(x, skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = x->type_offload->xmit(x, skb, features);
 | 
				
			||||||
 | 
							if (err) {
 | 
				
			||||||
 | 
								XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR);
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							skb_push(skb, skb->data - skb_mac_header(skb));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(validate_xmit_xfrm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 | 
					int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 | 
				
			||||||
		       struct xfrm_user_offload *xuo)
 | 
							       struct xfrm_user_offload *xuo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue