[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALx6S34-mUvQyUQNcVC+o+NeUxWEsCG2GS=Eq++eGqoh=kv8kg@mail.gmail.com>
Date: Tue, 1 Sep 2015 20:17:52 -0700
From: Tom Herbert <tom@...bertland.com>
To: Jeff Kirsher <jeffrey.t.kirsher@...el.com>
Cc: "David S. Miller" <davem@...emloft.net>,
Mark Rustad <mark.d.rustad@...el.com>,
Linux Kernel Network Developers <netdev@...r.kernel.org>,
nhorman@...hat.com, sassmann@...hat.com, jogreene@...hat.com
Subject: Re: [net-next 05/19] ixgbe: Add support for UDP-encapsulated tx
checksum offload
On Tue, Sep 1, 2015 at 6:13 PM, Jeff Kirsher
<jeffrey.t.kirsher@...el.com> wrote:
> From: Mark Rustad <mark.d.rustad@...el.com>
>
> By using GSO for UDP-encapsulated packets, all ixgbe devices can
> be directed to generate checksums for the inner headers because
> the outer UDP checksum can be zero. So point the machinery at the
> inner headers and have the hardware generate the checksum.
>
I suspect this is not UDP-encapsulation specific, will it work with
TCP/IP/IP, TCP/IP/GRE etc.?
Isn't there anyway the ixgbe could just be made to NETIF_HW_CSUM? That
would be so much more straightforward and support nearly all use cases
without needing to jump through all these hoops.
Tom
> Signed-off-by: Mark Rustad <mark.d.rustad@...el.com>
> Tested-by: Phil Schmitt <phillip.j.schmitt@...el.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@...el.com>
> ---
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 66 ++++++++++++++++++++++-----
> 1 file changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index ab28dc2..900562e 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -6912,31 +6912,55 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
> if (!(first->tx_flags & IXGBE_TX_FLAGS_HW_VLAN) &&
> !(first->tx_flags & IXGBE_TX_FLAGS_CC))
> return;
> + vlan_macip_lens = skb_network_offset(skb) <<
> + IXGBE_ADVTXD_MACLEN_SHIFT;
> } else {
> u8 l4_hdr = 0;
> - switch (first->protocol) {
> - case htons(ETH_P_IP):
> - vlan_macip_lens |= skb_network_header_len(skb);
> + union {
> + struct iphdr *ipv4;
> + struct ipv6hdr *ipv6;
> + u8 *raw;
> + } network_hdr;
> + union {
> + struct tcphdr *tcphdr;
> + u8 *raw;
> + } transport_hdr;
> +
> + if (skb->encapsulation) {
> + network_hdr.raw = skb_inner_network_header(skb);
> + transport_hdr.raw = skb_inner_transport_header(skb);
> + vlan_macip_lens = skb_inner_network_offset(skb) <<
> + IXGBE_ADVTXD_MACLEN_SHIFT;
> + } else {
> + network_hdr.raw = skb_network_header(skb);
> + transport_hdr.raw = skb_transport_header(skb);
> + vlan_macip_lens = skb_network_offset(skb) <<
> + IXGBE_ADVTXD_MACLEN_SHIFT;
> + }
> +
> + /* use first 4 bits to determine IP version */
> + switch (network_hdr.ipv4->version) {
> + case IPVERSION:
> + vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
> type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
> - l4_hdr = ip_hdr(skb)->protocol;
> + l4_hdr = network_hdr.ipv4->protocol;
> break;
> - case htons(ETH_P_IPV6):
> - vlan_macip_lens |= skb_network_header_len(skb);
> - l4_hdr = ipv6_hdr(skb)->nexthdr;
> + case 6:
> + vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
> + l4_hdr = network_hdr.ipv6->nexthdr;
> break;
> default:
> if (unlikely(net_ratelimit())) {
> dev_warn(tx_ring->dev,
> - "partial checksum but proto=%x!\n",
> - first->protocol);
> + "partial checksum but version=%d\n",
> + network_hdr.ipv4->version);
> }
> - break;
> }
>
> switch (l4_hdr) {
> case IPPROTO_TCP:
> type_tucmd |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
> - mss_l4len_idx = tcp_hdrlen(skb) <<
> + mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) <<
> IXGBE_ADVTXD_L4LEN_SHIFT;
> break;
> case IPPROTO_SCTP:
> @@ -6962,7 +6986,6 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
> }
>
> /* vlan_macip_lens: MACLEN, VLAN tag */
> - vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT;
> vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
>
> ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, 0,
> @@ -8207,6 +8230,21 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
> kfree(fwd_adapter);
> }
>
> +#define IXGBE_MAX_TUNNEL_HDR_LEN 80
> +static netdev_features_t
> +ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
> + netdev_features_t features)
> +{
> + if (!skb->encapsulation)
> + return features;
> +
> + if (unlikely(skb_inner_mac_header(skb) - skb_transport_header(skb) >
> + IXGBE_MAX_TUNNEL_HDR_LEN))
> + return features & ~NETIF_F_ALL_CSUM;
> +
> + return features;
> +}
> +
> static const struct net_device_ops ixgbe_netdev_ops = {
> .ndo_open = ixgbe_open,
> .ndo_stop = ixgbe_close,
> @@ -8254,6 +8292,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
> .ndo_dfwd_del_station = ixgbe_fwd_del,
> .ndo_add_vxlan_port = ixgbe_add_vxlan_port,
> .ndo_del_vxlan_port = ixgbe_del_vxlan_port,
> + .ndo_features_check = ixgbe_features_check,
> };
>
> /**
> @@ -8613,6 +8652,9 @@ skip_sriov:
> netdev->vlan_features |= NETIF_F_IPV6_CSUM;
> netdev->vlan_features |= NETIF_F_SG;
>
> + netdev->hw_enc_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
> + NETIF_F_IPV6_CSUM;
> +
> netdev->priv_flags |= IFF_UNICAST_FLT;
> netdev->priv_flags |= IFF_SUPP_NOFCS;
>
> --
> 2.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists