Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

Read.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999 - 2003
00003  * NetGroup, Politecnico di Torino (Italy)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  * notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  * notice, this list of conditions and the following disclaimer in the
00014  * documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
00016  * contributors may be used to endorse or promote products derived from
00017  * this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  */
00032 
00033 #include <stdarg.h>
00034 #include "ntddk.h"
00035 #include <ntiologc.h>
00036 #include <ndis.h>
00037 #include "debug.h"
00038 #include "packet.h"
00039 #include "win_bpf.h"
00040 
00041 #include "tme.h"
00042 #include "time_calls.h"
00043 
00044 extern struct time_conv G_Start_Time; // from openclos.c
00045 
00046 extern ULONG NCpu; //from packet.c
00047 
00048 NTSTATUS NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
00049 {
00050     POPEN_INSTANCE      Open;
00051     PIO_STACK_LOCATION  IrpSp;
00052     PUCHAR              packp;
00053     ULONG               Input_Buffer_Length;
00054     UINT                Thead;
00055     UINT                Ttail;
00056     UINT                TLastByte;
00057     PUCHAR              CurrBuff;
00058     LARGE_INTEGER       CapTime;
00059     LARGE_INTEGER       TimeFreq;
00060     struct bpf_hdr      *header;
00061     KIRQL               Irql;
00062     PUCHAR              UserPointer;
00063     ULONG               bytecopy;
00064     UINT                SizeToCopy;
00065     UINT                PktLen;
00066     ULONG               copied,count,current_cpu,av,plen,increment,ToCopy,available;
00067     CpuPrivateData      *LocalData;
00068     ULONG               i;
00069     ULONG               Occupation;
00070     IF_LOUD(DbgPrint("NPF: Read\n");)
00071         
00072     IrpSp = IoGetCurrentIrpStackLocation(Irp);
00073     Open=IrpSp->FileObject->FsContext;
00074 
00075     if( Open->Bound == FALSE )
00076     {
00077         // The Network adapter has been removed or diasabled
00078         EXIT_FAILURE(0);
00079     }
00080     
00081     if (Open->Size == 0)    
00082     {
00083         EXIT_FAILURE(0);
00084     }
00085 
00086     if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){  
00087         // this instance is in dump mode, but the dump file has still not been opened
00088         EXIT_FAILURE(0);
00089     }
00090     
00091     Occupation=0;
00092 
00093     for(i=0;i<NCpu;i++)
00094         Occupation += (Open->Size - Open->CpuData[i].Free);
00095     
00096     //See if the buffer is full enough to be copied
00097     if( Occupation <= Open->MinToCopy*NCpu || Open->mode & MODE_DUMP )
00098     {
00099         //wait until some packets arrive or the timeout expires     
00100         if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
00101             KeWaitForSingleObject(Open->ReadEvent,
00102                 UserRequest,
00103                 KernelMode,
00104                 TRUE,
00105                 (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
00106 
00107         KeClearEvent(Open->ReadEvent);
00108         
00109         if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
00110 #ifdef NDIS50
00111             CurrBuff=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
00112 #else
00113             CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
00114 #endif
00115 
00116             //fill the bpf header for this packet
00117             header=(struct bpf_hdr*)CurrBuff;
00118             GET_TIME(&header->bh_tstamp,&G_Start_Time);
00119 
00120             if(Open->mode & MODE_DUMP){
00121                 *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
00122                 header->bh_caplen=24;
00123                 header->bh_datalen=24;
00124                 Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
00125             }
00126             else{
00127                 header->bh_caplen=16;
00128                 header->bh_datalen=16;
00129                 header->bh_hdrlen=sizeof(struct bpf_hdr);
00130                 Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
00131             }
00132 
00133             *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
00134             *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
00135             
00136             //reset the countetrs
00137             NdisAcquireSpinLock( &Open->CountersLock );
00138             Open->Npackets.QuadPart=0;
00139             Open->Nbytes.QuadPart=0;
00140             NdisReleaseSpinLock( &Open->CountersLock );
00141             
00142             Irp->IoStatus.Status = STATUS_SUCCESS;
00143             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00144             
00145             return STATUS_SUCCESS;
00146         }
00147         
00148         if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
00149         {   
00150             PTME_DATA data;
00151             ULONG cnt;
00152             ULONG block_size;
00153             PUCHAR tmp;
00154 
00155 #ifdef NDIS50
00156             UserPointer=MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
00157 #else
00158             UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
00159 #endif
00160 
00161             if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
00162             {   
00163                 EXIT_FAILURE(0);
00164             }
00165             
00166             header=(struct bpf_hdr*)UserPointer;
00167     
00168             GET_TIME(&header->bh_tstamp,&G_Start_Time);
00169 
00170             
00171             header->bh_hdrlen=sizeof(struct bpf_hdr);
00172             
00173 
00174             //moves user memory pointer
00175             UserPointer+=sizeof(struct bpf_hdr);
00176             
00177             //calculus of data to be copied
00178             //if the user buffer is smaller than data to be copied,
00179             //only some data will be copied
00180             data=&Open->tme.block_data[Open->tme.active_read];
00181 
00182             if (data->last_read.tv_sec!=0)
00183                 data->last_read=header->bh_tstamp;
00184             
00185 
00186             bytecopy=data->block_size*data->filled_blocks;
00187             
00188             if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
00189                 bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
00190             else 
00191                 bytecopy=data->filled_blocks;
00192 
00193             tmp=data->shared_memory_base_address;
00194             block_size=data->block_size;
00195             
00196             for (cnt=0;cnt<bytecopy;cnt++)
00197             {
00198                 NdisAcquireSpinLock(&Open->MachineLock);
00199                 RtlCopyMemory(UserPointer,tmp,block_size);
00200                 NdisReleaseSpinLock(&Open->MachineLock);
00201                 tmp+=block_size;
00202                 UserPointer+=block_size;
00203             }
00204                         
00205             bytecopy*=block_size;
00206 
00207             header->bh_caplen=bytecopy;
00208             header->bh_datalen=header->bh_caplen;
00209 
00210             EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
00211         }
00212 
00213         Occupation=0;
00214 
00215         for(i=0;i<NCpu;i++)
00216             Occupation += (Open->Size - Open->CpuData[i].Free);
00217 
00218 
00219         if ( Occupation == 0 || Open->mode & MODE_DUMP)
00220             // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
00221             // We must awake the application, returning an empty buffer.
00222         {
00223             EXIT_SUCCESS(0);
00224         }
00225                 
00226     }
00227 
00228 
00229 
00230 
00231 //------------------------------------------------------------------------------
00232     copied=0;
00233     count=0;
00234     current_cpu=0;
00235     available = IrpSp->Parameters.Read.Length;
00236 #ifdef NDIS50
00237     packp=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
00238 #else
00239     packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
00240 #endif
00241 
00242 
00243     KeClearEvent(Open->ReadEvent);
00244 
00245     while (count < NCpu) //round robin on the CPUs, if count = NCpu there are no packets left to be copied
00246     {
00247         if (available == copied)
00248         {
00249             EXIT_SUCCESS(copied);
00250         }
00251         
00252         LocalData = &Open->CpuData[current_cpu];
00253 
00254         if (LocalData->Free < Open->Size)  
00255         {  //there are some packets in the selected (aka LocalData) buffer
00256             struct PacketHeader *Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->C);
00257 
00258             if ( Header->SN == Open->ReaderSN)
00259             {   //check if it the next one to be copied
00260                 plen = Header->header.bh_caplen;
00261                 if (plen + sizeof (struct bpf_hdr) > available-copied)  
00262                 {  //if the packet does not fit into the user buffer, we've ended copying packets
00263                     EXIT_SUCCESS(copied);
00264                 }
00265                 
00266 //              FIX_TIMESTAMPS(&Header->header.bh_tstamp);
00267 
00268                 *((struct bpf_hdr*)(&packp[copied]))=Header->header;
00269                 
00270                 copied += sizeof(struct bpf_hdr);
00271                 LocalData->C += sizeof(struct PacketHeader);
00272 
00273                 if (LocalData->C == Open->Size)
00274                     LocalData->C = 0;
00275 
00276                 if (Open->Size - LocalData->C < plen)
00277                 {
00278                     //the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
00279                     ToCopy = Open->Size - LocalData->C;
00280                     RtlCopyMemory(packp + copied,LocalData->Buffer + LocalData->C,ToCopy);
00281                     RtlCopyMemory(packp + copied + ToCopy,LocalData->Buffer,plen-ToCopy);
00282                     LocalData->C = plen-ToCopy;
00283                 }
00284                 else
00285                 {
00286                     //the packet is not fragmented
00287                     RtlCopyMemory(packp + copied ,LocalData->Buffer + LocalData->C ,plen);
00288                     LocalData->C += plen;
00289             //      if (c==size)  inutile, contemplato nell "header atomico"
00290             //          c=0;
00291                 }
00292 
00293                 Open->ReaderSN++;
00294                 copied+=Packet_WORDALIGN(plen);
00295 
00296                 increment = plen + sizeof(struct PacketHeader);
00297                 if ( Open->Size - LocalData->C < sizeof(struct PacketHeader))
00298                 {   //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
00299                     //so the producer (--> the consumer) skips to the beginning of the buffer
00300                     increment += Open->Size-LocalData->C;
00301                     LocalData->C=0;
00302                 }
00303                 InterlockedExchangeAdd(&Open->CpuData[current_cpu].Free,increment);
00304                 count=0;
00305             }
00306             else
00307             {
00308                 current_cpu=(current_cpu+1)%NCpu;
00309                 count++;    
00310             }
00311         
00312         }
00313         else
00314         {
00315             current_cpu=(current_cpu+1)%NCpu;
00316             count++;    
00317         }
00318     }
00319         
00320     {EXIT_SUCCESS(copied);}
00321 
00322 //------------------------------------------------------------------------------
00323 
00324 }
00325 
00326 NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
00327                         IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookaheadBuffer,
00328                         IN UINT LookaheadBufferSize,IN UINT PacketSize)
00329 {
00330     POPEN_INSTANCE      Open;
00331     PNDIS_PACKET        pPacket;
00332     ULONG               SizeToTransfer;
00333     NDIS_STATUS         Status;
00334     UINT                BytesTransfered;
00335     ULONG               BufferLength;
00336     PMDL                pMdl1,pMdl2;
00337     LARGE_INTEGER       CapTime;
00338     LARGE_INTEGER       TimeFreq;
00339     UINT                fres;
00340     USHORT              NPFHdrSize;
00341 
00342     CpuPrivateData      *LocalData;
00343     ULONG               Cpu;
00344     struct PacketHeader *Header;
00345     ULONG               ToCopy;
00346     ULONG               increment;
00347     ULONG               i;
00348     BOOLEAN             Flag;
00349 
00350     IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
00351     IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n", 
00352     HeaderBufferSize,
00353     LookaheadBuffer,
00354     LookaheadBufferSize,
00355     PacketSize);)
00356 
00357     Open= (POPEN_INSTANCE)ProtocolBindingContext;
00358     
00359     if (Open->SkipProcessing == 1)  //some IoCtl is modifying some shared structure, we must drop the packet.
00360         return NDIS_STATUS_NOT_ACCEPTED;
00361     
00362     Cpu = KeGetCurrentProcessorNumber();
00363     LocalData = &Open->CpuData[Cpu];
00364 
00365     LocalData->Processing = 1;    //this tells the Ioctls that we are processing a packet, they cannot modify anything
00366                                   //until ALL the Cpu have terminated their processing (aka, set their LocalData->processing to 0)
00367     LocalData->Received++;
00368     IF_LOUD(DbgPrint("Received on CPU %d \t%d\n",Cpu,LocalData->Received);)
00369 //  Open->Received++;       // Number of packets received by filter ++
00370 
00371     if (Open->mode == MODE_MON)
00372     {
00373         Flag = TRUE;
00374         NdisAcquireSpinLock(&Open->MachineLock);
00375     }
00376     else
00377         Flag = FALSE;
00378     
00379     //
00380     //Check if the lookahead buffer follows the mac header.
00381     //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
00382     //executed on the packet.
00383     //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
00384     //things like this) bpf_filter_with_2_buffers() is executed.
00385     //
00386     if((UINT)LookaheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
00387         fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
00388                                        HeaderBuffer,
00389                                        LookaheadBuffer,
00390                                        HeaderBufferSize,
00391                                        PacketSize+HeaderBufferSize,
00392                                        LookaheadBufferSize+HeaderBufferSize,
00393                                        &Open->mem_ex,
00394                                        &Open->tme,
00395                                        &G_Start_Time);
00396     
00397     
00398     else 
00399         if(Open->Filter != NULL)
00400         {
00401             if (Open->bpfprogram != NULL)
00402             {
00403                 fres=Open->Filter->Function(HeaderBuffer,
00404                                     PacketSize+HeaderBufferSize,
00405                                     LookaheadBufferSize+HeaderBufferSize);
00406         
00407                 // Restore the stack. 
00408                 // I ignore the reason, but this instruction is needed only at kernel level
00409                 _asm add esp,12     
00410             }
00411             else
00412                 fres = -1;
00413         }
00414         else
00415             fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
00416                         HeaderBuffer,
00417                         PacketSize+HeaderBufferSize,
00418                         LookaheadBufferSize+HeaderBufferSize,
00419                         &Open->mem_ex,
00420                         &Open->tme,
00421                         &G_Start_Time);
00422 
00423     if (Flag)
00424         NdisReleaseSpinLock(&Open->MachineLock);
00425     
00426     if(Open->mode==MODE_MON)
00427     // we are in monitor mode
00428     {
00429         if (fres==1) 
00430             KeSetEvent(Open->ReadEvent,0,FALSE);
00431         LocalData->Processing = 0;
00432         return NDIS_STATUS_NOT_ACCEPTED;
00433 
00434     }
00435 
00436     if(fres==0)
00437     {
00438         // Packet not accepted by the filter, ignore it.
00439         LocalData->Processing = 0;
00440         return NDIS_STATUS_NOT_ACCEPTED;
00441     }
00442 
00443     //if the filter returns -1 the whole packet must be accepted
00444     if(fres==-1 || fres > PacketSize+HeaderBufferSize)
00445         fres = PacketSize+HeaderBufferSize; 
00446 
00447     if(Open->mode & MODE_STAT)
00448     {
00449     // we are in statistics mode
00450         NdisAcquireSpinLock( &Open->CountersLock );
00451 
00452         Open->Npackets.QuadPart++;
00453         
00454         if(PacketSize+HeaderBufferSize<60)
00455             Open->Nbytes.QuadPart+=60;
00456         else
00457             Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
00458         // add preamble+SFD+FCS to the packet
00459         // these values must be considered because are not part of the packet received from NDIS
00460         Open->Nbytes.QuadPart+=12;
00461 
00462         NdisReleaseSpinLock( &Open->CountersLock );
00463         
00464         if(!(Open->mode & MODE_DUMP))
00465         {
00466             LocalData->Processing = 0;
00467             return NDIS_STATUS_NOT_ACCEPTED;
00468         }
00469     }
00470 
00471     if(Open->Size == 0)
00472     {
00473         LocalData->Dropped++;
00474         LocalData->Processing = 0;
00475         return NDIS_STATUS_NOT_ACCEPTED;
00476     }
00477 
00478     if(Open->mode & MODE_DUMP && Open->MaxDumpPacks)
00479     {
00480         ULONG Accepted=0;
00481         for(i=0;i<NCpu;i++)
00482             Accepted+=Open->CpuData[i].Accepted;
00483         
00484         if(  Accepted > Open->MaxDumpPacks)
00485         {
00486             // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
00487             Open->DumpLimitReached = TRUE; // This stops the thread
00488             // Awake the dump thread
00489             NdisSetEvent(&Open->DumpEvent);
00490 
00491             // Awake the application
00492             KeSetEvent(Open->ReadEvent,0,FALSE);
00493 
00494             LocalData->Processing = 0;
00495             return NDIS_STATUS_NOT_ACCEPTED;
00496         }
00497     }
00498 
00500 
00501     if (fres + sizeof(struct PacketHeader) > LocalData->Free)
00502     {
00503         LocalData->Dropped++;
00504         LocalData->Processing = 0;
00505         return NDIS_STATUS_NOT_ACCEPTED;
00506     }
00507 
00508     if (LocalData->TransferMdl1 != NULL)
00509     {
00510         //if TransferMdl is not NULL, there is some TransferData pending (i.e. not having called TransferDataComplete, yet)
00511         //in order to avoid buffer corruption, we drop the packet
00512         LocalData->Dropped++;
00513         LocalData->Processing = 0;
00514         return NDIS_STATUS_NOT_ACCEPTED;
00515     }
00516 
00517 
00518     if (LookaheadBufferSize + HeaderBufferSize >= fres)
00519     {
00520         //we do not need to call NdisTransferData, either because we need only the HeaderBuffer, or because the LookaheadBuffer
00521         //contains what we need
00522 
00523         
00524 
00525         Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
00526         LocalData->Accepted++;
00527         GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
00528         Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
00529 
00530         Header->header.bh_caplen = fres;
00531         Header->header.bh_datalen = PacketSize + HeaderBufferSize;
00532         Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
00533 
00534         LocalData->P +=sizeof(struct PacketHeader);
00535         if (LocalData->P == Open->Size)
00536             LocalData->P = 0;
00537 
00538         if ( fres <= HeaderBufferSize || ( (ULONG)LookaheadBuffer - (ULONG)HeaderBuffer ) == HeaderBufferSize )
00539         {
00540             //we can consider the buffer contiguous, either because we use only the data 
00541             //present in the HeaderBuffer, or because HeaderBuffer and LookaheadBuffer are contiguous
00542             // ;-))))))
00543 
00544             if (Open->Size - LocalData->P < fres)
00545             {
00546                 //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
00547                 //two copies!!
00548                 ToCopy = Open->Size - LocalData->P;
00549                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P,HeaderBuffer, ToCopy);
00550                 NdisMoveMappedMemory(LocalData->Buffer + 0 , (PUCHAR)HeaderBuffer + ToCopy, fres - ToCopy);
00551                 LocalData->P = fres-ToCopy;
00552             }
00553             else
00554             {
00555                 //the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
00556                 // ;-)))))) only ONE copy
00557                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, fres);
00558                 LocalData->P += fres;
00559             }
00560         }
00561         else
00562         {
00563             //HeaderBuffer and LookAhead buffer are NOT contiguous,
00564             //AND, we need some bytes from the LookaheadBuffer, too
00565             if (Open->Size - LocalData->P < fres)
00566             {
00567                 //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
00568                 if (Open->Size - LocalData->P >= HeaderBufferSize)
00569                 {
00570                     //HeaderBuffer is NOT fragmented
00571                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
00572                     LocalData->P += HeaderBufferSize;
00573                     
00574                     if (LocalData->P == Open->Size)
00575                     {
00576                         //the fragmentation of the packet in the buffer is the same fragmentation
00577                         //in HeaderBuffer+LookaheadBuffer
00578                         LocalData->P=0; 
00579                         NdisMoveMappedMemory(LocalData->Buffer + 0, LookaheadBuffer, fres - HeaderBufferSize);
00580                         LocalData->P += (fres - HeaderBufferSize);
00581                     }
00582                     else
00583                     {
00584                         //LookAheadBuffer is fragmented, two copies
00585                         ToCopy = Open->Size - LocalData->P;
00586                         NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, ToCopy);
00587                         LocalData->P=0;
00588                         NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer+ ToCopy, fres - HeaderBufferSize - ToCopy);
00589                         LocalData->P = fres - HeaderBufferSize - ToCopy;
00590                     }
00591                 }
00592                 else
00593                 {
00594                     //HeaderBuffer is fragmented in the buffer (aka, it will skip the buffer boundary)
00595                     //two copies to copy the HeaderBuffer
00596                     ToCopy = Open->Size - LocalData->P;
00597                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, ToCopy);
00598                     LocalData->P = 0;
00599                     NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
00600                     LocalData->P = HeaderBufferSize - ToCopy;
00601                     
00602                     //only one copy to copy the LookaheadBuffer
00603                     NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres- HeaderBufferSize);
00604                     LocalData->P += (fres - HeaderBufferSize);
00605                 }
00606             }
00607             else
00608             {   
00609                 //the packet won't be fragmented in the destination buffer (aka, it won't skip the buffer boundary)
00610                 //two copies, the former to copy the HeaderBuffer, the latter to copy the LookaheadBuffer
00611                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
00612                 LocalData->P += HeaderBufferSize;
00613                 NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres - HeaderBufferSize);
00614                 LocalData->P += (fres - HeaderBufferSize);
00615             }        
00616         }       
00617 
00618         increment = fres + sizeof(struct PacketHeader);
00619         if (Open->Size - LocalData->P < sizeof(struct PacketHeader))  //we check that the available, AND contiguous, space in the buffer will fit
00620         {                                                          //the NewHeader structure, at least, otherwise we skip the producer
00621             increment += Open->Size-LocalData->P;                  //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
00622             LocalData->P = 0;
00623         }
00624 
00625         InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
00626         if(Open->Size - LocalData->Free >= Open->MinToCopy)
00627         {
00628             if(Open->mode & MODE_DUMP)
00629                 NdisSetEvent(&Open->DumpEvent);
00630             else
00631                 KeSetEvent(Open->ReadEvent,0,FALSE);    
00632         }
00633 
00634         LocalData->Processing = 0;
00635         return NDIS_STATUS_NOT_ACCEPTED;
00636     }
00637     else
00638     {
00639         IF_LOUD(DbgPrint("TransferData!!\n");)
00640         //ndisTransferData required
00641         LocalData->NewP = LocalData->P;
00642 
00643         LocalData->NewP +=sizeof(struct PacketHeader);
00644         if (LocalData->NewP == Open->Size)
00645             LocalData->NewP = 0;
00646 
00647         //first of all, surely the header must be copied
00648         if (Open->Size-LocalData->NewP >= HeaderBufferSize)
00649         {
00650             //1 copy!
00651             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, HeaderBufferSize);
00652             LocalData->NewP += HeaderBufferSize;
00653             if (LocalData->NewP == Open->Size)
00654                 LocalData->NewP = 0;
00655         }
00656         else
00657         {
00658             ToCopy = Open->Size - LocalData->NewP;
00659             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, ToCopy);
00660             NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
00661             LocalData->NewP = HeaderBufferSize - ToCopy;
00662         }
00663 
00664         //then we copy the Lookahead buffer
00665 
00666         if (Open->Size-LocalData->NewP >= LookaheadBufferSize)
00667         {
00668             //1 copy!
00669             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, LookaheadBufferSize);
00670             LocalData->NewP += LookaheadBufferSize;
00671             if (LocalData->NewP == Open->Size)
00672                 LocalData->NewP = 0;
00673         }
00674         else
00675         {
00676             ToCopy = Open->Size - LocalData->NewP;
00677             NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, ToCopy);
00678             NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer + ToCopy, LookaheadBufferSize - ToCopy);
00679             LocalData->NewP = LookaheadBufferSize - ToCopy;
00680         }
00681 
00682         //Now we must prepare the buffer(s) for the NdisTransferData
00683         if ((Open->Size - LocalData->NewP) >= (fres - HeaderBufferSize - LookaheadBufferSize))
00684         {
00685             //only 1 buffer
00686             pMdl1 = IoAllocateMdl(
00687                 LocalData->Buffer + LocalData->NewP, 
00688                 fres - HeaderBufferSize - LookaheadBufferSize,
00689                 FALSE,
00690                 FALSE,
00691                 NULL);
00692             
00693             if (pMdl1 == NULL)
00694             {
00695                 IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
00696                 LocalData->Dropped++;
00697                 LocalData->Processing = 0;
00698                 return NDIS_STATUS_NOT_ACCEPTED;
00699             }
00700 
00701             MmBuildMdlForNonPagedPool(pMdl1);
00702             pMdl2=NULL;
00703             LocalData->NewP += fres - HeaderBufferSize - LookaheadBufferSize;
00704 
00705 
00706         }
00707         else
00708         {
00709             //2 buffers
00710             pMdl1 = IoAllocateMdl(
00711                 LocalData->Buffer + LocalData->NewP, 
00712                 Open->Size - LocalData->NewP,
00713                 FALSE,
00714                 FALSE,
00715                 NULL);
00716             
00717             if (pMdl1 == NULL)
00718             {
00719                 IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
00720                 LocalData->Dropped++;
00721                 LocalData->Processing = 0;
00722                 return NDIS_STATUS_NOT_ACCEPTED;
00723             }
00724 
00725             pMdl2 = IoAllocateMdl(
00726                 LocalData->Buffer + 0, 
00727                 fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP),
00728                 FALSE,
00729                 FALSE,
00730                 NULL);
00731             
00732             if (pMdl2 == NULL)
00733             {
00734                 IF_LOUD(DbgPrint("Error allocating Mdl2\n");)
00735                 IoFreeMdl(pMdl1);
00736                 LocalData->Dropped++;
00737                 LocalData->Processing = 0;
00738                 return NDIS_STATUS_NOT_ACCEPTED;
00739             }
00740 
00741             LocalData->NewP = fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP);
00742 
00743             MmBuildMdlForNonPagedPool(pMdl1);
00744             MmBuildMdlForNonPagedPool(pMdl2);
00745         }
00746 
00747 
00748         NdisAllocatePacket(&Status, &pPacket, Open->PacketPool);
00749 
00750         if (Status != NDIS_STATUS_SUCCESS)
00751         {
00752             IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
00753             IoFreeMdl(pMdl1);
00754             if (pMdl2 != NULL)
00755                 IoFreeMdl(pMdl2);
00756             LocalData->Dropped++;
00757             LocalData->Processing = 0;
00758             return NDIS_STATUS_NOT_ACCEPTED;
00759         }
00760 
00761         if (pMdl2 != NULL)
00762             NdisChainBufferAtFront(pPacket,pMdl2);
00763         
00764         NdisChainBufferAtFront(pPacket,pMdl1);
00765 
00766         RESERVED(pPacket)->Cpu = Cpu;
00767 
00768         LocalData->TransferMdl1 = pMdl1;    
00769         LocalData->TransferMdl2 = pMdl2;    
00770 
00771     
00772         Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
00773         Header->header.bh_caplen = fres;
00774         Header->header.bh_datalen = PacketSize + HeaderBufferSize;
00775         Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
00776 
00777         NdisTransferData(
00778                 &Status,
00779                 Open->AdapterHandle,
00780                 MacReceiveContext,
00781                 LookaheadBufferSize,
00782                 fres - HeaderBufferSize - LookaheadBufferSize,
00783                 pPacket,
00784                 &BytesTransfered);
00785 
00786         if (Status != NDIS_STATUS_PENDING)
00787         {
00788             IF_LOUD(DbgPrint("NdisTransferData, not pending!\n");)  
00789             LocalData->TransferMdl1 = NULL;
00790             LocalData->TransferMdl2 = NULL;
00791 
00792             IoFreeMdl(pMdl1);
00793             if ( pMdl2 != NULL )
00794                 IoFreeMdl(pMdl2);
00795 
00796             NdisReinitializePacket(pPacket);
00797             // Put the packet on the free queue
00798             NdisFreePacket(pPacket);
00799 
00800             LocalData->P = LocalData->NewP;
00801 
00802             LocalData->Accepted++;
00803             GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
00804             Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
00805 
00806             increment = fres + sizeof(struct PacketHeader);
00807             if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
00808             {
00809                 increment += Open->Size-LocalData->P;
00810                 LocalData->P = 0;
00811             }
00812 
00813             InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
00814 
00815             if(Open->Size - LocalData->Free >= Open->MinToCopy)
00816             {
00817                 if(Open->mode & MODE_DUMP)
00818                     NdisSetEvent(&Open->DumpEvent);
00819                 else
00820                     KeSetEvent(Open->ReadEvent,0,FALSE);    
00821             }
00822 
00823             LocalData->Processing = 0;
00824             return NDIS_STATUS_NOT_ACCEPTED;
00825         }
00826         else
00827         {
00828             DbgPrint("NdisTransferData, pending!\n");   
00829             return NDIS_STATUS_NOT_ACCEPTED;
00830         }
00831     }
00832 
00833     return NDIS_STATUS_SUCCESS;
00834     
00835 }
00836 
00837 //-------------------------------------------------------------------
00838 
00839 VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
00840                                  IN NDIS_STATUS Status,IN UINT BytesTransfered)
00841 {
00842     POPEN_INSTANCE      Open;
00843     ULONG               Cpu;
00844     CpuPrivateData      *LocalData;
00845     struct PacketHeader*    Header;
00846     ULONG               increment;
00847 
00848     IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
00849     
00850     Open = (POPEN_INSTANCE)ProtocolBindingContext;
00851 
00852     Cpu = RESERVED(pPacket)->Cpu;
00853 
00854     LocalData = &Open->CpuData[Cpu];
00855 
00856     IoFreeMdl(LocalData->TransferMdl1);
00857     if ( LocalData->TransferMdl2 != NULL )
00858         IoFreeMdl(LocalData->TransferMdl2);
00859 
00860     NdisReinitializePacket(pPacket);
00861     // Put the packet on the free queue
00862     NdisFreePacket(pPacket);
00863 
00864     //the packet has been successfully copied to the kernel buffer, we can prepend it with the PacketHeader,
00865     //and obtain the sequence number and the timestamp
00866 
00867     LocalData->Accepted++;
00868     Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
00869     GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
00870     Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
00871 
00872     LocalData->P = LocalData->NewP;
00873     
00874     increment = Header->header.bh_caplen + sizeof(struct PacketHeader);
00875     if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
00876     {
00877         increment += Open->Size-LocalData->P;
00878         LocalData->P = 0;
00879     }
00880 
00881     InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
00882 
00883     if(Open->Size - LocalData->Free >= Open->MinToCopy)
00884     {
00885         if(Open->mode & MODE_DUMP)
00886             NdisSetEvent(&Open->DumpEvent);
00887         else
00888             KeSetEvent(Open->ReadEvent,0,FALSE);    
00889     }
00890 
00891     LocalData->TransferMdl1 = NULL;
00892     LocalData->TransferMdl2 = NULL;
00893     LocalData->Processing = 0;
00894 
00895 // Unfreeze the consumer
00896     if(Open->Size - LocalData->Free > Open->MinToCopy)
00897     {
00898         if(Open->mode & MODE_DUMP)
00899             NdisSetEvent(&Open->DumpEvent);
00900         else
00901             KeSetEvent(Open->ReadEvent,0,FALSE);    
00902     }
00903     return;
00904 }
00905 
00906 //-------------------------------------------------------------------
00907 
00908 VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
00909 {
00910     IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
00911     return;
00912 }

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