win-pvdrivers

changeset 995:0879eec3f528 0.11.0.372

Fix packet leak under 2003
author James Harper <james.harper@bendigoit.com.au>
date Mon Oct 22 21:21:16 2012 +1100 (2012-10-22)
parents 673b6d369a80
children 3a4a56ed205f
files xennet/xennet5.h xennet/xennet5_rx.c
line diff
     1.1 --- a/xennet/xennet5.h	Wed Oct 10 22:21:06 2012 +1100
     1.2 +++ b/xennet/xennet5.h	Mon Oct 22 21:21:16 2012 +1100
     1.3 @@ -232,6 +232,8 @@ typedef struct {
     1.4  #define PAGE_LIST_SIZE (max(NET_RX_RING_SIZE, NET_TX_RING_SIZE) * 4)
     1.5  #define MULTICAST_LIST_MAX_SIZE 32
     1.6  
     1.7 +#define NDIS_STATUS_RESOURCES_MAX_LENGTH 64
     1.8 +
     1.9  struct xennet_info
    1.10  {
    1.11    BOOLEAN inactive;
     2.1 --- a/xennet/xennet5_rx.c	Wed Oct 10 22:21:06 2012 +1100
     2.2 +++ b/xennet/xennet5_rx.c	Mon Oct 22 21:21:16 2012 +1100
     2.3 @@ -163,9 +163,8 @@ get_packet_from_freelist(struct xennet_i
     2.4      return NULL;
     2.5  
     2.6    NdisAllocatePacket(&status, &packet, xi->rx_packet_pool);
     2.7 -  if (status != NDIS_STATUS_SUCCESS)
     2.8 -  {
     2.9 -    KdPrint((__DRIVER_NAME "     cannot allocate packet\n"));
    2.10 +  if (status != NDIS_STATUS_SUCCESS) {
    2.11 +    KdPrint((__DRIVER_NAME "     cannot allocate packet status = %08x, rx_outstanding = %d\n", status, xi->rx_outstanding));
    2.12      return NULL;
    2.13    }
    2.14    NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
    2.15 @@ -199,6 +198,7 @@ XenNet_MakePacket(struct xennet_info *xi
    2.16    ULONG out_remaining;
    2.17    ULONG tcp_length;
    2.18    ULONG header_extra;
    2.19 +  ULONG packet_length = 0;
    2.20    shared_buffer_t *header_buf;
    2.21  
    2.22    //FUNCTION_ENTER();
    2.23 @@ -229,7 +229,7 @@ XenNet_MakePacket(struct xennet_info *xi
    2.24      ref_pb(xi, pi->first_pb); /* so that the buffer doesn't get freed at the end of MakePackets*/
    2.25      //FUNCTION_EXIT();
    2.26      /* windows gets lazy about ack packets and holds on to them forever under high load situations. we don't like this */
    2.27 -    if (pi->ip_proto == 6 && pi->tcp_length == 0)
    2.28 +    if (pi->ip_proto == 6 && pi->total_length <= NDIS_STATUS_RESOURCES_MAX_LENGTH)
    2.29        NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_RESOURCES);
    2.30      else
    2.31        NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
    2.32 @@ -269,6 +269,7 @@ XenNet_MakePacket(struct xennet_info *xi
    2.33      return NULL;
    2.34    }
    2.35    NdisChainBufferAtBack(packet, out_buffer);
    2.36 +  packet_length += pi->header_length;
    2.37    *(shared_buffer_t **)&packet->MiniportReservedEx[0] = header_buf;
    2.38    header_buf->next = pi->curr_pb;
    2.39  
    2.40 @@ -315,6 +316,7 @@ XenNet_MakePacket(struct xennet_info *xi
    2.41      NdisCopyBuffer(&status, &out_buffer, xi->rx_buffer_pool, pi->curr_buffer, pi->curr_mdl_offset, out_length);
    2.42      ASSERT(status == STATUS_SUCCESS); //TODO: properly handle error
    2.43      NdisChainBufferAtBack(packet, out_buffer);
    2.44 +    packet_length += out_length;
    2.45      ref_pb(xi, pi->curr_pb);
    2.46      pi->curr_mdl_offset = (USHORT)(pi->curr_mdl_offset + out_length);
    2.47      if (pi->curr_mdl_offset == in_buffer_length)
    2.48 @@ -325,15 +327,14 @@ XenNet_MakePacket(struct xennet_info *xi
    2.49      }
    2.50      out_remaining -= out_length;
    2.51    }
    2.52 -  if (pi->split_required)
    2.53 -  {
    2.54 +  if (pi->split_required) {
    2.55      XenNet_SumIpHeader(header_va, pi->ip4_header_length);
    2.56    }
    2.57    if (header_extra > 0)
    2.58      pi->header_length -= header_extra;
    2.59    ASSERT(*(shared_buffer_t **)&packet->MiniportReservedEx[0]);
    2.60    /* windows gets lazy about ack packets and holds on to them forever under high load situations. we don't like this */
    2.61 -  if (pi->ip_proto == 6 && pi->tcp_length == 0)
    2.62 +  if (pi->ip_proto == 6 && packet_length <= NDIS_STATUS_RESOURCES_MAX_LENGTH)
    2.63      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_RESOURCES);
    2.64    else
    2.65      NDIS_SET_PACKET_STATUS(packet, NDIS_STATUS_SUCCESS);
    2.66 @@ -712,18 +713,16 @@ XenNet_ReturnPacket(
    2.67    }
    2.68  
    2.69    put_packet_on_freelist(xi, Packet);
    2.70 -  InterlockedDecrement(&xi->rx_outstanding);
    2.71 -  
    2.72 -  if (!xi->rx_outstanding && xi->rx_shutting_down)
    2.73 -    KeSetEvent(&xi->packet_returned_event, IO_NO_INCREMENT, FALSE);
    2.74 -
    2.75 -#if 0 /* don't do this as it's called an awful lot */
    2.76 -  KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    2.77 -
    2.78 -  XenNet_FillRing(xi);
    2.79 -
    2.80 -  KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    2.81 -#endif
    2.82 +  if (!InterlockedDecrement(&xi->rx_outstanding)) {
    2.83 +    if (xi->rx_shutting_down) {
    2.84 +      KeSetEvent(&xi->packet_returned_event, IO_NO_INCREMENT, FALSE);
    2.85 +    } else {
    2.86 +      /* check performance of this - only happens on ring empty */
    2.87 +      KeAcquireSpinLockAtDpcLevel(&xi->rx_lock);
    2.88 +      XenNet_FillRing(xi);
    2.89 +      KeReleaseSpinLockFromDpcLevel(&xi->rx_lock);
    2.90 +    }
    2.91 +  }
    2.92    //FUNCTION_EXIT();
    2.93  }
    2.94    
    2.95 @@ -993,7 +992,7 @@ XenNet_RxBufferCheck(struct xennet_info 
    2.96      packets[packet_count++] = packet;
    2.97      InterlockedIncrement(&xi->rx_outstanding);
    2.98      entry = RemoveHeadList(&rx_packet_list);
    2.99 -    /* if we indicate a packet with NDIS_STATUS_RESOURCES  then any following packet can't be NDIS_STATUS_SUCCESS */
   2.100 +    /* if we indicate a packet with NDIS_STATUS_RESOURCES then any following packet can't be NDIS_STATUS_SUCCESS */
   2.101      if (packet_count == MAXIMUM_PACKETS_PER_INDICATE || entry == &rx_packet_list
   2.102          || (NDIS_GET_PACKET_STATUS(CONTAINING_RECORD(entry, NDIS_PACKET, MiniportReservedEx[sizeof(PVOID)])) == NDIS_STATUS_SUCCESS
   2.103              && status == NDIS_STATUS_RESOURCES))