win-pvdrivers

changeset 691:7232a030f662

Fix a problem with RX checksum calculation in the case where a 1 byte sg element
author James Harper <james.harper@bendigoit.com.au>
date Sun Nov 08 21:53:31 2009 +1100 (2009-11-08)
parents abde3e790a21
children 1fe30f6966eb
files xennet/xennet_rx.c
line diff
     1.1 --- a/xennet/xennet_rx.c	Sun Nov 08 14:49:49 2009 +1100
     1.2 +++ b/xennet/xennet_rx.c	Sun Nov 08 21:53:31 2009 +1100
     1.3 @@ -324,6 +324,7 @@ XenNet_SumPacketData(
     1.4    PUSHORT csum_ptr;
     1.5    USHORT remaining;
     1.6    USHORT ip4_length;
     1.7 +  BOOLEAN csum_span = TRUE; /* when the USHORT to be checksummed spans a buffer */
     1.8    
     1.9    //FUNCTION_ENTER();
    1.10  
    1.11 @@ -340,9 +341,11 @@ XenNet_SumPacketData(
    1.12    switch (pi->ip_proto)
    1.13    {
    1.14    case 6:
    1.15 +    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 17));
    1.16      csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 16];
    1.17      break;
    1.18    case 17:
    1.19 +    ASSERT(buffer_length >= (USHORT)(XN_HDR_SIZE + pi->ip4_header_length + 7));
    1.20      csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + pi->ip4_header_length + 6];
    1.21      break;
    1.22    default:
    1.23 @@ -362,15 +365,44 @@ XenNet_SumPacketData(
    1.24    remaining = ip4_length - pi->ip4_header_length;
    1.25  
    1.26    csum += remaining;
    1.27 -
    1.28 -  for (buffer_offset = i = XN_HDR_SIZE + pi->ip4_header_length; i < total_length - 1; i += 2, buffer_offset += 2)
    1.29 +  
    1.30 +  csum_span = FALSE;
    1.31 +  buffer_offset = i = XN_HDR_SIZE + pi->ip4_header_length;
    1.32 +  while (i < total_length)
    1.33    {
    1.34      /* don't include the checksum field itself in the calculation */
    1.35      if ((pi->ip_proto == 6 && i == XN_HDR_SIZE + pi->ip4_header_length + 16) || (pi->ip_proto == 17 && i == XN_HDR_SIZE + pi->ip4_header_length + 6))
    1.36 +    {
    1.37 +      /* we know that this always happens in the header buffer so we are guaranteed the full two bytes */
    1.38 +      i += 2;
    1.39 +      buffer_offset += 2;
    1.40        continue;
    1.41 -    if (buffer_offset == buffer_length - 1) // deal with a buffer ending on an odd byte boundary
    1.42 +    }
    1.43 +    if (csum_span)
    1.44      {
    1.45 +      /* the other half of the next bit */
    1.46 +      ASSERT(buffer_offset == 0);
    1.47 +      csum += (USHORT)buffer[buffer_offset];
    1.48 +      csum_span = FALSE;
    1.49 +      i += 1;
    1.50 +      buffer_offset += 1;
    1.51 +    }
    1.52 +    else if (buffer_offset == buffer_length - 1)
    1.53 +    {
    1.54 +      /* deal with a buffer ending on an odd byte boundary */
    1.55        csum += (USHORT)buffer[buffer_offset] << 8;
    1.56 +      csum_span = TRUE;
    1.57 +      i += 1;
    1.58 +      buffer_offset += 1;
    1.59 +    }
    1.60 +    else
    1.61 +    {
    1.62 +      csum += GET_NET_PUSHORT(&buffer[buffer_offset]);
    1.63 +      i += 2;
    1.64 +      buffer_offset += 2;
    1.65 +    }
    1.66 +    if (buffer_offset == buffer_length && i < total_length)
    1.67 +    {
    1.68        NdisGetNextBuffer(mdl, &mdl);
    1.69        if (mdl == NULL)
    1.70        {
    1.71 @@ -378,46 +410,18 @@ XenNet_SumPacketData(
    1.72          return FALSE; // should never happen
    1.73        }
    1.74        NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
    1.75 -      csum += ((USHORT)buffer[0]);
    1.76 -      buffer_offset = (USHORT)-1;
    1.77 -    }
    1.78 -    else
    1.79 -    {
    1.80 -      if (buffer_offset == buffer_length)
    1.81 -      {
    1.82 -//        KdPrint((__DRIVER_NAME "     New buffer - aligned...\n"));
    1.83 -        NdisGetNextBuffer(mdl, &mdl);
    1.84 -        if (mdl == NULL)
    1.85 -        {
    1.86 -          KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
    1.87 -          return FALSE; // should never happen
    1.88 -        }
    1.89 -        NdisQueryBufferSafe(mdl, (PVOID) &buffer, &buffer_length, NormalPagePriority);
    1.90 -        buffer_offset = 0;
    1.91 -      }
    1.92 -      csum += GET_NET_PUSHORT(&buffer[buffer_offset]);
    1.93 +      ASSERT(buffer_length);
    1.94 +      buffer_offset = 0;
    1.95      }
    1.96    }
    1.97 -  if (i != total_length) // last odd byte
    1.98 -  {
    1.99 -    if (buffer_offset >= buffer_length)
   1.100 -    {
   1.101 -      NdisGetNextBuffer(mdl, &mdl);
   1.102 -      if (mdl == NULL)
   1.103 -      {
   1.104 -        KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   1.105 -        return FALSE; // should never happen
   1.106 -      }
   1.107 -      NdisQueryBufferSafe(mdl, (PVOID)&buffer, &buffer_length, NormalPagePriority);
   1.108 -      buffer_offset = 0;
   1.109 -    }
   1.110 -    csum += ((USHORT)buffer[buffer_offset] << 8);
   1.111 -  }
   1.112 +      
   1.113    while (csum & 0xFFFF0000)
   1.114      csum = (csum & 0xFFFF) + (csum >> 16);
   1.115    
   1.116    if (set_csum)
   1.117 +  {
   1.118      *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
   1.119 +  }
   1.120    else
   1.121    {
   1.122      //FUNCTION_EXIT();