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

Alexander Duyck alexander.duyck at gmail.com
Tue Nov 17 17:01:00 UTC 2015


On Tue, Nov 17, 2015 at 8:48 AM, Tom Herbert <tom at herbertland.com> wrote:
> 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.

Right, but it is still something that needs to get fixed.  By
triggering the dev_warn here we at least create visibility that
something has gone horribly wrong.

- Alex


More information about the Intel-wired-lan mailing list