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