win-pvdrivers

changeset 219:6974a4ace9d3

rx still not working but getting there
author James Harper <james.harper@bendigoit.com.au>
date Sat Mar 22 16:57:29 2008 +1100 (2008-03-22)
parents c33404027885
children d076e1ed8071
files xennet/xennet.h xennet/xennet_rx.c
line diff
     1.1 --- a/xennet/xennet.h	Fri Mar 21 20:40:03 2008 +1100
     1.2 +++ b/xennet/xennet.h	Sat Mar 22 16:57:29 2008 +1100
     1.3 @@ -94,11 +94,30 @@ Foundation, Inc., 51 Franklin Street, Fi
     1.4  #define XN_VENDOR_DESC "Xensource"
     1.5  #define MAX_XENBUS_STR_LEN 128
     1.6  
     1.7 -
     1.8  #define RX_MIN_TARGET 8
     1.9  #define RX_DFL_MIN_TARGET 128
    1.10  #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
    1.11  
    1.12 +#define MAX_BUFFERS_PER_PACKET 32
    1.13 +
    1.14 +
    1.15 +typedef struct {
    1.16 +  PNDIS_BUFFER mdls[MAX_BUFFERS_PER_PACKET];
    1.17 +  ULONG mdl_count;
    1.18 +  USHORT mss;
    1.19 +  NDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
    1.20 +  BOOLEAN csum_calc_required;
    1.21 +  BOOLEAN split_required;
    1.22 +  UCHAR ip_version;
    1.23 +  USHORT total_length;
    1.24 +  USHORT ip4_header_length;
    1.25 +  USHORT ip4_length;
    1.26 +  USHORT tcp_header_length;
    1.27 +  USHORT tcp_length;
    1.28 +  BOOLEAN extra_info;
    1.29 +  BOOLEAN more_frags;
    1.30 +} rx_packet_info_t;
    1.31 +
    1.32  struct xennet_info
    1.33  {
    1.34    /* Base device vars */
    1.35 @@ -154,10 +173,14 @@ struct xennet_info
    1.36    PNDIS_BUFFER rx_buffers[NET_RX_RING_SIZE];
    1.37    PMDL page_list[NET_RX_RING_SIZE];
    1.38    ULONG page_free;
    1.39 +
    1.40 +  rx_packet_info_t rx;
    1.41 +/*
    1.42    PNDIS_PACKET rx_current_packet;
    1.43    PMDL rx_first_mdl;
    1.44    USHORT rx_extra_info;
    1.45    USHORT rx_first_buffer_length;
    1.46 +*/
    1.47  
    1.48    /* Receive-ring batched refills. */
    1.49    ULONG rx_target;
     2.1 --- a/xennet/xennet_rx.c	Fri Mar 21 20:40:03 2008 +1100
     2.2 +++ b/xennet/xennet_rx.c	Sat Mar 22 16:57:29 2008 +1100
     2.3 @@ -145,110 +145,65 @@ XenNet_RxBufferAlloc(struct xennet_info 
     2.4    return NDIS_STATUS_SUCCESS;
     2.5  }
     2.6  
     2.7 -static VOID
     2.8 -XenNet_SplitRxPacket(
     2.9 - PNDIS_PACKET *packets,
    2.10 - PULONG packet_count,
    2.11 - ULONG total_packet_length
    2.12 -)
    2.13 -{
    2.14 -  ULONG mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[*packet_count], TcpLargeSendPacketInfo));
    2.15 -  ULONG header_length = 54; //TODO: actually calculate this from the TCP header
    2.16 -  ULONG tcp_length = total_packet_length - header_length;
    2.17 -  ULONG remaining = tcp_length;
    2.18 -
    2.19 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.20 -
    2.21 -  KdPrint((__DRIVER_NAME "     mss = %d\n", mss));
    2.22 -
    2.23 -  while (remaining)
    2.24 -  {
    2.25 -    // take the buffers off of the current packet
    2.26 -    KdPrint((__DRIVER_NAME "     Remaining = %d\n", remaining));
    2.27 -
    2.28 -    if (remaining > mss)
    2.29 -    {
    2.30 -      // tcp length = mss;
    2.31 -      remaining -= mss;
    2.32 -    }
    2.33 -    else
    2.34 -    {
    2.35 -      // tcp length = remaining
    2.36 -      remaining = 0;
    2.37 -    }
    2.38 -    // do some creative stuff here... clone the header of the previous packet and update the various fields
    2.39 -    // append the remaining data buffers
    2.40 -    // increment the packet count
    2.41 -  }
    2.42 -
    2.43 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    2.44 -
    2.45 -  return;
    2.46 -}
    2.47 -
    2.48  #define __NET_USHORT_BYTE_0(x) ((USHORT)(x & 0xFF))
    2.49  #define __NET_USHORT_BYTE_1(x) ((USHORT)((PUCHAR)&x)[1] & 0xFF)
    2.50  #define NET_USHORT(x) ((__NET_USHORT_BYTE_0(x) << 8) | __NET_USHORT_BYTE_1(x))
    2.51  
    2.52  static VOID
    2.53 -XenNet_SplitLargePackets(
    2.54 -  PNDIS_PACKET *packets,
    2.55 -  ULONG packet_count,
    2.56 -  PULONG new_packets,
    2.57 -  USHORT ip4_length,
    2.58 -  USHORT ip4_header_length,
    2.59 -  USHORT tcp_header_length
    2.60 +XenNet_ParseHeader(
    2.61 +  struct xennet_info *xi
    2.62  )
    2.63  {
    2.64 -  PUCHAR header;
    2.65 -  PNDIS_PACKET first_packet;
    2.66 -  PNDIS_PACKET curr_packet;
    2.67 -
    2.68 -  new_packets = 0;
    2.69 -
    2.70 -  header = buffer;
    2.71 -  remaining = ip4_length - ip4_header_length - tcp_header_length;
    2.72 -  // save psh status of packet
    2.73 -  while (remaining)
    2.74 -  {
    2.75 -    *((PUSHORT)&buffer[XN_HDR_SIZE + 2]) = NET_USHORT(mss);
    2.76 -    tcp_length = min(remaining, mss);
    2.77 -    remaining -= tcp_length;
    2.78 -
    2.79 -      // clear psh of old packet
    2.80 -
    2.81 -    NdisAllocatePacket(&status, &packets[packet_count + 1], xi->packet_pool);
    2.82 -    ASSERT(status == NDIS_STATUS_SUCCESS);
    2.83 -    NDIS_SET_PACKET_HEADER_SIZE(packets[packet_count + 1], XN_HDR_SIZE);
    2.84 +  USHORT i;
    2.85 +  PUCHAR buffer;
    2.86 +  PMDL mdl;
    2.87 +  UINT total_length;
    2.88 +  UINT buffer_length;
    2.89  
    2.90 -    new_buffer_mdl = get_page_from_freelist(xi);
    2.91 -    new_buffer = MmGetMdlVirtualAddress(new_buffer_mdl);
    2.92 -    memcpy(new_buffer, buffer, XN_HDR_SIZE + ip4_header_length + tcp_header_length);
    2.93 -    *((PUSHORT)&new_header[XN_HDR_SIZE + 2]) = NET_USHORT(tcp_length);
    2.94 -    // fix tcp sequence of new packet
    2.95 -    new_remaining = tcp_length;
    2.96 -    while (new_remaining > 0)
    2.97 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.98 +
    2.99 +  ASSERT(!xi->rx.mdls[0]);
   2.100 +  
   2.101 +  NdisQueryBuffer(xi->rx.mdls[0], &buffer, &buffer_length);
   2.102 +
   2.103 +  if (buffer_length < XN_HDR_SIZE + 20 + 20) // minimum size of first buffer is ETH + IP + TCP header
   2.104 +  {
   2.105 +    KdPrint((__DRIVER_NAME "     %d is not enough data for the first buffer\n", buffer_length));
   2.106 +    return;
   2.107 +  }
   2.108 +  
   2.109 +  switch (NET_USHORT(buffer[12])) // L2 protocol field
   2.110 +  {
   2.111 +  case 0x0800:
   2.112 +    ip_version = (buffer[XN_HDR_SIZE + 0] & 0xF0) >> 4;
   2.113 +    if (xi->rx.ip_version != 4)
   2.114      {
   2.115 -         
   2.116 -      if (buffer_offset != 0)
   2.117 -      {
   2.118 -        new_buffer = 
   2.119 -        // allocate a new buffer
   2.120 -        // copy remaining data to new buffer
   2.121 -        // set length of current buffer
   2.122 -        // set length of new buffer
   2.123 -      }
   2.124 -
   2.125 -// I was up to here...
   2.126 -      NdisUnchainBufferAtBack(packets[packet_count], &mdl);
   2.127 -      NdisChainBufferAtFront(packets[packet_count + 1], mdl);
   2.128 -      NdisChainBufferAtFront(packets[packet_count + 1], new_header_mdl);
   2.129 -      
   2.130 -      
   2.131 -      // copy all buffers to new packet
   2.132 -      packet_count++;
   2.133 +      KdPrint((__DRIVER_NAME "     ip_version = %d\n", xi->rx.ip_version));
   2.134 +      return;
   2.135      }
   2.136 -    // restore psh status to last packet
   2.137 +    xi->rx.ip4_header_length = (buffer[XN_HDR_SIZE + 0] & 0x0F) << 2;
   2.138 +    if (buffer_length < (ULONG)(xi->rx.ip4_header_length + 20))
   2.139 +    {
   2.140 +      KdPrint((__DRIVER_NAME "     first packet is only %d long, must be >= %d\n", XN_HDR_SIZE + buffer_length, (ULONG)(XN_HDR_SIZE + xi->rx.ip4_header_length + 20)));
   2.141 +      return;
   2.142 +    }
   2.143 +    break;
   2.144 +  default:
   2.145 +    KdPrint((__DRIVER_NAME "     Not IP\n"));
   2.146 +    return;
   2.147 +  }
   2.148 +  xi->rx.ip4_proto = buffer[XN_HDR_SIZE + 9];
   2.149 +  switch (xi->rx.ip4_proto)
   2.150 +  {
   2.151 +  case 6:  // TCP
   2.152 +  case 17: // UDP
   2.153 +    break;
   2.154 +  default:
   2.155 +    KdPrint((__DRIVER_NAME "     Not TCP or UDP\n"));
   2.156 +    return;
   2.157 +  }
   2.158 +  xi->rx.ip4_length = NET_USHORT(buffer[XN_HDR_SIZE + 2]);
   2.159 +  xi->rx.tcp_header_length = (buffer[XN_HDR_SIZE + xi->rx.ip4_header_length + 12] & 0xf0) >> 2;
   2.160  }
   2.161  
   2.162  /*
   2.163 @@ -269,76 +224,21 @@ XenNet_SumData(
   2.164    UINT buffer_length;
   2.165    ULONG csum, pre_csum;
   2.166    PUSHORT csum_ptr;
   2.167 -  UCHAR ip_version;
   2.168 -  USHORT ip4_header_length;
   2.169 -  USHORT ip4_length;
   2.170 -  USHORT tcp_header_length;
   2.171 -  USHORT tcp_length;
   2.172 -  USHORT buffer_offset;
   2.173 -  USHORT mss;
   2.174    PNDIS_PACKET packet;
   2.175  
   2.176    KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.177  
   2.178    mss = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo);
   2.179    NdisGetFirstBufferFromPacketSafe(packet, &mdl, &buffer, &buffer_length, &total_length, NormalPagePriority);
   2.180 -  if (mdl == NULL)
   2.181 -  {
   2.182 -    KdPrint((__DRIVER_NAME "     Cannot get first buffer\n"));
   2.183 -    return;
   2.184 -  }
   2.185 +  ASSERT(mdl);
   2.186  
   2.187 -  if (buffer_length < XN_HDR_SIZE + 20 + 20) // minimum size of ETH + IP + TCP header
   2.188 -  {
   2.189 -    KdPrint((__DRIVER_NAME "     %d is not enough data for the first buffer\n", buffer_length));
   2.190 -    return;
   2.191 -  }
   2.192 -  
   2.193 -  switch (NET_USHORT(buffer[12])) // L2 protocol field
   2.194 -  {
   2.195 -  case 0x0800:
   2.196 -    ip_version = (buffer[XN_HDR_SIZE + 0] & 0xF0) >> 4;
   2.197 -    if (ip_version != 4)
   2.198 -    {
   2.199 -      KdPrint((__DRIVER_NAME "     ip_version = %d\n", ip_version));
   2.200 -      return;
   2.201 -    }
   2.202 -    ip4_header_length = (buffer[XN_HDR_SIZE + 0] & 0x0F) << 2;
   2.203 -    if (buffer_length < (ULONG)(ip4_header_length + 20))
   2.204 -    {
   2.205 -      KdPrint((__DRIVER_NAME "     first packet is only %d long, must be >= %d\n", XN_HDR_SIZE + buffer_length, (ULONG)(XN_HDR_SIZE + ip4_header_length + 20)));
   2.206 -      return;
   2.207 -    }
   2.208 -    break;
   2.209 -  default:
   2.210 -    KdPrint((__DRIVER_NAME "     Not IP\n"));
   2.211 -    return;
   2.212 -  }
   2.213 -  switch (buffer[XN_HDR_SIZE + 9])
   2.214 -  {
   2.215 -  case 6:  // TCP
   2.216 -  case 17: // UDP
   2.217 -    break;
   2.218 -  default:
   2.219 -    KdPrint((__DRIVER_NAME "     Not TCP or UDP\n"));
   2.220 -    return;
   2.221 -  }
   2.222 -  ip4_length = NET_USHORT(buffer[XN_HDR_SIZE + 2]);
   2.223 -  tcp_header_length = (buffer[XN_HDR_SIZE + ip4_header_length + 12] & 0xf0) >> 2;
   2.224 -  csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + ip4_header_length + 16];
   2.225 +  csum_ptr = (USHORT *)&buffer[XN_HDR_SIZE + xi->rx.ip4_header_length + 16];
   2.226    *csum_ptr = 0;
   2.227  
   2.228 -KdPrint((__DRIVER_NAME "     buffer_length = %d, total_length = %d, ip4_length = %d, ip4_header_length = %d, tcp_header_length = %d\n", buffer_length, total_length, ip4_length, ip4_header_length, tcp_header_length));
   2.229 -
   2.230    ASSERT((USHORT)(ip4_length + XN_HDR_SIZE) == total_length);
   2.231  
   2.232    remaining = ip4_length - ip4_header_length - tcp_header_length;
   2.233 -  if (mss && remaining > mss)
   2.234 -  {
   2.235 -    ASSERT(mss <= PAGE_SIZE); // maybe fix this one day, but its a good assumption for now
   2.236 -    SplitLargePackets(packets, current_packet, &new_packets);
   2.237 -  }
   2.238 -  
   2.239 +  // TODO: pre-calc a sum of the header...
   2.240    pre_csum = 0;
   2.241    pre_csum += NET_USHORT(buffer[XN_HDR_SIZE + 12]) + NET_USHORT(buffer[XN_HDR_SIZE + 14]);
   2.242    pre_csum += NET_USHORT(buffer[XN_HDR_SIZE + 16]) + NET_USHORT(buffer[XN_HDR_SIZE + 18]);
   2.243 @@ -346,20 +246,28 @@ KdPrint((__DRIVER_NAME "     buffer_leng
   2.244  
   2.245    remaining = ip4_length - ip4_header_length;
   2.246  
   2.247 -  while (remaining > 0)
   2.248 +  csum = pre_csum + tcp_length;
   2.249 +  for (buffer_offset = i = XN_HDR_SIZE + ip4_header_length; i < tcp_length - 1; i += 2, buffer_offset += 2)
   2.250    {
   2.251 -    if (mss == 0)
   2.252 -      tcp_length = remaining;
   2.253 +    if (buffer_offset == buffer_length - 1) // deal with a buffer ending on an odd byte boundary
   2.254 +    {
   2.255 +      csum += (USHORT)buffer[buffer_offset] << 8;
   2.256 +      NdisGetNextBuffer(mdl, &mdl);
   2.257 +      if (mdl == NULL)
   2.258 +      {
   2.259 +        KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   2.260 +        return;
   2.261 +      }
   2.262 +      NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   2.263 +      KdPrint((__DRIVER_NAME "     New buffer - unaligned...\n"));
   2.264 +      csum += ((USHORT)buffer[0]);
   2.265 +      buffer_offset = -1;
   2.266 +    }
   2.267      else
   2.268 -      tcp_length = min(remaining, mss);
   2.269 -    remaining -= tcp_length;
   2.270 -
   2.271 -    csum = pre_csum + tcp_length;
   2.272 -    for (buffer_offset = i = XN_HDR_SIZE + ip4_header_length; i < tcp_length - 1; i += 2, buffer_offset += 2)
   2.273      {
   2.274 -      if (buffer_offset == buffer_length - 1) // deal with a buffer ending on an odd byte boundary
   2.275 +      if (buffer_offset == buffer_length)
   2.276        {
   2.277 -        csum += (USHORT)buffer[buffer_offset] << 8;
   2.278 +        KdPrint((__DRIVER_NAME "     New buffer - aligned...\n"));
   2.279          NdisGetNextBuffer(mdl, &mdl);
   2.280          if (mdl == NULL)
   2.281          {
   2.282 @@ -367,49 +275,143 @@ KdPrint((__DRIVER_NAME "     buffer_leng
   2.283            return;
   2.284          }
   2.285          NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   2.286 -        KdPrint((__DRIVER_NAME "     New buffer - unaligned...\n"));
   2.287 -        csum += ((USHORT)buffer[0]);
   2.288 -        buffer_offset = -1;
   2.289 +        buffer_offset = 0;
   2.290        }
   2.291 -      else
   2.292 -      {
   2.293 -        if (buffer_offset == buffer_length)
   2.294 -        {
   2.295 -          KdPrint((__DRIVER_NAME "     New buffer - aligned...\n"));
   2.296 -          NdisGetNextBuffer(mdl, &mdl);
   2.297 -          if (mdl == NULL)
   2.298 -          {
   2.299 -            KdPrint((__DRIVER_NAME "     Ran out of buffers\n"));
   2.300 -            return;
   2.301 -          }
   2.302 -          NdisQueryBufferSafe(mdl, &buffer, &buffer_length, NormalPagePriority);
   2.303 -          buffer_offset = 0;
   2.304 -        }
   2.305 -        csum += NET_USHORT(buffer[buffer_offset]);
   2.306 +      csum += NET_USHORT(buffer[buffer_offset]);
   2.307  //KdPrint((__DRIVER_NAME "     %04X\n", NET_USHORT(buffer[buffer_offset])));
   2.308 -      }
   2.309 -    }
   2.310 -    if (i != ip4_length) // last odd byte
   2.311 -    {
   2.312 -//KdPrint((__DRIVER_NAME "    *%04X\n", (USHORT)buffer[buffer_offset] << 8));
   2.313 -      csum += ((USHORT)buffer[buffer_offset] << 8);
   2.314      }
   2.315 -    while (csum & 0xFFFF0000)
   2.316 -      csum = (csum & 0xFFFF) + (csum >> 16);
   2.317 -    *csum_ptr = (USHORT)~NET_USHORT(csum);
   2.318 +  }
   2.319 +  if (i != ip4_length) // last odd byte
   2.320 +  {
   2.321 +//KdPrint((__DRIVER_NAME "    *%04X\n", (USHORT)buffer[buffer_offset] << 8));
   2.322 +    csum += ((USHORT)buffer[buffer_offset] << 8);
   2.323 +  }
   2.324 +  while (csum & 0xFFFF0000)
   2.325 +    csum = (csum & 0xFFFF) + (csum >> 16);
   2.326 +  *csum_ptr = (USHORT)~NET_USHORT(csum);
   2.327  
   2.328 -    if (remaining != 0)
   2.329 +  KdPrint((__DRIVER_NAME "     csum = %04x\n", *csum_ptr));
   2.330 +
   2.331 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.332 +}
   2.333 +
   2.334 +static PUCHAR
   2.335 +XenNet_GetMoreData(
   2.336 +  struct xennet_info xi,
   2.337 +  PUSHORT remaining
   2.338 +)
   2.339 +{
   2.340 +  PNDIS_BUFFER mdl = xi->rx.mdls[mdl_number];
   2.341 +  PUCHAR buffer = MmGetMdlVirtualAddress(mdl) + xi->rx.curr_mdl_offset;
   2.342 +  USHORT length = min(*remaining, MmGetMdlByteCount(mdl) - xi->rx.curr_mdl_offset);
   2.343 +
   2.344 +  *remaining -= length;
   2.345 +  xi->rx.curr_mdl_offset += length;
   2.346 +  if (xi->rx.curr_mdl_offset == MmGetMdlByteCount(mdl))
   2.347 +    xi->rx.mdl_number++;
   2.348 +  return buffer;
   2.349 +}
   2.350 +
   2.351 +
   2.352 +static NDIS_PACKET
   2.353 +XenNet_MakePacket(
   2.354 +  struct xennet_info xi,
   2.355 +  PUCHAR header,
   2.356 +  ULONG mdl_number,
   2.357 +  ULONG buf_offset;
   2.358 +)
   2.359 +{
   2.360 +  PNDIS_PACKET packet;
   2.361 +  PUCHAR in_buffer;
   2.362 +  PNDIS_BUFFER out_mdl;
   2.363 +  PUCHAR out_buffer;
   2.364 +  USHORT out_offset;
   2.365 +
   2.366 +  NdisAllocatePacket(&status, &packets[*packet_count], xi->packet_pool);
   2.367 +  ASSERT(status == NDIS_STATUS_SUCCESS);
   2.368 +  NDIS_SET_PACKET_HEADER_SIZE(packets[*packet_count], XN_HDR_SIZE);
   2.369 +  if (header == NULL)
   2.370 +  {
   2.371 +    for (i = 0; i < xi->rx.mdl_count; i++)
   2.372 +      NdisChainBufferAtBack(packet, mdls[i]);
   2.373 +    NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
   2.374 +  }
   2.375 +  else
   2.376 +  {
   2.377 +    out_mdl = get_page_from_freelist(xi);
   2.378 +    out_buffer = out_ptr = MmGetMdlVirtualAddress(out_mdl);
   2.379 +    out_offset = XN_HDR_SIZE + xi->rx.ip4_header_length + xi->rx.tcp_header_length;
   2.380 +    out_remaining = xi->rx.mss;
   2.381 +    memcpy(out_buffer, header, out_offset);
   2.382 +    do 
   2.383      {
   2.384 -      // create a new packet
   2.385 -      // copy the header to a new buffer
   2.386 -      // if we are not at the start of the current buffer, copy the remaining data from the current buffer into a new buffer
   2.387 -      
   2.388 -    }
   2.389 -  
   2.390 -    KdPrint((__DRIVER_NAME "     csum = %04x\n", *csum_ptr));
   2.391 +      in_buffer = XenNet_GetMoreData(xi, &out_remaining, &length);
   2.392 +      memcpy(&out_buffer[out_offset], in_buffer, length);
   2.393 +    } while (out_remaining != 0 && in_buffer != NULL)
   2.394 +    length = xi->rx.mss - out_remaining;
   2.395 +    in_buffer[___ip4_length_offset___] = NET_USHORT(...); // recalc this
   2.396 +    in_buffer[___mss_offset___] = NET_USHORT(length);
   2.397 +    in_buffer[___seq_offset___] = NET_ULONG(in_buffer[___seq_offset___]) + ???
   2.398 +  }
   2.399 +  return packet;
   2.400 +}
   2.401 +
   2.402 +static VOID
   2.403 +XenNet_MakePackets(
   2.404 +  struct xennet_info *xi,
   2.405 +  PNDIS_PACKET *packets,
   2.406 +  PULONG packet_count
   2.407 +)
   2.408 +{
   2.409 +  PNDIS_PACKET first_packet;
   2.410 +  PNDIS_PACKET curr_packet;
   2.411 +  PNDIS_BUFFER mdls[MAX_BUFFERS_PER_PACKET];
   2.412 +  ULONG mdl_count = 0;
   2.413 +  ULONG curr_in_mdl_index;
   2.414 +  PNDIS_BUFFER curr_out_mdl;
   2.415 +  ULONG curr_in_offset;
   2.416 +  ULONG curr_out_offset;
   2.417 +  PUCHAR header;
   2.418 +  PUCHAR curr_in_buffer;
   2.419 +  PUCHAR curr_out_buffer;
   2.420 +
   2.421 +  ULONG total_in_remaining;
   2.422 +  ULONG buffer_in_remaining;
   2.423 +
   2.424 +  XenNet_ParseHeader(xi);
   2.425 +  switch (xi->rx.ip4_proto)
   2.426 +  {
   2.427 +  case 6:  // TCP
   2.428 +    if (xi->rx.split_required)
   2.429 +      break;
   2.430 +    packets[*packet_count] = XenNet_MakePacket(xi);
   2.431 +    if (xi->rx.csum_calc_required)
   2.432 +      XenNet_SumPacket(xi, packets[*packet_count];
   2.433 +    *packet_count++;
   2.434 +    return;
   2.435 +  case 17:  // UDP
   2.436 +    packets[*packet_count] = XenNet_MakePacket(xi);
   2.437 +    if (xi->rx.csum_calc_required)
   2.438 +      XenNet_SumPacket(xi, packets[*packet_count];
   2.439 +    *packet_count++;
   2.440 +    return;
   2.441 +  default:
   2.442 +    packets[*packet_count] = XenNet_MakePacket(xi, ...);
   2.443 +    *packet_count++;
   2.444 +    return;
   2.445    }
   2.446  
   2.447 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.448 +  while (data left in buffer)
   2.449 +  {
   2.450 +    packets[*packet_count] = XenNet_MakePacket(xi, ...);
   2.451 +    XenNet_SumPacket(xi, packets[*packet_count];
   2.452 +    *packet_count++;
   2.453 +  }
   2.454 +  // TODO: restore psh status to last packet
   2.455 +  for (i = 0; i < mdl_count; i++)
   2.456 +  {
   2.457 +    put_page_on_freelist(xi, mdls[i];
   2.458 +  }
   2.459  }
   2.460  
   2.461  // Called at DISPATCH_LEVEL
   2.462 @@ -423,12 +425,8 @@ XenNet_RxBufferCheck(struct xennet_info 
   2.463    int moretodo;
   2.464    struct netif_rx_response *rxrsp = NULL;
   2.465    struct netif_extra_info *ei;
   2.466 -  int more_frags = 0;
   2.467    NDIS_STATUS status;
   2.468    USHORT id;
   2.469 -  PNDIS_TCP_IP_CHECKSUM_PACKET_INFO csum_info;
   2.470 -  USHORT total_packet_length = 0;
   2.471 -  BOOLEAN csum_calc_required;
   2.472    int cycles = 0;
   2.473  #if defined(XEN_PROFILE)
   2.474    LARGE_INTEGER tsc, tsc2, dummy;
   2.475 @@ -445,13 +443,6 @@ XenNet_RxBufferCheck(struct xennet_info 
   2.476    KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
   2.477  
   2.478    packet_count = 0;
   2.479 -  csum_calc_required = FALSE;
   2.480 -  if (xi->rx_current_packet)
   2.481 -  {
   2.482 -    packets[packet_count] = xi->rx_current_packet;
   2.483 -    xi->rx_current_packet = NULL;
   2.484 -    more_frags = NETRXF_more_data;
   2.485 -  }
   2.486    do {
   2.487      ASSERT(cycles++ < 256);
   2.488      prod = xi->rx.sring->rsp_prod;
   2.489 @@ -464,21 +455,19 @@ XenNet_RxBufferCheck(struct xennet_info 
   2.490        mdl = xi->rx_buffers[id];
   2.491        xi->rx_buffers[id] = NULL;
   2.492        xi->rx_id_free++;
   2.493 -      if (xi->rx_extra_info)
   2.494 +      if (xi->rx.extra_info)
   2.495        {
   2.496 -KdPrint((__DRIVER_NAME "     RX extra info packet detected\n"));
   2.497          put_page_on_freelist(xi, mdl);
   2.498          ei = (struct netif_extra_info *)RING_GET_RESPONSE(&xi->rx, cons);
   2.499 -        xi->rx_extra_info = ei->flags & XEN_NETIF_EXTRA_FLAG_MORE;
   2.500 +        xi->rx.extra_info = !!(ei->flags & XEN_NETIF_EXTRA_FLAG_MORE);
   2.501          switch (ei->type)
   2.502          {
   2.503          case XEN_NETIF_EXTRA_TYPE_GSO:
   2.504 -KdPrint((__DRIVER_NAME "     GSO detected - size = %d\n", ei->u.gso.size));
   2.505            switch (ei->u.gso.type)
   2.506            {
   2.507            case XEN_NETIF_GSO_TYPE_TCPV4:
   2.508 -KdPrint((__DRIVER_NAME "     GSO_TYPE_TCPV4 detected\n"));
   2.509 -            NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo) = (PVOID)(xen_ulong_t)(ei->u.gso.size);
   2.510 +            xi->rx.mss = (PVOID)(xen_ulong_t)(ei->u.gso.size);
   2.511 +            ASSERT(header_len + xi->rx.mss <= PAGE_SIZE); // this limits MTU to PAGE_SIZE - XN_HEADER_LEN
   2.512              break;
   2.513            default:
   2.514              KdPrint((__DRIVER_NAME "     Unknown GSO type (%d) detected\n", ei->u.gso.type));
   2.515 @@ -492,71 +481,41 @@ KdPrint((__DRIVER_NAME "     GSO_TYPE_TC
   2.516        }
   2.517        else
   2.518        {
   2.519 -//KdPrint((__DRIVER_NAME "     normal packet detected\n"));
   2.520          rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
   2.521          if (rxrsp->status <= 0
   2.522            || rxrsp->offset + rxrsp->status > PAGE_SIZE)
   2.523          {
   2.524            KdPrint((__DRIVER_NAME ": Error: rxrsp offset %d, size %d\n",
   2.525              rxrsp->offset, rxrsp->status));
   2.526 +          put_page_on_freelist(xi, mdl);
   2.527            continue;
   2.528          }
   2.529          ASSERT(rxrsp->id == id);
   2.530 -        if (!more_frags) // handling the packet's 1st buffer
   2.531 +        if (!xi->rx.more_frags) // handling the packet's 1st buffer
   2.532          {
   2.533 -          NdisAllocatePacket(&status, &packets[packet_count], xi->packet_pool);
   2.534 -          ASSERT(status == NDIS_STATUS_SUCCESS);
   2.535 -          NDIS_SET_PACKET_HEADER_SIZE(packets[packet_count], XN_HDR_SIZE);
   2.536 -          NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo) = 0;
   2.537 -          total_packet_length = 0;
   2.538 +          
   2.539            if (rxrsp->flags & (NETRXF_csum_blank|NETRXF_data_validated) && xi->config_csum) // and we are enabled for offload...
   2.540            {
   2.541 -//KdPrint((__DRIVER_NAME "     RX csum blank = %d, validated = %d\n", !!(rxrsp->flags & NETRXF_csum_blank), !!(rxrsp->flags & NETRXF_data_validated)));
   2.542 +            //KdPrint((__DRIVER_NAME "     RX csum blank = %d, validated = %d\n", !!(rxrsp->flags & NETRXF_csum_blank), !!(rxrsp->flags & NETRXF_data_validated)));
   2.543              if (rxrsp->flags & NETRXF_csum_blank)
   2.544 -              csum_calc_required = TRUE;
   2.545 -            csum_info = (PNDIS_TCP_IP_CHECKSUM_PACKET_INFO)&NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpIpChecksumPacketInfo);
   2.546 -            csum_info->Receive.NdisPacketTcpChecksumSucceeded = 1;
   2.547 -            csum_info->Receive.NdisPacketUdpChecksumSucceeded = 0;
   2.548 -            csum_info->Receive.NdisPacketIpChecksumSucceeded = 1;
   2.549 -#if defined(XEN_PROFILE)
   2.550 +              xi->rx.csum_calc_required = TRUE;
   2.551 +            #if defined(XEN_PROFILE)
   2.552              ProfCount_RxPacketsCsumOffload++;
   2.553 -#endif
   2.554 -//KdPrint((__DRIVER_NAME "     RX csum offload TcpFailed = %d, UdpFailed = %d\n", csum_info->Receive.NdisPacketTcpChecksumFailed, csum_info->Receive.NdisPacketUdpChecksumFailed));
   2.555 +            #endif
   2.556            }
   2.557          }
   2.558 -        total_packet_length = total_packet_length  + rxrsp->status;
   2.559          NdisAdjustBufferLength(mdl, rxrsp->status);
   2.560 -        NdisChainBufferAtBack(packets[packet_count], mdl);
   2.561 -        
   2.562 -        xi->rx_extra_info = rxrsp->flags & NETRXF_extra_info;
   2.563 -        more_frags = rxrsp->flags & NETRXF_more_data;
   2.564 +        xi->rx.mdls[mdl_count++] = mdl;
   2.565 +        xi->rx.extra_info = !!(rxrsp->flags & NETRXF_extra_info);
   2.566 +        xi->rx.more_frags = !!(rxrsp->flags & NETRXF_more_data);
   2.567 +        xi->rx.total_length += rxrsp->status;
   2.568        }
   2.569  
   2.570 -if (more_frags)
   2.571 -  KdPrint((__DRIVER_NAME "     more frags\n"));
   2.572        /* Packet done, add it to the list */
   2.573 -      if (!more_frags && !xi->rx_extra_info)
   2.574 +      if (!xi->rx.more_frags && !xi->rx.extra_info)
   2.575        {
   2.576 -if (PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo)))
   2.577 -  KdPrint((__DRIVER_NAME "     total length = %d, mss = %d\n", total_packet_length, PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(packets[packet_count], TcpLargeSendPacketInfo))));
   2.578 -#if defined(XEN_PROFILE)
   2.579 -        ProfCount_RxPacketsTotal++;
   2.580 -#endif
   2.581 -        xi->stat_rx_ok++;
   2.582 -        NDIS_SET_PACKET_STATUS(packets[packet_count], NDIS_STATUS_SUCCESS);
   2.583 -
   2.584 -/*
   2.585 -        if (total_packet_length > xi->config_mtu + XN_HDR_SIZE)
   2.586 -        {
   2.587 -          KdPrint((__DRIVER_NAME "     total_packet_length %d, config_mtu = %d\n", total_packet_length, xi->config_mtu));
   2.588 -          XenNet_SplitRxPacket(packets, &packet_count, total_packet_length);
   2.589 -        }
   2.590 -        else */ if (csum_calc_required)
   2.591 -        {
   2.592 -          XenNet_SumData(packets[packet_count]);
   2.593 -          csum_calc_required = FALSE;
   2.594 -        }
   2.595 -
   2.596 +        XenNet_MakePackets(xi, packets, &packet_count)
   2.597 +        RtlZeroMemory(xi->rx, sizeof(xi->rx));
   2.598          packet_count++;
   2.599        }
   2.600      }
   2.601 @@ -568,12 +527,6 @@ if (PtrToUlong(NDIS_PER_PACKET_INFO_FROM
   2.602    /* Give netback more buffers */
   2.603    XenNet_RxBufferAlloc(xi);
   2.604  
   2.605 -  if (more_frags)
   2.606 -  {
   2.607 -KdPrint((__DRIVER_NAME "     leftover frags\n"));
   2.608 -    xi->rx_current_packet = packets[packet_count];
   2.609 -  }
   2.610 -
   2.611    KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
   2.612  
   2.613  #if defined(XEN_PROFILE)