packet: allow to transmit +4 byte in TX_RING slot for VLAN case
Commit57f89bfa21("network: Allow af_packet to transmit +4 bytes for VLAN packets.") added the possibility for non-mmaped frames to send extra 4 byte for VLAN header so the MTU increases from 1500 to 1504 byte, for example. Commitcbd89acb9e("af_packet: fix for sending VLAN frames via packet_mmap") attempted to fix that for the mmap part but was reverted as it caused regressions while using eth_type_trans() on output path. Lets just act analogous to57f89bfa21and add a similar logic to TX_RING. We presume size_max as overcharged with +4 bytes and later on after skb has been built by tpacket_fill_skb() check for ETH_P_8021Q header on packets larger than normal MTU. Can be easily reproduced with a slightly modified trafgen in mmap(2) mode, test cases: { fill(0xff, 12) const16(0x8100) fill(0xff, <1504|1505>) } { fill(0xff, 12) const16(0x0806) fill(0xff, <1500|1501>) } Note that we need to do the test right after tpacket_fill_skb() as sockets can have PACKET_LOSS set where we would not fail but instead just continue to traverse the ring. Reported-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Cc: Ben Greear <greearb@candelatech.com> Cc: Phil Sutter <phil@nwl.cc> Tested-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								07cb1c175e
							
						
					
				
			
			
				commit
				
					
						52f1454f62
					
				
			
		
					 1 changed files with 13 additions and 3 deletions
				
			
		|  | @ -2257,8 +2257,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | ||||||
| 	if (unlikely(!(dev->flags & IFF_UP))) | 	if (unlikely(!(dev->flags & IFF_UP))) | ||||||
| 		goto out_put; | 		goto out_put; | ||||||
| 
 | 
 | ||||||
| 	reserve = dev->hard_header_len; | 	reserve = dev->hard_header_len + VLAN_HLEN; | ||||||
| 
 |  | ||||||
| 	size_max = po->tx_ring.frame_size | 	size_max = po->tx_ring.frame_size | ||||||
| 		- (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 		- (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | ||||||
| 
 | 
 | ||||||
|  | @ -2286,7 +2285,18 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | ||||||
| 
 | 
 | ||||||
| 		tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 		tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | ||||||
| 					  addr, hlen); | 					  addr, hlen); | ||||||
|  | 		if (tp_len > dev->mtu + dev->hard_header_len) { | ||||||
|  | 			struct ethhdr *ehdr; | ||||||
|  | 			/* Earlier code assumed this would be a VLAN pkt,
 | ||||||
|  | 			 * double-check this now that we have the actual | ||||||
|  | 			 * packet in hand. | ||||||
|  | 			 */ | ||||||
| 
 | 
 | ||||||
|  | 			skb_reset_mac_header(skb); | ||||||
|  | 			ehdr = eth_hdr(skb); | ||||||
|  | 			if (ehdr->h_proto != htons(ETH_P_8021Q)) | ||||||
|  | 				tp_len = -EMSGSIZE; | ||||||
|  | 		} | ||||||
| 		if (unlikely(tp_len < 0)) { | 		if (unlikely(tp_len < 0)) { | ||||||
| 			if (po->tp_loss) { | 			if (po->tp_loss) { | ||||||
| 				__packet_set_status(po, ph, | 				__packet_set_status(po, ph, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Daniel Borkmann
				Daniel Borkmann