blob: d667f2ecb7d39d4810428d9848dc7a591a51a45b [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/**
33 * @file bal_dpp_qos.c
34 * @brief BAL Switch Util QoS configuration API
35 *
36 * This file contains the data structures and functions for
37 * configuring and managing Quality of Service (QoS) for services on
38 * DUNE Pack Processor (DPP).
39 *
40 * The scheduler setup is presented below. In addition to setting up
41 * the scheduling elements (SEs), the BAL_DPP_QOS configures an egress
42 * port shaper on each PON-side port, as well as a per-Access Link (GEMID/LLID)
43 * shaper to implement the downstream SLA for the subscriber service.
44 *
45 * Currently the BAL_DPP_QOS configures downstream QoS only (over the
46 * PON). Maple PON Link SLAs are used to implement upstream SLAs for
47 * the subscriber service in the BAL+Maple+DPP
48 * architecture. Additional upstream QoS for TM within DPP (over the
49 * NNIs) are considered an OEM System vendor responsibility. No
50 * implementation for upstream QoS is provided by the BAL_DPP_QOS.
51 *
52 *
53 * ********************************************************************************
54 *
55 */
56
57/*@{*/
58#ifndef TEST_SW_UTIL_LOOPBACK
59
60#define BCM_PETRA_SUPPORT 1 /* TBD - this should be define in the Makefile of the ~/dpp directory */
61#define LINK_ARAD_LIBRARIES 1 /* SDK Make.config - BCM_88650_A0 */
62#define LINK_PPD_LIBRARIES 1 /* SDK Make.config - BCM_88650_A0 */
63#define INCLUDE_L3 1 /* bcm/l3.h support */
64
65#include <stdint.h> /* for compiler defined int64_t and uint64_t */
66
67#include "phymod_custom_config.h" /* resolve PHYMOD_xxx in phymod_system.h */
68#include "bcm/debug.h"
69#include "bcm/error.h"
70#include "bcm/l2.h"
71#include "bcm/mpls.h"
72#include "bcm/qos.h"
73#include "bcm/vlan.h"
74#include "bcm/vswitch.h"
75#include <soc/mcm/allenum.h>
76#include "bcm/field.h"
77#include <bcm/cosq.h>
78#include <bcm/stack.h>
79#include <bcm_int/dpp/alloc_mngr.h>
80#include <bcm_int/dpp/qos.h>
81#include <bcm_int/dpp/error.h>
82#include <bcm_int/dpp/utils.h>
83#include <bcm_int/dpp/qos.h>
84#include <soc/dpp/PPD/ppd_api_eg_vlan_edit.h>
85
86#include "bcm_dev_log.h"
87#include "bcmos_errno.h"
88#include "bal_switch_acc_term.h"
89#include "bal_switch_flow.h"
90#include "bal_switch_util.h"
91#include "bal_dpp_qos.h"
92
93/** @brief A global QoS configuration context */
94bal_sw_qos_cfg g_bal_bcm_qos_cfg = {0};
95
96/** @brief Pointer to global QoS configuration context */
97bal_sw_qos_cfg *gp_bal_bcm_qos_cfg = &g_bal_bcm_qos_cfg;
98
99/**
100 * @brief Number of traffic classes
101 */
102#define BAL_BCM_QOS_TC_NUM 8
103
104/**
105 * @brief PCP/CoS mapping to internal Traffic Class (TC)
106 *
107 * The mapping is as follows, where TC 0 maps to the lowest priority
108 * and TC 3 maps to the highest priority.
109 *
110 * PCP/DEI TC
111 * ------- --
112 * 0/0 0
113 * 0/1 0
114 * 1/0 0
115 * 1/1 0
116 * 2/0 1
117 * 2/1 1
118 * 3/0 1
119 * 3/1 1
120 * 4/0 2
121 * 4/1 2
122 * 5/0 2
123 * 5/1 2
124 * 6/0 3
125 * 6/1 3
126 * 7/0 3
127 * 7/1 3
128 *
129 * PCP values: 0 1 2 3 4 5 6 7
130 */
131const int g_bal_bcm_qos_tc_map[BAL_BCM_QOS_TC_NUM] = {0, 0, 1, 1, 2, 2, 3, 3};
132
133/**************************************************************************/
134/**
135 // * @brief Initialize the QOS Flow/VOQ ID resource pool
136 *
137 * This function initializes the QOS Flow/VOQ ID resource pool, which
138 * consists of an attribute representing the next ID value to allocate
139 * and a table containing free voq ID values.
140 *
141 * The BAL_DPP_QOS assumes four queues are assigned to each access port (GEMID/LLID) in
142 * the downstream direction. Four queues per access port is the smallest
143 * value of queues per access port supported by the DPP device.
144 *
145 * Note, in the BAL_DPP_QOS, the qos Flow and VOQ ID are set to the
146 * same value.
147 *
148 * @param p_pool Pointer to a voq ID pool
149 * @param init_value The initial value to use during voq ID allocation
150 * @param max_value The maximum value assigned by this pool
151 *
152 **************************************************************************/
153static void bal_sw_dpp_init_flow_id_pool(bal_sw_dpp_qos_flowid_pool *p_pool, uint32_t init_value, uint32_t max_value)
154{
155 /* Parameter checks */
156 BUG_ON(p_pool == NULL);
157
158 /* Initialize the data structure */
159 memset(p_pool, 0, sizeof(bal_sw_dpp_qos_flowid_pool));
160
161 /* Store the first value to be used as the voq ID */
162 p_pool->next_flow_id_value = init_value;
163
164 /* Store the maximum value assigned by the pool */
165 p_pool->max_value = max_value;
166
167 /* Initialize the free pool table */
168 TAILQ_INIT(&p_pool->free_table);
169}
170
171/**************************************************************************/
172/**
173 * @brief Clean up the qos Flow/VOQ ID resource pool
174 *
175 * This function cleans up the qos Flow/VOQ ID resource pool. It frees all
176 * of the memory used for bal_sw_dpp_qos_flowid_pool_entry_t's
177 *
178 * @param p_pool Pointer to a voq ID pool
179 *
180 **************************************************************************/
181static void bal_sw_dpp_cleanup_flow_id_pool(bal_sw_dpp_qos_flowid_pool *p_pool)
182{
183 bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
184
185 /* Parameter checks */
186 BUG_ON(p_pool == NULL);
187
188 while ((p_pool_entry = TAILQ_FIRST(&p_pool->free_table)) != NULL)
189 {
190 /* Remove the entry from the free pool table. */
191 TAILQ_REMOVE(&p_pool->free_table, p_pool_entry, entry);
192
193 /* Free the entry */
194 sal_free(p_pool_entry);
195 }
196}
197
198/**************************************************************************/
199/**
200 * @brief Allocate a qos Flow/VOQ ID from the pool
201 *
202 * This function allocates a Flow/VOQ ID from the resource pool. If
203 * there is a free voq ID entry in the free pool, the voq ID from
204 * the entry is used (i.e., returned to the caller) and the entry is
205 * freed. Otherwise, a new voq ID value is allocated and
206 * returned. This function returns an error if there are no voq IDs
207 * available.
208 *
209 * @param p_pool Pointer to a voq ID pool
210 * @param p_flow_id Pointer to the voq ID (value returned to caller)
211 *
212 * @return bcmos_errno
213 *
214 **************************************************************************/
215static bcmos_errno bal_sw_dpp_qos_alloc_flow_id(bal_sw_dpp_qos_flowid_pool *p_pool, int *p_flow_id)
216{
217 bcmos_errno rc = BCM_ERR_OK;
218 bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
219 uint32_t flow_id = 0;
220
221 /* Parameter checks */
222 BUG_ON(p_pool == NULL);
223 BUG_ON(p_flow_id == NULL);
224
225 /* Get an entry from the free pool */
226 p_pool_entry = TAILQ_FIRST(&p_pool->free_table);
227
228 /* If an entry exists from the free pool, use the voq ID from the
229 * entry.
230 */
231 if (p_pool_entry != NULL)
232 {
233 /* Remove the entry from the free pool. */
234 TAILQ_REMOVE(&p_pool->free_table, p_pool_entry, entry);
235
236 /* Use the voq ID from the entry */
237 flow_id = p_pool_entry->flow_id;
238
239 /* Free the entry */
240 sal_free(p_pool_entry);
241 }
242 else
243 {
244 /* Otherwise, use the next voq ID value (if available) */
245 if (p_pool->next_flow_id_value <= p_pool->max_value)
246 {
247 /* Use the next available voq ID value */
248 flow_id = p_pool->next_flow_id_value;
249
250 /* Increment the next_flow_id_value parameter */
251 p_pool->next_flow_id_value += BAL_BCM_QOS_QUEUES_PER_LLID;
252 }
253 }
254
255 /* Check to see if a voq ID value was available. */
256 if (flow_id == 0)
257 {
258 /* Error */
259 BCM_LOG(ERROR, log_id_sw_util, "%s(): No voq IDs available\n",
260 __FUNCTION__);
261 *p_flow_id = 0;
262 rc = BCM_ERR_NORES;
263 }
264 else
265 {
266 *p_flow_id = flow_id;
267 }
268
269 return rc;
270}
271
272/**************************************************************************/
273/**
274 * @brief Free a qos Flow/VOQ ID and return it to the resource pool
275 *
276 * This function "frees" a Flow/VOQ ID and returns it to the free
277 * pool. The free pool consists of a linked list of voq ID values
278 * that are available for reuse. When a voq ID is freed, memory is
279 * allocated to store the free voq ID value, which is appended to the
280 * link list used to implement the free pool.
281 *
282 * @param p_pool Pointer to a voq ID pool
283 * @param p_flow_id Pointer to the voq ID to free
284 *
285 * @return bcmos_errno
286 *
287 **************************************************************************/
288static bcmos_errno bal_sw_dpp_qos_free_flow_id(bal_sw_dpp_qos_flowid_pool *p_pool, int *p_flow_id)
289{
290 bcmos_errno rc = BCM_ERR_OK;
291 bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
292
293 /* Parameter checks */
294 BUG_ON(p_pool == NULL);
295 BUG_ON(p_flow_id == NULL);
296
297 /* Make sure there is something to free */
298 if (*p_flow_id == 0)
299 {
300 /* Nothing to free - just return */
301 return BCM_ERR_OK;
302 }
303
304 /* Allocate memory for a free pool entry */
305 p_pool_entry = sal_alloc(sizeof(bal_sw_dpp_qos_flowid_pool_entry), "voq ID Free Pool Entry");
306 if (p_pool_entry == NULL)
307 {
308 /* Error */
309 BCM_LOG(ERROR, log_id_sw_util,
310 "%s(): No memory for bal_sw_dpp_qos_flowid_pool_entry_t for voq ID %u\n",
311 __FUNCTION__, *p_flow_id);
312
313 rc = BCM_ERR_NORES;
314 }
315 else
316 {
317 /* Initialize the entry */
318 memset(p_pool_entry, 0, sizeof(bal_sw_dpp_qos_flowid_pool_entry));
319
320 /* Store the voq ID */
321 p_pool_entry->flow_id = *p_flow_id;
322
323 /* Add the service entry to the table */
324 TAILQ_INSERT_TAIL(&p_pool->free_table, p_pool_entry, entry);
325
326 /* Clear the voq ID entry */
327 *p_flow_id = 0;
328 }
329
330 return rc;
331}
332
333/**************************************************************************/
334/**
335 * @brief Create the PCP and DEI to Traffic Class (TC) mapping
336 *
337 * This function creates the mapping from PCP/CoS and DEI bits in the
338 * frames received by DPP to the internal traffic class (TC) in
339 * DPP. The TC is used to determine the destination VOQ for the
340 * frame.
341 *
342 * Please see comments for @ref g_bal_bcm_qos_tc_map for a description of
343 * mapping.
344 *
345 * @param unit SDK unit number
346 * @param p_tc_map Pointer to PCP/DEI to TC map array
347 *
348 * @return bcmos_errno
349 *
350 **************************************************************************/
351static bcmos_errno bal_sw_dpp_qos_tc_map_create(int unit, const int *p_tc_map)
352{
353 bcm_error_t sdk_rc = BCM_E_NONE;
354 bcm_qos_map_t l2_in_map;
355 int pcp = 0;
356 int dei = 0;
357 int32_t qos_map_id;
358
359 /* Parameter checks */
360 BUG_ON(p_tc_map == NULL);
361
362 /* Create the TC map object */
363 sdk_rc = bcm_qos_map_create(unit, BCM_QOS_MAP_INGRESS, &qos_map_id);
364 if (sdk_rc != BCM_E_NONE)
365 {
366 /* Error */
367 BCM_LOG(ERROR, log_id_sw_util,
368 "%s(): bcm_qos_map_create failed with %s\n",
369 __FUNCTION__, bcm_errmsg(sdk_rc));
370
371 return BCM_ERR_INTERNAL;
372 }
373
374 /* Create a mapping for each PCP/CoS and DEI bit value. */
375 for (pcp = 0; pcp < BAL_BCM_QOS_TC_NUM; pcp++)
376 {
377 for (dei = 0; dei < 2; dei++)
378 {
379 bcm_qos_map_t_init(&l2_in_map);
380
381 /* Ingress PCP/CoS value */
382 l2_in_map.pkt_pri = pcp;
383
384 /* DEI Bit */
385 l2_in_map.pkt_cfi = dei;
386
387 /* Set internal priority for this ingress pri */
388 l2_in_map.int_pri = p_tc_map[pcp];
389
390 /* Set color for this ingress Priority */
391 l2_in_map.color = bcmColorGreen;
392
393 sdk_rc = bcm_qos_map_add(unit, BCM_QOS_MAP_L2, &l2_in_map, qos_map_id);
394 if (sdk_rc != BCM_E_NONE)
395 {
396 /* Error */
397 BCM_LOG(ERROR, log_id_sw_util,
398 "%s(): bcm_qos_map_add failed with %s, for pcp %d, dei %d\n",
399 __FUNCTION__, bcm_errmsg(sdk_rc), pcp, dei);
400
401 return BCM_ERR_INTERNAL;
402 }
403 }
404 }
405
406 gp_bal_bcm_qos_cfg->qos_port_map_id = qos_map_id;
407
408 return BCM_ERR_OK;
409}
410
411/**************************************************************************/
412/**
413 * @brief Clean up the PCP and DEI to Traffic Class (TC) map
414 *
415 * @param unit SDK unit number
416 *
417 **************************************************************************/
418static void bal_sw_dpp_qos_tc_map_cleanup(int unit)
419{
420 bcm_error_t sdk_rc = BCM_E_NONE;
421 bcm_qos_map_t l2_in_map;
422 int pcp = 0;
423 int dei = 0;
424
425 /* Delete all mapping entries */
426 for (pcp = 0; pcp < BAL_BCM_QOS_TC_NUM; pcp++)
427 {
428 for (dei = 0; dei < 2; dei++)
429 {
430 bcm_qos_map_t_init(&l2_in_map);
431
432 /* Ingress PCP/CoS value */
433 l2_in_map.pkt_pri = pcp;
434
435 /* DEI Bit */
436 l2_in_map.pkt_cfi = dei;
437
438 sdk_rc = bcm_qos_map_delete(unit, BCM_QOS_MAP_L2, &l2_in_map, gp_bal_bcm_qos_cfg->qos_port_map_id);
439 if (sdk_rc != BCM_E_NONE)
440 {
441 /* Error */
442 BCM_LOG(ERROR, log_id_sw_util,
443 "%s(): bcm_qos_map_delete failed with %s, for pcp %d, dei %d\n",
444 __FUNCTION__, bcm_errmsg(sdk_rc), pcp, dei);
445
446 /* Continue processing - don't halt because of errors during clearn up */
447 }
448 }
449 }
450
451 /* Delete the TC map object */
452 sdk_rc = bcm_qos_map_destroy(unit, gp_bal_bcm_qos_cfg->qos_port_map_id);
453 if (sdk_rc != BCM_E_NONE)
454 {
455 /* Error */
456 BCM_LOG(ERROR, log_id_sw_util,
457 "%s(): bcm_qos_map_destroy failed with %s\n",
458 __FUNCTION__, bcm_errmsg(sdk_rc));
459
460 /* Continue processing - don't halt because of errors during clearn up */
461 }
462}
463
464/**************************************************************************/
465/**
466 * @brief Initialize the BAL DPP QoS Module
467 *
468 * This function initializes the QoS module for the BAL BCM Switch Util.
469 * This function initializes the global QoS context, and
470 * sets up downstream scheduling hierarchy on each channelized
471 * PON-side port. Scheduling/QoS is applied to packets that egress the
472 * port.
473 *
474 * @param unit SDK unit number
475 * @param pon_mode pon interface mode
476 *
477 * @return bcmos_errno
478 *
479 **************************************************************************/
480bcmos_errno bal_sw_dpp_qos_init(int unit, bal_swapp_port_map_indx pon_mode)
481{
482 bcmos_errno rc = BCM_ERR_OK;
483 bcm_error_t sdk_rc = BCM_E_NONE;
484 bal_sw_dpp_qos_sched_pon_chan pon_chan;
485 uint32_t port_rate, pri_channel_rate, sec_channel_rate;
486 int ii, port_num;
487
488 /* Initialization */
489 memset(gp_bal_bcm_qos_cfg, 0, sizeof(*gp_bal_bcm_qos_cfg));
490
491 do /* Exception Block Start */
492 {
493 rc = bal_sw_dpp_qos_tc_map_create(unit, g_bal_bcm_qos_tc_map);
494 if (rc != BCM_ERR_OK)
495 {
496 /* Error */
497 BCM_LOG(ERROR, log_id_sw_util,
498 "Failed to create the default QoS TC map\n");
499
500 rc = BCM_ERR_INTERNAL;
501 break;
502 }
503
504 /* Get this module ID for this ARAD device. This is used by
505 * several of the bcm API calls during QoS setups.
506 */
507 sdk_rc = bcm_stk_modid_get(unit, &gp_bal_bcm_qos_cfg->mod_id);
508 if (sdk_rc != BCM_E_NONE)
509 {
510 /* Error */
511 BCM_LOG(ERROR, log_id_sw_util,
512 "%s(): bcm_stk_modid_get failed with %s\n",
513 __FUNCTION__, bcm_errmsg(sdk_rc));
514
515 rc = BCM_ERR_INTERNAL;
516 break;
517 }
518
519 /* set the port rate based on board type */
520 switch(pon_mode)
521 {
522 case BAL_SWAPP_PORT_MAP_GPON:
523 case BAL_SWAPP_PORT_MAP_GPON_V3:
524 port_rate = 2500000; /* 2.5G */
525 pri_channel_rate = 2500000; /* 2.5G */
526 sec_channel_rate = 0;
527 gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
528 break;
529 case BAL_SWAPP_PORT_MAP_EXP:
530 case BAL_SWAPP_PORT_MAP_EXP2:
531 case BAL_SWAPP_PORT_MAP_SVK4:
532 port_rate = 10000000; /* 10G */
533 pri_channel_rate = 10000000; /* 10G */
534 sec_channel_rate = 0;
535 gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
536 break;
537 case BAL_SWAPP_PORT_MAP_EPON_TDMA:
538 port_rate = BAL_BCM_QOS_DEFAULT_PORT_RATE; /* 12.5G */
539 pri_channel_rate = BAL_BCM_QOS_DEFAULT_10G_CHAN_RATE; /* 10.25G */
540 sec_channel_rate = BAL_BCM_QOS_DEFAULT_1G_CHAN_RATE; /* 2.25G */
541 gp_bal_bcm_qos_cfg->num_channels_per_pon = 2;
542 break;
543 case BAL_SWAPP_PORT_MAP_EPON_1G:
544 port_rate = 2500000; /* 2.5G */
545 pri_channel_rate = BAL_BCM_QOS_DEFAULT_1G_CHAN_RATE; /* 2.25G */
546 sec_channel_rate = 0;
547 gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
548 break;
549 case BAL_SWAPP_PORT_MAP_EPON_10G:
550 port_rate = BAL_BCM_QOS_DEFAULT_PORT_RATE; /* 12.5G */
551 pri_channel_rate = BAL_BCM_QOS_DEFAULT_10G_CHAN_RATE; /* 10.25G */
552 sec_channel_rate = 0;
553 gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
554 break;
555 default:
556 /* Error */
557 BCM_LOG(ERROR, log_id_sw_util,
558 "%s(): pon mode %d not supported\n",
559 __FUNCTION__, pon_mode);
560
561 return BCM_ERR_INTERNAL;
562 }
563 /*
564 * Initialize the egress scheduling for downstream QoS on each
565 * PON-side port.
566 */
567 ii = 0; /* Start with the first PON logical interface */
568 /* loop through all pon port, -1 indicate end of table */
569 while(-1 != (port_num = bal_bcm_pon_inf_pbm_get(ii)))
570 {
571 /*
572 * Default port settings
573 *
574 * Set the port shaper to rate based on physical layout on each board.
575 * On Epon, there are 2 channels on each port.
576 * The channel interface shapers are set to 10G and 2G for the 10G and 1G
577 * channels respectively. DPP will rely on flow control from
578 * Maple for back pressure.
579 */
580 bal_sw_dpp_qos_set_port_bandwidth(unit, port_num,
581 port_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
582 bal_sw_dpp_qos_set_portchan_bandwidth(unit, port_num, BAL_BCM_SCHED_PON_CHAN_10G,
583 pri_channel_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
584 if(gp_bal_bcm_qos_cfg->num_channels_per_pon > 1)
585 {
586 bal_sw_dpp_qos_set_portchan_bandwidth(unit, port_num, BAL_BCM_SCHED_PON_CHAN_1G,
587 sec_channel_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
588 }
589 for (pon_chan = 0; pon_chan < gp_bal_bcm_qos_cfg->num_channels_per_pon; pon_chan++)
590 {
591 /* pass the logical port number - ii, to the port qos init function,
592 * the logical port number and the channel number will be mapped to
593 * packet process port number that used in qos configuration
594 */
595 rc = bal_sw_dpp_port_qos_init(unit, ii, pon_chan);
596
597 if (rc != BCM_ERR_OK)
598 {
599 /* Error */
600 BCM_LOG(ERROR, log_id_sw_util,
601 "QoS setup failed for port %u pon_chan %u\n",
602 port_num, pon_chan);
603
604 rc = BCM_ERR_INTERNAL;
605 break;
606 }
607 }
608
609 /* Exception Block - check for errors from the previous loop */
610 if (rc != BCM_ERR_OK)
611 {
612 /* Error */
613 break;
614 }
615 ii++;
616 }
617
618 /* Check for errors */
619 if (rc != BCM_ERR_OK)
620 {
621 break;
622 }
623
624 /* Initialize the Flow/VOQ ID pools */
625 bal_sw_dpp_init_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_10g,
626 DEFAULT_QOS_VOQ_BASE_10G,
627 DEFAULT_QOS_VOQ_MAX_10G);
628
629 bal_sw_dpp_init_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_1g,
630 DEFAULT_QOS_VOQ_BASE_1G,
631 DEFAULT_QOS_VOQ_MAX_1G);
632
633 } while(0); /* Exception Block - End */
634
635 /* Check for errors */
636 if (rc != BCM_ERR_OK)
637 {
638 /* Failure */
639 BCM_LOG(ERROR, log_id_sw_util,
640 "BAL BCM App not initialized, failed setting up the QoS module\n");
641
642 /* Cleanup */
643 bal_sw_dpp_qos_cleanup(unit);
644 }
645 else
646 {
647 /* Success */
648 BCM_LOG(INFO, log_id_sw_util,
649 "Successfully initialized the QoS module\n");
650 }
651
652 return rc;
653}
654
655/**************************************************************************/
656/**
657 * @brief Cleanup the BAL BCM APP QoS Module
658 *
659 * @param unit SDK unit number
660 *
661 **************************************************************************/
662void bal_sw_dpp_qos_cleanup(int unit)
663{
664 bcm_port_t port_num;
665 bal_sw_dpp_qos_sched_pon_chan pon_chan;
666 int ii;
667 /*
668 * Cleanup the egress scheduling for downstream QoS on each
669 * PON-side port.
670 */
671 ii = 0; /* Start with the first PON logical interface */
672 /* loop through all pon port, -1 indicate end of table */
673 while(-1 != (port_num = bal_bcm_pon_inf_pbm_get(ii)))
674 {
675 /* Clean up each channelized port */
676 for (pon_chan = 0; pon_chan < gp_bal_bcm_qos_cfg->num_channels_per_pon; pon_chan++)
677 {
678 bal_sw_dpp_port_qos_cleanup(unit, ii, pon_chan);
679 }
680 ii++;
681 }
682
683 /* Clean up the TC map */
684 bal_sw_dpp_qos_tc_map_cleanup(unit);
685
686 /* Free memory that was used for the Flow/VOQ ID pools */
687 bal_sw_dpp_cleanup_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_10g);
688 bal_sw_dpp_cleanup_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_1g);
689}
690
691/**************************************************************************/
692/**
693 * @brief Configure the rate shaper for a PON port
694 *
695 * This function configures the rate shaper (i.e., rate limit) for a
696 * PON side port. The rate limit and maximum burst size is set to the
697 * value specified in the function call. The maximum burst size is
698 * only set for max_burst values greater than '0'.
699 *
700 * @param unit SDK unit number
701 * @param pon_port PON port number
702 * @param bandwidth Shaper data rate in kbps
703 * @param max_burst Shaper maximum burst size in bytes
704 *
705 * @return bcmos_errno
706 *
707 **************************************************************************/
708bcmos_errno bal_sw_dpp_qos_set_port_bandwidth(int unit, bcm_port_t pon_port,
709 uint32_t bandwidth, uint32_t max_burst)
710{
711 bcmos_errno rc = BCM_ERR_OK;
712 bcm_error_t sdk_rc = BCM_E_NONE;
713 bcm_gport_t e2e_pon_gport;
714 bcm_gport_t e2e_parent_gport;
715
716 /* Parameter checks */
717 BUG_ON(pon_port > BAL_BCM_MAX_PON_NUM);
718
719 /* Get the gport object for the E2E interface for the specified
720 * pon_port
721 */
722 BCM_COSQ_GPORT_E2E_PORT_SET(e2e_pon_gport, pon_port);
723
724 do /* Exception Block Start */
725 {
726 /*
727 * Get the gport for the E2E Interface
728 */
729 sdk_rc = bcm_fabric_port_get(unit,
730 e2e_pon_gport,
731 0,
732 &e2e_parent_gport);
733 if (sdk_rc != BCM_E_NONE)
734 {
735 /* Error */
736 BCM_LOG(ERROR, log_id_sw_util,
737 "%s(): bcm_fabric_port_get for Egress Port failed with %s for pon %u\n",
738 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
739
740 rc = BCM_ERR_INTERNAL;
741 break;
742 }
743
744 /*
745 * Set rate on the E2E Interface
746 */
747 sdk_rc = bcm_cosq_gport_bandwidth_set(unit,
748 e2e_parent_gport,
749 0,
750 0,
751 bandwidth,
752 0);
753 if (sdk_rc != BCM_E_NONE)
754 {
755 /* Error */
756 BCM_LOG(ERROR, log_id_sw_util,
757 "%s(): bcm_cosq_gport_bandwidth_set for Egress Port failed with %s for pon %u\n",
758 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
759
760 rc = BCM_ERR_INTERNAL;
761 break;
762 }
763
764 /* Set the Burst */
765 if (max_burst > 0)
766 {
767 sdk_rc = bcm_cosq_control_set(unit,
768 e2e_parent_gport,
769 0,
770 bcmCosqControlBandwidthBurstMax,
771 max_burst);
772 if (sdk_rc != BCM_E_NONE)
773 {
774 /* Error */
775 BCM_LOG(ERROR, log_id_sw_util,
776 "%s(): bcm_cosq_control_set for MaxBurst failed with %s for pon %u\n",
777 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
778
779 rc = BCM_ERR_INTERNAL;
780 break;
781 }
782 }
783
784 } while(0); /* Exception Block - End */
785
786 return rc;
787}
788
789/**************************************************************************/
790/**
791 * @brief Configure the rate shaper for a PON channel
792 *
793 * This function configures the rate shaper (i.e., rate limit) for a
794 * PON channel 10G. vs. 1G. The rate limit and maximum burst size is
795 * set to the value specified in the function call. The maximum burst
796 * size is only set for max_burst values greater than '0'.
797 *
798 * @param unit SDK unit number
799 * @param pon_port PON port number
800 * @param pon_chan PON channel (10G vs. 1G)
801 * @param bandwidth Shaper data rate in kbps
802 * @param max_burst Shaper maximum burst size in bytes
803 *
804 * @return bcmos_errno
805 *
806 **************************************************************************/
807bcmos_errno bal_sw_dpp_qos_set_portchan_bandwidth(int unit, bcm_port_t pon_port,
808 bal_sw_dpp_qos_sched_pon_chan pon_chan,
809 uint32_t bandwidth, uint32_t max_burst)
810{
811 bcmos_errno rc = BCM_ERR_OK;
812 bcm_error_t sdk_rc = BCM_E_NONE;
813 bcm_port_t pp_port;
814 bcm_gport_t e2e_gport;
815 bcm_gport_t local_gport;
816 bcm_gport_t e2e_tc_gport;
817 bcm_gport_t local_tc_gport;
818 uint32_t adj_bandwidth;
819
820 /* Parameter checks */
821 BUG_ON(pon_port > BAL_BCM_MAX_PON_NUM);
822 BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
823
824 /* Get the local port number for the specified device PON port number and channel */
825 pp_port = BAL_BCM_GET_PP_PORT(pon_port, pon_chan);
826
827 do /* Exception Block Start */
828 {
829 /* Apply a rate adjustment to the credit generator */
830 adj_bandwidth = bandwidth + ((uint32_t)(bandwidth * BAL_BCM_QOS_CREDIT_RATE_ADJ));
831
832 BCM_COSQ_GPORT_E2E_PORT_SET(e2e_gport, pp_port);
833 sdk_rc = bcm_cosq_gport_bandwidth_set(unit, e2e_gport, 0, 0, adj_bandwidth, 0);
834 if (sdk_rc != BCM_E_NONE)
835 {
836 /* Error */
837 BCM_LOG(ERROR, log_id_sw_util,
838 "%s(): bcm_cosq_gport_bandwidth_set for e2e_gport failed with %s for pon %u chan %u pp_port %u\n",
839 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
840
841 rc = BCM_ERR_INTERNAL;
842 break;
843 }
844
845 /* Apply a rate adjustment to the shaper */
846 adj_bandwidth = bandwidth + ((uint32_t)(bandwidth * BAL_BCM_QOS_SHAPER_RATE_ADJ));
847
848 BCM_GPORT_LOCAL_SET(local_gport, pp_port);
849 sdk_rc = bcm_cosq_gport_bandwidth_set(unit, local_gport, 0, 0, adj_bandwidth, 0);
850 if (sdk_rc != BCM_E_NONE)
851 {
852 /* Error */
853 BCM_LOG(ERROR, log_id_sw_util,
854 "%s(): bcm_cosq_gport_bandwidth_set for local_gport failed with %s for pon %u chan %u pp_port %u\n",
855 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
856
857 rc = BCM_ERR_INTERNAL;
858 break;
859 }
860
861 BCM_COSQ_GPORT_E2E_PORT_TC_SET(e2e_tc_gport, pp_port);
862 sdk_rc = bcm_cosq_gport_bandwidth_set(unit, e2e_tc_gport, 0, 0, bandwidth, 0);
863 if (sdk_rc != BCM_E_NONE)
864 {
865 /* Error */
866 BCM_LOG(ERROR, log_id_sw_util,
867 "%s(): bcm_cosq_gport_bandwidth_set for e2e_tc_gport failed with %s for pon %u chan %u pp_port %u\n",
868 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
869
870 rc = BCM_ERR_INTERNAL;
871 break;
872 }
873
874 BCM_COSQ_GPORT_PORT_TC_SET(local_tc_gport, pp_port);
875 sdk_rc = bcm_cosq_gport_bandwidth_set(unit, local_tc_gport, 0, 0, bandwidth, 0);
876 if (sdk_rc != BCM_E_NONE)
877 {
878 /* Error */
879 BCM_LOG(ERROR, log_id_sw_util,
880 "%s(): bcm_cosq_gport_bandwidth_set for local_tc_gport failed with %s for pon %u chan %u pp_port %u\n",
881 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
882
883 rc = BCM_ERR_INTERNAL;
884 break;
885 }
886
887 } while(0); /* Exception Block - End */
888
889 return rc;
890}
891
892/**************************************************************************/
893/**
894 * @brief Configure SP or WFQ scheduling for a PON channel
895 *
896 * This function configures scheduling for a PON channel (10G
897 * vs. 1G). If all of the specified weight values are non-zero, then
898 * WFQ is enabled on the PON channel. Otherwise, if one or more of the
899 * weight values is zero, strict priority (SP) scheduling will be used
900 * on this port.
901 *
902 * @param unit SDK unit number
903 * @param pon_port PON port number
904 * @param pon_chan PON channel (10G vs. 1G)
905 * @param p_wfq_cfg Pointer to the WFQ scheduler configuration
906 *
907 * @return bcmos_errno
908 *
909 **************************************************************************/
910bcmos_errno bal_sw_dpp_qos_set_ponchan_wfq_cfg(int unit, bcm_port_t pon_port,
911 bal_sw_dpp_qos_sched_pon_chan pon_chan, bal_sw_dpp_qos_wfq_cfg *p_wfq_cfg)
912{
913 bcmos_errno rc = BCM_ERR_OK;
914 bcm_error_t sdk_rc = BCM_E_NONE;
915 bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
916 uint8_t wfq_lvl;
917 uint32_t weight;
918
919 /* Parameter checks */
920 BUG_ON(pon_port >= BAL_BCM_QOS_NUM_PON_PORTS);
921 BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
922
923 /* Get the scheduler configuration for the port. */
924 p_port_qos = &gp_bal_bcm_qos_cfg->pon[pon_port][pon_chan];
925
926 /* Assume WFQ is used until a zero weight value is encountered. */
927 p_port_qos->sched_type = BAL_BCM_SCHED_TYPE_WFQ;
928 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
929 {
930 if (p_wfq_cfg->weights[wfq_lvl] == 0)
931 {
932 /* Use strict priority */
933 memset(&p_port_qos->pon_chan_weight_cfg, 0, sizeof(p_port_qos->pon_chan_weight_cfg));
934 p_port_qos->sched_type = BAL_BCM_SCHED_TYPE_SP;
935 break;
936 }
937 else
938 {
939 p_port_qos->pon_chan_weight_cfg[wfq_lvl] = p_wfq_cfg->weights[wfq_lvl];
940 }
941 }
942
943 /* If WFQ is being used, update the weight values in the PON
944 * channel's SE. Otherwise, the scheduling type is SP and there is
945 * nothing else to do.
946 */
947 if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_WFQ)
948 {
949 /* Apply the weight configuration for each WFQ scheduling
950 * level to the hardware.
951 */
952 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
953 {
954 /* The weight cannot exceed 4K on ARAD */
955 weight = p_port_qos->pon_chan_weight_cfg[wfq_lvl];
956 if (weight > BAL_BCM_SCHED_WFQ_MAX_WEIGHT)
957 {
958 BCM_LOG(WARNING, log_id_sw_util,
959 "Configured weight value %u is larger than the maximum supported by ARAD, capping value to %u, pon %u, chan %u, wfq_lvl %u\n",
960 weight, BAL_BCM_SCHED_WFQ_MAX_WEIGHT, pon_port, pon_chan, wfq_lvl);
961
962 /* If the weight value exceeds max, cap that value at 4K. */
963 weight = BAL_BCM_SCHED_WFQ_MAX_WEIGHT;
964 }
965
966 /* Configure the hardware */
967 sdk_rc = bcm_cosq_gport_sched_set(unit,
968 p_port_qos->wfq_scheduler[wfq_lvl],
969 0,
970 BCM_COSQ_SP3,
971 weight);
972 if (sdk_rc != BCM_E_NONE)
973 {
974 /* Error */
975 BCM_LOG(ERROR, log_id_sw_util,
976 "%s(): bcm_cosq_gport_sched_set for PON Channel WFQ SE failed with %s for pon %u, chan %u, wfq_lvl %u\n",
977 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
978
979 rc = BCM_ERR_INTERNAL;
980 break;
981 }
982 }
983 }
984
985 return rc;
986}
987
988/**************************************************************************/
989/**
990 * @brief Initialize downstream QoS for a channelized PON port
991 *
992 * This function initializes downstream QoS for a channelized PON
993 * port, where scheduling/QoS is applied to packets that egress the
994 * port. Please refer to the "SCHEDULER MODEL" diagram at the top of
995 * this file.
996 *
997 * This function configures the Port-related scheduling elements
998 * (SEs), including the PON channel (10G vs. 1G) High Resolution
999 * Diff-serve (HR) SE. CIR flows are attached directly to the channel
1000 * HR. Strict Priority (SP) and Weighted-Fair Queue (WFQ) SEs are
1001 * created to implement DOCSIS Traffic Priority for EIR flows. After
1002 * creating the SEs, each SE is connected to the hierarchy as shown in
1003 * the diagram.
1004 *
1005 * @param unit SDK unit number
1006 * @param log_pon logical PON port number
1007 * @param pon_chan PON channel (10G vs. 1G)
1008 *
1009 * @return bcmos_errno
1010 *
1011 **************************************************************************/
1012bcmos_errno bal_sw_dpp_port_qos_init(int unit, bcm_port_t log_pon, bal_sw_dpp_qos_sched_pon_chan pon_chan)
1013{
1014 bcmos_errno rc = BCM_ERR_OK;
1015 bcm_error_t sdk_rc = BCM_E_NONE;
1016 bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
1017 bcm_gport_t mod_gport;
1018 int flags = 0;
1019 int wfq_lvl;
1020 bcm_port_t pp_port, pon_port;
1021
1022 /* Parameter checks */
1023 BUG_ON(log_pon >= BAL_BCM_QOS_NUM_PON_PORTS);
1024 BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
1025
1026 BCM_LOG(DEBUG, log_id_sw_util,
1027 "%s(): initializing QoS on port %d, %s channel w sche mode %s\n",
1028 __FUNCTION__, log_pon, (pon_chan == BAL_BCM_SCHED_PON_CHAN_10G) ? "10G" : "1G",
1029 (bal_bcm_ds_sched_mode_get()) ? "WFQ" : "SP");
1030
1031 /* Retrieve the QoS configuration for the specified channel, index by logical pon number */
1032 p_port_qos = &gp_bal_bcm_qos_cfg->pon[log_pon][pon_chan];
1033
1034 /* Get Max rate scheduling mode from global setting */
1035 /* TBD - the scheduling mode can be different for each port */
1036 p_port_qos->sched_type = bal_bcm_ds_sched_mode_get();
1037
1038 /* get the pp port from the device port number */
1039 pon_port = bal_bcm_pon_inf_pbm_get(log_pon);
1040 pp_port = BAL_BCM_GET_PP_PORT(pon_port, pon_chan);
1041
1042 /*
1043 * Setup downstream scheduling this channelized port
1044 */
1045
1046 do /* Exception Block Start */
1047 {
1048 /*
1049 * Get the mod port for this channel.
1050 */
1051 BCM_GPORT_MODPORT_SET(mod_gport, gp_bal_bcm_qos_cfg->mod_id, pp_port);
1052 p_port_qos->mod_gport = mod_gport;
1053
1054 /* Initialize the channel weights to defaults values.
1055 *
1056 * By default strict priority is used, so these weight values
1057 * are not "active". However, we need to set the weights to
1058 * something non-zero during initialization.
1059 *
1060 * The default channel weights are...
1061 * 32, 64, 128, 256, 512, 1024, 2048, 4096
1062 */
1063 p_port_qos->pon_chan_weight_cfg[0] = 32;
1064 for (wfq_lvl=1; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
1065 {
1066 p_port_qos->pon_chan_weight_cfg[wfq_lvl] = 2 * p_port_qos->pon_chan_weight_cfg[wfq_lvl-1];
1067 }
1068
1069 /*
1070 * Channel HR (level 1)
1071 *
1072 * Get the OTM port HR for this PON channel. The rest of
1073 * the downstream scheduling hierarchy is attached to this
1074 * HR.
1075 *
1076 * The 'BCM_COSQ_GPORT_REPLACE' flag is passed into the
1077 * bcm_cosq_gport_add() function call, which changes the
1078 * scheduling type from the default mode to a SINGLE_WFQ
1079 * mode.
1080 */
1081 BCM_COSQ_GPORT_E2E_PORT_SET(p_port_qos->pon_chan_scheduler, pp_port);
1082 flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_HR_SINGLE_WFQ | BCM_COSQ_GPORT_REPLACE;
1083 sdk_rc = bcm_cosq_gport_add(unit, pp_port, 1, flags, &p_port_qos->pon_chan_scheduler);
1084 if (sdk_rc != BCM_E_NONE)
1085 {
1086 /* Error */
1087 BCM_LOG(ERROR, log_id_sw_util,
1088 "%s(): bcm_cosq_gport_add (with REPLACE) for PON Channel HR failed with %s for pon %u chan %u\n",
1089 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1090
1091 rc = BCM_ERR_INTERNAL;
1092 break;
1093 }
1094 else
1095 {
1096
1097 BCM_LOG(DEBUG, log_id_sw_util,
1098 "%s(): bcm_cosq_gport_add (with REPLACE) for PON Channel HR - gport 0x%x\n",
1099 __FUNCTION__, p_port_qos->pon_chan_scheduler);
1100 }
1101 /*
1102 * Strict Priority HR (level 2)
1103 *
1104 * Set up a Strict Priority HR scheduler for EIR (MAX Rate)
1105 * flows. This SE is only used when the PON channel is running
1106 * in Strict Priority mode.
1107 */
1108
1109 /* Create the scheduler object */
1110 flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_HR_ENHANCED;
1111 sdk_rc = bcm_cosq_gport_add(unit, 0, 1, flags, &p_port_qos->sp_scheduler);
1112 if (sdk_rc != BCM_E_NONE)
1113 {
1114 /* Error */
1115 BCM_LOG(ERROR, log_id_sw_util,
1116 "%s(): bcm_cosq_gport_add for MAX Rate SP HR failed with %s for pon %u chan %u\n",
1117 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1118
1119 rc = BCM_ERR_INTERNAL;
1120 break;
1121 }
1122 else
1123 {
1124
1125 BCM_LOG(DEBUG, log_id_sw_util,
1126 "%s(): bcm_cosq_gport_add for MAX Rate SP HR - gport 0x%x\n",
1127 __FUNCTION__, p_port_qos->sp_scheduler);
1128 }
1129
1130 /* Configure the priority for this scheduler. The SP SE is
1131 * attached at priority '2'.
1132 */
1133 sdk_rc = bcm_cosq_gport_sched_set(unit,
1134 p_port_qos->sp_scheduler,
1135 0,
1136 BCM_COSQ_SP2,
1137 0);
1138 if (sdk_rc != BCM_E_NONE)
1139 {
1140 /* Error */
1141 BCM_LOG(ERROR, log_id_sw_util,
1142 "%s(): bcm_cosq_gport_sched_set for MAX Rate SP HR failed with %s for pon %u chan %u\n",
1143 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1144
1145 rc = BCM_ERR_INTERNAL;
1146 break;
1147 }
1148
1149 /* Attach the SP scheduler to the Channel HR. */
1150 sdk_rc = bcm_cosq_gport_attach(unit,
1151 p_port_qos->pon_chan_scheduler,
1152 p_port_qos->sp_scheduler,
1153 0);
1154 if (sdk_rc != BCM_E_NONE)
1155 {
1156 /* Error */
1157 BCM_LOG(ERROR, log_id_sw_util,
1158 "%s(): bcm_cosq_gport_attach for MAX Rate SP HR failed with %s for pon %u chan %u\n",
1159 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1160
1161 rc = BCM_ERR_INTERNAL;
1162 break;
1163 }
1164
1165 /*
1166 * WFQ (level 2)
1167 *
1168 * Create FQ scheduling elements and attach one to each
1169 * WFQ level. This is used to schedule EIR (MAX Rate)
1170 * flows when the PON channel is running in WFQ mode.
1171 */
1172
1173 /* Create a FQ scheduler for each WFQ level */
1174 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
1175 {
1176 /* Create the scheduler object */
1177 flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_FQ;
1178 sdk_rc = bcm_cosq_gport_add(unit, 0, 1, flags, &p_port_qos->wfq_scheduler[wfq_lvl]);
1179 if (sdk_rc != BCM_E_NONE)
1180 {
1181 /* Error */
1182 BCM_LOG(ERROR, log_id_sw_util,
1183 "%s(): bcm_cosq_gport_add for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
1184 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
1185
1186 rc = BCM_ERR_INTERNAL;
1187 break;
1188 }
1189
1190 /* Configure the priority for this SE. (WFQ is SP3 on
1191 * the Channel HR.)
1192 */
1193 sdk_rc = bcm_cosq_gport_sched_set(unit,
1194 p_port_qos->wfq_scheduler[wfq_lvl],
1195 0,
1196 BCM_COSQ_SP3,
1197 p_port_qos->pon_chan_weight_cfg[wfq_lvl]);
1198 if (sdk_rc != BCM_E_NONE)
1199 {
1200 /* Error */
1201 BCM_LOG(ERROR, log_id_sw_util,
1202 "%s(): bcm_cosq_gport_sched_set for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
1203 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
1204
1205 rc = BCM_ERR_INTERNAL;
1206 break;
1207 }
1208
1209 /* Attach the FQ scheduler the WFQ on the Channel HR. */
1210 sdk_rc = bcm_cosq_gport_attach(unit,
1211 p_port_qos->pon_chan_scheduler,
1212 p_port_qos->wfq_scheduler[wfq_lvl],
1213 0);
1214 if (sdk_rc != BCM_E_NONE)
1215 {
1216 /* Error */
1217 BCM_LOG(ERROR, log_id_sw_util,
1218 "%s(): bcm_cosq_gport_attach for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
1219 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
1220
1221 rc = BCM_ERR_INTERNAL;
1222 break;
1223 }
1224 }
1225
1226 } while(0); /* Exception Block - End */
1227
1228 return rc;
1229}
1230
1231/**************************************************************************/
1232/**
1233 * @brief Clean up QoS for a PON-side port
1234 *
1235 * Each SE must be disconnected from the hierarchy before freeing the
1236 * SE.
1237 *
1238 * @param unit SDK unit number
1239 * @param pon_port PON port number
1240 * @param pon_chan PON channel (10G vs. 1G)
1241 *
1242 **************************************************************************/
1243void bal_sw_dpp_port_qos_cleanup(int unit, bcm_port_t pon_port, bal_sw_dpp_qos_sched_pon_chan pon_chan)
1244{
1245 bcm_error_t sdk_rc = BCM_E_NONE;
1246 bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
1247 int wfq_lvl;
1248
1249 /* Parameter checks */
1250 BUG_ON(pon_port >= BAL_BCM_QOS_NUM_PON_PORTS);
1251 BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
1252
1253 /* Retrieve the QoS configuration for the specified port */
1254 p_port_qos = &gp_bal_bcm_qos_cfg->pon[pon_port][pon_chan];
1255
1256 /*
1257 * Clean up WFQ
1258 */
1259 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
1260 {
1261 /* Disconnect the scheduler from the one above */
1262 sdk_rc = bcm_cosq_gport_detach(unit,
1263 p_port_qos->pon_chan_scheduler,
1264 p_port_qos->wfq_scheduler[wfq_lvl],
1265 0);
1266 if (sdk_rc != BCM_E_NONE)
1267 {
1268 /* Error */
1269 BCM_LOG(ERROR, log_id_sw_util,
1270 "%s(): bcm_cosq_gport_detach for MAX Rate WFQ failed with %s for pon %u pon_chan %u wfq_lvl %u\n",
1271 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
1272
1273 /* Continue cleanup, don't halt processing because of this error */
1274 }
1275
1276 sdk_rc = bcm_cosq_gport_delete(unit, p_port_qos->wfq_scheduler[wfq_lvl]);
1277 if (sdk_rc != BCM_E_NONE)
1278 {
1279 /* Error */
1280 BCM_LOG(ERROR, log_id_sw_util,
1281 "%s(): bcm_cosq_gport_delete for MAX Rate WFQ failed with %s for pon %u pon_chan %u wfq_lvl %u\n",
1282 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
1283
1284 /* Continue cleanup, don't halt processing because of this error */
1285 }
1286 }
1287
1288 /*
1289 * Clean up SP HR
1290 */
1291
1292 /* Disconnect the scheduler from the one above */
1293 sdk_rc = bcm_cosq_gport_detach(unit,
1294 p_port_qos->pon_chan_scheduler,
1295 p_port_qos->sp_scheduler,
1296 0);
1297 if (sdk_rc != BCM_E_NONE)
1298 {
1299 /* Error */
1300 BCM_LOG(ERROR, log_id_sw_util,
1301 "%s(): bcm_cosq_gport_detach for MAX Rate SP HR failed with %s for pon %u pon_chan %u\n",
1302 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1303
1304 /* Continue cleanup, don't halt processing because of this error */
1305 }
1306
1307 sdk_rc = bcm_cosq_gport_delete(unit, p_port_qos->sp_scheduler);
1308 if (sdk_rc != BCM_E_NONE)
1309 {
1310 /* Error */
1311 BCM_LOG(ERROR, log_id_sw_util,
1312 "%s(): bcm_cosq_gport_delete for MAX Rate SP HR failed with %s for pon %u pon_chan %u\n",
1313 __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
1314
1315 /* Continue cleanup, don't halt processing because of this error */
1316 }
1317
1318}
1319
1320/**************************************************************************/
1321/**
1322 * @brief Configure a rate shaper and maximum burst size for a PON Link
1323 *
1324 * This function configures the rate and maximum burst size for the
1325 * specified shaper (MIN Rate vs. MAX Rate) for a PON Link (LLID).
1326 *
1327 * @param unit SDK unit number
1328 * @param p_service_cfg Pointer to the service configuration entry
1329 * @param sla_type Shaper type (MIN vs. MAX)
1330 * @param bandwidth Data rate in Kbps (i.e., token bucket fill rate)
1331 * @param max_burst Maximum burst size in bytes (i.e., token bucket size)
1332 *
1333 * @return bcmos_errno
1334 *
1335 **************************************************************************/
1336bcmos_errno bal_sw_dpp_qos_set_llid_bandwidth(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg,
1337 bal_sw_dpp_qos_sched_sla_type sla_type, uint32_t bandwidth, uint32_t max_burst)
1338{
1339 bcm_error_t sdk_rc = BCM_E_NONE;
1340 bcm_gport_t scheduler_gport;
1341
1342 /* Parameter checks */
1343 BUG_ON(p_service_cfg == NULL);
1344
1345 /* Get the scheduler gport that the VOQs are attached to (MIN vs. MAX) */
1346 if (sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)
1347 {
1348 scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
1349 }
1350 else
1351 {
1352 scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
1353 }
1354
1355 /* Set the Rate - drain rate */
1356 sdk_rc = bcm_cosq_gport_bandwidth_set(unit,
1357 scheduler_gport,
1358 0,
1359 0,
1360 bandwidth,
1361 0);
1362 if (sdk_rc != BCM_E_NONE)
1363 {
1364 /* Error */
1365 BCM_LOG(ERROR, log_id_sw_util,
1366 "%s(): bcm_cosq_gport_bandwidth_set failed with %s for %s gport 0x%x\n",
1367 __FUNCTION__, bcm_errmsg(sdk_rc), (sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)? "SLA_MIN_RATE":"SLA_MAX_RATE", scheduler_gport);
1368
1369 return BCM_ERR_INTERNAL;
1370 }
1371 else
1372 {
1373 BCM_LOG(INFO, log_id_sw_util,
1374 "%s() set gport 0x%x with %s of %d\n",
1375 __FUNCTION__, scheduler_gport,(sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)? "SLA_MIN_RATE":"SLA_MAX_RATE", bandwidth);
1376 }
1377
1378 /* Set the Burst - bucket size that hold the incoming frames */
1379 sdk_rc = bcm_cosq_control_set(unit,
1380 scheduler_gport,
1381 0,
1382 bcmCosqControlBandwidthBurstMax,
1383 max_burst);
1384 if (sdk_rc != BCM_E_NONE)
1385 {
1386 /* Error */
1387 BCM_LOG(ERROR, log_id_sw_util,
1388 "%s(): bcm_cosq_control_set for MaxBurst failed with %s for pon %u tid %u\n",
1389 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1390
1391 return BCM_ERR_INTERNAL;
1392 }
1393
1394 return BCM_ERR_OK;
1395}
1396
1397/**************************************************************************/
1398/**
1399 * @brief Configure downstream QoS for a PON Link (LLID)
1400 *
1401 * This function configures downstream QoS for a PON Link (LLID),
1402 * which is represented by a tunnel ID in ARAD. Please refer to the
1403 * "SCHEDULER MODEL" diagram at the top of this file. This function
1404 * configures the PON Link SE and queues (VOQ + VOQ Connector) for the
1405 * Link. The PON Link scheduler processes queues using strict
1406 * priority. This function configures four queues for the Link, which
1407 * is the smallest number of queues per LLID supported by
1408 * ARAD. However, the BAL BCM App currently only makes use of a single
1409 * queue.
1410 *
1411 * This function configures MIN (CIR) and MAX (EIR) rate shapers. If
1412 * the MIN rate is disabled (i.e., bandwidth configured with a value
1413 * of '0' kbps), the shaper is not "connected" to the port's MIN Rate
1414 * SE.
1415 *
1416 * @param unit SDK unit number
1417 * @param p_service_cfg Pointer to the service configuration entry
1418 *
1419 * @return bcmos_errno
1420 *
1421 **************************************************************************/
1422bcmos_errno bal_sw_dpp_llid_qos_config(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
1423{
1424 bcmos_errno rc = BCM_ERR_OK;
1425 bcm_error_t sdk_rc = BCM_E_NONE;
1426 bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
1427 int flags = 0;
1428 int cosq;
1429 bcm_cosq_gport_connection_t connection;
1430 bal_sw_dpp_qos_sched_pon_chan ds_pon_chan;
1431 bcm_gport_t scheduler_gport;
1432
1433 /* Parameter checks */
1434 BUG_ON(p_service_cfg == NULL);
1435
1436 /* Store the downstream PON rate, which will be used in several
1437 * places throughout this function.
1438 */
1439 ds_pon_chan = p_service_cfg->ds_qos.pon_chan;
1440
1441 /* Retrieve the QoS configuration for the specified port */
1442 p_port_qos = &gp_bal_bcm_qos_cfg->pon[p_service_cfg->pon_port][ds_pon_chan];
1443
1444 do /* Exception Block Start */
1445 {
1446 /* Allocate the voq ID from the free pool */
1447 if (ds_pon_chan == BAL_BCM_SCHED_PON_CHAN_10G)
1448 {
1449 rc = bal_sw_dpp_qos_alloc_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_10g, &p_service_cfg->ds_qos.voq_flow_id);
1450 }
1451 else
1452 {
1453 rc = bal_sw_dpp_qos_alloc_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_1g, &p_service_cfg->ds_qos.voq_flow_id);
1454 }
1455 if (rc != BCM_ERR_OK)
1456 {
1457 /* Error */
1458 BCM_LOG(ERROR, log_id_sw_util,
1459 "%s(): Unable to allocate voq ID for pon %u tid %u\n",
1460 __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1461
1462 rc = BCM_ERR_INTERNAL;
1463 break;
1464 }
1465
1466 /* In the BAL BCM App, the VOQ ID is equal to the voq ID */
1467 p_service_cfg->ds_qos.voq_id = p_service_cfg->ds_qos.voq_flow_id;
1468
1469 /*
1470 * PON Link scheduler (level 2)
1471 */
1472 if (p_service_cfg->ds_qos.min.rate > 0)
1473 {
1474 /* Create a composite, strict priority scheduler for this PON
1475 * Link. This is used to schedule between the queues assigned to
1476 * this PON Link.
1477 */
1478 flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_CLASS_MODE1_4SP | BCM_COSQ_GPORT_COMPOSITE;
1479 sdk_rc = bcm_cosq_gport_add(unit,
1480 0,
1481 1, /* Number of CoS levels */
1482 flags,
1483 &p_service_cfg->ds_qos.min.scheduler_gport);
1484 if (sdk_rc != BCM_E_NONE)
1485 {
1486 /* Error */
1487 BCM_LOG(ERROR, log_id_sw_util,
1488 "%s(): bcm_cosq_gport_add for PON Link SE failed with %s for pon %u tid %u\n",
1489 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1490
1491 rc = BCM_ERR_INTERNAL;
1492 break;
1493 }
1494
1495 /* A single priority on the Channel HR handles all MIN Rates (CIRs). */
1496 sdk_rc = bcm_cosq_gport_sched_set(unit,
1497 p_service_cfg->ds_qos.min.scheduler_gport,
1498 0,
1499 BCM_COSQ_SP1,
1500 0);
1501 if (sdk_rc != BCM_E_NONE)
1502 {
1503 /* Error */
1504 BCM_LOG(ERROR, log_id_sw_util,
1505 "%s(): bcm_cosq_gport_sched_set for Min Rate SE failed with %s for pon %u tid %u\n",
1506 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1507
1508 rc = BCM_ERR_INTERNAL;
1509 break;
1510 }
1511
1512 /* Attach the PON Link scheduler to the Channel HR. */
1513 sdk_rc = bcm_cosq_gport_attach(unit,
1514 p_port_qos->pon_chan_scheduler,
1515 p_service_cfg->ds_qos.min.scheduler_gport,
1516 0);
1517 if (sdk_rc != BCM_E_NONE)
1518 {
1519 /* Error */
1520 BCM_LOG(ERROR, log_id_sw_util,
1521 "%s(): bcm_cosq_gport_attach for Min Rate SE failed with %s for pon %u tid %u\n",
1522 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1523
1524 rc = BCM_ERR_INTERNAL;
1525 break;
1526 }
1527
1528 /* Save the gport of the parent SE (used for cleanup) */
1529 p_service_cfg->ds_qos.min.parent_gport = p_port_qos->pon_chan_scheduler;
1530
1531 /* Configure the MIN Rate shaper */
1532 rc = bal_sw_dpp_qos_set_llid_bandwidth(unit,
1533 p_service_cfg,
1534 BAL_BCM_SCHED_SLA_MIN_RATE,
1535 p_service_cfg->ds_qos.min.rate,
1536 p_service_cfg->ds_qos.min.burst);
1537 if (rc != BCM_ERR_OK)
1538 {
1539 /* Error */
1540 BCM_LOG(ERROR, log_id_sw_util,
1541 "%s(): Set MIN Rate shaper failed for pon %u tid %u\n",
1542 __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1543
1544 rc = BCM_ERR_INTERNAL;
1545 break;
1546 }
1547
1548 /* Set the gport for the MAX Rate scheduler */
1549 BCM_COSQ_GPORT_COMPOSITE_SF2_SET(p_service_cfg->ds_qos.max.scheduler_gport, p_service_cfg->ds_qos.min.scheduler_gport);
1550
1551 /* Set the scheduler gport that the VOQs are attached to */
1552 scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
1553 }
1554 else
1555 {
1556 /*
1557 * MAX Rate only (level 2)
1558 */
1559 flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_CLASS_MODE1_4SP;
1560 sdk_rc = bcm_cosq_gport_add(unit,
1561 0,
1562 1, /* Number of CoS levels */
1563 flags,
1564 &p_service_cfg->ds_qos.max.scheduler_gport);
1565 if (sdk_rc != BCM_E_NONE)
1566 {
1567 /* Error */
1568 BCM_LOG(ERROR, log_id_sw_util,
1569 "%s(): bcm_cosq_gport_add for PON Link SE failed with %s for pon %u tid %u\n",
1570 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1571
1572 rc = BCM_ERR_INTERNAL;
1573 break;
1574 }
1575
1576 /* Set the scheduler gport that the VOQs are attached to */
1577 scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
1578 }
1579
1580 /* The type of MAX Rate scheduling depends on what scheduling
1581 * mode is configured on the PON channel (SP vs. WFQ).
1582 */
1583 if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_SP)
1584 {
1585 /*
1586 * Strict Priority (SP) scheduling is being used
1587 */
1588
1589 /* Set the priority used for the attachment to the SP HR */
1590 sdk_rc = bcm_cosq_gport_sched_set(unit,
1591 p_service_cfg->ds_qos.max.scheduler_gport,
1592 0,
1593 BCM_COSQ_SP0 + p_service_cfg->ds_qos.max.traffic_priority,
1594 0);
1595 if (sdk_rc != BCM_E_NONE)
1596 {
1597 /* Error */
1598 BCM_LOG(ERROR, log_id_sw_util,
1599 "%s(): bcm_cosq_gport_sched_set for Max Rate SE failed with %s for pon %u tid %u\n",
1600 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1601
1602 rc = BCM_ERR_INTERNAL;
1603 break;
1604 }
1605
1606 /* Attach the PON Link scheduler to the SP HR. */
1607 sdk_rc = bcm_cosq_gport_attach(unit,
1608 p_port_qos->sp_scheduler,
1609 p_service_cfg->ds_qos.max.scheduler_gport,
1610 0);
1611 if (sdk_rc != BCM_E_NONE)
1612 {
1613 /* Error */
1614 BCM_LOG(ERROR, log_id_sw_util,
1615 "%s(): bcm_cosq_gport_attach for Max Rate SE failed with %s for pon %u tid %u\n",
1616 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1617
1618 rc = BCM_ERR_INTERNAL;
1619 break;
1620 }
1621
1622 /* Save the gport of the parent SE (used for cleanup) */
1623 p_service_cfg->ds_qos.max.parent_gport = p_port_qos->sp_scheduler;
1624 }
1625 else
1626 {
1627 /*
1628 * Weighted Fair Queuing (WFQ) scheduling is being used
1629 */
1630
1631 /* Set the priority used for the attachment to the FQ. */
1632 sdk_rc = bcm_cosq_gport_sched_set(unit,
1633 p_service_cfg->ds_qos.max.scheduler_gport,
1634 0,
1635 BCM_COSQ_SP0,
1636 0);
1637 if (sdk_rc != BCM_E_NONE)
1638 {
1639 /* Error */
1640 BCM_LOG(ERROR, log_id_sw_util,
1641 "%s(): bcm_cosq_gport_sched_set for Max Rate SE failed with %s for pon %u tid %u\n",
1642 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1643
1644 rc = BCM_ERR_INTERNAL;
1645 break;
1646 }
1647
1648 /* Attach the PON Link scheduler to the FQ. */
1649 sdk_rc = bcm_cosq_gport_attach(unit,
1650 p_port_qos->wfq_scheduler[p_service_cfg->ds_qos.max.traffic_priority],
1651 p_service_cfg->ds_qos.max.scheduler_gport,
1652 0);
1653 if (sdk_rc != BCM_E_NONE)
1654 {
1655 /* Error */
1656 BCM_LOG(ERROR, log_id_sw_util,
1657 "%s(): bcm_cosq_gport_attach for Max Rate SE failed with %s for pon %u tid %u\n",
1658 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1659
1660 rc = BCM_ERR_INTERNAL;
1661 break;
1662 }
1663
1664 /* Save the gport of the parent SE (used for cleanup) */
1665 p_service_cfg->ds_qos.max.parent_gport = p_port_qos->wfq_scheduler[p_service_cfg->ds_qos.max.traffic_priority];
1666 }
1667
1668 /* Configure the MAX Rate shaper */
1669 rc = bal_sw_dpp_qos_set_llid_bandwidth(unit,
1670 p_service_cfg,
1671 BAL_BCM_SCHED_SLA_MAX_RATE,
1672 p_service_cfg->ds_qos.max.rate,
1673 p_service_cfg->ds_qos.max.burst);
1674 if (rc != BCM_ERR_OK)
1675 {
1676 /* Error */
1677 BCM_LOG(ERROR, log_id_sw_util,
1678 "%s(): Set MAX Rate shaper failed for pon %u tid %u\n",
1679 __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1680
1681 break;
1682 }
1683
1684 /*
1685 * Create a VOQ connector (level 3)
1686 */
1687
1688 /* Create the VOQ connector object for a bundle of four queues */
1689 flags = BCM_COSQ_GPORT_VOQ_CONNECTOR | BCM_COSQ_GPORT_WITH_ID;
1690 BCM_COSQ_GPORT_VOQ_CONNECTOR_SET(p_service_cfg->ds_qos.voq_connector_gport, p_service_cfg->ds_qos.voq_flow_id);
1691 sdk_rc = bcm_cosq_gport_add(unit,
1692 p_port_qos->mod_gport,
1693 BAL_BCM_QOS_QUEUES_PER_LLID,
1694 flags,
1695 &p_service_cfg->ds_qos.voq_connector_gport);
1696 if (sdk_rc != BCM_E_NONE)
1697 {
1698 /* Error */
1699 BCM_LOG(ERROR, log_id_sw_util,
1700 "%s(): bcm_cosq_gport_add for VOQ Connector failed with %s for pon %u tid %u voq ID %u\n",
1701 __FUNCTION__, bcm_errmsg(sdk_rc),
1702 p_service_cfg->pon_port,
1703 p_service_cfg->tunnel_id,
1704 p_service_cfg->ds_qos.voq_flow_id);
1705
1706 rc = BCM_ERR_INTERNAL;
1707 break;
1708 }
1709
1710 /* Set the traffic class for each queue and attach the VOQ
1711 * connector to the PON Link scheduler.
1712 */
1713 for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
1714 {
1715 /* Set the traffic class for the queue */
1716 sdk_rc = bcm_cosq_gport_sched_set(unit,
1717 p_service_cfg->ds_qos.voq_connector_gport,
1718 cosq,
1719 BCM_COSQ_SP3 - cosq,
1720 0);
1721 if (sdk_rc != BCM_E_NONE)
1722 {
1723 /* Error */
1724 BCM_LOG(ERROR, log_id_sw_util,
1725 "%s(): bcm_cosq_gport_sched_set for VOQ Connector failed with %s for pon %u tid %u\n",
1726 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1727
1728 rc = BCM_ERR_INTERNAL;
1729 break;
1730 }
1731
1732 /* Attach the connection for each queue to the PON Link
1733 * scheduler, based on the traffic class.
1734 */
1735 sdk_rc = bcm_cosq_gport_attach(unit,
1736 scheduler_gport,
1737 p_service_cfg->ds_qos.voq_connector_gport,
1738 cosq);
1739 if (sdk_rc != BCM_E_NONE)
1740 {
1741 /* Error */
1742 BCM_LOG(ERROR, log_id_sw_util,
1743 "%s(): bcm_cosq_gport_attach for VOQ Connector failed with %s for pon %u tid %u\n",
1744 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1745
1746 rc = BCM_ERR_INTERNAL;
1747 break;
1748 }
1749 }
1750
1751 /* Exception Block - check for errors from the previous loop */
1752 if (rc != BCM_ERR_OK)
1753 {
1754 /* Error */
1755 break;
1756 }
1757
1758 /*
1759 * Create a VOQ (level 3)
1760 */
1761 flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_TM_FLOW_ID | BCM_COSQ_GPORT_WITH_ID;
1762 BCM_GPORT_UNICAST_QUEUE_GROUP_SET(p_service_cfg->ds_qos.voq_gport, p_service_cfg->ds_qos.voq_id);
1763 sdk_rc = bcm_cosq_gport_add(unit,
1764 p_port_qos->mod_gport,
1765 BAL_BCM_QOS_QUEUES_PER_LLID,
1766 flags,
1767 &p_service_cfg->ds_qos.voq_gport);
1768 if (sdk_rc != BCM_E_NONE)
1769 {
1770 /* Error */
1771 BCM_LOG(ERROR, log_id_sw_util,
1772 "%s(): bcm_cosq_gport_add for VOQ failed with %s for voq id %u, voq gport 0x%x, pon %u tid %u\n",
1773 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->ds_qos.voq_id, p_service_cfg->ds_qos.voq_gport,
1774 p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1775
1776 rc = BCM_ERR_INTERNAL;
1777 break;
1778 }
1779 /* QAX not support per Queue compensation */
1780#ifndef QAX_SWITCH
1781 /* Start - header adjust */
1782 {
1783 /*
1784 * If necessary, adjust the packet header overhead to match
1785 * the configured value.
1786 */
1787 int32_t val = 0;
1788 int32_t cfg_dpp_hdr_size = 0;
1789
1790 /* Calculate the expected DPP header size, which depends on
1791 * whether or not traffic is untagged, PB tagged, ICT
1792 * tagged, or Shared Vlan tagged. If the traffic is tagged
1793 * (either PB, ICT, or Shared Vlan), there are five fewer
1794 * bytes in the DPP header.
1795 */
1796 cfg_dpp_hdr_size = DEFAULT_QOS_DPP_PKT_HDR_SIZE;
1797 if (p_service_cfg->service_type != BAL_BCM_SVC_TYPE_IP)
1798 {
1799 cfg_dpp_hdr_size -= BAL_BCM_DPP_FLOWID_HDR_SIZE;
1800 }
1801
1802 /* If the traffic is ICT stack mode or Shared Vlan tagged, we
1803 * need to exclude the Vlan tag overhead from the bandwidth
1804 * calculation (i.e., add four bytes of overhead).
1805 */
1806 if (((p_service_cfg->service_type == BAL_BCM_SVC_TYPE_ICT) /*&& (p_service_cfg->ictStkType != BAL_BCM_ICT_STACK_TYPE_NONE)*/)||
1807 (p_service_cfg->service_type == BAL_BCM_SVC_TYPE_SHVLAN))
1808 {
1809 cfg_dpp_hdr_size += BAL_BCM_QOS_SINGLE_VLAN_TAG_HDR_SIZE;
1810 }
1811
1812 /* Get the header length */
1813 sdk_rc = bcm_cosq_control_get(unit,
1814 p_service_cfg->ds_qos.voq_gport,
1815 0,
1816 bcmCosqControlPacketLengthAdjust,
1817 &val);
1818 if (sdk_rc != BCM_E_NONE)
1819 {
1820 /* Error */
1821 BCM_LOG(ERROR, log_id_sw_util,
1822 "%s(): bcm_cosq_control_get for bcmCosqControlPacketLengthAdjust failed with %s for pon %u tid %u\n",
1823 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1824
1825 rc = BCM_ERR_INTERNAL;
1826 break;
1827 }
1828
1829 /* If current length does not match the configured length,
1830 * configure it now.
1831 */
1832 if (val != cfg_dpp_hdr_size)
1833 {
1834 /* Debug */
1835 BCM_LOG(INFO, log_id_sw_util,
1836 "%s(): modifying value of bcmCosqControlPacketLengthAdjust from %u to %u for pon %u tid %u\n",
1837 __FUNCTION__,
1838 val,
1839 cfg_dpp_hdr_size,
1840 p_service_cfg->pon_port,
1841 p_service_cfg->tunnel_id);
1842
1843 /* Adjust the packet length calculated above. This has to
1844 * be configured for each queue (cosq) in the voq
1845 * group.
1846 */
1847 for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
1848 {
1849 /* Adjust the packet length calculated above. */
1850 sdk_rc = bcm_cosq_control_set(unit,
1851 p_service_cfg->ds_qos.voq_gport,
1852 cosq,
1853 bcmCosqControlPacketLengthAdjust,
1854 cfg_dpp_hdr_size);
1855 if (sdk_rc != BCM_E_NONE)
1856 {
1857 /* Error */
1858 BCM_LOG(ERROR, log_id_sw_util,
1859 "%s(): bcm_cosq_control_set for bcmCosqControlPacketLengthAdjust for cosq %d failed with %s for pon %u tid %u\n",
1860 __FUNCTION__, cosq, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1861
1862 rc = BCM_ERR_INTERNAL;
1863 break;
1864 }
1865 }
1866
1867 /* Exception Block - check for errors from the previous loop */
1868 if (rc != BCM_ERR_OK)
1869 {
1870 /* Error */
1871 break;
1872 }
1873 }
1874 } /* End - header adjustment */
1875#endif
1876 /*
1877 * Connect a VOQ to a VOQ connector
1878 */
1879
1880 /* Connect VOQ to the VOQ connector for the ingress direction */
1881 connection.flags = BCM_COSQ_GPORT_CONNECTION_INGRESS;
1882 connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
1883 connection.voq = p_service_cfg->ds_qos.voq_gport;
1884 connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
1885
1886 sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
1887 if (sdk_rc != BCM_E_NONE)
1888 {
1889 /* Error */
1890 BCM_LOG(ERROR, log_id_sw_util,
1891 "%s(): bcm_cosq_gport_connection_set for INGRESS failed with %s for pon %u tid %u\n",
1892 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1893
1894 rc = BCM_ERR_INTERNAL;
1895 break;
1896 }
1897
1898 /* Connect VOQ to the VOQ connector for the egress direction */
1899 connection.flags = BCM_COSQ_GPORT_CONNECTION_EGRESS;
1900 connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
1901 connection.voq = p_service_cfg->ds_qos.voq_gport;
1902 connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
1903
1904 sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
1905 if (sdk_rc != BCM_E_NONE)
1906 {
1907 /* Error */
1908 BCM_LOG(ERROR, log_id_sw_util,
1909 "%s(): bcm_cosq_gport_connection_set for EGRESS failed with %s for pon %u tid %u\n",
1910 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1911
1912 rc = BCM_ERR_INTERNAL;
1913 break;
1914 }
1915
1916 } while(0); /* Exception Block - End */
1917
1918 /* Check for errors */
1919 if (rc != BCM_ERR_OK)
1920 {
1921 /* Failure */
1922 BCM_LOG(WARNING, log_id_sw_util,
1923 "Downstream QoS setup failed for pon %u tid %u\n",
1924 p_service_cfg->pon_port, p_service_cfg->tunnel_id);
1925
1926 /* Cleanup */
1927 bal_sw_dpp_llid_qos_cleanup(unit, p_service_cfg);
1928 }
1929
1930 return rc;
1931}
1932
1933/**************************************************************************/
1934/**
1935 * @brief Configure downstream QoS Port Map for a PON Link (LLID)
1936 *
1937 * This function configures downstream QoS Port Map for a PON Link
1938 * (LLID), which is represented by a tunnel ID in ARAD. This sets the
1939 * default traffic class (TC) value for VLAN tags being inserted or
1940 * modified.
1941 *
1942 * @param unit SDK unit number
1943 * @param p_service_cfg Pointer to the service configuration entry
1944 *
1945 * @return bcmos_errno
1946 *
1947 **************************************************************************/
1948bcmos_errno bal_sw_dpp_llid_set_qos_port_map(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
1949{
1950 bcmos_errno rc = BCM_ERR_OK;
1951 bcm_error_t sdk_rc = BCM_E_NONE;
1952 int i;
1953 /* Parameter checks */
1954 BUG_ON(p_service_cfg == NULL);
1955
1956 /* Set the QoS Port Map for the NNI LIF */
1957 for(i = 0; i < p_service_cfg->num_nni_gport; i++)
1958 {
1959 sdk_rc = bcm_qos_port_map_set(unit, p_service_cfg->nni_gport[i], gp_bal_bcm_qos_cfg->qos_port_map_id, -1);
1960 if (sdk_rc != BCM_E_NONE)
1961 {
1962 /* Error */
1963 BCM_LOG(ERROR, log_id_sw_util,
1964 "%s(): bcm_qos_port_map_set for nni_index %d returned with failure code '%s'\n",
1965 __FUNCTION__, i, bcm_errmsg(sdk_rc));
1966
1967 rc = BCM_ERR_INTERNAL;
1968 }
1969 }
1970
1971 return rc;
1972}
1973
1974/**************************************************************************/
1975/**
1976 * @brief Clean up QoS for a PON Link (LLID)
1977 *
1978 * Each SE and VOQ must be disconnected from the hierarchy before
1979 * freeing the SE and VOQ objects.
1980 *
1981 * @param unit SDK unit number
1982 * @param p_service_cfg Pointer to the service configuration entry
1983 *
1984 **************************************************************************/
1985void bal_sw_dpp_llid_qos_cleanup(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
1986{
1987 bcm_error_t sdk_rc = BCM_E_NONE;
1988 int cosq;
1989 bcm_cosq_gport_connection_t connection;
1990 bal_sw_dpp_qos_sched_pon_chan ds_pon_chan;
1991 bcm_gport_t scheduler_gport;
1992
1993 /* Parameter checks */
1994 BUG_ON(p_service_cfg == NULL);
1995
1996 /* Store the downstream PON rate, which will be used in several
1997 * places throughout this function.
1998 */
1999 ds_pon_chan = p_service_cfg->ds_qos.pon_chan;
2000
2001 /* Get the scheduler gport that the VOQs are attached to */
2002 if (p_service_cfg->ds_qos.min.rate > 0)
2003 {
2004 scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
2005 }
2006 else
2007 {
2008 scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
2009 }
2010
2011 /* Disconnect VOQ from the VOQ connector for the egress direction */
2012 connection.flags = BCM_COSQ_GPORT_CONNECTION_EGRESS | BCM_COSQ_GPORT_CONNECTION_INVALID;
2013 connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
2014 connection.voq = p_service_cfg->ds_qos.voq_gport;
2015 connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
2016
2017 sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
2018 if (sdk_rc != BCM_E_NONE)
2019 {
2020 /* Error */
2021 BCM_LOG(WARNING, log_id_sw_util,
2022 "%s(): bcm_cosq_gport_connection_set for DISCONNECT EGRESS failed with %s for pon %u tid %u\n",
2023 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2024
2025 /* Continue cleanup, don't halt processing because of this error */
2026 }
2027
2028 /* Disconnect VOQ from the VOQ connector for the ingress direction */
2029 connection.flags = BCM_COSQ_GPORT_CONNECTION_INGRESS | BCM_COSQ_GPORT_CONNECTION_INVALID;
2030 connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
2031 connection.voq = p_service_cfg->ds_qos.voq_gport;
2032 connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
2033
2034 sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
2035 if (sdk_rc != BCM_E_NONE)
2036 {
2037 /* Error */
2038 BCM_LOG(WARNING, log_id_sw_util,
2039 "%s(): bcm_cosq_gport_connection_set for DISCONNECT INGRESS failed with %s for pon %u tid %u\n",
2040 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2041
2042 /* Continue cleanup, don't halt processing because of this error */
2043 }
2044
2045 /* Delete the VOQ */
2046 sdk_rc = bcm_cosq_gport_delete(unit, p_service_cfg->ds_qos.voq_gport);
2047 if (sdk_rc != BCM_E_NONE)
2048 {
2049 /* Error */
2050 BCM_LOG(WARNING, log_id_sw_util,
2051 "%s(): bcm_cosq_gport_delete for VOQ failed with %s for pon %u tid %u\n",
2052 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2053
2054 /* Continue cleanup, don't halt processing because of this error */
2055 }
2056
2057 /* Disconnect the VOQ connector */
2058 for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
2059 {
2060 sdk_rc = bcm_cosq_gport_detach(unit,
2061 scheduler_gport,
2062 p_service_cfg->ds_qos.voq_connector_gport,
2063 cosq);
2064 if (sdk_rc != BCM_E_NONE)
2065 {
2066 /* Error */
2067 BCM_LOG(WARNING, log_id_sw_util,
2068 "%s(): bcm_cosq_gport_detach for VOQ Connector failed with %s for pon %u tid %u\n",
2069 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2070
2071 /* Continue cleanup, don't halt processing because of this error */
2072 }
2073 }
2074
2075 /* Delete the VOQ connector */
2076 sdk_rc = bcm_cosq_gport_delete(unit, p_service_cfg->ds_qos.voq_connector_gport);
2077 if (sdk_rc != BCM_E_NONE)
2078 {
2079 /* Error */
2080 BCM_LOG(WARNING, log_id_sw_util,
2081 "%s(): bcm_cosq_gport_delete for VOQ Connector failed with %s for pon %u tid %u\n",
2082 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2083
2084 /* Continue cleanup, don't halt processing because of this error */
2085 }
2086
2087 /* If a MIN rate was configured for this PON Link, disconnect the
2088 * PON Link scheduler from the MIN Rate scheduler.
2089 */
2090 if (p_service_cfg->ds_qos.min.rate > 0)
2091 {
2092 /* Detach from the parent SE */
2093 sdk_rc = bcm_cosq_gport_detach(unit,
2094 p_service_cfg->ds_qos.min.parent_gport,
2095 p_service_cfg->ds_qos.min.scheduler_gport,
2096 0);
2097 if (sdk_rc != BCM_E_NONE)
2098 {
2099 /* Error */
2100 BCM_LOG(WARNING, log_id_sw_util,
2101 "%s(): bcm_cosq_gport_detach for MIN Rate SE failed with %s for pon %u tid %u\n",
2102 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2103
2104 /* Continue cleanup, don't halt processing because of this error */
2105 }
2106 }
2107
2108 /* Disconnect the PON Link scheduler from the MAX Rate scheduler. */
2109 sdk_rc = bcm_cosq_gport_detach(unit,
2110 p_service_cfg->ds_qos.max.parent_gport,
2111 p_service_cfg->ds_qos.max.scheduler_gport,
2112 0);
2113 if (sdk_rc != BCM_E_NONE)
2114 {
2115 /* Error */
2116 BCM_LOG(WARNING, log_id_sw_util,
2117 "%s(): bcm_cosq_gport_detach for MAX Rate SE failed with %s for pon %u tid %u\n",
2118 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2119
2120 /* Continue cleanup, don't halt processing because of this error */
2121 }
2122
2123 /* Delete the PON Link scheduler */
2124 sdk_rc = bcm_cosq_gport_delete(unit, scheduler_gport);
2125 if (sdk_rc != BCM_E_NONE)
2126 {
2127 /* Error */
2128 BCM_LOG(WARNING, log_id_sw_util,
2129 "%s(): bcm_cosq_gport_delete for PON Link SE failed with %s for pon %u tid %u\n",
2130 __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
2131
2132 /* Continue cleanup, don't halt processing because of this error */
2133 }
2134
2135 /* Free the voq ID to the free pool */
2136 if (ds_pon_chan == BAL_BCM_SCHED_PON_CHAN_10G)
2137 {
2138 bal_sw_dpp_qos_free_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_10g, &p_service_cfg->ds_qos.voq_flow_id);
2139 }
2140 else
2141 {
2142 bal_sw_dpp_qos_free_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_1g, &p_service_cfg->ds_qos.voq_flow_id);
2143 }
2144}
2145
2146/**
2147 * @brief Clear statistics for a VOQ
2148 *
2149 * This function is used to clear VOQ counters
2150 *
2151 * @param unit SDK unit number
2152 * @param gport VOQ gport PON port number
2153 *
2154 */
2155void bal_sw_dpp_qos_clear_voq_stats(int unit, bcm_gport_t gport)
2156{
2157 int cosq;
2158
2159 /* Clear all VOQ counters for the VOQ group */
2160 for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
2161 {
2162 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportReceivedBytes, 0);
2163 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportReceivedPkts, 0);
2164 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportEnqueuedBytes, 0);
2165 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportEnqueuedPkts, 0);
2166 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportDroppedBytes, 0);
2167 bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportDroppedPkts, 0);
2168 }
2169}
2170
2171/**
2172 * @brief Display the qos configuration for each on the console (stdout)
2173 */
2174void bal_sw_dpp_print_all_port_qos(int unit)
2175{
2176 bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
2177 uint8_t port_num;
2178 uint8_t pon_chan;
2179 bcm_gport_t e2e_pon_gport;
2180 bcm_gport_t e2e_parent_gport;
2181 uint32_t min, flags;
2182 uint32_t bandwidth;
2183 int32_t max_burst;
2184 int32_t mode;
2185 int32_t weight;
2186 uint8_t wfq_lvl;
2187
2188 /* Display header */
2189 printf("Port\\Chan\tgport\t\tRate (kbps)\tMaxBurst (bytes)\tWeight\n");
2190 printf("---------\t-----\t\t-----------\t----------------\t------\n");
2191
2192 for (port_num=BAL_PON_PORT_START; port_num<=BAL_PON_PORT_END; port_num++)
2193 {
2194 /* Display Port info */
2195
2196
2197 BCM_COSQ_GPORT_E2E_PORT_SET(e2e_pon_gport, port_num);
2198
2199 if (BCM_E_NONE == bcm_fabric_port_get(unit,
2200 e2e_pon_gport,
2201 0,
2202 &e2e_parent_gport))
2203 {
2204 bandwidth = 0;
2205 max_burst = 0;
2206 weight = 0;
2207
2208 bcm_cosq_gport_bandwidth_get(unit,
2209 e2e_parent_gport,
2210 0,
2211 &min,
2212 &bandwidth,
2213 &flags);
2214
2215 printf("Port %u\t0x%08X\t%11u\t%16d\t%6d\n",
2216 port_num,
2217 0,
2218 bandwidth,
2219 0,
2220 0);
2221
2222 }
2223
2224 /* Display PON channel configuration */
2225 for (pon_chan = 0; pon_chan < BAL_BCM_SCHED_PON_CHAN_NUM; pon_chan++)
2226 {
2227 p_port_qos = &gp_bal_bcm_qos_cfg->pon[port_num][pon_chan];
2228
2229 bandwidth = 0;
2230 max_burst = 0;
2231 weight = 0;
2232
2233 /* Bandwidth (rate) */
2234 bcm_cosq_gport_bandwidth_get(unit,
2235 p_port_qos->pon_chan_scheduler,
2236 0,
2237 0,
2238 &bandwidth,
2239 0);
2240
2241 /* Max Burst */
2242 bcm_cosq_control_get(unit,
2243 p_port_qos->pon_chan_scheduler,
2244 0,
2245 bcmCosqControlBandwidthBurstMax,
2246 &max_burst);
2247
2248 printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
2249 (pon_chan == BAL_BCM_SCHED_PON_CHAN_10G) ? "10G" : "1G",
2250 p_port_qos->pon_chan_scheduler,
2251 bandwidth,
2252 max_burst,
2253 weight);
2254
2255 printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
2256 "MIN",
2257 p_port_qos->pon_chan_scheduler,
2258 0,
2259 0,
2260 0);
2261
2262 if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_SP)
2263 {
2264 printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
2265 " MAX (SP)",
2266 p_port_qos->sp_scheduler,
2267 0,
2268 0,
2269 0);
2270 }
2271 else
2272 {
2273 printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
2274 " MAX (WFQ)",
2275 0,
2276 0,
2277 0,
2278 0);
2279
2280 printf(" WFQ weight [");
2281 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
2282 {
2283 bcm_cosq_gport_sched_get(unit,
2284 p_port_qos->wfq_scheduler[wfq_lvl],
2285 0,
2286 &mode,
2287 &weight);
2288
2289 printf("w%u=%u(%u)", wfq_lvl, p_port_qos->pon_chan_weight_cfg[wfq_lvl], weight);
2290
2291 if (wfq_lvl != BAL_BCM_SCHED_WFQ_PRI_NUM - 1)
2292 {
2293 printf(", ");
2294 }
2295 }
2296 printf("]\n");
2297
2298 printf(" WFQ gports [");
2299 for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
2300 {
2301 printf("w%u=0x%08X", wfq_lvl, p_port_qos->wfq_scheduler[wfq_lvl]);
2302
2303 if (wfq_lvl != BAL_BCM_SCHED_WFQ_PRI_NUM - 1)
2304 {
2305 printf(", ");
2306 }
2307 }
2308 printf("]\n");
2309 }
2310 }
2311
2312 printf("\n");
2313 }
2314}
2315
2316/**
2317 * @brief Display the Flow/VOQ ID pool information
2318 */
2319void bal_sw_dpp_qos_print_flowid_pool(int unit)
2320{
2321 bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
2322 uint8_t count, free_count;
2323 int sdkVal;
2324
2325 printf("\nvoq ID Information:\n");
2326 printf(" Min 10G voq ID = %u\n", DEFAULT_QOS_VOQ_BASE_10G);
2327 printf(" Max 10G voq ID = %u\n", DEFAULT_QOS_VOQ_MAX_10G);
2328 printf(" Min 1G voq ID = %u\n", DEFAULT_QOS_VOQ_BASE_1G);
2329 printf(" Max 1G voq ID = %u\n", DEFAULT_QOS_VOQ_MAX_1G);
2330 bcm_fabric_control_get(unit, bcmFabricQueueMin, &sdkVal);
2331 printf(" Min VOQ ID = %d\n", sdkVal);
2332 bcm_fabric_control_get(unit ,bcmFabricQueueMax, &sdkVal);
2333 printf(" Max VOQ ID = %d\n", sdkVal);
2334
2335 printf("\n10G voq ID Table Info:\n");
2336 printf(" next_flow_id_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_10g.next_flow_id_value);
2337 printf(" max_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_10g.max_value);
2338 printf(" Free 10g voq IDs = ");
2339
2340 printf(" ");
2341 count = 0;
2342 free_count = 0;
2343 TAILQ_FOREACH(p_pool_entry, &gp_bal_bcm_qos_cfg->flow_id_pool_10g.free_table, entry)
2344 {
2345 printf("%d, ", p_pool_entry->flow_id);
2346
2347 if (count < 15)
2348 {
2349 count++;
2350 }
2351 else
2352 {
2353 printf("\n ");
2354 count = 0;
2355 }
2356 free_count++;
2357 }
2358 printf("\n");
2359 printf(" Number of Free 10g voq IDs = %d\n", free_count);
2360
2361 printf("\n1G voq ID Table Info:\n");
2362 printf(" next_flow_id_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_1g.next_flow_id_value);
2363 printf(" max_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_1g.max_value);
2364 printf(" Free 1g voq IDs = ");
2365
2366 printf(" ");
2367 count = 0;
2368 free_count = 0;
2369 TAILQ_FOREACH(p_pool_entry, &gp_bal_bcm_qos_cfg->flow_id_pool_1g.free_table, entry)
2370 {
2371 printf("%d, ", p_pool_entry->flow_id);
2372
2373 if (count < 15)
2374 {
2375 count++;
2376 }
2377 else
2378 {
2379 printf("\n ");
2380 count = 0;
2381 }
2382 free_count++;
2383 }
2384 printf("\n");
2385 printf(" Number of Free 1g voq IDs = %d\n", free_count);
2386}
2387
2388#endif /* TEST_SW_UTIL_LOOPBACK */
2389
2390/*@}*/