win-pvdrivers

changeset 436:c4204f69c506

Many many updates to fix bugs encountered in ndistest.
Also fixed an erroneous call to NdisMDeregisterInterrupt in XenNet_Shutdown
author James Harper <james.harper@bendigoit.com.au>
date Tue Nov 04 17:30:22 2008 +1100 (2008-11-04)
parents 29da24ccca8a
children 3b1ba2d7056c
files xennet/xennet.c xennet/xennet.h xennet/xennet_common.c xennet/xennet_oid.c xennet/xennet_rx.c xennet/xennet_tx.c
line diff
     1.1 --- a/xennet/xennet.c	Sun Nov 02 16:10:40 2008 +1100
     1.2 +++ b/xennet/xennet.c	Tue Nov 04 17:30:22 2008 +1100
     1.3 @@ -420,7 +420,7 @@ XenNet_Init(
     1.4      status = NDIS_STATUS_RESOURCES;
     1.5      goto err;
     1.6    }
     1.7 -  NdisSetPacketPoolProtocolId(xi->packet_pool, NDIS_PROTOCOL_ID_TCP_IP);
     1.8 +  //IS THIS NECESSARY??? NdisSetPacketPoolProtocolId(xi->packet_pool, NDIS_PROTOCOL_ID_TCP_IP);
     1.9  
    1.10    NdisAllocateBufferPool(&status, &xi->buffer_pool, XN_RX_QUEUE_LEN);
    1.11    if (status != NDIS_STATUS_SUCCESS)
    1.12 @@ -477,6 +477,7 @@ XenNet_Init(
    1.13    if (!NT_SUCCESS(status))
    1.14    {
    1.15      KdPrint(("Could not open config in registry (%08x)\n", status));
    1.16 +    status = NDIS_STATUS_RESOURCES;
    1.17      goto err;
    1.18    }
    1.19  
    1.20 @@ -590,7 +591,10 @@ XenNet_Init(
    1.21    if (!NT_SUCCESS(status))
    1.22    {
    1.23      KdPrint(("NdisMRegisterInterrupt failed with 0x%x\n", status));
    1.24 -    status = NDIS_STATUS_FAILURE;
    1.25 +    status = NDIS_STATUS_RESOURCES;
    1.26 +    xi->connected = FALSE;
    1.27 +    XenNet_TxShutdown(xi);
    1.28 +    XenNet_RxShutdown(xi);
    1.29      goto err;
    1.30    }
    1.31  
    1.32 @@ -602,6 +606,7 @@ XenNet_Init(
    1.33  
    1.34  err:
    1.35    NdisFreeMemory(xi, 0, 0);
    1.36 +  *OpenErrorStatus = status;
    1.37    FUNCTION_ERROR_EXIT();
    1.38    return status;
    1.39  }
    1.40 @@ -628,11 +633,12 @@ XenNet_Shutdown(
    1.41    IN NDIS_HANDLE MiniportAdapterContext
    1.42    )
    1.43  {
    1.44 -  struct xennet_info *xi = MiniportAdapterContext;
    1.45 +  UNREFERENCED_PARAMETER(MiniportAdapterContext);
    1.46  
    1.47    FUNCTION_CALLED();
    1.48  
    1.49 -  NdisMDeregisterInterrupt(&xi->interrupt);
    1.50 +  /* can't do this as shutdown might be called at DIRQL or higher */
    1.51 +  /* NdisMDeregisterInterrupt(&xi->interrupt); */
    1.52  }
    1.53  
    1.54  /* Opposite of XenNet_Init */
    1.55 @@ -646,8 +652,7 @@ XenNet_Halt(
    1.56    FUNCTION_ENTER();
    1.57    KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
    1.58  
    1.59 -  // Disables the interrupt
    1.60 -  XenNet_Shutdown(xi);
    1.61 +  NdisMDeregisterInterrupt(&xi->interrupt);
    1.62  
    1.63    xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
    1.64  
     2.1 --- a/xennet/xennet.h	Sun Nov 02 16:10:40 2008 +1100
     2.2 +++ b/xennet/xennet.h	Tue Nov 04 17:30:22 2008 +1100
     2.3 @@ -43,6 +43,11 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  #endif
     2.5  
     2.6  
     2.7 +#define VENDOR_DRIVER_VERSION_MAJOR 0
     2.8 +#define VENDOR_DRIVER_VERSION_MINOR 9
     2.9 +
    2.10 +#define VENDOR_DRIVER_VERSION (((VENDOR_DRIVER_VERSION_MAJOR) << 16) | (VENDOR_DRIVER_VERSION_MINOR))
    2.11 +
    2.12  #define __DRIVER_NAME "XenNet"
    2.13  
    2.14  #include <xen_windows.h>
    2.15 @@ -144,9 +149,10 @@ SET_NET_ULONG(PVOID ptr, ULONG data)
    2.16  #define MIN_LARGE_SEND_SEGMENTS 4
    2.17  
    2.18  /* TODO: crank this up if we support higher mtus? */
    2.19 -#define XN_DATA_SIZE 1500
    2.20  #define XN_HDR_SIZE 14
    2.21 -#define XN_MIN_PKT_SIZE 60
    2.22 +#define XN_MAX_DATA_SIZE 1500
    2.23 +#define XN_MIN_FRAME_SIZE 60
    2.24 +#define XN_MAX_FRAME_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
    2.25  /*
    2.26  #if !defined(OFFLOAD_LARGE_SEND)
    2.27    #define XN_MAX_PKT_SIZE (XN_HDR_SIZE + XN_DATA_SIZE)
     3.1 --- a/xennet/xennet_common.c	Sun Nov 02 16:10:40 2008 +1100
     3.2 +++ b/xennet/xennet_common.c	Tue Nov 04 17:30:22 2008 +1100
     3.3 @@ -53,9 +53,15 @@ XenNet_ParsePacketHeader(
     3.4        return PARSE_UNKNOWN_TYPE;
     3.5      }
     3.6      pi->ip4_header_length = (pi->header[XN_HDR_SIZE + 0] & 0x0F) << 2;
     3.7 -    if (header_length < (ULONG)(pi->ip4_header_length + 20))
     3.8 +    if (header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20))
     3.9      {
    3.10 -      KdPrint((__DRIVER_NAME "     first buffer is only %d bytes long, must be >= %d (1)\n", XN_HDR_SIZE + header_length, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)));
    3.11 +      int i;
    3.12 +      KdPrint((__DRIVER_NAME "     first buffer is only %d bytes long, must be >= %d (1)\n", header_length, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)));
    3.13 +      KdPrint((__DRIVER_NAME "     total_length = %d\n", pi->total_length));
    3.14 +      for (i = 0; i < pi->mdl_count; i++)
    3.15 +      {
    3.16 +        KdPrint((__DRIVER_NAME "     mdl %d length = %d\n", i, MmGetMdlByteCount(pi->mdls[i])));
    3.17 +      }
    3.18        // we need to do something conclusive here...
    3.19        return PARSE_TOO_SMALL;
    3.20      }
    3.21 @@ -76,9 +82,9 @@ XenNet_ParsePacketHeader(
    3.22    pi->ip4_length = GET_NET_PUSHORT(&pi->header[XN_HDR_SIZE + 2]);
    3.23    pi->tcp_header_length = (pi->header[XN_HDR_SIZE + pi->ip4_header_length + 12] & 0xf0) >> 2;
    3.24  
    3.25 -  if (header_length < (ULONG)(pi->ip4_header_length + 20)) // pi->tcp_header_length))
    3.26 +  if (header_length < (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + 20)) // pi->tcp_header_length))
    3.27    {
    3.28 -    KdPrint((__DRIVER_NAME "     first buffer is only %d bytes long, must be >= %d (2)\n", XN_HDR_SIZE + header_length, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)));
    3.29 +    KdPrint((__DRIVER_NAME "     first buffer is only %d bytes long, must be >= %d (2)\n", header_length, (ULONG)(XN_HDR_SIZE + pi->ip4_header_length + pi->tcp_header_length)));
    3.30      return PARSE_TOO_SMALL;
    3.31    }
    3.32  
     4.1 --- a/xennet/xennet_oid.c	Sun Nov 02 16:10:40 2008 +1100
     4.2 +++ b/xennet/xennet_oid.c	Tue Nov 04 17:30:22 2008 +1100
     4.3 @@ -40,6 +40,7 @@ NDIS_OID supported_oids[] =
     4.4    OID_GEN_CURRENT_PACKET_FILTER, // QS
     4.5    OID_GEN_CURRENT_LOOKAHEAD,     // QS
     4.6    OID_GEN_DRIVER_VERSION,        // Q
     4.7 +  OID_GEN_VENDOR_DRIVER_VERSION, // Q
     4.8    OID_GEN_MAXIMUM_TOTAL_SIZE,    // Q
     4.9    OID_GEN_PROTOCOL_OPTIONS,      // S
    4.10    OID_GEN_MAC_OPTIONS,           // Q
    4.11 @@ -56,12 +57,13 @@ NDIS_OID supported_oids[] =
    4.12    OID_802_3_CURRENT_ADDRESS,
    4.13    OID_802_3_MULTICAST_LIST,
    4.14    OID_802_3_MAXIMUM_LIST_SIZE,
    4.15 +  OID_802_3_RCV_ERROR_ALIGNMENT,
    4.16 +  OID_802_3_XMIT_ONE_COLLISION,
    4.17 +  OID_802_3_XMIT_MORE_COLLISIONS,
    4.18    /* tcp offload */
    4.19    OID_TCP_TASK_OFFLOAD,
    4.20  };
    4.21  
    4.22 -
    4.23 -
    4.24  /* return 4 or 8 depending on size of buffer */
    4.25  #define HANDLE_STAT_RETURN \
    4.26    {if (InformationBufferLength == 4) { \
    4.27 @@ -121,7 +123,7 @@ XenNet_QueryInformation(
    4.28        temp_data = NdisMedium802_3;
    4.29        break;
    4.30      case OID_GEN_MAXIMUM_LOOKAHEAD:
    4.31 -      temp_data = PAGE_SIZE; //XN_DATA_SIZE;
    4.32 +      temp_data = PAGE_SIZE;
    4.33        break;
    4.34      case OID_GEN_MAXIMUM_FRAME_SIZE:
    4.35        temp_data = xi->config_mtu;
    4.36 @@ -130,13 +132,10 @@ XenNet_QueryInformation(
    4.37        temp_data = 10000000; /* 1Gb */
    4.38        break;
    4.39      case OID_GEN_TRANSMIT_BUFFER_SPACE:
    4.40 -      /* pkts times sizeof ring, maybe? */
    4.41        /* multiply this by some small number as we can queue additional packets */
    4.42        temp_data = PAGE_SIZE * NET_TX_RING_SIZE * 4;
    4.43        break;
    4.44      case OID_GEN_RECEIVE_BUFFER_SPACE:
    4.45 -      /* pkts times sizeof ring, maybe? */
    4.46 -//      temp_data = XN_MAX_PKT_SIZE * NET_RX_RING_SIZE;
    4.47        temp_data = PAGE_SIZE * NET_RX_RING_SIZE;
    4.48        break;
    4.49      case OID_GEN_TRANSMIT_BLOCK_SIZE:
    4.50 @@ -156,15 +155,18 @@ XenNet_QueryInformation(
    4.51        temp_data = xi->packet_filter;
    4.52        break;
    4.53      case OID_GEN_CURRENT_LOOKAHEAD:
    4.54 -      // TODO: we should store this...
    4.55 -      temp_data = xi->config_max_pkt_size;
    4.56 +      temp_data = xi->config_mtu + XN_HDR_SIZE;
    4.57        break;
    4.58      case OID_GEN_DRIVER_VERSION:
    4.59        temp_data = (NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION;
    4.60        len = 2;
    4.61        break;
    4.62 +    case OID_GEN_VENDOR_DRIVER_VERSION:
    4.63 +      temp_data = VENDOR_DRIVER_VERSION;
    4.64 +      len = 4;
    4.65 +      break;
    4.66      case OID_GEN_MAXIMUM_TOTAL_SIZE:
    4.67 -      temp_data = xi->config_max_pkt_size;
    4.68 +      temp_data = xi->config_mtu + XN_HDR_SIZE;
    4.69        break;
    4.70      case OID_GEN_MAC_OPTIONS:
    4.71        temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | 
    4.72 @@ -209,6 +211,12 @@ XenNet_QueryInformation(
    4.73        data = xi->curr_mac_addr;
    4.74        len = ETH_ALEN;
    4.75        break;
    4.76 +    case OID_802_3_RCV_ERROR_ALIGNMENT:
    4.77 +    case OID_802_3_XMIT_ONE_COLLISION:
    4.78 +    case OID_802_3_XMIT_MORE_COLLISIONS:
    4.79 +      temp_data = 0;
    4.80 +      HANDLE_STAT_RETURN;
    4.81 +      break;
    4.82      case OID_802_3_MULTICAST_LIST:
    4.83        data = NULL;
    4.84        len = 0;
    4.85 @@ -289,8 +297,8 @@ XenNet_QueryInformation(
    4.86          nttic->V4Transmit.TcpChecksum = 1;
    4.87          nttic->V4Transmit.TcpOptionsSupported = 1;
    4.88          nttic->V4Transmit.UdpChecksum = 1;
    4.89 -        nttic->V4Receive.IpChecksum = 1;
    4.90 -        nttic->V4Receive.IpOptionsSupported = 1;
    4.91 +        nttic->V4Receive.IpChecksum = 0;
    4.92 +        nttic->V4Receive.IpOptionsSupported = 0;
    4.93          nttic->V4Receive.TcpChecksum = 1;
    4.94          nttic->V4Receive.TcpOptionsSupported = 1;
    4.95          nttic->V4Receive.UdpChecksum = 1;
    4.96 @@ -337,8 +345,7 @@ XenNet_QueryInformation(
    4.97          nttls->MinSegmentCount = MIN_LARGE_SEND_SEGMENTS;
    4.98          nttls->TcpOptions = TRUE;
    4.99          nttls->IpOptions = TRUE;
   4.100 -        KdPrint(("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions)));
   4.101 -        
   4.102 +        KdPrint(("&(nttls->IpOptions) = %p\n", &(nttls->IpOptions)));        
   4.103        }
   4.104  
   4.105        if (nto)
   4.106 @@ -391,8 +398,8 @@ XenNet_SetInformation(
   4.107    PULONG64 data = InformationBuffer;
   4.108    PNDIS_TASK_OFFLOAD_HEADER ntoh;
   4.109    PNDIS_TASK_OFFLOAD nto;
   4.110 -  PNDIS_TASK_TCP_IP_CHECKSUM nttic;
   4.111 -  PNDIS_TASK_TCP_LARGE_SEND nttls;
   4.112 +  PNDIS_TASK_TCP_IP_CHECKSUM nttic = NULL;
   4.113 +  PNDIS_TASK_TCP_LARGE_SEND nttls = NULL;
   4.114    int offset;
   4.115  
   4.116    //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.117 @@ -558,6 +565,18 @@ XenNet_SetInformation(
   4.118        KdPrint(("Set OID_TCP_TASK_OFFLOAD\n"));
   4.119        // we should disable everything here, then enable what has been set
   4.120        ntoh = (PNDIS_TASK_OFFLOAD_HEADER)InformationBuffer;
   4.121 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION)
   4.122 +      {
   4.123 +        KdPrint(("Invalid version (%d passed but must be %d)\n", ntoh->Version, NDIS_TASK_OFFLOAD_VERSION));
   4.124 +        status = NDIS_STATUS_INVALID_DATA;
   4.125 +        break;
   4.126 +      }
   4.127 +      if (ntoh->Version != NDIS_TASK_OFFLOAD_VERSION || ntoh->Size != sizeof(NDIS_TASK_OFFLOAD_HEADER))
   4.128 +      {
   4.129 +        KdPrint(("Invalid size (%d passed but must be %d)\n", ntoh->Size, sizeof(NDIS_TASK_OFFLOAD_HEADER)));
   4.130 +        status = NDIS_STATUS_INVALID_DATA;
   4.131 +        break;
   4.132 +      }
   4.133        *BytesRead = sizeof(NDIS_TASK_OFFLOAD_HEADER);
   4.134        offset = ntoh->OffsetFirstTask;
   4.135        nto = (PNDIS_TASK_OFFLOAD)ntoh; // not really, just to get the first offset right
   4.136 @@ -569,9 +588,8 @@ XenNet_SetInformation(
   4.137          {
   4.138          case TcpIpChecksumNdisTask:
   4.139            *BytesRead += sizeof(NDIS_TASK_TCP_IP_CHECKSUM);
   4.140 +          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   4.141            KdPrint(("TcpIpChecksumNdisTask\n"));
   4.142 -          nttic = (PNDIS_TASK_TCP_IP_CHECKSUM)nto->TaskBuffer;
   4.143 -          xi->setting_csum = *nttic;
   4.144            KdPrint(("  V4Transmit.IpOptionsSupported  = %d\n", nttic->V4Transmit.IpOptionsSupported));
   4.145            KdPrint(("  V4Transmit.TcpOptionsSupported = %d\n", nttic->V4Transmit.TcpOptionsSupported));
   4.146            KdPrint(("  V4Transmit.TcpChecksum         = %d\n", nttic->V4Transmit.TcpChecksum));
   4.147 @@ -590,22 +608,89 @@ XenNet_SetInformation(
   4.148            KdPrint(("  V6Receive.TcpOptionsSupported  = %d\n", nttic->V6Receive.TcpOptionsSupported));
   4.149            KdPrint(("  V6Receive.TcpChecksum          = %d\n", nttic->V6Receive.TcpChecksum));
   4.150            KdPrint(("  V6Receive.UdpChecksum          = %d\n", nttic->V6Receive.UdpChecksum));
   4.151 +          /* check for stuff we outright don't support */
   4.152 +          if (nttic->V6Transmit.IpOptionsSupported ||
   4.153 +            nttic->V6Transmit.TcpOptionsSupported ||
   4.154 +            nttic->V6Transmit.TcpChecksum ||
   4.155 +            nttic->V6Transmit.UdpChecksum ||
   4.156 +            nttic->V6Receive.IpOptionsSupported ||
   4.157 +            nttic->V6Receive.TcpOptionsSupported ||
   4.158 +            nttic->V6Receive.TcpChecksum ||
   4.159 +            nttic->V6Receive.UdpChecksum)
   4.160 +          {
   4.161 +            KdPrint(("IPv6 offload not supported\n"));
   4.162 +            status = NDIS_STATUS_INVALID_DATA;
   4.163 +            nttic = NULL;
   4.164 +            break;
   4.165 +          }
   4.166 +          if (nttic->V4Transmit.IpOptionsSupported ||
   4.167 +            nttic->V4Transmit.IpChecksum)
   4.168 +          {
   4.169 +            KdPrint(("IPv4 IP Transmit offload not supported\n"));
   4.170 +            status = NDIS_STATUS_INVALID_DATA;
   4.171 +            nttic = NULL;
   4.172 +            break;
   4.173 +          }
   4.174 +          if (nttic->V4Receive.IpOptionsSupported &&
   4.175 +            !nttic->V4Receive.IpChecksum)
   4.176 +          {
   4.177 +            KdPrint(("Invalid combination\n"));
   4.178 +            status = NDIS_STATUS_INVALID_DATA;
   4.179 +            nttic = NULL;
   4.180 +            break;
   4.181 +          }
   4.182 +          if (nttic->V4Transmit.TcpOptionsSupported &&
   4.183 +            !nttic->V4Transmit.TcpChecksum)
   4.184 +          {
   4.185 +            KdPrint(("Invalid combination\n"));
   4.186 +            status = NDIS_STATUS_INVALID_DATA;
   4.187 +            nttic = NULL;
   4.188 +            break;
   4.189 +          }
   4.190 +          if (nttic->V4Receive.TcpOptionsSupported &&
   4.191 +            !nttic->V4Receive.TcpChecksum)
   4.192 +          {
   4.193 +            KdPrint(("Invalid combination\n"));
   4.194 +            status = NDIS_STATUS_INVALID_DATA;
   4.195 +            nttic = NULL;
   4.196 +            break;
   4.197 +          }
   4.198            break;
   4.199          case TcpLargeSendNdisTask:
   4.200            *BytesRead += sizeof(NDIS_TASK_TCP_LARGE_SEND);
   4.201            KdPrint(("TcpLargeSendNdisTask\n"));
   4.202            nttls = (PNDIS_TASK_TCP_LARGE_SEND)nto->TaskBuffer;
   4.203 -          xi->setting_max_offload = nttls->MaxOffLoadSize;
   4.204 -          KdPrint(("  MaxOffLoadSize                 = %d\n", nttls->MaxOffLoadSize));
   4.205 -          KdPrint(("  MinSegmentCount                = %d\n", nttls->MinSegmentCount));
   4.206 -          KdPrint(("  TcpOptions                     = %d\n", nttls->TcpOptions));
   4.207 -          KdPrint(("  IpOptions                      = %d\n", nttls->IpOptions));
   4.208 +          KdPrint(("     MaxOffLoadSize                 = %d\n", nttls->MaxOffLoadSize));
   4.209 +          KdPrint(("     MinSegmentCount                = %d\n", nttls->MinSegmentCount));
   4.210 +          KdPrint(("     TcpOptions                     = %d\n", nttls->TcpOptions));
   4.211 +          KdPrint(("     IpOptions                      = %d\n", nttls->IpOptions));
   4.212 +          if (nttls->MinSegmentCount != MIN_LARGE_SEND_SEGMENTS)
   4.213 +          {
   4.214 +            KdPrint(("     MinSegmentCount should be %d\n", MIN_LARGE_SEND_SEGMENTS));
   4.215 +            status = NDIS_STATUS_INVALID_DATA;
   4.216 +            nttls = NULL;
   4.217 +            break;
   4.218 +          }
   4.219            break;
   4.220          default:
   4.221 -          KdPrint(("  Unknown Task %d\n", nto->Task));
   4.222 +          KdPrint(("     Unknown Task %d\n", nto->Task));
   4.223          }
   4.224          offset = nto->OffsetNextTask;
   4.225        }
   4.226 +      if (nttic != NULL)
   4.227 +        xi->setting_csum = *nttic;
   4.228 +      else
   4.229 +      {
   4.230 +        RtlZeroMemory(&xi->setting_csum, sizeof(NDIS_TASK_TCP_IP_CHECKSUM));
   4.231 +        KdPrint(("     csum offload disabled\n", nto->Task));
   4.232 +      }        
   4.233 +      if (nttls != NULL)
   4.234 +        xi->setting_max_offload = nttls->MaxOffLoadSize;
   4.235 +      else
   4.236 +      {
   4.237 +        xi->setting_max_offload = 0;
   4.238 +        KdPrint(("     LSO disabled\n", nto->Task));
   4.239 +      }
   4.240        break;
   4.241      default:
   4.242        KdPrint(("Set Unknown OID 0x%x\n", Oid));
     5.1 --- a/xennet/xennet_rx.c	Sun Nov 02 16:10:40 2008 +1100
     5.2 +++ b/xennet/xennet_rx.c	Tue Nov 04 17:30:22 2008 +1100
     5.3 @@ -101,6 +101,7 @@ get_packet_from_freelist(struct xennet_i
     5.4  static VOID
     5.5  put_packet_on_freelist(struct xennet_info *xi, PNDIS_PACKET packet)
     5.6  {
     5.7 +  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
     5.8    //ASSERT(!KeTestSpinLock(&xi->rx_lock));
     5.9  
    5.10    if (xi->rx_packet_free == NET_RX_RING_SIZE * 2)
    5.11 @@ -109,7 +110,13 @@ put_packet_on_freelist(struct xennet_inf
    5.12      NdisFreePacket(packet);
    5.13      return;
    5.14    }
    5.15 +/*
    5.16    NdisReinitializePacket(packet);
    5.17 +  RtlZeroMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(packet), sizeof(NDIS_PACKET_EXTENSION));
    5.18 +*/
    5.19 +  csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
    5.20 +    packet, TcpIpChecksumPacketInfo);
    5.21 +  csum_info->Value = 0;
    5.22    xi->rx_packet_list[xi->rx_packet_free] = packet;
    5.23    xi->rx_packet_free++;
    5.24  }
    5.25 @@ -152,7 +159,7 @@ XenNet_MakePacket(struct xennet_info *xi
    5.26      for (i = 0; i < xi->rxpi.mdl_count; i++)
    5.27        NdisChainBufferAtBack(packet, xi->rxpi.mdls[i]);
    5.28  
    5.29 -    NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo) = UlongToPtr(xi->rxpi.mss);
    5.30 +    //NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo) = UlongToPtr(xi->rxpi.mss);
    5.31  
    5.32      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
    5.33    }
    5.34 @@ -191,6 +198,30 @@ XenNet_MakePacket(struct xennet_info *xi
    5.35      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
    5.36    }
    5.37  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (%p)\n", packet));
    5.38 +
    5.39 +  if (1)
    5.40 +  {
    5.41 +    PMDL mdl;
    5.42 +    PVOID *addr;
    5.43 +    UINT buffer_length;
    5.44 +    UINT total_length;
    5.45 +    UINT calc_length = 0;
    5.46 +    NdisGetFirstBufferFromPacketSafe(packet, &mdl, &addr, &buffer_length, &total_length, NormalPagePriority);
    5.47 +    //KdPrint((__DRIVER_NAME "     total_length = %d\n", total_length));
    5.48 +    while (mdl)
    5.49 +    {
    5.50 +      NdisQueryBufferSafe(mdl, &addr, &buffer_length, NormalPagePriority);
    5.51 +      ASSERT(mdl != NULL);
    5.52 +      ASSERT(addr != NULL);
    5.53 +      ASSERT(buffer_length != 0);
    5.54 +      calc_length += buffer_length;
    5.55 +      NdisGetNextBuffer(mdl, &mdl);
    5.56 +    }
    5.57 +    ASSERT(calc_length == total_length);
    5.58 +  }
    5.59 +  // verify buffers
    5.60 +  // verify that total length == sum of buffer lengths
    5.61 +  
    5.62    return packet;
    5.63  }
    5.64  
    5.65 @@ -200,10 +231,12 @@ XenNet_MakePacket(struct xennet_info *xi
    5.66   same bridge in Dom0. Doh!
    5.67   This is only for TCP and UDP packets. IP checksums appear to be correct anyways.
    5.68  */
    5.69 -static VOID
    5.70 +
    5.71 +static BOOLEAN
    5.72  XenNet_SumPacketData(
    5.73 -  packet_info_t *pi,  
    5.74 -  PNDIS_PACKET packet
    5.75 +  packet_info_t *pi,
    5.76 +  PNDIS_PACKET packet,
    5.77 +  BOOLEAN set_csum
    5.78  )
    5.79  {
    5.80    USHORT i;
    5.81 @@ -239,10 +272,11 @@ XenNet_SumPacketData(
    5.82      break;
    5.83    default:
    5.84      KdPrint((__DRIVER_NAME "     Don't know how to calc sum for IP Proto %d\n", pi->ip_proto));
    5.85 -    return;
    5.86 +    return FALSE; // should never happen
    5.87    }
    5.88 -    
    5.89 -  *csum_ptr = 0;
    5.90 +
    5.91 +  if (set_csum)  
    5.92 +    *csum_ptr = 0;
    5.93  
    5.94    csum = 0;
    5.95    csum += GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 12]) + GET_NET_PUSHORT(&buffer[XN_HDR_SIZE + 14]); // src
    5.96 @@ -255,6 +289,9 @@ XenNet_SumPacketData(
    5.97  
    5.98    for (buffer_offset = i = XN_HDR_SIZE + pi->ip4_header_length; i < total_length - 1; i += 2, buffer_offset += 2)
    5.99    {
   5.100 +    /* don't include the checksum field itself in the calculation */
   5.101 +    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))
   5.102 +      continue;
   5.103      if (buffer_offset == buffer_length - 1) // deal with a buffer ending on an odd byte boundary
   5.104      {
   5.105        csum += (USHORT)buffer[buffer_offset] << 8;
   5.106 @@ -262,7 +299,7 @@ XenNet_SumPacketData(
   5.107        if (mdl == NULL)
   5.108        {
   5.109          KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   5.110 -        return;
   5.111 +        return FALSE; // should never happen
   5.112        }
   5.113        NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   5.114        csum += ((USHORT)buffer[0]);
   5.115 @@ -277,7 +314,7 @@ XenNet_SumPacketData(
   5.116          if (mdl == NULL)
   5.117          {
   5.118            KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   5.119 -          return;
   5.120 +          return FALSE; // should never happen
   5.121          }
   5.122          NdisQueryBufferSafe(mdl, (PVOID) &buffer, &buffer_length, NormalPagePriority);
   5.123          buffer_offset = 0;
   5.124 @@ -291,8 +328,13 @@ XenNet_SumPacketData(
   5.125    }
   5.126    while (csum & 0xFFFF0000)
   5.127      csum = (csum & 0xFFFF) + (csum >> 16);
   5.128 -  *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
   5.129 +  
   5.130 +  if (set_csum)
   5.131 +    *csum_ptr = (USHORT)~GET_NET_USHORT((USHORT)csum);
   5.132 +  else
   5.133 +    return (BOOLEAN)(*csum_ptr == (USHORT)~GET_NET_USHORT((USHORT)csum));
   5.134  
   5.135 +  return TRUE;
   5.136  //  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   5.137  }
   5.138  
   5.139 @@ -308,10 +350,11 @@ XenNet_MakePackets(
   5.140    PLIST_ENTRY entry;
   5.141    UCHAR psh;
   5.142    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   5.143 +  ULONG parse_result;  
   5.144  
   5.145  //  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "(packets = %p, packet_count = %d)\n", packets, *packet_count_p));
   5.146  
   5.147 -  XenNet_ParsePacketHeader(&xi->rxpi);
   5.148 +  parse_result = XenNet_ParsePacketHeader(&xi->rxpi);
   5.149    switch (xi->rxpi.ip_proto)
   5.150    {
   5.151    case 6:  // TCP
   5.152 @@ -327,13 +370,63 @@ XenNet_MakePackets(
   5.153        packet_count = 0;
   5.154        goto done;
   5.155      }
   5.156 -    if (xi->rxpi.csum_blank)
   5.157 -      XenNet_SumPacketData(&xi->rxpi, packet);
   5.158 -    if (xi->rxpi.csum_blank || xi->rxpi.data_validated)
   5.159 +    if (parse_result == PARSE_OK)
   5.160      {
   5.161 +      if (xi->rxpi.csum_blank)
   5.162 +        XenNet_SumPacketData(&xi->rxpi, packet, TRUE);
   5.163        csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   5.164          packet, TcpIpChecksumPacketInfo);
   5.165 -      csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.166 +      if (xi->rxpi.csum_blank || xi->rxpi.data_validated)
   5.167 +      {
   5.168 +        if (xi->setting_csum.V4Receive.TcpChecksum && xi->rxpi.ip_proto == 6)
   5.169 +          csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.170 +        if (xi->setting_csum.V4Receive.UdpChecksum && xi->rxpi.ip_proto == 17)
   5.171 +          csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
   5.172 +      }
   5.173 +      else
   5.174 +      {
   5.175 +        if (xi->setting_csum.V4Receive.TcpChecksum && xi->rxpi.ip_proto == 6)
   5.176 +        {
   5.177 +          if (XenNet_SumPacketData(&xi->rxpi, packet, FALSE))
   5.178 +            csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.179 +          else
   5.180 +            csum_info->Receive.NdisPacketTcpChecksumFailed = TRUE;
   5.181 +        }
   5.182 +        if (xi->setting_csum.V4Receive.UdpChecksum && xi->rxpi.ip_proto == 17)
   5.183 +        {
   5.184 +          if (XenNet_SumPacketData(&xi->rxpi, packet, FALSE))
   5.185 +            csum_info->Receive.NdisPacketUdpChecksumSucceeded = TRUE;
   5.186 +          else
   5.187 +            csum_info->Receive.NdisPacketUdpChecksumFailed = TRUE;
   5.188 +        }
   5.189 +      }
   5.190 +#if 0      
   5.191 +      if (xi->rxpi.ip_proto == 17)
   5.192 +      {
   5.193 +        PMDL mdl;
   5.194 +        PVOID *addr;
   5.195 +        UINT buffer_length;
   5.196 +        UINT total_length;
   5.197 +        UINT calc_length = 0;
   5.198 +        NdisGetFirstBufferFromPacketSafe(packet, &mdl, &addr, &buffer_length, &total_length, NormalPagePriority);
   5.199 +        KdPrint((__DRIVER_NAME "     packet = %p\n", packet));
   5.200 +        KdPrint((__DRIVER_NAME "     total_length = %d\n", total_length));
   5.201 +        while (mdl)
   5.202 +        {
   5.203 +          NdisQueryBufferSafe(mdl, &addr, &buffer_length, NormalPagePriority);
   5.204 +          ASSERT(mdl != NULL);
   5.205 +          ASSERT(addr != NULL);
   5.206 +          ASSERT(buffer_length != 0);
   5.207 +          calc_length += buffer_length;
   5.208 +          KdPrint((__DRIVER_NAME "     mdl = %p\n", mdl));
   5.209 +          KdPrint((__DRIVER_NAME "     addr = %p\n", addr));
   5.210 +          KdPrint((__DRIVER_NAME "     buffer_length = %d\n", buffer_length));
   5.211 +          KdPrint((__DRIVER_NAME "     calc_length = %d\n", calc_length));
   5.212 +          NdisGetNextBuffer(mdl, &mdl);
   5.213 +        }
   5.214 +        ASSERT(calc_length == total_length);
   5.215 +      }      
   5.216 +#endif
   5.217      }
   5.218      entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   5.219      InsertTailList(rx_packet_list, entry);
   5.220 @@ -375,9 +468,12 @@ XenNet_MakePackets(
   5.221        xi->stat_rx_no_buffer++;
   5.222        break; /* we are out of memory - just drop the packets */
   5.223      }
   5.224 -    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   5.225 -      packet, TcpIpChecksumPacketInfo);
   5.226 -    csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.227 +    if (xi->setting_csum.V4Receive.TcpChecksum)
   5.228 +    {
   5.229 +      csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
   5.230 +        packet, TcpIpChecksumPacketInfo);
   5.231 +      csum_info->Receive.NdisPacketTcpChecksumSucceeded = TRUE;
   5.232 +    }
   5.233      if (psh)
   5.234      {
   5.235        NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
   5.236 @@ -390,7 +486,7 @@ XenNet_MakePackets(
   5.237          buffer[XN_HDR_SIZE + xi->rxpi.ip4_header_length + 13] |= 8;
   5.238        }
   5.239      }
   5.240 -    XenNet_SumPacketData(&xi->rxpi, packet);
   5.241 +    XenNet_SumPacketData(&xi->rxpi, packet, TRUE);
   5.242      entry = (PLIST_ENTRY)&packet->MiniportReservedEx[sizeof(PVOID)];
   5.243      InsertTailList(rx_packet_list, entry);
   5.244      packet_count++;
   5.245 @@ -487,8 +583,41 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.246            if (rxrsp->flags & NETRXF_data_validated)
   5.247              xi->rxpi.data_validated = TRUE;
   5.248          }
   5.249 -        NdisAdjustBufferLength(mdl, rxrsp->status);
   5.250 -        xi->rxpi.mdls[xi->rxpi.mdl_count++] = mdl;
   5.251 +        
   5.252 +        if (!xi->rxpi.mdl_count || MmGetMdlByteCount(xi->rxpi.mdls[xi->rxpi.mdl_count - 1]) == PAGE_SIZE)
   5.253 +        {
   5.254 +          /* first buffer or no room in current buffer */
   5.255 +          NdisAdjustBufferLength(mdl, rxrsp->status);
   5.256 +          xi->rxpi.mdls[xi->rxpi.mdl_count++] = mdl;
   5.257 +        }
   5.258 +        else if (MmGetMdlByteCount(xi->rxpi.mdls[xi->rxpi.mdl_count - 1]) + rxrsp->status <= PAGE_SIZE)
   5.259 +        {
   5.260 +          /* this buffer fits entirely in current buffer */
   5.261 +          PMDL dst_mdl = xi->rxpi.mdls[xi->rxpi.mdl_count - 1];
   5.262 +          PUCHAR dst_addr = MmGetMdlVirtualAddress(dst_mdl);
   5.263 +          PUCHAR src_addr = MmGetMdlVirtualAddress(mdl);
   5.264 +          dst_addr += MmGetMdlByteCount(dst_mdl);
   5.265 +          memcpy(dst_addr, src_addr, rxrsp->status);
   5.266 +          NdisAdjustBufferLength(dst_mdl, MmGetMdlByteCount(dst_mdl) + rxrsp->status);
   5.267 +          XenFreelist_PutPage(&xi->rx_freelist, mdl);
   5.268 +        }
   5.269 +        else
   5.270 +        {
   5.271 +          /* this buffer doesn't fit entirely in current buffer */
   5.272 +          PMDL dst_mdl = xi->rxpi.mdls[xi->rxpi.mdl_count - 1];
   5.273 +          PUCHAR dst_addr = MmGetMdlVirtualAddress(dst_mdl);
   5.274 +          PUCHAR src_addr = MmGetMdlVirtualAddress(mdl);
   5.275 +          ULONG copy_size = PAGE_SIZE - MmGetMdlByteCount(dst_mdl);
   5.276 +          dst_addr += MmGetMdlByteCount(dst_mdl);
   5.277 +          memcpy(dst_addr, src_addr, copy_size);
   5.278 +          NdisAdjustBufferLength(dst_mdl, PAGE_SIZE);
   5.279 +          dst_addr = src_addr;
   5.280 +          src_addr += copy_size;
   5.281 +          copy_size = rxrsp->status - copy_size;
   5.282 +          memmove(dst_addr, src_addr, copy_size); /* use memmove because the regions overlap */
   5.283 +          NdisAdjustBufferLength(mdl, copy_size);
   5.284 +          xi->rxpi.mdls[xi->rxpi.mdl_count++] = mdl;
   5.285 +        }
   5.286          xi->rxpi.extra_info = (BOOLEAN)!!(rxrsp->flags & NETRXF_extra_info);
   5.287          xi->rxpi.more_frags = (BOOLEAN)!!(rxrsp->flags & NETRXF_more_data);
   5.288          xi->rxpi.total_length = xi->rxpi.total_length + rxrsp->status;
   5.289 @@ -516,7 +645,13 @@ XenNet_RxBufferCheck(struct xennet_info 
   5.290    packet_count = 0;
   5.291    while (entry != &rx_packet_list)
   5.292    {
   5.293 -    packets[packet_count++] = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   5.294 +    PNDIS_PACKET packet = CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)]);
   5.295 +    PVOID *addr;
   5.296 +    UINT buffer_length;
   5.297 +    UINT total_length;
   5.298 +    NdisGetFirstBufferFromPacketSafe(packet, &mdl, &addr, &buffer_length, &total_length, NormalPagePriority);
   5.299 +    ASSERT(total_length <= xi->config_mtu + XN_HDR_SIZE);
   5.300 +    packets[packet_count++] = packet;
   5.301      entry = RemoveHeadList(&rx_packet_list);
   5.302      if (packet_count == MAXIMUM_PACKETS_PER_INDICATE || entry == &rx_packet_list)
   5.303      {
     6.1 --- a/xennet/xennet_tx.c	Sun Nov 02 16:10:40 2008 +1100
     6.2 +++ b/xennet/xennet_tx.c	Tue Nov 04 17:30:22 2008 +1100
     6.3 @@ -103,7 +103,7 @@ XenNet_HWSendPacket(struct xennet_info *
     6.4    struct netif_extra_info *ei = NULL;
     6.5    PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
     6.6    //UINT total_packet_length;
     6.7 -  ULONG mss;
     6.8 +  ULONG mss = 0;
     6.9    PMDL in_mdl;
    6.10    PUCHAR in_buffer = NULL;
    6.11    PUCHAR out_buffer;
    6.12 @@ -133,14 +133,69 @@ XenNet_HWSendPacket(struct xennet_info *
    6.13      KdPrint((__DRIVER_NAME "     Zero length packet\n"));
    6.14      return TRUE; // we don't want to see this packet again...
    6.15    }  
    6.16 +
    6.17 +  if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) == NDIS_PROTOCOL_ID_TCP_IP)
    6.18 +  {
    6.19 +    csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
    6.20 +      packet, TcpIpChecksumPacketInfo);
    6.21 +    if (csum_info->Transmit.NdisPacketChecksumV6)
    6.22 +    {
    6.23 +      KdPrint((__DRIVER_NAME "     NdisPacketChecksumV6 not supported\n"));
    6.24 +      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.25 +      return TRUE;
    6.26 +    }
    6.27 +
    6.28 +    if (csum_info->Transmit.NdisPacketChecksumV4)
    6.29 +    {
    6.30 +      if (csum_info->Transmit.NdisPacketIpChecksum && !xi->setting_csum.V4Transmit.IpChecksum)
    6.31 +      {
    6.32 +        KdPrint((__DRIVER_NAME "     IpChecksum not enabled\n"));
    6.33 +        NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.34 +        return TRUE;
    6.35 +      }
    6.36 +      if (csum_info->Transmit.NdisPacketTcpChecksum && !xi->setting_csum.V4Transmit.TcpChecksum)
    6.37 +      {
    6.38 +        KdPrint((__DRIVER_NAME "     TcpChecksum not enabled\n"));
    6.39 +        NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.40 +        return TRUE;
    6.41 +      }
    6.42 +      if (csum_info->Transmit.NdisPacketUdpChecksum && !xi->setting_csum.V4Transmit.UdpChecksum)
    6.43 +      {
    6.44 +        KdPrint((__DRIVER_NAME "     UdpChecksum not enabled\n"));
    6.45 +        NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.46 +        return TRUE;
    6.47 +      }
    6.48 +      if (csum_info->Transmit.NdisPacketTcpChecksum
    6.49 +        || csum_info->Transmit.NdisPacketUdpChecksum)
    6.50 +      {
    6.51 +        flags |= NETTXF_csum_blank | NETTXF_data_validated;
    6.52 +      }
    6.53 +    }
    6.54 +  }
    6.55      
    6.56 -  csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(
    6.57 -    packet, TcpIpChecksumPacketInfo);
    6.58    mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packet, TcpLargeSendPacketInfo));
    6.59  
    6.60    if (mss)
    6.61 +  {
    6.62 +    if (NDIS_GET_PACKET_PROTOCOL_TYPE(packet) != NDIS_PROTOCOL_ID_TCP_IP)
    6.63 +    {
    6.64 +      KdPrint((__DRIVER_NAME "     mss specified when packet is not NDIS_PROTOCOL_ID_TCP_IP\n"));
    6.65 +    }
    6.66      ndis_lso = TRUE;
    6.67 +    if (mss > xi->setting_max_offload)
    6.68 +    {
    6.69 +      KdPrint((__DRIVER_NAME "     Requested MSS (%d) larger than allowed MSS (%d)\n", mss, xi->setting_max_offload));
    6.70 +      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.71 +      return TRUE;
    6.72 +    }
    6.73 +  }
    6.74  
    6.75 +  if (!mss && total_length > xi->config_mtu + XN_HDR_SIZE)
    6.76 +  {
    6.77 +    KdPrint((__DRIVER_NAME "     Packet size (%d) larger than MTU (%d) + header (%d). mss = %d\n", total_length, xi->config_mtu, XN_HDR_SIZE, mss));
    6.78 +    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_FAILURE);
    6.79 +    return TRUE;
    6.80 +  }
    6.81    pages_required = (total_length + PAGE_SIZE - 1) / PAGE_SIZE;
    6.82  
    6.83    if (pages_required + !!ndis_lso > (int)free_requests(xi))
    6.84 @@ -185,23 +240,45 @@ XenNet_HWSendPacket(struct xennet_info *
    6.85          in_mdl = in_mdl->Next;
    6.86      }
    6.87    }
    6.88 -  ASSERT(!in_mdl);
    6.89 -
    6.90 -  if (csum_info->Transmit.NdisPacketTcpChecksum
    6.91 -    || csum_info->Transmit.NdisPacketUdpChecksum)
    6.92 +  /* consume any zero length buffers tacked on the end */
    6.93 +  while (in_mdl && MmGetMdlByteCount(in_mdl) == 0)
    6.94 +    in_mdl = in_mdl->Next;
    6.95 +    
    6.96 +  if (in_mdl)
    6.97    {
    6.98 -    flags |= NETTXF_csum_blank | NETTXF_data_validated;
    6.99 +    KdPrint((__DRIVER_NAME "     Something went wrong... analyzing\n"));
   6.100 +    NdisGetFirstBufferFromPacketSafe(packet, &in_mdl, &pi.header, &first_buffer_length, &total_length, NormalPagePriority);
   6.101 +    KdPrint((__DRIVER_NAME "     total_length = %d\n", total_length));
   6.102 +    while (in_mdl)
   6.103 +    {
   6.104 +      KdPrint((__DRIVER_NAME "     in_mdl = %p\n", in_mdl));
   6.105 +      KdPrint((__DRIVER_NAME "     MmGetSystemAddressForMdlSafe(in_mdl) = %p\n", MmGetSystemAddressForMdlSafe(in_mdl, LowPagePriority)));
   6.106 +      KdPrint((__DRIVER_NAME "     MmGetMdlByteCount(in_mdl) = %d\n", MmGetMdlByteCount(in_mdl)));
   6.107 +      in_mdl = in_mdl->Next;
   6.108 +    }
   6.109 +    ASSERT(FALSE);
   6.110    }
   6.111  
   6.112    if (ndis_lso)
   6.113    {
   6.114 -    XenNet_ParsePacketHeader(&pi);
   6.115 -    XenNet_SumIpHeader(MmGetSystemAddressForMdlSafe(pi.mdls[0], NormalPagePriority), pi.ip4_header_length);
   6.116 -    flags |= NETTXF_csum_blank | NETTXF_data_validated; /* these may be implied but not specified when lso is used*/
   6.117 -    if (pi.tcp_length >= mss)
   6.118 +    ULONG parse_result = XenNet_ParsePacketHeader(&pi);
   6.119 +    if (parse_result == PARSE_OK)
   6.120      {
   6.121 -      flags |= NETTXF_extra_info;
   6.122 -      xen_gso = TRUE;
   6.123 +      XenNet_SumIpHeader(MmGetSystemAddressForMdlSafe(pi.mdls[0], NormalPagePriority), pi.ip4_header_length);
   6.124 +      flags |= NETTXF_csum_blank | NETTXF_data_validated; /* these may be implied but not specified when lso is used*/
   6.125 +      if (pi.tcp_length >= mss)
   6.126 +      {
   6.127 +        flags |= NETTXF_extra_info;
   6.128 +        xen_gso = TRUE;
   6.129 +      }
   6.130 +      else
   6.131 +      {
   6.132 +        KdPrint((__DRIVER_NAME "     large send specified when tcp_length < mss\n"));
   6.133 +      }
   6.134 +    }
   6.135 +    else
   6.136 +    {
   6.137 +        KdPrint((__DRIVER_NAME "     could not parse packet - no large send offload done\n"));
   6.138      }
   6.139    }
   6.140  
   6.141 @@ -248,6 +325,7 @@ XenNet_HWSendPacket(struct xennet_info *
   6.142  
   6.143    xi->stat_tx_ok++;
   6.144  
   6.145 +  NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   6.146    return TRUE;
   6.147  }
   6.148  
   6.149 @@ -308,7 +386,7 @@ XenNet_ReturnSentPackets(struct xennet_i
   6.150      {
   6.151        KeReleaseSpinLockFromDpcLevel(&xi->tx_lock);
   6.152        for (i = 0; i < packet_index; i++)
   6.153 -        NdisMSendComplete(xi->adapter_handle, packets[i], NDIS_STATUS_SUCCESS);
   6.154 +        NdisMSendComplete(xi->adapter_handle, packets[i], NDIS_GET_PACKET_STATUS(packets[i]));
   6.155        if (entry != &xi->tx_sent_pkt_list) /* don't acquire the lock if we have no more packets to SendComplete */
   6.156          KeAcquireSpinLockAtDpcLevel(&xi->tx_lock);
   6.157        packet_index = 0;