forked from mirrors/linux
		
	net/packet: fix packet drop as of virtio gso
When we use raw socket as the vhost backend, a packet from virito with
gso offloading information, cannot be sent out in later validaton at
xmit path, as we did not set correct skb->protocol which is further used
for looking up the gso function.
To fix this, we set this field according to virito hdr information.
Fixes: e858fae2b0 ("virtio_net: use common code for virtio_net_hdr and skb GSO conversion")
Signed-off-by: Jianfeng Tan <jianfeng.tan@linux.alibaba.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									ca89319483
								
							
						
					
					
						commit
						9d2f67e43b
					
				
					 2 changed files with 25 additions and 4 deletions
				
			
		|  | @ -5,6 +5,24 @@ | |||
| #include <linux/if_vlan.h> | ||||
| #include <uapi/linux/virtio_net.h> | ||||
| 
 | ||||
| static inline int virtio_net_hdr_set_proto(struct sk_buff *skb, | ||||
| 					   const struct virtio_net_hdr *hdr) | ||||
| { | ||||
| 	switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | ||||
| 	case VIRTIO_NET_HDR_GSO_TCPV4: | ||||
| 	case VIRTIO_NET_HDR_GSO_UDP: | ||||
| 		skb->protocol = cpu_to_be16(ETH_P_IP); | ||||
| 		break; | ||||
| 	case VIRTIO_NET_HDR_GSO_TCPV6: | ||||
| 		skb->protocol = cpu_to_be16(ETH_P_IPV6); | ||||
| 		break; | ||||
| 	default: | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, | ||||
| 					const struct virtio_net_hdr *hdr, | ||||
| 					bool little_endian) | ||||
|  |  | |||
|  | @ -2715,10 +2715,12 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (po->has_vnet_hdr && virtio_net_hdr_to_skb(skb, vnet_hdr, | ||||
| 							      vio_le())) { | ||||
| 			tp_len = -EINVAL; | ||||
| 			goto tpacket_error; | ||||
| 		if (po->has_vnet_hdr) { | ||||
| 			if (virtio_net_hdr_to_skb(skb, vnet_hdr, vio_le())) { | ||||
| 				tp_len = -EINVAL; | ||||
| 				goto tpacket_error; | ||||
| 			} | ||||
| 			virtio_net_hdr_set_proto(skb, vnet_hdr); | ||||
| 		} | ||||
| 
 | ||||
| 		skb->destructor = tpacket_destruct_skb; | ||||
|  | @ -2915,6 +2917,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 		if (err) | ||||
| 			goto out_free; | ||||
| 		len += sizeof(vnet_hdr); | ||||
| 		virtio_net_hdr_set_proto(skb, &vnet_hdr); | ||||
| 	} | ||||
| 
 | ||||
| 	skb_probe_transport_header(skb, reserve); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Jianfeng Tan
						Jianfeng Tan