1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** NetX Component                                                        */
15 /**                                                                       */
16 /**   Multiple Registration Protocol (MRP)                                */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 /* Include necessary system files.  */
22 #include "nx_mrp.h"
23 
24 #ifdef NX_ENABLE_VLAN
25 
26 #ifdef NX_MRP_DEBUG_ENABLE
27 /* For debug */
28 UCHAR *event_str[] =
29 {
30     "rNew", "rJoinin", "rIN", "rJoinMT", "rMT", "rLV", "rLA",
31     "begin", "new", "join",
32     "lv", "tx", "txLA", "txLAF", "Flush", "redec",
33     "periodic", "LVTimer", "LATimer", "pTimer",
34     "pdEnable", "pdDisable",
35 };
36 
37 UCHAR *state_str[] =
38 {
39     "VO", "VP", "VN", "AN", "AA", "QA", "LA", "AO", "QO", "AP", "QP", "LO",
40     "IN", "LV", "MT",
41     "LA_A", "LA_P",
42     "PT_A", "PT_P",
43 };
44 
45 UCHAR *action_str[] =
46 {
47     "NX_NULL", "SN", "SJ", "SJOPT", "SL", "S", "SOPT", "SLA",
48     "Periodic", "Start_LVT", "Stop_LVT", "Start_LAT", "Stop_LAT",
49 };
50 #endif
51 
52 /**************************************************************************/
53 /*                                                                        */
54 /*  FUNCTION                                               RELEASE        */
55 /*                                                                        */
56 /*    nx_mrp_applicant_event_process                      PORTABLE C      */
57 /*                                                           6.4.0        */
58 /*  AUTHOR                                                                */
59 /*                                                                        */
60 /*    Yajun Xia, Microsoft Corporation                                    */
61 /*                                                                        */
62 /*  DESCRIPTION                                                           */
63 /*                                                                        */
64 /*    This function processes event for attribute of mrp participant.     */
65 /*                                                                        */
66 /*  INPUT                                                                 */
67 /*                                                                        */
68 /*    mrp                                   Pointer to MRP instance       */
69 /*    participant                           Pointer to MRP participant    */
70 /*    attribute                             Pointer to MRP attribute      */
71 /*    event                                 Event to be processed         */
72 /*                                                                        */
73 /*  OUTPUT                                                                */
74 /*                                                                        */
75 /*    status                                Completion status             */
76 /*                                                                        */
77 /*  CALLS                                                                 */
78 /*                                                                        */
79 /*    None                                                                */
80 /*                                                                        */
81 /*  CALLED BY                                                             */
82 /*                                                                        */
83 /*    nx_mrp_event_process                  MRP event process             */
84 /*    nx_mrp_attribute_new                  MRP attribute new             */
85 /*    nx_mrp_periodic_timeout_process       MRP periodic timeout process  */
86 /*    nx_mrp_join_timeout_process           MRP join timeout process      */
87 /*                                                                        */
88 /*  RELEASE HISTORY                                                       */
89 /*                                                                        */
90 /*    DATE              NAME                      DESCRIPTION             */
91 /*                                                                        */
92 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
93 /*                                                                        */
94 /**************************************************************************/
nx_mrp_applicant_event_process(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant,NX_MRP_ATTRIBUTE * attribute,UCHAR mrp_event)95 UINT nx_mrp_applicant_event_process(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant, NX_MRP_ATTRIBUTE *attribute, UCHAR mrp_event)
96 {
97 #ifdef NX_MRP_DEBUG_ENABLE
98 UCHAR origin_state = attribute -> applicant.state;
99 #endif
100     NX_PARAMETER_NOT_USED(participant);
101     if (attribute == NX_NULL || mrp == NX_NULL)
102     {
103         return(NX_INVALID_PARAMETERS);
104     }
105 
106     attribute -> applicant.action = NX_MRP_ACTION_NULL;
107 
108     switch (mrp_event)
109     {
110     case NX_MRP_EVENT_BEGIN:
111         attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VO;
112         break;
113 
114     case NX_MRP_EVENT_NEW:
115         if (attribute -> applicant.state != NX_MRP_APPLICANT_STATE_AN)
116         {
117             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VN;
118         }
119 
120         break;
121 
122     case NX_MRP_EVENT_JOIN:
123         switch (attribute -> applicant.state)
124         {
125         case NX_MRP_APPLICANT_STATE_VO:
126             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VP;
127             break;
128 
129         case NX_MRP_APPLICANT_STATE_LA:
130             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
131             break;
132 
133         case NX_MRP_APPLICANT_STATE_AO:
134             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AP;
135             break;
136 
137         case NX_MRP_APPLICANT_STATE_QO:
138             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QP;
139             break;
140 
141         case NX_MRP_APPLICANT_STATE_LO:
142             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VP;
143             break;
144 
145         default:
146             /* do nothing */
147             break;
148         }
149         break;
150 
151     case NX_MRP_EVENT_LV:
152         switch (attribute -> applicant.state)
153         {
154         case NX_MRP_APPLICANT_STATE_VP:
155             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VO;
156             break;
157 
158         case NX_MRP_APPLICANT_STATE_VN:
159         case NX_MRP_APPLICANT_STATE_AN:
160         case NX_MRP_APPLICANT_STATE_AA:
161         case NX_MRP_APPLICANT_STATE_QA:
162             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_LA;
163             break;
164 
165         case NX_MRP_APPLICANT_STATE_AP:
166             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AO;
167             break;
168 
169         case NX_MRP_APPLICANT_STATE_QP:
170             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QO;
171             break;
172 
173         default:
174             /* do nothing */
175             break;
176         }
177         break;
178 
179     case NX_MRP_EVENT_RNEW:
180         /* do nothing */
181         break;
182 
183     case NX_MRP_EVENT_RJOININ:
184         switch (attribute -> applicant.state)
185         {
186         case NX_MRP_APPLICANT_STATE_VO:
187             /* Ignored (no transition) if point-to-point subset or if operPointToPointMAC is TRUE */
188             if (mrp -> oper_p2p_mac != NX_TRUE)
189             {
190                 attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AO;
191             }
192 
193             break;
194 
195         case NX_MRP_APPLICANT_STATE_VP:
196             /* Ignored (no transition) if point-to-point subset or if operPointToPointMAC is TRUE */
197             if (mrp -> oper_p2p_mac != NX_TRUE)
198             {
199                 attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AP;
200             }
201             break;
202 
203         case NX_MRP_APPLICANT_STATE_AA:
204             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
205             break;
206 
207         case NX_MRP_APPLICANT_STATE_AO:
208             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QO;
209             break;
210 
211         case NX_MRP_APPLICANT_STATE_AP:
212             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QP;
213             break;
214 
215         default:
216             /* do nothing */
217             break;
218         }
219         break;
220 
221     case NX_MRP_EVENT_RIN:
222         if (attribute -> applicant.state == NX_MRP_APPLICANT_STATE_AA)
223         {
224             /* Ignored (no transition) if operPointToPointMAC is FALSE */
225             if (mrp -> oper_p2p_mac == NX_TRUE)
226             {
227                 attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
228             }
229         }
230         break;
231 
232     case NX_MRP_EVENT_RJOINMT:
233     case NX_MRP_EVENT_RMT:
234         switch (attribute -> applicant.state)
235         {
236         case NX_MRP_APPLICANT_STATE_QA:
237             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
238             break;
239 
240         case NX_MRP_APPLICANT_STATE_QO:
241             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AO;
242             break;
243 
244         case NX_MRP_APPLICANT_STATE_QP:
245             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AP;
246             break;
247 
248         case NX_MRP_APPLICANT_STATE_LO:
249             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VO;
250             break;
251 
252         default:
253             /* do nothing */
254             break;
255         }
256         break;
257 
258     case NX_MRP_EVENT_RLV:
259     case NX_MRP_EVENT_RLA:
260     case NX_MRP_EVENT_REDECLARE:
261         switch (attribute -> applicant.state)
262         {
263         case NX_MRP_APPLICANT_STATE_VO:
264         case NX_MRP_APPLICANT_STATE_AO:
265         case NX_MRP_APPLICANT_STATE_QO:
266             /* Applicant-Only participants exclude the LO state, and transition to VO */
267             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_LO;
268             break;
269 
270         case NX_MRP_APPLICANT_STATE_AN:
271             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VN;
272             break;
273 
274         case NX_MRP_APPLICANT_STATE_AA:
275         case NX_MRP_APPLICANT_STATE_QA:
276         case NX_MRP_APPLICANT_STATE_AP:
277         case NX_MRP_APPLICANT_STATE_QP:
278             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VP;
279             break;
280 
281         default:
282             /* do nothing */
283             break;
284         }
285         break;
286 
287     case NX_MRP_EVENT_PERIODIC:
288         switch (attribute -> applicant.state)
289         {
290         case NX_MRP_APPLICANT_STATE_QA:
291             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
292             break;
293 
294         case NX_MRP_APPLICANT_STATE_QP:
295             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AP;
296             break;
297 
298         default:
299             /* do nothing */
300             break;
301         }
302         break;
303 
304     case NX_MRP_EVENT_TX:
305         switch (attribute -> applicant.state)
306         {
307         case NX_MRP_APPLICANT_STATE_VO:
308         case NX_MRP_APPLICANT_STATE_AO:
309         case NX_MRP_APPLICANT_STATE_QO:
310         case NX_MRP_APPLICANT_STATE_QP:
311             attribute -> applicant.action = NX_MRP_ACTION_S_OPT;
312             break;
313 
314         case NX_MRP_APPLICANT_STATE_VP:
315             attribute -> applicant.action = NX_MRP_ACTION_SJ;
316             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
317             break;
318 
319         case NX_MRP_APPLICANT_STATE_VN:
320             attribute -> applicant.action = NX_MRP_ACTION_SN;
321             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AN;
322             break;
323 
324         case NX_MRP_APPLICANT_STATE_AN:
325             attribute -> applicant.action = NX_MRP_ACTION_SN;
326             if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_IN)
327             {
328                 attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
329             }
330             else
331             {
332                 attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
333             }
334             break;
335 
336         case NX_MRP_APPLICANT_STATE_AA:
337         case NX_MRP_APPLICANT_STATE_AP:
338             attribute -> applicant.action = NX_MRP_ACTION_SJ;
339             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
340             break;
341 
342         case NX_MRP_APPLICANT_STATE_QA:
343             attribute -> applicant.action = NX_MRP_ACTION_SJ_OPT;
344             break;
345 
346         case NX_MRP_APPLICANT_STATE_LA:
347             attribute -> applicant.action = NX_MRP_ACTION_SL;
348             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VO;
349             break;
350 
351         case NX_MRP_APPLICANT_STATE_LO:
352             attribute -> applicant.action = NX_MRP_ACTION_S;
353             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VO;
354             break;
355 
356         default:
357             /* do nothing */
358             break;
359         }
360         break;
361 
362     case NX_MRP_EVENT_TXLA:
363         switch (attribute -> applicant.state)
364         {
365         case NX_MRP_APPLICANT_STATE_VO:
366         case NX_MRP_APPLICANT_STATE_LA:
367         case NX_MRP_APPLICANT_STATE_AO:
368         case NX_MRP_APPLICANT_STATE_QO:
369         case NX_MRP_APPLICANT_STATE_LO:
370             attribute -> applicant.action = NX_MRP_ACTION_S_OPT;
371             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_LO;
372             break;
373 
374         case NX_MRP_APPLICANT_STATE_VP:
375             attribute -> applicant.action = NX_MRP_ACTION_S;
376             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AA;
377             break;
378 
379         case NX_MRP_APPLICANT_STATE_VN:
380             attribute -> applicant.action = NX_MRP_ACTION_SN;
381             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_AN;
382             break;
383 
384         case NX_MRP_APPLICANT_STATE_AN:
385             attribute -> applicant.action = NX_MRP_ACTION_SN;
386             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
387             break;
388 
389         case NX_MRP_APPLICANT_STATE_AA:
390         case NX_MRP_APPLICANT_STATE_QA:
391         case NX_MRP_APPLICANT_STATE_AP:
392         case NX_MRP_APPLICANT_STATE_QP:
393             attribute -> applicant.action = NX_MRP_ACTION_SJ;
394             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_QA;
395             break;
396 
397         default:
398             /* do nothing */
399             break;
400         }
401         break;
402 
403     case NX_MRP_EVENT_TXLAF:
404         switch (attribute -> applicant.state)
405         {
406         case NX_MRP_APPLICANT_STATE_VO:
407         case NX_MRP_APPLICANT_STATE_LA:
408         case NX_MRP_APPLICANT_STATE_AO:
409         case NX_MRP_APPLICANT_STATE_QO:
410         case NX_MRP_APPLICANT_STATE_LO:
411             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_LO;
412             break;
413 
414         case NX_MRP_APPLICANT_STATE_VP:
415         case NX_MRP_APPLICANT_STATE_AA:
416         case NX_MRP_APPLICANT_STATE_QA:
417         case NX_MRP_APPLICANT_STATE_AP:
418         case NX_MRP_APPLICANT_STATE_QP:
419             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VP;
420             break;
421 
422         case NX_MRP_APPLICANT_STATE_VN:
423         case NX_MRP_APPLICANT_STATE_AN:
424             attribute -> applicant.state = NX_MRP_APPLICANT_STATE_VN;
425             break;
426 
427         default:
428             /* do nothing */
429             break;
430         }
431         break;
432 
433     default:
434         /* do nothing */
435         break;
436     }
437 
438     /* Transmitting the value is not necessary for correct protocol operation, transfer it to NX_NULL action */
439     if ((attribute -> applicant.action == NX_MRP_ACTION_SJ_OPT) ||
440         (attribute -> applicant.action == NX_MRP_ACTION_S_OPT))
441     {
442         attribute -> applicant.action = NX_MRP_ACTION_NULL;
443     }
444 
445 #ifdef NX_MRP_DEBUG_ENABLE
446     printf("APPLICANT: origin state: %4s, mrp_event: %8s, next state: %4s, action: %8s\n",
447            state_str[origin_state], event_str[mrp_event], state_str[attribute -> applicant.state], action_str[attribute -> applicant.action]);
448 #endif
449 
450     return(NX_SUCCESS);
451 }
452 
453 /**************************************************************************/
454 /*                                                                        */
455 /*  FUNCTION                                               RELEASE        */
456 /*                                                                        */
457 /*    nx_mrp_registrar_event_process                      PORTABLE C      */
458 /*                                                           6.4.0        */
459 /*  AUTHOR                                                                */
460 /*                                                                        */
461 /*    Yajun Xia, Microsoft Corporation                                    */
462 /*                                                                        */
463 /*  DESCRIPTION                                                           */
464 /*                                                                        */
465 /*    This function processes event for attribute of mrp registrar.       */
466 /*                                                                        */
467 /*  INPUT                                                                 */
468 /*                                                                        */
469 /*    mrp                                   Pointer to MRP instance       */
470 /*    participant                           Pointer to MRP participant    */
471 /*    attribute                             Pointer to MRP attribute      */
472 /*    event                                 Event to be processed         */
473 /*                                                                        */
474 /*  OUTPUT                                                                */
475 /*                                                                        */
476 /*    status                                Completion status             */
477 /*                                                                        */
478 /*  CALLS                                                                 */
479 /*                                                                        */
480 /*    None                                                                */
481 /*                                                                        */
482 /*  CALLED BY                                                             */
483 /*                                                                        */
484 /*    nx_mrp_attribute_new                  MRP attribute new             */
485 /*    nx_mrp_event_process                  MRP event process             */
486 /*    nx_mrp_join_timeout_process           MRP join timeout process      */
487 /*    nx_mrp_leave_timeout_process          MRP leave timeout process     */
488 /*                                                                        */
489 /*  RELEASE HISTORY                                                       */
490 /*                                                                        */
491 /*    DATE              NAME                      DESCRIPTION             */
492 /*                                                                        */
493 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
494 /*                                                                        */
495 /**************************************************************************/
nx_mrp_registrar_event_process(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant,NX_MRP_ATTRIBUTE * attribute,UCHAR mrp_event)496 UINT nx_mrp_registrar_event_process(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant, NX_MRP_ATTRIBUTE *attribute, UCHAR mrp_event)
497 {
498 #ifdef NX_MRP_DEBUG_ENABLE
499 UCHAR origin_state = attribute -> registrar.state;
500 #endif
501 
502     if (participant == NX_NULL || attribute == NX_NULL)
503     {
504         return(NX_INVALID_PARAMETERS);
505     }
506 
507     switch (mrp_event)
508     {
509     case NX_MRP_EVENT_BEGIN:
510         attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_MT;
511         break;
512 
513     case NX_MRP_EVENT_RNEW:
514         if (participant -> indication_function != NX_NULL)
515         {
516             participant -> indication_function(mrp, participant, attribute, NX_MRP_INDICATION_NEW);
517         }
518 
519         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
520         {
521             /* Stop leavetimer */
522             attribute -> leave_timer = 0;
523         }
524 
525         attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_IN;
526         break;
527 
528     case NX_MRP_EVENT_RJOININ:
529     case NX_MRP_EVENT_RJOINMT:
530         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
531         {
532             /* Stop leavetimer */
533             attribute -> leave_timer = 0;
534         }
535         else if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_MT)
536         {
537             if (participant -> indication_function != NX_NULL)
538             {
539                 participant -> indication_function(mrp, participant, attribute, NX_MRP_INDICATION_JOIN);
540             }
541         }
542         attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_IN;
543         break;
544 
545     case NX_MRP_EVENT_RLV:
546     case NX_MRP_EVENT_RLA:
547     case NX_MRP_EVENT_TXLA:
548     case NX_MRP_EVENT_REDECLARE:
549         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_IN)
550         {
551             /* Start leavetimer */
552             attribute -> leave_timer = NX_MRP_TIMER_LEAVE;
553             attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_LV;
554         }
555         break;
556 
557     case NX_MRP_EVENT_FLUSH:
558         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
559         {
560             if (participant -> indication_function != NX_NULL)
561             {
562                 participant -> indication_function(mrp, participant, attribute, NX_MRP_INDICATION_LV);
563             }
564         }
565         attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_MT;
566 
567         break;
568 
569     case NX_MRP_EVENT_LEAVETIMER:
570         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
571         {
572             if (participant -> indication_function != NX_NULL)
573             {
574                 participant -> indication_function(mrp, participant, attribute, NX_MRP_INDICATION_LV);
575             }
576 
577             attribute -> registrar.state = NX_MRP_REGISTRAR_STATE_MT;
578         }
579         break;
580 
581     default:
582         break;
583     }
584 
585 #ifdef NX_MRP_DEBUG_ENABLE
586     printf("REGISTRAR: origin state: %4s, mrp_event: %8s, next state: %4s\n",
587            state_str[origin_state], event_str[mrp_event], state_str[attribute -> registrar.state]);
588 #endif
589 
590     return(NX_SUCCESS);
591 }
592 
593 /**************************************************************************/
594 /*                                                                        */
595 /*  FUNCTION                                               RELEASE        */
596 /*                                                                        */
597 /*    nx_mrp_leaveall_event_process                       PORTABLE C      */
598 /*                                                           6.4.0        */
599 /*  AUTHOR                                                                */
600 /*                                                                        */
601 /*    Yajun Xia, Microsoft Corporation                                    */
602 /*                                                                        */
603 /*  DESCRIPTION                                                           */
604 /*                                                                        */
605 /*    This function processes leave all event for participant.            */
606 /*                                                                        */
607 /*  INPUT                                                                 */
608 /*                                                                        */
609 /*    participant                           Pointer to MRP participant    */
610 /*    mrp_event                             Event to be processed         */
611 /*                                                                        */
612 /*  OUTPUT                                                                */
613 /*                                                                        */
614 /*    status                                Completion status             */
615 /*                                                                        */
616 /*  CALLS                                                                 */
617 /*                                                                        */
618 /*    None                                                                */
619 /*                                                                        */
620 /*  CALLED BY                                                             */
621 /*                                                                        */
622 /*    nx_mrp_event_process                  MRP event process             */
623 /*    nx_mrp_join_timeout_process           MRP join timeout process      */
624 /*    nx_mrp_leaveall_timeout_process       MRP leave all timeout process */
625 /*                                                                        */
626 /*  RELEASE HISTORY                                                       */
627 /*                                                                        */
628 /*    DATE              NAME                      DESCRIPTION             */
629 /*                                                                        */
630 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
631 /*                                                                        */
632 /**************************************************************************/
nx_mrp_leaveall_event_process(NX_MRP_PARTICIPANT * participant,UCHAR mrp_event)633 UINT nx_mrp_leaveall_event_process(NX_MRP_PARTICIPANT *participant, UCHAR mrp_event)
634 {
635 #ifdef NX_MRP_DEBUG_ENABLE
636 UCHAR origin_state = participant -> leaveall.state;
637 #endif
638 
639     if (participant == NX_NULL)
640     {
641         return(NX_INVALID_PARAMETERS);
642     }
643 
644     participant -> leaveall.action = NX_MRP_ACTION_NULL;
645     switch (mrp_event)
646     {
647     case NX_MRP_EVENT_BEGIN:
648         /* start leave all timer */
649         participant -> leaveall_timer = NX_MRP_TIMER_LEAVEALL;
650         participant -> leaveall.state = NX_MRP_LA_STATE_PASSIVE;
651         break;
652 
653     case NX_MRP_EVENT_TX:
654         if (participant -> leaveall.state == NX_MRP_LA_STATE_ACTIVE)
655         {
656             participant -> leaveall.action = NX_MRP_ACTION_SLA; /* The next TX should be changed to TXLA */
657             participant -> leaveall.state = NX_MRP_LA_STATE_PASSIVE;
658         }
659         break;
660 
661     case NX_MRP_EVENT_RLA:
662 
663         /* start leave all timer */
664         participant -> leaveall_timer = NX_MRP_TIMER_LEAVEALL;
665         participant -> leaveall.state = NX_MRP_LA_STATE_PASSIVE;
666         break;
667 
668     case NX_MRP_EVENT_LEAVEALLTIMER:
669 
670         /* start leave all timer */
671         participant -> leaveall_timer = NX_MRP_TIMER_LEAVEALL;
672         participant -> leaveall.state = NX_MRP_LA_STATE_ACTIVE;
673         break;
674 
675     default:
676         break;
677     }
678 
679 #ifdef NX_MRP_DEBUG_ENABLE
680     printf("LA       : origin state: %4s, mrp_event: %8s, next state: %4s, action: %8s\n",
681            state_str[origin_state], event_str[mrp_event], state_str[participant -> leaveall.state], action_str[participant -> leaveall.action]);
682 #endif
683     return(NX_SUCCESS);
684 }
685 
686 /**************************************************************************/
687 /*                                                                        */
688 /*  FUNCTION                                               RELEASE        */
689 /*                                                                        */
690 /*    nx_mrp_participant_add                              PORTABLE C      */
691 /*                                                           6.4.0        */
692 /*  AUTHOR                                                                */
693 /*                                                                        */
694 /*    Yajun Xia, Microsoft Corporation                                    */
695 /*                                                                        */
696 /*  DESCRIPTION                                                           */
697 /*                                                                        */
698 /*    This function adds a participant to the MRP instance.               */
699 /*                                                                        */
700 /*  INPUT                                                                 */
701 /*                                                                        */
702 /*    mrp                                   Pointer to MRP instance       */
703 /*    participant                           Pointer to MRP participant    */
704 /*                                                                        */
705 /*  OUTPUT                                                                */
706 /*                                                                        */
707 /*    status                                Completion status             */
708 /*                                                                        */
709 /*  CALLS                                                                 */
710 /*                                                                        */
711 /*    None                                                                */
712 /*                                                                        */
713 /*  CALLED BY                                                             */
714 /*                                                                        */
715 /*    nx_srp_init                           SRP init                      */
716 /*                                                                        */
717 /*  RELEASE HISTORY                                                       */
718 /*                                                                        */
719 /*    DATE              NAME                      DESCRIPTION             */
720 /*                                                                        */
721 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
722 /*                                                                        */
723 /**************************************************************************/
nx_mrp_participant_add(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant)724 UINT nx_mrp_participant_add(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant)
725 {
726 NX_MRP_PARTICIPANT *tmp_participant = mrp -> list_head;
727 
728     if ((mrp == NX_NULL) || (participant == NX_NULL))
729     {
730         return(NX_INVALID_PARAMETERS);
731     }
732 
733     if (tmp_participant == NX_NULL)
734     {
735         mrp -> list_head = participant;
736     }
737     else
738     {
739         if (tmp_participant == participant)
740         {
741 
742             /* the participant is already linked, do nothing */
743             return(NX_SUCCESS);
744         }
745 
746         while (tmp_participant -> next != NX_NULL)
747         {
748             tmp_participant = tmp_participant -> next;
749             if (tmp_participant == participant)
750             {
751 
752                 /* the participant is already linked, do nothing */
753                 return(NX_SUCCESS);
754             }
755         }
756         tmp_participant -> next = participant;
757     }
758     return(NX_SUCCESS);
759 }
760 
761 /**************************************************************************/
762 /*                                                                        */
763 /*  FUNCTION                                               RELEASE        */
764 /*                                                                        */
765 /*    nx_mrp_attribute_new                                PORTABLE C      */
766 /*                                                           6.4.0        */
767 /*  AUTHOR                                                                */
768 /*                                                                        */
769 /*    Yajun Xia, Microsoft Corporation                                    */
770 /*                                                                        */
771 /*  DESCRIPTION                                                           */
772 /*                                                                        */
773 /*    This function news a attribute for the participant.                 */
774 /*                                                                        */
775 /*  INPUT                                                                 */
776 /*                                                                        */
777 /*    mrp                                   Pointer to MRP instance       */
778 /*    participant                           Pointer to MRP participant    */
779 /*    attribute_array                       Pointer to attribute array    */
780 /*    unit_size                             Size of an attribute          */
781 /*    unit_number                           Number of attribute           */
782 /*                                                                        */
783 /*  OUTPUT                                                                */
784 /*                                                                        */
785 /*    pointer to attribute                                                */
786 /*                                                                        */
787 /*  CALLS                                                                 */
788 /*                                                                        */
789 /*    nx_mrp_applicant_event_process        Applicant event process       */
790 /*    nx_mrp_registrar_event_process        Registrar event process       */
791 /*                                                                        */
792 /*  CALLED BY                                                             */
793 /*                                                                        */
794 /*    Internal function                                                   */
795 /*                                                                        */
796 /*  RELEASE HISTORY                                                       */
797 /*                                                                        */
798 /*    DATE              NAME                      DESCRIPTION             */
799 /*                                                                        */
800 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
801 /*                                                                        */
802 /**************************************************************************/
nx_mrp_attribute_new(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant,NX_MRP_ATTRIBUTE * attribute_array,UINT unit_size,UINT unit_number)803 NX_MRP_ATTRIBUTE *nx_mrp_attribute_new(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant,
804                                        NX_MRP_ATTRIBUTE *attribute_array, UINT unit_size,
805                                        UINT unit_number)
806 {
807 NX_MRP_ATTRIBUTE *tmp;
808 UCHAR            *buf;
809 UINT              i;
810 
811     if (mrp == NX_NULL ||
812         participant == NX_NULL ||
813         attribute_array == NX_NULL)
814     {
815         return(NX_NULL);
816     }
817 
818     buf = (UCHAR *)attribute_array;
819     for (i = 0; i < unit_number; i++)
820     {
821         tmp = (NX_MRP_ATTRIBUTE *)buf;
822         if (tmp -> in_use == NX_FALSE)
823         {
824             break;
825         }
826         buf += unit_size;
827     }
828 
829     if (i == unit_number)
830     {
831         return(NX_NULL);
832     }
833 
834     tmp -> in_use = NX_TRUE;
835     tmp -> pre = NX_NULL;
836     tmp -> next = NX_NULL;
837 
838     nx_mrp_applicant_event_process(mrp, participant, tmp, NX_MRP_EVENT_BEGIN);
839     nx_mrp_registrar_event_process(mrp, participant, tmp, NX_MRP_EVENT_BEGIN);
840 
841     return(tmp);
842 }
843 
844 /**************************************************************************/
845 /*                                                                        */
846 /*  FUNCTION                                               RELEASE        */
847 /*                                                                        */
848 /*    nx_mrp_attribute_evict                              PORTABLE C      */
849 /*                                                           6.4.0        */
850 /*  AUTHOR                                                                */
851 /*                                                                        */
852 /*    Yajun Xia, Microsoft Corporation                                    */
853 /*                                                                        */
854 /*  DESCRIPTION                                                           */
855 /*                                                                        */
856 /*    This function evicts a attribute for the participant.               */
857 /*                                                                        */
858 /*  INPUT                                                                 */
859 /*                                                                        */
860 /*    mrp                                   Pointer to MRP instance       */
861 /*    participant                           Pointer to MRP participant    */
862 /*    target                                Pointer to MRP attribute      */
863 /*                                                                        */
864 /*  OUTPUT                                                                */
865 /*                                                                        */
866 /*    status                                Completion status             */
867 /*                                                                        */
868 /*  CALLS                                                                 */
869 /*                                                                        */
870 /*    None                                                                */
871 /*                                                                        */
872 /*  CALLED BY                                                             */
873 /*                                                                        */
874 /*    Internal function                                                   */
875 /*                                                                        */
876 /*  RELEASE HISTORY                                                       */
877 /*                                                                        */
878 /*    DATE              NAME                      DESCRIPTION             */
879 /*                                                                        */
880 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
881 /*                                                                        */
882 /**************************************************************************/
nx_mrp_attribute_evict(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant,NX_MRP_ATTRIBUTE * target)883 UINT nx_mrp_attribute_evict(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant, NX_MRP_ATTRIBUTE *target)
884 {
885 NX_MRP_ATTRIBUTE *attribute = target;
886 
887     if ((attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_MT) &&
888         ((attribute -> applicant.state == NX_MRP_APPLICANT_STATE_VO) ||
889          (attribute -> applicant.state == NX_MRP_APPLICANT_STATE_AO) ||
890          (attribute -> applicant.state == NX_MRP_APPLICANT_STATE_QO)))
891     {
892         if (attribute -> pre == NX_NULL)
893         {
894             participant -> inused_head = attribute -> next;
895             attribute -> next -> pre = NX_NULL;
896         }
897         else
898         {
899             attribute -> pre -> next = attribute -> next;
900             attribute -> next -> pre = attribute -> pre;
901         }
902 
903         if (participant -> indication_function != NX_NULL)
904         {
905             participant -> indication_function(mrp, participant, attribute, NX_MRP_INDICATION_EVICT);
906         }
907 
908         /* Delete the attribute from list */
909         attribute -> in_use = NX_FALSE;
910     }
911 
912     return(NX_SUCCESS);
913 }
914 
915 /**************************************************************************/
916 /*                                                                        */
917 /*  FUNCTION                                               RELEASE        */
918 /*                                                                        */
919 /*    nx_mrp_timer_handle                                 PORTABLE C      */
920 /*                                                           6.4.0        */
921 /*  AUTHOR                                                                */
922 /*                                                                        */
923 /*    Yajun Xia, Microsoft Corporation                                    */
924 /*                                                                        */
925 /*  DESCRIPTION                                                           */
926 /*                                                                        */
927 /*    This function handles the timer interrupt.                          */
928 /*                                                                        */
929 /*  INPUT                                                                 */
930 /*                                                                        */
931 /*    mrp_instance                          Pointer to MRP instance       */
932 /*                                                                        */
933 /*  OUTPUT                                                                */
934 /*                                                                        */
935 /*    None                                                                */
936 /*                                                                        */
937 /*  CALLS                                                                 */
938 /*                                                                        */
939 /*    tx_event_flags_set                    Set event flags               */
940 /*                                                                        */
941 /*  CALLED BY                                                             */
942 /*                                                                        */
943 /*    nx_mrp_init                           Initialize MRP Module         */
944 /*                                                                        */
945 /*  RELEASE HISTORY                                                       */
946 /*                                                                        */
947 /*    DATE              NAME                      DESCRIPTION             */
948 /*                                                                        */
949 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
950 /*                                                                        */
951 /**************************************************************************/
nx_mrp_timer_handle(ULONG mrp_instance)952 void nx_mrp_timer_handle(ULONG mrp_instance)
953 {
954 NX_MRP *mrp = (NX_MRP *)mrp_instance;
955 
956     tx_event_flags_set(&(mrp -> mrp_events), NX_MRP_TIMER_EVENT, TX_OR);
957 }
958 
959 /**************************************************************************/
960 /*                                                                        */
961 /*  FUNCTION                                               RELEASE        */
962 /*                                                                        */
963 /*    nx_mrp_timer_handle                                 PORTABLE C      */
964 /*                                                           6.4.0        */
965 /*  AUTHOR                                                                */
966 /*                                                                        */
967 /*    Yajun Xia, Microsoft Corporation                                    */
968 /*                                                                        */
969 /*  DESCRIPTION                                                           */
970 /*                                                                        */
971 /*    This function is callback function for ethernet receive.            */
972 /*                                                                        */
973 /*  INPUT                                                                 */
974 /*                                                                        */
975 /*    ip_ptr                                Pointer to IP instance        */
976 /*    interface_index                       Index to the interface        */
977 /*    packet_ptr                            Pointer to received packet    */
978 /*    physical_address_msw                  Physical address MSW          */
979 /*    physical_address_lsw                  Physical address LSW          */
980 /*    packet_type                           Packet type                   */
981 /*    header_size                           Size of the header            */
982 /*    context                               Pointer to MRP instance       */
983 /*    time_ptr                              Pointer to time structure     */
984 /*                                                                        */
985 /*  OUTPUT                                                                */
986 /*                                                                        */
987 /*    status                                Completion status             */
988 /*                                                                        */
989 /*  CALLS                                                                 */
990 /*                                                                        */
991 /*    tx_event_flags_set                    Set event flags               */
992 /*    nx_packet_release                     Release packet                */
993 /*                                                                        */
994 /*  CALLED BY                                                             */
995 /*                                                                        */
996 /*    nx_mrp_init                           Initialize MRP Module         */
997 /*                                                                        */
998 /*  RELEASE HISTORY                                                       */
999 /*                                                                        */
1000 /*    DATE              NAME                      DESCRIPTION             */
1001 /*                                                                        */
1002 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1003 /*                                                                        */
1004 /**************************************************************************/
nx_mrp_ethernet_receive_notify(NX_IP * ip_ptr,UINT interface_index,NX_PACKET * packet_ptr,ULONG physical_address_msw,ULONG physical_address_lsw,UINT packet_type,UINT header_size,VOID * context,struct NX_LINK_TIME_STRUCT * time_ptr)1005 UINT nx_mrp_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
1006                                     ULONG physical_address_msw, ULONG physical_address_lsw,
1007                                     UINT packet_type, UINT header_size, VOID *context,
1008                                     struct NX_LINK_TIME_STRUCT *time_ptr)
1009 {
1010 TX_INTERRUPT_SAVE_AREA
1011 NX_MRP *mrp = (NX_MRP *)context;
1012 
1013     NX_PARAMETER_NOT_USED(ip_ptr);
1014     NX_PARAMETER_NOT_USED(interface_index);
1015     NX_PARAMETER_NOT_USED(physical_address_msw);
1016     NX_PARAMETER_NOT_USED(physical_address_lsw);
1017     NX_PARAMETER_NOT_USED(time_ptr);
1018     NX_PARAMETER_NOT_USED(header_size);
1019 
1020     if (packet_type == NX_LINK_ETHERNET_MVRP ||
1021         packet_type == NX_LINK_ETHERNET_MSRP ||
1022         packet_type == NX_LINK_ETHERNET_MMRP)
1023     {
1024 
1025         /* Disable interrupts.  */
1026         TX_DISABLE
1027 
1028         /* Check to see if the receive queue is empty.  */
1029         if (mrp -> received_packet_head)
1030         {
1031 
1032             /* Not empty, just place the packet at the end of the queue.  */
1033             (mrp -> received_packet_tail) -> nx_packet_queue_next = packet_ptr;
1034             packet_ptr -> nx_packet_queue_next = NX_NULL;
1035             mrp -> received_packet_tail = packet_ptr;
1036         }
1037         else
1038         {
1039 
1040             /* Empty receive processing queue.  */
1041             mrp -> received_packet_head = packet_ptr;
1042             mrp -> received_packet_tail = packet_ptr;
1043             packet_ptr -> nx_packet_queue_next = NX_NULL;
1044         }
1045 
1046         /* Restore interrupts.  */
1047         TX_RESTORE
1048         /* set packet rcv event */
1049         tx_event_flags_set(&(mrp -> mrp_events), NX_MRP_RX_EVENT, TX_OR);
1050     }
1051     else
1052     {
1053         nx_packet_release(packet_ptr);
1054     }
1055 
1056     return(NX_SUCCESS);
1057 }
1058 
1059 /**************************************************************************/
1060 /*                                                                        */
1061 /*  FUNCTION                                               RELEASE        */
1062 /*                                                                        */
1063 /*    nx_mrp_init                                         PORTABLE C      */
1064 /*                                                           6.4.0        */
1065 /*  AUTHOR                                                                */
1066 /*                                                                        */
1067 /*    Yajun Xia, Microsoft Corporation                                    */
1068 /*                                                                        */
1069 /*  DESCRIPTION                                                           */
1070 /*                                                                        */
1071 /*    This function initializes the MRP module.                           */
1072 /*                                                                        */
1073 /*  INPUT                                                                 */
1074 /*                                                                        */
1075 /*    mrp                                   Pointer to MRP instance       */
1076 /*    ip_ptr                                Pointer to IP instance        */
1077 /*    interface_index                       Index to the interface        */
1078 /*    pkt_pool_ptr                          Pointer to packet pool        */
1079 /*    thread_name                           Name of the thread            */
1080 /*    stack_ptr                             Pointer to stack              */
1081 /*    stack_size                            Size of the stack             */
1082 /*    priority                              Priority of the thread        */
1083 /*                                                                        */
1084 /*  OUTPUT                                                                */
1085 /*                                                                        */
1086 /*    status                                Completion status             */
1087 /*                                                                        */
1088 /*  CALLS                                                                 */
1089 /*                                                                        */
1090 /*    nx_link_packet_receive_callback_add   Add receive callback          */
1091 /*    tx_timer_create                       Create timer                  */
1092 /*    tx_thread_create                      Create thread                 */
1093 /*    tx_event_flags_create                 Create event flag             */
1094 /*                                                                        */
1095 /*  CALLED BY                                                             */
1096 /*                                                                        */
1097 /*    nx_srp_init                           Initialize SRP Module         */
1098 /*                                                                        */
1099 /*  RELEASE HISTORY                                                       */
1100 /*                                                                        */
1101 /*    DATE              NAME                      DESCRIPTION             */
1102 /*                                                                        */
1103 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1104 /*                                                                        */
1105 /**************************************************************************/
nx_mrp_init(NX_MRP * mrp,NX_IP * ip_ptr,UINT interface_index,NX_PACKET_POOL * pkt_pool_ptr,CHAR * thread_name,VOID * stack_ptr,ULONG stack_size,UINT priority)1106 UINT nx_mrp_init(NX_MRP *mrp, NX_IP *ip_ptr, UINT interface_index, NX_PACKET_POOL *pkt_pool_ptr,
1107                  CHAR *thread_name, VOID *stack_ptr, ULONG stack_size, UINT priority)
1108 {
1109 UINT status;
1110 
1111     mrp -> list_head = NX_NULL;
1112     mrp -> periodic_timer = NX_MRP_TIMER_PERIODIC;
1113     mrp -> oper_p2p_mac = NX_MRP_DEFAULT_OPER_P2P_MAC;
1114     mrp -> ip_ptr = ip_ptr;
1115     mrp -> interface_index = interface_index;
1116     mrp -> received_packet_head = NX_NULL;
1117     mrp -> received_packet_tail = NX_NULL;
1118     mrp -> pkt_pool = pkt_pool_ptr;
1119 
1120     /* Start mrp timer */
1121     status = tx_timer_create(&(mrp -> mrp_timer), "MRP Timer", nx_mrp_timer_handle,
1122                              (ULONG)mrp,
1123                              (TX_TIMER_TICKS_PER_SECOND / NX_MRP_TIMER_TICKS_PER_SECOND),
1124                              (TX_TIMER_TICKS_PER_SECOND / NX_MRP_TIMER_TICKS_PER_SECOND),
1125                              TX_AUTO_START);
1126     if (status != NX_SUCCESS)
1127     {
1128         return(status);
1129     }
1130 
1131 
1132     /* Create the mrp main thread.  */
1133     status = tx_thread_create(&mrp -> mrp_thread, thread_name, nx_mrp_thread_entry, (ULONG)mrp,
1134                               stack_ptr, stack_size,
1135                               priority, priority, TX_NO_TIME_SLICE, TX_AUTO_START);
1136     if (status != NX_SUCCESS)
1137     {
1138         return(status);
1139     }
1140 
1141     /* Add the link callback function */
1142     status = nx_link_packet_receive_callback_add(mrp -> ip_ptr, mrp -> interface_index, &mrp -> receive_queue,
1143                                                  NX_LINK_PACKET_TYPE_ALL, nx_mrp_ethernet_receive_notify, (VOID *)mrp);
1144     if (status != NX_SUCCESS)
1145     {
1146         return(status);
1147     }
1148 
1149     /* Create the mrp event flag instance.  */
1150     status = tx_event_flags_create(&(mrp -> mrp_events), "MRP Events Queue");
1151     /* Check for error. */
1152     if (status != TX_SUCCESS)
1153     {
1154         return(status);
1155     }
1156 
1157     /* Create the mrp mutex */
1158     status = tx_mutex_create(&(mrp -> mrp_mutex), "MRP Mutex", TX_NO_INHERIT);
1159     if (status != TX_SUCCESS)
1160     {
1161         return(status);
1162     }
1163 
1164     /* Join MSRP multicase group */
1165     status = nx_link_multicast_join(mrp -> ip_ptr, mrp -> interface_index,
1166                                     NX_MRP_MRP_ETH_MULTICAST_ADDR_MSB, NX_MRP_MSRP_ETH_MULTICAST_ADDR_LSB);
1167     if (status != TX_SUCCESS)
1168     {
1169         return(status);
1170     }
1171 
1172     /* Join MVRP multicase group */
1173     status = nx_link_multicast_join(mrp -> ip_ptr, mrp -> interface_index,
1174                                     NX_MRP_MRP_ETH_MULTICAST_ADDR_MSB, NX_MRP_MVRP_ETH_MULTICAST_ADDR_LSB);
1175     if (status != TX_SUCCESS)
1176     {
1177         return(status);
1178     }
1179 
1180     /* Join MMRP multicase group */
1181     status = nx_link_multicast_join(mrp -> ip_ptr, mrp -> interface_index,
1182                                     NX_MRP_MRP_ETH_MULTICAST_ADDR_MSB, NX_MRP_MVRP_ETH_MULTICAST_ADDR_LSB);
1183     return(status);
1184 }
1185 
1186 /**************************************************************************/
1187 /*                                                                        */
1188 /*  FUNCTION                                               RELEASE        */
1189 /*                                                                        */
1190 /*    nx_mrp_participant_search                           PORTABLE C      */
1191 /*                                                           6.4.0        */
1192 /*  AUTHOR                                                                */
1193 /*                                                                        */
1194 /*    Yajun Xia, Microsoft Corporation                                    */
1195 /*                                                                        */
1196 /*  DESCRIPTION                                                           */
1197 /*                                                                        */
1198 /*    This function searches a participant in the MRP instance.           */
1199 /*                                                                        */
1200 /*  INPUT                                                                 */
1201 /*                                                                        */
1202 /*    mrp                                   Pointer to MRP instance       */
1203 /*    participant_type                      Type of the participant       */
1204 /*                                                                        */
1205 /*  OUTPUT                                                                */
1206 /*                                                                        */
1207 /*    pointer to participant                                              */
1208 /*                                                                        */
1209 /*  CALLS                                                                 */
1210 /*                                                                        */
1211 /*    Pointer to participant                                              */
1212 /*                                                                        */
1213 /*  CALLED BY                                                             */
1214 /*                                                                        */
1215 /*    nx_mrp_rcv_pkt_process                Process received packet       */
1216 /*                                                                        */
1217 /*  RELEASE HISTORY                                                       */
1218 /*                                                                        */
1219 /*    DATE              NAME                      DESCRIPTION             */
1220 /*                                                                        */
1221 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1222 /*                                                                        */
1223 /**************************************************************************/
nx_mrp_participant_search(NX_MRP * mrp,UINT participant_type)1224 NX_MRP_PARTICIPANT *nx_mrp_participant_search(NX_MRP *mrp, UINT participant_type)
1225 {
1226 NX_MRP_PARTICIPANT *participant = NX_NULL;
1227 
1228     participant = mrp -> list_head;
1229 
1230     while (participant)
1231     {
1232         if (participant -> participant_type == participant_type)
1233         {
1234             return(participant);
1235         }
1236 
1237         participant = participant -> next;
1238     }
1239 
1240     return(NX_NULL);
1241 }
1242 
1243 /**************************************************************************/
1244 /*                                                                        */
1245 /*  FUNCTION                                               RELEASE        */
1246 /*                                                                        */
1247 /*    nx_mrp_rcv_pkt_process                              PORTABLE C      */
1248 /*                                                           6.4.0        */
1249 /*  AUTHOR                                                                */
1250 /*                                                                        */
1251 /*    Yajun Xia, Microsoft Corporation                                    */
1252 /*                                                                        */
1253 /*  DESCRIPTION                                                           */
1254 /*                                                                        */
1255 /*    This function handles the received packet.                          */
1256 /*                                                                        */
1257 /*  INPUT                                                                 */
1258 /*                                                                        */
1259 /*    mrp                                   Pointer to MRP instance       */
1260 /*    participant_type                      Type of the participant       */
1261 /*                                                                        */
1262 /*  OUTPUT                                                                */
1263 /*                                                                        */
1264 /*    None                                                                */
1265 /*                                                                        */
1266 /*  CALLS                                                                 */
1267 /*                                                                        */
1268 /*    nx_link_ethernet_header_parse         Parse ethernet header         */
1269 /*    nx_mrp_participant_search             Search participant            */
1270 /*                                                                        */
1271 /*  CALLED BY                                                             */
1272 /*                                                                        */
1273 /*    nx_mrp_thread_entry                   MRP thread entry              */
1274 /*                                                                        */
1275 /*  RELEASE HISTORY                                                       */
1276 /*                                                                        */
1277 /*    DATE              NAME                      DESCRIPTION             */
1278 /*                                                                        */
1279 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1280 /*                                                                        */
1281 /**************************************************************************/
nx_mrp_rcv_pkt_process(NX_MRP * mrp)1282 void nx_mrp_rcv_pkt_process(NX_MRP *mrp)
1283 {
1284 TX_INTERRUPT_SAVE_AREA
1285 USHORT              packet_type;
1286 UINT                header_size;
1287 USHORT              vlan_tag;
1288 UCHAR               vlan_tag_valid;
1289 ULONG               physical_address_msw;
1290 ULONG               physical_address_lsw;
1291 NX_PACKET          *packet_ptr = NX_NULL;
1292 NX_MRP_PARTICIPANT *participant;
1293 
1294     /* Loop to receive all packets. */
1295     while (mrp -> received_packet_head)
1296     {
1297 
1298         /* Remove the first packet and process it!  */
1299 
1300         /* Disable interrupts.  */
1301         TX_DISABLE
1302 
1303         /* Pickup the first packet.  */
1304         packet_ptr =  mrp -> received_packet_head;
1305 
1306         /* Move the head pointer to the next packet.  */
1307         mrp -> received_packet_head =  packet_ptr -> nx_packet_queue_next;
1308 
1309         if (mrp -> received_packet_head == NX_NULL)
1310         {
1311 
1312             /* Yes, the queue is empty.  Set the tail pointer to NX_NULL.  */
1313             mrp -> received_packet_tail =  NX_NULL;
1314         }
1315 
1316         /* Restore interrupts.  */
1317         TX_RESTORE
1318 
1319         /*The packet parsed twice(need to optimize) */
1320         nx_link_ethernet_header_parse(packet_ptr, &physical_address_msw, &physical_address_lsw,
1321                                       NX_NULL, NX_NULL, &packet_type, &vlan_tag, &vlan_tag_valid, &header_size);
1322 
1323         /* Clean off the Ethernet header.  */
1324         packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + header_size;
1325 
1326         /* Adjust the packet length.  */
1327         packet_ptr -> nx_packet_length =  packet_ptr -> nx_packet_length - header_size;
1328 
1329         if ((packet_type == NX_LINK_ETHERNET_MVRP) ||
1330             (packet_type == NX_LINK_ETHERNET_MSRP) ||
1331             (packet_type == NX_LINK_ETHERNET_MMRP))
1332         {
1333             participant = nx_mrp_participant_search(mrp, packet_type);
1334             if (participant && (participant -> unpack_function != NX_NULL))
1335             {
1336                 participant -> unpack_function(mrp, participant, packet_ptr);
1337             }
1338             nx_packet_release(packet_ptr);
1339         }
1340     }
1341 }
1342 
1343 /**************************************************************************/
1344 /*                                                                        */
1345 /*  FUNCTION                                               RELEASE        */
1346 /*                                                                        */
1347 /*    nx_mrp_event_process                                PORTABLE C      */
1348 /*                                                           6.4.0        */
1349 /*  AUTHOR                                                                */
1350 /*                                                                        */
1351 /*    Yajun Xia, Microsoft Corporation                                    */
1352 /*                                                                        */
1353 /*  DESCRIPTION                                                           */
1354 /*                                                                        */
1355 /*    This function processes event for attribute of mrp participant.     */
1356 /*                                                                        */
1357 /*  INPUT                                                                 */
1358 /*                                                                        */
1359 /*    mrp                                   Pointer to MRP instance       */
1360 /*    participant                           Pointer to MRP participant    */
1361 /*    attribute                             Pointer to MRP attribute      */
1362 /*    mrp_event                             Event to be processed         */
1363 /*                                                                        */
1364 /*  OUTPUT                                                                */
1365 /*                                                                        */
1366 /*    status                                Completion status             */
1367 /*                                                                        */
1368 /*  CALLS                                                                 */
1369 /*                                                                        */
1370 /*    nx_mrp_applicant_event_process        Applicant event process       */
1371 /*                                                                        */
1372 /*  CALLED BY                                                             */
1373 /*                                                                        */
1374 /*    Internal function                                                   */
1375 /*                                                                        */
1376 /*  RELEASE HISTORY                                                       */
1377 /*                                                                        */
1378 /*    DATE              NAME                      DESCRIPTION             */
1379 /*                                                                        */
1380 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1381 /*                                                                        */
1382 /**************************************************************************/
nx_mrp_event_process(NX_MRP * mrp,NX_MRP_PARTICIPANT * participant,NX_MRP_ATTRIBUTE * attribute,UCHAR mrp_event)1383 UINT nx_mrp_event_process(NX_MRP *mrp, NX_MRP_PARTICIPANT *participant, NX_MRP_ATTRIBUTE *attribute, UCHAR mrp_event)
1384 {
1385 UINT status;
1386 
1387     switch (mrp_event)
1388     {
1389     case NX_MRP_EVENT_NEW:
1390     case NX_MRP_EVENT_JOIN:
1391     case NX_MRP_EVENT_LV:
1392 
1393     /* Receive msg types just need to process for applicant */
1394     case NX_MRP_EVENT_RIN:
1395     case NX_MRP_EVENT_RMT:
1396         status = nx_mrp_applicant_event_process(mrp, participant, attribute, mrp_event);
1397         break;
1398 
1399     case NX_MRP_EVENT_RNEW:
1400     case NX_MRP_EVENT_RJOININ:
1401     case NX_MRP_EVENT_RJOINMT:
1402     case NX_MRP_EVENT_RLV:
1403     case NX_MRP_EVENT_REDECLARE:
1404         status = nx_mrp_applicant_event_process(mrp, participant, attribute, mrp_event);
1405         status = nx_mrp_registrar_event_process(mrp, participant, attribute, mrp_event);
1406         break;
1407 
1408     case NX_MRP_EVENT_RLA:
1409         status = nx_mrp_applicant_event_process(mrp, participant, attribute, mrp_event);
1410         status = nx_mrp_registrar_event_process(mrp, participant, attribute, mrp_event);
1411         status = nx_mrp_leaveall_event_process(participant, mrp_event);
1412         break;
1413 
1414     default:
1415         status = NX_INVALID_PARAMETERS;
1416         break;
1417     }
1418 
1419     return(status);
1420 }
1421 
1422 /**************************************************************************/
1423 /*                                                                        */
1424 /*  FUNCTION                                               RELEASE        */
1425 /*                                                                        */
1426 /*    nx_mrp_attribute_event_get                          PORTABLE C      */
1427 /*                                                           6.4.0        */
1428 /*  AUTHOR                                                                */
1429 /*                                                                        */
1430 /*    Yajun Xia, Microsoft Corporation                                    */
1431 /*                                                                        */
1432 /*  DESCRIPTION                                                           */
1433 /*                                                                        */
1434 /*    This function gets event for attribute.                             */
1435 /*                                                                        */
1436 /*  INPUT                                                                 */
1437 /*                                                                        */
1438 /*    attribute                             Pointer to MRP attribute      */
1439 /*    event_ptr                             Pointer to event              */
1440 /*                                                                        */
1441 /*  OUTPUT                                                                */
1442 /*                                                                        */
1443 /*    status                                Completion status             */
1444 /*                                                                        */
1445 /*  CALLS                                                                 */
1446 /*                                                                        */
1447 /*    None                                                                */
1448 /*                                                                        */
1449 /*  CALLED BY                                                             */
1450 /*                                                                        */
1451 /*    Internal function                                                   */
1452 /*                                                                        */
1453 /*  RELEASE HISTORY                                                       */
1454 /*                                                                        */
1455 /*    DATE              NAME                      DESCRIPTION             */
1456 /*                                                                        */
1457 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1458 /*                                                                        */
1459 /**************************************************************************/
nx_mrp_attribute_event_get(NX_MRP_ATTRIBUTE * attribute,UCHAR * event_ptr)1460 UINT nx_mrp_attribute_event_get(NX_MRP_ATTRIBUTE *attribute, UCHAR *event_ptr)
1461 {
1462 
1463     switch (attribute -> applicant.action)
1464     {
1465     case NX_MRP_ACTION_SN:
1466         *event_ptr = NX_MRP_ATTRIBUTE_EVENT_NEW;
1467         break;
1468 
1469     case NX_MRP_ACTION_SJ:
1470         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_IN)
1471         {
1472             *event_ptr = NX_MRP_ATTRIBUTE_EVENT_JOININ;
1473         }
1474         else if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_MT  ||
1475                  attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
1476         {
1477             *event_ptr = NX_MRP_ATTRIBUTE_EVENT_JOINMT;
1478         }
1479         else
1480         {
1481             return(NX_INVALID_PARAMETERS);
1482         }
1483 
1484         break;
1485 
1486     case NX_MRP_ACTION_SL:
1487         *event_ptr = NX_MRP_ATTRIBUTE_EVENT_LV;
1488         break;
1489 
1490     case NX_MRP_ACTION_S:
1491         if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_IN)
1492         {
1493             *event_ptr = NX_MRP_ATTRIBUTE_EVENT_IN;
1494         }
1495         else if (attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_MT  ||
1496                  attribute -> registrar.state == NX_MRP_REGISTRAR_STATE_LV)
1497         {
1498             *event_ptr = NX_MRP_ATTRIBUTE_EVENT_MT;
1499         }
1500         else
1501         {
1502             return(NX_INVALID_PARAMETERS);
1503         }
1504 
1505         break;
1506 
1507     default:
1508         return(NX_INVALID_PARAMETERS);
1509     }
1510 
1511     return(NX_SUCCESS);
1512 }
1513 
1514 /**************************************************************************/
1515 /*                                                                        */
1516 /*  FUNCTION                                               RELEASE        */
1517 /*                                                                        */
1518 /*    nx_mrp_periodic_timeout_process                     PORTABLE C      */
1519 /*                                                           6.4.0        */
1520 /*  AUTHOR                                                                */
1521 /*                                                                        */
1522 /*    Yajun Xia, Microsoft Corporation                                    */
1523 /*                                                                        */
1524 /*  DESCRIPTION                                                           */
1525 /*                                                                        */
1526 /*    This function handles the periodic timeout.                         */
1527 /*                                                                        */
1528 /*  INPUT                                                                 */
1529 /*                                                                        */
1530 /*    mrp                                   Pointer to MRP instance       */
1531 /*                                                                        */
1532 /*  OUTPUT                                                                */
1533 /*                                                                        */
1534 /*    None                                                                */
1535 /*                                                                        */
1536 /*  CALLS                                                                 */
1537 /*                                                                        */
1538 /*    nx_mrp_applicant_event_process        Applicant event process       */
1539 /*                                                                        */
1540 /*  CALLED BY                                                             */
1541 /*                                                                        */
1542 /*    nx_mrp_timeout_process                MRP timeout process           */
1543 /*                                                                        */
1544 /*  RELEASE HISTORY                                                       */
1545 /*                                                                        */
1546 /*    DATE              NAME                      DESCRIPTION             */
1547 /*                                                                        */
1548 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1549 /*                                                                        */
1550 /**************************************************************************/
nx_mrp_periodic_timeout_process(NX_MRP * mrp)1551 void nx_mrp_periodic_timeout_process(NX_MRP *mrp)
1552 {
1553 NX_MRP_PARTICIPANT *participant;
1554 NX_MRP_ATTRIBUTE   *attribute;
1555 
1556     if (mrp -> periodic_timer > NX_MRP_TIMEOUT_INTERVAL)
1557     {
1558         mrp -> periodic_timer -= NX_MRP_TIMEOUT_INTERVAL;
1559     }
1560     else if (mrp -> periodic_timer == NX_MRP_TIMEOUT_INTERVAL)
1561     {
1562         /* Periodic timeout, restart */
1563         mrp -> periodic_timer = NX_MRP_TIMER_PERIODIC;
1564 
1565         participant = mrp -> list_head;
1566         while (participant != NX_NULL)
1567         {
1568             attribute = participant -> inused_head;
1569             while (attribute != NX_NULL)
1570             {
1571                 nx_mrp_applicant_event_process(mrp, participant, attribute, NX_MRP_EVENT_PERIODIC);
1572                 attribute = attribute -> next;
1573             }
1574 
1575             participant = participant -> next;
1576         }
1577     }
1578 }
1579 
1580 /**************************************************************************/
1581 /*                                                                        */
1582 /*  FUNCTION                                               RELEASE        */
1583 /*                                                                        */
1584 /*    nx_mrp_join_timeout_process                         PORTABLE C      */
1585 /*                                                           6.4.0        */
1586 /*  AUTHOR                                                                */
1587 /*                                                                        */
1588 /*    Yajun Xia, Microsoft Corporation                                    */
1589 /*                                                                        */
1590 /*  DESCRIPTION                                                           */
1591 /*                                                                        */
1592 /*    This function handles the join timeout.                             */
1593 /*                                                                        */
1594 /*  INPUT                                                                 */
1595 /*                                                                        */
1596 /*    mrp                                   Pointer to MRP instance       */
1597 /*                                                                        */
1598 /*  OUTPUT                                                                */
1599 /*                                                                        */
1600 /*    None                                                                */
1601 /*                                                                        */
1602 /*  CALLS                                                                 */
1603 /*                                                                        */
1604 /*    nx_mrp_leaveall_event_process         Leaveall event process        */
1605 /*    nx_mrp_applicant_event_process        Applicant event process       */
1606 /*    nx_mrp_registrar_event_process        Registrar event process       */
1607 /*    nx_packet_allocate                    Allocate a packet             */
1608 /*    nx_packet_release                     Release a packet              */
1609 /*    nx_link_ethernet_packet_send          Send a packet                 */
1610 /*                                                                        */
1611 /*  CALLED BY                                                             */
1612 /*                                                                        */
1613 /*    nx_mrp_timeout_process                MRP timeout process           */
1614 /*                                                                        */
1615 /*  RELEASE HISTORY                                                       */
1616 /*                                                                        */
1617 /*    DATE              NAME                      DESCRIPTION             */
1618 /*                                                                        */
1619 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1620 /*                                                                        */
1621 /**************************************************************************/
nx_mrp_join_timeout_process(NX_MRP * mrp)1622 void nx_mrp_join_timeout_process(NX_MRP *mrp)
1623 {
1624 NX_MRP_PARTICIPANT *participant;
1625 NX_MRP_ATTRIBUTE   *attribute;
1626 UCHAR               mrp_event;
1627 NX_PACKET          *packet_ptr;
1628 UINT                status;
1629 ULONG               mul_msb;
1630 ULONG               mul_lsb;
1631 UINT                eth_type;
1632 
1633     participant = mrp -> list_head;
1634     while (participant != NX_NULL)
1635     {
1636         if (participant -> join_timer > NX_MRP_TIMEOUT_INTERVAL)
1637         {
1638             participant -> join_timer -= NX_MRP_TIMEOUT_INTERVAL;
1639         }
1640         else if (participant -> join_timer == NX_MRP_TIMEOUT_INTERVAL)
1641         {
1642             /* Join timeout, restart */
1643             participant -> join_timer = NX_MRP_TIMER_JOIN;
1644 
1645             /* Tx! process for participant */
1646             mrp_event = NX_MRP_EVENT_TX;
1647             nx_mrp_leaveall_event_process(participant, mrp_event);
1648 
1649             /* If the LeaveAll state machine has signaled LeaveAll, then tx! is modified to txLA! */
1650             if (participant -> leaveall.action == NX_MRP_ACTION_SLA)
1651             {
1652                 mrp_event = NX_MRP_EVENT_TXLA;
1653             }
1654 
1655             attribute = participant -> inused_head;
1656 
1657             if (attribute == NX_NULL)
1658             {
1659                 participant = participant -> next;
1660                 continue;
1661             }
1662 
1663             while (attribute != NX_NULL)
1664             {
1665                 nx_mrp_applicant_event_process(mrp, participant, attribute, mrp_event);
1666 
1667                 if (mrp_event == NX_MRP_EVENT_TXLA)
1668                 {
1669                     nx_mrp_registrar_event_process(mrp, participant, attribute, mrp_event);
1670                 }
1671 
1672                 attribute = attribute -> next;
1673             }
1674 
1675             if (participant -> pack_function)
1676             {
1677                 /* Allocate a packet.  */
1678                 status =  nx_packet_allocate(mrp -> pkt_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_WAIT_FOREVER);
1679                 if (status != NX_SUCCESS)
1680                 {
1681                     return;
1682                 }
1683 
1684                 status = participant -> pack_function(mrp, participant, packet_ptr);
1685 
1686                 if (status != NX_SUCCESS)
1687                 {
1688                     nx_packet_release(packet_ptr);
1689                 }
1690                 else
1691                 {
1692                     switch (participant -> participant_type)
1693                     {
1694                     case NX_MRP_PARTICIPANT_MSRP:
1695                         mul_lsb = NX_MRP_MSRP_ETH_MULTICAST_ADDR_LSB;
1696                         eth_type = NX_LINK_ETHERNET_MSRP;
1697                         break;
1698                     case NX_MRP_PARTICIPANT_MMRP:
1699                         mul_lsb = NX_MRP_MMRP_ETH_MULTICAST_ADDR_LSB;
1700                         eth_type = NX_LINK_ETHERNET_MMRP;
1701                         break;
1702                     case NX_MRP_PARTICIPANT_MVRP:
1703                         mul_lsb = NX_MRP_MVRP_ETH_MULTICAST_ADDR_LSB;
1704                         eth_type = NX_LINK_ETHERNET_MVRP;
1705                         break;
1706                     default:
1707                         /* do nothing */
1708                         break;
1709                     }
1710                     mul_msb = NX_MRP_MRP_ETH_MULTICAST_ADDR_MSB;
1711                     if (packet_ptr -> nx_packet_length == 0)
1712                     {
1713                         nx_packet_release(packet_ptr);
1714                         return;
1715                     }
1716 
1717                     /* Send out one packet */
1718                     status = nx_link_ethernet_packet_send(mrp -> ip_ptr,
1719                                                           mrp -> interface_index, packet_ptr,
1720                                                           mul_msb,
1721                                                           mul_lsb,
1722                                                           eth_type);
1723 
1724                     if (status)
1725                     {
1726 
1727                         /* release packet in case of error */
1728                         nx_packet_release(packet_ptr);
1729                     }
1730                 }
1731             }
1732         }
1733         participant = participant -> next;
1734     }
1735 }
1736 
1737 /**************************************************************************/
1738 /*                                                                        */
1739 /*  FUNCTION                                               RELEASE        */
1740 /*                                                                        */
1741 /*    nx_mrp_join_timeout_process                         PORTABLE C      */
1742 /*                                                           6.4.0        */
1743 /*  AUTHOR                                                                */
1744 /*                                                                        */
1745 /*    Yajun Xia, Microsoft Corporation                                    */
1746 /*                                                                        */
1747 /*  DESCRIPTION                                                           */
1748 /*                                                                        */
1749 /*    This function handles the leaveall timeout.                         */
1750 /*                                                                        */
1751 /*  INPUT                                                                 */
1752 /*                                                                        */
1753 /*    mrp                                   Pointer to MRP instance       */
1754 /*                                                                        */
1755 /*  OUTPUT                                                                */
1756 /*                                                                        */
1757 /*    None                                                                */
1758 /*                                                                        */
1759 /*  CALLS                                                                 */
1760 /*                                                                        */
1761 /*    nx_mrp_leaveall_event_process         Leaveall event process        */
1762 /*                                                                        */
1763 /*  CALLED BY                                                             */
1764 /*                                                                        */
1765 /*    nx_mrp_timeout_process                MRP timeout process           */
1766 /*                                                                        */
1767 /*  RELEASE HISTORY                                                       */
1768 /*                                                                        */
1769 /*    DATE              NAME                      DESCRIPTION             */
1770 /*                                                                        */
1771 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1772 /*                                                                        */
1773 /**************************************************************************/
nx_mrp_leaveall_timeout_process(NX_MRP * mrp)1774 void nx_mrp_leaveall_timeout_process(NX_MRP *mrp)
1775 {
1776 NX_MRP_PARTICIPANT *participant;
1777 
1778     participant = mrp -> list_head;
1779     while (participant != NX_NULL)
1780     {
1781         if (participant -> leaveall_timer > NX_MRP_TIMEOUT_INTERVAL)
1782         {
1783             participant -> leaveall_timer -= NX_MRP_TIMEOUT_INTERVAL;
1784         }
1785         else if (participant -> leaveall_timer == NX_MRP_TIMEOUT_INTERVAL)
1786         {
1787 
1788             /* Generate leave all timeout event */
1789             nx_mrp_leaveall_event_process(participant, NX_MRP_EVENT_LEAVEALLTIMER);
1790         }
1791 
1792         participant = participant -> next;
1793     }
1794 }
1795 
1796 /**************************************************************************/
1797 /*                                                                        */
1798 /*  FUNCTION                                               RELEASE        */
1799 /*                                                                        */
1800 /*    nx_mrp_join_timeout_process                         PORTABLE C      */
1801 /*                                                           6.4.0        */
1802 /*  AUTHOR                                                                */
1803 /*                                                                        */
1804 /*    Yajun Xia, Microsoft Corporation                                    */
1805 /*                                                                        */
1806 /*  DESCRIPTION                                                           */
1807 /*                                                                        */
1808 /*    This function handles the leave timeout.                            */
1809 /*                                                                        */
1810 /*  INPUT                                                                 */
1811 /*                                                                        */
1812 /*    mrp                                   Pointer to MRP instance       */
1813 /*                                                                        */
1814 /*  OUTPUT                                                                */
1815 /*                                                                        */
1816 /*    None                                                                */
1817 /*                                                                        */
1818 /*  CALLS                                                                 */
1819 /*                                                                        */
1820 /*    nx_mrp_registrar_event_process        Registrar event process       */
1821 /*    nx_mrp_attribute_evict                Evict attribute               */
1822 /*                                                                        */
1823 /*  CALLED BY                                                             */
1824 /*                                                                        */
1825 /*    nx_mrp_timeout_process                MRP timeout process           */
1826 /*                                                                        */
1827 /*  RELEASE HISTORY                                                       */
1828 /*                                                                        */
1829 /*    DATE              NAME                      DESCRIPTION             */
1830 /*                                                                        */
1831 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1832 /*                                                                        */
1833 /**************************************************************************/
nx_mrp_leave_timeout_process(NX_MRP * mrp)1834 void nx_mrp_leave_timeout_process(NX_MRP *mrp)
1835 {
1836 NX_MRP_PARTICIPANT *participant;
1837 NX_MRP_ATTRIBUTE   *attribute;
1838 
1839     participant = mrp -> list_head;
1840     while (participant != NX_NULL)
1841     {
1842         attribute = participant -> inused_head;
1843         while (attribute != NX_NULL)
1844         {
1845             if (attribute -> leave_timer > NX_MRP_TIMEOUT_INTERVAL)
1846             {
1847                 attribute -> leave_timer -= NX_MRP_TIMEOUT_INTERVAL;
1848             }
1849             else if (attribute -> leave_timer == NX_MRP_TIMEOUT_INTERVAL)
1850             {
1851                 nx_mrp_registrar_event_process(mrp, participant, attribute, NX_MRP_EVENT_LEAVETIMER);
1852 
1853                 nx_mrp_attribute_evict(mrp, participant, attribute);
1854             }
1855             attribute = attribute -> next;
1856         }
1857         participant = participant -> next;
1858     }
1859 }
1860 
1861 /**************************************************************************/
1862 /*                                                                        */
1863 /*  FUNCTION                                               RELEASE        */
1864 /*                                                                        */
1865 /*    nx_mrp_join_timeout_process                         PORTABLE C      */
1866 /*                                                           6.4.0        */
1867 /*  AUTHOR                                                                */
1868 /*                                                                        */
1869 /*    Yajun Xia, Microsoft Corporation                                    */
1870 /*                                                                        */
1871 /*  DESCRIPTION                                                           */
1872 /*                                                                        */
1873 /*    This function handles the timeout of MRP.                           */
1874 /*                                                                        */
1875 /*  INPUT                                                                 */
1876 /*                                                                        */
1877 /*    mrp                                   Pointer to MRP instance       */
1878 /*                                                                        */
1879 /*  OUTPUT                                                                */
1880 /*                                                                        */
1881 /*    None                                                                */
1882 /*                                                                        */
1883 /*  CALLS                                                                 */
1884 /*                                                                        */
1885 /*    nx_mrp_periodic_timeout_process      Process periodic timeout       */
1886 /*    nx_mrp_leaveall_timeout_process      Process leaveall timeout       */
1887 /*    nx_mrp_join_timeout_process          Process join timeout           */
1888 /*    nx_mrp_leave_timeout_process         Process leave timeout          */
1889 /*                                                                        */
1890 /*  CALLED BY                                                             */
1891 /*                                                                        */
1892 /*    nx_mrp_thread_entry                   MRP thread entry              */
1893 /*                                                                        */
1894 /*  RELEASE HISTORY                                                       */
1895 /*                                                                        */
1896 /*    DATE              NAME                      DESCRIPTION             */
1897 /*                                                                        */
1898 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1899 /*                                                                        */
1900 /**************************************************************************/
nx_mrp_timeout_process(NX_MRP * mrp)1901 void nx_mrp_timeout_process(NX_MRP *mrp)
1902 {
1903     /* Periodic timer process (based on each port) */
1904     nx_mrp_periodic_timeout_process(mrp);
1905 
1906     /* Leave all timer process (based on participant) */
1907     nx_mrp_leaveall_timeout_process(mrp);
1908 
1909     /* Join timer process (based on participant) */
1910     nx_mrp_join_timeout_process(mrp);
1911 
1912     /* Leave timer process (based on each participant) */
1913     nx_mrp_leave_timeout_process(mrp);
1914 }
1915 
1916 /**************************************************************************/
1917 /*                                                                        */
1918 /*  FUNCTION                                               RELEASE        */
1919 /*                                                                        */
1920 /*    nx_mrp_thread_entry                                 PORTABLE C      */
1921 /*                                                           6.4.0        */
1922 /*  AUTHOR                                                                */
1923 /*                                                                        */
1924 /*    Yajun Xia, Microsoft Corporation                                    */
1925 /*                                                                        */
1926 /*  DESCRIPTION                                                           */
1927 /*                                                                        */
1928 /*    This function is the entry of MRP thread.                           */
1929 /*                                                                        */
1930 /*  INPUT                                                                 */
1931 /*                                                                        */
1932 /*    mrp_instance                          Pointer to MRP instance       */
1933 /*                                                                        */
1934 /*  OUTPUT                                                                */
1935 /*                                                                        */
1936 /*    None                                                                */
1937 /*                                                                        */
1938 /*  CALLS                                                                 */
1939 /*                                                                        */
1940 /*    nx_mrp_timeout_process               Process timeout                */
1941 /*    nx_mrp_rcv_pkt_process               Process received packet        */
1942 /*                                                                        */
1943 /*  CALLED BY                                                             */
1944 /*                                                                        */
1945 /*    Internal function                                                   */
1946 /*                                                                        */
1947 /*  RELEASE HISTORY                                                       */
1948 /*                                                                        */
1949 /*    DATE              NAME                      DESCRIPTION             */
1950 /*                                                                        */
1951 /*  12-31-2023     Yajun Xia                Initial Version 6.4.0         */
1952 /*                                                                        */
1953 /**************************************************************************/
nx_mrp_thread_entry(ULONG mrp_instance)1954 void nx_mrp_thread_entry(ULONG mrp_instance)
1955 {
1956 NX_MRP *mrp = (NX_MRP *)mrp_instance;
1957 ULONG   actual_flags;
1958 
1959     while (1)
1960     {
1961         /* Wait for event.  */
1962         tx_event_flags_get(&mrp -> mrp_events, NX_MRP_ALL_EVENTS, TX_OR_CLEAR,
1963                            &actual_flags, TX_WAIT_FOREVER);
1964         /* Get mutex. */
1965         tx_mutex_get(&mrp -> mrp_mutex, NX_WAIT_FOREVER);
1966 
1967         if (actual_flags & NX_MRP_TIMER_EVENT)
1968         {
1969             nx_mrp_timeout_process(mrp);
1970         }
1971 
1972         if (actual_flags & NX_MRP_RX_EVENT)
1973         {
1974             nx_mrp_rcv_pkt_process(mrp);
1975         }
1976 
1977         /* Release the mutex.  */
1978         tx_mutex_put(&(mrp -> mrp_mutex));
1979     }
1980 }
1981 #endif /* NX_ENABLE_VLAN */
1982 
1983