Main Page   Modules   Data Structures   File List   Data Fields   Globals  

Write.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999, 2000
00003  *  Politecnico di Torino.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that: (1) source code distributions
00007  * retain the above copyright notice and this paragraph in its entirety, (2)
00008  * distributions including binary code include the above copyright notice and
00009  * this paragraph in its entirety in the documentation or other materials
00010  * provided with the distribution, and (3) all advertising materials mentioning
00011  * features or use of this software display the following acknowledgement:
00012  * ``This product includes software developed by the Politecnico
00013  * di Torino, and its contributors.'' Neither the name of
00014  * the University nor the names of its contributors may be used to endorse
00015  * or promote products derived from this software without specific prior
00016  * written permission.
00017  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00020  */
00021 
00022 #include "stdarg.h"
00023 #include "ntddk.h"
00024 #include "ntiologc.h"
00025 #include "ndis.h"
00026 
00027 #include "debug.h"
00028 #include "packet.h"
00029 
00030 
00031 //-------------------------------------------------------------------
00032 
00033 NTSTATUS
00034 NPF_Write(
00035     IN PDEVICE_OBJECT DeviceObject,
00036     IN PIRP Irp
00037     )
00038 
00039 {
00040     POPEN_INSTANCE      Open;
00041     PIO_STACK_LOCATION  IrpSp;
00042     PNDIS_PACKET        pPacket;
00043     UINT                i;
00044     NDIS_STATUS         Status;
00045 
00046 
00047     IF_LOUD(DbgPrint("Packet: SendAdapter\n");)
00048 
00049     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00050 
00051 
00052     Open=IrpSp->FileObject->FsContext;
00053 
00054     // Check the length of the packet to avoid to use an empty packet
00055     if(IrpSp->Parameters.Write.Length==0)
00056     {
00057         Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
00058         IoCompleteRequest (Irp, IO_NO_INCREMENT);
00059         return NDIS_STATUS_SUCCESS;
00060     }
00061 
00062 
00063     IoMarkIrpPending(Irp);
00064 
00065     Open->Multiple_Write_Counter=Open->Nwrites;
00066 
00067     NdisResetEvent(&Open->WriteEvent);
00068 
00069 
00070     for(i=0;i<Open->Nwrites;i++){
00071         
00072         //  Try to get a packet from our list of free ones
00073         NdisAllocatePacket(
00074             &Status,
00075             &pPacket,
00076             Open->PacketPool
00077             );
00078         
00079         if (Status != NDIS_STATUS_SUCCESS) {
00080             
00081             //  No free packets
00082             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
00083             IoCompleteRequest (Irp, IO_NO_INCREMENT);
00084             return STATUS_INSUFFICIENT_RESOURCES;
00085         }
00086         
00087         // The packet has a buffer that needs not to be freed after every single write
00088         RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
00089 
00090         // Save the IRP associated with the packet
00091         RESERVED(pPacket)->Irp=Irp;
00092         
00093         //  Attach the writes buffer to the packet
00094         NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
00095         
00096         //  Call the MAC
00097         NdisSend(
00098             &Status,
00099             Open->AdapterHandle,
00100             pPacket);
00101 
00102         if (Status != NDIS_STATUS_PENDING) {
00103             //  The send didn't pend so call the completion handler now
00104             NPF_SendComplete(
00105                 Open,
00106                 pPacket,
00107                 Status
00108                 );
00109             
00110         }
00111         
00112         if(i%100==99){
00113             NdisWaitEvent(&Open->WriteEvent,1000);  
00114             NdisResetEvent(&Open->WriteEvent);
00115         }
00116     }
00117     
00118     return(STATUS_PENDING);
00119 
00120 }
00121 
00122 
00123 //-------------------------------------------------------------------
00124 
00125 INT
00126 NPF_BufferedWrite(
00127     IN PIRP Irp, 
00128     IN PCHAR UserBuff, 
00129     IN ULONG UserBuffSize, 
00130     BOOLEAN Sync)
00131 {
00132     POPEN_INSTANCE      Open;
00133     PIO_STACK_LOCATION  IrpSp;
00134     PNDIS_PACKET        pPacket;
00135     UINT                i;
00136     NDIS_STATUS         Status;
00137     LARGE_INTEGER       StartTicks, CurTicks, TargetTicks;
00138     LARGE_INTEGER       TimeFreq;
00139     struct timeval      BufStartTime;
00140     struct sf_pkthdr    *winpcap_hdr;
00141     PMDL                TmpMdl;
00142     PCHAR               CurPos;
00143     PCHAR               EndOfUserBuff = UserBuff + UserBuffSize;
00144     
00145     IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
00146         
00147     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00148     
00149     Open=IrpSp->FileObject->FsContext;
00150     
00151     // Security check on the length of the user buffer
00152     if(UserBuff==0)
00153     {
00154         return 0;
00155     }
00156         
00157     // Start from the first packet
00158     winpcap_hdr = (struct sf_pkthdr*)UserBuff;
00159     
00160     // Retrieve the time references
00161     StartTicks = KeQueryPerformanceCounter(&TimeFreq);
00162     BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
00163     BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
00164     
00165     // Chech the consistency of the user buffer
00166     if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
00167     {
00168         IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
00169 
00170         return -1;
00171     }
00172     
00173     // Save the current time stamp counter
00174     CurTicks = KeQueryPerformanceCounter(NULL);
00175     
00176     // Main loop: send the buffer to the wire
00177     while( TRUE ){
00178         
00179         if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > 65536)
00180         {
00181             // Malformed header
00182             IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed user buffer, aborting write.\n");)
00183             
00184             return -1;
00185         }
00186         
00187         // Allocate an MDL to map the packet data
00188         TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
00189             winpcap_hdr->caplen,
00190             FALSE,
00191             FALSE,
00192             NULL);
00193         
00194         if (TmpMdl == NULL)
00195         {
00196             // Unable to map the memory: packet lost
00197             IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
00198 
00199             return -1;
00200         }
00201         
00202         MmBuildMdlForNonPagedPool(TmpMdl);  // XXX can this line be removed?
00203         
00204         // Allocate a packet from our free list
00205         NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
00206         
00207         if (Status != NDIS_STATUS_SUCCESS) {
00208             //  No free packets
00209             IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
00210 
00211             return (PCHAR)winpcap_hdr - UserBuff;
00212         }
00213         
00214         // The packet has a buffer that needs to be freed after every single write
00215         RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
00216         
00217         // Attach the MDL to the packet
00218         NdisChainBufferAtFront(pPacket,TmpMdl);
00219         
00220         // Call the MAC
00221         NdisSend( &Status, Open->AdapterHandle, pPacket);
00222         
00223         if (Status != NDIS_STATUS_PENDING) {
00224             // The send didn't pend so call the completion handler now
00225             NPF_SendComplete(
00226                 Open,
00227                 pPacket,
00228                 Status
00229                 );              
00230         }
00231         
00232         // Step to the next packet in the buffer
00233         (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
00234         
00235         // Check if the end of the user buffer has been reached
00236         if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
00237         {
00238             IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
00239 
00240             return (PCHAR)winpcap_hdr - UserBuff;
00241         }
00242         
00243         if( Sync ){
00244             
00245             // Release the application if it has been blocked for approximately more than 1 seconds
00246             if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
00247             {
00248                 IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
00249                     
00250                 return (PCHAR)winpcap_hdr - UserBuff;
00251             }
00252             
00253             // Calculate the time interval to wait before sending the next packet
00254             TargetTicks.QuadPart = StartTicks.QuadPart +
00255                 (LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
00256                 winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
00257                 (TimeFreq.QuadPart) / 1000000;
00258             
00259             // Wait until the time interval has elapsed
00260             while( CurTicks.QuadPart <= TargetTicks.QuadPart )
00261                 CurTicks = KeQueryPerformanceCounter(NULL);
00262         }
00263         
00264     }
00265                 
00266     return (PCHAR)winpcap_hdr - UserBuff;
00267         
00268 }
00269 
00270 
00271 //-------------------------------------------------------------------
00272 
00273 VOID
00274 NPF_SendComplete(
00275                    IN NDIS_HANDLE   ProtocolBindingContext,
00276                    IN PNDIS_PACKET  pPacket,
00277                    IN NDIS_STATUS   Status
00278                    )
00279                    
00280 {
00281     PIRP              Irp;
00282     PIO_STACK_LOCATION  irpSp;
00283     POPEN_INSTANCE      Open;
00284     PMDL TmpMdl;
00285     
00286     IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
00287         
00288     Open= (POPEN_INSTANCE)ProtocolBindingContext;
00289     
00290     if( RESERVED(pPacket)->FreeBufAfterWrite ){
00291         // Free the MDL associated with the packet
00292         NdisUnchainBufferAtFront(pPacket, &TmpMdl);
00293         IoFreeMdl(TmpMdl);
00294     }
00295     else{
00296         if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
00297             NdisSetEvent(&Open->WriteEvent);
00298         
00299         Open->Multiple_Write_Counter--;
00300     }
00301     
00302     //  recyle the packet
00303     NdisReinitializePacket(pPacket);
00304     
00305     //  Put the packet back on the free list
00306     NdisFreePacket(pPacket);
00307     
00308     if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
00309         if(Open->Multiple_Write_Counter==0){
00310             // Release the buffer and awake the application
00311             NdisUnchainBufferAtFront(pPacket, &TmpMdl);
00312             
00313             Irp=RESERVED(pPacket)->Irp;
00314             irpSp = IoGetCurrentIrpStackLocation(Irp);
00315 
00316             Irp->IoStatus.Status = Status;
00317             Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
00318             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00319             
00320         }
00321     }
00322 
00323     return;
00324 }

documentation. Copyright (c) 2002 Politecnico di Torino. All rights reserved.