diff options
author | Gal Pressman <galp@mellanox.com> | 2016-09-07 12:08:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-09-08 19:15:29 -0400 |
commit | cd17d230dd060a12f7451c0caeedb3fd5158eaf9 (patch) | |
tree | 78a463ca47e06f2b59dad504f05904f1ee0e5f85 | |
parent | 4e39883d9c7426f8246ef86a32dc6a6f06f5aace (diff) |
net/mlx5e: Fix parsing of vlan packets when updating lro header
Currently vlan tagged packets were not parsed correctly
and assumed to be regular IPv4/IPv6 packets.
We should check for 802.1Q/802.1ad tags and update the lro header
accordingly.
This fixes the use case where LRO is on and rxvlan is off
(vlan stripping is off).
Fixes: e586b3b0baee ('net/mlx5: Ethernet Datapath files')
Signed-off-by: Gal Pressman <galp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index b6f8ebbdb487..e7c969df3dad 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | |||
@@ -637,24 +637,32 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq) | |||
637 | static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, | 637 | static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, |
638 | u32 cqe_bcnt) | 638 | u32 cqe_bcnt) |
639 | { | 639 | { |
640 | struct ethhdr *eth = (struct ethhdr *)(skb->data); | 640 | struct ethhdr *eth = (struct ethhdr *)(skb->data); |
641 | struct iphdr *ipv4 = (struct iphdr *)(skb->data + ETH_HLEN); | 641 | struct iphdr *ipv4; |
642 | struct ipv6hdr *ipv6 = (struct ipv6hdr *)(skb->data + ETH_HLEN); | 642 | struct ipv6hdr *ipv6; |
643 | struct tcphdr *tcp; | 643 | struct tcphdr *tcp; |
644 | int network_depth = 0; | ||
645 | __be16 proto; | ||
646 | u16 tot_len; | ||
644 | 647 | ||
645 | u8 l4_hdr_type = get_cqe_l4_hdr_type(cqe); | 648 | u8 l4_hdr_type = get_cqe_l4_hdr_type(cqe); |
646 | int tcp_ack = ((CQE_L4_HDR_TYPE_TCP_ACK_NO_DATA == l4_hdr_type) || | 649 | int tcp_ack = ((CQE_L4_HDR_TYPE_TCP_ACK_NO_DATA == l4_hdr_type) || |
647 | (CQE_L4_HDR_TYPE_TCP_ACK_AND_DATA == l4_hdr_type)); | 650 | (CQE_L4_HDR_TYPE_TCP_ACK_AND_DATA == l4_hdr_type)); |
648 | 651 | ||
649 | u16 tot_len = cqe_bcnt - ETH_HLEN; | 652 | skb->mac_len = ETH_HLEN; |
653 | proto = __vlan_get_protocol(skb, eth->h_proto, &network_depth); | ||
650 | 654 | ||
651 | if (eth->h_proto == htons(ETH_P_IP)) { | 655 | ipv4 = (struct iphdr *)(skb->data + network_depth); |
652 | tcp = (struct tcphdr *)(skb->data + ETH_HLEN + | 656 | ipv6 = (struct ipv6hdr *)(skb->data + network_depth); |
657 | tot_len = cqe_bcnt - network_depth; | ||
658 | |||
659 | if (proto == htons(ETH_P_IP)) { | ||
660 | tcp = (struct tcphdr *)(skb->data + network_depth + | ||
653 | sizeof(struct iphdr)); | 661 | sizeof(struct iphdr)); |
654 | ipv6 = NULL; | 662 | ipv6 = NULL; |
655 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 663 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; |
656 | } else { | 664 | } else { |
657 | tcp = (struct tcphdr *)(skb->data + ETH_HLEN + | 665 | tcp = (struct tcphdr *)(skb->data + network_depth + |
658 | sizeof(struct ipv6hdr)); | 666 | sizeof(struct ipv6hdr)); |
659 | ipv4 = NULL; | 667 | ipv4 = NULL; |
660 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | 668 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; |