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 /** TSN shaper */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 /* Include necessary system files. */
22 #include "nx_shaper.h"
23 #include "nx_link.h"
24
25 #ifdef NX_ENABLE_VLAN
26 /**************************************************************************/
27 /* */
28 /* FUNCTION RELEASE */
29 /* */
30 /* nx_shaper_create PORTABLE C */
31 /* 6.4.0 */
32 /* AUTHOR */
33 /* */
34 /* Yajun Xia, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function creates shaper in shaper container, and connects the */
39 /* shaper container with interface instance. */
40 /* */
41 /* INPUT */
42 /* */
43 /* interface_ptr Pointer to interface instance */
44 /* shaper_container Pinter to Shaper container */
45 /* shaper Pinter to Shaper */
46 /* shaper_type Shaper type */
47 /* shaper_driver Driver entry of shaper */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* status Completion status */
52 /* */
53 /* CALLS */
54 /* */
55 /* None */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* Application Code */
60 /* */
61 /* RELEASE HISTORY */
62 /* */
63 /* DATE NAME DESCRIPTION */
64 /* */
65 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
66 /* */
67 /**************************************************************************/
nx_shaper_create(NX_INTERFACE * interface_ptr,NX_SHAPER_CONTAINER * shaper_container,NX_SHAPER * shaper,UCHAR shaper_type,NX_SHAPER_DRIVER shaper_driver)68 UINT nx_shaper_create(NX_INTERFACE *interface_ptr,
69 NX_SHAPER_CONTAINER *shaper_container,
70 NX_SHAPER *shaper,
71 UCHAR shaper_type,
72 NX_SHAPER_DRIVER shaper_driver)
73 {
74 UINT i;
75 UINT status;
76 NX_SHAPER_DRIVER_PARAMETER driver_request;
77
78 if ((interface_ptr == NX_NULL) ||
79 (shaper_container == NX_NULL) ||
80 (shaper == NX_NULL) ||
81 (shaper_type >= NX_SHAPER_TYPE_MAX) ||
82 (shaper_driver == NX_NULL))
83 {
84 return(NX_INVALID_PARAMETERS);
85 }
86
87 if (shaper_container -> shaper_number >= NX_SHAPER_NUMBERS)
88 {
89 return(NX_NO_MORE_ENTRIES);
90 }
91
92 for (i = 0; i < NX_SHAPER_NUMBERS; i++)
93 {
94 if (shaper_container -> shaper[i] == NX_NULL)
95 {
96 shaper_container -> shaper[i] = shaper;
97 shaper_container -> shaper[i] -> shaper_type = shaper_type;
98 shaper_container -> shaper[i] -> shaper_driver = shaper_driver;
99
100 break;
101 }
102 shaper_container -> shaper_number++;
103 }
104
105 if (i >= NX_SHAPER_NUMBERS)
106 {
107 return(NX_NO_MORE_ENTRIES);
108 }
109
110 /* Bind the shaper_container with interface. */
111 if (interface_ptr -> shaper_container == NX_NULL)
112 {
113 interface_ptr -> shaper_container = shaper_container;
114 }
115
116 /* Init process */
117 driver_request.nx_shaper_driver_command = NX_SHAPER_COMMAND_INIT;
118 driver_request.shaper_type = interface_ptr -> shaper_container -> shaper[i] -> shaper_type;
119 driver_request.nx_ip_driver_interface = interface_ptr;
120 driver_request.shaper_parameter = NX_NULL;
121
122 status = interface_ptr -> shaper_container -> shaper[i] -> shaper_driver(&driver_request);
123 if (status != NX_SUCCESS)
124 {
125 return(status);
126 }
127
128 /* Config process */
129 driver_request.nx_shaper_driver_command = NX_SHAPER_COMMAND_CONFIG;
130 driver_request.shaper_type = 0; /* not used in driver */
131 driver_request.nx_ip_driver_interface = interface_ptr;
132 driver_request.shaper_parameter = NX_NULL;
133
134 status = interface_ptr -> shaper_container -> shaper[i] -> shaper_driver(&driver_request);
135
136 return(status);
137 }
138
139 /**************************************************************************/
140 /* */
141 /* FUNCTION RELEASE */
142 /* */
143 /* nx_shaper_delete PORTABLE C */
144 /* 6.4.0 */
145 /* AUTHOR */
146 /* */
147 /* Yajun Xia, Microsoft Corporation */
148 /* */
149 /* DESCRIPTION */
150 /* */
151 /* This function deletes a shaper from interface instance, unlink the */
152 /* shaper container with IP interface when there is no shaper exists. */
153 /* */
154 /* INPUT */
155 /* */
156 /* interface_ptr Pointer to interface instance */
157 /* shaper Pinter to Shaper */
158 /* */
159 /* OUTPUT */
160 /* */
161 /* status Completion status */
162 /* */
163 /* CALLS */
164 /* */
165 /* None */
166 /* */
167 /* CALLED BY */
168 /* */
169 /* Application Code */
170 /* */
171 /* RELEASE HISTORY */
172 /* */
173 /* DATE NAME DESCRIPTION */
174 /* */
175 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
176 /* */
177 /**************************************************************************/
nx_shaper_delete(NX_INTERFACE * interface_ptr,NX_SHAPER * shaper)178 UINT nx_shaper_delete(NX_INTERFACE *interface_ptr, NX_SHAPER *shaper)
179 {
180 UINT i;
181
182 if (interface_ptr == NX_NULL)
183 {
184 return(NX_INVALID_PARAMETERS);
185 }
186
187 if (interface_ptr -> shaper_container == NX_NULL)
188 {
189
190 /* None shaper existed. */
191 return(NX_SUCCESS);
192 }
193
194 for (i = 0; i < NX_SHAPER_NUMBERS; i++)
195 {
196 if (interface_ptr -> shaper_container -> shaper[i] == shaper)
197 {
198 interface_ptr -> shaper_container -> shaper[i] = NX_NULL;
199 interface_ptr -> shaper_container -> shaper_number--;
200 break;
201 }
202 }
203
204 if (i >= NX_SHAPER_NUMBERS)
205 {
206 return(NX_ENTRY_NOT_FOUND);
207 }
208
209 if (interface_ptr -> shaper_container -> shaper_number == 0)
210 {
211
212 /* No shaper existed, delete the shaper_container. */
213 interface_ptr -> shaper_container = NX_NULL;
214 }
215
216 return(NX_SUCCESS);
217 }
218
219 /**************************************************************************/
220 /* */
221 /* FUNCTION RELEASE */
222 /* */
223 /* nx_shaper_config PORTABLE C */
224 /* 6.4.0 */
225 /* AUTHOR */
226 /* */
227 /* Yajun Xia, Microsoft Corporation */
228 /* */
229 /* DESCRIPTION */
230 /* */
231 /* This function configures the hardware parameters of shaper by */
232 /* network driver. */
233 /* */
234 /* INPUT */
235 /* */
236 /* interface_ptr Pointer to interface instance */
237 /* port_rate Port rate */
238 /* shaper_capability Capability of shaper */
239 /* hw_queue_number Number of HW queues */
240 /* hw_queue Pointer to HW queue list */
241 /* */
242 /* OUTPUT */
243 /* */
244 /* status Completion status */
245 /* */
246 /* CALLS */
247 /* */
248 /* nx_shaper_hw_queue_set Set HW queue info */
249 /* */
250 /* CALLED BY */
251 /* */
252 /* Network driver */
253 /* */
254 /* RELEASE HISTORY */
255 /* */
256 /* DATE NAME DESCRIPTION */
257 /* */
258 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
259 /* */
260 /**************************************************************************/
nx_shaper_config(NX_INTERFACE * interface_ptr,UINT port_rate,UCHAR shaper_capability,UCHAR hw_queue_number,NX_SHAPER_HW_QUEUE * hw_queue)261 UINT nx_shaper_config(NX_INTERFACE *interface_ptr,
262 UINT port_rate,
263 UCHAR shaper_capability,
264 UCHAR hw_queue_number,
265 NX_SHAPER_HW_QUEUE *hw_queue)
266 {
267 INT i;
268 UINT status;
269
270 interface_ptr -> shaper_container -> port_rate = port_rate;
271 interface_ptr -> shaper_container -> shaper_capability |= shaper_capability;
272 interface_ptr -> shaper_container -> hw_queue_number = hw_queue_number;
273 for (i = 0; i < hw_queue_number; i++)
274 {
275 status = nx_shaper_hw_queue_set(interface_ptr, hw_queue[i].hw_queue_id, hw_queue[i].priority, hw_queue[i].type);
276 if (status != NX_SUCCESS)
277 {
278 return(status);
279 }
280 }
281
282 return(NX_SUCCESS);
283 }
284
285 /**************************************************************************/
286 /* */
287 /* FUNCTION RELEASE */
288 /* */
289 /* nx_shaper_hw_queue_set PORTABLE C */
290 /* 6.4.0 */
291 /* AUTHOR */
292 /* */
293 /* Yajun Xia, Microsoft Corporation */
294 /* */
295 /* DESCRIPTION */
296 /* */
297 /* This function configures the hardware queue of shaper. */
298 /* */
299 /* INPUT */
300 /* */
301 /* interface_ptr Pointer to interface instance */
302 /* hw_queue_id HW queue id */
303 /* priority HW queue priority */
304 /* type HW queue type */
305 /* */
306 /* OUTPUT */
307 /* */
308 /* status Completion status */
309 /* */
310 /* CALLS */
311 /* */
312 /* None */
313 /* */
314 /* CALLED BY */
315 /* */
316 /* nx_shaper_config Config the shaper HW params */
317 /* */
318 /* RELEASE HISTORY */
319 /* */
320 /* DATE NAME DESCRIPTION */
321 /* */
322 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
323 /* */
324 /**************************************************************************/
nx_shaper_hw_queue_set(NX_INTERFACE * interface_ptr,UCHAR hw_queue_id,UCHAR priority,UCHAR type)325 UINT nx_shaper_hw_queue_set(NX_INTERFACE *interface_ptr, UCHAR hw_queue_id, UCHAR priority, UCHAR type)
326 {
327 UCHAR i, insert_id;
328
329 if (interface_ptr -> shaper_container == NX_NULL)
330 {
331 return(NX_NOT_SUPPORTED);
332 }
333
334 for (i = 0; i < interface_ptr -> shaper_container -> hw_queue_number; i++)
335 {
336
337 /* If the hw queue is already configured, we should avoid the double config. */
338 if ((interface_ptr -> shaper_container -> hw_queue[i].hw_queue_id == hw_queue_id) &&
339 (interface_ptr -> shaper_container -> hw_queue[i].type != NX_SHAPER_HW_QUEUE_NONE))
340 {
341 if (interface_ptr -> shaper_container -> hw_queue[i].priority != priority)
342 {
343 return(NX_INVALID_PARAMETERS);
344 }
345 else
346 {
347 interface_ptr -> shaper_container -> hw_queue[i].type |= type;
348 return(NX_SUCCESS);
349 }
350 }
351 }
352
353 /* The queue is not configured, insert the queue to the queue list and sort. */
354 for (i = 0; i < interface_ptr -> shaper_container -> hw_queue_number; i++)
355 {
356 if (interface_ptr -> shaper_container -> hw_queue[i].type == NX_SHAPER_HW_QUEUE_NONE)
357 {
358 /* find the first unused place to insert */
359 break;
360 }
361
362 if (interface_ptr -> shaper_container -> hw_queue[i].priority > priority)
363 {
364 /* find the first place to insert */
365 break;
366 }
367 }
368
369 if (i == interface_ptr -> shaper_container -> hw_queue_number)
370 {
371 return(NX_NOT_SUCCESSFUL);
372 }
373
374 insert_id = i;
375 for (i = (UCHAR)(interface_ptr -> shaper_container -> hw_queue_number - 1); i > insert_id; i--)
376 {
377 memcpy(&interface_ptr -> shaper_container -> hw_queue[i], &interface_ptr -> shaper_container -> hw_queue[i - 1],
378 sizeof(struct NX_SHAPER_HW_QUEUE_STRUCT)); /* use case of memcpy is verified. */
379 }
380
381 interface_ptr -> shaper_container -> hw_queue[insert_id].hw_queue_id = hw_queue_id;
382 interface_ptr -> shaper_container -> hw_queue[insert_id].priority = priority;
383 interface_ptr -> shaper_container -> hw_queue[insert_id].type = type;
384
385 return(NX_SUCCESS);
386 }
387
388 /**************************************************************************/
389 /* */
390 /* FUNCTION RELEASE */
391 /* */
392 /* nx_shaper_default_mapping_get PORTABLE C */
393 /* 6.4.0 */
394 /* AUTHOR */
395 /* */
396 /* Yajun Xia, Microsoft Corporation */
397 /* */
398 /* DESCRIPTION */
399 /* */
400 /* This function gets the default pcp to HW queue mapping config. */
401 /* */
402 /* INPUT */
403 /* */
404 /* interface_ptr Pointer to interface instance */
405 /* pcp_list Pointer to PCP list */
406 /* queue_id_list Pointer to Queue id list */
407 /* list_size Size of PCP list */
408 /* */
409 /* OUTPUT */
410 /* */
411 /* status Completion status */
412 /* */
413 /* CALLS */
414 /* */
415 /* nx_shaper_hw_cbs_queue_number_get Get number of CBS HW queue */
416 /* */
417 /* CALLED BY */
418 /* */
419 /* Application Code */
420 /* */
421 /* RELEASE HISTORY */
422 /* */
423 /* DATE NAME DESCRIPTION */
424 /* */
425 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
426 /* */
427 /**************************************************************************/
nx_shaper_default_mapping_get(NX_INTERFACE * interface_ptr,UCHAR * pcp_list,UCHAR * queue_id_list,UCHAR list_size)428 UINT nx_shaper_default_mapping_get(NX_INTERFACE *interface_ptr, UCHAR *pcp_list, UCHAR *queue_id_list, UCHAR list_size)
429 {
430 UCHAR index = (UCHAR)(interface_ptr -> shaper_container -> hw_queue_number - 1);
431 UCHAR item_number = 0;
432 UCHAR hw_cbs_queue_number;
433
434 if (interface_ptr -> shaper_container == NX_NULL)
435 {
436 return(NX_NOT_SUPPORTED);
437 }
438
439 if (list_size != NX_SHAPER_MAPPING_LIST_SIZE)
440 {
441 return(NX_INVALID_PARAMETERS);
442 }
443
444 memset(pcp_list, 0, list_size);
445 memset(queue_id_list, 0, list_size);
446
447 if (nx_shaper_hw_cbs_queue_number_get(interface_ptr, &hw_cbs_queue_number) != NX_SUCCESS)
448 {
449 return(NX_NOT_SUPPORTED);
450 }
451
452 if (hw_cbs_queue_number == 0)
453 {
454 /* no default config for this case */
455 return(NX_NOT_SUPPORTED);
456 }
457
458 if ((hw_cbs_queue_number == 1) ||
459 ((hw_cbs_queue_number == 2) &&
460 (interface_ptr -> shaper_container -> hw_queue_number == 2)))
461 {
462 pcp_list[item_number] = NX_SHAPER_CLASS_B_PCP;
463 queue_id_list[item_number++] = index--;
464 switch (interface_ptr -> shaper_container -> hw_queue_number)
465 {
466 case 2:
467 /* nothing need to do */
468 break;
469
470 case 3:
471 pcp_list[item_number] = 7;
472 queue_id_list[item_number++] = index;
473 pcp_list[item_number] = 6;
474 queue_id_list[item_number++] = index;
475 pcp_list[item_number] = 5;
476 queue_id_list[item_number++] = index;
477 pcp_list[item_number] = 4;
478 queue_id_list[item_number++] = index;
479 break;
480
481 case 4:
482 pcp_list[item_number] = 7;
483 queue_id_list[item_number++] = index;
484 pcp_list[item_number] = 6;
485 queue_id_list[item_number++] = index--;
486 pcp_list[item_number] = 5;
487 queue_id_list[item_number++] = index;
488 pcp_list[item_number] = 4;
489 queue_id_list[item_number++] = index;
490 break;
491
492 case 5:
493 pcp_list[item_number] = 7;
494 queue_id_list[item_number++] = index;
495 pcp_list[item_number] = 6;
496 queue_id_list[item_number++] = index--;
497 pcp_list[item_number] = 5;
498 queue_id_list[item_number++] = index;
499 pcp_list[item_number] = 4;
500 queue_id_list[item_number++] = index--;
501 pcp_list[item_number] = 3;
502 queue_id_list[item_number++] = index;
503 break;
504
505 case 6:
506 pcp_list[item_number] = 7;
507 queue_id_list[item_number++] = index--;
508 pcp_list[item_number] = 6;
509 queue_id_list[item_number++] = index--;
510 pcp_list[item_number] = 5;
511 queue_id_list[item_number++] = index;
512 pcp_list[item_number] = 4;
513 queue_id_list[item_number++] = index--;
514 pcp_list[item_number] = 3;
515 queue_id_list[item_number++] = index;
516 break;
517 case 7:
518 pcp_list[item_number] = 7;
519 queue_id_list[item_number++] = index--;
520 pcp_list[item_number] = 6;
521 queue_id_list[item_number++] = index--;
522 pcp_list[item_number] = 5;
523 queue_id_list[item_number++] = index;
524 pcp_list[item_number] = 4;
525 queue_id_list[item_number++] = index--;
526 pcp_list[item_number] = 3;
527 queue_id_list[item_number++] = index--;
528 pcp_list[item_number] = 0;
529 queue_id_list[item_number++] = index;
530 break;
531 case 8:
532 default:
533 pcp_list[item_number] = 7;
534 queue_id_list[item_number++] = index--;
535 pcp_list[item_number] = 6;
536 queue_id_list[item_number++] = index--;
537 pcp_list[item_number] = 5;
538 queue_id_list[item_number++] = index--;
539 pcp_list[item_number] = 4;
540 queue_id_list[item_number++] = index--;
541 pcp_list[item_number] = 3;
542 queue_id_list[item_number++] = index--;
543 pcp_list[item_number] = 0;
544 queue_id_list[item_number++] = index;
545 break;
546 }
547 }
548 else
549 {
550 pcp_list[item_number] = NX_SHAPER_CLASS_A_PCP;
551 queue_id_list[item_number++] = index--;
552 pcp_list[item_number] = NX_SHAPER_CLASS_B_PCP;
553 queue_id_list[item_number++] = index--;
554
555 switch (interface_ptr -> shaper_container -> hw_queue_number)
556 {
557 case 3:
558 /* nothing need to do */
559 break;
560 case 4:
561 pcp_list[item_number] = 7;
562 queue_id_list[item_number++] = index;
563 pcp_list[item_number] = 6;
564 queue_id_list[item_number++] = index;
565 pcp_list[item_number] = 5;
566 queue_id_list[item_number++] = index;
567 pcp_list[item_number] = 4;
568 queue_id_list[item_number++] = index;
569 break;
570 case 5:
571 pcp_list[item_number] = 7;
572 queue_id_list[item_number++] = index;
573 pcp_list[item_number] = 6;
574 queue_id_list[item_number++] = index--;
575 pcp_list[item_number] = 5;
576 queue_id_list[item_number++] = index;
577 pcp_list[item_number] = 4;
578 queue_id_list[item_number++] = index;
579 break;
580 case 6:
581 pcp_list[item_number] = 7;
582 queue_id_list[item_number++] = index--;
583 pcp_list[item_number] = 6;
584 queue_id_list[item_number++] = index--;
585 pcp_list[item_number] = 5;
586 queue_id_list[item_number++] = index;
587 pcp_list[item_number] = 4;
588 queue_id_list[item_number++] = index;
589 break;
590 case 7:
591 pcp_list[item_number] = 7;
592 queue_id_list[item_number++] = index--;
593 pcp_list[item_number] = 6;
594 queue_id_list[item_number++] = index--;
595 pcp_list[item_number] = 5;
596 queue_id_list[item_number++] = index--;
597 pcp_list[item_number] = 4;
598 queue_id_list[item_number++] = index;
599 break;
600 case 8:
601 default:
602 pcp_list[item_number] = 7;
603 queue_id_list[item_number++] = index--;
604 pcp_list[item_number] = 6;
605 queue_id_list[item_number++] = index--;
606 pcp_list[item_number] = 5;
607 queue_id_list[item_number++] = index--;
608 pcp_list[item_number] = 4;
609 queue_id_list[item_number++] = index--;
610 pcp_list[item_number] = 0;
611 queue_id_list[item_number++] = index;
612 break;
613 }
614 }
615
616 return(NX_SUCCESS);
617 }
618
619 /**************************************************************************/
620 /* */
621 /* FUNCTION RELEASE */
622 /* */
623 /* nx_shaper_current_mapping_get PORTABLE C */
624 /* 6.4.0 */
625 /* AUTHOR */
626 /* */
627 /* Yajun Xia, Microsoft Corporation */
628 /* */
629 /* DESCRIPTION */
630 /* */
631 /* This function gets the current pcp to HW queue mapping config. */
632 /* */
633 /* INPUT */
634 /* */
635 /* interface_ptr Pointer to interface instance */
636 /* pcp_list Pointer to PCP list */
637 /* queue_id_list Pointer to Queue id list */
638 /* list_size Size of PCP list */
639 /* */
640 /* OUTPUT */
641 /* */
642 /* status Completion status */
643 /* */
644 /* CALLS */
645 /* */
646 /* None */
647 /* */
648 /* CALLED BY */
649 /* */
650 /* Application Code */
651 /* */
652 /* RELEASE HISTORY */
653 /* */
654 /* DATE NAME DESCRIPTION */
655 /* */
656 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
657 /* */
658 /**************************************************************************/
nx_shaper_current_mapping_get(NX_INTERFACE * interface_ptr,UCHAR * pcp_list,UCHAR * queue_id_list,UCHAR list_size)659 UINT nx_shaper_current_mapping_get(NX_INTERFACE *interface_ptr, UCHAR *pcp_list, UCHAR *queue_id_list, UCHAR list_size)
660 {
661 UCHAR i, j;
662
663 if (interface_ptr -> shaper_container == NX_NULL)
664 {
665 return(NX_NOT_SUPPORTED);
666 }
667
668 if (list_size != NX_SHAPER_MAPPING_LIST_SIZE)
669 {
670 return(NX_INVALID_PARAMETERS);
671 }
672
673 for (i = 0; i < list_size; i++)
674 {
675 pcp_list[i] = i;
676 for (j = 0; j < list_size; j++)
677 {
678 if (interface_ptr -> shaper_container -> hw_queue[j].hw_queue_id ==
679 interface_ptr -> shaper_container -> queue_map[pcp_list[i]])
680 {
681 queue_id_list[i] = j;
682 break;
683 }
684 }
685 if (j == list_size)
686 {
687 return(NX_NOT_SUCCESSFUL);
688 }
689 }
690 return(NX_SUCCESS);
691 }
692
693 /**************************************************************************/
694 /* */
695 /* FUNCTION RELEASE */
696 /* */
697 /* nx_shaper_hw_queue_number_get PORTABLE C */
698 /* 6.4.0 */
699 /* AUTHOR */
700 /* */
701 /* Yajun Xia, Microsoft Corporation */
702 /* */
703 /* DESCRIPTION */
704 /* */
705 /* This function gets the number of hardware queue. */
706 /* */
707 /* INPUT */
708 /* */
709 /* interface_ptr Pointer to interface instance */
710 /* hw_queue_number Pointer to HW queue number */
711 /* */
712 /* OUTPUT */
713 /* */
714 /* status Completion status */
715 /* */
716 /* CALLS */
717 /* */
718 /* None */
719 /* */
720 /* CALLED BY */
721 /* */
722 /* Internal function */
723 /* */
724 /* RELEASE HISTORY */
725 /* */
726 /* DATE NAME DESCRIPTION */
727 /* */
728 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
729 /* */
730 /**************************************************************************/
nx_shaper_hw_queue_number_get(NX_INTERFACE * interface_ptr,UCHAR * hw_queue_number)731 UINT nx_shaper_hw_queue_number_get(NX_INTERFACE *interface_ptr, UCHAR *hw_queue_number)
732 {
733 if (interface_ptr -> shaper_container == NX_NULL)
734 {
735 return(NX_NOT_SUPPORTED);
736 }
737
738 *hw_queue_number = interface_ptr -> shaper_container -> hw_queue_number;
739 return(NX_SUCCESS);
740 }
741
742 /**************************************************************************/
743 /* */
744 /* FUNCTION RELEASE */
745 /* */
746 /* nx_shaper_hw_cbs_queue_number_get PORTABLE C */
747 /* 6.4.0 */
748 /* AUTHOR */
749 /* */
750 /* Yajun Xia, Microsoft Corporation */
751 /* */
752 /* DESCRIPTION */
753 /* */
754 /* This function gets the number of hardware queue that support CBS. */
755 /* */
756 /* INPUT */
757 /* */
758 /* interface_ptr Pointer to interface instance */
759 /* hw_cbs_queue_number Pointer to CBS HW queue */
760 /* number */
761 /* */
762 /* OUTPUT */
763 /* */
764 /* status Completion status */
765 /* */
766 /* CALLS */
767 /* */
768 /* None */
769 /* */
770 /* CALLED BY */
771 /* */
772 /* nx_shaper_default_mapping_get */
773 /* */
774 /* RELEASE HISTORY */
775 /* */
776 /* DATE NAME DESCRIPTION */
777 /* */
778 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
779 /* */
780 /**************************************************************************/
nx_shaper_hw_cbs_queue_number_get(NX_INTERFACE * interface_ptr,UCHAR * hw_cbs_queue_number)781 UINT nx_shaper_hw_cbs_queue_number_get(NX_INTERFACE *interface_ptr, UCHAR *hw_cbs_queue_number)
782 {
783 UCHAR i;
784
785 *hw_cbs_queue_number = 0;
786 if (interface_ptr -> shaper_container == NX_NULL)
787 {
788 return(NX_NOT_SUPPORTED);
789 }
790
791 for (i = 0; i < interface_ptr -> shaper_container -> hw_queue_number; i++)
792 {
793 if (interface_ptr -> shaper_container -> hw_queue[i].type & NX_SHAPER_HW_QUEUE_CBS)
794 {
795 (*hw_cbs_queue_number)++;
796 }
797 }
798
799 return(NX_SUCCESS);
800 }
801
802 /**************************************************************************/
803 /* */
804 /* FUNCTION RELEASE */
805 /* */
806 /* nx_shaper_port_rate_get PORTABLE C */
807 /* 6.4.0 */
808 /* AUTHOR */
809 /* */
810 /* Yajun Xia, Microsoft Corporation */
811 /* */
812 /* DESCRIPTION */
813 /* */
814 /* This function gets the port rate of the interface. */
815 /* */
816 /* INPUT */
817 /* */
818 /* interface_ptr Pointer to interface instance */
819 /* port_rate Pointer to port rate */
820 /* */
821 /* OUTPUT */
822 /* */
823 /* status Completion status */
824 /* */
825 /* CALLS */
826 /* */
827 /* None */
828 /* */
829 /* CALLED BY */
830 /* */
831 /* Internal function */
832 /* */
833 /* RELEASE HISTORY */
834 /* */
835 /* DATE NAME DESCRIPTION */
836 /* */
837 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
838 /* */
839 /**************************************************************************/
nx_shaper_port_rate_get(NX_INTERFACE * interface_ptr,UINT * port_rate)840 UINT nx_shaper_port_rate_get(NX_INTERFACE *interface_ptr, UINT *port_rate)
841 {
842 if (interface_ptr -> shaper_container == NX_NULL)
843 {
844 return(NX_NOT_SUPPORTED);
845 }
846
847 *port_rate = interface_ptr -> shaper_container -> port_rate;
848 return(NX_SUCCESS);
849 }
850
851 /**************************************************************************/
852 /* */
853 /* FUNCTION RELEASE */
854 /* */
855 /* nx_shaper_mapping_set PORTABLE C */
856 /* 6.4.0 */
857 /* AUTHOR */
858 /* */
859 /* Yajun Xia, Microsoft Corporation */
860 /* */
861 /* DESCRIPTION */
862 /* */
863 /* This function configures the pcp to hardware queue mapping. */
864 /* */
865 /* INPUT */
866 /* */
867 /* interface_ptr Pointer to interface instance */
868 /* pcp_list Pointer to PCP list */
869 /* queue_id_list Pointer to Queue id list */
870 /* list_size Size of PCP list */
871 /* */
872 /* OUTPUT */
873 /* */
874 /* status Completion status */
875 /* */
876 /* CALLS */
877 /* */
878 /* None */
879 /* */
880 /* CALLED BY */
881 /* */
882 /* Application Code */
883 /* */
884 /* RELEASE HISTORY */
885 /* */
886 /* DATE NAME DESCRIPTION */
887 /* */
888 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
889 /* */
890 /**************************************************************************/
nx_shaper_mapping_set(NX_INTERFACE * interface_ptr,UCHAR * pcp_list,UCHAR * queue_id_list,UCHAR list_size)891 UINT nx_shaper_mapping_set(NX_INTERFACE *interface_ptr, UCHAR *pcp_list, UCHAR *queue_id_list, UCHAR list_size)
892 {
893 UCHAR pcp;
894 UCHAR queue_id;
895 UCHAR i;
896
897 if (interface_ptr -> shaper_container == NX_NULL)
898 {
899 return(NX_NOT_SUPPORTED);
900 }
901
902 if (list_size != NX_SHAPER_MAPPING_LIST_SIZE)
903 {
904 return(NX_INVALID_PARAMETERS);
905 }
906
907 for (i = 0; i < list_size; i++)
908 {
909 pcp = pcp_list[i];
910 queue_id = queue_id_list[i];
911
912 if ((pcp > NX_SHAPER_PCP_MAX) ||
913 (queue_id >= interface_ptr -> shaper_container -> hw_queue_number))
914 {
915 return(NX_INVALID_PARAMETERS);
916 }
917
918 if ((pcp == 0) && (queue_id == 0))
919 {
920 /* no need to configure here */
921 continue;
922 }
923 interface_ptr -> shaper_container -> queue_map[pcp] =
924 interface_ptr -> shaper_container -> hw_queue[queue_id].hw_queue_id;
925 }
926
927 return(NX_SUCCESS);
928 }
929
930 /**************************************************************************/
931 /* */
932 /* FUNCTION RELEASE */
933 /* */
934 /* nx_shaper_cbs_parameter_set PORTABLE C */
935 /* 6.4.0 */
936 /* AUTHOR */
937 /* */
938 /* Yajun Xia, Microsoft Corporation */
939 /* */
940 /* DESCRIPTION */
941 /* */
942 /* This function configures the hardware parameters for CBS shaper. */
943 /* */
944 /* INPUT */
945 /* */
946 /* interface_ptr Pointer to interface instance */
947 /* cbs_parameter Pointer to cbs parameter */
948 /* pcp PCP */
949 /* */
950 /* OUTPUT */
951 /* */
952 /* status Completion status */
953 /* */
954 /* CALLS */
955 /* */
956 /* None */
957 /* */
958 /* CALLED BY */
959 /* */
960 /* Application Code */
961 /* */
962 /* RELEASE HISTORY */
963 /* */
964 /* DATE NAME DESCRIPTION */
965 /* */
966 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
967 /* */
968 /**************************************************************************/
nx_shaper_cbs_parameter_set(NX_INTERFACE * interface_ptr,NX_SHAPER_CBS_PARAMETER * cbs_parameter,UCHAR pcp)969 UINT nx_shaper_cbs_parameter_set(NX_INTERFACE *interface_ptr, NX_SHAPER_CBS_PARAMETER *cbs_parameter, UCHAR pcp)
970 {
971 UCHAR i;
972 UCHAR hw_queue_id;
973 UCHAR cbs_index;
974 NX_SHAPER_DRIVER_PARAMETER set_parameter;
975 UINT status;
976
977 if (interface_ptr -> shaper_container == NX_NULL)
978 {
979 return(NX_NOT_SUPPORTED);
980 }
981
982 for (i = 0; i < NX_SHAPER_NUMBERS; i++)
983 {
984 if ((interface_ptr -> shaper_container -> shaper[i] != NX_NULL) &&
985 (interface_ptr -> shaper_container -> shaper[i] -> shaper_type == NX_SHAPER_TYPE_CBS))
986 {
987 cbs_index = i;
988 break;
989 }
990 }
991
992 if (i >= NX_SHAPER_NUMBERS)
993 {
994 return(NX_NOT_FOUND);
995 }
996
997 hw_queue_id = interface_ptr -> shaper_container -> queue_map[pcp];
998
999 for (i = (UCHAR)(interface_ptr -> shaper_container -> hw_queue_number - 1); i > 0; i--)
1000 {
1001 if (interface_ptr -> shaper_container -> hw_queue[i].hw_queue_id == hw_queue_id)
1002 {
1003 if ((interface_ptr -> shaper_container -> hw_queue[i].type & NX_SHAPER_HW_QUEUE_CBS) == 0)
1004 {
1005 return(NX_NOT_SUPPORTED);
1006 }
1007 else
1008 {
1009 break;
1010 }
1011 }
1012 }
1013
1014 /* queue id 0 is assumed not support cbs */
1015 if (i == 0)
1016 {
1017 return(NX_NOT_SUPPORTED);
1018 }
1019
1020 /* Save the cbs parameter */
1021 interface_ptr -> shaper_container -> shaper[cbs_index] -> cfg_pointer = (void *)cbs_parameter;
1022
1023 cbs_parameter -> hw_queue_id = hw_queue_id;
1024
1025 set_parameter.nx_shaper_driver_command = NX_SHAPER_COMMAND_PARAMETER_SET;
1026 set_parameter.shaper_type = NX_SHAPER_TYPE_CBS; /* not used in driver */
1027 set_parameter.nx_ip_driver_interface = interface_ptr;
1028 set_parameter.shaper_parameter = (void *)cbs_parameter; /* not used in driver */
1029
1030 status = interface_ptr -> shaper_container -> shaper[cbs_index] -> shaper_driver(&set_parameter);
1031
1032 return(status);
1033 }
1034
1035 /**************************************************************************/
1036 /* */
1037 /* FUNCTION RELEASE */
1038 /* */
1039 /* nx_shaper_hw_queue_id_get PORTABLE C */
1040 /* 6.4.0 */
1041 /* AUTHOR */
1042 /* */
1043 /* Yajun Xia, Microsoft Corporation */
1044 /* */
1045 /* DESCRIPTION */
1046 /* */
1047 /* This function gets the hardware queue id by network driver. */
1048 /* */
1049 /* INPUT */
1050 /* */
1051 /* interface_ptr Pointer to interface instance */
1052 /* packet_ptr Pointer to packet */
1053 /* hw_queue_id Pointer to HW queue ID */
1054 /* */
1055 /* OUTPUT */
1056 /* */
1057 /* status Completion status */
1058 /* */
1059 /* CALLS */
1060 /* */
1061 /* None */
1062 /* */
1063 /* CALLED BY */
1064 /* */
1065 /* Network driver */
1066 /* */
1067 /* RELEASE HISTORY */
1068 /* */
1069 /* DATE NAME DESCRIPTION */
1070 /* */
1071 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
1072 /* */
1073 /**************************************************************************/
nx_shaper_hw_queue_id_get(NX_INTERFACE * interface_ptr,NX_PACKET * packet_ptr,UCHAR * hw_queue_id)1074 UINT nx_shaper_hw_queue_id_get(NX_INTERFACE *interface_ptr, NX_PACKET *packet_ptr, UCHAR *hw_queue_id)
1075 {
1076 UCHAR *data_ptr = packet_ptr -> nx_packet_prepend_ptr;
1077 UCHAR pcp = 0;
1078
1079 if (interface_ptr -> shaper_container == NX_NULL)
1080 {
1081 return(NX_NOT_SUPPORTED);
1082 }
1083
1084 /* Check VLAN tag. */
1085 if (((data_ptr[12] << 8) | data_ptr[13]) == NX_LINK_ETHERNET_TPID)
1086 {
1087 /* VLAN tag is present. */
1088
1089 /* Get PCP */
1090 pcp = data_ptr[14] >> 5 & 0x07;
1091
1092 /* Get hardware queue id for this packet */
1093 *hw_queue_id = interface_ptr -> shaper_container -> queue_map[pcp];
1094 }
1095 else
1096 {
1097
1098 /* no VLAN tag in packet, send the packet to besteffort queue */
1099 *hw_queue_id = interface_ptr -> shaper_container -> queue_map[pcp];
1100 }
1101
1102 return(NX_SUCCESS);
1103 }
1104
1105 /**************************************************************************/
1106 /* */
1107 /* FUNCTION RELEASE */
1108 /* */
1109 /* nx_shaper_tas_parameter_set PORTABLE C */
1110 /* 6.4.0 */
1111 /* AUTHOR */
1112 /* */
1113 /* Yajun Xia, Microsoft Corporation */
1114 /* */
1115 /* DESCRIPTION */
1116 /* */
1117 /* This function configures the hardware parameters for TAS shaper. */
1118 /* */
1119 /* INPUT */
1120 /* */
1121 /* interface_ptr Pointer to interface instance */
1122 /* tas_config Pointer to cbs parameter */
1123 /* */
1124 /* OUTPUT */
1125 /* */
1126 /* status Completion status */
1127 /* */
1128 /* CALLS */
1129 /* */
1130 /* None */
1131 /* */
1132 /* CALLED BY */
1133 /* */
1134 /* Application Code */
1135 /* */
1136 /* RELEASE HISTORY */
1137 /* */
1138 /* DATE NAME DESCRIPTION */
1139 /* */
1140 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
1141 /* */
1142 /**************************************************************************/
nx_shaper_tas_parameter_set(NX_INTERFACE * interface_ptr,NX_SHAPER_TAS_CONFIG * tas_config)1143 UINT nx_shaper_tas_parameter_set(NX_INTERFACE *interface_ptr, NX_SHAPER_TAS_CONFIG *tas_config)
1144 {
1145 NX_SHAPER_TAS_PARAMETER tas_parameter;
1146 UCHAR i, j, tas_index = NX_SHAPER_INVALID_INDEX;
1147 UINT front, end, step;
1148 UINT left = 0, right;
1149 UCHAR gcl_index;
1150 UCHAR hw_queue_id;
1151 NX_SHAPER_DRIVER_PARAMETER set_parameter;
1152 UINT status;
1153 UINT auto_fill_start;
1154 UCHAR fp_enable = NX_FALSE;
1155 NX_SHAPER_FP_PARAMETER *fp_parameter;
1156
1157 /* Initialize tas_parameter */
1158 memset(&tas_parameter, 0, sizeof(NX_SHAPER_TAS_PARAMETER));
1159
1160 /* Initialize set_parameter */
1161 memset(&set_parameter, 0, sizeof(NX_SHAPER_DRIVER_PARAMETER));
1162
1163 /* Find the TAS index. */
1164 for (i = 0; i < NX_SHAPER_NUMBERS; i++)
1165 {
1166 if ((interface_ptr -> shaper_container -> shaper[i] != NX_NULL) &&
1167 (interface_ptr -> shaper_container -> shaper[i] -> shaper_type == NX_SHAPER_TYPE_TAS))
1168 {
1169 tas_index = i;
1170 }
1171 else if ((interface_ptr -> shaper_container -> shaper[i] != NX_NULL) &&
1172 (interface_ptr -> shaper_container -> shaper[i] -> shaper_type == NX_SHAPER_TYPE_FP))
1173 {
1174 fp_parameter = (NX_SHAPER_FP_PARAMETER *)interface_ptr -> shaper_container -> shaper[i] -> cfg_pointer;
1175 fp_enable = NX_TRUE;
1176 tas_parameter.fp_parameter = (void *)fp_parameter;
1177 }
1178 }
1179
1180 if (tas_index == NX_SHAPER_INVALID_INDEX)
1181 {
1182 return(NX_NOT_FOUND);
1183 }
1184
1185 auto_fill_start = 0;
1186 for (i = 0; i < tas_config -> traffic_count; i++)
1187 {
1188 if (tas_config -> traffic[i].time_offset + tas_config -> traffic[i].duration > auto_fill_start)
1189 {
1190 auto_fill_start = tas_config -> traffic[i].time_offset + tas_config -> traffic[i].duration;
1191 }
1192 }
1193
1194 /* Transform the application input into driver input. */
1195 front = 0;
1196 if (tas_config -> auto_fill_status == NX_SHAPER_TAS_IDLE_CYCLE_AUTO_FILL_DISABLED)
1197 {
1198 end = auto_fill_start;
1199 }
1200 else
1201 {
1202 end = tas_config -> cycle_time;
1203 }
1204 gcl_index = 0;
1205
1206 tas_parameter.base_time = tas_config -> base_time;
1207 tas_parameter.cycle_time = tas_config -> cycle_time;
1208 tas_parameter.cycle_time_extension = tas_config -> cycle_time / 2;
1209
1210 /*
1211 Input:(Cycle time: 1000us, Cycle extension: default (half of cycle time), FP: disabled)
1212 slot 0 slot 1
1213 P3(us) |-------200(O)-------|--------------------------800(C)--------------------|
1214 P2(us) |-------300(O)--------------------|-------------700(C)--------------------|
1215 Output:
1216 slot(GCL)0 slot(GCL)1 slot(GCL)2
1217 P3(us) |-------200(O)-------|--100(C)----|-------------700(C)--------------------|
1218 P2(us) |-------200(O)-------|--100(O)----|-------------700(C)--------------------|
1219 PX(us) |-------200(C)-------|--100(C)----|-------------700(C)--------------------|
1220
1221 Example:
1222 tas_config.base_time = 0;
1223 tas_config.cycle_time = 1000;
1224 tas_config.auto_fill_status = NX_SHAPER_TAS_IDLE_CYCLE_AUTO_FILL_WITH_CLOSE;
1225 tas_config.gcl_length = 2;
1226
1227 tas_config.traffic[0].pcp = 3;
1228 tas_config.traffic[0].time_offset = 0;
1229 tas_config.traffic[0].duration = 200;
1230 tas_config.traffic[0].traffic_control = NX_SHAPER_TRAFFIC_OPEN;
1231
1232 tas_config.traffic[1].pcp = 2;
1233 tas_config.traffic[1].time_offset = 0;
1234 tas_config.traffic[1].duration = 300;
1235 tas_config.traffic[1].traffic_control = NX_SHAPER_TRAFFIC_OPEN;
1236 */
1237
1238 /* Split cycle into slots */
1239 while (front < end)
1240 {
1241 step = end - front;
1242 for (i = 0; i < tas_config -> traffic_count; i++)
1243 {
1244 if ((tas_config -> traffic[i].time_offset > front) && (step > tas_config -> traffic[i].time_offset - front))
1245 {
1246 step = tas_config -> traffic[i].time_offset - front;
1247 }
1248 else if ((tas_config -> traffic[i].time_offset + tas_config -> traffic[i].duration > front) &&
1249 (step > tas_config -> traffic[i].time_offset + tas_config -> traffic[i].duration - front))
1250 {
1251 step = tas_config -> traffic[i].time_offset + tas_config -> traffic[i].duration - front;
1252 }
1253 else if (step > end - front)
1254 {
1255 step = end - front;
1256 }
1257 }
1258
1259 if (front >= auto_fill_start)
1260 {
1261 tas_parameter.gcl[gcl_index].gate_control |= NX_SHAPER_GCL_AUTO_FILL_FLAG;
1262 }
1263 tas_parameter.gcl_length++;
1264 tas_parameter.gcl[gcl_index++].duration = step;
1265 front = front + step;
1266 }
1267
1268 /* Config the gate_control on different slot */
1269 for (i = 0; i < tas_parameter.gcl_length; i++)
1270 {
1271 right = left + tas_parameter.gcl[i].duration;
1272 for (j = 0; j < tas_config -> traffic_count; j++)
1273 {
1274 if ((right <= tas_config -> traffic[j].time_offset) || (left >= tas_config -> traffic[j].time_offset + tas_config -> traffic[j].duration))
1275 {
1276 continue;
1277 }
1278
1279 /* Get the hw queue id from pcp */
1280 hw_queue_id = interface_ptr -> shaper_container -> queue_map[tas_config -> traffic[j].pcp];
1281 if (tas_config -> traffic[j].traffic_control == NX_SHAPER_TRAFFIC_OPEN)
1282 {
1283 tas_parameter.gcl[i].gate_control |= (UCHAR)(1 << hw_queue_id);
1284 }
1285 }
1286
1287 if (tas_parameter.gcl[i].gate_control & NX_SHAPER_GCL_AUTO_FILL_FLAG)
1288 {
1289 if (tas_config -> auto_fill_status == NX_SHAPER_TAS_IDLE_CYCLE_AUTO_FILL_WITH_OPEN)
1290 {
1291 tas_parameter.gcl[i].gate_control = 0xFF;
1292 }
1293 else
1294 {
1295 tas_parameter.gcl[i].gate_control &= ~NX_SHAPER_GCL_AUTO_FILL_FLAG;
1296 }
1297 }
1298
1299 /* If fp is enabled, set the hold/release state based on the express queue status. */
1300 if (fp_enable)
1301 {
1302 /*
1303 For a GCE with set-hold, all queues opened must be Express queues. For a GCE with
1304 set-release all queues opened must be Preemptable queues. The same queue cannot
1305 be open in both a set-hold and a set-release operation.
1306 */
1307 if (tas_parameter.gcl[i].gate_control & fp_parameter -> express_queue_bitmap)
1308 {
1309 tas_parameter.gcl[i].operation = NX_SHAPER_GATE_OPERATION_HOLD;
1310 }
1311 else
1312 {
1313 tas_parameter.gcl[i].operation = NX_SHAPER_GATE_OPERATION_RELEASE;
1314 }
1315 }
1316 else
1317 {
1318 tas_parameter.gcl[i].operation = NX_SHAPER_GATE_OPERATION_SET;
1319 }
1320
1321 left = right;
1322 }
1323
1324 /* save the tas parameter */
1325 interface_ptr -> shaper_container -> shaper[tas_index] -> cfg_pointer = (void *)tas_config;
1326
1327 /* Set the object(tas_param) of NX_SHAPER_TAS_PARAMETER */
1328 set_parameter.nx_shaper_driver_command = NX_SHAPER_COMMAND_PARAMETER_SET;
1329 set_parameter.shaper_type = NX_SHAPER_TYPE_TAS; /* not used in driver */
1330 set_parameter.nx_ip_driver_interface = interface_ptr;
1331 set_parameter.shaper_parameter = (void *)&tas_parameter; /* not used in driver */
1332
1333 status = interface_ptr -> shaper_container -> shaper[tas_index] -> shaper_driver(&set_parameter);
1334
1335 return(status);
1336 }
1337
1338 /**************************************************************************/
1339 /* */
1340 /* FUNCTION RELEASE */
1341 /* */
1342 /* nx_shaper_express_queue_set PORTABLE C */
1343 /* 6.4.0 */
1344 /* AUTHOR */
1345 /* */
1346 /* Yajun Xia, Microsoft Corporation */
1347 /* */
1348 /* DESCRIPTION */
1349 /* */
1350 /* This function configures the express queue for frame preemption. */
1351 /* */
1352 /* INPUT */
1353 /* */
1354 /* interface_ptr Pointer to interface instance */
1355 /* express_queue_bitmap Pointer to express queue */
1356 /* bitmap */
1357 /* */
1358 /* OUTPUT */
1359 /* */
1360 /* status Completion status */
1361 /* */
1362 /* CALLS */
1363 /* */
1364 /* None */
1365 /* */
1366 /* CALLED BY */
1367 /* */
1368 /* nx_shaper_fp_parameter_set FP parameter set */
1369 /* */
1370 /* RELEASE HISTORY */
1371 /* */
1372 /* DATE NAME DESCRIPTION */
1373 /* */
1374 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
1375 /* */
1376 /**************************************************************************/
nx_shaper_express_queue_set(NX_INTERFACE * interface_ptr,UCHAR * express_queue_bitmap,UCHAR pcp)1377 UINT nx_shaper_express_queue_set(NX_INTERFACE *interface_ptr, UCHAR *express_queue_bitmap, UCHAR pcp)
1378 {
1379 UCHAR hw_queue_id;
1380 NX_INTERFACE *parent_interface;
1381
1382 if (interface_ptr -> nx_interface_parent_ptr != NX_NULL)
1383 {
1384 parent_interface = interface_ptr -> nx_interface_parent_ptr;
1385 }
1386 else
1387 {
1388 parent_interface = interface_ptr;
1389 }
1390
1391 if (parent_interface -> shaper_container == NX_NULL)
1392 {
1393 return(NX_NOT_SUCCESSFUL);
1394 }
1395
1396 hw_queue_id = parent_interface -> shaper_container -> queue_map[pcp];
1397 *express_queue_bitmap |= (UCHAR)(1 << hw_queue_id);
1398
1399 return(NX_SUCCESS);
1400 }
1401
1402 /**************************************************************************/
1403 /* */
1404 /* FUNCTION RELEASE */
1405 /* */
1406 /* nx_shaper_sdu_tx_time_get PORTABLE C */
1407 /* 6.4.0 */
1408 /* AUTHOR */
1409 /* */
1410 /* Yajun Xia, Microsoft Corporation */
1411 /* */
1412 /* DESCRIPTION */
1413 /* */
1414 /* This function gets the sdu transmit time. */
1415 /* */
1416 /* INPUT */
1417 /* */
1418 /* interface_ptr Pointer to interface instance */
1419 /* sdu_size SDU size */
1420 /* tx_time Pointer to transmit time */
1421 /* */
1422 /* OUTPUT */
1423 /* */
1424 /* status Completion status */
1425 /* */
1426 /* CALLS */
1427 /* */
1428 /* None */
1429 /* */
1430 /* CALLED BY */
1431 /* */
1432 /* nx_shaper_fp_parameter_set */
1433 /* */
1434 /* RELEASE HISTORY */
1435 /* */
1436 /* DATE NAME DESCRIPTION */
1437 /* */
1438 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
1439 /* */
1440 /**************************************************************************/
nx_shaper_sdu_tx_time_get(NX_INTERFACE * interface_ptr,UINT sdu_size,UINT * tx_time)1441 UINT nx_shaper_sdu_tx_time_get(NX_INTERFACE *interface_ptr, UINT sdu_size, UINT *tx_time)
1442 {
1443 UINT tmp;
1444
1445 tmp = sdu_size * 8;
1446 tmp = tmp * 1000;
1447 if (interface_ptr -> shaper_container -> port_rate != 0)
1448 {
1449 tmp = tmp / interface_ptr -> shaper_container -> port_rate;
1450 }
1451 else
1452 {
1453 return(NX_NOT_SUCCESSFUL);
1454 }
1455
1456 *tx_time = tmp;
1457 return(NX_SUCCESS);
1458 }
1459
1460 /**************************************************************************/
1461 /* */
1462 /* FUNCTION RELEASE */
1463 /* */
1464 /* nx_shaper_fp_parameter_set PORTABLE C */
1465 /* 6.4.0 */
1466 /* AUTHOR */
1467 /* */
1468 /* Yajun Xia, Microsoft Corporation */
1469 /* */
1470 /* DESCRIPTION */
1471 /* */
1472 /* This function sets the frame preemption parameter, when used with */
1473 /* other shapers, FP parameter should be set before other shapers. */
1474 /* */
1475 /* INPUT */
1476 /* */
1477 /* interface_ptr Pointer to interface instance */
1478 /* fp_parameter Pointer to FP parameter */
1479 /* */
1480 /* OUTPUT */
1481 /* */
1482 /* status Completion status */
1483 /* */
1484 /* CALLS */
1485 /* */
1486 /* nx_shaper_express_queue_set Set express queue info */
1487 /* nx_shaper_sdu_tx_time_get Get sdu transmit time */
1488 /* */
1489 /* CALLED BY */
1490 /* */
1491 /* Application Code */
1492 /* */
1493 /* RELEASE HISTORY */
1494 /* */
1495 /* DATE NAME DESCRIPTION */
1496 /* */
1497 /* 12-31-2023 Yajun Xia Initial Version 6.4.0 */
1498 /* */
1499 /**************************************************************************/
nx_shaper_fp_parameter_set(NX_INTERFACE * interface_ptr,NX_SHAPER_FP_PARAMETER * fp_parameter)1500 UINT nx_shaper_fp_parameter_set(NX_INTERFACE *interface_ptr, NX_SHAPER_FP_PARAMETER *fp_parameter)
1501 {
1502 UINT status;
1503 NX_SHAPER_DRIVER_PARAMETER set_parameter;
1504 UINT i;
1505 UINT fp_index = NX_SHAPER_INVALID_INDEX;
1506 UINT min_ha, max_ra;
1507 UCHAR express_queue_bitmap = 0, pcp;
1508
1509
1510 /* Set the express queue bitmap. */
1511 for (i = 0; i <= NX_SHAPER_PCP_MAX; i++)
1512 {
1513 if (fp_parameter -> express_queue_bitmap & (1 << i))
1514 {
1515 pcp = (UCHAR)i;
1516
1517 status = nx_shaper_express_queue_set(interface_ptr, &express_queue_bitmap, pcp);
1518 if (status != NX_SUCCESS)
1519 {
1520 return(status);
1521 }
1522 }
1523 }
1524 fp_parameter -> express_queue_bitmap = express_queue_bitmap;
1525
1526 /* Set the object(fp_param) of NX_SHAPER_FP_PARAMETER */
1527 set_parameter.nx_shaper_driver_command = NX_SHAPER_COMMAND_PARAMETER_SET;
1528 set_parameter.shaper_type = NX_SHAPER_TYPE_FP; /* not used in driver */
1529 set_parameter.nx_ip_driver_interface = interface_ptr;
1530
1531 nx_shaper_sdu_tx_time_get(interface_ptr, NX_SHAPER_DEFAULT_MIN_FRAGMENTABLE_SDU_SIZE, &min_ha);
1532 nx_shaper_sdu_tx_time_get(interface_ptr, NX_SHAPER_DEFAULT_MIN_SDU_SIZE, &max_ra);
1533
1534 if (fp_parameter -> ha < min_ha)
1535 {
1536 fp_parameter -> ha = min_ha;
1537 }
1538 if (fp_parameter -> ra > max_ra)
1539 {
1540 fp_parameter -> ra = max_ra;
1541 }
1542
1543 set_parameter.shaper_parameter = (void *)fp_parameter; /* not used in driver */
1544
1545 for (i = 0; i < NX_SHAPER_NUMBERS; i++)
1546 {
1547 if ((interface_ptr -> shaper_container -> shaper[i] != NX_NULL) &&
1548 (interface_ptr -> shaper_container -> shaper[i] -> shaper_type == NX_SHAPER_TYPE_FP))
1549 {
1550
1551 fp_index = i;
1552 break;
1553 }
1554 }
1555
1556 if (fp_index == NX_SHAPER_INVALID_INDEX)
1557 {
1558 return(NX_NOT_SUCCESSFUL);
1559 }
1560
1561 /* save the fp parameter */
1562 interface_ptr -> shaper_container -> shaper[fp_index] -> cfg_pointer = (void *)fp_parameter;
1563
1564 status = interface_ptr -> shaper_container -> shaper[fp_index] -> shaper_driver(&set_parameter);
1565
1566 return(status);
1567 }
1568 #endif /* NX_ENABLE_VLAN */
1569