Annotation of ntddk/src/network/tdi/packet.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     packet.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains code that implements the TP_PACKET object, which
                     12:     describes an NDIS packet.
                     13: 
                     14: Environment:
                     15: 
                     16:     Kernel mode
                     17: 
                     18: Revision History:
                     19: 
                     20: --*/
                     21: 
                     22: #include "st.h"
                     23: 
                     24: //
                     25: // This is temporary; this is the quota that we charge for a receive
                     26: // packet for now, until we fix the problem with token-ring needing
                     27: // big packets and using all the memory. The number is the actual
                     28: // value for Ethernet.
                     29: //
                     30: 
                     31: #if 1
                     32: #define RECEIVE_BUFFER_QUOTA(_DeviceContext)   1533
                     33: #else
                     34: #define RECEIVE_BUFFER_QUOTA(_DeviceContext)   (_DeviceContext)->ReceiveBufferLength
                     35: #endif
                     36: 
                     37: 
                     38: 
                     39: 
                     40: VOID
                     41: StAllocateSendPacket(
                     42:     IN PDEVICE_CONTEXT DeviceContext,
                     43:     OUT PTP_PACKET *TransportSendPacket
                     44:     )
                     45: 
                     46: /*++
                     47: 
                     48: Routine Description:
                     49: 
                     50:     This routine allocates storage for a send packet. Some initialization
                     51:     is done here.
                     52: 
                     53:     NOTE: This routine is called with the device context spinlock
                     54:     held, or at such a time as synchronization is unnecessary.
                     55: 
                     56: Arguments:
                     57: 
                     58:     DeviceContext - Pointer to our device context to charge the packet to.
                     59: 
                     60:     TransportSendPacket - Returns a pointer to the packet, or NULL if no
                     61:         storage can be allocated.
                     62: 
                     63: Return Value:
                     64: 
                     65:     None.
                     66: 
                     67: --*/
                     68: 
                     69: {
                     70: 
                     71:     PTP_PACKET Packet;
                     72:     NDIS_STATUS NdisStatus;
                     73:     PNDIS_PACKET NdisPacket;
                     74:     PSEND_PACKET_TAG SendTag;
                     75:     PNDIS_BUFFER NdisBuffer;
                     76: 
                     77:     if ((DeviceContext->MemoryLimit != 0) &&
                     78:             ((DeviceContext->MemoryUsage + DeviceContext->PacketLength) >
                     79:                 DeviceContext->MemoryLimit)) {
                     80:         PANIC("ST: Could not allocate send packet: limit\n");
                     81:         StWriteResourceErrorLog (DeviceContext, DeviceContext->PacketLength, 107);
                     82:         *TransportSendPacket = NULL;
                     83:         return;
                     84:     }
                     85: 
                     86:     Packet = (PTP_PACKET)ExAllocatePool (NonPagedPool, DeviceContext->PacketLength);
                     87:     if (Packet == NULL) {
                     88:         PANIC("ST: Could not allocate send packet: no pool\n");
                     89:         StWriteResourceErrorLog (DeviceContext, DeviceContext->PacketLength, 207);
                     90:         *TransportSendPacket = NULL;
                     91:         return;
                     92:     }
                     93:     RtlZeroMemory (Packet, DeviceContext->PacketLength);
                     94: 
                     95:     DeviceContext->MemoryUsage += DeviceContext->PacketLength;
                     96: 
                     97:     NdisAllocatePacket (
                     98:         &NdisStatus,
                     99:         &NdisPacket,
                    100:         DeviceContext->SendPacketPoolHandle);
                    101: 
                    102:     if (NdisStatus != NDIS_STATUS_SUCCESS) {
                    103:         ExFreePool (Packet);
                    104:         StWriteResourceErrorLog (DeviceContext, 0, 307);
                    105:         *TransportSendPacket = NULL;
                    106:         return;
                    107:     }
                    108: 
                    109:     NdisAllocateBuffer(
                    110:         &NdisStatus,
                    111:         &NdisBuffer,
                    112:         DeviceContext->NdisBufferPoolHandle,
                    113:         Packet->Header,
                    114:         DeviceContext->PacketHeaderLength);
                    115: 
                    116:     if (NdisStatus != NDIS_STATUS_SUCCESS) {
                    117:         NdisFreePacket (NdisPacket);
                    118:         ExFreePool (Packet);
                    119:         *TransportSendPacket = NULL;
                    120:         return;
                    121:     }
                    122: 
                    123:     NdisChainBufferAtFront (NdisPacket, NdisBuffer);
                    124: 
                    125:     Packet->NdisPacket = NdisPacket;
                    126:     SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
                    127:     SendTag->Type = TYPE_I_FRAME;
                    128:     SendTag->Packet = Packet;
                    129:     SendTag->Owner = NULL;
                    130: 
                    131:     Packet->Type = ST_PACKET_SIGNATURE;
                    132:     Packet->Size = sizeof (TP_PACKET);
                    133:     Packet->Provider = DeviceContext;
                    134: 
                    135:     ++DeviceContext->PacketAllocated;
                    136: 
                    137:     *TransportSendPacket = Packet;
                    138: 
                    139: }   /* StAllocateSendPacket */
                    140: 
                    141: 
                    142: VOID
                    143: StDeallocateSendPacket(
                    144:     IN PDEVICE_CONTEXT DeviceContext,
                    145:     IN PTP_PACKET TransportSendPacket
                    146:     )
                    147: 
                    148: /*++
                    149: 
                    150: Routine Description:
                    151: 
                    152:     This routine frees storage for a send packet.
                    153: 
                    154:     NOTE: This routine is called with the device context spinlock
                    155:     held, or at such a time as synchronization is unnecessary.
                    156: 
                    157: Arguments:
                    158: 
                    159:     DeviceContext - Pointer to our device context to charge the packet to.
                    160: 
                    161:     TransportSendPacket - A pointer to the send packet.
                    162: 
                    163: Return Value:
                    164: 
                    165:     None.
                    166: 
                    167: --*/
                    168: 
                    169: {
                    170:     PNDIS_PACKET NdisPacket = TransportSendPacket->NdisPacket;
                    171:     PNDIS_BUFFER NdisBuffer;
                    172: 
                    173:     NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
                    174:     if (NdisBuffer != NULL) {
                    175:         NdisFreeBuffer (NdisBuffer);
                    176:     }
                    177: 
                    178:     NdisFreePacket (NdisPacket);
                    179:     ExFreePool (TransportSendPacket);
                    180: 
                    181:     --DeviceContext->PacketAllocated;
                    182:     DeviceContext->MemoryUsage -= DeviceContext->PacketLength;
                    183: 
                    184: }   /* StDeallocateSendPacket */
                    185: 
                    186: 
                    187: VOID
                    188: StAllocateReceivePacket(
                    189:     IN PDEVICE_CONTEXT DeviceContext,
                    190:     OUT PNDIS_PACKET *TransportReceivePacket
                    191:     )
                    192: 
                    193: /*++
                    194: 
                    195: Routine Description:
                    196: 
                    197:     This routine allocates storage for a receive packet. Some initialization
                    198:     is done here.
                    199: 
                    200:     NOTE: This routine is called with the device context spinlock
                    201:     held, or at such a time as synchronization is unnecessary.
                    202: 
                    203: Arguments:
                    204: 
                    205:     DeviceContext - Pointer to our device context to charge the packet to.
                    206: 
                    207:     TransportReceivePacket - Returns a pointer to the packet, or NULL if no
                    208:         storage can be allocated.
                    209: 
                    210: Return Value:
                    211: 
                    212:     None.
                    213: 
                    214: --*/
                    215: 
                    216: {
                    217:     NDIS_STATUS NdisStatus;
                    218:     PNDIS_PACKET NdisPacket;
                    219:     PRECEIVE_PACKET_TAG ReceiveTag;
                    220: 
                    221:     //
                    222:     // This does not count in DeviceContext->MemoryUsage because
                    223:     // the storage is allocated when we allocate the packet pool.
                    224:     //
                    225: 
                    226:     NdisAllocatePacket (
                    227:         &NdisStatus,
                    228:         &NdisPacket,
                    229:         DeviceContext->ReceivePacketPoolHandle);
                    230: 
                    231:     if (NdisStatus != NDIS_STATUS_SUCCESS) {
                    232:         StWriteResourceErrorLog (DeviceContext, 0, 309);
                    233:         *TransportReceivePacket = NULL;
                    234:         return;
                    235:     }
                    236: 
                    237:     ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
                    238:     ReceiveTag->PacketType = TYPE_AT_INDICATE;
                    239: 
                    240:     ++DeviceContext->ReceivePacketAllocated;
                    241: 
                    242:     *TransportReceivePacket = NdisPacket;
                    243: 
                    244: }   /* StAllocateReceivePacket */
                    245: 
                    246: 
                    247: VOID
                    248: StDeallocateReceivePacket(
                    249:     IN PDEVICE_CONTEXT DeviceContext,
                    250:     IN PNDIS_PACKET TransportReceivePacket
                    251:     )
                    252: 
                    253: /*++
                    254: 
                    255: Routine Description:
                    256: 
                    257:     This routine frees storage for a receive packet.
                    258: 
                    259:     NOTE: This routine is called with the device context spinlock
                    260:     held, or at such a time as synchronization is unnecessary.
                    261: 
                    262: Arguments:
                    263: 
                    264:     DeviceContext - Pointer to our device context to charge the packet to.
                    265: 
                    266:     TransportReceivePacket - A pointer to the packet.
                    267: 
                    268: Return Value:
                    269: 
                    270:     None.
                    271: 
                    272: --*/
                    273: 
                    274: {
                    275: 
                    276:     NdisFreePacket (TransportReceivePacket);
                    277: 
                    278:     --DeviceContext->ReceivePacketAllocated;
                    279: 
                    280: }   /* StDeallocateReceivePacket */
                    281: 
                    282: 
                    283: VOID
                    284: StAllocateReceiveBuffer(
                    285:     IN PDEVICE_CONTEXT DeviceContext,
                    286:     OUT PBUFFER_TAG *TransportReceiveBuffer
                    287:     )
                    288: 
                    289: /*++
                    290: 
                    291: Routine Description:
                    292: 
                    293:     This routine allocates storage for a receive buffer. Some initialization
                    294:     is done here.
                    295: 
                    296:     NOTE: This routine is called with the device context spinlock
                    297:     held, or at such a time as synchronization is unnecessary.
                    298: 
                    299: Arguments:
                    300: 
                    301:     DeviceContext - Pointer to our device context to charge the packet to.
                    302: 
                    303:     TransportReceiveBuffer - Returns a pointer to the buffer, or NULL if no
                    304:         storage can be allocated.
                    305: 
                    306: Return Value:
                    307: 
                    308:     None.
                    309: 
                    310: --*/
                    311: 
                    312: {
                    313:     PBUFFER_TAG BufferTag;
                    314:     NDIS_STATUS NdisStatus;
                    315:     PNDIS_BUFFER NdisBuffer;
                    316: 
                    317: 
                    318:     if ((DeviceContext->MemoryLimit != 0) &&
                    319:             ((DeviceContext->MemoryUsage + RECEIVE_BUFFER_QUOTA(DeviceContext)) >
                    320:                 DeviceContext->MemoryLimit)) {
                    321:         PANIC("ST: Could not allocate receive buffer: limit\n");
                    322:         StWriteResourceErrorLog (DeviceContext, RECEIVE_BUFFER_QUOTA(DeviceContext), 108);
                    323:         *TransportReceiveBuffer = NULL;
                    324:         return;
                    325:     }
                    326: 
                    327:     BufferTag = (PBUFFER_TAG)ExAllocatePool (
                    328:                     NonPagedPoolCacheAligned,
                    329:                     DeviceContext->ReceiveBufferLength);
                    330: 
                    331:     if (BufferTag == NULL) {
                    332:         PANIC("ST: Could not allocate receive buffer: no pool\n");
                    333:         StWriteResourceErrorLog (DeviceContext, DeviceContext->ReceiveBufferLength, 208);
                    334:         *TransportReceiveBuffer = NULL;
                    335:         return;
                    336:     }
                    337: 
                    338:     DeviceContext->MemoryUsage += RECEIVE_BUFFER_QUOTA(DeviceContext);
                    339: 
                    340:     //
                    341:     // point to the buffer for NDIS
                    342:     //
                    343: 
                    344:     NdisAllocateBuffer(
                    345:         &NdisStatus,
                    346:         &NdisBuffer,
                    347:         DeviceContext->NdisBufferPoolHandle,
                    348:         BufferTag->Buffer,
                    349:         DeviceContext->MaxReceivePacketSize);
                    350: 
                    351:     if (NdisStatus != NDIS_STATUS_SUCCESS) {
                    352:         ExFreePool (BufferTag);
                    353:         *TransportReceiveBuffer = NULL;
                    354:         return;
                    355:     }
                    356: 
                    357:     BufferTag->Length = DeviceContext->MaxReceivePacketSize;
                    358:     BufferTag->NdisBuffer = NdisBuffer;
                    359: 
                    360:     ++DeviceContext->ReceiveBufferAllocated;
                    361: 
                    362:     *TransportReceiveBuffer = BufferTag;
                    363: 
                    364: }   /* StAllocateReceiveBuffer */
                    365: 
                    366: 
                    367: VOID
                    368: StDeallocateReceiveBuffer(
                    369:     IN PDEVICE_CONTEXT DeviceContext,
                    370:     IN PBUFFER_TAG TransportReceiveBuffer
                    371:     )
                    372: 
                    373: /*++
                    374: 
                    375: Routine Description:
                    376: 
                    377:     This routine frees storage for a receive buffer.
                    378: 
                    379:     NOTE: This routine is called with the device context spinlock
                    380:     held, or at such a time as synchronization is unnecessary.
                    381: 
                    382: Arguments:
                    383: 
                    384:     DeviceContext - Pointer to our device context to charge the packet to.
                    385: 
                    386:     TransportReceiveBuffer - A pointer to the buffer.
                    387: 
                    388: Return Value:
                    389: 
                    390:     None.
                    391: 
                    392: --*/
                    393: 
                    394: {
                    395: 
                    396:     NdisFreeBuffer (TransportReceiveBuffer->NdisBuffer);
                    397:     ExFreePool (TransportReceiveBuffer);
                    398: 
                    399:     --DeviceContext->ReceiveBufferAllocated;
                    400:     DeviceContext->MemoryUsage -= RECEIVE_BUFFER_QUOTA(DeviceContext);
                    401: 
                    402: }   /* StDeallocateReceiveBuffer */
                    403: 
                    404: 
                    405: NTSTATUS
                    406: StCreatePacket(
                    407:     PDEVICE_CONTEXT DeviceContext,
                    408:     PTP_PACKET *Packet
                    409:     )
                    410: 
                    411: /*++
                    412: 
                    413: Routine Description:
                    414: 
                    415:     This routine allocates a packet from the device context's pool,
                    416:     and prepares the MAC and DLC headers for use by the connection.
                    417: 
                    418: Arguments:
                    419: 
                    420:     DeviceContext - Pointer to our device context to charge the packet to.
                    421: 
                    422:     Packet - Pointer to a place where we will return a pointer to the
                    423:         allocated packet.
                    424: 
                    425: Return Value:
                    426: 
                    427:     NTSTATUS - status of operation.
                    428: 
                    429: --*/
                    430: 
                    431: {
                    432:     KIRQL oldirql;
                    433:     PSINGLE_LIST_ENTRY s;
                    434:     PTP_PACKET ThePacket;
                    435: 
                    436:     s = ExInterlockedPopEntryList (
                    437:             &DeviceContext->PacketPool,
                    438:             &DeviceContext->Interlock);
                    439: 
                    440:     if (s == NULL) {
                    441:         ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    442:         ++DeviceContext->PacketExhausted;
                    443:         RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    444:         return STATUS_INSUFFICIENT_RESOURCES;
                    445:     }
                    446: 
                    447:     ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage);
                    448: 
                    449:     ThePacket->Provider = DeviceContext;   // who owns this packet
                    450:     ThePacket->PacketSent = FALSE;
                    451:     ThePacket->PacketNoNdisBuffer = FALSE;
                    452: 
                    453:     *Packet = ThePacket;                // return pointer to the packet.
                    454:     return STATUS_SUCCESS;
                    455: } /* StCreatePacket */
                    456: 
                    457: 
                    458: VOID
                    459: StDestroyPacket(
                    460:     PTP_PACKET Packet
                    461:     )
                    462: 
                    463: /*++
                    464: 
                    465: Routine Description:
                    466: 
                    467:     This routine destroys a packet, thereby returning it to the pool.  If
                    468:     it is determined that there is at least one connection waiting for a
                    469:     packet to become available (and it just has), then the connection is
                    470:     removed from the device context's list and AdvanceSend is called to
                    471:     prep the connection further.
                    472: 
                    473: Arguments:
                    474: 
                    475:     Packet - Pointer to a packet to be returned to the pool.
                    476: 
                    477: Return Value:
                    478: 
                    479:     none.
                    480: 
                    481: --*/
                    482: 
                    483: {
                    484:     KIRQL oldirql1;
                    485:     PDEVICE_CONTEXT DeviceContext;
                    486:     PTP_CONNECTION Connection;
                    487:     PLIST_ENTRY p;
                    488:     PNDIS_BUFFER HeaderBuffer;
                    489:     PNDIS_BUFFER NdisBuffer;
                    490: 
                    491: 
                    492:     //
                    493:     // Strip off and unmap the buffers describing data and header.
                    494:     //
                    495: 
                    496:     NdisUnchainBufferAtFront (Packet->NdisPacket, &HeaderBuffer);
                    497: 
                    498:     // data buffers get thrown away
                    499: 
                    500:     if (Packet->PacketNoNdisBuffer) {
                    501: 
                    502:         //
                    503:         // If the NDIS_BUFFER chain is not ours, then we can't
                    504:         // start unchaining since that would mess up the queue;
                    505:         // instead we just drop the rest of the chain.
                    506:         //
                    507: 
                    508:         NdisReinitializePacket (Packet->NdisPacket);
                    509: 
                    510:     } else {
                    511: 
                    512:         //
                    513:         // Return all the NDIS_BUFFERs to the system.
                    514:         //
                    515: 
                    516:         NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
                    517:         while (NdisBuffer != NULL) {
                    518:             NdisFreeBuffer (NdisBuffer);
                    519:             NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
                    520:         }
                    521: 
                    522:     }
                    523: 
                    524:     ASSERT (HeaderBuffer != NULL);
                    525:     NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
                    526: 
                    527:     NdisChainBufferAtFront (Packet->NdisPacket, HeaderBuffer);
                    528: 
                    529: 
                    530:     //
                    531:     // Put the packet back for use again.
                    532:     //
                    533: 
                    534:     DeviceContext = Packet->Provider;
                    535: 
                    536:     ExInterlockedPushEntryList (
                    537:             &DeviceContext->PacketPool,
                    538:             (PSINGLE_LIST_ENTRY)&Packet->Linkage,
                    539:             &DeviceContext->Interlock);
                    540: 
                    541:     //
                    542:     // If there is a connection waiting to ship out more packets, then
                    543:     // wake it up and start packetizing again.
                    544:     //
                    545:     // We do a quick check without the lock; there is a small
                    546:     // window where we may not take someone off, but this
                    547:     // window exists anyway and we assume that more packets
                    548:     // will be freed in the future.
                    549:     //
                    550: 
                    551:     if (IsListEmpty (&DeviceContext->PacketWaitQueue)) {
                    552:         return;
                    553:     }
                    554: 
                    555:     p = ExInterlockedRemoveHeadList(
                    556:         &DeviceContext->PacketWaitQueue,
                    557:         &DeviceContext->SpinLock);
                    558: 
                    559:     if (p != NULL) {
                    560: 
                    561:         //
                    562:         // Remove a connection from the "packet starved" queue.
                    563:         //
                    564: 
                    565:         Connection = CONTAINING_RECORD (p, TP_CONNECTION, PacketWaitLinkage);
                    566:         ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql1);
                    567:         Connection->Flags &= ~CONNECTION_FLAGS_SUSPENDED;
                    568: 
                    569:         //
                    570:         // Place the connection on the packetize queue and start
                    571:         // packetizing the next connection to be serviced.  If he
                    572:         // is already on the packetize queue for some reason, then
                    573:         // don't do this.
                    574:         //
                    575: 
                    576:         Connection->SendState = CONNECTION_SENDSTATE_PACKETIZE;
                    577: 
                    578:         if (!(Connection->Flags & CONNECTION_FLAGS_STOPPING) &&
                    579:             !(Connection->Flags & CONNECTION_FLAGS_PACKETIZE)) {
                    580: 
                    581:             Connection->Flags |= CONNECTION_FLAGS_PACKETIZE;
                    582: 
                    583:             StReferenceConnection ("Packet available", Connection);
                    584: 
                    585:             ExInterlockedInsertTailList(
                    586:                 &DeviceContext->PacketizeQueue,
                    587:                 &Connection->PacketizeLinkage,
                    588:                 &DeviceContext->SpinLock);
                    589:         }
                    590: 
                    591:         RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql1);
                    592:         PacketizeConnections (DeviceContext);
                    593: 
                    594:     }
                    595: 
                    596: } /* StDestroyPacket */
                    597: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.