ixgbe: Add support for IPv6 and UDP to ixgbe_get_headlen
authorAlexander Duyck <alexander.h.duyck@intel.com>
Thu, 24 May 2012 08:26:29 +0000 (08:26 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 23 Oct 2012 04:13:48 +0000 (21:13 -0700)
This change adds support for IPv6 and UDP to ixgbe_get_headlen. The
advantage to this is that we can now handle ipv4/UDP, ipv6/TCP, and
ipv6/UDP with a single memcpy instead of having to do them in multiple
pskb_may_pull calls.

A quick bit of testing shows that we increase throughput for a single
session of netperf from 8800Mpbs to about 9300Mpbs in the case of ipv6/TCP.
As such overall ipv6 performance should improve with this change.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Stephen Ko <stephen.s.ko@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index e2a6691cbd7c52f94d5053f300579a9a90637b49..3ef74f893c2e9362ee2c66a0024a30b0f4b57c93 100644 (file)
@@ -1244,6 +1244,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                struct vlan_hdr *vlan;
                /* l3 headers */
                struct iphdr *ipv4;
+               struct ipv6hdr *ipv6;
        } hdr;
        __be16 protocol;
        u8 nexthdr = 0; /* default to not TCP */
@@ -1284,6 +1285,13 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                /* record next protocol */
                nexthdr = hdr.ipv4->protocol;
                hdr.network += hlen;
+       } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+                       return max_len;
+
+               /* record next protocol */
+               nexthdr = hdr.ipv6->nexthdr;
+               hdr.network += sizeof(struct ipv6hdr);
 #ifdef IXGBE_FCOE
        } else if (protocol == __constant_htons(ETH_P_FCOE)) {
                if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
@@ -1294,7 +1302,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                return hdr.network - data;
        }
 
-       /* finally sort out TCP */
+       /* finally sort out TCP/UDP */
        if (nexthdr == IPPROTO_TCP) {
                if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
                        return max_len;
@@ -1307,6 +1315,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                        return hdr.network - data;
 
                hdr.network += hlen;
+       } else if (nexthdr == IPPROTO_UDP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+                       return max_len;
+
+               hdr.network += sizeof(struct udphdr);
        }
 
        /*