Commit 8c1a90aa authored by Matthew Vick's avatar Matthew Vick Committed by Jeff Kirsher
Browse files

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: default avatarMatthew Vick <matthew.vick@intel.com>
Tested-by: default avatarKrishneil Singh <Krishneil.k.singh@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b898441f
Loading
Loading
Loading
Loading
+24 −9
Original line number Diff line number Diff line
@@ -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;
}

+3 −0
Original line number Diff line number Diff line
@@ -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