[Intel-wired-lan] [PATCH V2] ixgbe: Handle extended IPv6 headers in tx path

Tom Herbert tom at herbertland.com
Tue Nov 17 16:48:38 UTC 2015


On Tue, Nov 17, 2015 at 8:41 AM, Alexander Duyck
<alexander.duyck at gmail.com> wrote:
> On Mon, Nov 16, 2015 at 9:21 PM, Tom Herbert <tom at herbertland.com> wrote:
>> On Mon, Nov 16, 2015 at 4:26 PM, Mark D Rustad <mark.d.rustad at intel.com> wrote:
>>> Check for and handle IPv6 extended headers so that tx checksum
>>> offload can be done. Thanks to Tom Herbert for noticing this
>>> problem. Thanks to Alexander Duyck for recognizing problems with
>>> the first version of this patch.
>>>
>>> Reported-by: Tom Herbert <tom at herbertland.com>
>>> Signed-off-by: Mark Rustad <mark.d.rustad at intel.com>
>>> ---
>>> Changed in V2:
>>> - Use ipv6_skip_exthdr instead of ipv6_find_hdr
>>> - Move code into L3 processing and avoid any possible loop
>>> - Handle encapsulated IPv6 extended headers correctly
>>> ---
>>>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   19 +++++++++++++++++++
>>>  1 file changed, 19 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> index 1ffbe85eab7b..23f316a9ad5a 100644
>>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>>> @@ -7229,6 +7229,8 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
>>>                         struct tcphdr *tcphdr;
>>>                         u8 *raw;
>>>                 } transport_hdr;
>>> +               __be16 frag_off;
>>> +               int rc;
>>>
>>>                 if (skb->encapsulation) {
>>>                         network_hdr.raw = skb_inner_network_header(skb);
>>> @@ -7252,6 +7254,23 @@ static void ixgbe_tx_csum(struct ixgbe_ring *tx_ring,
>>>                 case 6:
>>>                         vlan_macip_lens |= transport_hdr.raw - network_hdr.raw;
>>>                         l4_hdr = network_hdr.ipv6->nexthdr;
>>> +                       if (likely((transport_hdr.raw - network_hdr.raw) ==
>>> +                                  sizeof(struct ipv6hdr)))
>>> +                               break;
>>> +                       rc = ipv6_skip_exthdr(skb, network_hdr.raw +
>>> +                                                  sizeof(struct ipv6hdr) -
>>> +                                                  skb->data,
>>> +                                             &l4_hdr, &frag_off);
>>> +                       if (rc < 0) {
>>> +                               if (unlikely(net_ratelimit())) {
>>> +                                       dev_warn(tx_ring->dev,
>>> +                                                "ipv6_skip_exthdr returned %d\n",
>>> +                                                rc);
>>> +                               }
>>> +                               break;
>>> +                       }
>>> +                       if (frag_off)
>>> +                               l4_hdr = 0;
>>>                         break;
>>>                 default:
>>>                         if (unlikely(net_ratelimit())) {
>>>
>>
>> Failures should not result in dev_warn, just call skb_checksum_help
>> instead. Ignoring CHECKSUM_PARTIAL is guaranteed to be sending a bad
>> checksum!
>
> The problem is there are scenarios here where a checksum shouldn't be
> computed.  If for example the frame is fragmented we should be
> displaying some sort of error message and not computing the checksum
> because no matter what we compute it isn't going to be valid.
>
If the stack is sending fragments with CHECKSUM_PARTIAL set then that
is a bug higher in the stack-- the driver does not need to worry about
that.


More information about the Intel-wired-lan mailing list