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