aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-11-12 20:13:33 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-12-01 06:44:10 -0500
commited83da12ee742da8cefa784def3af64e4e195462 (patch)
tree9608397aaffd4ae63c5f4ccd5d6ecce873c34e3a
parente921eb1ac411a32b98fa1a9ccbba1b24fae8de2d (diff)
ixgbe: Do not parse past IP header on fragments beyond the first
This change makes it so that only the first fragment in a series of fragments will have the L4 header pulled. Previously we were always pulling the L4 header as well and in the case of UDP this can harm performance since only the first fragment will have the header, the rest just contain data which should be left in the paged portion of the packet. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Stephen Ko <stephen.s.ko@intel.com> Tested-by: Marcus Dennis <marcusx.e.dennis@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 484bbedffe2a..79b834583188 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1338,26 +1338,29 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
1338 if (hlen < sizeof(struct iphdr)) 1338 if (hlen < sizeof(struct iphdr))
1339 return hdr.network - data; 1339 return hdr.network - data;
1340 1340
1341 /* record next protocol */ 1341 /* record next protocol if header is present */
1342 nexthdr = hdr.ipv4->protocol; 1342 if (!hdr.ipv4->frag_off)
1343 hdr.network += hlen; 1343 nexthdr = hdr.ipv4->protocol;
1344 } else if (protocol == __constant_htons(ETH_P_IPV6)) { 1344 } else if (protocol == __constant_htons(ETH_P_IPV6)) {
1345 if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) 1345 if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
1346 return max_len; 1346 return max_len;
1347 1347
1348 /* record next protocol */ 1348 /* record next protocol */
1349 nexthdr = hdr.ipv6->nexthdr; 1349 nexthdr = hdr.ipv6->nexthdr;
1350 hdr.network += sizeof(struct ipv6hdr); 1350 hlen = sizeof(struct ipv6hdr);
1351#ifdef IXGBE_FCOE 1351#ifdef IXGBE_FCOE
1352 } else if (protocol == __constant_htons(ETH_P_FCOE)) { 1352 } else if (protocol == __constant_htons(ETH_P_FCOE)) {
1353 if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN)) 1353 if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
1354 return max_len; 1354 return max_len;
1355 hdr.network += FCOE_HEADER_LEN; 1355 hlen = FCOE_HEADER_LEN;
1356#endif 1356#endif
1357 } else { 1357 } else {
1358 return hdr.network - data; 1358 return hdr.network - data;
1359 } 1359 }
1360 1360
1361 /* relocate pointer to start of L4 header */
1362 hdr.network += hlen;
1363
1361 /* finally sort out TCP/UDP */ 1364 /* finally sort out TCP/UDP */
1362 if (nexthdr == IPPROTO_TCP) { 1365 if (nexthdr == IPPROTO_TCP) {
1363 if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) 1366 if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))