diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe/ixgbe_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 116 |
1 files changed, 1 insertions, 115 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5a3efd9f9de0..166dc0015a5e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -1521,120 +1521,6 @@ void ixgbe_alloc_rx_buffers(struct ixgbe_ring *rx_ring, u16 cleaned_count) | |||
1521 | ixgbe_release_rx_desc(rx_ring, i); | 1521 | ixgbe_release_rx_desc(rx_ring, i); |
1522 | } | 1522 | } |
1523 | 1523 | ||
1524 | /** | ||
1525 | * ixgbe_get_headlen - determine size of header for RSC/LRO/GRO/FCOE | ||
1526 | * @data: pointer to the start of the headers | ||
1527 | * @max_len: total length of section to find headers in | ||
1528 | * | ||
1529 | * This function is meant to determine the length of headers that will | ||
1530 | * be recognized by hardware for LRO, GRO, and RSC offloads. The main | ||
1531 | * motivation of doing this is to only perform one pull for IPv4 TCP | ||
1532 | * packets so that we can do basic things like calculating the gso_size | ||
1533 | * based on the average data per packet. | ||
1534 | **/ | ||
1535 | static unsigned int ixgbe_get_headlen(unsigned char *data, | ||
1536 | unsigned int max_len) | ||
1537 | { | ||
1538 | union { | ||
1539 | unsigned char *network; | ||
1540 | /* l2 headers */ | ||
1541 | struct ethhdr *eth; | ||
1542 | struct vlan_hdr *vlan; | ||
1543 | /* l3 headers */ | ||
1544 | struct iphdr *ipv4; | ||
1545 | struct ipv6hdr *ipv6; | ||
1546 | } hdr; | ||
1547 | __be16 protocol; | ||
1548 | u8 nexthdr = 0; /* default to not TCP */ | ||
1549 | u8 hlen; | ||
1550 | |||
1551 | /* this should never happen, but better safe than sorry */ | ||
1552 | if (max_len < ETH_HLEN) | ||
1553 | return max_len; | ||
1554 | |||
1555 | /* initialize network frame pointer */ | ||
1556 | hdr.network = data; | ||
1557 | |||
1558 | /* set first protocol and move network header forward */ | ||
1559 | protocol = hdr.eth->h_proto; | ||
1560 | hdr.network += ETH_HLEN; | ||
1561 | |||
1562 | /* handle any vlan tag if present */ | ||
1563 | if (protocol == htons(ETH_P_8021Q)) { | ||
1564 | if ((hdr.network - data) > (max_len - VLAN_HLEN)) | ||
1565 | return max_len; | ||
1566 | |||
1567 | protocol = hdr.vlan->h_vlan_encapsulated_proto; | ||
1568 | hdr.network += VLAN_HLEN; | ||
1569 | } | ||
1570 | |||
1571 | /* handle L3 protocols */ | ||
1572 | if (protocol == htons(ETH_P_IP)) { | ||
1573 | if ((hdr.network - data) > (max_len - sizeof(struct iphdr))) | ||
1574 | return max_len; | ||
1575 | |||
1576 | /* access ihl as a u8 to avoid unaligned access on ia64 */ | ||
1577 | hlen = (hdr.network[0] & 0x0F) << 2; | ||
1578 | |||
1579 | /* verify hlen meets minimum size requirements */ | ||
1580 | if (hlen < sizeof(struct iphdr)) | ||
1581 | return hdr.network - data; | ||
1582 | |||
1583 | /* record next protocol if header is present */ | ||
1584 | if (!(hdr.ipv4->frag_off & htons(IP_OFFSET))) | ||
1585 | nexthdr = hdr.ipv4->protocol; | ||
1586 | } else if (protocol == htons(ETH_P_IPV6)) { | ||
1587 | if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr))) | ||
1588 | return max_len; | ||
1589 | |||
1590 | /* record next protocol */ | ||
1591 | nexthdr = hdr.ipv6->nexthdr; | ||
1592 | hlen = sizeof(struct ipv6hdr); | ||
1593 | #ifdef IXGBE_FCOE | ||
1594 | } else if (protocol == htons(ETH_P_FCOE)) { | ||
1595 | if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN)) | ||
1596 | return max_len; | ||
1597 | hlen = FCOE_HEADER_LEN; | ||
1598 | #endif | ||
1599 | } else { | ||
1600 | return hdr.network - data; | ||
1601 | } | ||
1602 | |||
1603 | /* relocate pointer to start of L4 header */ | ||
1604 | hdr.network += hlen; | ||
1605 | |||
1606 | /* finally sort out TCP/UDP */ | ||
1607 | if (nexthdr == IPPROTO_TCP) { | ||
1608 | if ((hdr.network - data) > (max_len - sizeof(struct tcphdr))) | ||
1609 | return max_len; | ||
1610 | |||
1611 | /* access doff as a u8 to avoid unaligned access on ia64 */ | ||
1612 | hlen = (hdr.network[12] & 0xF0) >> 2; | ||
1613 | |||
1614 | /* verify hlen meets minimum size requirements */ | ||
1615 | if (hlen < sizeof(struct tcphdr)) | ||
1616 | return hdr.network - data; | ||
1617 | |||
1618 | hdr.network += hlen; | ||
1619 | } else if (nexthdr == IPPROTO_UDP) { | ||
1620 | if ((hdr.network - data) > (max_len - sizeof(struct udphdr))) | ||
1621 | return max_len; | ||
1622 | |||
1623 | hdr.network += sizeof(struct udphdr); | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * If everything has gone correctly hdr.network should be the | ||
1628 | * data section of the packet and will be the end of the header. | ||
1629 | * If not then it probably represents the end of the last recognized | ||
1630 | * header. | ||
1631 | */ | ||
1632 | if ((hdr.network - data) < max_len) | ||
1633 | return hdr.network - data; | ||
1634 | else | ||
1635 | return max_len; | ||
1636 | } | ||
1637 | |||
1638 | static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring, | 1524 | static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring, |
1639 | struct sk_buff *skb) | 1525 | struct sk_buff *skb) |
1640 | { | 1526 | { |
@@ -1793,7 +1679,7 @@ static void ixgbe_pull_tail(struct ixgbe_ring *rx_ring, | |||
1793 | * we need the header to contain the greater of either ETH_HLEN or | 1679 | * we need the header to contain the greater of either ETH_HLEN or |
1794 | * 60 bytes if the skb->len is less than 60 for skb_pad. | 1680 | * 60 bytes if the skb->len is less than 60 for skb_pad. |
1795 | */ | 1681 | */ |
1796 | pull_len = ixgbe_get_headlen(va, IXGBE_RX_HDR_SIZE); | 1682 | pull_len = eth_get_headlen(va, IXGBE_RX_HDR_SIZE); |
1797 | 1683 | ||
1798 | /* align pull length to size of long to optimize memcpy performance */ | 1684 | /* align pull length to size of long to optimize memcpy performance */ |
1799 | skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); | 1685 | skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); |