Annotation of ntddk/src/network/tdi/packet.c, revision 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.