diff options
author | Maxime Chevallier <maxime.chevallier@bootlin.com> | 2018-10-05 03:04:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-05 17:52:43 -0400 |
commit | 35f3625c21852ad839f20c91c7d81c4c1101e207 (patch) | |
tree | b6e41c36935045703f589f169f1f6a3554adc272 | |
parent | a688caa34beb2fd2a92f1b6d33e40cde433ba160 (diff) |
net: mvpp2: Extract the correct ethtype from the skb for tx csum offload
When offloading the L3 and L4 csum computation on TX, we need to extract
the l3_proto from the ethtype, independently of the presence of a vlan
tag.
The actual driver uses skb->protocol as-is, resulting in packets with
the wrong L4 checksum being sent when there's a vlan tag in the packet
header and checksum offloading is enabled.
This commit makes use of vlan_protocol_get() to get the correct ethtype
regardless the presence of a vlan tag.
Fixes: 3f518509dedc ("ethernet: Add new driver for Marvell Armada 375 network unit")
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 38cc01beea79..a74002b43b51 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | |||
@@ -1725,7 +1725,7 @@ static void mvpp2_txq_desc_put(struct mvpp2_tx_queue *txq) | |||
1725 | } | 1725 | } |
1726 | 1726 | ||
1727 | /* Set Tx descriptors fields relevant for CSUM calculation */ | 1727 | /* Set Tx descriptors fields relevant for CSUM calculation */ |
1728 | static u32 mvpp2_txq_desc_csum(int l3_offs, int l3_proto, | 1728 | static u32 mvpp2_txq_desc_csum(int l3_offs, __be16 l3_proto, |
1729 | int ip_hdr_len, int l4_proto) | 1729 | int ip_hdr_len, int l4_proto) |
1730 | { | 1730 | { |
1731 | u32 command; | 1731 | u32 command; |
@@ -2600,14 +2600,15 @@ static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb) | |||
2600 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 2600 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
2601 | int ip_hdr_len = 0; | 2601 | int ip_hdr_len = 0; |
2602 | u8 l4_proto; | 2602 | u8 l4_proto; |
2603 | __be16 l3_proto = vlan_get_protocol(skb); | ||
2603 | 2604 | ||
2604 | if (skb->protocol == htons(ETH_P_IP)) { | 2605 | if (l3_proto == htons(ETH_P_IP)) { |
2605 | struct iphdr *ip4h = ip_hdr(skb); | 2606 | struct iphdr *ip4h = ip_hdr(skb); |
2606 | 2607 | ||
2607 | /* Calculate IPv4 checksum and L4 checksum */ | 2608 | /* Calculate IPv4 checksum and L4 checksum */ |
2608 | ip_hdr_len = ip4h->ihl; | 2609 | ip_hdr_len = ip4h->ihl; |
2609 | l4_proto = ip4h->protocol; | 2610 | l4_proto = ip4h->protocol; |
2610 | } else if (skb->protocol == htons(ETH_P_IPV6)) { | 2611 | } else if (l3_proto == htons(ETH_P_IPV6)) { |
2611 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 2612 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
2612 | 2613 | ||
2613 | /* Read l4_protocol from one of IPv6 extra headers */ | 2614 | /* Read l4_protocol from one of IPv6 extra headers */ |
@@ -2619,7 +2620,7 @@ static u32 mvpp2_skb_tx_csum(struct mvpp2_port *port, struct sk_buff *skb) | |||
2619 | } | 2620 | } |
2620 | 2621 | ||
2621 | return mvpp2_txq_desc_csum(skb_network_offset(skb), | 2622 | return mvpp2_txq_desc_csum(skb_network_offset(skb), |
2622 | skb->protocol, ip_hdr_len, l4_proto); | 2623 | l3_proto, ip_hdr_len, l4_proto); |
2623 | } | 2624 | } |
2624 | 2625 | ||
2625 | return MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE; | 2626 | return MVPP2_TXD_L4_CSUM_NOT | MVPP2_TXD_IP_CSUM_DISABLE; |