Skip to content

Commit a4d6de3

Browse files
Vlad Yasevichpopcornmix
Vlad Yasevich
authored andcommitted
net: Correctly set segment mac_len in skb_segment().
[ Upstream commit fcdfe3a ] When performing segmentation, the mac_len value is copied right out of the original skb. However, this value is not always set correctly (like when the packet is VLAN-tagged) and we'll end up copying a bad value. One way to demonstrate this is to configure a VM which tags packets internally and turn off VLAN acceleration on the forwarding bridge port. The packets show up corrupt like this: 16:18:24.985548 52:54:00:ab:be:25 > 52:54:00:26:ce:a3, ethertype 802.1Q (0x8100), length 1518: vlan 100, p 0, ethertype 0x05e0, 0x0000: 8cdb 1c7c 8cdb 0064 4006 b59d 0a00 6402 ...|[email protected]. 0x0010: 0a00 6401 9e0d b441 0a5e 64ec 0330 14fa ..d....A.^d..0.. 0x0020: 29e3 01c9 f871 0000 0101 080a 000a e833)....q.........3 0x0030: 000f 8c75 6e65 7470 6572 6600 6e65 7470 ...unetperf.netp 0x0040: 6572 6600 6e65 7470 6572 6600 6e65 7470 erf.netperf.netp 0x0050: 6572 6600 6e65 7470 6572 6600 6e65 7470 erf.netperf.netp 0x0060: 6572 6600 6e65 7470 6572 6600 6e65 7470 erf.netperf.netp ... This also leads to awful throughput as GSO packets are dropped and cause retransmissions. The solution is to set the mac_len using the values already available in then new skb. We've already adjusted all of the header offset, so we might as well correctly figure out the mac_len using skb_reset_mac_len(). After this change, packets are segmented correctly and performance is restored. CC: Eric Dumazet <[email protected]> Signed-off-by: Vlad Yasevich <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 11e2c88 commit a4d6de3

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

net/core/skbuff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2831,7 +2831,6 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
28312831
tail = nskb;
28322832

28332833
__copy_skb_header(nskb, head_skb);
2834-
nskb->mac_len = head_skb->mac_len;
28352834

28362835
/* nskb and skb might have different headroom */
28372836
if (nskb->ip_summed == CHECKSUM_PARTIAL)
@@ -2841,6 +2840,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
28412840
skb_set_network_header(nskb, head_skb->mac_len);
28422841
nskb->transport_header = (nskb->network_header +
28432842
skb_network_header_len(head_skb));
2843+
skb_reset_mac_len(nskb);
28442844

28452845
skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
28462846
nskb->data - tnl_hlen,

0 commit comments

Comments
 (0)