]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
MdeModulePkg: Remove trailing white space
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4If.c
CommitLineData
772db4bb 1/** @file\r
3e8c18da 2 Implement IP4 pesudo interface.\r
d1102dba
LG
3\r
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
772db4bb 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
772db4bb 13**/\r
14\r
15#include "Ip4Impl.h"\r
16\r
17//\r
18// Mac address with all zero, used to determine whethter the ARP\r
19// resolve succeeded. Failed ARP requests zero the MAC address buffer.\r
20//\r
fe1e36e5 21EFI_MAC_ADDRESS mZeroMacAddress;\r
772db4bb 22\r
2ff29212 23/**\r
24 Callback funtion when frame transmission is finished. It will\r
25 call the frame owner's callback function to tell it the result.\r
26\r
3e8c18da 27 @param[in] Context Context which is point to the token.\r
2ff29212 28\r
29**/\r
36ee91ca 30VOID\r
31EFIAPI\r
32Ip4OnFrameSentDpc (\r
2ff29212 33 IN VOID *Context\r
36ee91ca 34 );\r
35\r
2ff29212 36/**\r
37 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.\r
38\r
3e8c18da 39 @param[in] Event The transmit token's event.\r
40 @param[in] Context Context which is point to the token.\r
2ff29212 41\r
42**/\r
772db4bb 43VOID\r
44EFIAPI\r
45Ip4OnFrameSent (\r
2ff29212 46 IN EFI_EVENT Event,\r
47 IN VOID *Context\r
772db4bb 48 );\r
49\r
2ff29212 50/**\r
51 Callback function when ARP request are finished. It will cancelled\r
52 all the queued frame if the ARP requests failed. Or transmit them\r
53 if the request succeed.\r
54\r
3e8c18da 55 @param[in] Context The context of the callback, a point to the ARP\r
2ff29212 56 queue\r
57\r
2ff29212 58**/\r
36ee91ca 59VOID\r
60EFIAPI\r
61Ip4OnArpResolvedDpc (\r
62 IN VOID *Context\r
63 );\r
64\r
2ff29212 65/**\r
66 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.\r
67\r
3e8c18da 68 @param Event The Arp request event.\r
69 @param Context The context of the callback, a point to the ARP\r
70 queue.\r
d1102dba 71\r
2ff29212 72**/\r
772db4bb 73VOID\r
74EFIAPI\r
75Ip4OnArpResolved (\r
76 IN EFI_EVENT Event,\r
77 IN VOID *Context\r
78 );\r
79\r
2ff29212 80/**\r
81 Received a frame from MNP, wrap it in net buffer then deliver\r
82 it to IP's input function. The ownship of the packet also\r
83 transferred to IP. When Ip is finished with this packet, it\r
84 will call NetbufFree to release the packet, NetbufFree will\r
85 again call the Ip4RecycleFrame to signal MNP's event and free\r
86 the token used.\r
87\r
88 @param Context Context for the callback.\r
89\r
2ff29212 90**/\r
36ee91ca 91VOID\r
92EFIAPI\r
93Ip4OnFrameReceivedDpc (\r
2ff29212 94 IN VOID *Context\r
36ee91ca 95 );\r
96\r
2ff29212 97/**\r
2ff29212 98 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.\r
99\r
100 @param Event The receive event delivered to MNP for receive.\r
101 @param Context Context for the callback.\r
2ff29212 102\r
103**/\r
772db4bb 104VOID\r
105EFIAPI\r
106Ip4OnFrameReceived (\r
2ff29212 107 IN EFI_EVENT Event,\r
108 IN VOID *Context\r
772db4bb 109 );\r
110\r
2ff29212 111/**\r
112 Remove all the frames on the ARP queue that pass the FrameToCancel,\r
113 that is, either FrameToCancel is NULL or it returns true for the frame.\r
114\r
3e8c18da 115 @param[in] ArpQue ARP frame to remove the frames from.\r
116 @param[in] IoStatus The status returned to the cancelled frames'\r
2ff29212 117 callback function.\r
3e8c18da 118 @param[in] FrameToCancel Function to select which frame to cancel.\r
119 @param[in] Context Opaque parameter to the FrameToCancel.\r
2ff29212 120\r
121**/\r
772db4bb 122VOID\r
123Ip4CancelFrameArp (\r
124 IN IP4_ARP_QUE *ArpQue,\r
125 IN EFI_STATUS IoStatus,\r
24af132f 126 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 127 IN VOID *Context\r
128 );\r
129\r
130\r
131/**\r
132 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.\r
133\r
3e8c18da 134 @param[in] Interface The interface to send out to.\r
135 @param[in] IpInstance The IpInstance that transmit the packet. NULL if\r
772db4bb 136 the packet is sent by the IP4 driver itself.\r
3e8c18da 137 @param[in] Packet The packet to transmit\r
138 @param[in] CallBack Call back function to execute if transmission\r
772db4bb 139 finished.\r
3e8c18da 140 @param[in] Context Opaque parameter to the call back.\r
12ae56cf 141 @param[in] IpSb The pointer to the IP4 service binding instance.\r
772db4bb 142\r
d1102dba 143 @retval Token The wrapped token if succeed\r
3e8c18da 144 @retval NULL The wrapped token if NULL\r
772db4bb 145\r
146**/\r
772db4bb 147IP4_LINK_TX_TOKEN *\r
148Ip4WrapLinkTxToken (\r
149 IN IP4_INTERFACE *Interface,\r
24af132f 150 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 151 IN NET_BUF *Packet,\r
152 IN IP4_FRAME_CALLBACK CallBack,\r
12ae56cf
FS
153 IN VOID *Context,\r
154 IN IP4_SERVICE *IpSb\r
772db4bb 155 )\r
156{\r
157 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
158 EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;\r
159 IP4_LINK_TX_TOKEN *Token;\r
160 EFI_STATUS Status;\r
161 UINT32 Count;\r
162\r
e48e37fc 163 Token = AllocatePool (sizeof (IP4_LINK_TX_TOKEN) + \\r
772db4bb 164 (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));\r
165\r
166 if (Token == NULL) {\r
167 return NULL;\r
168 }\r
169\r
170 Token->Signature = IP4_FRAME_TX_SIGNATURE;\r
e48e37fc 171 InitializeListHead (&Token->Link);\r
772db4bb 172\r
173 Token->Interface = Interface;\r
174 Token->IpInstance = IpInstance;\r
12ae56cf 175 Token->IpSb = IpSb;\r
772db4bb 176 Token->CallBack = CallBack;\r
177 Token->Packet = Packet;\r
178 Token->Context = Context;\r
687a2e5f 179 CopyMem (&Token->DstMac, &mZeroMacAddress, sizeof (Token->DstMac));\r
180 CopyMem (&Token->SrcMac, &Interface->Mac, sizeof (Token->SrcMac));\r
772db4bb 181\r
182 MnpToken = &(Token->MnpToken);\r
183 MnpToken->Status = EFI_NOT_READY;\r
184\r
185 Status = gBS->CreateEvent (\r
186 EVT_NOTIFY_SIGNAL,\r
e48e37fc 187 TPL_NOTIFY,\r
772db4bb 188 Ip4OnFrameSent,\r
189 Token,\r
190 &MnpToken->Event\r
191 );\r
192\r
193 if (EFI_ERROR (Status)) {\r
766c7483 194 FreePool (Token);\r
772db4bb 195 return NULL;\r
196 }\r
197\r
198 MnpTxData = &Token->MnpTxData;\r
199 MnpToken->Packet.TxData = MnpTxData;\r
200\r
201 MnpTxData->DestinationAddress = &Token->DstMac;\r
202 MnpTxData->SourceAddress = &Token->SrcMac;\r
203 MnpTxData->ProtocolType = IP4_ETHER_PROTO;\r
204 MnpTxData->DataLength = Packet->TotalSize;\r
205 MnpTxData->HeaderLength = 0;\r
206\r
207 Count = Packet->BlockOpNum;\r
208\r
209 NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);\r
210 MnpTxData->FragmentCount = (UINT16)Count;\r
211\r
212 return Token;\r
213}\r
214\r
215\r
216/**\r
217 Free the link layer transmit token. It will close the event\r
218 then free the memory used.\r
219\r
3e8c18da 220 @param[in] Token Token to free\r
772db4bb 221\r
222**/\r
772db4bb 223VOID\r
224Ip4FreeLinkTxToken (\r
225 IN IP4_LINK_TX_TOKEN *Token\r
226 )\r
227{\r
228 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
229\r
230 gBS->CloseEvent (Token->MnpToken.Event);\r
766c7483 231 FreePool (Token);\r
772db4bb 232}\r
233\r
234\r
235/**\r
236 Create an IP_ARP_QUE structure to request ARP service.\r
237\r
3e8c18da 238 @param[in] Interface The interface to send ARP from.\r
239 @param[in] DestIp The destination IP (host byte order) to request MAC\r
772db4bb 240 for\r
241\r
242 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.\r
243\r
244**/\r
772db4bb 245IP4_ARP_QUE *\r
246Ip4CreateArpQue (\r
247 IN IP4_INTERFACE *Interface,\r
248 IN IP4_ADDR DestIp\r
249 )\r
250{\r
251 IP4_ARP_QUE *ArpQue;\r
252 EFI_STATUS Status;\r
253\r
e48e37fc 254 ArpQue = AllocatePool (sizeof (IP4_ARP_QUE));\r
772db4bb 255\r
256 if (ArpQue == NULL) {\r
257 return NULL;\r
258 }\r
259\r
260 ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;\r
e48e37fc 261 InitializeListHead (&ArpQue->Link);\r
772db4bb 262\r
e48e37fc 263 InitializeListHead (&ArpQue->Frames);\r
772db4bb 264 ArpQue->Interface = Interface;\r
265\r
266 Status = gBS->CreateEvent (\r
267 EVT_NOTIFY_SIGNAL,\r
e48e37fc 268 TPL_NOTIFY,\r
772db4bb 269 Ip4OnArpResolved,\r
270 ArpQue,\r
271 &ArpQue->OnResolved\r
272 );\r
273\r
274 if (EFI_ERROR (Status)) {\r
766c7483 275 FreePool (ArpQue);\r
772db4bb 276 return NULL;\r
277 }\r
278\r
279 ArpQue->Ip = DestIp;\r
687a2e5f 280 CopyMem (&ArpQue->Mac, &mZeroMacAddress, sizeof (ArpQue->Mac));\r
772db4bb 281\r
282 return ArpQue;\r
283}\r
284\r
285\r
286/**\r
287 Remove all the transmit requests queued on the ARP queue, then free it.\r
288\r
3e8c18da 289 @param[in] ArpQue Arp queue to free\r
290 @param[in] IoStatus The transmit status returned to transmit requests'\r
772db4bb 291 callback.\r
292\r
772db4bb 293**/\r
772db4bb 294VOID\r
295Ip4FreeArpQue (\r
296 IN IP4_ARP_QUE *ArpQue,\r
297 IN EFI_STATUS IoStatus\r
298 )\r
299{\r
300 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
301\r
302 //\r
303 // Remove all the frame waiting the ARP response\r
304 //\r
305 Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);\r
306\r
307 gBS->CloseEvent (ArpQue->OnResolved);\r
766c7483 308 FreePool (ArpQue);\r
772db4bb 309}\r
310\r
311\r
312/**\r
313 Create a link layer receive token to wrap the receive request\r
314\r
3e8c18da 315 @param[in] Interface The interface to receive from\r
316 @param[in] IpInstance The instance that request the receive (NULL for IP4\r
772db4bb 317 driver itself)\r
3e8c18da 318 @param[in] CallBack Call back function to execute when finished.\r
319 @param[in] Context Opaque parameters to the callback\r
772db4bb 320\r
321 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.\r
322\r
323**/\r
772db4bb 324IP4_LINK_RX_TOKEN *\r
325Ip4CreateLinkRxToken (\r
326 IN IP4_INTERFACE *Interface,\r
327 IN IP4_PROTOCOL *IpInstance,\r
328 IN IP4_FRAME_CALLBACK CallBack,\r
329 IN VOID *Context\r
330 )\r
331{\r
332 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
333 IP4_LINK_RX_TOKEN *Token;\r
334 EFI_STATUS Status;\r
335\r
e48e37fc 336 Token = AllocatePool (sizeof (IP4_LINK_RX_TOKEN));\r
772db4bb 337 if (Token == NULL) {\r
338 return NULL;\r
339 }\r
340\r
341 Token->Signature = IP4_FRAME_RX_SIGNATURE;\r
342 Token->Interface = Interface;\r
343 Token->IpInstance = IpInstance;\r
344 Token->CallBack = CallBack;\r
345 Token->Context = Context;\r
346\r
347 MnpToken = &Token->MnpToken;\r
348 MnpToken->Status = EFI_NOT_READY;\r
349\r
350 Status = gBS->CreateEvent (\r
351 EVT_NOTIFY_SIGNAL,\r
e48e37fc 352 TPL_NOTIFY,\r
772db4bb 353 Ip4OnFrameReceived,\r
354 Token,\r
355 &MnpToken->Event\r
356 );\r
357\r
358 if (EFI_ERROR (Status)) {\r
766c7483 359 FreePool (Token);\r
772db4bb 360 return NULL;\r
361 }\r
362\r
363 MnpToken->Packet.RxData = NULL;\r
364 return Token;\r
365}\r
366\r
367\r
368/**\r
369 Free the link layer request token. It will close the event\r
370 then free the memory used.\r
371\r
3e8c18da 372 @param[in] Token Request token to free.\r
772db4bb 373\r
374**/\r
772db4bb 375VOID\r
376Ip4FreeFrameRxToken (\r
377 IN IP4_LINK_RX_TOKEN *Token\r
378 )\r
379{\r
380\r
381 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
382\r
383 gBS->CloseEvent (Token->MnpToken.Event);\r
766c7483 384 FreePool (Token);\r
772db4bb 385}\r
386\r
387\r
388/**\r
389 Remove all the frames on the ARP queue that pass the FrameToCancel,\r
390 that is, either FrameToCancel is NULL or it returns true for the frame.\r
391\r
3e8c18da 392 @param[in] ArpQue ARP frame to remove the frames from.\r
393 @param[in] IoStatus The status returned to the cancelled frames'\r
772db4bb 394 callback function.\r
3e8c18da 395 @param[in] FrameToCancel Function to select which frame to cancel.\r
396 @param[in] Context Opaque parameter to the FrameToCancel.\r
772db4bb 397\r
398**/\r
772db4bb 399VOID\r
400Ip4CancelFrameArp (\r
401 IN IP4_ARP_QUE *ArpQue,\r
402 IN EFI_STATUS IoStatus,\r
24af132f 403 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 404 IN VOID *Context\r
405 )\r
406{\r
e48e37fc 407 LIST_ENTRY *Entry;\r
408 LIST_ENTRY *Next;\r
772db4bb 409 IP4_LINK_TX_TOKEN *Token;\r
410\r
411 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
412 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
413\r
414 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {\r
e48e37fc 415 RemoveEntryList (Entry);\r
772db4bb 416\r
417 Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);\r
418 Ip4FreeLinkTxToken (Token);\r
419 }\r
420 }\r
421}\r
422\r
423\r
424/**\r
425 Remove all the frames on the interface that pass the FrameToCancel,\r
426 either queued on ARP queues or that have already been delivered to\r
427 MNP and not yet recycled.\r
428\r
1f6729ff 429 @param[in] Interface Interface to remove the frames from.\r
3e8c18da 430 @param[in] IoStatus The transmit status returned to the frames'\r
1f6729ff 431 callback.\r
3e8c18da 432 @param[in] FrameToCancel Function to select the frame to cancel, NULL to\r
1f6729ff 433 select all.\r
434 @param[in] Context Opaque parameters passed to FrameToCancel.\r
772db4bb 435\r
436**/\r
437VOID\r
438Ip4CancelFrames (\r
439 IN IP4_INTERFACE *Interface,\r
440 IN EFI_STATUS IoStatus,\r
24af132f 441 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 442 IN VOID *Context\r
443 )\r
444{\r
e48e37fc 445 LIST_ENTRY *Entry;\r
446 LIST_ENTRY *Next;\r
772db4bb 447 IP4_ARP_QUE *ArpQue;\r
448 IP4_LINK_TX_TOKEN *Token;\r
449\r
450 //\r
451 // Cancel all the pending frames on ARP requests\r
452 //\r
453 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {\r
454 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);\r
455\r
456 Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);\r
457\r
e48e37fc 458 if (IsListEmpty (&ArpQue->Frames)) {\r
772db4bb 459 Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);\r
772db4bb 460 }\r
461 }\r
462\r
463 //\r
464 // Cancel all the frames that have been delivered to MNP\r
465 // but not yet recycled.\r
466 //\r
467 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {\r
468 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
469\r
470 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {\r
772db4bb 471 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);\r
772db4bb 472 }\r
473 }\r
474}\r
475\r
476\r
477/**\r
478 Create an IP4_INTERFACE. Delay the creation of ARP instance until\r
479 the interface is configured.\r
480\r
3e8c18da 481 @param[in] Mnp The shared MNP child of this IP4 service binding\r
1f6729ff 482 instance.\r
3e8c18da 483 @param[in] Controller The controller this IP4 service binding instance\r
772db4bb 484 is installed. Most like the UNDI handle.\r
1f6729ff 485 @param[in] ImageHandle This driver's image handle.\r
772db4bb 486\r
487 @return Point to the created IP4_INTERFACE, otherwise NULL.\r
488\r
489**/\r
490IP4_INTERFACE *\r
491Ip4CreateInterface (\r
492 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,\r
493 IN EFI_HANDLE Controller,\r
494 IN EFI_HANDLE ImageHandle\r
495 )\r
496{\r
497 IP4_INTERFACE *Interface;\r
498 EFI_SIMPLE_NETWORK_MODE SnpMode;\r
499\r
e48e37fc 500 Interface = AllocatePool (sizeof (IP4_INTERFACE));\r
772db4bb 501\r
502 if ((Interface == NULL) || (Mnp == NULL)) {\r
503 return NULL;\r
504 }\r
505\r
506 Interface->Signature = IP4_INTERFACE_SIGNATURE;\r
e48e37fc 507 InitializeListHead (&Interface->Link);\r
772db4bb 508 Interface->RefCnt = 1;\r
509\r
510 Interface->Ip = IP4_ALLZERO_ADDRESS;\r
511 Interface->SubnetMask = IP4_ALLZERO_ADDRESS;\r
512 Interface->Configured = FALSE;\r
513\r
514 Interface->Controller = Controller;\r
515 Interface->Image = ImageHandle;\r
516 Interface->Mnp = Mnp;\r
517 Interface->Arp = NULL;\r
518 Interface->ArpHandle = NULL;\r
519\r
e48e37fc 520 InitializeListHead (&Interface->ArpQues);\r
521 InitializeListHead (&Interface->SentFrames);\r
772db4bb 522\r
523 Interface->RecvRequest = NULL;\r
524\r
525 //\r
526 // Get the interface's Mac address and broadcast mac address from SNP\r
527 //\r
528 if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {\r
766c7483 529 FreePool (Interface);\r
772db4bb 530 return NULL;\r
531 }\r
532\r
687a2e5f 533 CopyMem (&Interface->Mac, &SnpMode.CurrentAddress, sizeof (Interface->Mac));\r
534 CopyMem (&Interface->BroadcastMac, &SnpMode.BroadcastAddress, sizeof (Interface->BroadcastMac));\r
772db4bb 535 Interface->HwaddrLen = SnpMode.HwAddressSize;\r
536\r
e48e37fc 537 InitializeListHead (&Interface->IpInstances);\r
772db4bb 538 Interface->PromiscRecv = FALSE;\r
539\r
540 return Interface;\r
541}\r
542\r
543\r
544/**\r
545 Set the interface's address, create and configure\r
546 the ARP child if necessary.\r
547\r
1f6729ff 548 @param Interface The interface to set the address.\r
549 @param IpAddr The interface's IP address.\r
550 @param SubnetMask The interface's netmask.\r
772db4bb 551\r
552 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,\r
553 and a ARP is created for it.\r
554 @retval Others Failed to set the interface's address.\r
555\r
556**/\r
557EFI_STATUS\r
558Ip4SetAddress (\r
5405e9a6 559 IN OUT IP4_INTERFACE *Interface,\r
560 IN IP4_ADDR IpAddr,\r
561 IN IP4_ADDR SubnetMask\r
772db4bb 562 )\r
563{\r
564 EFI_ARP_CONFIG_DATA ArpConfig;\r
565 EFI_STATUS Status;\r
772db4bb 566\r
567 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
568\r
772db4bb 569 //\r
570 // Set the ip/netmask, then compute the subnet broadcast\r
571 // and network broadcast for easy access. When computing\r
572 // nework broadcast, the subnet mask is most like longer\r
573 // than the default netmask (not subneted) as defined in\r
574 // RFC793. If that isn't the case, we are aggregating the\r
575 // networks, use the subnet's mask instead.\r
576 //\r
577 Interface->Ip = IpAddr;\r
578 Interface->SubnetMask = SubnetMask;\r
579 Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);\r
01b5ac88 580 Interface->NetBrdcast = (IpAddr | ~SubnetMask);\r
772db4bb 581\r
1f6729ff 582 //\r
583 // Do clean up for Arp child\r
584 //\r
585 if (Interface->ArpHandle != NULL) {\r
586 if (Interface->Arp != NULL) {\r
587 gBS->CloseProtocol (\r
588 Interface->ArpHandle,\r
589 &gEfiArpProtocolGuid,\r
590 Interface->Image,\r
591 Interface->Controller\r
592 );\r
d1102dba 593\r
1f6729ff 594 Interface->Arp = NULL;\r
595 }\r
d1102dba 596\r
1f6729ff 597 NetLibDestroyServiceChild (\r
598 Interface->Controller,\r
599 Interface->Image,\r
600 &gEfiArpServiceBindingProtocolGuid,\r
601 &Interface->ArpHandle\r
602 );\r
603\r
604 Interface->ArpHandle = NULL;\r
605 }\r
606\r
772db4bb 607 //\r
608 // If the address is NOT all zero, create then configure an ARP child.\r
609 // Pay attention: DHCP configures its station address as 0.0.0.0/0\r
610 //\r
772db4bb 611 if (IpAddr != IP4_ALLZERO_ADDRESS) {\r
612 Status = NetLibCreateServiceChild (\r
613 Interface->Controller,\r
614 Interface->Image,\r
615 &gEfiArpServiceBindingProtocolGuid,\r
616 &Interface->ArpHandle\r
617 );\r
618\r
619 if (EFI_ERROR (Status)) {\r
1f6729ff 620 return Status;\r
772db4bb 621 }\r
622\r
623 Status = gBS->OpenProtocol (\r
624 Interface->ArpHandle,\r
625 &gEfiArpProtocolGuid,\r
626 (VOID **) &Interface->Arp,\r
627 Interface->Image,\r
628 Interface->Controller,\r
629 EFI_OPEN_PROTOCOL_BY_DRIVER\r
630 );\r
631\r
632 if (EFI_ERROR (Status)) {\r
633 goto ON_ERROR;\r
634 }\r
635\r
636 IpAddr = HTONL (IpAddr);\r
637 ArpConfig.SwAddressType = IP4_ETHER_PROTO;\r
638 ArpConfig.SwAddressLength = 4;\r
639 ArpConfig.StationAddress = &IpAddr;\r
640 ArpConfig.EntryTimeOut = 0;\r
641 ArpConfig.RetryCount = 0;\r
642 ArpConfig.RetryTimeOut = 0;\r
643\r
644 Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);\r
645\r
646 if (EFI_ERROR (Status)) {\r
647 gBS->CloseProtocol (\r
1f6729ff 648 Interface->ArpHandle,\r
649 &gEfiArpProtocolGuid,\r
650 Interface->Image,\r
651 Interface->Controller\r
652 );\r
772db4bb 653\r
654 goto ON_ERROR;\r
655 }\r
656 }\r
657\r
658 Interface->Configured = TRUE;\r
659 return EFI_SUCCESS;\r
660\r
661ON_ERROR:\r
662 NetLibDestroyServiceChild (\r
663 Interface->Controller,\r
664 Interface->Image,\r
665 &gEfiArpServiceBindingProtocolGuid,\r
666 &Interface->ArpHandle\r
667 );\r
668\r
669 return Status;\r
670}\r
671\r
672\r
673/**\r
5405e9a6 674 Filter function to cancel all the frame related to an IP instance.\r
772db4bb 675\r
3e8c18da 676 @param[in] Frame The transmit request to test whether to cancel\r
677 @param[in] Context The context which is the Ip instance that issued\r
772db4bb 678 the transmit.\r
679\r
680 @retval TRUE The frame belongs to this instance and is to be\r
681 removed\r
682 @retval FALSE The frame doesn't belong to this instance.\r
683\r
684**/\r
772db4bb 685BOOLEAN\r
686Ip4CancelInstanceFrame (\r
687 IN IP4_LINK_TX_TOKEN *Frame,\r
688 IN VOID *Context\r
689 )\r
690{\r
691 if (Frame->IpInstance == (IP4_PROTOCOL *) Context) {\r
692 return TRUE;\r
693 }\r
694\r
695 return FALSE;\r
696}\r
697\r
698\r
699\r
700/**\r
701 If there is a pending receive request, cancel it. Don't call\r
702 the receive request's callback because this function can be only\r
703 called if the instance or driver is tearing itself down. It\r
704 doesn't make sense to call it back. But it is necessary to call\r
705 the transmit token's callback to give it a chance to free the\r
706 packet and update the upper layer's transmit request status, say\r
707 that from the UDP.\r
708\r
3e8c18da 709 @param[in] Interface The interface used by the IpInstance\r
772db4bb 710\r
711**/\r
712VOID\r
713Ip4CancelReceive (\r
714 IN IP4_INTERFACE *Interface\r
715 )\r
716{\r
717 EFI_TPL OldTpl;\r
718 IP4_LINK_RX_TOKEN *Token;\r
719\r
720 if ((Token = Interface->RecvRequest) != NULL) {\r
e48e37fc 721 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 722\r
723 Interface->RecvRequest = NULL;\r
724 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);\r
772db4bb 725\r
e48e37fc 726 gBS->RestoreTPL (OldTpl);\r
772db4bb 727 }\r
728}\r
729\r
730\r
731/**\r
732 Free the interface used by IpInstance. All the IP instance with\r
733 the same Ip/Netmask pair share the same interface. It is reference\r
734 counted. All the frames haven't been sent will be cancelled.\r
735 Because the IpInstance is optional, the caller must remove\r
736 IpInstance from the interface's instance list itself.\r
737\r
1f6729ff 738 @param[in] Interface The interface used by the IpInstance.\r
3e8c18da 739 @param[in] IpInstance The Ip instance that free the interface. NULL if\r
5405e9a6 740 the Ip driver is releasing the default interface.\r
772db4bb 741\r
742 @retval EFI_SUCCESS The interface use IpInstance is freed.\r
743\r
744**/\r
745EFI_STATUS\r
746Ip4FreeInterface (\r
747 IN IP4_INTERFACE *Interface,\r
748 IN IP4_PROTOCOL *IpInstance OPTIONAL\r
749 )\r
750{\r
751 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
752 ASSERT (Interface->RefCnt > 0);\r
753\r
754 //\r
755 // Remove all the pending transmit token related to this IP instance.\r
756 //\r
757 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);\r
758\r
d0ccf55e 759 if (--Interface->RefCnt > 0) {\r
760 return EFI_SUCCESS;\r
761 }\r
762\r
772db4bb 763 //\r
d0ccf55e 764 // Destroy the interface if this is the last IP instance that\r
765 // has the address. Remove all the system transmitted packets\r
766 // from this interface, cancel the receive request if there is\r
767 // one, and destroy the ARP requests.\r
772db4bb 768 //\r
d0ccf55e 769 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);\r
770 Ip4CancelReceive (Interface);\r
771\r
772 ASSERT (IsListEmpty (&Interface->IpInstances));\r
773 ASSERT (IsListEmpty (&Interface->ArpQues));\r
774 ASSERT (IsListEmpty (&Interface->SentFrames));\r
775\r
776 if (Interface->Arp != NULL) {\r
772db4bb 777 gBS->CloseProtocol (\r
778 Interface->ArpHandle,\r
779 &gEfiArpProtocolGuid,\r
780 Interface->Image,\r
781 Interface->Controller\r
782 );\r
783\r
784 NetLibDestroyServiceChild (\r
785 Interface->Controller,\r
786 Interface->Image,\r
787 &gEfiArpServiceBindingProtocolGuid,\r
788 Interface->ArpHandle\r
789 );\r
790 }\r
791\r
e48e37fc 792 RemoveEntryList (&Interface->Link);\r
766c7483 793 FreePool (Interface);\r
772db4bb 794\r
795 return EFI_SUCCESS;\r
796}\r
797\r
12ae56cf 798/**\r
4a76d9b9 799 This function tries to send all the queued frames in ArpQue to the default gateway if\r
12ae56cf
FS
800 the ARP resolve for direct destination address is failed when using /32 subnet mask.\r
801\r
802 @param[in] ArpQue The ARP queue of a failed request.\r
4a76d9b9 803\r
12ae56cf
FS
804 @retval EFI_SUCCESS All the queued frames have been send to the default route.\r
805 @retval Others Failed to send the queued frames.\r
4a76d9b9 806\r
12ae56cf
FS
807**/\r
808EFI_STATUS\r
809Ip4SendFrameToDefaultRoute (\r
810 IN IP4_ARP_QUE *ArpQue\r
811 )\r
812{\r
813 LIST_ENTRY *Entry;\r
814 LIST_ENTRY *Next;\r
815 IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;\r
816 IP4_LINK_TX_TOKEN *Token;\r
817 IP4_ADDR Gateway;\r
818 EFI_STATUS Status;\r
819 IP4_ROUTE_ENTRY *DefaultRoute;\r
4a76d9b9 820\r
12ae56cf
FS
821 //\r
822 // ARP resolve failed when using /32 subnet mask.\r
823 //\r
824 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
825 RemoveEntryList (Entry);\r
826 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
827 ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);\r
828 //\r
829 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().\r
830 //\r
831 RtCacheEntry = NULL;\r
832 if (Token->IpInstance != NULL) {\r
833 RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
834 }\r
835 if (RtCacheEntry == NULL) {\r
836 RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
837 }\r
838 if (RtCacheEntry == NULL) {\r
839 Status= EFI_NO_MAPPING;\r
840 goto ON_ERROR;\r
841 }\r
842 DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;\r
843 if (DefaultRoute == NULL) {\r
844 Status= EFI_NO_MAPPING;\r
845 goto ON_ERROR;\r
846 }\r
847 //\r
848 // Try to send the frame to the default route.\r
849 //\r
850 Gateway = DefaultRoute->NextHop;\r
851 if (ArpQue->Ip == Gateway) {\r
852 //\r
4a76d9b9 853 // ARP resolve for the default route is failed, return error to caller.\r
12ae56cf
FS
854 //\r
855 Status= EFI_NO_MAPPING;\r
856 goto ON_ERROR;\r
857 }\r
858 RtCacheEntry->NextHop = Gateway;\r
859 Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);\r
860 if (EFI_ERROR (Status)) {\r
861 Status= EFI_NO_MAPPING;\r
862 goto ON_ERROR;\r
863 }\r
864 Ip4FreeRouteCacheEntry (RtCacheEntry);\r
865 }\r
866\r
867 return EFI_SUCCESS;\r
4a76d9b9 868\r
12ae56cf
FS
869ON_ERROR:\r
870 if (RtCacheEntry != NULL) {\r
871 Ip4FreeRouteCacheEntry (RtCacheEntry);\r
872 }\r
873 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
874 Ip4FreeLinkTxToken (Token);\r
875 return Status;\r
876}\r
877\r
772db4bb 878\r
879/**\r
12ae56cf 880 Callback function when ARP request are finished. It will cancel\r
772db4bb 881 all the queued frame if the ARP requests failed. Or transmit them\r
882 if the request succeed.\r
883\r
3e8c18da 884 @param[in] Context The context of the callback, a point to the ARP\r
772db4bb 885 queue\r
886\r
772db4bb 887**/\r
772db4bb 888VOID\r
889EFIAPI\r
36ee91ca 890Ip4OnArpResolvedDpc (\r
772db4bb 891 IN VOID *Context\r
892 )\r
893{\r
e48e37fc 894 LIST_ENTRY *Entry;\r
895 LIST_ENTRY *Next;\r
772db4bb 896 IP4_ARP_QUE *ArpQue;\r
897 IP4_INTERFACE *Interface;\r
898 IP4_LINK_TX_TOKEN *Token;\r
899 EFI_STATUS Status;\r
12ae56cf 900 EFI_STATUS IoStatus;\r
772db4bb 901\r
902 ArpQue = (IP4_ARP_QUE *) Context;\r
903 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
904\r
e48e37fc 905 RemoveEntryList (&ArpQue->Link);\r
772db4bb 906\r
907 //\r
4a76d9b9 908 // ARP resolve failed for some reason.\r
772db4bb 909 //\r
910 if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {\r
12ae56cf
FS
911 if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {\r
912 //\r
913 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's\r
914 // owner back.\r
915 //\r
916 IoStatus = EFI_NO_MAPPING;\r
917 } else {\r
918 //\r
919 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the\r
920 // default route.\r
921 //\r
922 IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);\r
923 }\r
924 goto ON_EXIT;\r
772db4bb 925 }\r
926\r
927 //\r
928 // ARP resolve succeeded, Transmit all the frame. Release the ARP\r
929 // queue. It isn't necessary for us to cache the ARP binding because\r
930 // we always check the ARP cache first before transmit.\r
931 //\r
12ae56cf 932 IoStatus = EFI_SUCCESS;\r
772db4bb 933 Interface = ArpQue->Interface;\r
934\r
935 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
e48e37fc 936 RemoveEntryList (Entry);\r
772db4bb 937\r
938 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
687a2e5f 939 CopyMem (&Token->DstMac, &ArpQue->Mac, sizeof (Token->DstMac));\r
772db4bb 940\r
36ee91ca 941 //\r
942 // Insert the tx token before transmitting it via MNP as the FrameSentDpc\r
943 // may be called before Mnp->Transmit returns which will remove this tx\r
944 // token from the SentFrames list. Remove it from the list if the returned\r
945 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the\r
946 // FrameSentDpc won't be queued.\r
947 //\r
e48e37fc 948 InsertTailList (&Interface->SentFrames, &Token->Link);\r
772db4bb 949\r
36ee91ca 950 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
772db4bb 951 if (EFI_ERROR (Status)) {\r
ad18ec95 952 RemoveEntryList (&Token->Link);\r
772db4bb 953 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
954\r
955 Ip4FreeLinkTxToken (Token);\r
956 continue;\r
957 }\r
772db4bb 958 }\r
959\r
12ae56cf
FS
960ON_EXIT:\r
961 Ip4FreeArpQue (ArpQue, IoStatus);\r
772db4bb 962}\r
963\r
5405e9a6 964/**\r
965 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.\r
966\r
3e8c18da 967 @param Event The Arp request event.\r
968 @param Context The context of the callback, a point to the ARP\r
969 queue.\r
d1102dba 970\r
5405e9a6 971**/\r
36ee91ca 972VOID\r
973EFIAPI\r
974Ip4OnArpResolved (\r
975 IN EFI_EVENT Event,\r
976 IN VOID *Context\r
977 )\r
36ee91ca 978{\r
979 //\r
980 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK\r
981 //\r
d8d26fb2 982 QueueDpc (TPL_CALLBACK, Ip4OnArpResolvedDpc, Context);\r
36ee91ca 983}\r
984\r
985\r
772db4bb 986\r
987/**\r
988 Callback funtion when frame transmission is finished. It will\r
989 call the frame owner's callback function to tell it the result.\r
990\r
3e8c18da 991 @param[in] Context Context which is point to the token.\r
772db4bb 992\r
993**/\r
772db4bb 994VOID\r
995EFIAPI\r
36ee91ca 996Ip4OnFrameSentDpc (\r
772db4bb 997 IN VOID *Context\r
998 )\r
999{\r
1000 IP4_LINK_TX_TOKEN *Token;\r
1001\r
1002 Token = (IP4_LINK_TX_TOKEN *) Context;\r
1003 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
1004\r
e48e37fc 1005 RemoveEntryList (&Token->Link);\r
772db4bb 1006\r
1007 Token->CallBack (\r
1008 Token->IpInstance,\r
1009 Token->Packet,\r
1010 Token->MnpToken.Status,\r
1011 0,\r
1012 Token->Context\r
1013 );\r
1014\r
1015 Ip4FreeLinkTxToken (Token);\r
1016}\r
1017\r
5405e9a6 1018/**\r
1019 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.\r
1020\r
3e8c18da 1021 @param[in] Event The transmit token's event.\r
1022 @param[in] Context Context which is point to the token.\r
5405e9a6 1023\r
1024**/\r
36ee91ca 1025VOID\r
1026EFIAPI\r
1027Ip4OnFrameSent (\r
1028 IN EFI_EVENT Event,\r
1029 IN VOID *Context\r
1030 )\r
36ee91ca 1031{\r
1032 //\r
1033 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK\r
1034 //\r
d8d26fb2 1035 QueueDpc (TPL_CALLBACK, Ip4OnFrameSentDpc, Context);\r
36ee91ca 1036}\r
1037\r
772db4bb 1038\r
1039\r
1040/**\r
1041 Send a frame from the interface. If the next hop is broadcast or\r
1042 multicast address, it is transmitted immediately. If the next hop\r
1043 is a unicast, it will consult ARP to resolve the NextHop's MAC.\r
1044 If some error happened, the CallBack won't be called. So, the caller\r
1045 must test the return value, and take action when there is an error.\r
1046\r
3e8c18da 1047 @param[in] Interface The interface to send the frame from\r
1048 @param[in] IpInstance The IP child that request the transmission. NULL\r
772db4bb 1049 if it is the IP4 driver itself.\r
3e8c18da 1050 @param[in] Packet The packet to transmit.\r
1051 @param[in] NextHop The immediate destination to transmit the packet\r
772db4bb 1052 to.\r
3e8c18da 1053 @param[in] CallBack Function to call back when transmit finished.\r
1054 @param[in] Context Opaque parameter to the call back.\r
12ae56cf 1055 @param[in] IpSb The pointer to the IP4 service binding instance.\r
772db4bb 1056\r
1057 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame\r
1058 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop\r
1059 @retval EFI_SUCCESS The packet is successfully transmitted.\r
5405e9a6 1060 @retval other Other error occurs.\r
772db4bb 1061\r
1062**/\r
1063EFI_STATUS\r
1064Ip4SendFrame (\r
1065 IN IP4_INTERFACE *Interface,\r
24af132f 1066 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 1067 IN NET_BUF *Packet,\r
1068 IN IP4_ADDR NextHop,\r
1069 IN IP4_FRAME_CALLBACK CallBack,\r
12ae56cf
FS
1070 IN VOID *Context,\r
1071 IN IP4_SERVICE *IpSb\r
772db4bb 1072 )\r
1073{\r
1074 IP4_LINK_TX_TOKEN *Token;\r
e48e37fc 1075 LIST_ENTRY *Entry;\r
772db4bb 1076 IP4_ARP_QUE *ArpQue;\r
1077 EFI_ARP_PROTOCOL *Arp;\r
1078 EFI_STATUS Status;\r
1079\r
1080 ASSERT (Interface->Configured);\r
1081\r
12ae56cf 1082 Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);\r
772db4bb 1083\r
1084 if (Token == NULL) {\r
1085 return EFI_OUT_OF_RESOURCES;\r
1086 }\r
1087\r
1088 //\r
1089 // Get the destination MAC address for multicast and broadcasts.\r
1090 // Don't depend on ARP to solve the address since there maybe no\r
1091 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for\r
1092 // all the broadcasts.\r
1093 //\r
1094 if (NextHop == IP4_ALLONE_ADDRESS) {\r
687a2e5f 1095 CopyMem (&Token->DstMac, &Interface->BroadcastMac, sizeof (Token->DstMac));\r
772db4bb 1096 goto SEND_NOW;\r
1097\r
1098 } else if (IP4_IS_MULTICAST (NextHop)) {\r
1099\r
1100 Status = Ip4GetMulticastMac (Interface->Mnp, NextHop, &Token->DstMac);\r
1101\r
1102 if (EFI_ERROR (Status)) {\r
1103 goto ON_ERROR;\r
1104 }\r
1105\r
1106 goto SEND_NOW;\r
1107 }\r
1108\r
1109 //\r
1110 // Can only send out multicast/broadcast if the IP address is zero\r
1111 //\r
1112 if ((Arp = Interface->Arp) == NULL) {\r
1113 Status = EFI_NO_MAPPING;\r
1114 goto ON_ERROR;\r
1115 }\r
1116\r
1117 //\r
1118 // First check whether this binding is in the ARP cache.\r
1119 //\r
1120 NextHop = HTONL (NextHop);\r
1121 Status = Arp->Request (Arp, &NextHop, NULL, &Token->DstMac);\r
1122\r
1123 if (Status == EFI_SUCCESS) {\r
1124 goto SEND_NOW;\r
1125\r
1126 } else if (Status != EFI_NOT_READY) {\r
1127 goto ON_ERROR;\r
1128 }\r
1129\r
1130 //\r
1131 // Have to do asynchronous ARP resolution. First check\r
1132 // whether there is already a pending request.\r
1133 //\r
1134 ArpQue = NULL;\r
1135\r
1136 NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {\r
1137 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);\r
1138\r
1139 if (ArpQue->Ip == NextHop) {\r
1140 break;\r
1141 }\r
1142 }\r
1143\r
1144 //\r
1145 // Found a pending ARP request, enqueue the frame then return\r
1146 //\r
1147 if (Entry != &Interface->ArpQues) {\r
e48e37fc 1148 InsertTailList (&ArpQue->Frames, &Token->Link);\r
772db4bb 1149 return EFI_SUCCESS;\r
1150 }\r
1151\r
1152 //\r
1153 // First frame to NextHop, issue an asynchronous ARP requests\r
1154 //\r
1155 ArpQue = Ip4CreateArpQue (Interface, NextHop);\r
1156\r
1157 if (ArpQue == NULL) {\r
1158 Status = EFI_OUT_OF_RESOURCES;\r
1159 goto ON_ERROR;\r
1160 }\r
1161\r
1162 Status = Arp->Request (Arp, &ArpQue->Ip, ArpQue->OnResolved, ArpQue->Mac.Addr);\r
1163\r
1164 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
1165 Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);\r
1166 goto ON_ERROR;\r
1167 }\r
1168\r
e48e37fc 1169 InsertHeadList (&ArpQue->Frames, &Token->Link);\r
1170 InsertHeadList (&Interface->ArpQues, &ArpQue->Link);\r
772db4bb 1171 return EFI_SUCCESS;\r
1172\r
1173SEND_NOW:\r
36ee91ca 1174 //\r
1175 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.\r
1176 // Remove it if the returned status is not EFI_SUCCESS.\r
1177 //\r
e48e37fc 1178 InsertTailList (&Interface->SentFrames, &Token->Link);\r
772db4bb 1179 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
772db4bb 1180 if (EFI_ERROR (Status)) {\r
ad18ec95 1181 RemoveEntryList (&Token->Link);\r
772db4bb 1182 goto ON_ERROR;\r
1183 }\r
1184\r
772db4bb 1185 return EFI_SUCCESS;\r
1186\r
1187ON_ERROR:\r
1188 Ip4FreeLinkTxToken (Token);\r
1189 return Status;\r
1190}\r
1191\r
1192\r
1193/**\r
1194 Call back function when the received packet is freed.\r
1195 Check Ip4OnFrameReceived for information.\r
1196\r
3e8c18da 1197 @param Context Context, which is the IP4_LINK_RX_TOKEN.\r
772db4bb 1198\r
1199**/\r
772db4bb 1200VOID\r
e798cd87 1201EFIAPI\r
772db4bb 1202Ip4RecycleFrame (\r
1203 IN VOID *Context\r
1204 )\r
1205{\r
1206 IP4_LINK_RX_TOKEN *Frame;\r
1207\r
1208 Frame = (IP4_LINK_RX_TOKEN *) Context;\r
1209 NET_CHECK_SIGNATURE (Frame, IP4_FRAME_RX_SIGNATURE);\r
1210\r
1211 gBS->SignalEvent (Frame->MnpToken.Packet.RxData->RecycleEvent);\r
1212 Ip4FreeFrameRxToken (Frame);\r
1213}\r
1214\r
1215\r
1216/**\r
1217 Received a frame from MNP, wrap it in net buffer then deliver\r
1218 it to IP's input function. The ownship of the packet also\r
1219 transferred to IP. When Ip is finished with this packet, it\r
1220 will call NetbufFree to release the packet, NetbufFree will\r
1221 again call the Ip4RecycleFrame to signal MNP's event and free\r
1222 the token used.\r
1223\r
772db4bb 1224 @param Context Context for the callback.\r
1225\r
772db4bb 1226**/\r
772db4bb 1227VOID\r
1228EFIAPI\r
36ee91ca 1229Ip4OnFrameReceivedDpc (\r
772db4bb 1230 IN VOID *Context\r
1231 )\r
1232{\r
1233 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
1234 EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;\r
1235 IP4_LINK_RX_TOKEN *Token;\r
1236 NET_FRAGMENT Netfrag;\r
1237 NET_BUF *Packet;\r
1238 UINT32 Flag;\r
1239\r
1240 Token = (IP4_LINK_RX_TOKEN *) Context;\r
1241 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
1242\r
1243 //\r
1244 // First clear the interface's receive request in case the\r
1245 // caller wants to call Ip4ReceiveFrame in the callback.\r
1246 //\r
1247 Token->Interface->RecvRequest = NULL;\r
1248\r
1249 MnpToken = &Token->MnpToken;\r
1250 MnpRxData = MnpToken->Packet.RxData;\r
1251\r
1252 if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {\r
1253 Token->CallBack (Token->IpInstance, NULL, MnpToken->Status, 0, Token->Context);\r
1254 Ip4FreeFrameRxToken (Token);\r
1255\r
1256 return ;\r
1257 }\r
1258\r
1259 //\r
1260 // Wrap the frame in a net buffer then deliever it to IP input.\r
1261 // IP will reassemble the packet, and deliver it to upper layer\r
1262 //\r
1263 Netfrag.Len = MnpRxData->DataLength;\r
1264 Netfrag.Bulk = MnpRxData->PacketData;\r
1265\r
1266 Packet = NetbufFromExt (&Netfrag, 1, 0, IP4_MAX_HEADLEN, Ip4RecycleFrame, Token);\r
1267\r
1268 if (Packet == NULL) {\r
1269 gBS->SignalEvent (MnpRxData->RecycleEvent);\r
1270\r
1271 Token->CallBack (Token->IpInstance, NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);\r
1272 Ip4FreeFrameRxToken (Token);\r
1273\r
1274 return ;\r
1275 }\r
1276\r
1277 Flag = (MnpRxData->BroadcastFlag ? IP4_LINK_BROADCAST : 0);\r
1278 Flag |= (MnpRxData->MulticastFlag ? IP4_LINK_MULTICAST : 0);\r
1279 Flag |= (MnpRxData->PromiscuousFlag ? IP4_LINK_PROMISC : 0);\r
1280\r
1281 Token->CallBack (Token->IpInstance, Packet, EFI_SUCCESS, Flag, Token->Context);\r
1282}\r
1283\r
2ff29212 1284/**\r
2ff29212 1285 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.\r
1286\r
1287 @param Event The receive event delivered to MNP for receive.\r
1288 @param Context Context for the callback.\r
2ff29212 1289\r
1290**/\r
36ee91ca 1291VOID\r
1292EFIAPI\r
1293Ip4OnFrameReceived (\r
1294 IN EFI_EVENT Event,\r
1295 IN VOID *Context\r
1296 )\r
36ee91ca 1297{\r
1298 //\r
1299 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK\r
1300 //\r
d8d26fb2 1301 QueueDpc (TPL_CALLBACK, Ip4OnFrameReceivedDpc, Context);\r
36ee91ca 1302}\r
1303\r
772db4bb 1304\r
1305/**\r
1306 Request to receive the packet from the interface.\r
1307\r
1f6729ff 1308 @param[in] Interface The interface to receive the frames from.\r
3e8c18da 1309 @param[in] IpInstance The instance that requests the receive. NULL for\r
772db4bb 1310 the driver itself.\r
3e8c18da 1311 @param[in] CallBack Function to call when receive finished.\r
1f6729ff 1312 @param[in] Context Opaque parameter to the callback.\r
772db4bb 1313\r
1314 @retval EFI_ALREADY_STARTED There is already a pending receive request.\r
1f6729ff 1315 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.\r
772db4bb 1316 @retval EFI_SUCCESS The recieve request has been started.\r
5405e9a6 1317 @retval other Other error occurs.\r
772db4bb 1318\r
1319**/\r
1320EFI_STATUS\r
1321Ip4ReceiveFrame (\r
1322 IN IP4_INTERFACE *Interface,\r
24af132f 1323 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 1324 IN IP4_FRAME_CALLBACK CallBack,\r
1325 IN VOID *Context\r
1326 )\r
1327{\r
1328 IP4_LINK_RX_TOKEN *Token;\r
1329 EFI_STATUS Status;\r
1330\r
1331 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
1332\r
1333 if (Interface->RecvRequest != NULL) {\r
1334 return EFI_ALREADY_STARTED;\r
1335 }\r
1336\r
1337 Token = Ip4CreateLinkRxToken (Interface, IpInstance, CallBack, Context);\r
1338\r
1339 if (Token == NULL) {\r
1340 return EFI_OUT_OF_RESOURCES;\r
1341 }\r
1342\r
36ee91ca 1343 Interface->RecvRequest = Token;\r
772db4bb 1344 Status = Interface->Mnp->Receive (Interface->Mnp, &Token->MnpToken);\r
772db4bb 1345 if (EFI_ERROR (Status)) {\r
36ee91ca 1346 Interface->RecvRequest = NULL;\r
772db4bb 1347 Ip4FreeFrameRxToken (Token);\r
1348 return Status;\r
1349 }\r
772db4bb 1350 return EFI_SUCCESS;\r
1351}\r