forked from mirrors/linux
		
	gue: TX support for using remote checksum offload option
Add if_tunnel flag TUNNEL_ENCAP_FLAG_REMCSUM to configure remote checksum offload on an IP tunnel. Add logic in gue_build_header to insert remote checksum offload option. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									c1aa8347e7
								
							
						
					
					
						commit
						b17f709a24
					
				
					 3 changed files with 46 additions and 4 deletions
				
			
		| 
						 | 
					@ -20,7 +20,19 @@ static size_t fou_encap_hlen(struct ip_tunnel_encap *e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
 | 
					static size_t gue_encap_hlen(struct ip_tunnel_encap *e)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return sizeof(struct udphdr) + sizeof(struct guehdr);
 | 
						size_t len;
 | 
				
			||||||
 | 
						bool need_priv = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len = sizeof(struct udphdr) + sizeof(struct guehdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) {
 | 
				
			||||||
 | 
							len += GUE_PLEN_REMCSUM;
 | 
				
			||||||
 | 
							need_priv = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len += need_priv ? GUE_LEN_PRIV : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,7 @@ enum tunnel_encap_types {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TUNNEL_ENCAP_FLAG_CSUM		(1<<0)
 | 
					#define TUNNEL_ENCAP_FLAG_CSUM		(1<<0)
 | 
				
			||||||
#define TUNNEL_ENCAP_FLAG_CSUM6		(1<<1)
 | 
					#define TUNNEL_ENCAP_FLAG_CSUM6		(1<<1)
 | 
				
			||||||
 | 
					#define TUNNEL_ENCAP_FLAG_REMCSUM	(1<<2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SIT-mode i_flags */
 | 
					/* SIT-mode i_flags */
 | 
				
			||||||
#define	SIT_ISATAP	0x0001
 | 
					#define	SIT_ISATAP	0x0001
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -562,11 +562,19 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 | 
				
			||||||
	bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
 | 
						bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM);
 | 
				
			||||||
	int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
 | 
						int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
 | 
				
			||||||
	struct guehdr *guehdr;
 | 
						struct guehdr *guehdr;
 | 
				
			||||||
	size_t optlen = 0;
 | 
						size_t hdrlen, optlen = 0;
 | 
				
			||||||
	__be16 sport;
 | 
						__be16 sport;
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
	bool need_priv = false;
 | 
						bool need_priv = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) &&
 | 
				
			||||||
 | 
						    skb->ip_summed == CHECKSUM_PARTIAL) {
 | 
				
			||||||
 | 
							csum = false;
 | 
				
			||||||
 | 
							optlen += GUE_PLEN_REMCSUM;
 | 
				
			||||||
 | 
							type |= SKB_GSO_TUNNEL_REMCSUM;
 | 
				
			||||||
 | 
							need_priv = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	optlen += need_priv ? GUE_LEN_PRIV : 0;
 | 
						optlen += need_priv ? GUE_LEN_PRIV : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb = iptunnel_handle_offloads(skb, csum, type);
 | 
						skb = iptunnel_handle_offloads(skb, csum, type);
 | 
				
			||||||
| 
						 | 
					@ -578,7 +586,9 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 | 
				
			||||||
	sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
 | 
						sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
 | 
				
			||||||
					       skb, 0, 0, false);
 | 
										       skb, 0, 0, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	skb_push(skb, sizeof(struct guehdr) + optlen);
 | 
						hdrlen = sizeof(struct guehdr) + optlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						skb_push(skb, hdrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	guehdr = (struct guehdr *)skb->data;
 | 
						guehdr = (struct guehdr *)skb->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -597,7 +607,26 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 | 
				
			||||||
		*flags = 0;
 | 
							*flags = 0;
 | 
				
			||||||
		data += GUE_LEN_PRIV;
 | 
							data += GUE_LEN_PRIV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Add private flags */
 | 
							if (type & SKB_GSO_TUNNEL_REMCSUM) {
 | 
				
			||||||
 | 
								u16 csum_start = skb_checksum_start_offset(skb);
 | 
				
			||||||
 | 
								__be16 *pd = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (csum_start < hdrlen)
 | 
				
			||||||
 | 
									return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								csum_start -= hdrlen;
 | 
				
			||||||
 | 
								pd[0] = htons(csum_start);
 | 
				
			||||||
 | 
								pd[1] = htons(csum_start + skb->csum_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!skb_is_gso(skb)) {
 | 
				
			||||||
 | 
									skb->ip_summed = CHECKSUM_NONE;
 | 
				
			||||||
 | 
									skb->encapsulation = 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								*flags |= GUE_PFLAG_REMCSUM;
 | 
				
			||||||
 | 
								data += GUE_PLEN_REMCSUM;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fou_build_udp(skb, e, fl4, protocol, sport);
 | 
						fou_build_udp(skb, e, fl4, protocol, sport);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue