fm10k: Modify tunnel length header check when offloading

The FM10000 host interface can only support up to 184 bytes when
performing tunnel offloads. Because of this, a check was added to
prevent the driver from attempting to feed a header to the hardware too
big for it to parse. Make this check a little more robust by calculating
the inner L4 header length based on whether it is TCP or UDP.

Cc: Joe Stringer <joestringer@nicira.com>
Signed-off-by: Matthew Vick <matthew.vick@intel.com>
Tested-by: Krishneil Singh <Krishneil.k.singh@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Matthew Vick 2015-01-29 07:17:22 +00:00 committed by Jeff Kirsher
parent b898441f4e
commit 8c1a90aa49
2 changed files with 27 additions and 9 deletions

View file

@ -711,10 +711,6 @@ static struct ethhdr *fm10k_gre_is_nvgre(struct sk_buff *skb)
if (nvgre_hdr->flags & FM10K_NVGRE_RESERVED0_FLAGS)
return NULL;
/* verify protocol is transparent Ethernet bridging */
if (nvgre_hdr->proto != htons(ETH_P_TEB))
return NULL;
/* report start of ethernet header */
if (nvgre_hdr->flags & NVGRE_TNI)
return (struct ethhdr *)(nvgre_hdr + 1);
@ -724,13 +720,11 @@ static struct ethhdr *fm10k_gre_is_nvgre(struct sk_buff *skb)
static __be16 fm10k_tx_encap_offload(struct sk_buff *skb)
{
u8 l4_hdr = 0, inner_l4_hdr = 0, inner_l4_hlen;
struct ethhdr *eth_hdr;
u8 l4_hdr = 0;
/* fm10k supports 184 octets of outer+inner headers. Minus 20 for inner L4. */
#define FM10K_MAX_ENCAP_TRANSPORT_OFFSET 164
if (skb_inner_transport_header(skb) - skb_mac_header(skb) >
FM10K_MAX_ENCAP_TRANSPORT_OFFSET)
if (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
skb->inner_protocol != htons(ETH_P_TEB))
return 0;
switch (vlan_get_protocol(skb)) {
@ -760,12 +754,33 @@ static __be16 fm10k_tx_encap_offload(struct sk_buff *skb)
switch (eth_hdr->h_proto) {
case htons(ETH_P_IP):
inner_l4_hdr = inner_ip_hdr(skb)->protocol;
break;
case htons(ETH_P_IPV6):
inner_l4_hdr = inner_ipv6_hdr(skb)->nexthdr;
break;
default:
return 0;
}
switch (inner_l4_hdr) {
case IPPROTO_TCP:
inner_l4_hlen = inner_tcp_hdrlen(skb);
break;
case IPPROTO_UDP:
inner_l4_hlen = 8;
break;
default:
return 0;
}
/* The hardware allows tunnel offloads only if the combined inner and
* outer header is 184 bytes or less
*/
if (skb_inner_transport_header(skb) + inner_l4_hlen -
skb_mac_header(skb) > FM10K_TUNNEL_HEADER_LENGTH)
return 0;
return eth_hdr->h_proto;
}

View file

@ -356,6 +356,9 @@ struct fm10k_hw;
#define FM10K_QUEUE_DISABLE_TIMEOUT 100
#define FM10K_RESET_TIMEOUT 150
/* Maximum supported combined inner and outer header length for encapsulation */
#define FM10K_TUNNEL_HEADER_LENGTH 184
/* VF registers */
#define FM10K_VFCTRL 0x00000
#define FM10K_VFCTRL_RST 0x00000008