|
@@ -7558,8 +7558,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
|
|
struct ipv6hdr *ipv6;
|
|
struct ipv6hdr *ipv6;
|
|
} hdr;
|
|
} hdr;
|
|
struct tcphdr *th;
|
|
struct tcphdr *th;
|
|
|
|
+ unsigned int hlen;
|
|
struct sk_buff *skb;
|
|
struct sk_buff *skb;
|
|
__be16 vlan_id;
|
|
__be16 vlan_id;
|
|
|
|
+ int l4_proto;
|
|
|
|
|
|
/* if ring doesn't have a interrupt vector, cannot perform ATR */
|
|
/* if ring doesn't have a interrupt vector, cannot perform ATR */
|
|
if (!q_vector)
|
|
if (!q_vector)
|
|
@@ -7571,10 +7573,14 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
|
|
|
|
|
|
ring->atr_count++;
|
|
ring->atr_count++;
|
|
|
|
|
|
|
|
+ /* currently only IPv4/IPv6 with TCP is supported */
|
|
|
|
+ if ((first->protocol != htons(ETH_P_IP)) &&
|
|
|
|
+ (first->protocol != htons(ETH_P_IPV6)))
|
|
|
|
+ return;
|
|
|
|
+
|
|
/* snag network header to get L4 type and address */
|
|
/* snag network header to get L4 type and address */
|
|
skb = first->skb;
|
|
skb = first->skb;
|
|
hdr.network = skb_network_header(skb);
|
|
hdr.network = skb_network_header(skb);
|
|
- th = tcp_hdr(skb);
|
|
|
|
#ifdef CONFIG_IXGBE_VXLAN
|
|
#ifdef CONFIG_IXGBE_VXLAN
|
|
if (skb->encapsulation &&
|
|
if (skb->encapsulation &&
|
|
first->protocol == htons(ETH_P_IP) &&
|
|
first->protocol == htons(ETH_P_IP) &&
|
|
@@ -7583,43 +7589,34 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
|
|
|
|
|
|
/* verify the port is recognized as VXLAN */
|
|
/* verify the port is recognized as VXLAN */
|
|
if (adapter->vxlan_port &&
|
|
if (adapter->vxlan_port &&
|
|
- udp_hdr(skb)->dest == adapter->vxlan_port) {
|
|
|
|
|
|
+ udp_hdr(skb)->dest == adapter->vxlan_port)
|
|
hdr.network = skb_inner_network_header(skb);
|
|
hdr.network = skb_inner_network_header(skb);
|
|
- th = inner_tcp_hdr(skb);
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
#endif /* CONFIG_IXGBE_VXLAN */
|
|
#endif /* CONFIG_IXGBE_VXLAN */
|
|
|
|
|
|
/* Currently only IPv4/IPv6 with TCP is supported */
|
|
/* Currently only IPv4/IPv6 with TCP is supported */
|
|
switch (hdr.ipv4->version) {
|
|
switch (hdr.ipv4->version) {
|
|
case IPVERSION:
|
|
case IPVERSION:
|
|
- if (hdr.ipv4->protocol != IPPROTO_TCP)
|
|
|
|
- return;
|
|
|
|
|
|
+ /* access ihl as u8 to avoid unaligned access on ia64 */
|
|
|
|
+ hlen = (hdr.network[0] & 0x0F) << 2;
|
|
|
|
+ l4_proto = hdr.ipv4->protocol;
|
|
break;
|
|
break;
|
|
case 6:
|
|
case 6:
|
|
- if (likely((unsigned char *)th - hdr.network ==
|
|
|
|
- sizeof(struct ipv6hdr))) {
|
|
|
|
- if (hdr.ipv6->nexthdr != IPPROTO_TCP)
|
|
|
|
- return;
|
|
|
|
- } else {
|
|
|
|
- __be16 frag_off;
|
|
|
|
- u8 l4_hdr;
|
|
|
|
-
|
|
|
|
- ipv6_skip_exthdr(skb, hdr.network - skb->data +
|
|
|
|
- sizeof(struct ipv6hdr),
|
|
|
|
- &l4_hdr, &frag_off);
|
|
|
|
- if (unlikely(frag_off))
|
|
|
|
- return;
|
|
|
|
- if (l4_hdr != IPPROTO_TCP)
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ hlen = hdr.network - skb->data;
|
|
|
|
+ l4_proto = ipv6_find_hdr(skb, &hlen, IPPROTO_TCP, NULL, NULL);
|
|
|
|
+ hlen -= hdr.network - skb->data;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* skip this packet since it is invalid or the socket is closing */
|
|
|
|
- if (!th || th->fin)
|
|
|
|
|
|
+ if (l4_proto != IPPROTO_TCP)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ th = (struct tcphdr *)(hdr.network + hlen);
|
|
|
|
+
|
|
|
|
+ /* skip this packet since the socket is closing */
|
|
|
|
+ if (th->fin)
|
|
return;
|
|
return;
|
|
|
|
|
|
/* sample on all syn packets or once every atr sample count */
|
|
/* sample on all syn packets or once every atr sample count */
|