]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
2268e6df828b1dbdb42d7ed0c6e4363327a6a7f5
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
1 /** @file
2
3 Copyright (c) 2005 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 MnpConfig.c
15
16 Abstract:
17
18 Implementation of Managed Network Protocol private services.
19
20
21 **/
22
23
24 #include "MnpImpl.h"
25
26 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {
27 MnpServiceBindingCreateChild,
28 MnpServiceBindingDestroyChild
29 };
30
31 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {
32 MnpGetModeData,
33 MnpConfigure,
34 MnpMcastIpToMac,
35 MnpGroups,
36 MnpTransmit,
37 MnpReceive,
38 MnpCancel,
39 MnpPoll
40 };
41
42 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
43 10000,
44 10000,
45 0,
46 FALSE,
47 FALSE,
48 FALSE,
49 FALSE,
50 FALSE,
51 FALSE,
52 FALSE
53 };
54
55 STATIC
56 EFI_STATUS
57 MnpAddFreeNbuf (
58 IN MNP_SERVICE_DATA *MnpServiceData,
59 IN UINTN Count
60 );
61
62 STATIC
63 EFI_STATUS
64 MnpStartSnp (
65 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
66 );
67
68 STATIC
69 EFI_STATUS
70 MnpStopSnp (
71 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
72 );
73
74 STATIC
75 EFI_STATUS
76 MnpStart (
77 IN MNP_SERVICE_DATA *MnpServiceData,
78 IN BOOLEAN IsConfigUpdate,
79 IN BOOLEAN EnableSystemPoll
80 );
81
82 STATIC
83 EFI_STATUS
84 MnpStop (
85 IN MNP_SERVICE_DATA *MnpServiceData
86 );
87
88 STATIC
89 EFI_STATUS
90 MnpConfigReceiveFilters (
91 IN MNP_SERVICE_DATA *MnpServiceData
92 );
93
94 STATIC
95 EFI_STATUS
96 MnpGroupOpAddCtrlBlk (
97 IN MNP_INSTANCE_DATA *Instance,
98 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
99 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
100 IN EFI_MAC_ADDRESS *MacAddress,
101 IN UINT32 HwAddressSize
102 );
103
104 STATIC
105 BOOLEAN
106 MnpGroupOpDelCtrlBlk (
107 IN MNP_INSTANCE_DATA *Instance,
108 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
109 );
110
111
112 /**
113 Add some NET_BUF into MnpServiceData->FreeNbufQue. The buffer length of
114 the NET_BUF is specified by MnpServiceData->BufferLength.
115
116 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
117 @param Count Number of NET_BUFFERs to add.
118
119 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated and
120 added into MnpServiceData->FreeNbufQue.
121 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
122
123 **/
124 STATIC
125 EFI_STATUS
126 MnpAddFreeNbuf (
127 IN MNP_SERVICE_DATA *MnpServiceData,
128 IN UINTN Count
129 )
130 {
131 EFI_STATUS Status;
132 UINTN Index;
133 NET_BUF *Nbuf;
134
135 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
136 ASSERT ((Count > 0) && (MnpServiceData->BufferLength > 0));
137
138 Status = EFI_SUCCESS;
139
140 for (Index = 0; Index < Count; Index++) {
141
142 Nbuf = NetbufAlloc (MnpServiceData->BufferLength + MnpServiceData->PaddingSize);
143 if (Nbuf == NULL) {
144
145 DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
146 Status = EFI_OUT_OF_RESOURCES;
147 break;
148 }
149
150 if (MnpServiceData->PaddingSize > 0) {
151 //
152 // Pad padding bytes before the media header
153 //
154 NetbufAllocSpace (Nbuf, MnpServiceData->PaddingSize, NET_BUF_TAIL);
155 NetbufTrim (Nbuf, MnpServiceData->PaddingSize, NET_BUF_HEAD);
156 }
157
158 NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
159 }
160
161 MnpServiceData->NbufCnt += Index;
162
163 return Status;
164 }
165
166
167 /**
168 Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
169 in the queue, first try to allocate some and add them into the queue, then
170 fetch the NET_BUF from the updated FreeNbufQue.
171
172 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
173
174 @return Pointer to the allocated free NET_BUF structure, if NULL the operation is failed.
175
176 **/
177 NET_BUF *
178 MnpAllocNbuf (
179 IN MNP_SERVICE_DATA *MnpServiceData
180 )
181 {
182 EFI_STATUS Status;
183 NET_BUF_QUEUE *FreeNbufQue;
184 NET_BUF *Nbuf;
185 EFI_TPL OldTpl;
186
187 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
188
189 FreeNbufQue = &MnpServiceData->FreeNbufQue;
190
191 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
192
193 //
194 // Check whether there are available buffers, or else try to add some.
195 //
196 if (FreeNbufQue->BufNum == 0) {
197
198 if ((MnpServiceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {
199
200 DEBUG (
201 (EFI_D_ERROR,
202 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
203 MnpServiceData)
204 );
205
206 Nbuf = NULL;
207 goto ON_EXIT;
208 }
209
210 Status = MnpAddFreeNbuf (MnpServiceData, MNP_NET_BUFFER_INCREASEMENT);
211 if (EFI_ERROR (Status)) {
212
213 DEBUG (
214 (EFI_D_ERROR,
215 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
216 Status)
217 );
218 //
219 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
220 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
221 //
222 }
223 }
224
225 Nbuf = NetbufQueRemove (FreeNbufQue);
226
227 //
228 // Increase the RefCnt.
229 //
230 if (Nbuf != NULL) {
231 NET_GET_REF (Nbuf);
232 }
233
234 ON_EXIT:
235 gBS->RestoreTPL (OldTpl);
236
237 return Nbuf;
238 }
239
240
241 /**
242 Try to reclaim the Nbuf into the buffer pool.
243
244 @param MnpServiceData Pointer to the mnp service context data.
245 @param Nbuf Pointer to the NET_BUF to free.
246
247 @return None.
248
249 **/
250 VOID
251 MnpFreeNbuf (
252 IN MNP_SERVICE_DATA *MnpServiceData,
253 IN NET_BUF *Nbuf
254 )
255 {
256 EFI_TPL OldTpl;
257
258 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
259 ASSERT (Nbuf->RefCnt > 1);
260
261 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
262
263 NET_PUT_REF (Nbuf);
264
265 if (Nbuf->RefCnt == 1) {
266 //
267 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
268 //
269 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);
270 NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
271 }
272
273 gBS->RestoreTPL (OldTpl);
274 }
275
276
277 /**
278 Initialize the mnp service context data.
279
280 @param MnpServiceData Pointer to the mnp service context data.
281 @param Snp Pointer to the simple network protocol.
282
283 @retval EFI_SUCCESS The mnp service context is initialized.
284 @retval Other Some error occurs.
285
286 **/
287 EFI_STATUS
288 MnpInitializeServiceData (
289 IN MNP_SERVICE_DATA *MnpServiceData,
290 IN EFI_HANDLE ImageHandle,
291 IN EFI_HANDLE ControllerHandle
292 )
293 {
294 EFI_STATUS Status;
295 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
296 EFI_SIMPLE_NETWORK_MODE *SnpMode;
297
298 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;
299
300 MnpServiceData->ControllerHandle = ControllerHandle;
301
302 //
303 // Copy the ServiceBinding structure.
304 //
305 MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;
306
307 //
308 // Open the Simple Network protocol.
309 //
310 Status = gBS->OpenProtocol (
311 ControllerHandle,
312 &gEfiSimpleNetworkProtocolGuid,
313 (VOID **) &Snp,
314 ImageHandle,
315 ControllerHandle,
316 EFI_OPEN_PROTOCOL_BY_DRIVER
317 );
318 if (EFI_ERROR (Status)) {
319 return EFI_UNSUPPORTED;
320 }
321
322 //
323 // Get MTU from Snp.
324 //
325 SnpMode = Snp->Mode;
326 MnpServiceData->Snp = Snp;
327 MnpServiceData->Mtu = SnpMode->MaxPacketSize;
328
329 //
330 // Initialize the lists.
331 //
332 InitializeListHead (&MnpServiceData->GroupAddressList);
333 InitializeListHead (&MnpServiceData->ChildrenList);
334
335 //
336 // Get the buffer length used to allocate NET_BUF to hold data received
337 // from SNP. Do this before fill the FreeNetBufQue.
338 //
339 MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;
340
341 //
342 // Make sure the protocol headers immediately following the media header
343 // 4-byte aligned
344 //
345 MnpServiceData->PaddingSize = (4 - SnpMode->MediaHeaderSize) & 0x3;
346
347 //
348 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
349 //
350 NetbufQueInit (&MnpServiceData->FreeNbufQue);
351 Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);
352 if (EFI_ERROR (Status)) {
353
354 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));
355 goto ERROR;
356 }
357 //
358 // Get one NET_BUF from the FreeNbufQue for rx cache.
359 //
360 MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);
361 NetbufAllocSpace (
362 MnpServiceData->RxNbufCache,
363 MnpServiceData->BufferLength,
364 NET_BUF_TAIL
365 );
366
367 //
368 // Allocate buffer pool for tx.
369 //
370 MnpServiceData->TxBuf = AllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);
371 if (MnpServiceData->TxBuf == NULL) {
372
373 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: AllocatePool failed.\n"));
374 Status = EFI_OUT_OF_RESOURCES;
375
376 goto ERROR;
377 }
378
379 //
380 // Create the system poll timer.
381 //
382 Status = gBS->CreateEvent (
383 EVT_NOTIFY_SIGNAL | EVT_TIMER,
384 TPL_CALLBACK,
385 MnpSystemPoll,
386 MnpServiceData,
387 &MnpServiceData->PollTimer
388 );
389 if (EFI_ERROR (Status)) {
390
391 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
392 goto ERROR;
393 }
394
395 //
396 // Create the timer for packet timeout check.
397 //
398 Status = gBS->CreateEvent (
399 EVT_NOTIFY_SIGNAL | EVT_TIMER,
400 TPL_CALLBACK,
401 MnpCheckPacketTimeout,
402 MnpServiceData,
403 &MnpServiceData->TimeoutCheckTimer
404 );
405 if (EFI_ERROR (Status)) {
406
407 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
408 goto ERROR;
409 }
410
411 //
412 // Create the timer for tx timeout check.
413 //
414 Status = gBS->CreateEvent (
415 EVT_TIMER,
416 TPL_CALLBACK,
417 NULL,
418 NULL,
419 &MnpServiceData->TxTimeoutEvent
420 );
421 if (EFI_ERROR (Status)) {
422
423 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
424 }
425
426 ERROR:
427
428 if (EFI_ERROR (Status)) {
429 //
430 // Free the dynamic allocated resources if necessary.
431 //
432 if (MnpServiceData->TimeoutCheckTimer != NULL) {
433
434 gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);
435 }
436
437 if (MnpServiceData->PollTimer != NULL) {
438
439 gBS->CloseEvent (MnpServiceData->PollTimer);
440 }
441
442 if (MnpServiceData->TxBuf != NULL) {
443
444 gBS->FreePool (MnpServiceData->TxBuf);
445 }
446
447 if (MnpServiceData->RxNbufCache != NULL) {
448
449 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
450 }
451
452 if (MnpServiceData->FreeNbufQue.BufNum != 0) {
453
454 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
455 }
456 }
457
458 return Status;
459 }
460
461
462 /**
463 Flush the mnp service context data.
464
465 @param MnpServiceData Pointer to the mnp service context data.
466
467 @return None.
468
469 **/
470 VOID
471 MnpFlushServiceData (
472 IN MNP_SERVICE_DATA *MnpServiceData,
473 IN EFI_HANDLE ImageHandle
474 )
475 {
476 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
477
478 //
479 // The GroupAddressList must be empty.
480 //
481 ASSERT (IsListEmpty (&MnpServiceData->GroupAddressList));
482
483 //
484 // Close the event.
485 //
486 gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);
487 gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);
488 gBS->CloseEvent (&MnpServiceData->PollTimer);
489
490 //
491 // Free the tx buffer.
492 //
493 gBS->FreePool (MnpServiceData->TxBuf);
494
495 //
496 // Free the RxNbufCache.
497 //
498 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
499
500 //
501 // Flush the FreeNbufQue.
502 //
503 MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;
504 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
505
506 DEBUG_CODE (
507
508 if (MnpServiceData->NbufCnt != 0) {
509
510 DEBUG ((EFI_D_WARN, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
511 }
512 );
513
514 //
515 // Close the Simple Network Protocol.
516 //
517 gBS->CloseProtocol (
518 MnpServiceData->ControllerHandle,
519 &gEfiSimpleNetworkProtocolGuid,
520 ImageHandle,
521 MnpServiceData->ControllerHandle
522 );
523 }
524
525
526 /**
527 Initialize the mnp instance context data.
528
529 @param MnpServiceData Pointer to the mnp service context data.
530 @param Instance Pointer to the mnp instance context data to
531 initialize.
532
533 @return None.
534
535 **/
536 VOID
537 MnpInitializeInstanceData (
538 IN MNP_SERVICE_DATA *MnpServiceData,
539 IN MNP_INSTANCE_DATA *Instance
540 )
541 {
542 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
543 ASSERT (Instance != NULL);
544
545 //
546 // Set the signature.
547 //
548 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
549
550 //
551 // Copy the MNP Protocol interfaces from the template.
552 //
553 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));
554
555 //
556 // Copy the default config data.
557 //
558 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));
559
560 //
561 // Initialize the lists.
562 //
563 InitializeListHead (&Instance->GroupCtrlBlkList);
564 InitializeListHead (&Instance->RcvdPacketQueue);
565 InitializeListHead (&Instance->RxDeliveredPacketQueue);
566
567 //
568 // Initialize the RxToken Map.
569 //
570 NetMapInit (&Instance->RxTokenMap);
571
572 //
573 // Save the MnpServiceData info.
574 //
575 Instance->MnpServiceData = MnpServiceData;
576 }
577
578
579 /**
580 Check whether the token specified by Arg maches the token in Item.
581
582 @param Map Pointer to the NET_MAP.
583 @param Item Pointer to the NET_MAP_ITEM
584 @param Arg Pointer to the Arg, it's a pointer to the token to
585 check.
586
587 @retval EFI_SUCCESS The token specified by Arg is different from the
588 token in Item.
589 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
590 Item.
591
592 **/
593 EFI_STATUS
594 MnpTokenExist (
595 IN NET_MAP *Map,
596 IN NET_MAP_ITEM *Item,
597 IN VOID *Arg
598 )
599 {
600 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;
601 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;
602
603 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
604 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
605
606 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
607 //
608 // The token is the same either the two tokens equals or the Events in
609 // the two tokens are the same.
610 //
611 return EFI_ACCESS_DENIED;
612 }
613
614 return EFI_SUCCESS;
615 }
616
617
618 /**
619 Cancel the token specified by Arg if it matches the token in Item.
620
621 @param Map Pointer to the NET_MAP.
622 @param Item Pointer to the NET_MAP_ITEM
623 @param Arg Pointer to the Arg, it's a pointer to the token to
624 cancel.
625
626 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is
627 cancelled, or the Arg isn't NULL, and the token in
628 Item is different from the Arg.
629 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
630 Arg, and the token is cancelled.
631
632 **/
633 EFI_STATUS
634 MnpCancelTokens (
635 IN NET_MAP *Map,
636 IN NET_MAP_ITEM *Item,
637 IN VOID *Arg
638 )
639 {
640 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;
641
642 if ((Arg != NULL) && (Item->Key != Arg)) {
643 //
644 // The token in Item is not the token specified by Arg.
645 //
646 return EFI_SUCCESS;
647 }
648
649 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
650
651 //
652 // Remove the item from the map.
653 //
654 NetMapRemoveItem (Map, Item, NULL);
655
656 //
657 // Cancel this token with status set to EFI_ABORTED.
658 //
659 TokenToCancel->Status = EFI_ABORTED;
660 gBS->SignalEvent (TokenToCancel->Event);
661
662 if (Arg != NULL) {
663 //
664 // Only abort the token specified by Arg if Arg isn't NULL.
665 //
666 return EFI_ABORTED;
667 }
668
669 return EFI_SUCCESS;
670 }
671
672
673 /**
674 Start and initialize the simple network.
675
676 @param Snp Pointer to the simple network protocol.
677
678 @retval EFI_SUCCESS The simple network protocol is started.
679 @retval Other Some error occurs.
680
681 **/
682 STATIC
683 EFI_STATUS
684 MnpStartSnp (
685 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
686 )
687 {
688 EFI_STATUS Status;
689
690 ASSERT (Snp != NULL);
691
692 //
693 // Start the simple network.
694 //
695 Status = Snp->Start (Snp);
696
697 if (!EFI_ERROR (Status)) {
698 //
699 // Initialize the simple network.
700 //
701 Status = Snp->Initialize (Snp, 0, 0);
702 }
703
704 return Status;
705 }
706
707
708 /**
709 Stop the simple network.
710
711 @param Snp Pointer to the simple network protocol.
712
713 @retval EFI_SUCCESS The simple network is stopped.
714 @retval Other Some error occurs.
715
716 **/
717 STATIC
718 EFI_STATUS
719 MnpStopSnp (
720 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
721 )
722 {
723 EFI_STATUS Status;
724
725 ASSERT (Snp != NULL);
726
727 //
728 // Shut down the simple network.
729 //
730 Status = Snp->Shutdown (Snp);
731
732 if (!EFI_ERROR (Status)) {
733 //
734 // Stop the simple network.
735 //
736 Status = Snp->Stop (Snp);
737 }
738
739 return Status;
740 }
741
742
743 /**
744 Start the managed network, this function is called when one instance is configured
745 or reconfigured.
746
747 @param MnpServiceData Pointer to the mnp service context data.
748 @param IsConfigUpdate The instance is reconfigured or it's the first time
749 the instanced is configured.
750 @param EnableSystemPoll Enable the system polling or not.
751
752 @retval EFI_SUCCESS The managed network is started and some
753 configuration is updated.
754 @retval Other Some error occurs.
755
756 **/
757 STATIC
758 EFI_STATUS
759 MnpStart (
760 IN MNP_SERVICE_DATA *MnpServiceData,
761 IN BOOLEAN IsConfigUpdate,
762 IN BOOLEAN EnableSystemPoll
763 )
764 {
765 EFI_STATUS Status;
766 EFI_TIMER_DELAY TimerOpType;
767
768 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
769
770 Status = EFI_SUCCESS;
771
772 if (!IsConfigUpdate) {
773 //
774 // If it's not a configuration update, increase the configured children number.
775 //
776 MnpServiceData->ConfiguredChildrenNumber++;
777
778 if (MnpServiceData->ConfiguredChildrenNumber == 1) {
779 //
780 // It's the first configured child, start the simple network.
781 //
782 Status = MnpStartSnp (MnpServiceData->Snp);
783 if (EFI_ERROR (Status)) {
784
785 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));
786 goto ErrorExit;
787 }
788
789 //
790 // Start the timeout timer.
791 //
792 Status = gBS->SetTimer (
793 MnpServiceData->TimeoutCheckTimer,
794 TimerPeriodic,
795 MNP_TIMEOUT_CHECK_INTERVAL
796 );
797 if (EFI_ERROR (Status)) {
798
799 DEBUG (
800 (EFI_D_ERROR,
801 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
802 Status)
803 );
804 goto ErrorExit;
805 }
806 }
807 }
808
809 if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {
810 //
811 // The EnableSystemPoll differs with the current state, disable or enable
812 // the system poll.
813 //
814 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
815
816 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);
817 if (EFI_ERROR (Status)) {
818
819 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));
820 goto ErrorExit;
821 }
822
823 MnpServiceData->EnableSystemPoll = EnableSystemPoll;
824 }
825
826 //
827 // Change the receive filters if need.
828 //
829 Status = MnpConfigReceiveFilters (MnpServiceData);
830
831 ErrorExit:
832
833 return Status;
834 }
835
836
837 /**
838 Stop the managed network.
839
840 @param MnpServiceData Pointer to the mnp service context data.
841
842 @retval EFI_SUCCESS The managed network is stopped.
843 @retval Other Some error occurs.
844
845 **/
846 STATIC
847 EFI_STATUS
848 MnpStop (
849 IN MNP_SERVICE_DATA *MnpServiceData
850 )
851 {
852 EFI_STATUS Status;
853
854 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
855 ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);
856
857 //
858 // Configure the receive filters.
859 //
860 MnpConfigReceiveFilters (MnpServiceData);
861
862 //
863 // Decrease the children number.
864 //
865 MnpServiceData->ConfiguredChildrenNumber--;
866
867 if (MnpServiceData->ConfiguredChildrenNumber > 0) {
868 //
869 // If there are other configured chilren, return and keep the timers and
870 // simple network unchanged.
871 //
872 return EFI_SUCCESS;
873 }
874
875 //
876 // No configured children now.
877 //
878
879 if (MnpServiceData->EnableSystemPoll) {
880 //
881 // The system poll in on, cancel the poll timer.
882 //
883 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);
884 MnpServiceData->EnableSystemPoll = FALSE;
885 }
886
887 //
888 // Cancel the timeout timer.
889 //
890 Status = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);
891
892 //
893 // Stop the simple network.
894 //
895 Status = MnpStopSnp (MnpServiceData->Snp);
896
897 return Status;
898 }
899
900
901 /**
902 Flush the instance's received data.
903
904 @param Instance Pointer to the mnp instance context data.
905
906 @return None.
907
908 **/
909 VOID
910 MnpFlushRcvdDataQueue (
911 IN MNP_INSTANCE_DATA *Instance
912 )
913 {
914 EFI_TPL OldTpl;
915 MNP_RXDATA_WRAP *RxDataWrap;
916
917 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
918
919 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
920
921 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {
922 //
923 // Remove all the Wraps.
924 //
925 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
926
927 //
928 // Recycle the RxDataWrap.
929 //
930 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
931 Instance->RcvdPacketQueueSize--;
932 }
933
934 ASSERT (Instance->RcvdPacketQueueSize == 0);
935
936 gBS->RestoreTPL (OldTpl);
937 }
938
939
940 /**
941 Configure the Instance using ConfigData.
942
943 @param Instance Pointer to the mnp instance context data.
944 @param ConfigData Pointer to the configuration data used to configure
945 the isntance.
946
947 @retval EFI_SUCCESS The Instance is configured.
948 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
949 implementation doesn't support it.
950 @retval Other Some error occurs.
951
952 **/
953 EFI_STATUS
954 MnpConfigureInstance (
955 IN MNP_INSTANCE_DATA *Instance,
956 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
957 )
958 {
959 EFI_STATUS Status;
960 MNP_SERVICE_DATA *MnpServiceData;
961 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;
962 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;
963 BOOLEAN IsConfigUpdate;
964
965 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
966
967 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
968 //
969 // Don't support timestamp.
970 //
971 return EFI_UNSUPPORTED;
972 }
973
974 Status = EFI_SUCCESS;
975
976 MnpServiceData = Instance->MnpServiceData;
977 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
978
979 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
980
981 OldConfigData = &Instance->ConfigData;
982 NewConfigData = ConfigData;
983 if (NewConfigData == NULL) {
984 //
985 // Restore back the default config data if a reset of this instance
986 // is required.
987 //
988 NewConfigData = &mMnpDefaultConfigData;
989 }
990
991 //
992 // Reset the instance's receive filter.
993 //
994 Instance->ReceiveFilter = 0;
995
996 //
997 // Clear the receive counters according to the old ConfigData.
998 //
999 if (OldConfigData->EnableUnicastReceive) {
1000 MnpServiceData->UnicastCount--;
1001 }
1002
1003 if (OldConfigData->EnableMulticastReceive) {
1004 MnpServiceData->MulticastCount--;
1005 }
1006
1007 if (OldConfigData->EnableBroadcastReceive) {
1008 MnpServiceData->BroadcastCount--;
1009 }
1010
1011 if (OldConfigData->EnablePromiscuousReceive) {
1012 MnpServiceData->PromiscuousCount--;
1013 }
1014
1015 //
1016 // Set the receive filter counters and the receive filter of the
1017 // instance according to the new ConfigData.
1018 //
1019 if (NewConfigData->EnableUnicastReceive) {
1020 MnpServiceData->UnicastCount++;
1021 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
1022 }
1023
1024 if (NewConfigData->EnableMulticastReceive) {
1025 MnpServiceData->MulticastCount++;
1026 }
1027
1028 if (NewConfigData->EnableBroadcastReceive) {
1029 MnpServiceData->BroadcastCount++;
1030 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1031 }
1032
1033 if (NewConfigData->EnablePromiscuousReceive) {
1034 MnpServiceData->PromiscuousCount++;
1035 }
1036
1037 if (OldConfigData->FlushQueuesOnReset) {
1038
1039 MnpFlushRcvdDataQueue (Instance);
1040 }
1041
1042 if (ConfigData == NULL) {
1043
1044 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);
1045 }
1046
1047 if (!NewConfigData->EnableMulticastReceive) {
1048
1049 MnpGroupOp (Instance, FALSE, NULL, NULL);
1050 }
1051
1052 //
1053 // Save the new configuration data.
1054 //
1055 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));
1056
1057 Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1058
1059 if (Instance->Configured) {
1060 //
1061 // The instance is configured, start the Mnp.
1062 //
1063 Status = MnpStart (
1064 MnpServiceData,
1065 IsConfigUpdate,
1066 (BOOLEAN) !NewConfigData->DisableBackgroundPolling
1067 );
1068 } else {
1069 //
1070 // The instance is changed to the unconfigured state, stop the Mnp.
1071 //
1072 Status = MnpStop (MnpServiceData);
1073 }
1074
1075 return Status;
1076 }
1077
1078
1079 /**
1080 Configure the Snp receive filters according to the instances' receive filter
1081 settings.
1082
1083 @param MnpServiceData Pointer to the mnp service context data.
1084
1085 @retval EFI_SUCCESS The receive filters is configured.
1086 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack
1087 of memory resource.
1088
1089 **/
1090 STATIC
1091 EFI_STATUS
1092 MnpConfigReceiveFilters (
1093 IN MNP_SERVICE_DATA *MnpServiceData
1094 )
1095 {
1096 EFI_STATUS Status;
1097 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1098 EFI_MAC_ADDRESS *MCastFilter;
1099 UINT32 MCastFilterCnt;
1100 UINT32 EnableFilterBits;
1101 UINT32 DisableFilterBits;
1102 BOOLEAN ResetMCastFilters;
1103 LIST_ENTRY *Entry;
1104 UINT32 Index;
1105 MNP_GROUP_ADDRESS *GroupAddress;
1106
1107 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1108
1109 Snp = MnpServiceData->Snp;
1110
1111 //
1112 // Initialize the enable filter and disable filter.
1113 //
1114 EnableFilterBits = 0;
1115 DisableFilterBits = Snp->Mode->ReceiveFilterMask;
1116
1117 if (MnpServiceData->UnicastCount != 0) {
1118 //
1119 // Enable unicast if any instance wants to receive unicast.
1120 //
1121 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1122 }
1123
1124 if (MnpServiceData->BroadcastCount != 0) {
1125 //
1126 // Enable broadcast if any instance wants to receive broadcast.
1127 //
1128 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1129 }
1130
1131 MCastFilter = NULL;
1132 MCastFilterCnt = 0;
1133 ResetMCastFilters = TRUE;
1134
1135 if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {
1136 //
1137 // There are instances configured to receive multicast and already some group
1138 // addresses are joined.
1139 //
1140
1141 ResetMCastFilters = FALSE;
1142
1143 if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
1144 //
1145 // The joind group address is less than simple network's maximum count.
1146 // Just configure the snp to do the multicast filtering.
1147 //
1148
1149 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1150
1151 //
1152 // Allocate pool for the mulicast addresses.
1153 //
1154 MCastFilterCnt = MnpServiceData->GroupAddressCount;
1155 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);
1156 if (MCastFilter == NULL) {
1157
1158 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1159 return EFI_OUT_OF_RESOURCES;
1160 }
1161
1162 //
1163 // Fill the multicast HW address buffer.
1164 //
1165 Index = 0;
1166 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
1167
1168 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1169 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));
1170 Index++;
1171
1172 ASSERT (Index <= MCastFilterCnt);
1173 }
1174 } else {
1175 //
1176 // The maximum multicast is reached, set the filter to be promiscuous
1177 // multicast.
1178 //
1179
1180 if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
1181 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1182 } else {
1183 //
1184 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1185 // set the NIC to be promiscuous although this will tremendously degrade
1186 // the performance.
1187 //
1188 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1189 }
1190 }
1191 }
1192
1193 if (MnpServiceData->PromiscuousCount != 0) {
1194 //
1195 // Enable promiscuous if any instance wants to receive promiscuous.
1196 //
1197 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1198 }
1199
1200 //
1201 // Set the disable filter.
1202 //
1203 DisableFilterBits ^= EnableFilterBits;
1204
1205 //
1206 // Configure the receive filters of SNP.
1207 //
1208 Status = Snp->ReceiveFilters (
1209 Snp,
1210 EnableFilterBits,
1211 DisableFilterBits,
1212 ResetMCastFilters,
1213 MCastFilterCnt,
1214 MCastFilter
1215 );
1216 DEBUG_CODE (
1217 if (EFI_ERROR (Status)) {
1218
1219 DEBUG (
1220 (EFI_D_ERROR,
1221 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1222 Status)
1223 );
1224 }
1225 );
1226
1227 if (MCastFilter != NULL) {
1228 //
1229 // Free the buffer used to hold the group addresses.
1230 //
1231 gBS->FreePool (MCastFilter);
1232 }
1233
1234 return Status;
1235 }
1236
1237
1238 /**
1239 Add a group address control block which controls the MacAddress for
1240 this instance.
1241
1242 @param Instance Pointer to the mnp instance context data.
1243 @param CtrlBlk Pointer to the group address control block.
1244 @param GroupAddress Pointer to the group adress.
1245 @param MacAddress Pointer to the mac address.
1246 @param HwAddressSize The hardware address size.
1247
1248 @retval EFI_SUCCESS The group address control block is added.
1249 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1250
1251 **/
1252 STATIC
1253 EFI_STATUS
1254 MnpGroupOpAddCtrlBlk (
1255 IN MNP_INSTANCE_DATA *Instance,
1256 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
1257 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
1258 IN EFI_MAC_ADDRESS *MacAddress,
1259 IN UINT32 HwAddressSize
1260 )
1261 {
1262 MNP_SERVICE_DATA *MnpServiceData;
1263
1264 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1265
1266 MnpServiceData = Instance->MnpServiceData;
1267 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1268
1269 if (GroupAddress == NULL) {
1270
1271 ASSERT (MacAddress != NULL);
1272
1273 //
1274 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1275 //
1276 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));
1277 if (GroupAddress == NULL) {
1278
1279 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1280
1281 return EFI_OUT_OF_RESOURCES;
1282 }
1283
1284 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));
1285 GroupAddress->RefCnt = 0;
1286 InsertTailList (
1287 &MnpServiceData->GroupAddressList,
1288 &GroupAddress->AddrEntry
1289 );
1290 MnpServiceData->GroupAddressCount++;
1291 }
1292
1293 //
1294 // Increase the RefCnt.
1295 //
1296 GroupAddress->RefCnt++;
1297
1298 //
1299 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1300 //
1301 CtrlBlk->GroupAddress = GroupAddress;
1302 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1303
1304 return EFI_SUCCESS;
1305 }
1306
1307
1308 /**
1309 Delete a group control block from the instance. If the controlled group address's
1310 reference count reaches zero, the group address is removed too.
1311
1312 @param Instance Pointer to the instance context data.
1313 @param CtrlBlk Pointer to the group control block to delete.
1314
1315 @return The group address controlled by the control block is no longer used or not.
1316
1317 **/
1318 STATIC
1319 BOOLEAN
1320 MnpGroupOpDelCtrlBlk (
1321 IN MNP_INSTANCE_DATA *Instance,
1322 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
1323 )
1324 {
1325 MNP_SERVICE_DATA *MnpServiceData;
1326 MNP_GROUP_ADDRESS *GroupAddress;
1327
1328 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1329
1330 MnpServiceData = Instance->MnpServiceData;
1331 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1332
1333 //
1334 // Remove and free the CtrlBlk.
1335 //
1336 GroupAddress = CtrlBlk->GroupAddress;
1337 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);
1338 gBS->FreePool (CtrlBlk);
1339
1340 ASSERT (GroupAddress->RefCnt > 0);
1341
1342 //
1343 // Count down the RefCnt.
1344 //
1345 GroupAddress->RefCnt--;
1346
1347 if (GroupAddress->RefCnt == 0) {
1348 //
1349 // Free this GroupAddress entry if no instance uses it.
1350 //
1351 MnpServiceData->GroupAddressCount--;
1352 RemoveEntryList (&GroupAddress->AddrEntry);
1353 gBS->FreePool (GroupAddress);
1354
1355 return TRUE;
1356 }
1357
1358 return FALSE;
1359 }
1360
1361
1362 /**
1363 Do the group operations for this instance.
1364
1365 @param Instance Pointer to the instance context data.
1366 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1367 group/groups.
1368 @param MacAddress Pointer to the group address to join or leave.
1369 @param CtrlBlk Pointer to the group control block if JoinFlag if
1370 FALSE.
1371
1372 @retval EFI_SUCCESS The group operation finished.
1373 @retval Other Some error occurs.
1374
1375 **/
1376 EFI_STATUS
1377 MnpGroupOp (
1378 IN MNP_INSTANCE_DATA *Instance,
1379 IN BOOLEAN JoinFlag,
1380 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,
1381 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
1382 )
1383 {
1384 MNP_SERVICE_DATA *MnpServiceData;
1385 LIST_ENTRY *Entry;
1386 LIST_ENTRY *NextEntry;
1387 MNP_GROUP_ADDRESS *GroupAddress;
1388 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1389 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1390 EFI_STATUS Status;
1391 BOOLEAN AddressExist;
1392 BOOLEAN NeedUpdate;
1393
1394 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1395
1396 MnpServiceData = Instance->MnpServiceData;
1397 SnpMode = MnpServiceData->Snp->Mode;
1398
1399 if (JoinFlag) {
1400 //
1401 // A new gropu address is to be added.
1402 //
1403
1404 GroupAddress = NULL;
1405 AddressExist = FALSE;
1406
1407 //
1408 // Allocate memory for the control block.
1409 //
1410 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1411 if (NewCtrlBlk == NULL) {
1412
1413 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));
1414 return EFI_OUT_OF_RESOURCES;
1415 }
1416
1417 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
1418 //
1419 // Check whether the MacAddress is already joined by other instances.
1420 //
1421 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1422 if (0 == CompareMem (
1423 MacAddress,
1424 &GroupAddress->Address,
1425 SnpMode->HwAddressSize
1426 )) {
1427
1428 AddressExist = TRUE;
1429 break;
1430 }
1431 }
1432
1433 if (!AddressExist) {
1434 GroupAddress = NULL;
1435 }
1436
1437 //
1438 // Add the GroupAddress for this instance.
1439 //
1440 Status = MnpGroupOpAddCtrlBlk (
1441 Instance,
1442 NewCtrlBlk,
1443 GroupAddress,
1444 MacAddress,
1445 SnpMode->HwAddressSize
1446 );
1447 if (EFI_ERROR (Status)) {
1448
1449 return Status;
1450 }
1451
1452 NeedUpdate = TRUE;
1453 } else {
1454
1455 if (MacAddress != NULL) {
1456
1457 ASSERT (CtrlBlk != NULL);
1458
1459 //
1460 // Leave the specific multicast mac address.
1461 //
1462 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1463 } else {
1464 //
1465 // Leave all multicast mac addresses.
1466 //
1467 NeedUpdate = FALSE;
1468
1469 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1470
1471 NewCtrlBlk = NET_LIST_USER_STRUCT (
1472 Entry,
1473 MNP_GROUP_CONTROL_BLOCK,
1474 CtrlBlkEntry
1475 );
1476 //
1477 // Update is required if the group address left is no longer used
1478 // by other instances.
1479 //
1480 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1481 }
1482 }
1483 }
1484
1485 Status = EFI_SUCCESS;
1486
1487 if (NeedUpdate) {
1488 //
1489 // Reconfigure the receive filters if necessary.
1490 //
1491 Status = MnpConfigReceiveFilters (MnpServiceData);
1492 }
1493
1494 return Status;
1495 }