2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: datalink/loopback.c
5 * PURPOSE: Loopback adapter
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
13 PIP_INTERFACE Loopback
= NULL
;
14 typedef struct _LAN_WQ_ITEM
{
18 UINT BytesTransferred
;
19 } LAN_WQ_ITEM
, *PLAN_WQ_ITEM
;
21 /* Work around being called back into afd at Dpc level */
22 KSPIN_LOCK LoopWorkLock
;
23 LIST_ENTRY LoopWorkList
;
24 WORK_QUEUE_ITEM LoopWorkItem
;
25 BOOLEAN LoopReceiveWorkerBusy
= FALSE
;
27 VOID STDCALL
LoopReceiveWorker( PVOID Context
) {
28 PLIST_ENTRY ListEntry
;
29 PLAN_WQ_ITEM WorkItem
;
32 UINT BytesTransferred
;
33 PNDIS_BUFFER NdisBuffer
;
36 TI_DbgPrint(DEBUG_DATALINK
, ("Called.\n"));
39 ExInterlockedRemoveHeadList( &LoopWorkList
, &LoopWorkLock
)) ) {
40 WorkItem
= CONTAINING_RECORD(ListEntry
, LAN_WQ_ITEM
, ListEntry
);
42 TI_DbgPrint(DEBUG_DATALINK
, ("WorkItem: %x\n", WorkItem
));
44 Packet
= WorkItem
->Packet
;
45 Adapter
= WorkItem
->Adapter
;
46 BytesTransferred
= WorkItem
->BytesTransferred
;
48 ExFreePool( WorkItem
);
50 IPPacket
.NdisPacket
= Packet
;
52 TI_DbgPrint(DEBUG_DATALINK
, ("Packet %x Adapter %x Trans %x\n",
53 Packet
, Adapter
, BytesTransferred
));
55 NdisGetFirstBufferFromPacket(Packet
,
61 IPPacket
.ContigSize
= IPPacket
.TotalSize
= BytesTransferred
;
62 /* Determine which upper layer protocol that should receive
63 this packet and pass it to the correct receive handler */
65 TI_DbgPrint(MID_TRACE
,
66 ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n",
67 IPPacket
.ContigSize
, IPPacket
.TotalSize
,
70 IPPacket
.Position
= 0;
72 IPReceive(Loopback
, &IPPacket
);
74 FreeNdisPacket( Packet
);
76 TI_DbgPrint(DEBUG_DATALINK
, ("Leaving\n"));
77 LoopReceiveWorkerBusy
= FALSE
;
80 VOID
LoopSubmitReceiveWork(
81 NDIS_HANDLE BindingContext
,
84 UINT BytesTransferred
) {
86 PLAN_ADAPTER Adapter
= (PLAN_ADAPTER
)BindingContext
;
89 TcpipAcquireSpinLock( &LoopWorkLock
, &OldIrql
);
91 WQItem
= ExAllocatePool( NonPagedPool
, sizeof(LAN_WQ_ITEM
) );
93 TcpipReleaseSpinLock( &LoopWorkLock
, OldIrql
);
97 WQItem
->Packet
= Packet
;
98 WQItem
->Adapter
= Adapter
;
99 WQItem
->BytesTransferred
= BytesTransferred
;
100 InsertTailList( &LoopWorkList
, &WQItem
->ListEntry
);
102 TI_DbgPrint(DEBUG_DATALINK
, ("Packet %x Adapter %x BytesTrans %x\n",
103 Packet
, Adapter
, BytesTransferred
));
105 if( !LoopReceiveWorkerBusy
) {
106 LoopReceiveWorkerBusy
= TRUE
;
107 ExQueueWorkItem( &LoopWorkItem
, CriticalWorkQueue
);
108 TI_DbgPrint(DEBUG_DATALINK
,
109 ("Work item inserted %x %x\n", &LoopWorkItem
, WQItem
));
111 TI_DbgPrint(DEBUG_DATALINK
,
112 ("LOOP WORKER BUSY %x %x\n", &LoopWorkItem
, WQItem
));
114 TcpipReleaseSpinLock( &LoopWorkLock
, OldIrql
);
119 PNDIS_PACKET NdisPacket
,
124 * FUNCTION: Transmits a packet
126 * Context = Pointer to context information (NULL)
127 * NdisPacket = Pointer to NDIS packet to send
128 * Offset = Offset in packet where packet data starts
129 * LinkAddress = Pointer to link address
130 * Type = LAN protocol type (unused)
135 PNDIS_PACKET XmitPacket
;
136 NDIS_STATUS NdisStatus
;
138 ASSERT_KM_POINTER(NdisPacket
);
139 ASSERT_KM_POINTER(PC(NdisPacket
));
140 ASSERT_KM_POINTER(PC(NdisPacket
)->DLComplete
);
142 TI_DbgPrint(MAX_TRACE
, ("Called (NdisPacket = %x)\n", NdisPacket
));
144 GetDataPtr( NdisPacket
, MaxLLHeaderSize
, &PacketBuffer
, &PacketLength
);
146 NdisStatus
= AllocatePacketWithBuffer
147 ( &XmitPacket
, PacketBuffer
, PacketLength
);
149 if( NT_SUCCESS(NdisStatus
) ) {
150 LoopSubmitReceiveWork
151 ( NULL
, XmitPacket
, STATUS_SUCCESS
, PacketLength
);
154 (PC(NdisPacket
)->DLComplete
)
155 ( PC(NdisPacket
)->Context
, NdisPacket
, STATUS_SUCCESS
);
157 TI_DbgPrint(MAX_TRACE
, ("Done\n"));
160 NDIS_STATUS
LoopRegisterAdapter(
161 PNDIS_STRING AdapterName
,
162 PLAN_ADAPTER
*Adapter
)
164 * FUNCTION: Registers loopback adapter with the network layer
166 * AdapterName = Unused
169 * Status of operation
173 LLIP_BIND_INFO BindInfo
;
175 Status
= NDIS_STATUS_SUCCESS
;
177 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
179 InitializeListHead( &LoopWorkList
);
180 ExInitializeWorkItem( &LoopWorkItem
, LoopReceiveWorker
, NULL
);
182 /* Bind the adapter to network (IP) layer */
183 BindInfo
.Context
= NULL
;
184 BindInfo
.HeaderSize
= 0;
185 BindInfo
.MinFrameSize
= 0;
186 BindInfo
.MTU
= 16384;
187 BindInfo
.Address
= NULL
;
188 BindInfo
.AddressLength
= 0;
189 BindInfo
.Transmit
= LoopTransmit
;
191 Loopback
= IPCreateInterface(&BindInfo
);
193 Loopback
->Name
.Buffer
= L
"Loopback";
194 Loopback
->Name
.MaximumLength
= Loopback
->Name
.Length
=
195 wcslen(Loopback
->Name
.Buffer
) * sizeof(WCHAR
);
197 AddrInitIPv4(&Loopback
->Unicast
, LOOPBACK_ADDRESS_IPv4
);
198 AddrInitIPv4(&Loopback
->Netmask
, LOOPBACK_ADDRMASK_IPv4
);
200 IPRegisterInterface(Loopback
);
202 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
208 NDIS_STATUS
LoopUnregisterAdapter(
209 PLAN_ADAPTER Adapter
)
211 * FUNCTION: Unregisters loopback adapter with the network layer
215 * Status of operation
217 * Does not care wether we have registered loopback adapter
220 TI_DbgPrint(MID_TRACE
, ("Called.\n"));
222 if (Loopback
!= NULL
)
224 IPUnregisterInterface(Loopback
);
225 IPDestroyInterface(Loopback
);
229 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
231 return NDIS_STATUS_SUCCESS
;