policer.c (1043208B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 */ 7 /* 8 * All Rights Reserved.$ 9 * 10 * Module: Service Meter(global meter) 11 * 12 * Purpose: 13 * These routines manage the handling of service meter(global meter) 14 * functionality 15 */ 16 #include <shared/bsl.h> 17 #include <shared/idxres_afl.h> 18 19 #include <sal/core/libc.h> 20 21 #include <soc/defs.h> 22 #include <soc/scache.h> 23 24 #include <bcm/policer.h> 25 #include <bcm/module.h> 26 #include <bcm_int/esw/policer.h> 27 #include <bcm_int/esw/port.h> 28 #include <bcm_int/esw/vlan.h> 29 #include <bcm_int/esw/firebolt.h> 30 #include <bcm_int/esw/switch.h> 31 #include <bcm_int/esw_dispatch.h> 32 #include <bcm_int/esw/field.h> 33 #include <bcm_int/esw/xgs4.h> 34 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(BCM_FIELD_SUPPORT) 35 #include <bcm/field.h> 36 #endif 37 38 #if defined(BCM_GREYHOUND2_SUPPORT) 39 #include <bcm_int/esw/greyhound2.h> 40 #endif /* BCM_GREYHOUND2_SUPPORT */ 41 42 #ifdef BCM_WARM_BOOT_SUPPORT 43 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 44 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 45 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 46 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 47 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_3 48 #endif 49 50 #define _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER _BCM_XGS_METER_FLAG_FP_POLICER 51 52 53 #define UNKNOWN_PKT 0x00 54 #define CONTROL_PKT 0x01 55 #define OAM_PKT 0x02 56 #define BFD_PKT 0x03 57 #define BPDU_PKT 0x04 58 #define ICNM_PKT 0x05 59 #define PKT_IS_1588 0x06 60 #define KNOWN_L2UC_PKT 0x07 61 62 #define UNKNOWN_L2UC_PKT 0x08 63 #define KNOWN_L2MC_PKT 0x09 64 #define UNKNOWN_L2MC_PKT 0x0a 65 #define L2BC_PKT 0x0b 66 #define KNOWN_L3UC_PKT 0x0c 67 #define UNKNOWN_L3UC_PKT 0x0d 68 #define KNOWN_IPMC_PKT 0x0e 69 #define UNKNOWN_IPMC_PKT 0x0f 70 71 #define KNOWN_MPLS_L2_PKT 0x10 72 #define UNKNOWN_MPLS_PKT 0x11 73 #define KNOWN_MPLS_L3_PKT 0x12 74 #define KNOWN_MPLS_PKT 0x13 75 #define KNOWN_MPLS_MULTICAST_PKT 0x14 76 #define KNOWN_MIM_PKT 0x15 77 #define UNKNOWN_MIM_PKT 0x16 78 #define KNOWN_TRILL_PKT 0x17 79 80 #define UNKNOWN_TRILL_PKT 0x18 81 #define KNOWN_NIV_PKT 0x19 82 #define UNKNOWN_NIV_PKT 0x1a 83 #define KNOWN_L2GRE_PKT 0x1b 84 #define KNOWN_VDL2_PKT 0x1c 85 #define KNOWN_FCOE_PKT 0x1d 86 #define UNKNOWN_FCOE_PKT 0x1e 87 #define SAT_DN_SAMP_RX 0x1f 88 #define FP_RESOLUTION_MAX 0x20 /* Max value */ 89 90 #define METER_REFRESH_INTERVAL 8 /* 7.8125usec */ 91 #define MIN_BURST_MULTIPLE 2 92 93 #define CONVERT_SECOND_TO_MICROSECOND 1000000 94 95 static soc_reg_t _pkt_attr_sel_key_reg[4] = { 96 ING_SVM_PKT_ATTR_SELECTOR_KEY_0r, 97 ING_SVM_PKT_ATTR_SELECTOR_KEY_1r, 98 ING_SVM_PKT_ATTR_SELECTOR_KEY_2r, 99 ING_SVM_PKT_ATTR_SELECTOR_KEY_3r 100 }; 101 102 STATIC sal_mutex_t global_meter_mutex[BCM_MAX_NUM_UNITS] = {NULL}; 103 104 /* Refer to FP_RESOLUTION */ 105 static uint8 kt_pkt_res[FP_RESOLUTION_MAX] = 106 { 107 0x0, 0x1, 0x0, 0x0, 0x2, 0x0, 0x0, 0x4, 108 0x5, 0x8, 0x9, 0x3, 0xa, 0xb, 0x7, 0x6, 109 0xe, 0xf, 0xd, 0xc, 0x12, 0x10, 0x11, 0, 110 0, 0, 0, 0, 0, 0, 0, 0 111 }; 112 #ifdef BCM_TRIUMPH3_SUPPORT 113 static uint8 tr3_pkt_res[FP_RESOLUTION_MAX] = 114 { 115 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x8, 116 0x9, 0xa, 0xb, 0xc, 0x10, 0x11, 0x12, 0x13, 117 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21, 0x28, 118 0x29, 0x30, 0x31, 0, 0, 0, 0, 0 119 }; 120 #endif 121 #ifdef BCM_KATANA2_SUPPORT 122 static uint8 kt2_pkt_res[FP_RESOLUTION_MAX] = 123 { 124 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x8, 125 0x9, 0xa, 0xb, 0xc, 0x10, 0x11, 0x12, 0x13, 126 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21, 0x28, 127 0x29, 0x30, 0x31, 0, 0, 0, 0, 0 128 }; 129 #endif 130 #ifdef BCM_SABER2_SUPPORT 131 static uint8 sb2_pkt_res[FP_RESOLUTION_MAX] = 132 { 133 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x8, 134 0x9, 0xa, 0xb, 0xc, 0x10, 0x11, 0x12, 0x13, 135 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21, 0x28, 136 0x29, 0x30, 0x31, 0, 0, 0, 0, 0x32 137 }; 138 #endif 139 #ifdef BCM_APACHE_SUPPORT 140 static uint8 ap_pkt_res[FP_RESOLUTION_MAX] = 141 { 142 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x8, 143 0x9, 0xa, 0xb, 0xc, 0x10, 0x11, 0x12, 0x13, 144 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x20, 0x21, 0x28, 145 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00 146 }; 147 #endif 148 149 static uint32 refresh_max[] = { 100, 125, 150, 175, 150 200, 225, 250, 275, 151 300, 325, 350, 375, 152 400, 425, 450, 475, 153 500, 525, 550, 575, 154 600, 625, 650, 675, 155 700, 725, 750, 775, 156 800, 0 }; 157 158 159 typedef enum pkt_cmprsd_attr_map_e { 160 pkt_attr_pri_cng_map, 161 pkt_attr_pkt_pri_map, 162 pkt_attr_port_map, 163 pkt_attr_tos_map, 164 pkt_attr_pkt_res_map, 165 pkt_attr_ip_pkt_map, /* no map for IP_PKT in h/w */ 166 pkt_attr_map_count 167 } pkt_cmprsd_attrs_map_t; 168 169 static _bcm_policer_pkt_attr_bit_pos_t kt_pkt_cmprsd_attr_map_bit_pos[] = { 170 {32,37}, {24,31}, {17,23}, {9,16}, 171 {1,8}, {0,0} 172 }; 173 #ifdef BCM_KATANA2_SUPPORT 174 static _bcm_policer_pkt_attr_bit_pos_t kt2_pkt_cmprsd_attr_map_bit_pos[] = { 175 {33,38}, {25,32}, {17,24}, {9,16}, 176 {1,8}, {0,0} 177 }; 178 #endif 179 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_SABER2_SUPPORT) 180 static _bcm_policer_pkt_attr_bit_pos_t sb2_pkt_cmprsd_attr_map_bit_pos[] = { 181 {32,37}, {24,31}, {17,23}, {9,16}, 182 {1,8}, {0,0} 183 }; 184 #endif 185 186 /* 187 * Global meter policer control data, one per device. 188 */ 189 static _global_meter_policer_control_t 190 **global_meter_policer_bookkeep[BCM_MAX_NUM_UNITS]; 191 /* 192 * Global meter horizontal alloc management data, one per device. 193 */ 194 static _global_meter_horizontal_alloc_t 195 *global_meter_hz_alloc_bookkeep[BCM_MAX_NUM_UNITS]; 196 197 static bcm_policer_svc_meter_bookkeep_mode_t 198 global_meter_offset_mode[BCM_MAX_NUM_UNITS]\ 199 [BCM_POLICER_SVC_METER_MAX_MODE]; 200 201 /* 202 * Global meter packet compressed attributes maps information per device. 203 */ 204 static _bcm_policer_pkt_compressed_attr_maps_t 205 *svm_pkt_compressed_attr_maps_g[BCM_MAX_NUM_UNITS]; 206 207 static _bcm_policer_global_meter_control_t 208 *bcm_esw_svm_control[BCM_MAX_NUM_UNITS]; 209 210 #define BCM_SVM_DEV_ATTR(unit) (&(bcm_esw_svm_control[(unit)]->svm_dev_attr_info)) 211 #define BCM_SVM_SOURCE(unit, index) (bcm_esw_svm_control[(unit)]->svm_source[(index)]) 212 213 static bcm_policer_global_meter_action_bookkeep_t 214 *global_meter_action_bookkeep[BCM_MAX_NUM_UNITS]; 215 216 /* Global meter module status - initialised or not initilised */ 217 static bcm_policer_global_meter_init_status_t 218 global_meter_status[BCM_MAX_NUM_UNITS] = {{0}}; 219 /* 220 * Global meter resource lock 221 */ 222 #define GLOBAL_METER_LOCK(unit) \ 223 sal_mutex_take(global_meter_mutex[unit], sal_mutex_FOREVER); 224 225 #define GLOBAL_METER_UNLOCK(unit) \ 226 sal_mutex_give(global_meter_mutex[unit]); 227 228 /* Handles for indexed allocation - one for meter action id allocation 229 and the other for policer id alloaction */ 230 shr_aidxres_list_handle_t 231 meter_action_list_handle[BCM_UNITS_MAX] = {NULL}; 232 shr_aidxres_list_handle_t meter_alloc_list_handle[BCM_UNITS_MAX]\ 233 [BCM_POLICER_GLOBAL_METER_MAX_POOL * \ 234 BCM_POLICER_GLOBAL_METER_MAX_BANKS_PER_POOL] = {{NULL}}; 235 236 #define CHECK_GLOBAL_METER_INIT(unit) \ 237 do { \ 238 if (!global_meter_status[unit].initialised) { \ 239 LOG_ERROR(BSL_LS_BCM_POLICER, \ 240 (BSL_META_U(unit, \ 241 "Global Meter Error:" \ 242 " not initialized\n"))); \ 243 return BCM_E_INIT; \ 244 } \ 245 } while (0) 246 247 /* Parameter NULL error handling */ 248 #define POL_CHECK_NULL_PARAMETER(_u_, _parameter_) \ 249 do { \ 250 if (NULL == (_parameter_)) { \ 251 LOG_ERROR(BSL_LS_BCM_POLICER, \ 252 (BSL_META_U((_u_), \ 253 "Error: NULL parameter\n"))); \ 254 return BCM_E_PARAM; \ 255 } \ 256 } while (0) 257 258 /* Device Information NULL error handling */ 259 #define POL_CHECK_NULL_DEV_INSTANCE(_u_, _instance_) \ 260 do { \ 261 if (NULL == (_instance_)) { \ 262 LOG_ERROR(BSL_LS_BCM_POLICER, \ 263 (BSL_META_U((_u_), \ 264 "Error: NULL driver function \n"))); \ 265 return BCM_E_UNAVAIL; \ 266 } \ 267 } while (0) 268 269 /* Function Enter/Leave Tracing */ 270 #define POL_FUNCTION_TRACE(_u_, _str_) \ 271 do { \ 272 LOG_VERBOSE(BSL_LS_BCM_POLICER, \ 273 (BSL_META_U((_u_), \ 274 "%s: " _str_ "\n"), __FUNCTION__)); \ 275 } while (0) 276 277 /* Function VERBOSE Tracing */ 278 #define POL_FUNCTION_DEBUG(_u_, fmt, _args_) \ 279 do { \ 280 LOG_DEBUG(BSL_LS_BCM_POLICER, \ 281 (BSL_META_U((_u_), \ 282 "%s: " fmt "\n"), __FUNCTION__, _args_)); \ 283 } while (0) 284 285 #define POL_MEM_ALLOC _GLOBAL_METER_XGS3_ALLOC 286 287 #define POL_MEM_FREE(_mem_) \ 288 do { \ 289 if (NULL != (_mem_)) { \ 290 sal_free(_mem_); \ 291 (_mem_) = NULL; \ 292 } \ 293 } while (0) 294 295 /* Convenient macro: get log2 for a non-zero power-of-2 number */ 296 #define POL_GET_LOG2(_n_, _power_) \ 297 do { \ 298 unsigned int _num = (unsigned int)(_n_); \ 299 for ((_power_) = -1; _num; (_power_)++) { \ 300 _num >>= 1; \ 301 } \ 302 } while (0) 303 304 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 305 #ifdef BCM_WARM_BOOT_SUPPORT 306 typedef struct bcm_policer_config_wb_s { 307 uint32 flags; /* BCM_POLICER_* Flags. */ 308 bcm_policer_mode_t mode; /* Policer mode. */ 309 uint32 ckbits_sec; /* Committed rate (kbits per sec). */ 310 uint32 cbits_sec_lower; /* Committed rate (lower digits; 0~999 311 bits per sec). */ 312 uint32 max_ckbits_sec; /* Maximum Committed rate (kbits per 313 sec), Applicable only for cascade 314 mode. */ 315 uint32 max_cbits_sec_lower; /* Maximum Committed rate (lower 316 digits; 317 0~999 bits per sec). */ 318 uint32 ckbits_burst; /* Committed burst size (kbits). */ 319 uint32 cbits_burst_lower; /* Committed burst size (lower digits; 320 0~999 bits). */ 321 uint32 pkbits_sec; /* Peak rate (kbits per sec). */ 322 uint32 pbits_sec_lower; /* Peak rate (lower digits; 0~999 bits 323 per sec). */ 324 uint32 max_pkbits_sec; /* Maximum Peak rate (kbits per sec), 325 Applicable only for cascade mode. */ 326 uint32 max_pbits_sec_lower; /* Maximum Peak rate (lower digits; 327 0~999 bits per sec). */ 328 uint32 pkbits_burst; /* Peak burst size (kbits). */ 329 uint32 pbits_burst_lower; /* Peak burst size (lower digits; 0~999 330 bits). */ 331 uint32 kbits_current; /* Current size (kbits). */ 332 uint32 bits_current_lower; /* Current size (lower digits; 0~999 333 bits). */ 334 uint32 action_id; /* Index of the global meter action 335 entry */ 336 uint32 sharing_mode; /* Meter sharing mode in case of Macro 337 meter of Envelop */ 338 uint32 entropy_id; /* If set, indicate the configuration 339 group the policer belongs to */ 340 bcm_policer_pool_t pool_id; /* Meter Pool Id of the current 341 policer */ 342 uint32 bucket_width; /* Bucket width in bits of the current 343 policer */ 344 uint32 token_gran; /* Token granularity of the current 345 policer */ 346 uint32 bucket_init_val; /* Initial bucket count of the current 347 policer */ 348 uint32 bucket_rollover_val; /* Rollover bucket count of the current 349 policer */ 350 bcm_core_t core_id; /* Device core on which to allocate the 351 policer */ 352 bcm_policer_t ncoflow_policer_id; /* Next lower priority committed 353 policer 354 ID to overflow to. Applicable in 355 Cascaded policer modes on MEF 10.3+ 356 compliant devices */ 357 bcm_policer_t npoflow_policer_id; /* Next lower priority peak policer ID 358 to overflow to. Applicable in 359 Cascaded and CoupledCascade policer 360 modes on MEF 10.3+ compliant 361 devices */ 362 uint32 average_pkt_size; /* Estimated average Ethernet packet 363 size (1 to 16383 Bytes) for more 364 accurate metering. */ 365 int mark_drop_as_black; /* For drop decision (no committed or 366 Excess credits), mark it as black 367 (otherwise, it will be marked as 368 red). */ 369 int color_resolve_profile; /* Input data for the resolved table. 370 */ 371 } bcm_policer_config_wb_t; 372 #endif /* BCM_WARM_BOOT_SUPPORT */ 373 374 #define BCMI_GLOBAL_METER_HASH_SIZE (0x100) 375 #define BCMI_GLOBAL_METER_HASH_MASK (0xff) 376 #define BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES (2048) 377 #define BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY (8) 378 #define BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY (4) 379 #define BCMI_POLICER_METER_GRAN_SHFIT (8) 380 #define BCMI_POLICER_METER_GRAN_LOWER_UNIT (1000) 381 #define BCMI_POLICER_INVALID_POLICER_ID (0) 382 383 #define BCMI_POLICER_SVC_METER_TCAM_SIZE \ 384 SOC_INFO(unit).global_meter_tcam_size 385 386 #define BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE \ 387 SOC_INFO(unit).global_meter_offset_mode_max 388 389 #define BCMI_POLICER_SVC_METER_ACTION_SIZE \ 390 SOC_INFO(unit).global_meter_action_size 391 392 #define BCMI_POLICER_SVC_METER_POOL_SIZE \ 393 SOC_INFO(unit).global_meter_size_of_pool 394 395 /* Global Meter platform-specific information */ 396 STATIC const bcmi_global_meter_dev_info_t 397 *bcmi_global_meter_dev_info[BCM_MAX_NUM_UNITS]; 398 399 /* Initialization flag for bcmi_global_meter_dev_info_t info structure */ 400 STATIC int 401 bcmi_global_meter_dev_info_initialized = FALSE; 402 403 #define BCM_SVM_DEV_INFO_GET(_u_) (bcmi_global_meter_dev_info[(_u_)]) 404 405 #define CHECK_GLOBAL_METER_DEV_INFO_INIT(_u_) \ 406 do { \ 407 if (!soc_feature(unit, soc_feature_global_meter_v2)) { \ 408 return BCM_E_UNAVAIL; \ 409 } \ 410 if (!BCM_SVM_DEV_INFO_GET(_u_)) { \ 411 return BCM_E_UNAVAIL; \ 412 } \ 413 } while (0) 414 415 typedef struct pkt_res_final_offset_s { 416 uint8 final_offset; 417 bcm_policer_group_mode_attr_pkt_type_t attr_pkt_type; 418 }pkt_res_final_offset_t; 419 420 static bcmi_global_meter_policer_control_t 421 **global_meter_policer_bk[BCM_MAX_NUM_UNITS]; 422 423 static bcmi_policer_global_meter_action_bk_t 424 *global_meter_action_bk[BCM_MAX_NUM_UNITS]; 425 426 shr_aidxres_list_handle_t 427 action_list_handle[BCM_MAX_NUM_UNITS] = { NULL }; 428 shr_aidxres_list_handle_t 429 policer_list_handle[BCM_MAX_NUM_UNITS] = { NULL }; 430 431 #define BCMI_POLICER_BK_GET(_u_) \ 432 (global_meter_policer_bk[(_u_)]) 433 434 #define BCMI_POLICER_HASH_BK_GET(_u_, _hash_) \ 435 (global_meter_policer_bk[(_u_)][(_hash_)]) 436 437 #define BCMI_ACTION_BK_GET(_u_) \ 438 (global_meter_action_bk[(_u_)]) 439 440 #define BCMI_ACTION_ID_BK_GET(_u_, _action_id_) \ 441 (global_meter_action_bk[(_u_)][(_action_id_)]) 442 443 #define BCMI_ACTION_LIST_HANDLE_GET(_u_) \ 444 (action_list_handle[(_u_)]) 445 446 #define BCMI_POLICER_LIST_HANDLE_GET(_u_) \ 447 (policer_list_handle[(_u_)]) 448 449 static bcmi_policer_svm_bk_t bcmi_bk_svm[BCM_MAX_NUM_UNITS]; 450 451 #define GLOBAL_METER_BK_LOCK(unit) \ 452 sal_mutex_take(bcmi_bk_svm[unit].mutex, sal_mutex_FOREVER); 453 454 #define GLOBAL_METER_BK_UNLOCK(unit) \ 455 sal_mutex_give(bcmi_bk_svm[unit].mutex); 456 457 #define BCMI_SVM_BK_GET(_u_) \ 458 (&bcmi_bk_svm[(_u_)]) 459 #define BCMI_SVM_OFFSET_MODE_BK_GET(_u_, _offset_mode_) \ 460 (&bcmi_bk_svm[(_u_)].offset_mode_v[_offset_mode_]) 461 462 /* SVM TCAM usage bitmap operations */ 463 #define BCMI_SVM_TCAM_INTF_GET(_u_, _intf_) \ 464 SHR_BITGET(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_)) 465 #define BCMI_SVM_TCAM_INTF_SET(_u_, _intf_) \ 466 SHR_BITSET(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_)) 467 #define BCMI_SVM_TCAM_INTF_CLR(_u_, _intf_) \ 468 SHR_BITCLR(BCMI_SVM_BK_GET(_u_)->tcam_intf_bitmap, (_intf_)) 469 470 /* SVM Offset Mode usage bitmap operations */ 471 #define BCMI_OFFSET_MODE_ID_INTF_GET(_u_, _intf_) \ 472 SHR_BITGET(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_)) 473 #define BCMI_OFFSET_MODE_ID_INTF_SET(_u_, _intf_) \ 474 SHR_BITSET(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_)) 475 #define BCMI_OFFSET_MODE_ID_INTF_CLR(_u_, _intf_) \ 476 SHR_BITCLR(BCMI_SVM_BK_GET(_u_)->offset_mode_intf_bitmap, (_intf_)) 477 478 /* SVM Mode ID & Offset Mode conversion */ 479 #define OFFSET_MODE_TO_MODE_ID(_offset_mode_) \ 480 (_offset_mode_ + 1) 481 482 #define MODE_ID_TO_OFFSET_MODE(_mode_id_) \ 483 (_mode_id_ - 1) 484 485 /* 486 * SVM Policer ID encoding: 487 * 1bit (reserved) + 3-bit mode_id (1~4) + hw_policer_idx 488 */ 489 #define BCMI_POLICER_GLOBAL_METER_INDEX_MASK 0x0FFFFFFF 490 #define BCMI_POLICER_GLOBAL_METER_MODE_MASK 0x70000000 491 #define BCMI_POLICER_GLOBAL_METER_MODE_SHIFT 28 492 493 #define POLICER_IDX_TO_POLICER_ID(_offset_mode_, _policer_idx_) \ 494 (_policer_idx_) | \ 495 (OFFSET_MODE_TO_MODE_ID(_offset_mode_) << \ 496 BCMI_POLICER_GLOBAL_METER_MODE_SHIFT) 497 498 #define POLICER_ID_TO_POLICER_IDX(_policer_id_) \ 499 ((_policer_id_) & BCMI_POLICER_GLOBAL_METER_INDEX_MASK) 500 501 #define POLICER_ID_MODE_ID_GET(_policer_id_) \ 502 (((_policer_id_) & BCMI_POLICER_GLOBAL_METER_MODE_MASK) >> \ 503 BCMI_POLICER_GLOBAL_METER_MODE_SHIFT) 504 505 #define POLICER_ID_OFFSET_MODE_GET(_policer_id_) \ 506 (MODE_ID_TO_OFFSET_MODE(POLICER_ID_MODE_ID_GET(_policer_id_))) 507 508 #define POLICER_ID_API_SECTION 1 509 #define MODE_ID_API_SECTION 1 510 #define ACTION_API_SECTION 1 511 512 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 513 514 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 515 #ifdef BCM_WARM_BOOT_SUPPORT 516 /* helper macro to copy content between policer and wb policer structures */ 517 #define POLICER_CONFIG_ASSIGN(_dst_, _src_ , _arg_) \ 518 (_dst_->_arg_ = _src_->_arg_) 519 /* 520 * Function: 521 * policer_config_copy_to_wb_policer_config 522 * Purpose: 523 * Copy the content of policer config from 524 * bcm_policer_config_t to 525 * bcm_policer_config_wb_t 526 * Parameters: 527 * bcm_policer_config_t (IN) - bcm API policer config. 528 * bcm_policer_config_wb_t (OUT) - policer config. for GH2 WB structure 529 * Returns: 530 * BCM_E_XXX 531 */ 532 STATIC void 533 policer_config_copy_to_wb_policer_config( 534 bcm_policer_config_t *pol_cfg, 535 bcm_policer_config_wb_t *pol_cfg_wb) 536 { 537 if (NULL == pol_cfg || NULL == pol_cfg_wb) { 538 return; 539 } 540 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, flags); 541 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, mode); 542 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ckbits_sec); 543 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, cbits_sec_lower); 544 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_ckbits_sec); 545 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_cbits_sec_lower); 546 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ckbits_burst); 547 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, cbits_burst_lower); 548 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pkbits_sec); 549 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pbits_sec_lower); 550 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_pkbits_sec); 551 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, max_pbits_sec_lower); 552 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pkbits_burst); 553 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pbits_burst_lower); 554 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, kbits_current); 555 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bits_current_lower); 556 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, action_id); 557 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, sharing_mode); 558 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, entropy_id); 559 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, pool_id); 560 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_width); 561 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, token_gran); 562 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_init_val); 563 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, bucket_rollover_val); 564 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, core_id); 565 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, ncoflow_policer_id); 566 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, npoflow_policer_id); 567 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, average_pkt_size); 568 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, mark_drop_as_black); 569 POLICER_CONFIG_ASSIGN(pol_cfg_wb, pol_cfg, color_resolve_profile); 570 } 571 572 /* 573 * Function: 574 * wb_policer_config_copy_to_policer_config 575 * Purpose: 576 * Copy the content of policer config from 577 * bcm_policer_config_wb_t to bcm_policer_config_t 578 * Parameters: 579 * bcm_policer_config_wb_t (IN) - policer config. for GH2 WB structure 580 * bcm_policer_config_t (OUT) - bcm API policer config. 581 * Returns: 582 * BCM_E_XXX 583 */ 584 STATIC void 585 wb_policer_config_copy_to_policer_config( 586 bcm_policer_config_wb_t *pol_cfg_wb, 587 bcm_policer_config_t *pol_cfg) 588 { 589 if (NULL == pol_cfg_wb || NULL == pol_cfg) { 590 return; 591 } 592 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, flags); 593 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, mode); 594 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ckbits_sec); 595 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, cbits_sec_lower); 596 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_ckbits_sec); 597 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_cbits_sec_lower); 598 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ckbits_burst); 599 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, cbits_burst_lower); 600 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pkbits_sec); 601 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pbits_sec_lower); 602 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_pkbits_sec); 603 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, max_pbits_sec_lower); 604 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pkbits_burst); 605 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pbits_burst_lower); 606 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, kbits_current); 607 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bits_current_lower); 608 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, action_id); 609 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, sharing_mode); 610 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, entropy_id); 611 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, pool_id); 612 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_width); 613 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, token_gran); 614 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_init_val); 615 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, bucket_rollover_val); 616 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, core_id); 617 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, ncoflow_policer_id); 618 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, npoflow_policer_id); 619 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, average_pkt_size); 620 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, mark_drop_as_black); 621 POLICER_CONFIG_ASSIGN(pol_cfg, pol_cfg_wb, color_resolve_profile); 622 } 623 #endif /* BCM_WARM_BOOT_SUPPORT */ 624 /* 625 * Function: 626 * bcmi_global_meter_dev_info_init 627 * Purpose: 628 * register Global Meter platform specific information & functions 629 * Parameters: 630 * unit - (IN) Unit number 631 * Returns: 632 * BCM_E_xxx 633 */ 634 STATIC int 635 bcmi_global_meter_dev_info_init(int unit) 636 { 637 bcm_error_t rv = BCM_E_UNAVAIL; 638 639 POL_FUNCTION_TRACE(unit, "IN"); 640 641 #if defined(BCM_GREYHOUND2_SUPPORT) 642 if (SOC_IS_GREYHOUND2(unit)) { 643 rv = bcmi_gh2_global_meter_dev_info_init(unit, 644 &(bcmi_global_meter_dev_info[unit])); 645 } else 646 #endif /* BCM_GREYHOUND2_SUPPORT */ 647 { 648 return BCM_E_UNAVAIL; 649 } 650 651 if (BCM_FAILURE(rv) || NULL == bcmi_global_meter_dev_info[unit]) { 652 /* No chip specific information initialized */ 653 LOG_WARN(BSL_LS_BCM_SWITCH, 654 (BSL_META_U(unit, 655 "Global Meter not supported:\n" 656 "dev_info_init failed.\n"))); 657 if (BCM_SUCCESS(rv)) { 658 return BCM_E_UNAVAIL; 659 } 660 return rv; 661 } 662 663 POL_FUNCTION_TRACE(unit, "OUT"); 664 return rv; 665 } 666 667 STATIC const char 668 *bcm_policer_group_mode_attr_t_str[bcmPolicerGroupModeAttrCount] = { 669 "Invalid String", /* Since bcm_policer_group_mode_attr_t start from 1 */ 670 "bcmPolicerGroupModeAttrUdf", /* 1 */ 671 "bcmPolicerGroupModeAttrFieldIngressColor", 672 "bcmPolicerGroupModeAttrIntPri", 673 "bcmPolicerGroupModeAttrVlan", 674 "bcmPolicerGroupModeAttrOuterPri", /* 5 */ 675 "bcmPolicerGroupModeAttrInnerPri", 676 "bcmPolicerGroupModeAttrPort", 677 "bcmPolicerGroupModeAttrTosDscp", 678 "bcmPolicerGroupModeAttrTosEcn", 679 "bcmPolicerGroupModeAttrPktType", /* 10 */ 680 "bcmPolicerGroupModeAttrIngNetworkGroup", 681 "bcmPolicerGroupModeAttrDrop", 682 "bcmPolicerGroupModeAttrPacketTypeIp", 683 "bcmPolicerGroupModeAttrPreemptable", 684 "bcmPolicerGroupModeAttrEtherType" /* 15 */ 685 }; 686 687 STATIC const char 688 *bcm_policer_group_mode_t_str[bcmPolicerGroupModeCount] = { 689 "bcmPolicerGroupModeSingle", /* 0 */ 690 "bcmPolicerGroupModeTrafficType", 691 "bcmPolicerGroupModeDlfAll", 692 "bcmPolicerGroupModeDlfIntPri", 693 "bcmPolicerGroupModeTyped", 694 "bcmPolicerGroupModeTypedAll", /* 5 */ 695 "bcmPolicerGroupModeTypedIntPri", 696 "bcmPolicerGroupModeSingleWithControl", 697 "bcmPolicerGroupModeTrafficTypeWithControl", 698 "bcmPolicerGroupModeDlfAllWithControl", 699 "bcmPolicerGroupModeDlfIntPriWithControl", /* 10 */ 700 "bcmPolicerGroupModeTypedWithControl", 701 "bcmPolicerGroupModeTypedAllWithControl", 702 "bcmPolicerGroupModeTypedIntPriWithControl", 703 "bcmPolicerGroupModeDot1P", 704 "bcmPolicerGroupModeIntPri", /* 15 */ 705 "bcmPolicerGroupModeIntPriCng", 706 "bcmPolicerGroupModeSvpType", 707 "bcmPolicerGroupModeDscp", 708 "bcmPolicerGroupModeCascade", 709 "bcmPolicerGroupModeCascadeWithCoupling", /* 20 */ 710 "bcmPolicerGroupModeInnerDot1P", 711 "bcmPolicerGroupModeEgressSingle", 712 "bcmPolicerGroupModeEgressIntPri", 713 "bcmPolicerGroupModeShortIntPri", 714 "bcmPolicerGroupModeIntPriCascade", /* 25 */ 715 "bcmPolicerGroupModeIntPriCascadeWithCoupling", 716 "bcmPolicerGroupModePreemptable", 717 "bcmPolicerGroupModeCascadeDroppedPktExclude" 718 }; 719 720 STATIC const uint32 721 attr_to_bit_selector[bcmPolicerGroupModeAttrCount] = { 722 /* Since bcm_policer_group_mode_attr_t start from 1 */ 723 0, 724 /* bcmPolicerGroupModeAttrUdf = 1 */ 725 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_UDF_ATTR_BITS, 726 /* bcmPolicerGroupModeAttrFieldIngressColor */ 727 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS, 728 /* bcmPolicerGroupModeAttrIntPri */ 729 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS, 730 /* bcmPolicerGroupModeAttrVlan */ 731 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS, 732 /* bcmPolicerGroupModeAttrOuterPri */ 733 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS, 734 /* bcmPolicerGroupModeAttrInnerPri */ 735 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS, 736 /* bcmPolicerGroupModeAttrPort */ 737 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS, 738 /* bcmPolicerGroupModeAttrTosDscp */ 739 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS, 740 /* bcmPolicerGroupModeAttrTosEcn */ 741 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS, 742 /* bcmPolicerGroupModeAttrPktType */ 743 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS, 744 /* bcmPolicerGroupModeAttrIngNetworkGroup = 11 */ 745 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS, 746 /* bcmPolicerGroupModeAttrDrop */ 747 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS, 748 /* bcmPolicerGroupModeAttrPacketTypeIp */ 749 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS, 750 /* bcmPolicerGroupModeAttrPreemptable */ 751 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PREEMPTABLE_ATTR_BITS, 752 /* bcmPolicerGroupModeAttrEtherType */ 753 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_ETHERTYPE_ATTR_BITS 754 }; 755 756 /* 757 * Function: 758 * check_attr_to_bit_selector 759 * Purpose: 760 * Check if attr_to_bit_selector is mapping correctly. 761 * Parameters: 762 * Returns: 763 * none 764 */ 765 STATIC void 766 check_attr_to_bit_selector(void) 767 { 768 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrUdf] == 769 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_UDF_ATTR_BITS); 770 771 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrOuterPri] == 772 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS); 773 774 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrInnerPri] == 775 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS); 776 777 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPort] == 778 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS); 779 780 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrTosDscp] == 781 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS); 782 783 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrTosEcn] == 784 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS); 785 786 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPktType] == 787 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS); 788 789 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrIngNetworkGroup] == 790 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS); 791 792 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrDrop] == 793 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS); 794 795 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPacketTypeIp] == 796 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS); 797 798 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrPreemptable] == 799 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PREEMPTABLE_ATTR_BITS); 800 801 assert(attr_to_bit_selector[bcmPolicerGroupModeAttrEtherType] == 802 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_ETHERTYPE_ATTR_BITS); 803 } 804 805 /* 806 * Function: 807 * pkt_tcam_attr_bits_t_init 808 * Purpose: 809 * Init pkt_tcam_attr_bits_t 810 * Parameters: 811 * pkt_attr_selectors - pointer instance to pkt_tcam_attr_bits_t 812 * Returns: 813 * BCM_E_XXX 814 */ 815 void 816 pkt_tcam_attr_bits_t_init(pkt_tcam_attr_bits_t *attr) 817 { 818 /* Parameter NULL error handling */ 819 if (NULL == attr) { 820 return; 821 } 822 823 sal_memset(attr, 0, sizeof(pkt_tcam_attr_bits_t)); 824 } 825 826 /* 827 * Function: 828 * bcmi_policer_tcam_attr_selectors_t_init 829 * Purpose: 830 * Init bcmi_policer_tcam_attr_selectors_t 831 * Parameters: 832 * pkt_attr_selectors - pointer instance to bcmi_policer_tcam_attr_selectors_t 833 * Returns: 834 * BCM_E_XXX 835 */ 836 STATIC void 837 bcmi_policer_tcam_attr_selectors_t_init( 838 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 839 { 840 /* Parameter NULL error handling */ 841 if (NULL == pkt_attr_selectors) { 842 return; 843 } 844 845 sal_memset(pkt_attr_selectors, 0, 846 sizeof(bcmi_policer_tcam_attr_selectors_t)); 847 } 848 849 /* 850 * Function: 851 * bcmi_policer_svm_offset_mode_bk_t_init 852 * Purpose: 853 * Init bcmi_policer_svm_offset_mode_bk_t 854 * Parameters: 855 * bk_svm_mode_info - pointer instance to bcmi_policer_svm_offset_mode_bk_t 856 * Returns: 857 * BCM_E_XXX 858 */ 859 STATIC void 860 bcmi_policer_svm_offset_mode_bk_t_init( 861 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info) 862 { 863 /* Parameter NULL error handling */ 864 if (NULL == bk_svm_mode_info) { 865 return; 866 } 867 bk_svm_mode_info->ref_cnt = 0; 868 bk_svm_mode_info->used = 0; 869 bk_svm_mode_info->is_custom_group = FALSE; 870 bk_svm_mode_info->group_mode = bcmPolicerGroupModeCount; 871 bk_svm_mode_info->group_mode_type = bcmPolicerGroupModeTypeCount; 872 bk_svm_mode_info->no_of_policers = 0; 873 bk_svm_mode_info->no_of_attr_selectors = 0; 874 bk_svm_mode_info->attr_selectors = NULL; 875 bk_svm_mode_info->pkt_attr_v_cnt = 0; 876 bk_svm_mode_info->pkt_attr_v = NULL; 877 } 878 879 /* 880 * Function: 881 * bcmi_global_meter_policer_control_t_init 882 * Purpose: 883 * Init bcmi_global_meter_policer_control_t 884 * Parameters: 885 * policer_control - pointer instance to bcmi_global_meter_policer_control_t 886 * Returns: 887 * BCM_E_XXX 888 */ 889 STATIC void 890 bcmi_global_meter_policer_control_t_init( 891 bcmi_global_meter_policer_control_t *policer_control) 892 { 893 /* Parameter NULL error handling */ 894 if (NULL == policer_control) { 895 return; 896 } 897 policer_control->pid = 0; 898 policer_control->pol_cfg = NULL; 899 policer_control->ref_count = 0; 900 policer_control->no_of_policers = 0; 901 policer_control->grp_mode = bcmPolicerGroupModeCount; 902 policer_control->next = NULL; 903 } 904 905 /* 906 * Function: 907 * bcmi_global_meter_dump_config 908 * Purpose: 909 * dump the config of Global Meter 910 * Parameters: 911 * unit - (IN) Unit number 912 * prefix - (IN) Prefix string for dump message 913 * config - (IN) Global Meter Config 914 * Returns: 915 * BCM_E_xxx 916 */ 917 STATIC void 918 bcmi_global_meter_dump_config( 919 int unit, 920 char *prefix, 921 bcm_policer_global_meter_config_t *config) 922 { 923 int i; 924 925 /* Input parameters check. */ 926 if ((NULL == prefix) || (NULL == config)) { 927 return; 928 } 929 930 if (bsl_check(bslLayerBcm, bslSourcePolicer, bslSeverityDebug, unit)) { 931 LOG_DEBUG(BSL_LS_BCM_POLICER, 932 (BSL_META_U(unit, 933 "[bcm_policer_global_meter_config_t]:\n"))); 934 LOG_DEBUG(BSL_LS_BCM_POLICER, 935 (BSL_META_U(unit, 936 "%s ifg_enable: %d.\n"), 937 prefix, 938 config->ifg_enable 939 )); 940 941 LOG_DEBUG(BSL_LS_BCM_POLICER, 942 (BSL_META_U(unit, 943 "%s source_order_count: %d.\n"), 944 prefix, 945 config->source_order_count 946 )); 947 948 for (i = 0; i < bcmPolicerGlobalMeterSourceCount; i++) { 949 LOG_DEBUG(BSL_LS_BCM_POLICER, 950 (BSL_META_U(unit, 951 "%s source_order[%d]: %d.\n"), 952 prefix, 953 i, 954 config->source_order[i] 955 )); 956 } 957 } 958 } 959 960 /* 961 * Function: 962 * bcmi_policer_tcam_attr_dump 963 * Purpose: 964 * dump the config of Global Meter 965 * Parameters: 966 * unit - (IN) Unit number 967 * prefix - (IN) Prefix string for dump message 968 * attr - (IN) Global Meter Config 969 * Returns: 970 * BCM_E_xxx 971 */ 972 STATIC void 973 bcmi_policer_tcam_attr_dump( 974 int unit, 975 char *prefix, 976 pkt_tcam_attr_bits_t *attr) 977 { 978 int i; 979 980 if ((NULL == prefix) || (NULL == attr)) { 981 return; 982 } 983 984 if (bsl_check(bslLayerBcm, bslSourcePolicer, bslSeverityDebug, unit)) { 985 LOG_DEBUG(BSL_LS_BCM_POLICER, 986 (BSL_META_U(unit, 987 "%s: ref_count %d, tcam_idx %d, final_offset %d\n"), 988 prefix, 989 attr->ref_count, 990 attr->tcam_idx, 991 attr->final_offset)); 992 993 LOG_DEBUG(BSL_LS_BCM_POLICER, 994 (BSL_META_U(unit, 995 "%s: attr_bits_selector 0x%8x\n"), 996 prefix, 997 attr->attr_bits_selector)); 998 LOG_DEBUG(BSL_LS_BCM_POLICER, 999 (BSL_META_U(unit, 1000 "%s: udf0 value 0x%4x, mask 0x%4x\n"), 1001 prefix, 1002 attr->udf.udf0, 1003 attr->udf_mask.udf0)); 1004 1005 LOG_DEBUG(BSL_LS_BCM_POLICER, 1006 (BSL_META_U(unit, 1007 "%s: udf1 value 0x%4x, mask 0x%4x\n"), 1008 prefix, 1009 attr->udf.udf1, 1010 attr->udf_mask.udf1)); 1011 1012 for (i = bcmPolicerGroupModeAttrUdf; 1013 i < bcmPolicerGroupModeAttrCount; i++) { 1014 if (attr->attr_bits_selector & attr_to_bit_selector[i]) { 1015 LOG_DEBUG(BSL_LS_BCM_POLICER, 1016 (BSL_META_U(unit, 1017 "%s: [%d] value %4x, mask %4x, %s\n"), 1018 prefix, 1019 i, 1020 attr->value[i], 1021 attr->value_mask[i], 1022 bcm_policer_group_mode_attr_t_str[i])); 1023 } 1024 } 1025 } 1026 } 1027 1028 /* 1029 * Function: 1030 * bcmi_policer_tcam_allocate_check 1031 * Purpose: 1032 * Check TCAM size is enough or not 1033 * Parameters: 1034 * Unit - (IN) unit number 1035 * pkt_attr_v_cnt - (IN) pkt_attr_v_cnt 1036 * Returns: 1037 * BCM_E_XXX 1038 */ 1039 STATIC bcm_error_t 1040 bcmi_policer_tcam_allocate_check(int unit, uint32 pkt_attr_v_cnt) 1041 { 1042 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 1043 1044 POL_FUNCTION_TRACE(unit, "IN"); 1045 1046 /* Initialization check */ 1047 CHECK_GLOBAL_METER_INIT(unit); 1048 bk_svm_info = BCMI_SVM_BK_GET(unit); 1049 1050 /* Check if total TCAM is enough or not */ 1051 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 1052 LOG_ERROR(BSL_LS_BCM_POLICER, 1053 (BSL_META_U(unit, 1054 "TCAM entry (%d) isn't enough, need %d TCAMs\n"), 1055 BCMI_POLICER_SVC_METER_TCAM_SIZE, 1056 pkt_attr_v_cnt)); 1057 return BCM_E_UNAVAIL; 1058 } 1059 1060 /* Check if empty TCAM is enough */ 1061 if (pkt_attr_v_cnt > bk_svm_info->empty_tcam_idx_cnt) { 1062 LOG_ERROR(BSL_LS_BCM_POLICER, 1063 (BSL_META_U(unit, 1064 "No enough empty TCAM(%d), need %d TCAMs\n"), 1065 bk_svm_info->empty_tcam_idx_cnt, 1066 pkt_attr_v_cnt)); 1067 return BCM_E_RESOURCE; 1068 } 1069 1070 POL_FUNCTION_TRACE(unit, "OUT"); 1071 return BCM_E_NONE; 1072 } 1073 1074 /* 1075 * Function: 1076 * bcmi_policer_tcam_configurate_hw 1077 * Purpose: 1078 * Check TCAM size is enough or not 1079 * Parameters: 1080 * Unit - (IN) unit number 1081 * pkt_attr_v_cnt - (IN) pkt_attr_v_cnt 1082 * Returns: 1083 * BCM_E_XXX 1084 */ 1085 STATIC bcm_error_t 1086 bcmi_policer_tcam_configurate_hw( 1087 int unit, 1088 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 1089 { 1090 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 1091 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 1092 int sel, sel2; 1093 1094 POL_FUNCTION_TRACE(unit, "IN"); 1095 1096 /* Parameter NULL error handling */ 1097 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 1098 1099 /* Initialization check */ 1100 CHECK_GLOBAL_METER_INIT(unit); 1101 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1102 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 1103 1104 /* Check if the chip specific function existed */ 1105 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_set); 1106 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_delete); 1107 1108 /* Configured TCAM HW with pkt_attr_selectors */ 1109 for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt; sel++) { 1110 rv = gm_dev_info->tcam_keys_set( 1111 unit, &pkt_attr_selectors->pkt_attr_v[sel]); 1112 if (BCM_FAILURE(rv)) { 1113 LOG_ERROR(BSL_LS_BCM_POLICER, 1114 (BSL_META_U(unit, 1115 "HW Operation failed(rv = %d)\n"), 1116 rv)); 1117 /* Reset the TCAM to defaul value */ 1118 for (sel2 = 0; sel2 <= sel; sel2++) { 1119 rv2 = gm_dev_info->tcam_keys_delete( 1120 unit, pkt_attr_selectors->pkt_attr_v[sel2].tcam_idx); 1121 if (BCM_FAILURE(rv2)) { 1122 /* tcam_keys_delete shouldn't return error, need to check */ 1123 LOG_ERROR(BSL_LS_BCM_POLICER, 1124 (BSL_META_U(unit, 1125 "tcam_keys_delete failed\n"))); 1126 return rv2; 1127 } 1128 } 1129 return rv; 1130 } 1131 } 1132 1133 POL_FUNCTION_TRACE(unit, "OUT"); 1134 return BCM_E_NONE; 1135 } 1136 1137 /* 1138 * Function: 1139 * bcmi_policer_offset_mode_validate 1140 * Purpose: 1141 * Validate the given offset_mode 1142 * Parameters: 1143 * Unit - (IN) unit number 1144 * offset_mode - (IN) Meter offset_mode 1145 * Returns: 1146 * BCM_E_XXX 1147 */ 1148 STATIC bcm_error_t 1149 bcmi_policer_offset_mode_validate(int unit, uint32 offset_mode) 1150 { 1151 POL_FUNCTION_TRACE(unit, "IN"); 1152 if (offset_mode >= BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE) 1153 { 1154 LOG_VERBOSE(BSL_LS_BCM_POLICER, 1155 (BSL_META_U(unit, 1156 "Invalid Offset mode.\n"))); 1157 POL_FUNCTION_TRACE(unit, "OUT Invalid Offset mode"); 1158 return BCM_E_PARAM; 1159 1160 } 1161 POL_FUNCTION_TRACE(unit, "OUT"); 1162 return BCM_E_NONE; 1163 } 1164 1165 /* 1166 * Function: 1167 * bcmi_policer_mode_id_validate 1168 * Purpose: 1169 * Validate the given mode_id 1170 * Parameters: 1171 * Unit - (IN) unit number 1172 * mode_id - (IN) mode_id 1173 * Returns: 1174 * BCM_E_XXX 1175 */ 1176 STATIC bcm_error_t 1177 bcmi_policer_mode_id_validate(int unit, uint32 mode_id) 1178 { 1179 int rv = BCM_E_NONE; 1180 uint32 offset_mode = 0; 1181 1182 POL_FUNCTION_TRACE(unit, "IN"); 1183 1184 /* Initialization check */ 1185 CHECK_GLOBAL_METER_INIT(unit); 1186 1187 /* Validate offset_mode */ 1188 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 1189 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1190 BCM_IF_ERROR_RETURN(rv); 1191 1192 POL_FUNCTION_TRACE(unit, "OUT"); 1193 return BCM_E_NONE; 1194 } 1195 1196 /* 1197 * Function: 1198 * bcmi_policer_svc_meter_reserve_mode 1199 * Purpose: 1200 * Internal function to allocate/reserve meter offset mode 1201 * Parameters: 1202 * Unit - (IN) unit number 1203 * offset_mode - (IN) Meter offset mode 1204 * group_mode - (IN) Policer group mode 1205 * group_mode_type - (IN) Policer group mode type 1206 * npolicers - (IN) Number of policers 1207 * pkt_attr_selectors - (IN) tcam packet attribute selectors 1208 * Returns: 1209 * BCM_E_XXX 1210 */ 1211 STATIC bcm_error_t 1212 bcmi_policer_svc_meter_reserve_mode( 1213 int unit, 1214 bcm_policer_svc_meter_mode_t offset_mode, 1215 bcm_policer_group_mode_t group_mode, 1216 bcm_policer_group_mode_type_t group_mode_type, 1217 int npolicers, 1218 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 1219 { 1220 bcm_error_t rv = BCM_E_NONE; 1221 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 1222 int sel; 1223 1224 POL_FUNCTION_TRACE(unit, "IN"); 1225 1226 /* Parameter NULL error handling */ 1227 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 1228 1229 /* Initialization check */ 1230 CHECK_GLOBAL_METER_INIT(unit); 1231 1232 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1233 BCM_IF_ERROR_RETURN(rv); 1234 1235 GLOBAL_METER_BK_LOCK(unit); 1236 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 1237 bk_svm_mode_info->ref_cnt = 0; 1238 bk_svm_mode_info->used = 1; 1239 bk_svm_mode_info->group_mode_type = group_mode_type; 1240 bk_svm_mode_info->group_mode = group_mode; 1241 bk_svm_mode_info->no_of_policers = npolicers; 1242 1243 POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v); 1244 bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt; 1245 POL_MEM_ALLOC( 1246 bk_svm_mode_info->pkt_attr_v, 1247 bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t), 1248 "pkt_attr_v in offset mode instance"); 1249 if (NULL == bk_svm_mode_info->pkt_attr_v) { 1250 GLOBAL_METER_BK_UNLOCK(unit); 1251 LOG_ERROR(BSL_LS_BCM_POLICER, 1252 (BSL_META_U(unit, 1253 "Unable to allocate memory for " 1254 "pkt_attr_v\n"))); 1255 return (BCM_E_MEMORY); 1256 } 1257 1258 for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt ; sel++) { 1259 sal_memcpy(&bk_svm_mode_info->pkt_attr_v[sel], 1260 &pkt_attr_selectors->pkt_attr_v[sel], 1261 sizeof(pkt_tcam_attr_bits_t)); 1262 } 1263 /* Configured TCAM HW with pkt_attr_selectors */ 1264 rv = bcmi_policer_tcam_configurate_hw(unit, pkt_attr_selectors); 1265 if (BCM_FAILURE(rv)) { 1266 GLOBAL_METER_BK_UNLOCK(unit); 1267 return rv; 1268 } 1269 1270 /* 1271 * if and only if using bcmi_esw_policer_group_mode_id_create need 1272 * to record attr_selectors 1273 */ 1274 bk_svm_mode_info->is_custom_group = FALSE; 1275 bk_svm_mode_info->no_of_attr_selectors = 0; 1276 POL_MEM_FREE(bk_svm_mode_info->attr_selectors); 1277 1278 GLOBAL_METER_BK_UNLOCK(unit); 1279 1280 POL_FUNCTION_TRACE(unit, "OUT"); 1281 return BCM_E_NONE; 1282 } 1283 1284 STATIC int 1285 bcmi_esw_policer_group_mode_id_delete( 1286 int unit, 1287 uint32 mode_id); 1288 1289 /* 1290 * Function: 1291 * bcmi_policer_svc_meter_unreserve_mode 1292 * Purpose: 1293 * Internal function to unreserve meter offset mode 1294 * Parameters: 1295 * Unit - (IN) unit number 1296 * offset_mode - (IN) Meter offset mode 1297 * Returns: 1298 * BCM_E_XXX 1299 */ 1300 STATIC bcm_error_t 1301 bcmi_policer_svc_meter_unreserve_mode( 1302 int unit, 1303 bcm_policer_svc_meter_mode_t offset_mode) 1304 { 1305 bcm_error_t rv = BCM_E_NONE; 1306 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 1307 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 1308 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 1309 int sel; 1310 uint32 d_tcam_idx; 1311 1312 POL_FUNCTION_TRACE(unit, "IN"); 1313 1314 /* Initialization check */ 1315 CHECK_GLOBAL_METER_INIT(unit); 1316 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1317 bk_svm_info = BCMI_SVM_BK_GET(unit); 1318 1319 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1320 BCM_IF_ERROR_RETURN(rv); 1321 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 1322 if (bk_svm_mode_info->used == 0) { 1323 LOG_WARN(BSL_LS_BCM_POLICER, 1324 (BSL_META_U(unit, 1325 "Wrong offset mode: Mode is not in use\n"))); 1326 return BCM_E_NOT_FOUND; 1327 } 1328 if (bk_svm_mode_info->ref_cnt != 0) { 1329 LOG_WARN(BSL_LS_BCM_POLICER, 1330 (BSL_META_U(unit, 1331 "Mode is still in use\n"))); 1332 return BCM_E_BUSY; 1333 } 1334 1335 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 1336 /* Check if the chip specific function existed */ 1337 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->tcam_keys_delete); 1338 /* Delete TCAM and Reset TCAM HW selector keys */ 1339 for (sel = 0; sel < bk_svm_mode_info->pkt_attr_v_cnt ; sel++) { 1340 d_tcam_idx = bk_svm_mode_info->pkt_attr_v[sel].tcam_idx; 1341 GLOBAL_METER_LOCK(unit); 1342 rv = gm_dev_info->tcam_keys_delete( 1343 unit, d_tcam_idx); 1344 GLOBAL_METER_UNLOCK(unit); 1345 if (BCM_FAILURE(rv)) { 1346 /* tcam_keys_delete shouldn't return error, need to check */ 1347 LOG_ERROR(BSL_LS_BCM_POLICER, 1348 (BSL_META_U(unit, 1349 "tcam_keys_delete failed\n"))); 1350 return rv; 1351 } 1352 GLOBAL_METER_BK_LOCK(unit); 1353 1354 /* Delete the TCAM idx */ 1355 BCMI_SVM_TCAM_INTF_CLR(unit, d_tcam_idx); 1356 1357 /* Update empty start and end */ 1358 if (d_tcam_idx < bk_svm_info->empty_tcam_idx_start) { 1359 bk_svm_info->empty_tcam_idx_start = d_tcam_idx; 1360 } else if (d_tcam_idx > bk_svm_info->empty_tcam_idx_end) { 1361 bk_svm_info->empty_tcam_idx_end = d_tcam_idx; 1362 } 1363 1364 bk_svm_info->empty_tcam_idx_cnt++; 1365 if (bk_svm_info->valid_tcam_idx_cnt > 0) { 1366 bk_svm_info->valid_tcam_idx_cnt--; 1367 } else { 1368 GLOBAL_METER_BK_UNLOCK(unit); 1369 LOG_WARN(BSL_LS_BCM_POLICER, 1370 (BSL_META_U(unit, 1371 "Need to check valid_tcam_idx_cnt logic\n"))); 1372 return BCM_E_INTERNAL; 1373 } 1374 GLOBAL_METER_BK_UNLOCK(unit); 1375 } 1376 1377 /* Delete the offset mode SW database */ 1378 rv = bcmi_esw_policer_group_mode_id_delete( 1379 unit, OFFSET_MODE_TO_MODE_ID(offset_mode)); 1380 1381 BCM_IF_ERROR_RETURN(rv); 1382 1383 POL_FUNCTION_DEBUG(unit, 1384 "Free %d TCAM", bk_svm_mode_info->pkt_attr_v_cnt); 1385 POL_FUNCTION_DEBUG(unit, 1386 "%d empty TCAM left", bk_svm_info->empty_tcam_idx_cnt); 1387 1388 POL_FUNCTION_TRACE(unit, "OUT"); 1389 return BCM_E_NONE; 1390 } 1391 1392 /* 1393 * Function: 1394 * bcmi_policer_svc_meter_delete_mode 1395 * Purpose: 1396 * Delete a meter offset mode 1397 * Parameters: 1398 * Unit - (IN) unit number 1399 * offset_mode - (IN) Meter offset mode 1400 * Returns: 1401 * BCM_E_XXX 1402 */ 1403 STATIC bcm_error_t 1404 bcmi_policer_svc_meter_delete_mode( 1405 int unit, 1406 bcm_policer_svc_meter_mode_t offset_mode) 1407 { 1408 bcm_error_t rv = BCM_E_NONE; 1409 1410 POL_FUNCTION_TRACE(unit, "IN"); 1411 1412 /* Initialization check */ 1413 CHECK_GLOBAL_METER_INIT(unit); 1414 1415 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1416 BCM_IF_ERROR_RETURN(rv); 1417 1418 rv = bcmi_policer_svc_meter_unreserve_mode(unit, offset_mode); 1419 BCM_IF_ERROR_RETURN(rv); 1420 1421 POL_FUNCTION_TRACE(unit, "OUT"); 1422 return rv; 1423 } 1424 1425 /* 1426 * Function: 1427 * bcmi_policer_svc_meter_inc_mode_ref_cnt 1428 * Purpose: 1429 * Internal function to increment meter offset mode usage count 1430 * Parameters: 1431 * Unit - (IN) unit number 1432 * offset_mode - (IN) Meter offset mode 1433 * Returns: 1434 * BCM_E_XXX 1435 */ 1436 STATIC bcm_error_t 1437 bcmi_policer_svc_meter_inc_mode_ref_cnt( 1438 uint32 unit, 1439 bcm_policer_svc_meter_mode_t offset_mode) 1440 { 1441 bcm_error_t rv = BCM_E_NONE; 1442 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 1443 1444 POL_FUNCTION_TRACE(unit, "IN"); 1445 1446 /* Initialization check */ 1447 CHECK_GLOBAL_METER_INIT(unit); 1448 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1449 1450 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1451 BCM_IF_ERROR_RETURN(rv); 1452 1453 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 1454 GLOBAL_METER_BK_LOCK(unit); 1455 bk_svm_mode_info->ref_cnt++; 1456 GLOBAL_METER_BK_UNLOCK(unit); 1457 POL_FUNCTION_TRACE(unit, "OUT"); 1458 return BCM_E_NONE; 1459 } 1460 1461 /* 1462 * Function: 1463 * bcmi_policer_svc_meter_dec_mode_ref_cnt 1464 * Purpose: 1465 * Internal function to decrement meter offset mode usage count 1466 * Parameters: 1467 * Unit - (IN) unit number 1468 * offset_mode - (IN) Meter offset mode 1469 * Returns: 1470 * BCM_E_XXX 1471 */ 1472 STATIC bcm_error_t 1473 bcmi_policer_svc_meter_dec_mode_ref_cnt( 1474 uint32 unit, 1475 bcm_policer_svc_meter_mode_t offset_mode) 1476 { 1477 bcm_error_t rv = BCM_E_NONE; 1478 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 1479 1480 POL_FUNCTION_TRACE(unit, "IN"); 1481 1482 /* Initialization check */ 1483 CHECK_GLOBAL_METER_INIT(unit); 1484 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1485 1486 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 1487 BCM_IF_ERROR_RETURN(rv); 1488 1489 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 1490 1491 GLOBAL_METER_BK_LOCK(unit); 1492 if (bk_svm_mode_info->ref_cnt > 0) { 1493 bk_svm_mode_info->ref_cnt--; 1494 } 1495 if (bk_svm_mode_info->is_custom_group) { 1496 /* Deletion of the mode is done through 1497 bcm_policer_group_mode_id_destroy */ 1498 GLOBAL_METER_BK_UNLOCK(unit); 1499 POL_FUNCTION_TRACE(unit, "OUT:is_custom_group"); 1500 return BCM_E_NONE; 1501 } 1502 if (bk_svm_mode_info->ref_cnt == 0) { 1503 rv = bcmi_policer_svc_meter_delete_mode(unit, offset_mode); 1504 } 1505 GLOBAL_METER_BK_UNLOCK(unit); 1506 POL_FUNCTION_TRACE(unit, "OUT"); 1507 return rv; 1508 } 1509 1510 #if MODE_ID_API_SECTION 1511 /* 1512 * Function: 1513 * bcmi_esw_policer_group_mode_fillup_tcam_idx 1514 * Purpose: 1515 * update offset mode 1516 * Parameters: 1517 * unit - (IN) unit number 1518 * pkt_attr_v - (IN) Packet TCAM attributes 1519 * Returns: 1520 * BCM_E_XXX 1521 */ 1522 STATIC int 1523 bcmi_esw_policer_group_mode_fillup_tcam_idx( 1524 int unit, 1525 pkt_tcam_attr_bits_t *pkt_attr_v) 1526 { 1527 uint32 e_tcam_idx; 1528 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 1529 1530 POL_FUNCTION_TRACE(unit, "IN"); 1531 1532 /* Parameter NULL error handling */ 1533 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_v); 1534 1535 /* Initialization check */ 1536 CHECK_GLOBAL_METER_INIT(unit); 1537 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1538 bk_svm_info = BCMI_SVM_BK_GET(unit); 1539 1540 GLOBAL_METER_BK_LOCK(unit); 1541 /* Check if empty tcam is enough */ 1542 if (bk_svm_info->empty_tcam_idx_cnt == 0) { 1543 GLOBAL_METER_BK_UNLOCK(unit); 1544 LOG_ERROR(BSL_LS_BCM_TSN, 1545 (BSL_META_U(unit, 1546 "Not enough tcam \n"))); 1547 return BCM_E_RESOURCE; 1548 } 1549 1550 for (e_tcam_idx = bk_svm_info->empty_tcam_idx_start; 1551 e_tcam_idx <= bk_svm_info->empty_tcam_idx_end; 1552 e_tcam_idx++) { 1553 if (BCMI_SVM_TCAM_INTF_GET(unit, e_tcam_idx) == 0) { 1554 /* fill with the found empty tcam idx */ 1555 BCMI_SVM_TCAM_INTF_SET(unit, e_tcam_idx); 1556 1557 /* Update valid start and end */ 1558 if (e_tcam_idx < bk_svm_info->valid_tcam_idx_start) { 1559 bk_svm_info->valid_tcam_idx_start = e_tcam_idx; 1560 } else if (e_tcam_idx > bk_svm_info->valid_tcam_idx_end) { 1561 bk_svm_info->valid_tcam_idx_end = e_tcam_idx; 1562 } 1563 bk_svm_info->empty_tcam_idx_start = e_tcam_idx + 1; 1564 bk_svm_info->valid_tcam_idx_cnt++; 1565 if (bk_svm_info->empty_tcam_idx_cnt > 0) { 1566 bk_svm_info->empty_tcam_idx_cnt--; 1567 } 1568 1569 pkt_attr_v->tcam_idx = e_tcam_idx; 1570 break; 1571 } 1572 } 1573 GLOBAL_METER_BK_UNLOCK(unit); 1574 POL_FUNCTION_TRACE(unit, "OUT"); 1575 return BCM_E_NONE; 1576 } 1577 1578 /* 1579 * Function: 1580 * bcmi_esw_policer_group_empty_mode_id_get 1581 * Purpose: 1582 * Get an empty mode_id 1583 * Parameters: 1584 * unit - (IN) Unit number 1585 * mode_id - (OUT) Meter Mode ID 1586 * Returns: 1587 * BCM_E_NONE - Success on finding a empty mode_id 1588 */ 1589 STATIC int 1590 bcmi_esw_policer_group_empty_mode_id_get( 1591 int unit, 1592 uint32 *mode_id) 1593 { 1594 bcm_error_t rv = BCM_E_UNAVAIL; 1595 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 1596 /* Empty offset_mode */ 1597 uint32 e_offset_mode; 1598 1599 POL_FUNCTION_TRACE(unit, "IN"); 1600 1601 /* Parameter NULL error handling */ 1602 POL_CHECK_NULL_PARAMETER(unit, mode_id); 1603 1604 /* Initialization check */ 1605 CHECK_GLOBAL_METER_INIT(unit); 1606 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1607 bk_svm_info = BCMI_SVM_BK_GET(unit); 1608 1609 /* Check if empty mode_id is enough */ 1610 if (bk_svm_info->empty_offset_mode_cnt == 0) { 1611 LOG_ERROR(BSL_LS_BCM_TSN, 1612 (BSL_META_U(unit, 1613 "Not enough empty mode_id\n"))); 1614 return BCM_E_RESOURCE; 1615 } 1616 1617 GLOBAL_METER_BK_LOCK(unit); 1618 /* Try to find an empty id */ 1619 for (e_offset_mode = bk_svm_info->empty_offset_mode_start; 1620 e_offset_mode <= bk_svm_info->empty_offset_mode_end; 1621 e_offset_mode++) { 1622 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, e_offset_mode) == 0) { 1623 1624 /* An empty id found, set bit map as used */ 1625 BCMI_OFFSET_MODE_ID_INTF_SET(unit, e_offset_mode); 1626 1627 /* Update valid start and end */ 1628 if (bk_svm_info->valid_offset_mode_cnt == 0) { 1629 bk_svm_info->valid_offset_mode_start = e_offset_mode; 1630 bk_svm_info->valid_offset_mode_end = e_offset_mode; 1631 } else if (e_offset_mode < 1632 bk_svm_info->valid_offset_mode_start) { 1633 bk_svm_info->valid_offset_mode_start = e_offset_mode; 1634 } else if (e_offset_mode > 1635 bk_svm_info->valid_offset_mode_end) { 1636 bk_svm_info->valid_offset_mode_end = e_offset_mode; 1637 } 1638 bk_svm_info->valid_offset_mode_cnt++; 1639 if (bk_svm_info->empty_offset_mode_cnt > 0) { 1640 bk_svm_info->empty_offset_mode_cnt--; 1641 } 1642 *mode_id = OFFSET_MODE_TO_MODE_ID(e_offset_mode); 1643 1644 /* Update the empty start, assume next one is real empty */ 1645 bk_svm_info->empty_offset_mode_start = e_offset_mode + 1; 1646 1647 /* An empty id found, break and return BCM_E_NONE */ 1648 rv = BCM_E_NONE; 1649 break; 1650 } else { 1651 /* Not empty id, and then update the bk empty start */ 1652 1653 /* Update the empty start, assume next one is real empty */ 1654 bk_svm_info->empty_offset_mode_start = e_offset_mode + 1; 1655 } 1656 } 1657 GLOBAL_METER_BK_UNLOCK(unit); 1658 1659 POL_FUNCTION_DEBUG(unit, "mode_id %d\n", *mode_id); 1660 POL_FUNCTION_TRACE(unit, "OUT"); 1661 return rv; 1662 } 1663 1664 /* 1665 * Function: 1666 * bcmi_esw_policer_group_mode_id_delete 1667 * Purpose: 1668 * Destroy Customized Policer Group mode with given mode_id. 1669 * Parameters: 1670 * unit - (IN) unit number 1671 * mode_id - (IN) Destroy Policer Group Mode with given mode_id 1672 * Returns: 1673 * BCM_E_NONE - Success on destroying the given mode_id 1674 */ 1675 STATIC int 1676 bcmi_esw_policer_group_mode_id_delete( 1677 int unit, 1678 uint32 mode_id) 1679 { 1680 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 1681 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 1682 uint32 destroy_offset_mode; 1683 uint32 n_valid_offset_mode; 1684 1685 POL_FUNCTION_TRACE(unit, "IN"); 1686 1687 POL_FUNCTION_DEBUG(unit, "mode_id %d\n", mode_id); 1688 1689 /* Initialization check */ 1690 CHECK_GLOBAL_METER_INIT(unit); 1691 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1692 1693 bk_svm_info = BCMI_SVM_BK_GET(unit); 1694 destroy_offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 1695 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, destroy_offset_mode); 1696 1697 /* Free allocate memory allocated in bcmi_policer_svm_offset_mode_bk_t */ 1698 POL_MEM_FREE(bk_svm_mode_info->attr_selectors); 1699 POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v); 1700 1701 /* Reset bcmi_policer_svm_offset_mode_bk_t */ 1702 bcmi_policer_svm_offset_mode_bk_t_init(bk_svm_mode_info); 1703 1704 GLOBAL_METER_BK_LOCK(unit); 1705 /* Destroy bit map */ 1706 BCMI_OFFSET_MODE_ID_INTF_CLR(unit, destroy_offset_mode); 1707 1708 /* Update empty start and end */ 1709 if (destroy_offset_mode < bk_svm_info->empty_offset_mode_start) { 1710 bk_svm_info->empty_offset_mode_start = destroy_offset_mode; 1711 } else if (destroy_offset_mode > bk_svm_info->empty_offset_mode_end) { 1712 bk_svm_info->empty_offset_mode_end = destroy_offset_mode; 1713 } 1714 1715 /* Update valid, find a next valid start or next valid end */ 1716 n_valid_offset_mode = destroy_offset_mode; 1717 if (bk_svm_info->valid_offset_mode_cnt > 1) { 1718 if (n_valid_offset_mode == bk_svm_info->valid_offset_mode_start) { 1719 do { 1720 n_valid_offset_mode++; 1721 } while (BCMI_OFFSET_MODE_ID_INTF_GET(unit, n_valid_offset_mode) == 0); 1722 bk_svm_info->valid_offset_mode_start = n_valid_offset_mode; 1723 } else if (n_valid_offset_mode == bk_svm_info->valid_offset_mode_end) { 1724 do { 1725 n_valid_offset_mode--; 1726 } while (BCMI_OFFSET_MODE_ID_INTF_GET(unit, n_valid_offset_mode) == 0); 1727 bk_svm_info->valid_offset_mode_end = n_valid_offset_mode; 1728 } 1729 } 1730 bk_svm_info->valid_offset_mode_cnt--; 1731 bk_svm_info->empty_offset_mode_cnt++; 1732 GLOBAL_METER_BK_UNLOCK(unit); 1733 1734 POL_FUNCTION_TRACE(unit, "OUT"); 1735 return BCM_E_NONE; 1736 } 1737 1738 /* 1739 * Function: 1740 * bcmi_esw_policer_group_mode_id_associate 1741 * Purpose: 1742 * This function is used to reserve svm meter mode and 1743 * update h/w register/table 1744 * Parameters: 1745 * unit - (IN) unit number 1746 * flags - (IN) flags 1747 * group_mode_type - (IN) type of group mode 1748 * pkt_attr_selectors - (IN) tcam packet attribute selectors 1749 * mode_id - (OUT) mode_id which used by policer group 1750 * Returns: 1751 * BCM_E_XXX 1752 */ 1753 STATIC int 1754 bcmi_esw_policer_group_mode_id_associate( 1755 int unit, 1756 uint32 flags, 1757 bcm_policer_group_mode_type_t group_mode_type, 1758 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors, 1759 uint32 *mode_id) 1760 { 1761 int rv = BCM_E_UNAVAIL; 1762 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 1763 int sel = 0; 1764 uint32 pkt_attr_v_cnt; 1765 1766 POL_FUNCTION_TRACE(unit, "IN"); 1767 1768 /* Parameter NULL error handling */ 1769 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 1770 POL_CHECK_NULL_PARAMETER(unit, mode_id); 1771 1772 /* Initialization check */ 1773 CHECK_GLOBAL_METER_INIT(unit); 1774 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1775 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 1776 1777 /* Check if the chip specific function existed */ 1778 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_type_supported); 1779 1780 rv = gm_dev_info->group_mode_type_supported(unit, group_mode_type); 1781 BCM_IF_ERROR_RETURN(rv); 1782 1783 pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt; 1784 1785 GLOBAL_METER_BK_LOCK(unit); 1786 /* Check if TCAM size if enough or not */ 1787 rv = bcmi_policer_tcam_allocate_check(unit, pkt_attr_v_cnt); 1788 if (BCM_FAILURE(rv)) { 1789 GLOBAL_METER_BK_UNLOCK(unit); 1790 return rv; 1791 } 1792 1793 /* Get an empty mode_id(offset_mode) */ 1794 rv = bcmi_esw_policer_group_empty_mode_id_get(unit, mode_id); 1795 if (BCM_FAILURE(rv)) { 1796 GLOBAL_METER_BK_UNLOCK(unit); 1797 LOG_ERROR(BSL_LS_BCM_TSN, 1798 (BSL_META_U(unit, 1799 "no empty mode_id(rv = %d)\n"), 1800 rv)); 1801 return rv; 1802 } 1803 1804 /* Allocate empty TCAM for each pkt_attr_v with mode and offset_mode */ 1805 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 1806 /* Assign an empty TCAM idx */ 1807 rv = bcmi_esw_policer_group_mode_fillup_tcam_idx( 1808 unit, &pkt_attr_selectors->pkt_attr_v[sel]); 1809 if (BCM_FAILURE(rv)) { 1810 /* 1811 * This case shouldn't happen since the TCAM size is enough 1812 * (already checked in above bcmi_policer_tcam_allocate_check) 1813 */ 1814 GLOBAL_METER_BK_UNLOCK(unit); 1815 return rv; 1816 } 1817 1818 /* Assign mode id */ 1819 pkt_attr_selectors->pkt_attr_v[sel].mode_id = *mode_id; 1820 /* Assign offset_mode */ 1821 pkt_attr_selectors->pkt_attr_v[sel].offset_mode = 1822 MODE_ID_TO_OFFSET_MODE(*mode_id); 1823 } 1824 GLOBAL_METER_BK_UNLOCK(unit); 1825 1826 POL_FUNCTION_TRACE(unit, "OUT"); 1827 return BCM_E_NONE; 1828 } 1829 1830 /* 1831 * Function: 1832 * bcmi_esw_policer_custom_group_mode_fillup_tcam_values 1833 * Purpose: 1834 * Fill up temporary tcam structures in appropriate order for efficient 1835 * management of user input 1836 * Parameters: 1837 * unit - (IN) unit number 1838 * pol_offset - (IN) flags 1839 * attr - (IN) group mode packet attr type 1840 * attr_value - (IN) attribute value 1841 * attr_value_mask - (IN) mask of attribute value 1842 * pkt_attr_v - (OUT) Packet TCAM attributes 1843 * Returns: 1844 * BCM_E_XXX 1845 */ 1846 STATIC int 1847 bcmi_esw_policer_custom_group_mode_fillup_tcam_values( 1848 int unit, 1849 uint32 pol_offset, 1850 bcm_policer_group_mode_attr_t attr, 1851 uint32 attr_value, 1852 uint32 attr_value_mask, 1853 pkt_tcam_attr_bits_t *pkt_attr_v) 1854 { 1855 POL_FUNCTION_TRACE(unit, "IN"); 1856 1857 /* Parameter NULL error handling */ 1858 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_v); 1859 1860 /* Initialization check */ 1861 CHECK_GLOBAL_METER_INIT(unit); 1862 1863 /* "OR" the added attr to current attr_bits_selector */ 1864 pkt_attr_v->attr_bits_selector |= attr_to_bit_selector[attr]; 1865 pkt_attr_v->value[attr] = attr_value; 1866 pkt_attr_v->value_mask[attr] = attr_value_mask; 1867 pkt_attr_v->final_offset = pol_offset; 1868 1869 POL_FUNCTION_TRACE(unit, "OUT"); 1870 return BCM_E_NONE; 1871 } 1872 1873 /* 1874 * Function: 1875 * bcmi_esw_policer_custom_group_mode_fillup_values 1876 * Purpose: 1877 * Fill up temporary structures in appropriate order for efficient 1878 * management of user input 1879 * Parameters: 1880 * unit - (IN) unit number 1881 * flags - (IN) flags 1882 * group_mode_type - (IN) type of group mode 1883 * total_policers - (IN) total policers 1884 * num_selectors - (IN) number of selectors 1885 * attr_selectors - (IN) list of attributes selectors 1886 * pkt_attr_selectors - (OUT) tcam packet attribute selectors 1887 * Returns: 1888 * BCM_E_XXX 1889 */ 1890 STATIC int 1891 bcmi_esw_policer_custom_group_mode_fillup_values( 1892 int unit, 1893 uint32 flags, 1894 bcm_policer_group_mode_type_t group_mode_type, 1895 uint32 total_policers, 1896 uint32 num_selectors, 1897 bcm_policer_group_mode_attr_selector_t *attr_selectors, 1898 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 1899 { 1900 int rv; 1901 uint32 sel = 0, mul_sel = 0; 1902 uint32 pol_offset = 0, max_pol_offset = 0; 1903 SHR_BITDCL *pol_offset_int_f_bitmap; 1904 uint32 shr_bitdcl_size; 1905 uint32 acutal_total_policers = 0; 1906 bcm_policer_group_mode_attr_t attr; 1907 uint32 attr_value = 0, attr_value_mask = 0; 1908 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 1909 1910 POL_FUNCTION_TRACE(unit, "IN"); 1911 1912 /* Parameter NULL error handling */ 1913 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 1914 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 1915 1916 /* Initialization check */ 1917 CHECK_GLOBAL_METER_INIT(unit); 1918 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 1919 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 1920 1921 /* Check if the chip specific function existed */ 1922 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_attr_validate); 1923 1924 /* Loop all selectors checking if group_mode_attr & value is supported */ 1925 for (sel = 0; sel < num_selectors; sel++) { 1926 if (BCM_POLICER_ATTR_MULTI & attr_selectors[sel].flags) { 1927 for (mul_sel = 0; 1928 mul_sel < attr_selectors[sel].multi_attr_count; 1929 mul_sel++) { 1930 rv = gm_dev_info->group_mode_attr_validate( 1931 unit, 1932 attr_selectors[sel].multi_attr[mul_sel], 1933 attr_selectors[sel].multi_attr_value[mul_sel]); 1934 BCM_IF_ERROR_RETURN(rv); 1935 } 1936 } else { 1937 rv = gm_dev_info->group_mode_attr_validate( 1938 unit, 1939 attr_selectors[sel].attr, 1940 attr_selectors[sel].attr_value); 1941 BCM_IF_ERROR_RETURN(rv); 1942 } 1943 } 1944 1945 #define POL_OFFSET_INTF_GET(_intf_) \ 1946 SHR_BITGET(pol_offset_int_f_bitmap, (_intf_)) 1947 #define POL_OFFSET_INTF_SET(_intf_) \ 1948 SHR_BITSET(pol_offset_int_f_bitmap, (_intf_)) 1949 1950 /* Allocate usage bitmap */ 1951 shr_bitdcl_size = SHR_BITALLOCSIZE(num_selectors); 1952 pol_offset_int_f_bitmap = 1953 sal_alloc(shr_bitdcl_size, "pol_offset_int_f_bitmap"); 1954 if (NULL == pol_offset_int_f_bitmap) { 1955 LOG_ERROR(BSL_LS_BCM_TSN, 1956 (BSL_META_U(unit, 1957 "bcmi_esw_tsn_init: failed to " 1958 "allocate memory\n"))); 1959 return BCM_E_MEMORY; 1960 } 1961 sal_memset(pol_offset_int_f_bitmap, 0, shr_bitdcl_size); 1962 1963 /* Loop all selectors */ 1964 for (sel = 0; sel < num_selectors; sel++) { 1965 1966 /* make sure the attr bits selector is 0 */ 1967 pkt_attr_selectors->pkt_attr_v[sel].attr_bits_selector = 0; 1968 1969 LOG_DEBUG(BSL_LS_BCM_POLICER, 1970 (BSL_META_U(unit, 1971 "pkt_attr_v [sel] %d:\n" 1972 "pol_offset %d, flags %d \n"), 1973 sel, 1974 attr_selectors[sel].policer_offset, 1975 attr_selectors[sel].flags)); 1976 /* Final Offset */ 1977 pol_offset = attr_selectors[sel].policer_offset; 1978 1979 /* Record used Policer Offset */ 1980 if (!POL_OFFSET_INTF_GET(pol_offset)) { 1981 /* new Policer Offset found, 1982 * the same policer offset means the same policer 1983 */ 1984 POL_OFFSET_INTF_SET(pol_offset); 1985 acutal_total_policers++; 1986 } 1987 1988 /* Record Maximum Policer Offset */ 1989 if (max_pol_offset < pol_offset) { 1990 max_pol_offset = pol_offset; 1991 } 1992 1993 /* Fill attributes */ 1994 if (BCM_POLICER_ATTR_MULTI & attr_selectors[sel].flags) { 1995 POL_FUNCTION_DEBUG( 1996 unit, "flag 0x%x, Multiple attributes for TCAM\n", 1997 attr_selectors[sel].flags); 1998 /* Multiple attributes for TCAM */ 1999 for (mul_sel = 0; 2000 mul_sel < attr_selectors[sel].multi_attr_count; 2001 mul_sel++) { 2002 2003 attr = attr_selectors[sel].multi_attr[mul_sel]; 2004 attr_value = 2005 attr_selectors[sel].multi_attr_value[mul_sel]; 2006 attr_value_mask = 2007 attr_selectors[sel].multi_attr_value_mask[mul_sel]; 2008 2009 /* Copy to pkt_attr_selectors */ 2010 bcmi_esw_policer_custom_group_mode_fillup_tcam_values( 2011 unit, 2012 pol_offset, 2013 attr, 2014 attr_value, 2015 attr_value_mask, 2016 &pkt_attr_selectors->pkt_attr_v[sel]); 2017 } 2018 } 2019 else { 2020 POL_FUNCTION_DEBUG( 2021 unit, "flag 0x%x, Single attribute for TCAM\n", 2022 attr_selectors[sel].flags); 2023 /* Single attribute for TCAM */ 2024 attr = attr_selectors[sel].attr; 2025 attr_value = attr_selectors[sel].attr_value; 2026 attr_value_mask = attr_selectors[sel].attr_value_mask; 2027 2028 /* Copy to pkt_attr_selectors */ 2029 bcmi_esw_policer_custom_group_mode_fillup_tcam_values( 2030 unit, 2031 pol_offset, 2032 attr, 2033 attr_value, 2034 attr_value_mask, 2035 &pkt_attr_selectors->pkt_attr_v[sel]); 2036 } 2037 (void)bcmi_policer_tcam_attr_dump( 2038 unit, "pkt_attr_v", &pkt_attr_selectors->pkt_attr_v[sel]); 2039 } 2040 2041 /* Give pkt_attr_v(TCAM entries) number */ 2042 pkt_attr_selectors->pkt_attr_v_cnt = num_selectors; 2043 2044 /* Check if total_policers equal to acutal_total_policers */ 2045 if (total_policers != acutal_total_policers) { 2046 POL_MEM_FREE(pol_offset_int_f_bitmap); 2047 LOG_ERROR(BSL_LS_BCM_POLICER, 2048 (BSL_META_U(unit, 2049 "total_policers(%d) should equal to " 2050 "acutal_total_policers(%d)\n"), 2051 total_policers, 2052 acutal_total_policers)); 2053 return BCM_E_PARAM; 2054 } 2055 2056 /* Check Maximum Policer Offset match calculated total policer # */ 2057 if (max_pol_offset != acutal_total_policers - 1) { 2058 POL_MEM_FREE(pol_offset_int_f_bitmap); 2059 LOG_ERROR(BSL_LS_BCM_POLICER, 2060 (BSL_META_U(unit, 2061 "Maximum policer offset(%d) should equal to" 2062 " acutal_total_policers(%d) - 1.\n" 2063 "Please check 'policer_offset' of " 2064 " bcm_policer_group_mode_attr_selector_t\n"), 2065 max_pol_offset, 2066 max_pol_offset)); 2067 return BCM_E_PARAM; 2068 } 2069 2070 /* Free memory */ 2071 POL_MEM_FREE(pol_offset_int_f_bitmap); 2072 2073 /* Give total policer number */ 2074 pkt_attr_selectors->total_policers = total_policers; 2075 2076 POL_FUNCTION_DEBUG(unit, "total_policers %d", total_policers); 2077 2078 POL_FUNCTION_TRACE(unit, "OUT"); 2079 return BCM_E_NONE; 2080 } 2081 2082 /* 2083 * Function: 2084 * bcmi_esw_policer_custom_group_mode_id_existed_check 2085 * Purpose: 2086 * Check if given attribute selectors list is already 2087 * configured or not 2088 * Parameters: 2089 * unit - (IN) unit number 2090 * flags - (IN) flags 2091 * group_mode_type - (IN) type of group mode 2092 * num_selectors - (IN) number of selectors 2093 * attr_selectors - (IN) list of attributes selectors 2094 * mode_id - (OUT) pointer to meter mode_id 2095 * Returns: 2096 * BCM_E_XXX 2097 */ 2098 STATIC int 2099 bcmi_esw_policer_custom_group_mode_id_existed_check( 2100 uint32 unit, 2101 uint32 flags, 2102 bcm_policer_group_mode_type_t group_mode_type, 2103 uint32 num_selectors, 2104 bcm_policer_group_mode_attr_selector_t *attr_selectors, 2105 uint32 *mode_id) 2106 { 2107 uint32 offset_mode_idx = 0; 2108 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 2109 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 2110 2111 POL_FUNCTION_TRACE(unit, "IN"); 2112 2113 /* Parameter NULL error handling */ 2114 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 2115 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2116 2117 /* Initialization check */ 2118 CHECK_GLOBAL_METER_INIT(unit); 2119 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2120 bk_svm_info = BCMI_SVM_BK_GET(unit); 2121 2122 /* No valid mode_id */ 2123 if (bk_svm_info->valid_offset_mode_cnt == 0) { 2124 POL_FUNCTION_TRACE(unit, "OUT No valid mode_id"); 2125 return BCM_E_NONE; 2126 } 2127 2128 /* Loop through all valid mode_id and try to find a match one */ 2129 for (offset_mode_idx = bk_svm_info->valid_offset_mode_start; 2130 offset_mode_idx <= bk_svm_info->valid_offset_mode_end; 2131 offset_mode_idx++) { 2132 2133 if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode_idx)) { 2134 continue; 2135 } 2136 2137 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode_idx); 2138 if (bk_svm_mode_info->group_mode_type != group_mode_type) { 2139 continue; 2140 } 2141 2142 /* Check num selectors */ 2143 if (bk_svm_mode_info->no_of_attr_selectors == num_selectors) { 2144 if (bk_svm_mode_info->attr_selectors != NULL) { 2145 if (sal_memcmp(&attr_selectors[0], 2146 bk_svm_mode_info->attr_selectors, 2147 sizeof(bcm_policer_group_mode_attr_selector_t) * 2148 num_selectors) == 0) { 2149 *mode_id = OFFSET_MODE_TO_MODE_ID(offset_mode_idx); 2150 LOG_ERROR(BSL_LS_BCM_POLICER, 2151 (BSL_META_U(unit, 2152 "Same attr_selectors existed"))); 2153 return BCM_E_EXISTS; 2154 } 2155 } 2156 } 2157 } 2158 POL_FUNCTION_TRACE(unit, "OUT"); 2159 return BCM_E_NONE; 2160 } 2161 2162 /* 2163 * Function: 2164 * bcmi_esw_policer_custom_group_mode_id_info_update 2165 * Purpose: 2166 * update offset mode info 2167 * Parameters: 2168 * unit - (IN) unit number 2169 * mode_id - (IN) meter mode_id 2170 * group_mode_type - (IN) type of group mode 2171 * num_selectors - (IN) number of selectors 2172 * attr_selectors - (IN) list of attributes selectors 2173 * pkt_attr_selectors - (IN) tcam packet attribute selectors 2174 * Returns: 2175 * BCM_E_XXX 2176 */ 2177 STATIC int 2178 bcmi_esw_policer_custom_group_mode_id_info_update( 2179 int unit, 2180 bcm_policer_svc_meter_mode_t mode_id, 2181 bcm_policer_group_mode_type_t group_mode_type, 2182 int num_selectors, 2183 bcm_policer_group_mode_attr_selector_t *attr_selectors, 2184 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 2185 { 2186 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 2187 int sel; 2188 uint32 total_policers; 2189 uint32 offset_mode; 2190 2191 POL_FUNCTION_TRACE(unit, "IN"); 2192 2193 /* Parameter NULL error handling */ 2194 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 2195 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 2196 2197 /* Initialization check */ 2198 CHECK_GLOBAL_METER_INIT(unit); 2199 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2200 2201 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 2202 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 2203 2204 total_policers = pkt_attr_selectors->total_policers; 2205 2206 bk_svm_mode_info->no_of_policers = total_policers; 2207 bk_svm_mode_info->is_custom_group = TRUE; 2208 bk_svm_mode_info->group_mode_type = group_mode_type; 2209 bk_svm_mode_info->used = 1; 2210 2211 POL_FUNCTION_DEBUG(unit, "mode_id %d", mode_id); 2212 POL_FUNCTION_DEBUG(unit, "offset_mode %d", offset_mode); 2213 POL_FUNCTION_DEBUG(unit, "group_mode_type %d", group_mode_type); 2214 POL_FUNCTION_DEBUG(unit, "num_selectors %d", num_selectors); 2215 POL_FUNCTION_DEBUG(unit, "total_policers %d", total_policers); 2216 2217 /* Store bcm_policer_group_mode_attr_selector_t start */ 2218 2219 /* Free memory */ 2220 POL_MEM_FREE(bk_svm_mode_info->attr_selectors); 2221 2222 bk_svm_mode_info->no_of_attr_selectors = num_selectors; 2223 2224 POL_MEM_ALLOC( 2225 bk_svm_mode_info->attr_selectors, 2226 num_selectors * sizeof(bcm_policer_group_mode_attr_selector_t), 2227 "attr selectors"); 2228 if (NULL == bk_svm_mode_info->attr_selectors) { 2229 LOG_ERROR(BSL_LS_BCM_POLICER, 2230 (BSL_META_U(unit, 2231 "Unable to allocate memory for " 2232 "attr_selectors\n"))); 2233 return BCM_E_MEMORY; 2234 } 2235 sal_memcpy(bk_svm_mode_info->attr_selectors, 2236 attr_selectors, 2237 sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors); 2238 /* Store bcm_policer_group_mode_attr_selector_t end */ 2239 2240 /* Store pkt_tcam_attr_bits_t start */ 2241 POL_MEM_FREE(bk_svm_mode_info->pkt_attr_v); 2242 2243 bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_selectors->pkt_attr_v_cnt; 2244 2245 POL_MEM_ALLOC( 2246 bk_svm_mode_info->pkt_attr_v, 2247 bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t), 2248 "pkt_attr_v in offset mode instance"); 2249 if (NULL == bk_svm_mode_info->pkt_attr_v) { 2250 LOG_ERROR(BSL_LS_BCM_POLICER, 2251 (BSL_META_U(unit, 2252 "Unable to allocate memory for " 2253 "pkt_attr_v\n"))); 2254 return (BCM_E_MEMORY); 2255 } 2256 2257 for (sel = 0; sel < pkt_attr_selectors->pkt_attr_v_cnt ; sel++) { 2258 sal_memcpy(&bk_svm_mode_info->pkt_attr_v[sel], 2259 &pkt_attr_selectors->pkt_attr_v[sel], 2260 sizeof(pkt_tcam_attr_bits_t)); 2261 } 2262 /* Configured TCAM HW with pkt_attr_selectors */ 2263 BCM_IF_ERROR_RETURN( 2264 bcmi_policer_tcam_configurate_hw(unit, pkt_attr_selectors)); 2265 2266 /* Store pkt_tcam_attr_bits_t end */ 2267 POL_FUNCTION_TRACE(unit, "OUT"); 2268 return BCM_E_NONE; 2269 } 2270 2271 /* 2272 * Function: 2273 * bcmi_esw_policer_custom_group_mode_id_create 2274 * Purpose: 2275 * This function is used to configure customized group mode 2276 * Parameters: 2277 * unit - (IN) unit number 2278 * flags - (IN) flags 2279 * group_mode_type - (IN) type of group mode 2280 * total_policers - (IN) total policers 2281 * num_selectors - (IN) number of selectors 2282 * attr_selectors - (IN) list of attributes selectors 2283 * mode_id - (OUT) pointer to meter mode_id 2284 * Returns: 2285 * BCM_E_XXX 2286 */ 2287 STATIC int 2288 bcmi_esw_policer_custom_group_mode_id_create( 2289 int unit, 2290 uint32 flags, 2291 bcm_policer_group_mode_type_t group_mode_type, 2292 uint32 total_policers, 2293 uint32 num_selectors, 2294 bcm_policer_group_mode_attr_selector_t *attr_selectors, 2295 uint32 *mode_id) 2296 { 2297 int rv = BCM_E_UNAVAIL; 2298 bcmi_policer_tcam_attr_selectors_t pkt_attr_selectors; 2299 2300 POL_FUNCTION_TRACE(unit, "IN"); 2301 2302 /* Parameter NULL error handling */ 2303 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 2304 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2305 2306 /* Initialization check */ 2307 CHECK_GLOBAL_METER_INIT(unit); 2308 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2309 2310 /* Check if mode info already exists */ 2311 rv = bcmi_esw_policer_custom_group_mode_id_existed_check( 2312 unit, flags, group_mode_type, 2313 num_selectors, attr_selectors, mode_id); 2314 BCM_IF_ERROR_RETURN(rv); 2315 2316 (void)bcmi_policer_tcam_attr_selectors_t_init(&pkt_attr_selectors); 2317 POL_MEM_ALLOC( 2318 pkt_attr_selectors.pkt_attr_v, 2319 sizeof(pkt_tcam_attr_bits_t) * BCMI_POLICER_SVC_METER_TCAM_SIZE, 2320 "allocate pkt_attr_v"); 2321 2322 /* Create temportary pkt information from selectors */ 2323 rv = bcmi_esw_policer_custom_group_mode_fillup_values( 2324 unit, flags, group_mode_type, 2325 total_policers, num_selectors, attr_selectors, 2326 &pkt_attr_selectors); 2327 if (BCM_FAILURE(rv)) { 2328 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 2329 return rv; 2330 } 2331 2332 GLOBAL_METER_LOCK(unit); 2333 /* Add a new mode_id associated with pkt_attr_selectors information */ 2334 rv = bcmi_esw_policer_group_mode_id_associate(unit, 2335 flags, group_mode_type, &pkt_attr_selectors, mode_id); 2336 if (BCM_FAILURE(rv)) { 2337 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 2338 GLOBAL_METER_UNLOCK(unit); 2339 return rv; 2340 } 2341 2342 /* Update above pkt information to bookkeeping */ 2343 rv = bcmi_esw_policer_custom_group_mode_id_info_update( 2344 unit, *mode_id, group_mode_type, num_selectors, 2345 attr_selectors, &pkt_attr_selectors); 2346 if (BCM_FAILURE(rv)) { 2347 /* Delete the offset mode SW database */ 2348 bcmi_esw_policer_group_mode_id_delete(unit, *mode_id); 2349 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 2350 GLOBAL_METER_UNLOCK(unit); 2351 return rv; 2352 } 2353 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 2354 GLOBAL_METER_UNLOCK(unit); 2355 2356 POL_FUNCTION_TRACE(unit, "OUT"); 2357 return rv; 2358 } 2359 2360 /* 2361 * Function: 2362 * bcmi_esw_policer_group_mode_id_existed_check 2363 * Purpose: 2364 * Check if given attribute selectors list is already 2365 * configured or not 2366 * Parameters: 2367 * unit - (IN) unit number 2368 * group_mode - (IN) Policer group mode 2369 * npolicers - (IN) Number of policers 2370 * pkt_attr_selectors - (IN) tcam packet attribute selectors 2371 * mode_id - (OUT) pointer to found existed mode_id 2372 * existed - (OUT) existed or not existed 2373 * Returns: 2374 * BCM_E_XXX 2375 */ 2376 STATIC int 2377 bcmi_esw_policer_group_mode_id_existed_check( 2378 int unit, 2379 bcm_policer_group_mode_t group_mode, 2380 int npolicers, 2381 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors, 2382 uint32 *mode_id, 2383 int *existed) 2384 { 2385 uint32 offset_mode_idx = 0; 2386 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 2387 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 2388 2389 POL_FUNCTION_TRACE(unit, "IN"); 2390 2391 /* Parameter NULL error handling */ 2392 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 2393 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2394 POL_CHECK_NULL_PARAMETER(unit, existed); 2395 2396 POL_FUNCTION_DEBUG(unit, "group_mode %d", group_mode); 2397 POL_FUNCTION_DEBUG(unit, "group_mode %s", 2398 bcm_policer_group_mode_t_str[group_mode]); 2399 POL_FUNCTION_DEBUG(unit, "npolicers %d", npolicers); 2400 2401 *existed = FALSE; 2402 2403 /* Initialization check */ 2404 CHECK_GLOBAL_METER_INIT(unit); 2405 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2406 bk_svm_info = BCMI_SVM_BK_GET(unit); 2407 2408 /* No valid mode_id */ 2409 if (bk_svm_info->valid_offset_mode_cnt == 0) { 2410 /* no exsiting mode_id, thus don't need to check */ 2411 POL_FUNCTION_TRACE(unit, "OUT"); 2412 return BCM_E_NONE; 2413 } 2414 2415 /* Loop through all valid mode_id and try to find a match one */ 2416 for (offset_mode_idx = bk_svm_info->valid_offset_mode_start; 2417 offset_mode_idx <= bk_svm_info->valid_offset_mode_end; 2418 offset_mode_idx++) { 2419 2420 if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode_idx)) { 2421 continue; 2422 } 2423 2424 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode_idx); 2425 if (bk_svm_mode_info->group_mode != group_mode) { 2426 continue; 2427 } 2428 if (bk_svm_mode_info->no_of_policers != npolicers) { 2429 continue; 2430 } 2431 *mode_id = OFFSET_MODE_TO_MODE_ID(offset_mode_idx); 2432 *existed = TRUE; 2433 POL_FUNCTION_TRACE(unit, "OUT"); 2434 return BCM_E_NONE; 2435 } 2436 POL_FUNCTION_TRACE(unit, "OUT"); 2437 return BCM_E_NONE; 2438 } 2439 2440 /* 2441 * Function: 2442 * bcmi_esw_policer_group_mode_id_create 2443 * Purpose: 2444 * Create Customized Policer Group mode for given Policer Attributes 2445 * Parameters: 2446 * unit - (IN) unit number 2447 * flags - (IN) flags 2448 * group_mode_type - (IN) modes of policer group creation - 2449 * normal/cascade/cascade with coupling. 2450 * total_policers - (IN) Total Policers in Policer Group Mode 2451 * num_selectors - (IN) Number of Selectors for policer Group Mode 2452 * attr_selectors - (IN) Attribute Selectors for Policer Group Mode 2453 * mode_id - (OUT) Created mode Id for Policer Group Mode 2454 * Returns: 2455 * BCM_E_XXX 2456 */ 2457 2458 STATIC int 2459 bcmi_esw_policer_group_mode_id_create( 2460 int unit, 2461 uint32 flags, 2462 bcm_policer_group_mode_type_t group_mode_type, 2463 uint32 total_policers, 2464 uint32 num_selectors, 2465 bcm_policer_group_mode_attr_selector_t *attr_selectors, 2466 uint32 *mode_id) 2467 { 2468 bcm_error_t rv = BCM_E_UNAVAIL; 2469 2470 POL_FUNCTION_TRACE(unit, "IN"); 2471 2472 /* Parameter NULL error handling */ 2473 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2474 2475 /* Initialization check */ 2476 CHECK_GLOBAL_METER_INIT(unit); 2477 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2478 2479 if (group_mode_type >= bcmPolicerGroupModeTypeCount) { 2480 return (BCM_E_PARAM); 2481 } 2482 2483 /* Attribute selectors are used for selecting one of the policers created in 2484 * policer group. For total_policer = 1 there is just one policer. 2485 * Hence, attribute selectors have no significance. 2486 * All other IN parameters are set fixed to avoid any confusion 2487 * while fetching group policer config via bcm_policer_group_mode_id_get() 2488 */ 2489 if (total_policers == 1) { 2490 if ((group_mode_type == bcmPolicerGroupModeTypeNormal) && 2491 (attr_selectors == NULL) && 2492 (num_selectors == 0)) { 2493 *mode_id = 1; 2494 return (BCM_E_NONE); 2495 } else { 2496 return (BCM_E_PARAM); 2497 } 2498 } 2499 2500 /* Parameter NULL error handling */ 2501 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 2502 if ((total_policers == 0) || (num_selectors == 0)) { 2503 return (BCM_E_PARAM); 2504 } 2505 2506 if ((group_mode_type == bcmPolicerGroupModeTypeNormal) && 2507 (num_selectors > BCMI_POLICER_SVC_METER_TCAM_SIZE)) { 2508 return (BCM_E_PARAM); 2509 } 2510 2511 rv = bcmi_esw_policer_custom_group_mode_id_create( 2512 unit, flags, group_mode_type, 2513 total_policers, num_selectors, attr_selectors, mode_id); 2514 if (BCM_FAILURE(rv)) { 2515 LOG_ERROR(BSL_LS_BCM_POLICER, 2516 (BSL_META_U(unit, 2517 "Unable to create policer group\n"))); 2518 return (rv); 2519 } 2520 2521 POL_FUNCTION_DEBUG(unit, 2522 "Created policer group with mode id %x \n", *mode_id); 2523 POL_FUNCTION_TRACE(unit, "OUT"); 2524 return rv; 2525 } 2526 2527 /* 2528 * Function: 2529 * bcmi_esw_policer_group_mode_id_get 2530 * Purpose: 2531 * Retrieves Customized Policer Group mode Attributes for given mode_id. 2532 * Parameters: 2533 * unit - (IN) unit number 2534 * mode_id - (IN) Created mode Id for Policer Group Mode 2535 * num_selectors - (IN) Number of Selectors for policer Group Mode 2536 * flags - (OUT) flags 2537 * group_mode_type - (OUT) modes of policer group creation - 2538 * normal/cascade/cascade with coupling. 2539 * total_policers - (OUT) Total Policers in Policer Group Mode 2540 * attr_selectors - (OUT) Attribute Selectors for Policer Group Mode 2541 * actual_num_selectors - (OUT) Actual Number of Selectors for Policer 2542 * Group Mode 2543 * Returns: 2544 * BCM_E_XXX 2545 */ 2546 STATIC int 2547 bcmi_esw_policer_group_mode_id_get( 2548 int unit, 2549 uint32 mode_id, 2550 uint32 num_selectors, 2551 uint32 *flags, 2552 bcm_policer_group_mode_type_t *group_mode_type, 2553 uint32 *total_policers, 2554 bcm_policer_group_mode_attr_selector_t *attr_selectors, 2555 uint32 *actual_num_selectors) 2556 { 2557 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 2558 uint32 offset_mode; 2559 int i = 0; 2560 2561 POL_FUNCTION_TRACE(unit, "IN"); 2562 2563 /* Parameter NULL error handling */ 2564 POL_CHECK_NULL_PARAMETER(unit, flags); 2565 POL_CHECK_NULL_PARAMETER(unit, group_mode_type); 2566 POL_CHECK_NULL_PARAMETER(unit, total_policers); 2567 POL_CHECK_NULL_PARAMETER(unit, attr_selectors); 2568 POL_CHECK_NULL_PARAMETER(unit, actual_num_selectors); 2569 2570 /* Initialization check */ 2571 CHECK_GLOBAL_METER_INIT(unit); 2572 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2573 2574 /* Validate mode_id */ 2575 BCM_IF_ERROR_RETURN( 2576 bcmi_policer_mode_id_validate(unit, mode_id)); 2577 2578 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 2579 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 2580 2581 *total_policers = bk_svm_mode_info->no_of_policers; 2582 *actual_num_selectors = bk_svm_mode_info->no_of_attr_selectors; 2583 *group_mode_type = bk_svm_mode_info->group_mode_type; 2584 2585 if (*actual_num_selectors > num_selectors) { 2586 return (BCM_E_PARAM); 2587 } 2588 2589 for (i = 0; i < *actual_num_selectors; i++) { 2590 sal_memcpy (&attr_selectors[i], 2591 &bk_svm_mode_info->attr_selectors[i], 2592 sizeof(bcm_policer_group_mode_attr_selector_t)); 2593 } 2594 POL_FUNCTION_TRACE(unit, "OUT"); 2595 return BCM_E_NONE; 2596 } 2597 2598 /* 2599 * Function: 2600 * bcmi_esw_policer_group_mode_id_destroy 2601 * Purpose: 2602 * Destroy Customized Policer Group mode with given mode_id. 2603 * Parameters: 2604 * unit - (IN) unit number 2605 * mode_id - (IN) Destroy Policer Group Mode with given mode Id 2606 * Returns: 2607 * BCM_E_NONE - Success on destroying the given mode_id 2608 */ 2609 STATIC int 2610 bcmi_esw_policer_group_mode_id_destroy( 2611 int unit, 2612 uint32 mode_id) 2613 { 2614 bcm_error_t rv = BCM_E_UNAVAIL; 2615 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 2616 uint32 offset_mode; 2617 2618 POL_FUNCTION_TRACE(unit, "IN"); 2619 POL_FUNCTION_DEBUG(unit, "mode_id %d\n", mode_id); 2620 2621 /* Initialization check */ 2622 CHECK_GLOBAL_METER_INIT(unit); 2623 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2624 2625 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 2626 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 2627 2628 if (bk_svm_mode_info->ref_cnt > 0) { 2629 LOG_WARN(BSL_LS_BCM_POLICER, 2630 (BSL_META_U(unit, 2631 "Policer group mode is still in use \n"))); 2632 return (BCM_E_BUSY); 2633 } 2634 /* Destory SW & HW of allocated offset mode */ 2635 rv = bcmi_policer_svc_meter_delete_mode(unit, offset_mode); 2636 2637 POL_FUNCTION_TRACE(unit, "OUT"); 2638 return rv; 2639 } 2640 2641 #endif /* MODE_ID_API_SECTION */ 2642 2643 #if POLICER_ID_API_SECTION 2644 /* 2645 * Function: 2646 * global_meter_policer_id_alloc 2647 * Purpose: 2648 * Allocate a new policer. 2649 * Parameters: 2650 * unit - (IN) unit number 2651 * numbers - (IN/OUT) Number of policers 2652 * pid - (OUT) base policer id 2653 * Returns: 2654 * BCM_E_XXX 2655 */ 2656 STATIC int 2657 bcmi_global_meter_policer_id_alloc( 2658 int unit, 2659 int numbers, 2660 bcm_policer_t *pid) 2661 { 2662 int rv = BCM_E_NONE; 2663 2664 POL_FUNCTION_TRACE(unit, "IN"); 2665 2666 /* Parameter NULL error handling */ 2667 POL_CHECK_NULL_PARAMETER(unit, pid); 2668 2669 if (!(numbers > 0)) { 2670 return BCM_E_PARAM; 2671 } 2672 2673 /* Initialization check */ 2674 CHECK_GLOBAL_METER_INIT(unit); 2675 2676 rv = shr_aidxres_list_alloc_block( 2677 BCMI_POLICER_LIST_HANDLE_GET(unit), 2678 numbers, 2679 (uint32 *)pid); 2680 BCM_IF_ERROR_RETURN(rv); 2681 2682 POL_FUNCTION_DEBUG( 2683 unit, "allocated %d policers\n", numbers); 2684 POL_FUNCTION_DEBUG( 2685 unit, "allocated policer with pid %d", *pid); 2686 2687 POL_FUNCTION_TRACE(unit, "OUT"); 2688 return rv; 2689 } 2690 2691 /* 2692 * Function: 2693 * bcmi_global_meter_free_allocated_policer_on_error 2694 * Purpose: 2695 * Clean up the internal data structure in case of error. 2696 * Parameters: 2697 * unit - (IN) unit number 2698 * numbers - (IN) Number of policer to be freed 2699 * policer_index - (IN) Base policer id 2700 * Returns: 2701 * BCM_E_XXX 2702 */ 2703 STATIC int 2704 bcmi_global_meter_free_allocated_policer_on_error( 2705 int unit, 2706 uint32 numbers, 2707 uint32 policer_index) 2708 { 2709 int rv = BCM_E_NONE; 2710 int base_index = 0, index = 0; 2711 2712 POL_FUNCTION_TRACE(unit, "IN"); 2713 2714 /* Initialization check */ 2715 CHECK_GLOBAL_METER_INIT(unit); 2716 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2717 2718 for (index = 0;index < numbers; index++) { 2719 base_index = policer_index + index; 2720 rv = shr_aidxres_list_free( 2721 BCMI_POLICER_LIST_HANDLE_GET(unit), 2722 base_index); 2723 if (BCM_FAILURE(rv)) { 2724 LOG_DEBUG(BSL_LS_BCM_POLICER, 2725 (BSL_META_U(unit, 2726 "Unable to free policer handle \n"))); 2727 return BCM_E_INTERNAL; 2728 } 2729 } 2730 POL_FUNCTION_TRACE(unit, "OUT"); 2731 return rv; 2732 } 2733 2734 /* 2735 * Function: 2736 * bcmi_global_meter_policer_control_alloc 2737 * Purpose: 2738 * Allocate a new bcmi_global_meter_policer_control_t. 2739 * Parameters: 2740 * unit - (IN) unit number 2741 * npolicers - (IN) Number of policers created 2742 * policer_control - (OUT) Policer control info 2743 * Returns: 2744 * BCM_E_XXX 2745 */ 2746 STATIC int 2747 bcmi_global_meter_policer_control_alloc( 2748 int unit, 2749 uint32 npolicers, 2750 bcmi_global_meter_policer_control_t **policer_control) 2751 { 2752 POL_FUNCTION_TRACE(unit, "IN"); 2753 2754 POL_CHECK_NULL_PARAMETER(unit, policer_control); 2755 2756 POL_MEM_ALLOC( 2757 *policer_control, 2758 sizeof(bcmi_global_meter_policer_control_t), 2759 "Global meter policer"); 2760 if (NULL == (*policer_control)) { 2761 return (BCM_E_MEMORY); 2762 } 2763 (void)bcmi_global_meter_policer_control_t_init(*policer_control); 2764 2765 POL_MEM_ALLOC( 2766 (*policer_control)->pol_cfg, 2767 sizeof(bcm_policer_config_t) * npolicers, 2768 "pol_cfg of Global meter policer"); 2769 2770 if (NULL == (*policer_control)->pol_cfg) { 2771 POL_MEM_FREE(*policer_control); 2772 return (BCM_E_MEMORY); 2773 } 2774 POL_FUNCTION_TRACE(unit, "OUT"); 2775 return BCM_E_NONE; 2776 } 2777 2778 /* 2779 * Function: 2780 * bcmi_policer_svc_meter_create_mode 2781 * Purpose: 2782 * Function to create an offset mode with uncompressed packet attributes 2783 * Parameters: 2784 * Unit - (IN) unit number 2785 * pkt_attr_selectors - (IN) tcam packet attribute selectors 2786 * group_mode - (IN) Policer group mode 2787 * mode_id - (OUT) Meter mode id 2788 * Returns: 2789 * BCM_E_XXX 2790 */ 2791 STATIC int 2792 bcmi_policer_svc_meter_create_mode( 2793 int unit, 2794 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors, 2795 bcm_policer_group_mode_t group_mode, 2796 bcm_policer_group_mode_type_t group_mode_type, 2797 uint32 *mode_id) 2798 { 2799 bcm_error_t rv = BCM_E_NONE; 2800 uint32 flags = 0; 2801 2802 POL_FUNCTION_TRACE(unit, "IN"); 2803 2804 /* Input parameters check. */ 2805 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 2806 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2807 2808 /* Initialization check */ 2809 CHECK_GLOBAL_METER_INIT(unit); 2810 GLOBAL_METER_LOCK(unit); 2811 2812 /* Add a new mode_id associated with pkt_attr_selectors information */ 2813 rv = bcmi_esw_policer_group_mode_id_associate(unit, 2814 flags, group_mode_type, pkt_attr_selectors, mode_id); 2815 if (BCM_FAILURE(rv)) { 2816 GLOBAL_METER_UNLOCK(unit); 2817 return rv; 2818 } 2819 GLOBAL_METER_UNLOCK(unit); 2820 2821 POL_FUNCTION_TRACE(unit, "OUT"); 2822 return rv; 2823 } 2824 2825 /* 2826 * Function: 2827 * bcmi_esw_policer_svc_meter_create_mode 2828 * Purpose: 2829 * Function to create an Meter offset mode 2830 * Parameters: 2831 * Unit - (IN) unit number 2832 * pkt_attr_selectors - (IN) Packet attribute selectors 2833 * group_mode - (IN) Policer group mode 2834 * group_mode_type - (IN) Policer group mode type 2835 * npolicers - (IN) Number of policers created 2836 * mode_id - (OUT) Meter mode id 2837 * Returns: 2838 * BCM_E_XXX 2839 */ 2840 STATIC int 2841 bcmi_esw_policer_svc_meter_create_mode( 2842 int unit, 2843 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors, 2844 bcm_policer_group_mode_t group_mode, 2845 bcm_policer_group_mode_type_t group_mode_type, 2846 int npolicers, 2847 uint32 *mode_id) 2848 { 2849 bcm_error_t rv = BCM_E_UNAVAIL; 2850 int existed; 2851 bcm_policer_svc_meter_mode_t offset_mode; 2852 2853 POL_FUNCTION_TRACE(unit, "IN"); 2854 2855 /* Input parameters check. */ 2856 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 2857 POL_CHECK_NULL_PARAMETER(unit, mode_id); 2858 2859 /* Initialization check */ 2860 CHECK_GLOBAL_METER_INIT(unit); 2861 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 2862 2863 /* Check if mode info already exists */ 2864 rv = bcmi_esw_policer_group_mode_id_existed_check( 2865 unit, group_mode, npolicers, 2866 pkt_attr_selectors, mode_id, &existed); 2867 BCM_IF_ERROR_RETURN(rv); 2868 2869 if (existed) { 2870 POL_FUNCTION_DEBUG( 2871 unit, "mode_id %d already existed", *mode_id); 2872 } else { 2873 rv = bcmi_policer_svc_meter_create_mode( 2874 unit, pkt_attr_selectors, group_mode, 2875 group_mode_type, mode_id); 2876 BCM_IF_ERROR_RETURN(rv); 2877 offset_mode = MODE_ID_TO_OFFSET_MODE(*mode_id); 2878 2879 rv = bcmi_policer_svc_meter_reserve_mode( 2880 unit, offset_mode, group_mode, 2881 group_mode_type, npolicers, pkt_attr_selectors); 2882 BCM_IF_ERROR_RETURN(rv); 2883 } 2884 2885 POL_FUNCTION_DEBUG(unit, "mode_id %d", *mode_id); 2886 2887 POL_FUNCTION_TRACE(unit, "OUT"); 2888 return BCM_E_NONE; 2889 } 2890 2891 /* 2892 * Function: 2893 * bcmi_esw_get_policer_id_from_index_offset 2894 * Purpose: 2895 * Get policer id, given the HW policer index and offset_mode 2896 * Parameters: 2897 * Unit - (IN) unit number 2898 * index - (IN) HW policer index 2899 * offset_mode - (IN) offset mode 2900 * pid - (OUT) policer Id 2901 * Returns: 2902 * BCM_E_XXX 2903 */ 2904 STATIC int 2905 bcmi_esw_get_policer_id_from_index_offset( 2906 int unit, 2907 int index, 2908 int offset_mode, 2909 bcm_policer_t *pid) 2910 { 2911 POL_FUNCTION_TRACE(unit, "IN"); 2912 2913 /* Input parameters check. */ 2914 POL_CHECK_NULL_PARAMETER(unit, pid); 2915 2916 if (index == 0) { 2917 LOG_VERBOSE(BSL_LS_BCM_POLICER, 2918 (BSL_META_U(unit, 2919 "0 is reserved invalid table index\n"))); 2920 } else { 2921 *pid = POLICER_IDX_TO_POLICER_ID(offset_mode, index); 2922 } 2923 2924 POL_FUNCTION_TRACE(unit, "OUT"); 2925 2926 return BCM_E_NONE; 2927 } 2928 2929 /* 2930 * Function: 2931 * bcmi_esw_policer_table_index_get 2932 * Purpose: 2933 * Get the HW policer index, given a policer id. 2934 * Parameters: 2935 * Unit - (IN) unit number 2936 * policer_id - (IN) policer Id 2937 * index - (OUT) HW policer index 2938 * Returns: 2939 * BCM_E_XXX 2940 */ 2941 STATIC int 2942 bcmi_esw_policer_table_index_get( 2943 int unit, 2944 bcm_policer_t policer_id, 2945 int *index) 2946 { 2947 int rv = BCM_E_NONE; 2948 2949 POL_FUNCTION_TRACE(unit, "IN"); 2950 2951 /* Input parameters check. */ 2952 POL_CHECK_NULL_PARAMETER(unit, index); 2953 2954 *index = POLICER_ID_TO_POLICER_IDX(policer_id); 2955 2956 if (*index >= soc_mem_index_count(unit, SVM_METER_TABLEm)) { 2957 LOG_VERBOSE(BSL_LS_BCM_POLICER, 2958 (BSL_META_U(unit, 2959 "Invalid table index for " 2960 "SVM_METER_TABLE\n"))); 2961 return BCM_E_PARAM; 2962 } 2963 2964 POL_FUNCTION_TRACE(unit, "OUT"); 2965 return rv; 2966 } 2967 2968 /* 2969 * Function: 2970 * bcmi_esw_policer_offset_mode_get 2971 * Purpose: 2972 * Get the offset_mode with given a policer id. 2973 * Parameters: 2974 * Unit - (IN) unit number 2975 * policer_id - (IN) policer Id 2976 * offset_mode - (OUT) HW policer index 2977 * Returns: 2978 * BCM_E_XXX 2979 */ 2980 STATIC int 2981 bcmi_esw_policer_offset_mode_get( 2982 int unit, 2983 bcm_policer_t policer_id, 2984 int *offset_mode) 2985 { 2986 int rv = BCM_E_NONE; 2987 2988 POL_FUNCTION_TRACE(unit, "IN"); 2989 2990 /* Input parameters check. */ 2991 POL_CHECK_NULL_PARAMETER(unit, offset_mode); 2992 2993 if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) { 2994 LOG_VERBOSE(BSL_LS_BCM_POLICER, 2995 (BSL_META_U(unit, 2996 "Policer id passed is 0\n"))); 2997 *offset_mode = 0; 2998 return rv; 2999 } 3000 3001 *offset_mode = POLICER_ID_OFFSET_MODE_GET(policer_id); 3002 3003 POL_FUNCTION_TRACE(unit, "OUT"); 3004 return rv; 3005 } 3006 3007 STATIC int 3008 bcmi_esw_global_meter_base_policer_get( 3009 int unit, 3010 bcm_policer_t policer_id, 3011 bcmi_global_meter_policer_control_t **policer_p); 3012 3013 /* 3014 * Function: 3015 * bcmi_esw_policer_validate 3016 * Purpose: 3017 * Validate the given policer id 3018 * Parameters: 3019 * Unit - (IN) unit number 3020 * policer_id - (IN) policer Id 3021 * Returns: 3022 * BCM_E_XXX 3023 */ 3024 STATIC int 3025 bcmi_esw_policer_validate( 3026 int unit, 3027 bcm_policer_t policer_id) 3028 { 3029 int rv = BCM_E_NONE; 3030 int index = 0; 3031 uint32 offset_mode = 0; 3032 bcmi_global_meter_policer_control_t *policer_control = NULL; 3033 3034 POL_FUNCTION_TRACE(unit, "IN"); 3035 3036 /* Initialization check */ 3037 CHECK_GLOBAL_METER_INIT(unit); 3038 3039 if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) { 3040 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3041 (BSL_META_U(unit, 3042 "Policer id passed is 0\n"))); 3043 return rv; 3044 } 3045 3046 /* valid the policer id is create in current SW database or not */ 3047 rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control); 3048 BCM_IF_ERROR_RETURN(rv); 3049 3050 /* get the HW index for the policer */ 3051 rv = bcmi_esw_policer_table_index_get(unit, policer_id, &index); 3052 BCM_IF_ERROR_RETURN(rv); 3053 if (index > (soc_mem_index_max(unit, SVM_METER_TABLEm))) { 3054 LOG_WARN(BSL_LS_BCM_POLICER, 3055 (BSL_META_U(unit, 3056 "Invalid table index for SVM_POLICY_TABLE\n"))); 3057 return BCM_E_PARAM; 3058 } 3059 3060 if (index == 0) { 3061 /* Default HW value will be 0 and it's not a valid table index */ 3062 return BCM_E_PARAM; 3063 } 3064 3065 /* Get mode id from policer id */ 3066 offset_mode = POLICER_ID_OFFSET_MODE_GET(policer_id); 3067 3068 /* Validate offset_mode */ 3069 rv = bcmi_policer_offset_mode_validate(unit, offset_mode); 3070 3071 POL_FUNCTION_TRACE(unit, "OUT"); 3072 return rv; 3073 } 3074 3075 /* 3076 * Function: 3077 * bcmi_esw_base_policer_validate 3078 * Purpose: 3079 * Validate the given policer id if 3080 * it is base policer. 3081 * Parameters: 3082 * Unit - (IN) unit number 3083 * base_policer_id - (IN) base policer Id 3084 * Returns: 3085 * BCM_E_XXX 3086 */ 3087 STATIC int 3088 bcmi_esw_base_policer_validate( 3089 int unit, 3090 bcm_policer_t base_policer_id) 3091 { 3092 bcmi_global_meter_policer_control_t *policer_control = NULL; 3093 uint32 hash_index; /* Entry hash. */ 3094 uint32 hash_max; 3095 3096 POL_FUNCTION_TRACE(unit, "IN"); 3097 3098 /* Initialization check */ 3099 CHECK_GLOBAL_METER_INIT(unit); 3100 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3101 3102 BCM_IF_ERROR_RETURN( 3103 bcmi_esw_policer_validate(unit, base_policer_id)); 3104 3105 hash_max = base_policer_id & BCMI_GLOBAL_METER_HASH_MASK; 3106 for (hash_index = 0; hash_index <= hash_max; hash_index++) { 3107 policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index); 3108 while (NULL != policer_control) { 3109 /* Match entry's base policer id. */ 3110 if (base_policer_id == policer_control->pid) { 3111 POL_FUNCTION_TRACE(unit, "OUT: is base policer id"); 3112 return (BCM_E_NONE); 3113 } 3114 policer_control = policer_control->next; 3115 } 3116 } 3117 /* Not a base_policer_id. */ 3118 POL_FUNCTION_TRACE(unit, "OUT: not base policer id"); 3119 return (BCM_E_NOT_FOUND); 3120 } 3121 3122 /* 3123 * Function: 3124 * bcmi_esw_policer_increment_ref_count 3125 * Purpose: 3126 * Increment the policer usage reference count 3127 * Parameters: 3128 * unit - (IN) unit number 3129 * policer - (IN) policer Id 3130 * Returns: 3131 * BCM_E_XXX 3132 */ 3133 STATIC int 3134 bcmi_esw_policer_increment_ref_count( 3135 int unit, 3136 bcm_policer_t policer_id) 3137 { 3138 int rv = BCM_E_NONE; 3139 bcmi_global_meter_policer_control_t *policer_control = NULL; 3140 3141 POL_FUNCTION_TRACE(unit, "OUT"); 3142 3143 if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) { 3144 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3145 (BSL_META_U(unit, 3146 "inc refcnt:Policer id passed is 0\n"))); 3147 return rv; 3148 } 3149 3150 /* validate policer id */ 3151 rv = bcmi_esw_policer_validate(unit, policer_id); 3152 if (BCM_FAILURE(rv)) { 3153 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3154 (BSL_META_U(unit, 3155 "Invalid policer id passed: %x \n"), 3156 policer_id)); 3157 return (rv); 3158 } 3159 3160 GLOBAL_METER_BK_LOCK(unit); 3161 rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control); 3162 3163 if (BCM_FAILURE(rv)) { 3164 GLOBAL_METER_BK_UNLOCK(unit); 3165 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3166 (BSL_META_U(unit, 3167 "Unable to get policer control for policer " 3168 "id %d\n"), policer_id)); 3169 return (rv); 3170 } 3171 policer_control->ref_count++; 3172 GLOBAL_METER_BK_UNLOCK(unit); 3173 3174 POL_FUNCTION_TRACE(unit, "OUT"); 3175 return rv; 3176 } 3177 3178 /* 3179 * Function: 3180 * bcmi_esw_policer_decrement_ref_count 3181 * Purpose: 3182 * Decrement the policer usage refernce count 3183 * Parameters: 3184 * unit - (IN) unit number 3185 * policer - (IN) policer Id 3186 * Returns: 3187 * BCM_E_XXX 3188 */ 3189 STATIC int 3190 bcmi_esw_policer_decrement_ref_count( 3191 int unit, 3192 bcm_policer_t policer_id) 3193 { 3194 int rv = BCM_E_NONE; 3195 bcmi_global_meter_policer_control_t *policer_control = NULL; 3196 3197 POL_FUNCTION_TRACE(unit, "IN"); 3198 3199 if (BCMI_POLICER_INVALID_POLICER_ID == policer_id) { 3200 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3201 (BSL_META_U(unit, 3202 "dec refcnt:Policer id passed is 0\n"))); 3203 return rv; 3204 } 3205 3206 /* validate policer id */ 3207 rv = bcmi_esw_policer_validate(unit, policer_id); 3208 if (BCM_FAILURE(rv)) { 3209 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3210 (BSL_META_U(unit, 3211 "Invalid policer id passed: %x \n"), 3212 policer_id)); 3213 return (rv); 3214 } 3215 3216 GLOBAL_METER_BK_LOCK(unit); 3217 rv = bcmi_esw_global_meter_base_policer_get(unit, policer_id, &policer_control); 3218 3219 if (BCM_FAILURE(rv)) { 3220 GLOBAL_METER_BK_UNLOCK(unit); 3221 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3222 (BSL_META_U(unit, 3223 "Unable to get policer control for policer " 3224 "id %d\n"), policer_id)); 3225 return (rv); 3226 } 3227 if (policer_control->ref_count > 0) { 3228 policer_control->ref_count--; 3229 } 3230 GLOBAL_METER_BK_UNLOCK(unit); 3231 3232 POL_FUNCTION_TRACE(unit, "OUT"); 3233 return rv; 3234 } 3235 3236 /* 3237 * Function: 3238 * bcmi_esw_get_policer_from_table 3239 * Purpose: 3240 * Read the policer id configured in the given table 3241 * Parameters: 3242 * unit - (IN) unit number 3243 * table - (IN) Table from which the entry needs to be got 3244 * index - (IN) index in the table 3245 * data - (IN) Data to be written 3246 * policer - (OUT) policer Id 3247 * skip_read - (IN) Skip reading the policer entry 3248 * Returns: 3249 * BCM_E_XXX 3250 */ 3251 STATIC int 3252 bcmi_esw_get_policer_from_table( 3253 int unit, 3254 soc_mem_t table, 3255 int index, 3256 void *data, 3257 bcm_policer_t *policer_id, 3258 int skip_read) 3259 { 3260 bcm_error_t rv = BCM_E_UNAVAIL; 3261 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3262 int meter_index, meter_offset_mode; 3263 3264 POL_FUNCTION_TRACE(unit, "IN"); 3265 3266 /* Input parameters check. */ 3267 POL_CHECK_NULL_PARAMETER(unit, data); 3268 POL_CHECK_NULL_PARAMETER(unit, policer_id); 3269 3270 /* Initialization check */ 3271 CHECK_GLOBAL_METER_INIT(unit); 3272 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3273 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3274 3275 /* Check if the chip specific function existed */ 3276 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_get); 3277 3278 GLOBAL_METER_LOCK(unit); 3279 rv = gm_dev_info->policer_to_table_get(unit, 3280 table, 3281 index, 3282 data, 3283 &meter_index, 3284 &meter_offset_mode, 3285 skip_read); 3286 GLOBAL_METER_UNLOCK(unit); 3287 if (BCM_FAILURE(rv)) { 3288 LOG_ERROR(BSL_LS_BCM_POLICER, 3289 (BSL_META_U(unit, 3290 "HW Operation failed(rv = %d)\n"), 3291 rv)); 3292 return rv; 3293 } 3294 3295 BCM_IF_ERROR_RETURN( 3296 bcmi_esw_get_policer_id_from_index_offset( 3297 unit, meter_index, meter_offset_mode, policer_id)); 3298 POL_FUNCTION_TRACE(unit, "OUT"); 3299 return BCM_E_NONE; 3300 } 3301 3302 /* 3303 * Function: 3304 * bcmi_esw_add_policer_to_table 3305 * Purpose: 3306 * Add policer id to the table entry specified 3307 * Parameters: 3308 * unit - (IN) unit number 3309 * policer_id - (IN) policer Id 3310 * table - (IN) Table to which the entry needs to be added 3311 * index - (IN) index in the table 3312 * data - (IN) Data to be written 3313 * Returns: 3314 * BCM_E_XXX 3315 */ 3316 STATIC int 3317 bcmi_esw_add_policer_to_table(int unit, 3318 bcm_policer_t policer_id, 3319 soc_mem_t table, 3320 int index, 3321 void *data) 3322 { 3323 bcm_error_t rv = BCM_E_UNAVAIL; 3324 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3325 int meter_offset_mode = 0; 3326 int meter_index = 0; 3327 int skip_read = TRUE; 3328 bcm_policer_t current_policer_id = 0; 3329 3330 POL_FUNCTION_TRACE(unit, "IN"); 3331 3332 /* Input parameters check. */ 3333 POL_CHECK_NULL_PARAMETER(unit, data); 3334 3335 /* Initialization check */ 3336 CHECK_GLOBAL_METER_INIT(unit); 3337 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3338 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3339 3340 /* validate policer id */ 3341 rv = bcmi_esw_policer_validate(unit, policer_id); 3342 if (BCM_FAILURE(rv)) { 3343 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3344 (BSL_META_U(unit, 3345 "Invalid policer id passed: %x \n"), 3346 policer_id)); 3347 return (rv); 3348 } 3349 3350 /* get the policer id that is currently configured */ 3351 rv = bcmi_esw_get_policer_from_table(unit, table, index, data, 3352 ¤t_policer_id, skip_read); 3353 if (BCM_FAILURE(rv)) { 3354 LOG_VERBOSE(BSL_LS_BCM_POLICER, 3355 (BSL_META_U(unit, 3356 "Unable to read the table entry %d at " 3357 "index %d \n"), table, index)); 3358 return (rv); 3359 } 3360 3361 /* Set policer id */ 3362 BCM_IF_ERROR_RETURN( 3363 bcmi_esw_policer_table_index_get(unit, policer_id, &meter_index)); 3364 BCM_IF_ERROR_RETURN( 3365 bcmi_esw_policer_offset_mode_get(unit, policer_id, &meter_offset_mode)); 3366 3367 /* Check if the chip specific function existed */ 3368 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_set); 3369 3370 GLOBAL_METER_LOCK(unit); 3371 3372 rv = gm_dev_info->policer_to_table_set(unit, 3373 table, 3374 index, 3375 data, 3376 meter_index, 3377 meter_offset_mode, 3378 skip_read); 3379 GLOBAL_METER_UNLOCK(unit); 3380 if (BCM_FAILURE(rv)) { 3381 LOG_ERROR(BSL_LS_BCM_POLICER, 3382 (BSL_META_U(unit, 3383 "HW Operation failed(rv = %d)\n"), 3384 rv)); 3385 return rv; 3386 } 3387 3388 /* increment new set policer ref_cnt */ 3389 rv = bcmi_esw_policer_increment_ref_count(unit, policer_id); 3390 BCM_IF_ERROR_RETURN(rv); 3391 3392 /* decrement current hw policer ref_cnt */ 3393 rv = bcmi_esw_policer_validate(unit, current_policer_id); 3394 3395 /* Don't need to handle fail case since existed index could be 0 */ 3396 if (BCM_SUCCESS(rv)) { 3397 rv = bcmi_esw_policer_decrement_ref_count(unit, current_policer_id); 3398 BCM_IF_ERROR_RETURN(rv); 3399 } 3400 3401 POL_FUNCTION_TRACE(unit, "OUT"); 3402 return BCM_E_NONE; 3403 } 3404 3405 /* 3406 * Function: 3407 * bcmi_esw_delete_policer_from_table 3408 * Purpose: 3409 * Remove the policer id configured from a table and re-adjust 3410 * policer usage reference count 3411 * Parameters: 3412 * unit - (IN) unit number 3413 * policer_id - (IN) policer Id 3414 * table - (IN) Table in which an entry needs to be deleted 3415 * index - (IN) index in the table 3416 * data - (IN) Data to be written 3417 * Returns: 3418 * BCM_E_XXX 3419 */ 3420 int bcmi_esw_delete_policer_from_table( 3421 int unit, 3422 bcm_policer_t policer_id, 3423 soc_mem_t table, 3424 int index, 3425 void *data) 3426 { 3427 bcm_error_t rv = BCM_E_UNAVAIL; 3428 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3429 bcm_policer_t current_policer_id = 0; 3430 int meter_offset_mode = 0; 3431 int meter_index = 0; 3432 int skip_read = FALSE; 3433 3434 POL_FUNCTION_TRACE(unit, "IN"); 3435 3436 /* Input parameters check. */ 3437 POL_CHECK_NULL_PARAMETER(unit, data); 3438 3439 /* Initialization check */ 3440 CHECK_GLOBAL_METER_INIT(unit); 3441 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3442 3443 /* validate policer id */ 3444 rv = bcmi_esw_policer_validate(unit, policer_id); 3445 if (BCM_FAILURE(rv)) { 3446 LOG_DEBUG(BSL_LS_BCM_POLICER, 3447 (BSL_META_U(unit, 3448 "Invalid policer id passed: %x \n"), 3449 policer_id)); 3450 return (rv); 3451 } 3452 /* Deleting VFP_POLICY_TABLEm is handled in field module */ 3453 if (VFP_POLICY_TABLEm != table) { 3454 rv = bcmi_esw_get_policer_from_table(unit, table, index, data, 3455 ¤t_policer_id, skip_read); 3456 if (BCM_FAILURE(rv)) { 3457 LOG_ERROR(BSL_LS_BCM_POLICER, 3458 (BSL_META_U(unit, 3459 "Unable to read the policer from table " 3460 "%d at index %d\n"), table, index)); 3461 return (rv); 3462 } 3463 if (current_policer_id != policer_id) { 3464 LOG_ERROR(BSL_LS_BCM_POLICER, 3465 (BSL_META_U(unit, 3466 "Policer Id passed is different from the " 3467 "one that is configured in the table." 3468 "configured value is %d \n"), 3469 current_policer_id)); 3470 return BCM_E_INTERNAL; 3471 } 3472 3473 GLOBAL_METER_LOCK(unit); 3474 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3475 3476 /* Check if the chip specific function existed */ 3477 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policer_to_table_set); 3478 rv = gm_dev_info->policer_to_table_set(unit, 3479 table, 3480 index, 3481 data, 3482 meter_index, 3483 meter_offset_mode, 3484 skip_read); 3485 GLOBAL_METER_UNLOCK(unit); 3486 if (BCM_FAILURE(rv)) { 3487 LOG_ERROR(BSL_LS_BCM_POLICER, 3488 (BSL_META_U(unit, 3489 "HW Operation failed(rv = %d)\n"), 3490 rv)); 3491 return rv; 3492 } 3493 } 3494 3495 /* decrement current policer if any */ 3496 rv = bcmi_esw_policer_decrement_ref_count(unit, policer_id); 3497 BCM_IF_ERROR_RETURN(rv); 3498 3499 POL_FUNCTION_TRACE(unit, "OUT"); 3500 return BCM_E_NONE; 3501 } 3502 3503 /* 3504 * Function: 3505 * bcmi_esw_global_meter_read_config_from_hw 3506 * Purpose: 3507 * Read policer configuration form the HW table entry. 3508 * Parameters: 3509 * unit - (IN) unit number 3510 * policer_id - (IN) policer id 3511 * pol_cfg - (OUT) policer configuration 3512 * Returns: 3513 * BCM_E_XXX 3514 */ 3515 STATIC int 3516 bcmi_esw_global_meter_read_config_from_hw( 3517 int unit, 3518 bcm_policer_t policer_id, 3519 bcm_policer_config_t *pol_cfg) 3520 { 3521 bcm_error_t rv = BCM_E_UNAVAIL; 3522 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3523 uint32 refresh_rate = 0; /* Policer refresh rate. */ 3524 uint32 granularity = 0; /* Policer granularity. */ 3525 uint32 bucket_count = 0, bucket_size = 0; 3526 uint32 pkt_bytes = 0, tsn_modified = 0, average_pkt_size = 0; 3527 uint32 flags = 0; 3528 int index = 0, e_idx, c_idx, p_idx; 3529 uint32 meter_gran_mode = 0; 3530 uint32 pkbits_sec, pkbits_burst, ckbits_sec, ckbits_burst; 3531 3532 POL_FUNCTION_TRACE(unit, "IN"); 3533 3534 /* Input parameters check. */ 3535 POL_CHECK_NULL_PARAMETER(unit, pol_cfg); 3536 3537 (void)bcm_policer_config_t_init(pol_cfg); 3538 3539 /* Initialization check */ 3540 CHECK_GLOBAL_METER_INIT(unit); 3541 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3542 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3543 3544 /* get the HW index for the policer */ 3545 BCM_IF_ERROR_RETURN( 3546 bcmi_esw_policer_table_index_get(unit, policer_id, &index)); 3547 3548 /* Policy Table */ 3549 p_idx = index ; 3550 3551 /* Check if the chip specific function existed */ 3552 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_get); 3553 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_get); 3554 3555 rv = gm_dev_info->policy_mode_get( 3556 unit, 3557 p_idx, 3558 &pol_cfg->mode, 3559 &pol_cfg->flags); 3560 3561 if (BCM_FAILURE(rv)) { 3562 LOG_ERROR(BSL_LS_BCM_POLICER, 3563 (BSL_META_U(unit, 3564 "HW Operation failed(rv = %d)\n"), 3565 rv)); 3566 return rv; 3567 } 3568 3569 /* Commit */ 3570 c_idx = index * 2 + 1; 3571 3572 rv = gm_dev_info->meter_table_get( 3573 unit, 3574 c_idx, 3575 &bucket_size, 3576 &bucket_count, 3577 &refresh_rate, 3578 &granularity, 3579 &pkt_bytes, 3580 &tsn_modified, 3581 &meter_gran_mode, 3582 &average_pkt_size); 3583 3584 if (BCM_FAILURE(rv)) { 3585 LOG_ERROR(BSL_LS_BCM_POLICER, 3586 (BSL_META_U(unit, 3587 "HW Operation failed(rv = %d)\n"), 3588 rv)); 3589 return rv; 3590 } 3591 3592 if (pkt_bytes == 0) { 3593 pol_cfg->flags |= BCM_POLICER_MODE_BYTES; 3594 } else { 3595 pol_cfg->flags |= BCM_POLICER_MODE_PACKETS; 3596 } 3597 3598 if (tsn_modified == 1) { 3599 pol_cfg->mode = bcmPolicerModeSrTcmTsn; 3600 } 3601 pol_cfg->average_pkt_size = average_pkt_size; 3602 3603 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 3604 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 3605 3606 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 3607 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 3608 } 3609 3610 rv = _bcm_xgs_bucket_encoding_to_kbits( 3611 refresh_rate, bucket_size, granularity, flags, 3612 &ckbits_sec, &ckbits_burst); 3613 3614 if (BCM_FAILURE(rv)) { 3615 LOG_ERROR(BSL_LS_BCM_POLICER, 3616 (BSL_META_U(unit, 3617 "Unable to translate rate in kbps to bucket size " 3618 "and granularity \n"))); 3619 return rv; 3620 } 3621 /* ckbits_sec = (pol_cfg->ckbits_sec << 8) + (pol_cfg->cbits_sec_lower << 8) / 1000 */ 3622 if (meter_gran_mode) { 3623 pol_cfg->ckbits_sec = 3624 ckbits_sec >> BCMI_POLICER_METER_GRAN_SHFIT; 3625 pol_cfg->cbits_sec_lower = 3626 (ckbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >> 3627 BCMI_POLICER_METER_GRAN_SHFIT; 3628 pol_cfg->cbits_sec_lower -= 3629 (pol_cfg->ckbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT); 3630 3631 pol_cfg->ckbits_burst = 3632 ckbits_burst >> BCMI_POLICER_METER_GRAN_SHFIT; 3633 pol_cfg->cbits_burst_lower = 3634 (ckbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >> 3635 BCMI_POLICER_METER_GRAN_SHFIT; 3636 pol_cfg->cbits_burst_lower -= 3637 (pol_cfg->ckbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT); 3638 } else { 3639 pol_cfg->ckbits_sec = ckbits_sec; 3640 pol_cfg->ckbits_burst = ckbits_burst; 3641 } 3642 3643 /* Exceed */ 3644 e_idx = index * 2; 3645 3646 rv = gm_dev_info->meter_table_get( 3647 unit, 3648 e_idx, 3649 &bucket_size, 3650 &bucket_count, 3651 &refresh_rate, 3652 &granularity, 3653 &pkt_bytes, 3654 &tsn_modified, 3655 &meter_gran_mode, 3656 &average_pkt_size); 3657 3658 if (BCM_FAILURE(rv)) { 3659 LOG_ERROR(BSL_LS_BCM_POLICER, 3660 (BSL_META_U(unit, 3661 "HW Operation failed(rv = %d)\n"), 3662 rv)); 3663 return rv; 3664 } 3665 3666 rv = _bcm_xgs_bucket_encoding_to_kbits( 3667 refresh_rate, bucket_size, granularity, flags, 3668 &pkbits_sec, &pkbits_burst); 3669 if (BCM_FAILURE(rv)) { 3670 LOG_ERROR(BSL_LS_BCM_POLICER, 3671 (BSL_META_U(unit, 3672 "Unable to translate rate in kbps to bucket size " 3673 "and granularity \n"))); 3674 return rv; 3675 } 3676 /* pkbit_sec = (pol_cfg->pkbits_sec << 8) + (pol_cfg->pbits_sec_lower << 8) / 1000 */ 3677 if (meter_gran_mode) { 3678 pol_cfg->pkbits_sec = 3679 pkbits_sec >> BCMI_POLICER_METER_GRAN_SHFIT; 3680 pol_cfg->pbits_sec_lower = 3681 (pkbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >> 3682 BCMI_POLICER_METER_GRAN_SHFIT; 3683 pol_cfg->pbits_sec_lower -= 3684 (pol_cfg->pkbits_sec * BCMI_POLICER_METER_GRAN_LOWER_UNIT); 3685 3686 pol_cfg->pkbits_burst = 3687 pkbits_burst >> BCMI_POLICER_METER_GRAN_SHFIT; 3688 pol_cfg->pbits_burst_lower = 3689 (pkbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT) >> 3690 BCMI_POLICER_METER_GRAN_SHFIT; 3691 pol_cfg->pbits_burst_lower -= 3692 (pol_cfg->pkbits_burst * BCMI_POLICER_METER_GRAN_LOWER_UNIT); 3693 } else { 3694 pol_cfg->pkbits_sec = pkbits_sec; 3695 pol_cfg->pkbits_burst = pkbits_burst; 3696 } 3697 3698 POL_FUNCTION_TRACE(unit, "OUT"); 3699 return BCM_E_NONE; 3700 } 3701 3702 /* 3703 * Function: 3704 * bcmi_esw_global_meter_clear_config_on_hw 3705 * Purpose: 3706 * Clear policer configuration to meter table. 3707 * Parameters: 3708 * unit - (IN) unit number 3709 * pol_cfg - (IN) policer configuration 3710 * policer_id - (IN) policer id 3711 * policer_control - (IN) Policer control info 3712 * Returns: 3713 * BCM_E_XXX 3714 */ 3715 STATIC int 3716 bcmi_esw_global_meter_clear_config_on_hw( 3717 int unit, 3718 bcm_policer_t policer_id) 3719 { 3720 bcm_error_t rv = BCM_E_UNAVAIL; 3721 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3722 uint32 c_bucketsize = 0, e_bucketsize = 0; /* Bucket size */ 3723 uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */ 3724 uint32 granularity = 0; /* Policer granularity */ 3725 uint32 average_pkt_size = 0; 3726 uint32 c_bucketcount = 0, e_bucketcount; 3727 int index = 0, e_idx, c_idx, p_idx; 3728 bcm_policer_config_t pol_cfg; 3729 uint32 meter_gran_mode = 0; 3730 3731 POL_FUNCTION_TRACE(unit, "IN"); 3732 3733 (void)bcm_policer_config_t_init(&pol_cfg); 3734 3735 /* Initialization check */ 3736 CHECK_GLOBAL_METER_INIT(unit); 3737 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3738 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3739 3740 /* get the HW index for the policer */ 3741 BCM_IF_ERROR_RETURN( 3742 bcmi_esw_policer_table_index_get(unit, policer_id, &index)); 3743 3744 /* Check if the chip specific function existed */ 3745 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set); 3746 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_set); 3747 3748 /* Commit */ 3749 c_idx = index * 2 + 1; 3750 c_bucketsize = 0; 3751 c_bucketcount = 0; 3752 c_refresh_rate = 0; 3753 3754 /* Write to HW */ 3755 rv = gm_dev_info->meter_table_set( 3756 unit, 3757 c_idx, 3758 pol_cfg.mode, 3759 pol_cfg.flags, 3760 average_pkt_size, 3761 meter_gran_mode, 3762 c_bucketsize, 3763 c_bucketcount, 3764 c_refresh_rate, 3765 granularity); 3766 BCM_IF_ERROR_RETURN(rv); 3767 3768 /* Exceed */ 3769 e_idx = index * 2; 3770 e_bucketsize = 0; 3771 e_bucketcount = 0; 3772 e_refresh_rate = 0; 3773 granularity = 0; 3774 3775 /* Write to HW */ 3776 rv = gm_dev_info->meter_table_set( 3777 unit, 3778 e_idx, 3779 pol_cfg.mode, 3780 pol_cfg.flags, 3781 average_pkt_size, 3782 meter_gran_mode, 3783 e_bucketsize, 3784 e_bucketcount, 3785 e_refresh_rate, 3786 granularity); 3787 BCM_IF_ERROR_RETURN(rv); 3788 3789 /* Policy Table */ 3790 p_idx = index; 3791 3792 rv = gm_dev_info->policy_mode_set( 3793 unit, 3794 p_idx, 3795 pol_cfg.mode, 3796 pol_cfg.flags); 3797 BCM_IF_ERROR_RETURN(rv); 3798 3799 POL_FUNCTION_TRACE(unit, "OUT"); 3800 return BCM_E_NONE; 3801 } 3802 3803 /* 3804 * Function: 3805 * bcmi_esw_global_meter_write_config_to_hw 3806 * Purpose: 3807 * Write policer configuration to meter table. 3808 * Parameters: 3809 * unit - (IN) unit number 3810 * pol_cfg - (IN) policer configuration 3811 * policer_id - (IN) policer id 3812 * policer_control - (IN) Policer control info 3813 * Returns: 3814 * BCM_E_XXX 3815 */ 3816 STATIC int 3817 bcmi_esw_global_meter_write_config_to_hw( 3818 int unit, 3819 bcm_policer_config_t *pol_cfg, 3820 bcm_policer_t policer_id) 3821 { 3822 bcm_error_t rv = BCM_E_UNAVAIL; 3823 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 3824 uint32 flags = 0; 3825 uint32 c_bucketsize = 0, e_bucketsize = 0; /* Bucket size */ 3826 uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */ 3827 uint32 granularity = 0; /* Policer granularity */ 3828 uint32 refresh_bitsize; /* Number of bits for the 3829 refresh rate field */ 3830 uint32 bucket_max_bitsize; /* Number of bits for the 3831 bucket max field */ 3832 uint32 c_bucketcount = 0, e_bucketcount = 0, bucket_cnt_bitsize = 0; 3833 int index = 0, e_idx, c_idx, p_idx; 3834 uint32 meter_gran_mode = 0; 3835 uint32 pkbits_sec, pkbits_burst, ckbits_sec, ckbits_burst; 3836 3837 POL_FUNCTION_TRACE(unit, "IN"); 3838 3839 /* Input parameters check. */ 3840 POL_CHECK_NULL_PARAMETER(unit, pol_cfg); 3841 3842 /* Initialization check */ 3843 CHECK_GLOBAL_METER_INIT(unit); 3844 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 3845 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 3846 3847 /* get the HW index for the policer */ 3848 BCM_IF_ERROR_RETURN( 3849 bcmi_esw_policer_table_index_get(unit, policer_id, &index)); 3850 3851 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 3852 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 3853 3854 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 3855 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 3856 } 3857 3858 /* 3859 * Gran Meter Bytes Min Max 3860 * mode Gran /Token Refresh Rate MaxRefresh Rate 3861 * 1 0 1/2^15 32bps 8Mbps 3862 * 1 1/2^14 64bps 16Mbps 3863 * 2 1/2^13 128bps 32Mbps 3864 * 3 1/2^12 256bps 64Mbps 3865 * 4 1/2^11 512bps 128Mbps 3866 * 5 1/2^10 1Kbps 256Mbps 3867 * 6 1/2^9 2Kbps 512Mbps 3868 * 7 1/2^8 4Kbps 1Gbps 3869 * Gran Meter Bytes Min Max 3870 * mode Gran /Token Refresh Rate MaxRefresh Rate 3871 * 0 0 1/2^7 8Kbps 2Gbps 3872 * 1 1/2^6 16Kbps 4Gbps 3873 * 2 1/2^5 32Kbps 8Gbps 3874 * 3 1/2^4 64Kbps 16Gbps 3875 * 4 1/2^3 128Kbps 32Gbps 3876 * 5 1/2^2 256Kbps 64Gbps 3877 * 6 1/2^1 512Kbps 128Gbps 3878 * 7 1/2^0 1024Kbps 256Gbps 3879 */ 3880 3881 /* pkbit_sec = (pol_cfg->pkbits_sec << 8) + (pol_cfg->pbits_sec_lower << 8) / 1000 */ 3882 if (pol_cfg->pkbits_sec < BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY && 3883 pol_cfg->pkbits_burst < BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY && 3884 pol_cfg->ckbits_sec < BCMI_POLICER_METER_FINER_GRAN_RATE_BOUNDARY && 3885 pol_cfg->ckbits_burst < BCMI_POLICER_METER_FINER_GRAN_BURST_BOUNDARY) { 3886 pkbits_sec = 3887 (pol_cfg->pkbits_sec << BCMI_POLICER_METER_GRAN_SHFIT) + 3888 (pol_cfg->pbits_sec_lower << BCMI_POLICER_METER_GRAN_SHFIT) / 3889 BCMI_POLICER_METER_GRAN_LOWER_UNIT; 3890 pkbits_burst = 3891 (pol_cfg->pkbits_burst << BCMI_POLICER_METER_GRAN_SHFIT) + 3892 (pol_cfg->pbits_burst_lower << BCMI_POLICER_METER_GRAN_SHFIT) / 3893 BCMI_POLICER_METER_GRAN_LOWER_UNIT; 3894 ckbits_sec = 3895 (pol_cfg->ckbits_sec << BCMI_POLICER_METER_GRAN_SHFIT) + 3896 (pol_cfg->cbits_sec_lower << BCMI_POLICER_METER_GRAN_SHFIT) / 3897 BCMI_POLICER_METER_GRAN_LOWER_UNIT; 3898 ckbits_burst = 3899 (pol_cfg->ckbits_burst << BCMI_POLICER_METER_GRAN_SHFIT) + 3900 (pol_cfg->cbits_burst_lower << BCMI_POLICER_METER_GRAN_SHFIT) / 3901 BCMI_POLICER_METER_GRAN_LOWER_UNIT; 3902 3903 meter_gran_mode = 1; 3904 } else { 3905 pkbits_sec = pol_cfg->pkbits_sec; 3906 pkbits_burst = pol_cfg->pkbits_burst; 3907 ckbits_sec = pol_cfg->ckbits_sec; 3908 ckbits_burst = pol_cfg->ckbits_burst; 3909 3910 meter_gran_mode = 0; 3911 } 3912 3913 /* Commit */ 3914 c_idx = index * 2 + 1; 3915 3916 /* Check if the chip specific function existed */ 3917 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_bitsize_get); 3918 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set); 3919 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_mode_set); 3920 3921 /* Read from HW */ 3922 rv = gm_dev_info->meter_table_bitsize_get( 3923 unit, 3924 c_idx, 3925 &refresh_bitsize, 3926 &bucket_max_bitsize, 3927 &bucket_cnt_bitsize); 3928 3929 if (BCM_FAILURE(rv)) { 3930 LOG_ERROR(BSL_LS_BCM_POLICER, 3931 (BSL_META_U(unit, 3932 "HW Operation failed(rv = %d)\n"), 3933 rv)); 3934 return rv; 3935 } 3936 3937 /* Calculate policer bucket size/refresh_rate/granularity. */ 3938 if (pkbits_sec > ckbits_sec) { 3939 rv = _bcm_xgs_kbits_to_bucket_encoding(pkbits_sec, 3940 pkbits_burst, 3941 flags, refresh_bitsize, 3942 bucket_max_bitsize, 3943 &c_refresh_rate, 3944 &c_bucketsize, 3945 &granularity); 3946 BCM_IF_ERROR_RETURN(rv); 3947 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 3948 ckbits_sec, 3949 ckbits_burst, 3950 flags, refresh_bitsize, 3951 bucket_max_bitsize, 3952 &c_refresh_rate, 3953 &c_bucketsize, 3954 &granularity); 3955 BCM_IF_ERROR_RETURN(rv); 3956 } else { 3957 rv = _bcm_xgs_kbits_to_bucket_encoding(ckbits_sec, 3958 ckbits_burst, 3959 flags, refresh_bitsize, 3960 bucket_max_bitsize, 3961 &c_refresh_rate, 3962 &c_bucketsize, 3963 &granularity); 3964 BCM_IF_ERROR_RETURN(rv); 3965 } 3966 3967 /* Calculate initial bucket count. 3968 * bucket size << (bit count diff - 1(sign) -1 (overflow)) - 1 3969 */ 3970 if (c_bucketsize == 0 && c_refresh_rate == 0) { 3971 /* Committed should always be out of profile */ 3972 c_bucketcount = (1 << bucket_cnt_bitsize) - 1; 3973 } else if (c_bucketsize) { 3974 c_bucketcount = 3975 (c_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1; 3976 c_bucketcount &= ((1 << bucket_cnt_bitsize) - 1); 3977 } else { 3978 c_bucketcount = 0; 3979 } 3980 3981 /* Check if the chip specific function existed */ 3982 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->meter_table_set); 3983 3984 /* Write to HW */ 3985 rv = gm_dev_info->meter_table_set( 3986 unit, 3987 c_idx, 3988 pol_cfg->mode, 3989 pol_cfg->flags, 3990 pol_cfg->average_pkt_size, 3991 meter_gran_mode, 3992 c_bucketsize, 3993 c_bucketcount, 3994 c_refresh_rate, 3995 granularity); 3996 3997 if (BCM_FAILURE(rv)) { 3998 LOG_ERROR(BSL_LS_BCM_POLICER, 3999 (BSL_META_U(unit, 4000 "HW Operation failed(rv = %d)\n"), 4001 rv)); 4002 return rv; 4003 } 4004 4005 /* Exceed */ 4006 e_idx = index * 2; 4007 4008 /* Read from HW */ 4009 rv = gm_dev_info->meter_table_bitsize_get( 4010 unit, 4011 e_idx, 4012 &refresh_bitsize, 4013 &bucket_max_bitsize, 4014 &bucket_cnt_bitsize); 4015 4016 if ((ckbits_sec == 0) && (ckbits_burst == 0)) { 4017 rv = _bcm_xgs_kbits_to_bucket_encoding(pkbits_sec, 4018 pkbits_burst, 4019 flags, refresh_bitsize, 4020 bucket_max_bitsize, 4021 &e_refresh_rate, 4022 &e_bucketsize, 4023 &granularity); 4024 4025 } else { 4026 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 4027 pkbits_sec, 4028 pkbits_burst, 4029 flags, refresh_bitsize, 4030 bucket_max_bitsize, 4031 &e_refresh_rate, 4032 &e_bucketsize, 4033 &granularity); 4034 } 4035 BCM_IF_ERROR_RETURN(rv); 4036 /* Calculate initial bucket count. 4037 * bucket size << (bit count diff - 1(sign) -1 (overflow)) - 1 4038 */ 4039 if (e_bucketsize == 0 && e_refresh_rate == 0) { 4040 /* Excess should always be out of profile */ 4041 e_bucketcount = (1 << bucket_cnt_bitsize) - 1; 4042 } else if (e_bucketsize) { 4043 e_bucketcount = 4044 (e_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1; 4045 e_bucketcount &= ((1 << bucket_cnt_bitsize) - 1); 4046 } else { 4047 e_bucketcount = 0; 4048 } 4049 4050 /* Write to HW */ 4051 rv = gm_dev_info->meter_table_set( 4052 unit, 4053 e_idx, 4054 pol_cfg->mode, 4055 pol_cfg->flags, 4056 pol_cfg->average_pkt_size, 4057 meter_gran_mode, 4058 e_bucketsize, 4059 e_bucketcount, 4060 e_refresh_rate, 4061 granularity); 4062 4063 if (BCM_FAILURE(rv)) { 4064 LOG_ERROR(BSL_LS_BCM_POLICER, 4065 (BSL_META_U(unit, 4066 "HW Operation failed(rv = %d)\n"), 4067 rv)); 4068 return rv; 4069 } 4070 4071 /* Policy Table */ 4072 p_idx = index ; 4073 4074 rv = gm_dev_info->policy_mode_set( 4075 unit, 4076 p_idx, 4077 pol_cfg->mode, 4078 pol_cfg->flags); 4079 4080 if (BCM_FAILURE(rv)) { 4081 LOG_ERROR(BSL_LS_BCM_POLICER, 4082 (BSL_META_U(unit, 4083 "HW Operation failed(rv = %d)\n"), 4084 rv)); 4085 return rv; 4086 } 4087 4088 POL_FUNCTION_TRACE(unit, "OUT"); 4089 return BCM_E_NONE; 4090 } 4091 4092 /* 4093 * Function: 4094 * bcmi_esw_global_meter_base_policer_get 4095 * Purpose: 4096 * Get the internal data sructure for a given polier id if 4097 * it is base policer. 4098 * Parameters: 4099 * unit - (IN) unit number 4100 * pid - (IN) policer id 4101 * policer_p - (OUT) Policer control info 4102 * Returns: 4103 * BCM_E_XXX 4104 */ 4105 STATIC int 4106 bcmi_esw_global_meter_base_policer_get( 4107 int unit, 4108 bcm_policer_t policer_id, 4109 bcmi_global_meter_policer_control_t **policer_p) 4110 { 4111 bcmi_global_meter_policer_control_t *policer_control = NULL; 4112 uint32 hash_index; /* Entry hash. */ 4113 uint32 hash_max; 4114 4115 POL_FUNCTION_TRACE(unit, "IN"); 4116 4117 /* Input parameters check. */ 4118 POL_CHECK_NULL_PARAMETER(unit, policer_p); 4119 4120 /* Initialization check */ 4121 CHECK_GLOBAL_METER_INIT(unit); 4122 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4123 4124 hash_max = policer_id & BCMI_GLOBAL_METER_HASH_MASK; 4125 for (hash_index = 0; hash_index <= hash_max; hash_index++) { 4126 policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index); 4127 while (NULL != policer_control) { 4128 /* Match entry id. */ 4129 if (policer_id >= policer_control->pid && 4130 policer_id < policer_control->pid + policer_control->no_of_policers) { 4131 *policer_p = policer_control; 4132 POL_FUNCTION_TRACE(unit, "OUT found"); 4133 return (BCM_E_NONE); 4134 } 4135 policer_control = policer_control->next; 4136 } 4137 } 4138 /* Policer with policer_id was not found. */ 4139 POL_FUNCTION_TRACE(unit, "OUT not found"); 4140 return (BCM_E_NOT_FOUND); 4141 } 4142 4143 int _bcm_global_meter_min_burst_size_set( 4144 bcm_policer_config_t *pol_cfg); 4145 4146 STATIC int 4147 bcmi_esw_policer_action_attach( 4148 int unit, 4149 bcm_policer_t policer_id, 4150 uint32 action_id); 4151 4152 STATIC int 4153 bcmi_esw_policer_action_detach( 4154 int unit, 4155 bcm_policer_t policer_id, 4156 uint32 action_id); 4157 4158 STATIC int 4159 bcmi_esw_policer_action_attach_get( 4160 int unit, 4161 bcm_policer_t policer_id, 4162 uint32 *action_id); 4163 4164 /* 4165 * Function: 4166 * bcmi_esw_global_meter_policer_set 4167 * Purpose: 4168 * Configure the parmeters for a policer already created. 4169 * Parameters: 4170 * unit - (IN) unit number 4171 * policer_id - (IN) policer id 4172 * pol_cfg - (IN) Policer control info 4173 * Returns: 4174 * BCM_E_XXX 4175 */ 4176 STATIC int 4177 bcmi_esw_global_meter_policer_set( 4178 int unit, 4179 bcm_policer_t policer_id, 4180 bcm_policer_config_t *pol_cfg) 4181 { 4182 int rv = BCM_E_NONE, rv2 = BCM_E_NONE; 4183 bcmi_global_meter_policer_control_t *policer_control = NULL; 4184 uint32 pol_cfg_idx; 4185 4186 POL_FUNCTION_TRACE(unit, "IN"); 4187 4188 /* Input parameters check. */ 4189 POL_CHECK_NULL_PARAMETER(unit, pol_cfg); 4190 4191 /* lower must be 0 ~ 999 */ 4192 if (pol_cfg->cbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT || 4193 pol_cfg->cbits_burst_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT || 4194 pol_cfg->pbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT || 4195 pol_cfg->pbits_burst_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT || 4196 pol_cfg->max_cbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT || 4197 pol_cfg->max_pbits_sec_lower >= BCMI_POLICER_METER_GRAN_LOWER_UNIT) { 4198 return BCM_E_PARAM; 4199 } 4200 4201 /* Initialization check */ 4202 CHECK_GLOBAL_METER_INIT(unit); 4203 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4204 4205 /* validate policer id */ 4206 rv = bcmi_esw_policer_validate(unit, policer_id); 4207 if (BCM_FAILURE(rv)) { 4208 LOG_DEBUG(BSL_LS_BCM_POLICER, 4209 (BSL_META_U(unit, 4210 "Invalid policer id %x\n"), 4211 policer_id)); 4212 return (rv); 4213 } 4214 GLOBAL_METER_LOCK(unit); 4215 4216 if (BCM_SUCCESS(rv)) { 4217 /* Check whether the burst size is >= min required. If not, set it 4218 to minimum required value */ 4219 rv = _bcm_global_meter_min_burst_size_set(pol_cfg); 4220 if (BCM_FAILURE(rv)) { 4221 GLOBAL_METER_UNLOCK(unit); 4222 return (rv); 4223 } 4224 4225 /* Add code to write this to HW */ 4226 rv = bcmi_esw_global_meter_write_config_to_hw(unit, 4227 pol_cfg, policer_id); 4228 if (BCM_FAILURE(rv)) { 4229 GLOBAL_METER_UNLOCK(unit); 4230 rv2 = bcmi_esw_global_meter_clear_config_on_hw(unit, policer_id); 4231 BCM_IF_ERROR_RETURN(rv2); 4232 LOG_ERROR(BSL_LS_BCM_POLICER, 4233 (BSL_META_U(unit, 4234 "Unable to write policer config to hw %x\n"), 4235 policer_id)); 4236 return (rv); 4237 } 4238 } 4239 GLOBAL_METER_UNLOCK(unit); 4240 4241 rv = bcmi_esw_global_meter_base_policer_get( 4242 unit, policer_id, &policer_control); 4243 if (BCM_FAILURE(rv)) { 4244 LOG_ERROR(BSL_LS_BCM_POLICER, 4245 (BSL_META_U(unit, 4246 "Unable to get policer control for " 4247 "policer id 0x%x(%d)\n"), 4248 policer_id, 4249 policer_id)); 4250 return (rv); 4251 } 4252 pol_cfg_idx = policer_id - policer_control->pid; 4253 4254 /* Detach bk action */ 4255 if (BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID != 4256 policer_control->pol_cfg[pol_cfg_idx].action_id) { 4257 BCM_IF_ERROR_RETURN( 4258 bcmi_esw_policer_action_detach( 4259 unit, policer_id, 4260 policer_control->pol_cfg[pol_cfg_idx].action_id)); 4261 } 4262 4263 /* Attach new action */ 4264 if (BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID != 4265 pol_cfg->action_id) { 4266 BCM_IF_ERROR_RETURN( 4267 bcmi_esw_policer_action_attach( 4268 unit, policer_id, pol_cfg->action_id)); 4269 } 4270 4271 /* store pol_cfg to bk */ 4272 GLOBAL_METER_BK_LOCK(unit); 4273 sal_memcpy(&(policer_control->pol_cfg[pol_cfg_idx]), 4274 pol_cfg, 4275 sizeof(bcm_policer_config_t)); 4276 GLOBAL_METER_BK_UNLOCK(unit); 4277 4278 POL_FUNCTION_TRACE(unit, "OUT"); 4279 return rv; 4280 } 4281 4282 /* 4283 * Function: 4284 * bcmi_esw_global_meter_policer_get 4285 * Purpose: 4286 * Get the configuration info for a given policer id 4287 * Parameters: 4288 * unit - (IN) unit number 4289 * policer_id - (IN) policer id 4290 * pol_cfg - (OUT) Policer control info 4291 * Returns: 4292 * BCM_E_XXX 4293 */ 4294 STATIC int 4295 bcmi_esw_global_meter_policer_get( 4296 int unit, 4297 bcm_policer_t policer_id, 4298 bcm_policer_config_t *pol_cfg) 4299 { 4300 int rv = BCM_E_NONE; 4301 bcmi_global_meter_policer_control_t *policer_control = NULL; 4302 uint32 pol_cfg_idx; 4303 bcm_policer_config_t actual_pol_cfg; 4304 4305 POL_FUNCTION_TRACE(unit, "IN"); 4306 4307 /* Input parameters check. */ 4308 POL_CHECK_NULL_PARAMETER(unit, pol_cfg); 4309 4310 /* Initialization check */ 4311 CHECK_GLOBAL_METER_INIT(unit); 4312 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4313 4314 /* validate policer id */ 4315 rv = bcmi_esw_policer_validate(unit, policer_id); 4316 if (BCM_FAILURE(rv)) { 4317 LOG_DEBUG(BSL_LS_BCM_POLICER, 4318 (BSL_META_U(unit, 4319 "Invalid policer id %x \n"), 4320 policer_id)); 4321 return (rv); 4322 } 4323 4324 /* read pol_cfg from bk */ 4325 GLOBAL_METER_BK_LOCK(unit); 4326 rv = bcmi_esw_global_meter_base_policer_get( 4327 unit, policer_id, &policer_control); 4328 if (BCM_FAILURE(rv)) { 4329 GLOBAL_METER_BK_UNLOCK(unit); 4330 LOG_ERROR(BSL_LS_BCM_POLICER, 4331 (BSL_META_U(unit, 4332 "Unable to get policer control for " 4333 "policer id 0x%x(%d)\n"), 4334 policer_id, 4335 policer_id)); 4336 return (rv); 4337 } 4338 pol_cfg_idx = policer_id - policer_control->pid; 4339 sal_memcpy(pol_cfg, 4340 &(policer_control->pol_cfg[pol_cfg_idx]), 4341 sizeof(bcm_policer_config_t)); 4342 GLOBAL_METER_BK_UNLOCK(unit); 4343 4344 /* read from HW for actual_xxx */ 4345 GLOBAL_METER_LOCK(unit); 4346 rv = bcmi_esw_global_meter_read_config_from_hw(unit, 4347 policer_id, &actual_pol_cfg); 4348 GLOBAL_METER_UNLOCK(unit); 4349 if (BCM_FAILURE(rv)) { 4350 LOG_DEBUG(BSL_LS_BCM_POLICER, 4351 (BSL_META_U(unit, 4352 "Unable to read policer config from hw %x\n"), 4353 policer_id)); 4354 return (rv); 4355 } 4356 pol_cfg->actual_ckbits_sec = 4357 actual_pol_cfg.ckbits_sec; 4358 pol_cfg->actual_cbits_sec_lower = 4359 actual_pol_cfg.cbits_sec_lower; 4360 pol_cfg->actual_ckbits_burst = 4361 actual_pol_cfg.ckbits_burst; 4362 pol_cfg->actual_cbits_burst_lower = 4363 actual_pol_cfg.cbits_burst_lower; 4364 pol_cfg->actual_pkbits_sec = 4365 actual_pol_cfg.pkbits_sec; 4366 pol_cfg->actual_pbits_sec_lower = 4367 actual_pol_cfg.pbits_sec_lower; 4368 pol_cfg->actual_pkbits_burst = 4369 actual_pol_cfg.pkbits_burst; 4370 pol_cfg->actual_pbits_burst_lower = 4371 actual_pol_cfg.pbits_burst_lower; 4372 4373 POL_FUNCTION_TRACE(unit, "OUT"); 4374 return rv; 4375 } 4376 4377 /* 4378 * Function: 4379 * bcmi_esw_global_meter_policer_delete 4380 * Purpose: 4381 * Internal function that destroys a policer and readjusts action 4382 * usage reference count and policer allocation management data structure. 4383 * Parameters: 4384 * unit - (IN) unit number 4385 * policer_control - (IN) policer control info 4386 * Returns: 4387 * BCM_E_XXX 4388 */ 4389 STATIC int 4390 bcmi_esw_global_meter_policer_delete( 4391 int unit, 4392 bcmi_global_meter_policer_control_t *policer_control) 4393 { 4394 int rv = BCM_E_NONE; 4395 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 4396 uint32 numbers = 0, idx; 4397 int offset_mode = 0; 4398 int policer_idx; 4399 4400 POL_FUNCTION_TRACE(unit, "IN"); 4401 4402 /* Input parameters check. */ 4403 POL_CHECK_NULL_PARAMETER(unit, policer_control); 4404 4405 numbers = policer_control->no_of_policers; 4406 4407 /* Initialization check */ 4408 CHECK_GLOBAL_METER_INIT(unit); 4409 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4410 4411 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 4412 4413 GLOBAL_METER_LOCK(unit); 4414 4415 /* Make sure policer is not attached to any entry. */ 4416 if (0 != policer_control->ref_count) { 4417 GLOBAL_METER_UNLOCK(unit); 4418 LOG_DEBUG(BSL_LS_BCM_POLICER, 4419 (BSL_META_U(unit, 4420 "Policer is still in use\n"))); 4421 return (BCM_E_BUSY); 4422 } 4423 4424 /* Decrease the reference count of actions. */ 4425 for (idx = 0; idx < policer_control->no_of_policers; idx++) { 4426 if (BCMI_ACTION_ID_BK_GET( 4427 unit, 4428 policer_control->pol_cfg[idx].action_id).reference_count > 0) { 4429 BCMI_ACTION_ID_BK_GET( 4430 unit, 4431 policer_control->pol_cfg[idx].action_id).reference_count--; 4432 } 4433 } 4434 4435 /* get the HW index for the policer to be deleted */ 4436 rv = bcmi_esw_policer_table_index_get( 4437 unit, policer_control->pid, &policer_idx); 4438 if (BCM_FAILURE(rv)) { 4439 GLOBAL_METER_UNLOCK(unit); 4440 LOG_DEBUG(BSL_LS_BCM_POLICER, 4441 (BSL_META_U(unit, 4442 "Unable to Get policer index for " 4443 "policer \n"))); 4444 return rv; 4445 } 4446 4447 bcmi_global_meter_free_allocated_policer_on_error( 4448 unit, numbers, policer_idx); 4449 4450 /* Check if the chip specific function existed */ 4451 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->mem_range_clear); 4452 4453 /* Clear SVM METER TABLE */ 4454 rv = gm_dev_info->mem_range_clear(unit, policer_idx, numbers); 4455 if (BCM_FAILURE(rv)) { 4456 GLOBAL_METER_UNLOCK(unit); 4457 } 4458 4459 /* Delete policer from policers hash. */ 4460 _GLOBAL_METER_HASH_REMOVE( 4461 BCMI_POLICER_BK_GET(unit), bcmi_global_meter_policer_control_t, 4462 policer_control, (policer_control->pid & BCMI_GLOBAL_METER_HASH_MASK)); 4463 4464 /* decrement mode reference count */ 4465 BCM_IF_ERROR_RETURN( 4466 bcmi_esw_policer_offset_mode_get(unit, policer_control->pid, &offset_mode)); 4467 bcmi_policer_svc_meter_dec_mode_ref_cnt(unit, offset_mode); 4468 GLOBAL_METER_UNLOCK(unit); 4469 4470 /* De-allocate policer descriptor. */ 4471 POL_MEM_FREE(policer_control->pol_cfg); 4472 POL_MEM_FREE(policer_control); 4473 4474 POL_FUNCTION_TRACE(unit, "OUT"); 4475 return rv; 4476 } 4477 4478 /* 4479 * Function: 4480 * bcmi_esw_global_meter_policer_destroy 4481 * Purpose: 4482 * Destroys a policer and readjusts action 4483 * usage reference count and policer allocation management data structure. 4484 * Parameters: 4485 * unit - (IN) unit number 4486 * policer_id - (IN) policer id 4487 * Returns: 4488 * BCM_E_XXX 4489 */ 4490 STATIC int 4491 bcmi_esw_global_meter_policer_destroy( 4492 int unit, 4493 bcm_policer_t policer_id) 4494 { 4495 int rv = BCM_E_NONE; 4496 bcmi_global_meter_policer_control_t *policer_control = NULL; 4497 4498 POL_FUNCTION_TRACE(unit, "IN"); 4499 4500 /* Initialization check */ 4501 CHECK_GLOBAL_METER_INIT(unit); 4502 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4503 4504 /* Validate policer id */ 4505 rv = bcmi_esw_policer_validate(unit, policer_id); 4506 if (BCM_FAILURE(rv)) { 4507 LOG_VERBOSE(BSL_LS_BCM_POLICER, 4508 (BSL_META_U(unit, 4509 "Invalid policer id %x(%d)\n"), 4510 policer_id, policer_id)); 4511 return (rv); 4512 } 4513 4514 GLOBAL_METER_LOCK(unit); 4515 rv = bcmi_esw_global_meter_base_policer_get(unit, 4516 policer_id, &policer_control); 4517 if (BCM_FAILURE(rv)) { 4518 GLOBAL_METER_UNLOCK(unit); 4519 LOG_ERROR(BSL_LS_BCM_POLICER, 4520 (BSL_META_U(unit, 4521 "Unable to get policer control for " 4522 "policer id 0x%x(%d)\n"), 4523 policer_id, 4524 policer_id)); 4525 return (rv); 4526 } 4527 rv = bcmi_esw_global_meter_policer_delete(unit, policer_control); 4528 GLOBAL_METER_UNLOCK(unit); 4529 4530 POL_FUNCTION_TRACE(unit, "OUT"); 4531 return (rv); 4532 } 4533 4534 /* 4535 * Function: 4536 * bcmi_esw_global_meter_policer_destroy_all 4537 * Purpose: 4538 * Destroy all the policers. 4539 * Parameters: 4540 * unit - (IN) unit number 4541 * Returns: 4542 * BCM_E_XXX 4543 */ 4544 STATIC int 4545 bcmi_esw_global_meter_policer_destroy_all(int unit) 4546 { 4547 int rv = BCM_E_NONE; 4548 int idx = 0; 4549 bcmi_global_meter_policer_control_t *policer_control = NULL; 4550 4551 CHECK_GLOBAL_METER_INIT(unit); 4552 4553 GLOBAL_METER_LOCK(unit); 4554 4555 /* Iterate over all hash buckets. */ 4556 for (idx = 0; idx < BCMI_GLOBAL_METER_HASH_SIZE; idx++) { 4557 policer_control = BCMI_POLICER_HASH_BK_GET(unit, idx); 4558 /* Destroy entries in each bucket. */ 4559 while (NULL != policer_control) { 4560 rv = bcmi_esw_global_meter_policer_delete(unit, policer_control); 4561 if (BCM_FAILURE(rv)) { 4562 break; 4563 } 4564 policer_control = policer_control->next; 4565 } 4566 } 4567 4568 GLOBAL_METER_UNLOCK(unit); 4569 return rv; 4570 } 4571 4572 /* 4573 * Function: 4574 * bcmi_esw_global_meter_policer_traverse 4575 * Purpose: 4576 * Traverse through all the policers that are configured and 4577 * call the given call back function with policer configuration. 4578 * Parameters: 4579 * unit - (IN) unit number 4580 * cb - (IN) Call back function 4581 * user_data - (OUT) Data for callback function 4582 * Returns: 4583 * BCM_E_XXX 4584 */ 4585 STATIC int 4586 bcmi_esw_global_meter_policer_traverse( 4587 int unit, 4588 bcm_policer_traverse_cb cb, 4589 void *user_data) 4590 { 4591 int rv = BCM_E_NONE; 4592 int hash_index = 0; 4593 bcm_policer_config_t cfg; /* Policer configuration. */ 4594 bcmi_global_meter_policer_control_t *policer_control = NULL; 4595 4596 /* Iterate over all hash buckets. */ 4597 for (hash_index = 0; hash_index < BCMI_GLOBAL_METER_HASH_SIZE; hash_index++) { 4598 policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index); 4599 /* Iterate all entries in each bucket. */ 4600 while (NULL != policer_control) { 4601 rv = bcmi_esw_global_meter_policer_get(unit, 4602 policer_control->pid, &cfg); 4603 if (BCM_FAILURE(rv)) { 4604 break; 4605 } 4606 rv = (*cb)(unit, policer_control->pid, &cfg, user_data); 4607 if (BCM_FAILURE(rv)) { 4608 break; 4609 } 4610 policer_control = policer_control->next; 4611 } 4612 if (BCM_FAILURE(rv)) { 4613 break; 4614 } 4615 } 4616 return rv; 4617 } 4618 4619 /* 4620 * Function: 4621 * bcmi_esw_policer_envelop_create 4622 * Purpose: 4623 * Create a single policer in Envelop mode. The policer created is 4624 * micro or a macro meter depending on the configuration. 4625 * Parameters: 4626 * unit - (IN) unit number 4627 * flags - (IN) Indicates micro/macro flow policer 4628 * macro_flow_policer_id - (IN) macro flow policer id 4629 * policer_id - (OUT) policer Id 4630 * Returns: 4631 * BCM_E_XXX 4632 */ 4633 STATIC int 4634 bcmi_esw_policer_envelop_create(int unit, 4635 uint32 flags, 4636 bcm_policer_t macro_flow_policer_id, 4637 bcm_policer_t *policer_id) 4638 { 4639 bcm_error_t rv = BCM_E_UNAVAIL; 4640 4641 /* Not supported */ 4642 POL_FUNCTION_TRACE(unit, "IN"); 4643 POL_FUNCTION_TRACE(unit, "OUT"); 4644 return rv; 4645 } 4646 4647 /* 4648 * Function: 4649 * bcmi_esw_policer_envelop_group_create 4650 * Purpose: 4651 * Create a group of policers based on the mode. 4652 * Parameters: 4653 * unit - (IN) unit number 4654 * flags - (IN) Indicates micro/macro flow policer 4655 * mode - (IN) policer group mode 4656 * macro_flow_policer_id - (IN) macro flow policer id 4657 * policer_id - (OUT)Base policer Id 4658 * npolicers - (OUT) Number of policers created 4659 * Returns: 4660 * BCM_E_XXX 4661 */ 4662 STATIC int 4663 bcmi_esw_policer_envelop_group_create(int unit, 4664 uint32 flags, 4665 bcm_policer_group_mode_t mode, 4666 bcm_policer_t macro_flow_policer_id, 4667 bcm_policer_t *policer_id, 4668 int *npolicers) 4669 { 4670 bcm_error_t rv = BCM_E_UNAVAIL; 4671 4672 /* Not supported */ 4673 POL_FUNCTION_TRACE(unit, "IN"); 4674 POL_FUNCTION_TRACE(unit, "OUT"); 4675 return rv; 4676 } 4677 4678 /* 4679 * Function: 4680 * bcmi_esw_policer_custom_group_create 4681 * Purpose: 4682 * Create a group of policers based on the mode. 4683 * Parameters: 4684 * unit - (IN) unit number 4685 * flags - (IN) flags 4686 * mode_id - (IN) Created Mode Id for Policer Group Mode 4687 * macro_flow_policer_id - (IN) Is an optional parameter and needs to be 4688 * passed only while creating the micro flow 4689 * policers of a hierarchical groupi 4690 * (2 stage policers). 4691 * policer_id - (OUT)Base policer Id 4692 * npolicers - (OUT) Number of policers created 4693 * Returns: 4694 * BCM_E_XXX 4695 */ 4696 STATIC int 4697 bcmi_esw_policer_custom_group_create( 4698 int unit, 4699 uint32 flags, 4700 uint32 mode_id, 4701 bcm_policer_t macro_flow_policer_id, 4702 bcm_policer_t *policer_id, 4703 uint32 *npolicers) 4704 { 4705 bcm_error_t rv = BCM_E_NONE; 4706 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 4707 uint32 offset_mode; 4708 int policer_idx; 4709 bcmi_global_meter_policer_control_t *policer_control = NULL; 4710 bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeSingle; 4711 4712 POL_FUNCTION_TRACE(unit, "IN"); 4713 4714 /* Parameter NULL error handling */ 4715 POL_CHECK_NULL_PARAMETER(unit, policer_id); 4716 POL_CHECK_NULL_PARAMETER(unit, npolicers); 4717 4718 POL_FUNCTION_DEBUG(unit, "flags %x", flags); 4719 POL_FUNCTION_DEBUG(unit, "mode_id %d", mode_id); 4720 POL_FUNCTION_DEBUG(unit, "macro_flow_policer_id %d", 4721 macro_flow_policer_id); 4722 4723 /* Initialization check */ 4724 CHECK_GLOBAL_METER_INIT(unit); 4725 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4726 4727 /* Validate mode_id */ 4728 BCM_IF_ERROR_RETURN( 4729 bcmi_policer_mode_id_validate(unit, mode_id)); 4730 4731 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 4732 bk_svm_mode_info = BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 4733 4734 *npolicers = bk_svm_mode_info->no_of_policers; 4735 4736 POL_FUNCTION_DEBUG(unit, "offset_mode %d", offset_mode); 4737 POL_FUNCTION_DEBUG(unit, "npolicers %d", *npolicers); 4738 4739 GLOBAL_METER_LOCK(unit); 4740 rv = bcmi_global_meter_policer_id_alloc( 4741 unit, *npolicers, &policer_idx); 4742 if (BCM_FAILURE(rv)) { 4743 GLOBAL_METER_UNLOCK(unit); 4744 LOG_VERBOSE(BSL_LS_BCM_POLICER, 4745 (BSL_META_U(unit, 4746 "Failed to allocate policer\n"))); 4747 return rv; 4748 } 4749 4750 /* Allocate policer descriptor. */ 4751 rv = bcmi_global_meter_policer_control_alloc( 4752 unit, *npolicers, &policer_control); 4753 if (BCM_FAILURE(rv)) { 4754 GLOBAL_METER_UNLOCK(unit); 4755 bcmi_global_meter_free_allocated_policer_on_error( 4756 unit, *npolicers, policer_idx); 4757 LOG_ERROR(BSL_LS_BCM_POLICER, 4758 (BSL_META_U(unit, 4759 "Unable to allocate memory for " 4760 "policer control\n"))); 4761 return (rv); 4762 } 4763 4764 /* Add mode info to the policer index */ 4765 *policer_id = POLICER_IDX_TO_POLICER_ID(offset_mode, policer_idx); 4766 4767 /* Set policer configuration */ 4768 policer_control->pid = *policer_id; 4769 policer_control->no_of_policers = *npolicers; 4770 policer_control->grp_mode = group_mode; 4771 4772 /* increment mode reference count for new policer */ 4773 rv = bcmi_policer_svc_meter_inc_mode_ref_cnt(unit, offset_mode); 4774 if (BCM_FAILURE(rv)) { 4775 /* free all the allocated policers */ 4776 bcmi_global_meter_free_allocated_policer_on_error( 4777 unit, *npolicers, policer_idx); 4778 /* De-allocate policer descriptor. */ 4779 POL_MEM_FREE(policer_control->pol_cfg); 4780 POL_MEM_FREE(policer_control); 4781 GLOBAL_METER_UNLOCK(unit); 4782 return rv; 4783 } 4784 4785 /* Insert policer into policers hash. */ 4786 _GLOBAL_METER_HASH_INSERT(BCMI_POLICER_BK_GET(unit), 4787 policer_control, 4788 (*policer_id & _GLOBAL_METER_HASH_MASK)); 4789 4790 GLOBAL_METER_UNLOCK(unit); 4791 POL_FUNCTION_DEBUG(unit, "policer_id 0x%x", *policer_id); 4792 POL_FUNCTION_TRACE(unit, "OUT"); 4793 return rv; 4794 } 4795 4796 /* 4797 * Function: 4798 * bcmi_esw_policer_group_get 4799 * Purpose: 4800 * Get the list of policer members for a given policer group represented 4801 * by its base policer id 4802 * Parameters: 4803 * unit - (IN) unit number 4804 * base_policer_id - (IN) Base policer Id 4805 * member_max - (IN) Maximum number of policers to return in 4806 * the member_array parameter 4807 * member_array - (OUT) Place to store policer members of the given 4808 * policer group represented by its base_policer_id 4809 * Memory need to be allocated by the end user before 4810 * calling the API 4811 * member_count - (OUT) Place to store total number of policers 4812 * configured in the given policer group represented 4813 * by base_policer_id 4814 4815 * Returns: 4816 * BCM_E_XXX 4817 */ 4818 STATIC int 4819 bcmi_esw_policer_group_get( 4820 int unit, 4821 bcm_policer_t base_policer_id, 4822 int member_max, 4823 bcm_policer_t *member_array, 4824 int *member_count) 4825 { 4826 bcm_error_t rv = BCM_E_UNAVAIL; 4827 bcmi_global_meter_policer_control_t *policer_control = NULL; 4828 int index, indices_to_fill; 4829 4830 POL_FUNCTION_TRACE(unit, "IN"); 4831 CHECK_GLOBAL_METER_INIT(unit); 4832 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4833 4834 /* verify arguments */ 4835 if ((base_policer_id == 0) || (member_count == NULL)) { 4836 return BCM_E_PARAM; 4837 } 4838 /* verify arguments, desired array elements to be retrived */ 4839 if ((member_max > 0) && (member_array == NULL)) { 4840 return BCM_E_PARAM; 4841 } 4842 4843 rv = bcmi_esw_base_policer_validate(unit, base_policer_id); 4844 BCM_IF_ERROR_RETURN(rv); 4845 4846 GLOBAL_METER_LOCK(unit); 4847 rv = bcmi_esw_global_meter_base_policer_get( 4848 unit, base_policer_id, &policer_control); 4849 if (BCM_FAILURE(rv)) { 4850 GLOBAL_METER_UNLOCK(unit); 4851 LOG_ERROR(BSL_LS_BCM_POLICER, 4852 (BSL_META_U(unit, 4853 "Unable to get policer control for " 4854 "policer id 0x%x(%d)\n"), 4855 base_policer_id, 4856 base_policer_id)); 4857 return (rv); 4858 } 4859 4860 *member_count = policer_control->no_of_policers; 4861 4862 if (member_max < *member_count) { 4863 indices_to_fill = member_max; 4864 LOG_VERBOSE(BSL_LS_BCM_POLICER, 4865 (BSL_META_U(unit, 4866 "member_count(%d) of base_policer_id(%d)" 4867 "is large than the member_array size(%d)"), 4868 *member_count, 4869 base_policer_id, 4870 member_max)); 4871 } else { 4872 indices_to_fill = *member_count; 4873 } 4874 4875 for (index = 0; index < indices_to_fill; index++) { 4876 member_array[index] = base_policer_id + index; 4877 } 4878 4879 GLOBAL_METER_UNLOCK(unit); 4880 POL_FUNCTION_TRACE(unit, "OUT"); 4881 return rv; 4882 } 4883 4884 /* 4885 * Function: 4886 * bcmi_esw_policer_group_set_mode_and_map 4887 * Purpose: 4888 * create group set from given policer group mode and offset_map 4889 * Parameters: 4890 * unit - (IN) unit number 4891 * mode - (IN) Policer group mode 4892 * mapping - (IN) customized offset mapping 4893 * npolicers - (OUT) Number of policers 4894 * pkt_attr_selectors - (OUT) Packet attribute selectors 4895 * Returns: 4896 * BCM_E_XXX 4897 */ 4898 STATIC int 4899 bcmi_esw_policer_group_set_mode_and_map( 4900 int unit, 4901 bcm_policer_group_mode_t group_mode, 4902 bcm_policer_map_t *mapping, 4903 int *npolicers, 4904 bcmi_policer_tcam_attr_selectors_t *pkt_attr_selectors) 4905 { 4906 int rv = BCM_E_NONE; 4907 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 4908 int count = 0; /* Number of offset mappings */ 4909 uint8 *final_offset = NULL; 4910 uint8 base_final_offset = 0; 4911 uint32 pkt_attr_pkt_type_cnt = 0, pkt_attr_v_cnt = 0; 4912 bcm_policer_group_mode_attr_t attr = bcmPolicerGroupModeAttrPktType; 4913 pkt_tcam_attr_bits_t *pkt_attr_v = NULL; 4914 int sel = 0; 4915 uint32 pol_offset = 0, max_pol_offset = 0; 4916 4917 POL_FUNCTION_TRACE(unit, "IN"); 4918 4919 /* Parameter NULL error handling */ 4920 POL_CHECK_NULL_PARAMETER(unit, npolicers); 4921 POL_CHECK_NULL_PARAMETER(unit, pkt_attr_selectors); 4922 4923 /* Initialization check */ 4924 CHECK_GLOBAL_METER_INIT(unit); 4925 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 4926 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 4927 4928 /* Check if the chip specific function existed */ 4929 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->group_mode_supported); 4930 4931 /* Check if group mode is supported */ 4932 rv = gm_dev_info->group_mode_supported(unit, group_mode); 4933 if (BCM_FAILURE(rv)) { 4934 /* dump all support group_mode */ 4935 LOG_VERBOSE(BSL_LS_BCM_POLICER, 4936 (BSL_META_U(unit, 4937 "Supported group mode:\n"))); 4938 for (group_mode = bcmPolicerGroupModeSingle; 4939 group_mode < bcmPolicerGroupModeCount; 4940 group_mode++) { 4941 rv = gm_dev_info->group_mode_supported(unit, group_mode); 4942 if (BCM_SUCCESS(rv)) { 4943 LOG_VERBOSE(BSL_LS_BCM_POLICER, 4944 (BSL_META_U(unit, "%s\n"), 4945 bcm_policer_group_mode_t_str[group_mode])); 4946 } 4947 } 4948 return BCM_E_UNAVAIL; 4949 } 4950 4951 /* Check group mode support user defined "mapping->offset_map" */ 4952 switch (group_mode) { 4953 case bcmPolicerGroupModeDot1P: 4954 case bcmPolicerGroupModeInnerDot1P: 4955 case bcmPolicerGroupModeIntPri: 4956 case bcmPolicerGroupModeIntPriCng: 4957 case bcmPolicerGroupModeShortIntPri: 4958 case bcmPolicerGroupModeSvpType: 4959 case bcmPolicerGroupModeDscp: 4960 case bcmPolicerGroupModeCascade: 4961 case bcmPolicerGroupModeIntPriCascade: 4962 case bcmPolicerGroupModeCascadeDroppedPktExclude: 4963 case bcmPolicerGroupModeCascadeWithCoupling: 4964 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 4965 case bcmPolicerGroupModePreemptable: 4966 { 4967 /* Supported */ 4968 if (mapping != NULL) { 4969 final_offset = mapping->offset_map; 4970 count = mapping->count; 4971 } 4972 break; 4973 } 4974 default: 4975 { 4976 /* Not Supported and mapping should be NULL */ 4977 if (mapping != NULL) { 4978 LOG_ERROR(BSL_LS_BCM_POLICER, 4979 (BSL_META_U(unit, 4980 "group_mode(%d = %s) doesn't not support " 4981 "flexible mapping of offset. offset_map should be NULL\n"), 4982 group_mode, 4983 bcm_policer_group_mode_t_str[group_mode])); 4984 return BCM_E_PARAM; 4985 } 4986 } 4987 } 4988 4989 switch (group_mode) { 4990 /* A single policer used for all traffic types */ 4991 case bcmPolicerGroupModeSingle: 4992 { 4993 *npolicers = 1; 4994 pkt_attr_v_cnt = 1; 4995 pkt_attr_v = 4996 &pkt_attr_selectors->pkt_attr_v[0]; 4997 pkt_attr_v->attr_bits_selector = 1; 4998 break; 4999 } 5000 /********************************************************************/ 5001 /* A dedicated policer per traffic type Unicast, multicast, */ 5002 /* broadcast */ 5003 /* 1) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT */ 5004 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT| */ 5005 /* UNKNOWN_IPMC_PKT */ 5006 /* 3) L2BC_PKT| */ 5007 /********************************************************************/ 5008 case bcmPolicerGroupModeTrafficType: 5009 { 5010 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5011 { 5012 /* 1) CONTROL_PKT|BPDU_PKT */ 5013 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5014 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5015 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5016 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| 5017 KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT */ 5018 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5019 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5020 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5021 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5022 /* 3) L2BC_PKT */ 5023 {2, bcmPolicerGroupModeAttrPktTypeL2BC} 5024 }; 5025 5026 *npolicers = 3; 5027 5028 /* following is array size of pkt_res_final_offset_v */ 5029 pkt_attr_v_cnt = 3 + 4 + 1; 5030 5031 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5032 return BCM_E_RESOURCE; 5033 } 5034 5035 attr = bcmPolicerGroupModeAttrPktType; 5036 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5037 pkt_attr_v = 5038 &pkt_attr_selectors->pkt_attr_v[sel]; 5039 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5040 pkt_attr_v->value_mask[attr] = 5041 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5042 pkt_attr_v->value[attr] = 5043 pkt_res_final_offset_v[sel].attr_pkt_type; 5044 pkt_attr_v->final_offset = 5045 pkt_res_final_offset_v[sel].final_offset; 5046 } 5047 break; 5048 } 5049 /*****************************************************************/ 5050 /* A pair of policers where the base policer is used for dlf and */ 5051 /* the other is used for all traffic types */ 5052 /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 5053 /* 2) UNKNOWN_PKT | CONTROL_PKT|BPDU_PKT|L2BC_PKT|L2UC_PKT| */ 5054 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 5055 /* UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 5056 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 5057 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 5058 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 5059 /*****************************************************************/ 5060 case bcmPolicerGroupModeDlfAll: 5061 { 5062 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5063 { 5064 /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 5065 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}, 5066 /* 2) */ 5067 {1, bcmPolicerGroupModeAttrPktTypeUnknown}, 5068 {1, bcmPolicerGroupModeAttrPktTypeControl}, 5069 {1, bcmPolicerGroupModeAttrPktTypeBPDU}, 5070 {1, bcmPolicerGroupModeAttrPktTypeL2BC}, 5071 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5072 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5073 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5074 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5075 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5076 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5077 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5078 {1, bcmPolicerGroupModeAttrPktTypeKnownMpls}, 5079 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsL3}, 5080 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsL2}, 5081 {1, bcmPolicerGroupModeAttrPktTypeUnknownMpls}, 5082 {1, bcmPolicerGroupModeAttrPktTypeKnownMim}, 5083 {1, bcmPolicerGroupModeAttrPktTypeUnknownMim}, 5084 {1, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast} 5085 }; 5086 5087 *npolicers = 2; 5088 /* following is array size of pkt_res_final_offset_v */ 5089 pkt_attr_v_cnt = 1 + 18; 5090 5091 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5092 return BCM_E_RESOURCE; 5093 } 5094 5095 attr = bcmPolicerGroupModeAttrPktType; 5096 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5097 pkt_attr_v = 5098 &pkt_attr_selectors->pkt_attr_v[sel]; 5099 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5100 pkt_attr_v->value_mask[attr] = 5101 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5102 pkt_attr_v->value[attr] = 5103 pkt_res_final_offset_v[sel].attr_pkt_type; 5104 pkt_attr_v->final_offset = 5105 pkt_res_final_offset_v[sel].final_offset; 5106 } 5107 break; 5108 } 5109 /* ******************************************************* */ 5110 /* A dedicated policer for unknown unicast, known unicast, */ 5111 /* multicast, broadcast */ 5112 /* 1) UNKNOWN_L3UC_PKT */ 5113 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 5114 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT | */ 5115 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 5116 /* 4) L2BC_PKT */ 5117 /* ******************************************************* */ 5118 case bcmPolicerGroupModeTyped: 5119 { 5120 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5121 { 5122 /* 1) UNKNOWN_L3UC_PKT */ 5123 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5124 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 5125 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5126 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5127 /* 3) */ 5128 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5129 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5130 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5131 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5132 /* 4) L2BC_PKT */ 5133 {3, bcmPolicerGroupModeAttrPktTypeL2BC} 5134 }; 5135 5136 *npolicers = 4; 5137 /* following is array size of pkt_res_final_offset_v */ 5138 pkt_attr_v_cnt = 1 + 2 + 4 + 1; 5139 5140 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5141 return BCM_E_RESOURCE; 5142 } 5143 5144 attr = bcmPolicerGroupModeAttrPktType; 5145 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5146 pkt_attr_v = 5147 &pkt_attr_selectors->pkt_attr_v[sel]; 5148 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5149 pkt_attr_v->value_mask[attr] = 5150 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5151 pkt_attr_v->value[attr] = 5152 pkt_res_final_offset_v[sel].attr_pkt_type; 5153 pkt_attr_v->final_offset = 5154 pkt_res_final_offset_v[sel].final_offset; 5155 } 5156 break; 5157 } 5158 /* ******************************************************** */ 5159 /* A dedicated policer for unknown unicast, known unicast, */ 5160 /* multicast, broadcast and one for all traffic(not already */ 5161 /* counted) */ 5162 /* 1) UNKNOWN_L3UC_PKT */ 5163 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 5164 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 5165 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 5166 /* 4) L2BC_PKT */ 5167 /* 5) UNKNOWN_PKT|CONTROL_PKT|BPDU_PKT|L2DLF_PKT| */ 5168 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_MPLS_PKT | */ 5169 /* KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT */ 5170 /* KNOWN_MIM_PKT|UNKNOWN_MIM_PKT| */ 5171 /* KNOWN_MPLS_MULTICAST_PKT */ 5172 /* ******************************************************** */ 5173 case bcmPolicerGroupModeTypedAll: 5174 { 5175 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5176 { 5177 /* 1) UNKNOWN_L3UC_PKT */ 5178 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5179 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 5180 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5181 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5182 /* 3) */ 5183 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5184 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5185 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5186 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5187 /* 4) L2BC_PKT */ 5188 {3, bcmPolicerGroupModeAttrPktTypeL2BC}, 5189 /* 5) */ 5190 {4, bcmPolicerGroupModeAttrPktTypeUnknown}, 5191 {4, bcmPolicerGroupModeAttrPktTypeControl}, 5192 {4, bcmPolicerGroupModeAttrPktTypeBPDU}, 5193 {4, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}, 5194 {4, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5195 {4, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5196 {4, bcmPolicerGroupModeAttrPktTypeKnownMpls}, 5197 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsL3}, 5198 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsL2}, 5199 {4, bcmPolicerGroupModeAttrPktTypeUnknownMpls}, 5200 {4, bcmPolicerGroupModeAttrPktTypeKnownMim}, 5201 {4, bcmPolicerGroupModeAttrPktTypeUnknownMim}, 5202 {4, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast} 5203 }; 5204 5205 *npolicers = 5; 5206 /* following is array size of pkt_res_final_offset_v */ 5207 pkt_attr_v_cnt = 1 + 2 + 4 + 1 + 13; 5208 5209 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5210 return BCM_E_RESOURCE; 5211 } 5212 5213 attr = bcmPolicerGroupModeAttrPktType; 5214 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5215 pkt_attr_v = 5216 &pkt_attr_selectors->pkt_attr_v[sel]; 5217 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5218 pkt_attr_v->value_mask[attr] = 5219 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5220 pkt_attr_v->value[attr] = 5221 pkt_res_final_offset_v[sel].attr_pkt_type; 5222 pkt_attr_v->final_offset = 5223 pkt_res_final_offset_v[sel].final_offset; 5224 } 5225 break; 5226 } 5227 /* ************************************************************** */ 5228 /* A single policer used for all traffic types with an additional */ 5229 /* policer for control traffic */ 5230 /* 1) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|L2DLF_PKT| */ 5231 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 5232 /* UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 5233 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 5234 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 5235 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 5236 /* 2) CONTROL_PKT|BPDU_PKT */ 5237 /* ************************************************************** */ 5238 case bcmPolicerGroupModeSingleWithControl: 5239 { 5240 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5241 { 5242 /* 1) */ 5243 {0, bcmPolicerGroupModeAttrPktTypeUnknown}, 5244 {0, bcmPolicerGroupModeAttrPktTypeL2BC}, 5245 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5246 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}, 5247 {0, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5248 {0, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5249 {0, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5250 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5251 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5252 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5253 {0, bcmPolicerGroupModeAttrPktTypeKnownMpls}, 5254 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsL3}, 5255 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsL2}, 5256 {0, bcmPolicerGroupModeAttrPktTypeUnknownMpls}, 5257 {0, bcmPolicerGroupModeAttrPktTypeKnownMim}, 5258 {0, bcmPolicerGroupModeAttrPktTypeUnknownMim}, 5259 {0, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast}, 5260 /* 2) CONTROL_PKT|BPDU_PKT */ 5261 {1, bcmPolicerGroupModeAttrPktTypeControl}, 5262 {1, bcmPolicerGroupModeAttrPktTypeBPDU} 5263 }; 5264 5265 *npolicers = 2; 5266 /* following is array size of pkt_res_final_offset_v */ 5267 pkt_attr_v_cnt = 17 + 2; 5268 5269 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5270 return BCM_E_RESOURCE; 5271 } 5272 5273 attr = bcmPolicerGroupModeAttrPktType; 5274 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5275 pkt_attr_v = 5276 &pkt_attr_selectors->pkt_attr_v[sel]; 5277 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5278 pkt_attr_v->value_mask[attr] = 5279 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5280 pkt_attr_v->value[attr] = 5281 pkt_res_final_offset_v[sel].attr_pkt_type; 5282 pkt_attr_v->final_offset = 5283 pkt_res_final_offset_v[sel].final_offset; 5284 } 5285 break; 5286 } 5287 /* ******************************************************** */ 5288 /* A dedicated policer per traffic type unicast, multicast, */ 5289 /* broadcast with an additional counter for control traffic */ 5290 /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT */ 5291 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| */ 5292 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 5293 /* 3) L2BC_PKT| */ 5294 /* 4) CONTROL_PKT|BPDU_PKT */ 5295 /* ******************************************************** */ 5296 case bcmPolicerGroupModeTrafficTypeWithControl: 5297 { 5298 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5299 { 5300 /* 1) L2UC_PKT|KNOWN_L3UC_PKT|UNKNOWN_L3UC_PKT */ 5301 {0, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5302 {0, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5303 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5304 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| 5305 KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 5306 {1, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5307 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5308 {1, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5309 {1, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5310 /* 3) L2BC_PKT */ 5311 {2, bcmPolicerGroupModeAttrPktTypeL2BC}, 5312 /* 4) CONTROL_PKT|BPDU_PKT */ 5313 {3, bcmPolicerGroupModeAttrPktTypeControl}, 5314 {3, bcmPolicerGroupModeAttrPktTypeBPDU} 5315 }; 5316 5317 *npolicers = 4; 5318 /* following is array size of pkt_res_final_offset_v */ 5319 pkt_attr_v_cnt = 3 + 4 + 1 + 2; 5320 5321 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5322 return BCM_E_RESOURCE; 5323 } 5324 5325 attr = bcmPolicerGroupModeAttrPktType; 5326 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5327 pkt_attr_v = 5328 &pkt_attr_selectors->pkt_attr_v[sel]; 5329 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5330 pkt_attr_v->value_mask[attr] = 5331 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5332 pkt_attr_v->value[attr] = 5333 pkt_res_final_offset_v[sel].attr_pkt_type; 5334 pkt_attr_v->final_offset = 5335 pkt_res_final_offset_v[sel].final_offset; 5336 } 5337 break; 5338 } 5339 /* *************************************************************** */ 5340 /* A set of 3 policers where the base policer is used for control, */ 5341 /* the next one for dlf and the other counter is used for all */ 5342 /* traffic types */ 5343 /* 1) CONTROL_PKT|BPDU_PKT */ 5344 /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 5345 /* 3) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT| */ 5346 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 5347 /* UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 5348 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 5349 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 5350 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 5351 /* *************************************************************** */ 5352 case bcmPolicerGroupModeDlfAllWithControl: 5353 { 5354 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5355 { 5356 /* 1) CONTROL_PKT|BPDU_PKT */ 5357 {0, bcmPolicerGroupModeAttrPktTypeControl}, 5358 {0, bcmPolicerGroupModeAttrPktTypeBPDU}, 5359 /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 5360 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}, 5361 /* 3) */ 5362 {2, bcmPolicerGroupModeAttrPktTypeUnknown}, 5363 {2, bcmPolicerGroupModeAttrPktTypeL2BC}, 5364 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5365 {2, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5366 {2, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5367 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5368 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5369 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5370 {2, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5371 {2, bcmPolicerGroupModeAttrPktTypeKnownMpls}, 5372 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsL3}, 5373 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsL2}, 5374 {2, bcmPolicerGroupModeAttrPktTypeUnknownMpls}, 5375 {2, bcmPolicerGroupModeAttrPktTypeKnownMim}, 5376 {2, bcmPolicerGroupModeAttrPktTypeUnknownMim}, 5377 {2, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast} 5378 }; 5379 5380 *npolicers = 3; 5381 /* following is array size of pkt_res_final_offset_v */ 5382 pkt_attr_v_cnt = 2 + 1 + 16; 5383 5384 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5385 return BCM_E_RESOURCE; 5386 } 5387 5388 attr = bcmPolicerGroupModeAttrPktType; 5389 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5390 pkt_attr_v = 5391 &pkt_attr_selectors->pkt_attr_v[sel]; 5392 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5393 pkt_attr_v->value_mask[attr] = 5394 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5395 pkt_attr_v->value[attr] = 5396 pkt_res_final_offset_v[sel].attr_pkt_type; 5397 pkt_attr_v->final_offset = 5398 pkt_res_final_offset_v[sel].final_offset; 5399 } 5400 break; 5401 } 5402 /* **************************************************************** */ 5403 /* A dedicated policer for control, unknown unicast, known unicast, */ 5404 /* multicast, broadcast */ 5405 /* 1) CONTROL_PKT|BPDU_PKT */ 5406 /* 2) UNKNOWN_L3UC_PKT */ 5407 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5408 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| */ 5409 /* KNOWN_IPMC_PKT| UNKNOWN_IPMC_PKT */ 5410 /* 5) L2BC_PKT */ 5411 /* **************************************************************** */ 5412 case bcmPolicerGroupModeTypedWithControl: 5413 { 5414 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5415 { 5416 /* 1) CONTROL_PKT|BPDU_PKT */ 5417 {0, bcmPolicerGroupModeAttrPktTypeControl}, 5418 {0, bcmPolicerGroupModeAttrPktTypeBPDU}, 5419 /* 2) UNKNOWN_L3UC_PKT */ 5420 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5421 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5422 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5423 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5424 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| 5425 KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT */ 5426 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5427 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5428 {3, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5429 {3, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5430 /* 5) L2BC_PKT */ 5431 {4, bcmPolicerGroupModeAttrPktTypeL2BC} 5432 }; 5433 5434 *npolicers = 5; 5435 /* following is array size of pkt_res_final_offset_v */ 5436 pkt_attr_v_cnt = 2 + 1 + 2 + 4 + 1; 5437 5438 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5439 return BCM_E_RESOURCE; 5440 } 5441 5442 attr = bcmPolicerGroupModeAttrPktType; 5443 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5444 pkt_attr_v = 5445 &pkt_attr_selectors->pkt_attr_v[sel]; 5446 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5447 pkt_attr_v->value_mask[attr] = 5448 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5449 pkt_attr_v->value[attr] = 5450 pkt_res_final_offset_v[sel].attr_pkt_type; 5451 pkt_attr_v->final_offset = 5452 pkt_res_final_offset_v[sel].final_offset; 5453 } 5454 break; 5455 } 5456 /* ***************************************************************** */ 5457 /* A dedicated policer for control, unknown unicast, known unicast, */ 5458 /* multicast, broadcast and one for all traffic (not already policed)*/ 5459 /* 1) CONTROL_PKT|BPDU_PKT */ 5460 /* 2) UNKNOWN_L3UC_PKT */ 5461 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5462 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT| */ 5463 /* UNKNOWN_IPMC_PKT */ 5464 /* 5) L2BC_PKT */ 5465 /* 6) UNKNOWN_PKT|L2DLF_PKT|UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT */ 5466 /* KNOWN_MPLS_PKT | KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT| */ 5467 /* UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|UNKNOWN_MIM_PKT| */ 5468 /* KNOWN_MPLS_MULTICAST_PKT */ 5469 /* ***************************************************************** */ 5470 case bcmPolicerGroupModeTypedAllWithControl: 5471 { 5472 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5473 { 5474 /* 1) CONTROL_PKT|BPDU_PKT */ 5475 {0, bcmPolicerGroupModeAttrPktTypeControl}, 5476 {0, bcmPolicerGroupModeAttrPktTypeBPDU}, 5477 /* 2) UNKNOWN_L3UC_PKT */ 5478 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5479 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5480 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5481 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5482 /* 4) */ 5483 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5484 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5485 {3, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5486 {3, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5487 /* 5) L2BC_PKT */ 5488 {4, bcmPolicerGroupModeAttrPktTypeL2BC}, 5489 /* 6) */ 5490 {5, bcmPolicerGroupModeAttrPktTypeUnknown}, 5491 {5, bcmPolicerGroupModeAttrPktTypeUnknownL2UC}, 5492 {5, bcmPolicerGroupModeAttrPktTypeUnknownIPMC}, 5493 {5, bcmPolicerGroupModeAttrPktTypeKnownIPMC}, 5494 {5, bcmPolicerGroupModeAttrPktTypeKnownMpls}, 5495 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsL3}, 5496 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsL2}, 5497 {5, bcmPolicerGroupModeAttrPktTypeUnknownMpls}, 5498 {5, bcmPolicerGroupModeAttrPktTypeKnownMim}, 5499 {5, bcmPolicerGroupModeAttrPktTypeUnknownMim}, 5500 {5, bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast} 5501 }; 5502 5503 *npolicers = 6; 5504 /* following is array size of pkt_res_final_offset_v */ 5505 pkt_attr_v_cnt = 2 + 1 + 2 + 4 + 1 + 11; 5506 5507 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5508 return BCM_E_RESOURCE; 5509 } 5510 5511 attr = bcmPolicerGroupModeAttrPktType; 5512 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5513 pkt_attr_v = 5514 &pkt_attr_selectors->pkt_attr_v[sel]; 5515 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5516 pkt_attr_v->value_mask[attr] = 5517 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5518 pkt_attr_v->value[attr] = 5519 pkt_res_final_offset_v[sel].attr_pkt_type; 5520 pkt_attr_v->final_offset = 5521 pkt_res_final_offset_v[sel].final_offset; 5522 } 5523 break; 5524 } 5525 /* ********************************************************* */ 5526 /* A set of 8(2^3) policers selected based on outer Vlan pri */ 5527 /* outer_dot1p; 3 bits 1..8 */ 5528 /* ********************************************************* */ 5529 case bcmPolicerGroupModeDot1P: 5530 { 5531 *npolicers = 8; 5532 /* following is array size of pkt_res_final_offset_v */ 5533 pkt_attr_v_cnt = 8; 5534 5535 /* customize defined count & final_offset */ 5536 if (mapping != NULL) { 5537 pkt_attr_v_cnt = count; 5538 *npolicers = pkt_attr_v_cnt; 5539 } 5540 5541 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5542 return BCM_E_RESOURCE; 5543 } 5544 5545 attr = bcmPolicerGroupModeAttrOuterPri; 5546 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5547 pkt_attr_v = 5548 &pkt_attr_selectors->pkt_attr_v[sel]; 5549 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5550 pkt_attr_v->value[attr] = sel; 5551 pkt_attr_v->value_mask[attr] = 5552 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5553 pkt_attr_v->final_offset = (mapping == NULL) ? 5554 sel : final_offset[sel]; 5555 } 5556 break; 5557 } 5558 /* ********************************************************* */ 5559 /* A set of 8(2^3) policers selected based on inner Vlan pri */ 5560 /* inner_dot1p; 3 bits 1..8 */ 5561 /* ******************************************************** */ 5562 case bcmPolicerGroupModeInnerDot1P: 5563 { 5564 *npolicers = 8; 5565 pkt_attr_v_cnt = 8; 5566 5567 /* customize defined count & final_offset */ 5568 if (mapping != NULL) { 5569 pkt_attr_v_cnt = count; 5570 *npolicers = pkt_attr_v_cnt; 5571 } 5572 5573 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5574 return BCM_E_RESOURCE; 5575 } 5576 5577 attr = bcmPolicerGroupModeAttrInnerPri; 5578 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5579 pkt_attr_v = 5580 &pkt_attr_selectors->pkt_attr_v[sel]; 5581 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5582 pkt_attr_v->value[attr] = sel; 5583 pkt_attr_v->value_mask[attr] = 5584 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5585 pkt_attr_v->final_offset = (mapping == NULL) ? 5586 sel : final_offset[sel]; 5587 } 5588 break; 5589 } 5590 /* **************************************************** */ 5591 /* A set of 16(2^4) policers based on internal priority */ 5592 /* 1..16 INT_PRI bits: 4bits */ 5593 /* **************************************************** */ 5594 case bcmPolicerGroupModeIntPri: 5595 { 5596 *npolicers = 16; 5597 pkt_attr_v_cnt = 16; 5598 5599 /* customize defined count & final_offset */ 5600 if (mapping != NULL) { 5601 pkt_attr_v_cnt = count; 5602 *npolicers = pkt_attr_v_cnt; 5603 } 5604 5605 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5606 return BCM_E_RESOURCE; 5607 } 5608 5609 attr = bcmPolicerGroupModeAttrIntPri; 5610 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5611 pkt_attr_v = 5612 &pkt_attr_selectors->pkt_attr_v[sel]; 5613 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5614 pkt_attr_v->value[attr] = sel; 5615 pkt_attr_v->value_mask[attr] = 5616 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5617 pkt_attr_v->final_offset = (mapping == NULL) ? 5618 sel : final_offset[sel]; 5619 } 5620 break; 5621 } 5622 /* ********************************************************** */ 5623 /* set of 64 policers(2^(4+2)) based on Internal priority+CNG */ 5624 /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits */ 5625 /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits */ 5626 /* ********************************************************** */ 5627 case bcmPolicerGroupModeIntPriCng: 5628 { 5629 return BCM_E_UNAVAIL; 5630 break; 5631 } 5632 /* ********************************************************** */ 5633 /* set of 8 policers(2^3) based on Internal priority */ 5634 /* 1..8 INT_PRI bits: 3bits */ 5635 /* ********************************************************** */ 5636 case bcmPolicerGroupModeShortIntPri: 5637 { 5638 *npolicers = 8; 5639 pkt_attr_v_cnt = 8; 5640 5641 /* customize defined count & final_offset */ 5642 if (mapping != NULL) { 5643 pkt_attr_v_cnt = count; 5644 *npolicers = pkt_attr_v_cnt; 5645 } 5646 5647 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5648 return BCM_E_RESOURCE; 5649 } 5650 5651 attr = bcmPolicerGroupModeAttrIntPri; 5652 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5653 pkt_attr_v = 5654 &pkt_attr_selectors->pkt_attr_v[sel]; 5655 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5656 pkt_attr_v->value[attr] = sel; 5657 pkt_attr_v->value_mask[attr] = 5658 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5659 pkt_attr_v->final_offset = (mapping == NULL) ? 5660 sel : final_offset[sel]; 5661 } 5662 break; 5663 } 5664 /* ****************************************** */ 5665 /* A set of 2 policers(2^1) based on SVP type */ 5666 /* 1..2 (SVP 1 bit). In case of KT2, SVP is 3 */ 5667 /* 3 bits and hence no of policers is 8 */ 5668 /* ********************************************/ 5669 case bcmPolicerGroupModeSvpType: 5670 { 5671 return BCM_E_UNAVAIL; 5672 } 5673 /* ******************************************** */ 5674 /* A set of 64 policers(2^6) based on DSCP bits */ 5675 /* 1..64 (6 bits from TOS 8 bits) */ 5676 /* ******************************************** */ 5677 case bcmPolicerGroupModeDscp: 5678 { 5679 return BCM_E_UNAVAIL; 5680 } 5681 /* ******************************************** */ 5682 /* A set of n policers based on user input */ 5683 /* ******************************************** */ 5684 case bcmPolicerGroupModeCascade: 5685 { 5686 return BCM_E_UNAVAIL; 5687 } 5688 /* ******************************************************* */ 5689 /* A set of n policers based on user input based on IntPri */ 5690 /* ******************************************************* */ 5691 case bcmPolicerGroupModeIntPriCascade: 5692 { 5693 return BCM_E_UNAVAIL; 5694 } 5695 /* ************************************************************** */ 5696 /* A set of n policers based on user input, with dropped packets */ 5697 /* not eligible for metering */ 5698 /* ************************************************************** */ 5699 case bcmPolicerGroupModeCascadeDroppedPktExclude: 5700 { 5701 return BCM_E_UNAVAIL; 5702 } 5703 /* ******************************************** */ 5704 /* A set of n policers based on user input */ 5705 /* ******************************************** */ 5706 case bcmPolicerGroupModeCascadeWithCoupling: 5707 { 5708 return BCM_E_UNAVAIL; 5709 } 5710 /* ******************************************** */ 5711 /* A set of n policers based on user input */ 5712 /* ******************************************** */ 5713 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 5714 { 5715 return BCM_E_UNAVAIL; 5716 } 5717 /* *************************************************************** */ 5718 /* N+1 policers where in the base counter is used for dlf and next */ 5719 /* N are used as per Cos */ 5720 /* 1) L2_DLF(UNKNOWN_L2UC_PKT) */ 5721 /* 2..17) INT_PRI bits: 4bits */ 5722 /* *************************************************************** */ 5723 case bcmPolicerGroupModeDlfIntPri: 5724 { 5725 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5726 { 5727 /* 1) L2_DLF(UNKNOWN_L2UC_PKT) */ 5728 {0, bcmPolicerGroupModeAttrPktTypeUnknownL2UC} 5729 }; 5730 5731 *npolicers = 17; 5732 5733 /* following is array size of pkt_res_final_offset_v */ 5734 pkt_attr_pkt_type_cnt = 1; 5735 pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16; 5736 5737 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5738 return BCM_E_RESOURCE; 5739 } 5740 5741 attr = bcmPolicerGroupModeAttrPktType; 5742 for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) { 5743 pkt_attr_v = 5744 &pkt_attr_selectors->pkt_attr_v[sel]; 5745 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5746 pkt_attr_v->value_mask[attr] = 5747 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5748 pkt_attr_v->value[attr] = 5749 pkt_res_final_offset_v[sel].attr_pkt_type; 5750 pkt_attr_v->final_offset = 5751 pkt_res_final_offset_v[sel].final_offset; 5752 5753 /* for following final_offset */ 5754 if (base_final_offset < pkt_attr_v->final_offset) { 5755 base_final_offset = pkt_attr_v->final_offset; 5756 } 5757 } 5758 base_final_offset += 1; 5759 5760 attr = bcmPolicerGroupModeAttrIntPri; 5761 for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) { 5762 pkt_attr_v = 5763 &pkt_attr_selectors->pkt_attr_v[sel]; 5764 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5765 pkt_attr_v->value[attr] = 5766 sel - pkt_attr_pkt_type_cnt; 5767 pkt_attr_v->value_mask[attr] = 5768 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5769 pkt_attr_v->final_offset = 5770 base_final_offset + sel - pkt_attr_pkt_type_cnt; 5771 } 5772 break; 5773 } 5774 /* ***************************************************************** */ 5775 /* A dedicated policer for unknown unicast, known unicast, */ 5776 /* multicast, broadcast and N internal priority policers for traffic */ 5777 /* (not already policed) */ 5778 /* 1) UNKNOWN_L3UC_PKT */ 5779 /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5780 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 5781 /* 4) L2BC_PKT */ 5782 /* 5..20) INT_PRI bits: 4bits */ 5783 /* ***************************************************************** */ 5784 case bcmPolicerGroupModeTypedIntPri: 5785 { 5786 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5787 { 5788 /* 1) UNKNOWN_L3UC_PKT */ 5789 {0, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5790 /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5791 {1, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5792 {1, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5793 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 5794 {2, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5795 {2, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5796 /* 4) L2BC_PKT */ 5797 {3, bcmPolicerGroupModeAttrPktTypeL2BC} 5798 }; 5799 5800 *npolicers = 20; 5801 /* following is array size of pkt_res_final_offset_v */ 5802 pkt_attr_pkt_type_cnt = 1 + 2 + 2 + 1; 5803 pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16; 5804 5805 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5806 return BCM_E_RESOURCE; 5807 } 5808 5809 attr = bcmPolicerGroupModeAttrPktType; 5810 for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) { 5811 pkt_attr_v = 5812 &pkt_attr_selectors->pkt_attr_v[sel]; 5813 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5814 pkt_attr_v->value_mask[attr] = 5815 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5816 pkt_attr_v->value[attr] = 5817 pkt_res_final_offset_v[sel].attr_pkt_type; 5818 pkt_attr_v->final_offset = 5819 pkt_res_final_offset_v[sel].final_offset; 5820 /* for following final_offset */ 5821 if (base_final_offset < pkt_attr_v->final_offset) { 5822 base_final_offset = pkt_attr_v->final_offset; 5823 } 5824 } 5825 base_final_offset += 1; 5826 5827 attr = bcmPolicerGroupModeAttrIntPri; 5828 for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) { 5829 pkt_attr_v = 5830 &pkt_attr_selectors->pkt_attr_v[sel]; 5831 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5832 pkt_attr_v->value[attr] = 5833 sel - pkt_attr_pkt_type_cnt; 5834 pkt_attr_v->value_mask[attr] = 5835 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5836 pkt_attr_v->final_offset = 5837 base_final_offset + sel - pkt_attr_pkt_type_cnt; 5838 } 5839 break; 5840 } 5841 /* ************************************************************* */ 5842 /* N+2 policers where the base policers is used for control, the */ 5843 /* next one for dlf and next N are used per Cos */ 5844 /* 1) CONTROL_PKT|BPDU_PKT */ 5845 /* 2) L2_DLF(UNKNOWN_L2UC_PKT) */ 5846 /* 3..18) INT_PRI bits: 4bits */ 5847 /* ************************************************************* */ 5848 case bcmPolicerGroupModeDlfIntPriWithControl: 5849 { 5850 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5851 { 5852 /* 1) CONTROL_PKT|BPDU_PKT */ 5853 {0, bcmPolicerGroupModeAttrPktTypeControl}, 5854 {0, bcmPolicerGroupModeAttrPktTypeBPDU}, 5855 /* 2) L2_DLF(UNKNOWN_L2UC_PKT) */ 5856 {1, bcmPolicerGroupModeAttrPktTypeUnknownL2UC} 5857 }; 5858 5859 *npolicers = 18; 5860 /* following is array size of pkt_res_final_offset_v */ 5861 pkt_attr_pkt_type_cnt = 2 + 1; 5862 pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16; 5863 5864 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5865 return BCM_E_RESOURCE; 5866 } 5867 5868 attr = bcmPolicerGroupModeAttrPktType; 5869 for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) { 5870 pkt_attr_v = 5871 &pkt_attr_selectors->pkt_attr_v[sel]; 5872 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5873 pkt_attr_v->value_mask[attr] = 5874 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5875 pkt_attr_v->value[attr] = 5876 pkt_res_final_offset_v[sel].attr_pkt_type; 5877 pkt_attr_v->final_offset = 5878 pkt_res_final_offset_v[sel].final_offset; 5879 /* for following final_offset */ 5880 if (base_final_offset < pkt_attr_v->final_offset) { 5881 base_final_offset = pkt_attr_v->final_offset; 5882 } 5883 } 5884 base_final_offset += 1; 5885 5886 /* 3..18) INT_PRI bits: 4bits */ 5887 attr = bcmPolicerGroupModeAttrIntPri; 5888 for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) { 5889 pkt_attr_v = 5890 &pkt_attr_selectors->pkt_attr_v[sel]; 5891 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5892 pkt_attr_v->value[attr] = 5893 sel - pkt_attr_pkt_type_cnt; 5894 pkt_attr_v->value_mask[attr] = 5895 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5896 pkt_attr_v->final_offset = 5897 base_final_offset + sel - pkt_attr_pkt_type_cnt; 5898 } 5899 break; 5900 } 5901 /* *************************************************************** */ 5902 /* A dedicated counter for control, unknown unicast, known unicast */ 5903 /* , multicast, broadcast and N internal priority counters for */ 5904 /* traffic (not already counted) */ 5905 /* 1) CONTROL_PKT|BPDU_PKT */ 5906 /* 2) UNKNOWN_L3UC_PKT */ 5907 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5908 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 5909 /* 5) L2BC_PKT */ 5910 /* 6..21) INT_PRI bits: 4bits */ 5911 /* *************************************************************** */ 5912 case bcmPolicerGroupModeTypedIntPriWithControl: 5913 { 5914 pkt_res_final_offset_t pkt_res_final_offset_v[] = 5915 { 5916 /* 1) CONTROL_PKT|BPDU_PKT */ 5917 {0, bcmPolicerGroupModeAttrPktTypeControl}, 5918 {0, bcmPolicerGroupModeAttrPktTypeBPDU}, 5919 /* 2) UNKNOWN_L3UC_PKT */ 5920 {1, bcmPolicerGroupModeAttrPktTypeUnknownL3UC}, 5921 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 5922 {2, bcmPolicerGroupModeAttrPktTypeKnownL2UC}, 5923 {2, bcmPolicerGroupModeAttrPktTypeKnownL3UC}, 5924 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 5925 {3, bcmPolicerGroupModeAttrPktTypeKnownL2MC}, 5926 {3, bcmPolicerGroupModeAttrPktTypeUnknownL2MC}, 5927 /* 5) L2BC_PKT */ 5928 {4, bcmPolicerGroupModeAttrPktTypeL2BC} 5929 }; 5930 *npolicers = 21; 5931 /* following is array size of pkt_res_final_offset_v */ 5932 pkt_attr_pkt_type_cnt = 2 + 1 + 2 + 2 + 1; 5933 pkt_attr_v_cnt = pkt_attr_pkt_type_cnt + 16; 5934 5935 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5936 return BCM_E_RESOURCE; 5937 } 5938 5939 attr = bcmPolicerGroupModeAttrPktType; 5940 for (sel = 0; sel < pkt_attr_pkt_type_cnt; sel++) { 5941 pkt_attr_v = 5942 &pkt_attr_selectors->pkt_attr_v[sel]; 5943 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5944 pkt_attr_v->value_mask[attr] = 5945 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5946 pkt_attr_v->value[attr] = 5947 pkt_res_final_offset_v[sel].attr_pkt_type; 5948 pkt_attr_v->final_offset = 5949 pkt_res_final_offset_v[sel].final_offset; 5950 /* for following final_offset */ 5951 if (base_final_offset < pkt_attr_v->final_offset) { 5952 base_final_offset = pkt_attr_v->final_offset; 5953 } 5954 } 5955 base_final_offset += 1; 5956 5957 /* 6..21) INT_PRI bits: 4bits */ 5958 attr = bcmPolicerGroupModeAttrIntPri; 5959 for (sel = pkt_attr_pkt_type_cnt; sel < pkt_attr_v_cnt; sel++) { 5960 pkt_attr_v = 5961 &pkt_attr_selectors->pkt_attr_v[sel]; 5962 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5963 pkt_attr_v->value[attr] = 5964 sel - pkt_attr_pkt_type_cnt; 5965 pkt_attr_v->value_mask[attr] = 5966 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5967 pkt_attr_v->final_offset = 5968 base_final_offset + sel - pkt_attr_pkt_type_cnt; 5969 } 5970 break; 5971 } 5972 /* ************************************************** */ 5973 /* A dedicated counter for control, preemptable and */ 5974 /* non-preemptable packet */ 5975 /* 1) none-preemptable PKT */ 5976 /* 2) preemptable PKT */ 5977 /* ************************************************** */ 5978 case bcmPolicerGroupModePreemptable: 5979 { 5980 *npolicers = 2; 5981 pkt_attr_v_cnt = 2; 5982 5983 if (pkt_attr_v_cnt > BCMI_POLICER_SVC_METER_TCAM_SIZE) { 5984 return BCM_E_RESOURCE; 5985 } 5986 5987 attr = bcmPolicerGroupModeAttrPreemptable; 5988 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 5989 pkt_attr_v = 5990 &pkt_attr_selectors->pkt_attr_v[sel]; 5991 pkt_attr_v->attr_bits_selector = attr_to_bit_selector[attr]; 5992 pkt_attr_v->value[attr] = sel; 5993 pkt_attr_v->value_mask[attr] = 5994 BCMI_POLICER_GLOBAL_METER_ATTR_MASK_ALL; 5995 pkt_attr_v->final_offset = (mapping == NULL) ? 5996 sel : final_offset[sel]; 5997 5998 } 5999 break; 6000 } 6001 6002 default: 6003 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6004 (BSL_META_U(unit, 6005 "Invalid policer group mode\n"))); 6006 return BCM_E_PARAM; 6007 6008 } 6009 6010 for (sel = 0; sel < pkt_attr_v_cnt; sel++) { 6011 pkt_attr_v = &pkt_attr_selectors->pkt_attr_v[sel]; 6012 6013 (void)bcmi_policer_tcam_attr_dump( 6014 unit, "pkt_attr_v", pkt_attr_v); 6015 6016 /* Final Offset */ 6017 pol_offset = pkt_attr_v->final_offset; 6018 6019 /* Record Maximum Policer Offset */ 6020 if (max_pol_offset < pol_offset) { 6021 max_pol_offset = pol_offset; 6022 } 6023 } 6024 6025 /* Check Maximum Policer Offset */ 6026 if (max_pol_offset >= *npolicers) { 6027 LOG_ERROR(BSL_LS_BCM_POLICER, 6028 (BSL_META_U(unit, 6029 "Maximum policer offset(%d) should less than" 6030 " total policer number(%d).\n"), 6031 max_pol_offset, 6032 *npolicers)); 6033 return BCM_E_PARAM; 6034 } 6035 6036 pkt_attr_selectors->total_policers = *npolicers; 6037 pkt_attr_selectors->pkt_attr_v_cnt = pkt_attr_v_cnt; 6038 6039 POL_FUNCTION_TRACE(unit, "OUT"); 6040 return rv; 6041 } 6042 6043 /* 6044 * Function: 6045 * bcmi_esw_policer_group_create 6046 * Purpose: 6047 * Create a group of policers based on the mode. 6048 * Parameters: 6049 * unit - (IN) unit number 6050 * group_mode - (IN) Policer group mode 6051 * flow_info - (IN) Information regarding flow type and skip pool 6052 * offset_map - (IN) Attr_value to policer_offset mapping 6053 * policer_id - (OUT) Base policer id 6054 * npolicers - (OUT) Number of policers 6055 * Returns: 6056 * BCM_E_XXX 6057 */ 6058 STATIC int 6059 bcmi_esw_policer_group_create( 6060 int unit, 6061 bcm_policer_group_mode_t group_mode, 6062 _bcm_policer_flow_info_t *flow_info, 6063 bcm_policer_map_t *offset_map, 6064 bcm_policer_t *policer_id, 6065 int *npolicers) 6066 { 6067 bcm_error_t rv = BCM_E_UNAVAIL; 6068 bcm_policer_svc_meter_mode_t offset_mode = 0; 6069 uint32 mode_id = 0; 6070 int policer_idx; 6071 bcmi_policer_tcam_attr_selectors_t pkt_attr_selectors; 6072 bcmi_global_meter_policer_control_t *policer_control = NULL; 6073 bcm_policer_group_mode_type_t group_mode_type; 6074 6075 POL_FUNCTION_TRACE(unit, "IN"); 6076 6077 /* Parameter NULL error handling */ 6078 POL_CHECK_NULL_PARAMETER(unit, flow_info); 6079 POL_CHECK_NULL_PARAMETER(unit, policer_id); 6080 POL_CHECK_NULL_PARAMETER(unit, npolicers); 6081 6082 /* Initialization check */ 6083 CHECK_GLOBAL_METER_INIT(unit); 6084 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6085 6086 (void)bcmi_policer_tcam_attr_selectors_t_init(&pkt_attr_selectors); 6087 POL_MEM_ALLOC( 6088 pkt_attr_selectors.pkt_attr_v, 6089 sizeof(pkt_tcam_attr_bits_t) * BCMI_POLICER_SVC_METER_TCAM_SIZE, 6090 "Global meter policer"); 6091 6092 if (NULL == pkt_attr_selectors.pkt_attr_v) { 6093 LOG_ERROR(BSL_LS_BCM_POLICER, 6094 (BSL_META_U(unit, 6095 "Unable to allocate memory for " 6096 "pkt_attr_selectors.pkt_attr_v\n"))); 6097 return (BCM_E_MEMORY); 6098 } 6099 6100 /* Create temporary pkt information from group_mode */ 6101 rv = bcmi_esw_policer_group_set_mode_and_map( 6102 unit, group_mode, offset_map, npolicers, &pkt_attr_selectors); 6103 6104 if (BCM_FAILURE(rv)) { 6105 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6106 LOG_ERROR(BSL_LS_BCM_POLICER, 6107 (BSL_META_U(unit, 6108 "Failed to set mode and map\n"))); 6109 return rv; 6110 } 6111 6112 GLOBAL_METER_LOCK(unit); 6113 6114 if (group_mode == bcmPolicerGroupModeCascade) { 6115 group_mode_type = bcmPolicerGroupModeTypeCascade; 6116 } else if (group_mode == bcmPolicerGroupModeCascadeWithCoupling) { 6117 group_mode_type = bcmPolicerGroupModeTypeCascadeWithCoupling; 6118 } else { 6119 group_mode_type = bcmPolicerGroupModeTypeNormal; 6120 } 6121 6122 if (*npolicers >= 1) { 6123 rv = bcmi_esw_policer_svc_meter_create_mode(unit, 6124 &pkt_attr_selectors, group_mode, group_mode_type, 6125 *npolicers, &mode_id); 6126 if (BCM_FAILURE(rv)) { 6127 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6128 GLOBAL_METER_UNLOCK(unit); 6129 return rv; 6130 } 6131 } 6132 6133 offset_mode = MODE_ID_TO_OFFSET_MODE(mode_id); 6134 6135 rv = bcmi_global_meter_policer_id_alloc( 6136 unit, *npolicers, &policer_idx); 6137 6138 if (BCM_FAILURE(rv)) { 6139 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6140 GLOBAL_METER_UNLOCK(unit); 6141 LOG_ERROR(BSL_LS_BCM_POLICER, 6142 (BSL_META_U(unit, 6143 "Failed to allocate policer\n"))); 6144 return rv; 6145 } 6146 6147 /* Allocate policer descriptor. */ 6148 rv = bcmi_global_meter_policer_control_alloc( 6149 unit, *npolicers, &policer_control); 6150 if (BCM_FAILURE(rv)) { 6151 GLOBAL_METER_UNLOCK(unit); 6152 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6153 bcmi_global_meter_free_allocated_policer_on_error( 6154 unit, *npolicers, policer_idx); 6155 LOG_ERROR(BSL_LS_BCM_POLICER, 6156 (BSL_META_U(unit, 6157 "Unable to allocate memory for " 6158 "policer control\n"))); 6159 return (rv); 6160 } 6161 6162 /* Add mode info to the policer index */ 6163 *policer_id = POLICER_IDX_TO_POLICER_ID(offset_mode, policer_idx); 6164 6165 /* Set policer configuration */ 6166 policer_control->pid = *policer_id; 6167 policer_control->no_of_policers = *npolicers; 6168 policer_control->grp_mode = group_mode; 6169 6170 /* increment mode reference count for new policer */ 6171 rv = bcmi_policer_svc_meter_inc_mode_ref_cnt(unit, offset_mode); 6172 if (BCM_FAILURE(rv)) { 6173 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6174 /* free all the allocated policers */ 6175 bcmi_global_meter_free_allocated_policer_on_error( 6176 unit, *npolicers, policer_idx); 6177 /* De-allocate policer descriptor. */ 6178 POL_MEM_FREE(policer_control->pol_cfg); 6179 POL_MEM_FREE(policer_control); 6180 GLOBAL_METER_UNLOCK(unit); 6181 return rv; 6182 } 6183 6184 /* Insert policer into policers hash. */ 6185 _GLOBAL_METER_HASH_INSERT(BCMI_POLICER_BK_GET(unit), 6186 policer_control, 6187 (*policer_id & _GLOBAL_METER_HASH_MASK)); 6188 GLOBAL_METER_UNLOCK(unit); 6189 POL_MEM_FREE(pkt_attr_selectors.pkt_attr_v); 6190 6191 POL_FUNCTION_DEBUG(unit, "policer_id 0x%x", *policer_id); 6192 POL_FUNCTION_TRACE(unit, "OUT"); 6193 return BCM_E_NONE; 6194 } 6195 6196 #endif /* POLICER_ID_API_SECTION */ 6197 6198 #if ACTION_API_SECTION 6199 /* 6200 * Function: 6201 * bcmi_esw_policer_action_create 6202 * Purpose: 6203 * Create a new action entry in meter action table 6204 * Parameters: 6205 * unit - (IN) unit number 6206 * action_id - (OUT) Action Id created 6207 * Returns: 6208 * BCM_E_XXX 6209 */ 6210 STATIC int 6211 bcmi_esw_policer_action_create( 6212 int unit, 6213 uint32 *action_id) 6214 { 6215 int rv = BCM_E_NONE; 6216 6217 /* Parameter NULL error handling */ 6218 POL_CHECK_NULL_PARAMETER(unit, action_id); 6219 6220 CHECK_GLOBAL_METER_INIT(unit); 6221 rv = shr_aidxres_list_alloc_block( 6222 BCMI_ACTION_LIST_HANDLE_GET(unit), 1, (uint32 *)action_id); 6223 if (BCM_FAILURE(rv)) { 6224 LOG_ERROR(BSL_LS_BCM_POLICER, 6225 (BSL_META_U(unit, 6226 "Unable to allocate a handle for new " 6227 "action\n"))); 6228 return (rv); 6229 } 6230 BCMI_ACTION_ID_BK_GET(unit, *action_id).actions_count = 0; 6231 BCMI_ACTION_ID_BK_GET(unit, *action_id).used = 1; 6232 6233 POL_FUNCTION_DEBUG(unit, "action_id (%d) created", *action_id); 6234 return rv; 6235 } 6236 6237 /* Validate the action para is in the valid value range or not */ 6238 STATIC int 6239 bcmi_esw_policer_action_add_param_check( 6240 int unit, 6241 bcm_policer_action_t action, 6242 uint32 param0) 6243 { 6244 switch (action) { 6245 case bcmPolicerActionGpDrop: 6246 case bcmPolicerActionYpDrop: 6247 case bcmPolicerActionRpDrop: 6248 if (param0 != 0) { 6249 LOG_ERROR(BSL_LS_BCM_POLICER, 6250 (BSL_META_U(unit, 6251 "Invalid value for Drop\n"))); 6252 return BCM_E_PARAM; 6253 } 6254 break; 6255 case bcmPolicerActionGpEcnNew: 6256 case bcmPolicerActionYpEcnNew: 6257 case bcmPolicerActionRpEcnNew: 6258 if (param0 > 0x3) { 6259 LOG_ERROR(BSL_LS_BCM_POLICER, 6260 (BSL_META_U(unit, 6261 "Invalid value for ECN\n"))); 6262 return BCM_E_PARAM; 6263 } 6264 break; 6265 case bcmPolicerActionGpDscpNew: 6266 case bcmPolicerActionYpDscpNew: 6267 case bcmPolicerActionRpDscpNew: 6268 if (param0 > 0x3f) { 6269 LOG_ERROR(BSL_LS_BCM_POLICER, 6270 (BSL_META_U(unit, 6271 "Invalid value for DSCP\n"))); 6272 return BCM_E_PARAM; 6273 } 6274 break; 6275 case bcmPolicerActionGpPrioIntNew: 6276 case bcmPolicerActionYpPrioIntNew: 6277 case bcmPolicerActionRpPrioIntNew: 6278 if (param0 > 0xf) { 6279 LOG_ERROR(BSL_LS_BCM_POLICER, 6280 (BSL_META_U(unit, 6281 "Invalid value for int pri\n"))); 6282 return BCM_E_PARAM; 6283 } 6284 break; 6285 case bcmPolicerActionGpCngNew: 6286 case bcmPolicerActionYpCngNew: 6287 case bcmPolicerActionRpCngNew: 6288 if (param0 > 0x3) { 6289 LOG_ERROR(BSL_LS_BCM_POLICER, 6290 (BSL_META_U(unit, 6291 "Invalid value for CNG\n"))); 6292 return BCM_E_PARAM; 6293 } 6294 break; 6295 case bcmPolicerActionGpVlanPrioNew: 6296 case bcmPolicerActionYpVlanPrioNew: 6297 case bcmPolicerActionRpVlanPrioNew: 6298 if (param0 > 0x7) { 6299 LOG_ERROR(BSL_LS_BCM_POLICER, 6300 (BSL_META_U(unit, 6301 "Invalid value for vlan pri\n"))); 6302 return BCM_E_PARAM; 6303 } 6304 break; 6305 case bcmPolicerActionGpIntCongestionNotificationNew: 6306 case bcmPolicerActionYpIntCongestionNotificationNew: 6307 case bcmPolicerActionRpIntCongestionNotificationNew: 6308 if (param0 > 0x3) { 6309 LOG_ERROR(BSL_LS_BCM_POLICER, 6310 (BSL_META_U(unit, 6311 "Invalid value for " 6312 "Congestion Notification\n"))); 6313 return BCM_E_PARAM; 6314 } 6315 break; 6316 default: 6317 LOG_ERROR(BSL_LS_BCM_POLICER, 6318 (BSL_META_U(unit, 6319 "Unsupported Action specified\n"))); 6320 return BCM_E_PARAM; 6321 } 6322 return BCM_E_NONE; 6323 } 6324 6325 /* 6326 * Function: 6327 * bcmi_esw_policer_action_add 6328 * Purpose: 6329 * Add an entry to meter action table 6330 * Parameters: 6331 * unit - (IN) unit number 6332 * action_id - (IN) Action Id created 6333 * action - (IN) Action to be added 6334 * param0 - (IN) Parameter associated with action 6335 * Returns: 6336 * BCM_E_XXX 6337 */ 6338 STATIC int 6339 bcmi_esw_policer_action_add( 6340 int unit, 6341 uint32 action_id, 6342 bcm_policer_action_t action, 6343 uint32 param0) 6344 { 6345 bcm_error_t rv = BCM_E_UNAVAIL; 6346 uint32 idx = 0; 6347 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 6348 6349 POL_FUNCTION_TRACE(unit, "IN"); 6350 POL_FUNCTION_DEBUG(unit, "action_id %d", action_id); 6351 POL_FUNCTION_DEBUG(unit, "bcm_policer_action_t %d", action); 6352 POL_FUNCTION_DEBUG(unit, "param0 %d", param0); 6353 6354 if (action >= bcmPolicerActionCount) { 6355 return BCM_E_PARAM; 6356 } 6357 BCM_IF_ERROR_RETURN( 6358 bcmi_esw_policer_action_add_param_check(unit, action, param0)); 6359 6360 /* Initialization check */ 6361 CHECK_GLOBAL_METER_INIT(unit); 6362 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6363 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 6364 6365 /* Check if the chip specific function existed */ 6366 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->action_supported); 6367 6368 rv = gm_dev_info->action_supported(unit, action); 6369 BCM_IF_ERROR_RETURN(rv); 6370 6371 if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) { 6372 LOG_DEBUG(BSL_LS_BCM_POLICER, 6373 (BSL_META_U(unit, 6374 "Action id is not created \n"))); 6375 return BCM_E_PARAM; 6376 } 6377 6378 if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count != 0) { 6379 LOG_ERROR(BSL_LS_BCM_POLICER, 6380 (BSL_META_U(unit, 6381 "Action Id specified still being used \n"))); 6382 return BCM_E_BUSY; 6383 } 6384 6385 GLOBAL_METER_LOCK(unit); 6386 6387 /* Since there is no HW action table for GH2, we need to store actions */ 6388 idx = BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count; 6389 BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx] = action; 6390 BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx] = param0; 6391 BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count++; 6392 6393 GLOBAL_METER_UNLOCK(unit); 6394 POL_FUNCTION_TRACE(unit, "OUT"); 6395 return BCM_E_NONE; 6396 } 6397 6398 /* 6399 * Function: 6400 * bcmi_esw_policer_action_get 6401 * Purpose: 6402 * get action parameter for a given action 6403 * Parameters: 6404 * unit - (IN) unit number 6405 * action_id - (IN) Action Id 6406 * action - (IN) Action for which param is needed 6407 * param0 - (OUT) Parameter associated with action id 6408 * Returns: 6409 * BCM_E_XXX 6410 */ 6411 STATIC int 6412 bcmi_esw_policer_action_get( 6413 int unit, 6414 uint32 action_id, 6415 bcm_policer_action_t action, 6416 uint32 *param0) 6417 { 6418 bcm_error_t rv = BCM_E_UNAVAIL; 6419 uint32 idx = 0; 6420 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 6421 bcm_policer_action_t bk_action; 6422 uint32 bk_param0; 6423 6424 POL_FUNCTION_TRACE(unit, "IN"); 6425 6426 if (action >= bcmPolicerActionCount) { 6427 return BCM_E_PARAM; 6428 } 6429 6430 /* Parameter NULL error handling */ 6431 POL_CHECK_NULL_PARAMETER(unit, param0); 6432 6433 /* Initialization check */ 6434 CHECK_GLOBAL_METER_INIT(unit); 6435 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6436 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 6437 6438 if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) { 6439 LOG_DEBUG(BSL_LS_BCM_POLICER, 6440 (BSL_META_U(unit, 6441 "Action id is not created \n"))); 6442 return BCM_E_PARAM; 6443 } 6444 6445 /* Check if the chip specific function existed */ 6446 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->action_supported); 6447 6448 rv = gm_dev_info->action_supported(unit, action); 6449 BCM_IF_ERROR_RETURN(rv); 6450 6451 for (idx = 0; 6452 idx < BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count; 6453 idx++) { 6454 bk_action = BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx]; 6455 bk_param0 = BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx]; 6456 if (action == bk_action) { 6457 *param0 = bk_param0; 6458 return BCM_E_NONE; 6459 } 6460 } 6461 *param0 = 0; 6462 6463 POL_FUNCTION_TRACE(unit, "OUT"); 6464 return BCM_E_NOT_FOUND; 6465 } 6466 6467 /* 6468 * Function: 6469 * bcmi_esw_policer_action_destroy 6470 * Purpose: 6471 * Delete an entry from meter action table 6472 * Parameters: 6473 * unit - (IN) unit number 6474 * action_id - (IN) Action Id to be destroyed 6475 * Returns: 6476 * BCM_E_XXX 6477 */ 6478 STATIC int 6479 bcmi_esw_policer_action_destroy( 6480 int unit, 6481 uint32 action_id) 6482 { 6483 bcm_error_t rv = BCM_E_UNAVAIL; 6484 6485 POL_FUNCTION_TRACE(unit, "IN"); 6486 POL_FUNCTION_DEBUG(unit, "action_id %d", action_id); 6487 6488 /* Initialization check */ 6489 CHECK_GLOBAL_METER_INIT(unit); 6490 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6491 6492 if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) { 6493 LOG_DEBUG(BSL_LS_BCM_POLICER, 6494 (BSL_META_U(unit, 6495 "Action Id(%d) specified doesn't exist\n"), 6496 action_id)); 6497 return BCM_E_PARAM; 6498 } 6499 if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count != 0) { 6500 LOG_DEBUG(BSL_LS_BCM_POLICER, 6501 (BSL_META_U(unit, 6502 "Action Id(%d) specified still being used \n"), 6503 action_id)); 6504 return BCM_E_BUSY; 6505 } 6506 GLOBAL_METER_LOCK(unit); 6507 6508 rv = shr_aidxres_list_free( 6509 BCMI_ACTION_LIST_HANDLE_GET(unit), action_id); 6510 if (BCM_FAILURE(rv)) { 6511 GLOBAL_METER_UNLOCK(unit); 6512 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6513 (BSL_META_U(unit, 6514 "Unable to free action handle\n"))); 6515 return (rv); 6516 } 6517 BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count = 0; 6518 BCMI_ACTION_ID_BK_GET(unit, action_id).used = 0; 6519 GLOBAL_METER_UNLOCK(unit); 6520 6521 POL_FUNCTION_TRACE(unit, "OUT"); 6522 return BCM_E_NONE; 6523 } 6524 6525 /* 6526 * Function: 6527 * bcmi_esw_policer_action_attach_get 6528 * Purpose: 6529 * Get the action id associated with a given policer. 6530 * Parameters: 6531 * unit - (IN) unit number 6532 * policer_id - (IN) Base policer Id 6533 * action_id - (OUT) action id 6534 * Returns: 6535 * BCM_E_XXX 6536 */ 6537 STATIC int 6538 bcmi_esw_policer_action_attach_get( 6539 int unit, 6540 bcm_policer_t policer_id, 6541 uint32 *action_id) 6542 { 6543 bcm_error_t rv = BCM_E_UNAVAIL; 6544 bcmi_global_meter_policer_control_t *policer_control = NULL; 6545 uint32 pol_cfg_idx; 6546 6547 POL_FUNCTION_TRACE(unit, "IN"); 6548 6549 /* Parameter NULL error handling */ 6550 POL_CHECK_NULL_PARAMETER(unit, action_id); 6551 6552 /* Initialization check */ 6553 CHECK_GLOBAL_METER_INIT(unit); 6554 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6555 6556 /* validate policer id */ 6557 BCM_IF_ERROR_RETURN( 6558 bcmi_esw_policer_validate(unit, policer_id)); 6559 6560 GLOBAL_METER_BK_LOCK(unit); 6561 rv = bcmi_esw_global_meter_base_policer_get( 6562 unit, policer_id, &policer_control); 6563 if (BCM_FAILURE(rv)) { 6564 GLOBAL_METER_BK_UNLOCK(unit); 6565 LOG_ERROR(BSL_LS_BCM_POLICER, 6566 (BSL_META_U(unit, 6567 "Unable to get policer control for " 6568 "policer id 0x%x(%d)\n"), 6569 policer_id, 6570 policer_id)); 6571 return (rv); 6572 } 6573 pol_cfg_idx = policer_id - policer_control->pid; 6574 6575 /* get action id */ 6576 *action_id = policer_control->pol_cfg[pol_cfg_idx].action_id; 6577 6578 GLOBAL_METER_BK_UNLOCK(unit); 6579 POL_FUNCTION_DEBUG(unit, "action_id (%d)", *action_id); 6580 6581 POL_FUNCTION_TRACE(unit, "OUT"); 6582 return BCM_E_NONE; 6583 } 6584 6585 /* 6586 * Function: 6587 * bcmi_esw_policer_action_detach 6588 * Purpose: 6589 * Disassociate a policer action from a given policer id and 6590 * readjust reference count. 6591 * Parameters: 6592 * unit - (IN) unit number 6593 * policer_id - (IN) Base policer Id 6594 * action_id - (IN) action id 6595 * Returns: 6596 * BCM_E_XXX 6597 */ 6598 STATIC int 6599 bcmi_esw_policer_action_detach( 6600 int unit, 6601 bcm_policer_t policer_id, 6602 uint32 action_id) 6603 { 6604 bcm_error_t rv = BCM_E_UNAVAIL; 6605 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 6606 bcmi_global_meter_policer_control_t *policer_control = NULL; 6607 int policer_index = 0; 6608 uint32 pol_cfg_idx; 6609 uint64 reset = COMPILER_64_INIT(0, 0); 6610 6611 POL_FUNCTION_TRACE(unit, "IN"); 6612 6613 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6614 (BSL_META_U(unit, 6615 "Detach action_id (0x%x) on policer_id (0x%x)"), 6616 action_id, policer_id)); 6617 6618 /* Initialization check */ 6619 CHECK_GLOBAL_METER_INIT(unit); 6620 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6621 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 6622 6623 if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) { 6624 LOG_DEBUG(BSL_LS_BCM_POLICER, 6625 (BSL_META_U(unit, 6626 "Action id is not created \n"))); 6627 return BCM_E_PARAM; 6628 } 6629 6630 /* validate policer id */ 6631 rv = bcmi_esw_policer_validate(unit, policer_id); 6632 if (BCM_FAILURE(rv)) { 6633 LOG_DEBUG(BSL_LS_BCM_POLICER, 6634 (BSL_META_U(unit, 6635 "Invalid Policer Id \n"))); 6636 return (rv); 6637 } 6638 6639 GLOBAL_METER_LOCK(unit); 6640 rv = bcmi_esw_global_meter_base_policer_get( 6641 unit, policer_id, &policer_control); 6642 if (BCM_FAILURE(rv)) { 6643 GLOBAL_METER_UNLOCK(unit); 6644 LOG_ERROR(BSL_LS_BCM_POLICER, 6645 (BSL_META_U(unit, 6646 "Unable to get policer control for " 6647 "policer id 0x%x(%d)\n"), 6648 policer_id, 6649 policer_id)); 6650 return (rv); 6651 } 6652 /* read meter table and remove action_id */ 6653 BCM_IF_ERROR_RETURN( 6654 bcmi_esw_policer_table_index_get(unit, policer_id, &policer_index)); 6655 6656 /* Check if the chip specific function existed */ 6657 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_set); 6658 6659 /* write action table entry */ 6660 rv = gm_dev_info->policy_action_set(unit, 6661 policer_index, 6662 reset, 6663 reset, 6664 reset); 6665 if (BCM_FAILURE(rv)) { 6666 GLOBAL_METER_UNLOCK(unit); 6667 return rv; 6668 } 6669 6670 /* decrement action usage reference count */ 6671 if (BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count > 0) { 6672 BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count--; 6673 } 6674 6675 pol_cfg_idx = policer_id - policer_control->pid; 6676 6677 /* reset action id in policer control */ 6678 policer_control->pol_cfg[pol_cfg_idx].action_id = 6679 BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID; 6680 GLOBAL_METER_UNLOCK(unit); 6681 6682 POL_FUNCTION_TRACE(unit, "OUT"); 6683 return BCM_E_NONE; 6684 } 6685 6686 /* 6687 * Function: 6688 * bcmi_esw_policer_action_attach 6689 * Purpose: 6690 * Associate a policer action with a given policer id and 6691 * increment action usage reference count. 6692 * Parameters: 6693 * unit - (IN) unit number 6694 * policer_id - (IN) Base policer Id 6695 * action_id - (IN) action id 6696 * Returns: 6697 * BCM_E_XXX 6698 */ 6699 STATIC int 6700 bcmi_esw_policer_action_attach( 6701 int unit, 6702 bcm_policer_t policer_id, 6703 uint32 action_id) 6704 { 6705 bcm_error_t rv = BCM_E_UNAVAIL; 6706 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 6707 bcmi_global_meter_policer_control_t *policer_control = NULL; 6708 int policer_index = 0; 6709 uint64 green_action = COMPILER_64_INIT(0, 0); 6710 uint64 yellow_action = COMPILER_64_INIT(0, 0); 6711 uint64 red_action = COMPILER_64_INIT(0, 0); 6712 uint32 idx = 0, pol_cfg_idx; 6713 bcm_policer_action_t action; 6714 uint32 param0; 6715 6716 POL_FUNCTION_TRACE(unit, "IN"); 6717 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6718 (BSL_META_U(unit, 6719 "Attach action_id(0x%x) to policer_id (0x%x)\n"), 6720 action_id, policer_id)); 6721 6722 if (action_id == BCMI_POLICER_GLOBAL_METER_INVALID_ACTION_ID) { 6723 return BCM_E_PARAM; 6724 } 6725 6726 /* Initialization check */ 6727 CHECK_GLOBAL_METER_INIT(unit); 6728 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 6729 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 6730 6731 /* check if action id is allocated */ 6732 if (BCMI_ACTION_ID_BK_GET(unit, action_id).used != 1) { 6733 LOG_DEBUG(BSL_LS_BCM_POLICER, 6734 (BSL_META_U(unit, 6735 "Action Id is not created \n"))); 6736 return BCM_E_PARAM; 6737 } 6738 6739 /* Check if the chip specific function existed */ 6740 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_set); 6741 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_get); 6742 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->policy_action_param_configure); 6743 6744 /* validate policer id */ 6745 rv = bcmi_esw_policer_validate(unit, policer_id); 6746 if (BCM_FAILURE(rv)) { 6747 LOG_DEBUG(BSL_LS_BCM_POLICER, 6748 (BSL_META_U(unit, 6749 "Invalid Policer Id \n"))); 6750 return (rv); 6751 } 6752 6753 GLOBAL_METER_LOCK(unit); 6754 rv = bcmi_esw_global_meter_base_policer_get( 6755 unit, policer_id, &policer_control); 6756 if (BCM_FAILURE(rv)) { 6757 GLOBAL_METER_UNLOCK(unit); 6758 LOG_ERROR(BSL_LS_BCM_POLICER, 6759 (BSL_META_U(unit, 6760 "Unable to get policer control for " 6761 "policer id 0x%d(%x)\n"), 6762 policer_id, 6763 policer_id)); 6764 return (rv); 6765 } 6766 pol_cfg_idx = policer_id - policer_control->pid; 6767 6768 if (policer_control->pol_cfg[pol_cfg_idx].action_id == action_id) { 6769 GLOBAL_METER_UNLOCK(unit); 6770 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6771 (BSL_META_U(unit, 6772 "Action Id %d(%x) passed is the same as the " 6773 "one in policer control\n"), 6774 action_id, action_id)); 6775 return (BCM_E_NONE); 6776 } 6777 6778 /* set action to policy table */ 6779 BCM_IF_ERROR_RETURN( 6780 bcmi_esw_policer_table_index_get(unit, policer_id, &policer_index)); 6781 6782 /* read action table entry */ 6783 rv = gm_dev_info->policy_action_get( 6784 unit, policer_index, 6785 &green_action, &yellow_action, &red_action); 6786 if (BCM_FAILURE(rv)) { 6787 GLOBAL_METER_UNLOCK(unit); 6788 LOG_ERROR(BSL_LS_BCM_POLICER, 6789 (BSL_META_U(unit, 6790 "HW Operation failed(rv = %d)\n"), 6791 rv)); 6792 return rv; 6793 } 6794 6795 /* read from bk and set action to policy table */ 6796 for (idx = 0; 6797 idx < BCMI_ACTION_ID_BK_GET(unit, action_id).actions_count; 6798 idx++) { 6799 action = BCMI_ACTION_ID_BK_GET(unit, action_id).actions[idx]; 6800 param0 = BCMI_ACTION_ID_BK_GET(unit, action_id).param[idx]; 6801 6802 6803 rv = gm_dev_info->policy_action_param_configure( 6804 unit, action, param0, 6805 &green_action, &yellow_action, &red_action); 6806 6807 if (BCM_FAILURE(rv)) { 6808 GLOBAL_METER_UNLOCK(unit); 6809 LOG_ERROR(BSL_LS_BCM_POLICER, 6810 (BSL_META_U(unit, 6811 "HW Operation failed(rv = %d)\n"), 6812 rv)); 6813 return rv; 6814 } 6815 } 6816 6817 /* write action table entry */ 6818 rv = gm_dev_info->policy_action_set( 6819 unit, policer_index, 6820 green_action, yellow_action, red_action); 6821 6822 if (BCM_FAILURE(rv)) { 6823 GLOBAL_METER_UNLOCK(unit); 6824 LOG_ERROR(BSL_LS_BCM_POLICER, 6825 (BSL_META_U(unit, 6826 "HW Operation failed(rv = %d)\n"), 6827 rv)); 6828 return rv; 6829 } 6830 6831 /* increment action usage reference count */ 6832 BCMI_ACTION_ID_BK_GET(unit, action_id).reference_count++; 6833 policer_control->pol_cfg[pol_cfg_idx].action_id = action_id; 6834 GLOBAL_METER_UNLOCK(unit); 6835 6836 POL_FUNCTION_TRACE(unit, "OUT"); 6837 return BCM_E_NONE; 6838 } 6839 /* end Action API's */ 6840 #endif /* ACTION_API_SECTION */ 6841 6842 #ifdef BCM_WARM_BOOT_SUPPORT 6843 6844 STATIC int 6845 bcmi_esw_global_meter_policer_scache_alloc(int unit) 6846 { 6847 soc_scache_handle_t scache_handle; 6848 uint8 *policer_scache = NULL; 6849 int size = 0; 6850 int rv; 6851 6852 POL_FUNCTION_TRACE(unit, "IN"); 6853 6854 /* 1. tcam usage bitmap */ 6855 size += SHR_BITALLOCSIZE(BCMI_POLICER_SVC_METER_TCAM_SIZE); 6856 6857 /* 2. offset_mode usage bitmap */ 6858 size += SHR_BITALLOCSIZE(BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE); 6859 6860 /* 3. bcmi_policer_global_meter_action_bk_t */ 6861 size += sizeof(bcmi_policer_global_meter_action_bk_t) * 6862 BCMI_POLICER_SVC_METER_ACTION_SIZE; 6863 6864 /* 4. bcmi_policer_svm_offset_mode_bk_t */ 6865 size += sizeof(bcmi_policer_svm_offset_mode_bk_t) * 6866 BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 6867 6868 /* 4.1 bcm_policer_group_mode_attr_selector_t */ 6869 size += sizeof(bcm_policer_group_mode_attr_selector_t) * 6870 BCMI_POLICER_SVC_METER_TCAM_SIZE; 6871 6872 /* 4.2 pkt_tcam_attr_bits_t */ 6873 size += sizeof(pkt_tcam_attr_bits_t) * 6874 BCMI_POLICER_SVC_METER_TCAM_SIZE; 6875 6876 /* 5.1 bcmi_global_meter_policer_control_t */ 6877 size += sizeof(bcmi_global_meter_policer_control_t) * 6878 BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES; 6879 6880 /* 5.2 bcmi_global_meter_policer_control_t->pol_cfg[no_of_policers] */ 6881 size += sizeof(bcm_policer_config_wb_t) * 6882 BCMI_POLICER_SVC_METER_POOL_SIZE; 6883 6884 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 6885 6886 rv = _bcm_esw_scache_ptr_get( 6887 unit, scache_handle, TRUE, size, 6888 &policer_scache, BCM_WB_DEFAULT_VERSION, NULL); 6889 6890 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 6891 return rv; 6892 } 6893 POL_FUNCTION_TRACE(unit, "OUT"); 6894 return BCM_E_NONE; 6895 } 6896 6897 /* 6898 * Function: 6899 * bcmi_esw_global_meter_policer_sync 6900 * Purpose: 6901 * Write policers which are created but not yet used in any 6902 * table to scache so that we can recover the configuration 6903 * on warm boot 6904 * Parameters: 6905 * unit - (IN) unit number 6906 * Returns: 6907 * BCM_E_XXX 6908 */ 6909 STATIC int 6910 bcmi_esw_global_meter_policer_sync(int unit) 6911 { 6912 int rv = BCM_E_NONE; 6913 soc_scache_handle_t scache_handle; 6914 bcmi_global_meter_policer_control_t *policer_control = NULL; 6915 uint32 hash_index; /* Entry hash */ 6916 uint8 *policer_scache = NULL; 6917 int offset_mode; 6918 int count = 0; 6919 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 6920 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 6921 uint32 bmp_size, table_size; 6922 int i; 6923 uint8 is_custom_group; 6924 uint32 ref_cnt = 0; 6925 uint32 used = 0; 6926 bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeCount; 6927 bcm_policer_group_mode_type_t group_mode_type = 6928 bcmPolicerGroupModeTypeCount; 6929 uint32 no_of_policers = 0; 6930 uint32 no_of_attr_selectors = 0; 6931 uint32 pkt_attr_v_cnt = 0; 6932 bcm_policer_config_wb_t wb_pol_cfg; 6933 6934 POL_FUNCTION_TRACE(unit, "IN"); 6935 6936 CHECK_GLOBAL_METER_INIT(unit); 6937 6938 BCM_IF_ERROR_RETURN( 6939 bcmi_esw_global_meter_policer_scache_alloc(unit)); 6940 6941 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 6942 6943 BCM_IF_ERROR_RETURN( 6944 _bcm_esw_scache_ptr_get( 6945 unit, scache_handle, FALSE, 0, 6946 &policer_scache, BCM_WB_DEFAULT_VERSION, NULL)); 6947 6948 if (NULL == policer_scache) { 6949 LOG_VERBOSE(BSL_LS_BCM_POLICER, 6950 (BSL_META_U(unit, 6951 "SCACHE Memory not available \n"))); 6952 return BCM_E_MEMORY; 6953 } 6954 6955 bk_svm_info = BCMI_SVM_BK_GET(unit); 6956 6957 /* 1. Copy tcam usage bitmap */ 6958 bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE; 6959 sal_memcpy(policer_scache, bk_svm_info->tcam_intf_bitmap, 6960 SHR_BITALLOCSIZE(bmp_size)); 6961 policer_scache += SHR_BITALLOCSIZE(bmp_size); 6962 6963 /* 2. Copy offset_mode usage bitmap */ 6964 bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 6965 sal_memcpy(policer_scache, bk_svm_info->offset_mode_intf_bitmap, 6966 SHR_BITALLOCSIZE(bmp_size)); 6967 policer_scache += SHR_BITALLOCSIZE(bmp_size); 6968 6969 /* 3. Copy actions bk */ 6970 table_size = 6971 sizeof(bcmi_policer_global_meter_action_bk_t) * 6972 BCMI_POLICER_SVC_METER_ACTION_SIZE; 6973 sal_memcpy(policer_scache, BCMI_ACTION_BK_GET(unit), 6974 table_size); 6975 policer_scache += table_size; 6976 6977 /* 4. bcmi_policer_svm_offset_mode_bk_t */ 6978 for (offset_mode = 0; 6979 offset_mode < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 6980 offset_mode++) { 6981 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode)) { 6982 bk_svm_mode_info = 6983 BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 6984 6985 is_custom_group = bk_svm_mode_info->is_custom_group; 6986 ref_cnt = bk_svm_mode_info->ref_cnt; 6987 used = bk_svm_mode_info->used; 6988 no_of_policers = bk_svm_mode_info->no_of_policers; 6989 no_of_attr_selectors = bk_svm_mode_info->no_of_attr_selectors; 6990 group_mode = bk_svm_mode_info->group_mode; 6991 group_mode_type = bk_svm_mode_info->group_mode_type; 6992 pkt_attr_v_cnt = bk_svm_mode_info->pkt_attr_v_cnt; 6993 6994 sal_memcpy(policer_scache, &is_custom_group, 6995 sizeof(uint8)); 6996 policer_scache += sizeof(uint8); 6997 6998 sal_memcpy(policer_scache, &ref_cnt, 6999 sizeof(uint32)); 7000 policer_scache += sizeof(uint32); 7001 7002 sal_memcpy(policer_scache, &used, 7003 sizeof(uint32)); 7004 policer_scache += sizeof(uint32); 7005 7006 sal_memcpy(policer_scache, &no_of_policers, 7007 sizeof(uint32)); 7008 policer_scache += sizeof(uint32); 7009 7010 sal_memcpy(policer_scache, &no_of_attr_selectors, 7011 sizeof(uint32)); 7012 policer_scache += sizeof(uint32); 7013 7014 sal_memcpy(policer_scache, &pkt_attr_v_cnt, 7015 sizeof(uint32)); 7016 policer_scache += sizeof(uint32); 7017 7018 sal_memcpy(policer_scache, &group_mode, 7019 sizeof(bcm_policer_group_mode_t)); 7020 policer_scache += 7021 sizeof(bcm_policer_group_mode_t); 7022 7023 sal_memcpy(policer_scache, &group_mode_type, 7024 sizeof(bcm_policer_group_mode_type_t)); 7025 policer_scache += 7026 sizeof(bcm_policer_group_mode_type_t); 7027 7028 /* 4.1 Save attr_selectors info */ 7029 for (i = 0; i < no_of_attr_selectors; i++) { 7030 sal_memcpy(policer_scache, 7031 &bk_svm_mode_info->attr_selectors[i], 7032 sizeof(bcm_policer_group_mode_attr_selector_t)); 7033 policer_scache += sizeof(bcm_policer_group_mode_attr_selector_t); 7034 } 7035 7036 /* 4.2 Save pkt_attr_v info */ 7037 for (i = 0; i < pkt_attr_v_cnt; i++) { 7038 sal_memcpy(policer_scache, 7039 &bk_svm_mode_info->pkt_attr_v[i], 7040 sizeof(pkt_tcam_attr_bits_t)); 7041 policer_scache += sizeof(pkt_tcam_attr_bits_t); 7042 } 7043 } 7044 } 7045 7046 /* 5. go through policer control bookkeep structure and get policer 7047 entries */ 7048 for (hash_index = 0; hash_index < BCMI_GLOBAL_METER_HASH_SIZE; hash_index++) { 7049 policer_control = BCMI_POLICER_HASH_BK_GET(unit, hash_index); 7050 while ((NULL != policer_control) && 7051 (count < BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES)) { 7052 /* 5.1 Save policer_control */ 7053 sal_memcpy(policer_scache, policer_control, 7054 sizeof(bcmi_global_meter_policer_control_t)); 7055 policer_scache += sizeof(bcmi_global_meter_policer_control_t); 7056 7057 /* 5.2 Save policer_control->pol_cfg[no_of_policers] */ 7058 no_of_policers = policer_control->no_of_policers; 7059 for (i = 0; i < no_of_policers; i++) { 7060 policer_config_copy_to_wb_policer_config( 7061 &(policer_control->pol_cfg[i]), 7062 &wb_pol_cfg); 7063 sal_memcpy(policer_scache, &wb_pol_cfg, 7064 sizeof(bcm_policer_config_wb_t)); 7065 policer_scache += 7066 sizeof(bcm_policer_config_wb_t); 7067 } 7068 count++; 7069 policer_control = policer_control->next; 7070 } 7071 if (count == BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES) { 7072 return rv; 7073 } 7074 } 7075 POL_FUNCTION_TRACE(unit, "OUT"); 7076 return rv; 7077 } 7078 7079 /* 7080 * Function: 7081 * bcmi_esw_global_meter_policer_recover_from_scache 7082 * Purpose: 7083 * Recover policers which are not configured in HW from 7084 * Scache as part of warm boot 7085 * Parameters: 7086 * unit - (IN) unit number 7087 * policer_scache - (IN) scache memory pointer 7088 * Returns: 7089 * BCM_E_XXX 7090 */ 7091 STATIC int 7092 bcmi_esw_global_meter_policer_recover_from_scache( 7093 int unit, 7094 uint8 *policer_scache) 7095 { 7096 int rv = BCM_E_NONE; 7097 int offset_mode; 7098 int count_index = 0; 7099 bcmi_global_meter_policer_control_t *policer_control = NULL; 7100 bcm_policer_t policer_id; 7101 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 7102 bcmi_policer_svm_offset_mode_bk_t *bk_svm_mode_info = NULL; 7103 int bmp_size, table_size; 7104 int i; 7105 uint8 is_custom_group; 7106 uint32 ref_cnt = 0; 7107 uint32 used = 0; 7108 bcm_policer_group_mode_t group_mode = bcmPolicerGroupModeCount; 7109 bcm_policer_group_mode_type_t group_mode_type = 7110 bcmPolicerGroupModeTypeCount; 7111 uint32 no_of_policers = 0; 7112 uint32 no_of_attr_selectors = 0; 7113 uint32 pkt_attr_v_cnt = 0; 7114 bcm_policer_config_wb_t wb_pol_cfg; 7115 7116 POL_FUNCTION_TRACE(unit, "IN"); 7117 7118 if (SOC_WARM_BOOT(unit)) { 7119 if (NULL == policer_scache) { 7120 LOG_ERROR(BSL_LS_BCM_POLICER, 7121 (BSL_META_U(unit, 7122 "SCACHE Memory not available \n"))); 7123 return BCM_E_MEMORY; 7124 } 7125 7126 bk_svm_info = BCMI_SVM_BK_GET(unit); 7127 7128 /* 1. recovery tcam usage bitmap */ 7129 bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE; 7130 sal_memcpy(bk_svm_info->tcam_intf_bitmap, policer_scache, 7131 SHR_BITALLOCSIZE(bmp_size)); 7132 policer_scache += SHR_BITALLOCSIZE(bmp_size); 7133 7134 /* 2. recovery offset_mode usage bitmap */ 7135 bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 7136 sal_memcpy(bk_svm_info->offset_mode_intf_bitmap, policer_scache, 7137 SHR_BITALLOCSIZE(bmp_size)); 7138 policer_scache += SHR_BITALLOCSIZE(bmp_size); 7139 7140 /* 3. Copy actions bk */ 7141 table_size = 7142 sizeof(bcmi_policer_global_meter_action_bk_t) * 7143 BCMI_POLICER_SVC_METER_ACTION_SIZE; 7144 sal_memcpy(BCMI_ACTION_BK_GET(unit), policer_scache, 7145 table_size); 7146 policer_scache += table_size; 7147 7148 /* Recover actions list handle */ 7149 for (i = 0; i < BCMI_POLICER_SVC_METER_ACTION_SIZE; i++) { 7150 if (BCMI_ACTION_ID_BK_GET(unit, i).used) { 7151 rv = shr_aidxres_list_reserve_block( 7152 BCMI_ACTION_LIST_HANDLE_GET(unit), i, 1); 7153 BCM_IF_ERROR_RETURN(rv); 7154 } 7155 } 7156 7157 /* 4. bcmi_policer_svm_offset_mode_bk_t */ 7158 for (offset_mode = 0; 7159 offset_mode < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 7160 offset_mode++) { 7161 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, offset_mode)) { 7162 bk_svm_mode_info = 7163 BCMI_SVM_OFFSET_MODE_BK_GET(unit, offset_mode); 7164 7165 sal_memcpy(&is_custom_group, policer_scache, sizeof(uint8)); 7166 policer_scache += sizeof(uint8); 7167 7168 sal_memcpy(&ref_cnt, policer_scache, sizeof(uint32)); 7169 policer_scache += sizeof(uint32); 7170 7171 sal_memcpy(&used, policer_scache, sizeof(uint32)); 7172 policer_scache += sizeof(uint32); 7173 7174 sal_memcpy(&no_of_policers, policer_scache, sizeof(uint32)); 7175 policer_scache += sizeof(uint32); 7176 7177 sal_memcpy(&no_of_attr_selectors, policer_scache, 7178 sizeof(uint32)); 7179 policer_scache += sizeof(uint32); 7180 7181 sal_memcpy(&pkt_attr_v_cnt, policer_scache, 7182 sizeof(uint32)); 7183 policer_scache += sizeof(uint32); 7184 7185 sal_memcpy(&group_mode, policer_scache, 7186 sizeof(bcm_policer_group_mode_t)); 7187 policer_scache += 7188 sizeof(bcm_policer_group_mode_t); 7189 7190 sal_memcpy(&group_mode_type, policer_scache, 7191 sizeof(bcm_policer_group_mode_type_t)); 7192 policer_scache += 7193 sizeof(bcm_policer_group_mode_type_t); 7194 7195 bk_svm_mode_info->is_custom_group = is_custom_group; 7196 bk_svm_mode_info->ref_cnt = ref_cnt; 7197 bk_svm_mode_info->used = used; 7198 bk_svm_mode_info->no_of_policers = no_of_policers; 7199 bk_svm_mode_info->no_of_attr_selectors = no_of_attr_selectors; 7200 bk_svm_mode_info->group_mode = group_mode; 7201 bk_svm_mode_info->group_mode_type = group_mode_type; 7202 bk_svm_mode_info->pkt_attr_v_cnt = pkt_attr_v_cnt; 7203 7204 /* 4.1 recovery attr_selectors info */ 7205 POL_MEM_ALLOC( 7206 bk_svm_mode_info->attr_selectors, 7207 no_of_attr_selectors * 7208 sizeof(bcm_policer_group_mode_attr_selector_t), 7209 "attr selectors"); 7210 if (NULL == bk_svm_mode_info->attr_selectors) { 7211 LOG_ERROR(BSL_LS_BCM_POLICER, 7212 (BSL_META_U(unit, 7213 "Unable to allocate memory for " 7214 "attr_selectors\n"))); 7215 return BCM_E_MEMORY; 7216 } 7217 for (i = 0; i < no_of_attr_selectors; i++) { 7218 sal_memcpy(&bk_svm_mode_info->attr_selectors[i], 7219 policer_scache, 7220 sizeof(bcm_policer_group_mode_attr_selector_t)); 7221 policer_scache += 7222 sizeof(bcm_policer_group_mode_attr_selector_t); 7223 } 7224 7225 /* 4.2 recovery pkt_attr_v info */ 7226 POL_MEM_ALLOC( 7227 bk_svm_mode_info->pkt_attr_v, 7228 bk_svm_mode_info->pkt_attr_v_cnt * sizeof(pkt_tcam_attr_bits_t), 7229 "pkt_attr_v in offset mode instance"); 7230 if (NULL == bk_svm_mode_info->pkt_attr_v) { 7231 LOG_ERROR(BSL_LS_BCM_POLICER, 7232 (BSL_META_U(unit, 7233 "Unable to allocate memory for " 7234 "pkt_attr_v\n"))); 7235 return (BCM_E_MEMORY); 7236 } 7237 7238 for (i = 0; i < pkt_attr_v_cnt; i++) { 7239 sal_memcpy(&bk_svm_mode_info->pkt_attr_v[i], 7240 policer_scache, 7241 sizeof(pkt_tcam_attr_bits_t)); 7242 policer_scache += sizeof(pkt_tcam_attr_bits_t); 7243 } 7244 } 7245 } 7246 7247 /* 5. read from scache and create policer bookkeep data structure */ 7248 for (count_index = 0; 7249 count_index < BCMI_POLICER_GLOBAL_METER_MAX_SCACHE_ENTRIES; 7250 count_index++) { 7251 bcmi_global_meter_policer_control_t tmp_policer_control; 7252 7253 sal_memcpy(&tmp_policer_control, policer_scache, 7254 sizeof(bcmi_global_meter_policer_control_t)); 7255 policer_scache += sizeof(bcmi_global_meter_policer_control_t); 7256 7257 policer_id = tmp_policer_control.pid; 7258 if ((policer_id & BCMI_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 7259 /* Allocate policer descriptor. */ 7260 no_of_policers = tmp_policer_control.no_of_policers; 7261 policer_control = NULL; 7262 rv = bcmi_global_meter_policer_control_alloc( 7263 unit, no_of_policers, &policer_control); 7264 BCM_IF_ERROR_RETURN(rv); 7265 7266 /* 5.1 recovery policer_control */ 7267 policer_control->pid = policer_id; 7268 policer_control->ref_count = tmp_policer_control.ref_count; 7269 policer_control->no_of_policers = tmp_policer_control.no_of_policers; 7270 policer_control->grp_mode = tmp_policer_control.grp_mode; 7271 7272 /* 5.2 recovery policer_control->pol_cfg[no_of_policers] */ 7273 if (NULL != policer_control->pol_cfg) { 7274 for (i = 0; i < no_of_policers; i++) { 7275 sal_memcpy(&wb_pol_cfg, policer_scache, 7276 sizeof(bcm_policer_config_wb_t)); 7277 policer_scache += 7278 sizeof(bcm_policer_config_wb_t); 7279 wb_policer_config_copy_to_policer_config( 7280 &wb_pol_cfg, 7281 &(policer_control->pol_cfg[i])); 7282 } 7283 } 7284 7285 /* Insert policer into policers hash. */ 7286 _GLOBAL_METER_HASH_INSERT( 7287 BCMI_POLICER_BK_GET(unit), 7288 policer_control, 7289 (policer_id & _GLOBAL_METER_HASH_MASK)); 7290 /* Recover policer list handle */ 7291 rv = shr_aidxres_list_alloc_block( 7292 BCMI_POLICER_LIST_HANDLE_GET(unit), 7293 no_of_policers, 7294 (uint32 *)&policer_id); 7295 BCM_IF_ERROR_RETURN(rv); 7296 } 7297 } 7298 7299 /* Calculate the cnt/start/end */ 7300 bmp_size = BCMI_POLICER_SVC_METER_TCAM_SIZE; 7301 bk_svm_info->empty_tcam_idx_cnt = bmp_size; 7302 bk_svm_info->valid_tcam_idx_cnt = 0; 7303 bk_svm_info->valid_tcam_idx_start = 0; 7304 bk_svm_info->valid_tcam_idx_end = 0; 7305 bk_svm_info->empty_tcam_idx_start = 0; 7306 bk_svm_info->empty_tcam_idx_end = 0; 7307 7308 for (i = 0; i < bmp_size; i++) { 7309 if (BCMI_SVM_TCAM_INTF_GET(unit, i)) { 7310 bk_svm_info->valid_tcam_idx_cnt++; 7311 } 7312 7313 if (BCMI_SVM_TCAM_INTF_GET(unit, i) && 7314 !BCMI_OFFSET_MODE_ID_INTF_GET( 7315 unit, bk_svm_info->valid_tcam_idx_start)) { 7316 bk_svm_info->valid_tcam_idx_start = i; 7317 } 7318 7319 if (BCMI_SVM_TCAM_INTF_GET(unit, i) && 7320 bk_svm_info->valid_tcam_idx_end < i) { 7321 bk_svm_info->valid_tcam_idx_end = i; 7322 } 7323 7324 if (!BCMI_SVM_TCAM_INTF_GET(unit, i) && 7325 BCMI_OFFSET_MODE_ID_INTF_GET( 7326 unit, bk_svm_info->empty_tcam_idx_start)) { 7327 bk_svm_info->empty_tcam_idx_start = i; 7328 } 7329 7330 if (!BCMI_SVM_TCAM_INTF_GET(unit, i) && 7331 bk_svm_info->empty_tcam_idx_end < i) { 7332 bk_svm_info->empty_tcam_idx_end = i; 7333 } 7334 } 7335 bk_svm_info->empty_tcam_idx_cnt -= 7336 bk_svm_info->valid_tcam_idx_cnt; 7337 7338 bmp_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 7339 bk_svm_info->empty_offset_mode_cnt = bmp_size; 7340 bk_svm_info->valid_offset_mode_cnt = 0; 7341 bk_svm_info->valid_offset_mode_start = 0; 7342 bk_svm_info->valid_offset_mode_end = 0; 7343 bk_svm_info->empty_offset_mode_start = 0; 7344 bk_svm_info->empty_offset_mode_end = 0; 7345 7346 for (i = 0; i < bmp_size; i++) { 7347 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i)) { 7348 bk_svm_info->valid_offset_mode_cnt++; 7349 } 7350 7351 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) && 7352 !BCMI_OFFSET_MODE_ID_INTF_GET( 7353 unit, bk_svm_info->valid_offset_mode_start)) { 7354 bk_svm_info->valid_offset_mode_start = i; 7355 } 7356 7357 if (BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) && 7358 bk_svm_info->valid_offset_mode_end < i) { 7359 bk_svm_info->valid_offset_mode_end = i; 7360 } 7361 7362 if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) && 7363 BCMI_OFFSET_MODE_ID_INTF_GET( 7364 unit, bk_svm_info->empty_offset_mode_start)) { 7365 bk_svm_info->empty_offset_mode_start = i; 7366 } 7367 7368 if (!BCMI_OFFSET_MODE_ID_INTF_GET(unit, i) && 7369 bk_svm_info->empty_offset_mode_end < i) { 7370 bk_svm_info->empty_offset_mode_end = i; 7371 } 7372 } 7373 bk_svm_info->empty_offset_mode_cnt -= 7374 bk_svm_info->valid_offset_mode_cnt; 7375 } 7376 POL_FUNCTION_TRACE(unit, "OUT"); 7377 return rv; 7378 } 7379 7380 /* 7381 * Function: 7382 * bcmi_esw_global_meter_reinit 7383 * Purpose: 7384 * Reinit all the global meter internal data structures on warm boot 7385 * Parameters: 7386 * unit - (IN) unit number 7387 * Returns: 7388 * BCM_E_XXX 7389 */ 7390 STATIC int 7391 bcmi_esw_global_meter_reinit(int unit) 7392 { 7393 bcm_error_t rv = BCM_E_NONE; 7394 soc_scache_handle_t scache_handle; 7395 int stable_size; 7396 uint8 *policer_scache; 7397 7398 POL_FUNCTION_TRACE(unit, "IN"); 7399 7400 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 7401 7402 /* In case WARM BOOT level 2 store is not configured return from here. */ 7403 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 7404 /* Warm Boot */ 7405 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 7406 7407 rv = _bcm_esw_scache_ptr_get( 7408 unit, scache_handle, FALSE, 0, 7409 &policer_scache, BCM_WB_DEFAULT_VERSION, NULL); 7410 if (rv == BCM_E_NOT_FOUND) { 7411 /* Maybe proceed with Level 1 Warm Boot */ 7412 return BCM_E_NONE; 7413 } 7414 7415 /* go through scache and recover policer configuration */ 7416 BCM_IF_ERROR_RETURN( 7417 bcmi_esw_global_meter_policer_recover_from_scache(unit, policer_scache)); 7418 } 7419 7420 POL_FUNCTION_TRACE(unit, "OUT"); 7421 return rv; 7422 } 7423 #endif /* BCM_WARM_BOOT_SUPPORT */ 7424 7425 /* 7426 * Function: 7427 * bcmi_esw_global_meter_cleanup 7428 * Purpose: 7429 * Cleanup the global meter(service meter) internal data structure on 7430 * init failure. 7431 * Parameters: 7432 * Unit - unit number 7433 * Returns: 7434 * BCM_E_XXX 7435 */ 7436 STATIC int 7437 bcmi_esw_global_meter_cleanup(int unit) 7438 { 7439 int rv = BCM_E_NONE; 7440 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 7441 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 7442 int i = 0; 7443 bcmi_global_meter_policer_control_t *policer_control = NULL; 7444 7445 POL_FUNCTION_TRACE(unit, "IN"); 7446 7447 CHECK_GLOBAL_METER_INIT(unit); 7448 7449 bk_svm_info = BCMI_SVM_BK_GET(unit); 7450 7451 POL_MEM_FREE(bk_svm_info->tcam_intf_bitmap); 7452 7453 if (bk_svm_info->offset_mode_v != NULL) { 7454 for (i = 0; i < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; i++) { 7455 POL_MEM_FREE(bk_svm_info->offset_mode_v[i].attr_selectors); 7456 POL_MEM_FREE(bk_svm_info->offset_mode_v[i].pkt_attr_v); 7457 } 7458 } 7459 POL_MEM_FREE(bk_svm_info->offset_mode_v); 7460 POL_MEM_FREE(bk_svm_info->offset_mode_intf_bitmap); 7461 7462 /* mutex destroy */ 7463 if (NULL != bk_svm_info->mutex) { 7464 sal_mutex_destroy(bk_svm_info->mutex); 7465 bk_svm_info->mutex = NULL; 7466 } 7467 7468 /* mutex destroy */ 7469 if (NULL != global_meter_mutex[unit]) { 7470 sal_mutex_destroy(global_meter_mutex[unit]); 7471 global_meter_mutex[unit] = NULL; 7472 } 7473 7474 /* Free handles of index management for meter action */ 7475 if (NULL != BCMI_ACTION_LIST_HANDLE_GET(unit)) { 7476 shr_aidxres_list_destroy(BCMI_ACTION_LIST_HANDLE_GET(unit)); 7477 BCMI_ACTION_LIST_HANDLE_GET(unit) = NULL; 7478 } 7479 7480 /* Free handles of index management for meter policer */ 7481 if (NULL != BCMI_POLICER_LIST_HANDLE_GET(unit)) { 7482 shr_aidxres_list_destroy(BCMI_POLICER_LIST_HANDLE_GET(unit)); 7483 BCMI_POLICER_LIST_HANDLE_GET(unit) = NULL; 7484 } 7485 7486 /* Iterate over all hash buckets. */ 7487 for (i = 0; i < BCMI_GLOBAL_METER_HASH_SIZE; i++) { 7488 policer_control = BCMI_POLICER_HASH_BK_GET(unit, i); 7489 /* Destroy entries in each bucket. */ 7490 while (NULL != policer_control) { 7491 /* De-allocate policer descriptor. */ 7492 POL_MEM_FREE(policer_control->pol_cfg); 7493 POL_MEM_FREE(policer_control); 7494 } 7495 } 7496 7497 POL_MEM_FREE(BCMI_POLICER_BK_GET(unit)); 7498 POL_MEM_FREE(BCMI_ACTION_BK_GET(unit)); 7499 7500 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 7501 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 7502 7503 /* Check if the chip specific function existed */ 7504 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->mem_clear); 7505 7506 rv = gm_dev_info->mem_clear(unit); 7507 BCM_IF_ERROR_RETURN(rv); 7508 7509 global_meter_status[unit].initialised = FALSE; 7510 7511 POL_FUNCTION_TRACE(unit, "OUT"); 7512 return rv; 7513 } 7514 7515 /* 7516 * Function: 7517 * bcmi_esw_global_meter_init 7518 * Purpose: 7519 * Initialise service meter data-structure 7520 * Parameters: 7521 * Unit - unit number 7522 * Returns: 7523 * BCM_E_XXX 7524 */ 7525 STATIC int 7526 bcmi_esw_global_meter_init(int unit) 7527 { 7528 int rv = BCM_E_NONE; 7529 bcmi_policer_svm_bk_t *bk_svm_info = NULL; 7530 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 7531 uint32 global_meter_ctrl_disable = 0; 7532 uint32 table_size; 7533 uint32 action_size = 0; 7534 uint32 size_bank = 0, block_factor = 0; 7535 int i = 0; 7536 bcm_policer_global_meter_config_t global_meter_config_v; 7537 7538 POL_FUNCTION_TRACE(unit, "IN"); 7539 7540 if (!soc_feature(unit, soc_feature_global_meter)) { 7541 return BCM_E_UNAVAIL; 7542 } 7543 7544 if (!soc_feature(unit, soc_feature_global_meter_v2)) { 7545 return BCM_E_UNAVAIL; 7546 } 7547 7548 /* assert check that attr_to_bit_selector is added corrected */ 7549 (void)check_attr_to_bit_selector(); 7550 7551 /* Initial all unit with default value FALSE. */ 7552 if (FALSE == bcmi_global_meter_dev_info_initialized) { 7553 for (i = 0; i < BCM_MAX_NUM_UNITS; i++) { 7554 BCM_SVM_DEV_INFO_GET(unit) = NULL; 7555 } 7556 bcmi_global_meter_dev_info_initialized = TRUE; 7557 } 7558 7559 /* Register driver functions */ 7560 rv = bcmi_global_meter_dev_info_init(unit); 7561 if (BCM_FAILURE(rv)) { 7562 LOG_ERROR(BSL_LS_BCM_POLICER, 7563 (BSL_META_U(unit, 7564 "Device info init failed (rv = %d)\n"), 7565 rv)); 7566 return rv; 7567 } 7568 7569 if (TRUE == global_meter_status[unit].initialised) { 7570 bcmi_esw_global_meter_cleanup(unit); 7571 } 7572 7573 /* ******************************************** */ 7574 /* 7575 * Check if Service meter Block is enable or not in config.bcm 7576 * global_meter_control = 1 means enable 7577 * global_meter_control = 0 means disable 7578 */ 7579 if (!soc_property_get(unit, spn_GLOBAL_METER_CONTROL, 1)) { 7580 global_meter_ctrl_disable = BCM_POLICER_GLOBAL_METER_DISABLE; 7581 } 7582 7583 LOG_DEBUG(BSL_LS_BCM_POLICER, 7584 (BSL_META_U(unit, 7585 "global_meter_ctrl_disable = %d, " 7586 "enable %d\n"), 7587 global_meter_ctrl_disable, 7588 global_meter_ctrl_disable == 7589 BCM_POLICER_GLOBAL_METER_DISABLE ? 0 : 1 7590 )); 7591 7592 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 7593 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 7594 7595 /* Check if the chip specific function existed */ 7596 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->svm_enable_set); 7597 7598 if (BCM_POLICER_GLOBAL_METER_DISABLE == global_meter_ctrl_disable) { 7599 rv = gm_dev_info->svm_enable_set(unit, FALSE); 7600 BCM_IF_ERROR_RETURN(rv); 7601 global_meter_status[unit].initialised = FALSE; 7602 LOG_WARN(BSL_LS_BCM_POLICER, 7603 (BSL_META_U(unit, 7604 "GLOBAL METER FEATURE disabled " 7605 "at HW for unit %d\n"), unit)); 7606 return rv; 7607 } else { 7608 rv = gm_dev_info->svm_enable_set(unit, TRUE); 7609 BCM_IF_ERROR_RETURN(rv); 7610 } 7611 /* ******************************************** */ 7612 7613 /* ******************************************** */ 7614 /* 7615 * Always enable SEOP metering all the time in SVM block. 7616 * It's usable for any metering mode. 7617 */ 7618 7619 /* Check if the chip specific function existed */ 7620 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->seop_enable_set); 7621 7622 rv = gm_dev_info->seop_enable_set(unit, 1); 7623 BCM_IF_ERROR_RETURN(rv); 7624 /* ******************************************** */ 7625 7626 /* Initialize bookkeeping data structure */ 7627 bk_svm_info = BCMI_SVM_BK_GET(unit); 7628 7629 /* Allocate usage bitmap */ 7630 table_size = BCMI_POLICER_SVC_METER_TCAM_SIZE; 7631 if ((table_size) > (soc_mem_index_max(unit, SVC_METER_OFFSET_TCAMm) + 1)) 7632 { 7633 LOG_ERROR(BSL_LS_BCM_POLICER, 7634 (BSL_META_U(unit, 7635 "Number of global meters exceeding " 7636 "its max value\n"))); 7637 return BCM_E_INTERNAL; 7638 } 7639 7640 POL_MEM_ALLOC( 7641 bk_svm_info->tcam_intf_bitmap, 7642 SHR_BITALLOCSIZE(table_size), 7643 "TCAM intf_bitmap"); 7644 if (bk_svm_info->tcam_intf_bitmap == NULL) { 7645 bcmi_esw_global_meter_cleanup(unit); 7646 LOG_ERROR(BSL_LS_BCM_POLICER, 7647 (BSL_META_U(unit, 7648 "Unable to allocate memory for " 7649 "tcam_intf_bitmap\n"))); 7650 return BCM_E_MEMORY; 7651 } 7652 7653 bk_svm_info->valid_tcam_idx_cnt = 0; 7654 bk_svm_info->valid_tcam_idx_start = 0; 7655 bk_svm_info->valid_tcam_idx_end = 0; 7656 bk_svm_info->empty_tcam_idx_cnt = table_size; 7657 bk_svm_info->empty_tcam_idx_start = 0; 7658 bk_svm_info->empty_tcam_idx_end = table_size - 1; 7659 7660 /* Allocate usage bitmap */ 7661 table_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 7662 POL_MEM_ALLOC( 7663 bk_svm_info->offset_mode_intf_bitmap, 7664 SHR_BITALLOCSIZE(table_size), 7665 "Offset Mode intf_bitmap"); 7666 if (bk_svm_info->offset_mode_intf_bitmap == NULL) { 7667 bcmi_esw_global_meter_cleanup(unit); 7668 LOG_ERROR(BSL_LS_BCM_POLICER, 7669 (BSL_META_U(unit, 7670 "Unable to allocate memory for " 7671 "offset_mode_intf_bitmap\n"))); 7672 return BCM_E_MEMORY; 7673 } 7674 7675 7676 bk_svm_info->valid_offset_mode_cnt = 0; 7677 bk_svm_info->valid_offset_mode_start = 0; 7678 bk_svm_info->valid_offset_mode_end = 0; 7679 bk_svm_info->empty_offset_mode_cnt = table_size; 7680 bk_svm_info->empty_offset_mode_start = 0; 7681 bk_svm_info->empty_offset_mode_end = table_size - 1; 7682 7683 if (bk_svm_info->mutex == NULL) { 7684 bk_svm_info->mutex = sal_mutex_create("Global meter bk mutex"); 7685 if (bk_svm_info->mutex == NULL) { 7686 bcmi_esw_global_meter_cleanup(unit); 7687 LOG_ERROR(BSL_LS_BCM_POLICER, 7688 (BSL_META_U(unit, 7689 "Unable to create bk mutex\n"))); 7690 return BCM_E_MEMORY; 7691 } 7692 } 7693 7694 /* Init the offset table 0 such that it can be used for non-offset 7695 based metering */ 7696 if (global_meter_mutex[unit] == NULL) { 7697 global_meter_mutex[unit] = sal_mutex_create("Global meter mutex"); 7698 if (global_meter_mutex[unit] == NULL) { 7699 bcmi_esw_global_meter_cleanup(unit); 7700 LOG_ERROR(BSL_LS_BCM_POLICER, 7701 (BSL_META_U(unit, 7702 "Unable to create mutex\n"))); 7703 return BCM_E_MEMORY; 7704 } 7705 } 7706 7707 /* Allocate policer offset mode instance. */ 7708 table_size = BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; 7709 POL_MEM_ALLOC( 7710 bk_svm_info->offset_mode_v, 7711 table_size * sizeof(bcmi_policer_svm_offset_mode_bk_t), 7712 "offset mode instance"); 7713 if (NULL == bk_svm_info->offset_mode_v) { 7714 bcmi_esw_global_meter_cleanup(unit); 7715 LOG_ERROR(BSL_LS_BCM_POLICER, 7716 (BSL_META_U(unit, 7717 "Unable to allocate memory for " 7718 "offset_mode_v\n"))); 7719 return (BCM_E_MEMORY); 7720 } 7721 for (i = 0; i < BCMI_POLICER_SVC_METER_MAX_OFFSET_MODE; i++) { 7722 bcmi_policer_svm_offset_mode_bk_t_init( 7723 &(bk_svm_info->offset_mode_v[i])); 7724 } 7725 7726 /* Allocate meter action management data structure */ 7727 action_size = BCMI_POLICER_SVC_METER_ACTION_SIZE; 7728 if ((action_size) > (soc_mem_index_max(unit, SVM_POLICY_TABLEm) + 1)) { 7729 LOG_ERROR(BSL_LS_BCM_POLICER, 7730 (BSL_META_U(unit, 7731 "Global meter actions exceeding " 7732 "its max value\n"))); 7733 return BCM_E_INTERNAL; 7734 } 7735 7736 POL_MEM_ALLOC( 7737 BCMI_ACTION_BK_GET(unit), 7738 action_size * sizeof(bcmi_policer_global_meter_action_bk_t), 7739 "Global meter action alloc"); 7740 if (NULL == BCMI_ACTION_BK_GET(unit)) { 7741 bcmi_esw_global_meter_cleanup(unit); 7742 LOG_ERROR(BSL_LS_BCM_POLICER, 7743 (BSL_META_U(unit, 7744 "Unable to allocate memory for " 7745 "meter action\n"))); 7746 return (BCM_E_MEMORY); 7747 } 7748 7749 /* Index management for meter action */ 7750 if (NULL != BCMI_ACTION_LIST_HANDLE_GET(unit)) { 7751 shr_aidxres_list_destroy(BCMI_ACTION_LIST_HANDLE_GET(unit)); 7752 BCMI_ACTION_LIST_HANDLE_GET(unit) = NULL; 7753 } 7754 7755 /* Create meter action */ 7756 if (shr_aidxres_list_create( 7757 &BCMI_ACTION_LIST_HANDLE_GET(unit), 7758 0, (action_size - 1), 7759 0, (action_size - 1), 7760 8, 7761 "global_meter_action") != BCM_E_NONE) { 7762 bcmi_esw_global_meter_cleanup(unit); 7763 LOG_ERROR(BSL_LS_BCM_POLICER, 7764 (BSL_META_U(unit, 7765 "Couldn't create alligned list " 7766 "for global meter action\n"))); 7767 return BCM_E_INTERNAL; 7768 } 7769 7770 /* Reserve the first entry in action table */ 7771 rv = shr_aidxres_list_reserve_block( 7772 BCMI_ACTION_LIST_HANDLE_GET(unit), 0, 1); 7773 if (BCM_FAILURE(rv)) { 7774 bcmi_esw_global_meter_cleanup(unit); 7775 LOG_ERROR(BSL_LS_BCM_POLICER, 7776 (BSL_META_U(unit, 7777 "Not able to reserve first entry " 7778 "in action table\n"))); 7779 return (rv); 7780 } 7781 7782 /* Allocate policer lookup hash. */ 7783 POL_MEM_ALLOC( 7784 BCMI_POLICER_BK_GET(unit), 7785 BCMI_GLOBAL_METER_HASH_SIZE * 7786 sizeof(bcmi_global_meter_policer_control_t *), 7787 "Global meter hash"); 7788 7789 if (NULL == BCMI_POLICER_BK_GET(unit)) { 7790 bcmi_esw_global_meter_cleanup(unit); 7791 LOG_ERROR(BSL_LS_BCM_POLICER, 7792 (BSL_META_U(unit, 7793 "Unable to allocate memory for policer bookkeep " 7794 "data structure\n"))); 7795 return (BCM_E_MEMORY); 7796 } 7797 7798 if (NULL != BCMI_POLICER_LIST_HANDLE_GET(unit)) { 7799 shr_aidxres_list_destroy(BCMI_POLICER_LIST_HANDLE_GET(unit)); 7800 BCMI_POLICER_LIST_HANDLE_GET(unit) = NULL; 7801 } 7802 7803 size_bank = BCMI_POLICER_SVC_METER_POOL_SIZE; 7804 table_size = BCMI_POLICER_SVC_METER_TCAM_SIZE; 7805 POL_GET_LOG2(table_size, block_factor); 7806 7807 /* Create it */ 7808 if (shr_aidxres_list_create( 7809 &BCMI_POLICER_LIST_HANDLE_GET(unit), 7810 0, (size_bank - 1), 7811 0, (size_bank - 1), 7812 block_factor, 7813 "global_meter_policer") != BCM_E_NONE) { 7814 bcmi_esw_global_meter_cleanup(unit); 7815 LOG_ERROR(BSL_LS_BCM_POLICER, 7816 (BSL_META_U(unit, 7817 "Couldn't create alligned list for " 7818 "global meter policer\n"))); 7819 return BCM_E_INTERNAL; 7820 } 7821 7822 /* Reserve the first entry in policer table */ 7823 rv = shr_aidxres_list_reserve_block( 7824 BCMI_POLICER_LIST_HANDLE_GET(unit), 0, 1); 7825 if (BCM_FAILURE(rv)) { 7826 bcmi_esw_global_meter_cleanup(unit); 7827 LOG_ERROR(BSL_LS_BCM_POLICER, 7828 (BSL_META_U(unit, 7829 "Not able to reserve first entry " 7830 "in policer table\n"))); 7831 return (rv); 7832 } 7833 7834 #ifdef BCM_WARM_BOOT_SUPPORT 7835 if (SOC_WARM_BOOT(unit)) { 7836 rv = bcmi_esw_global_meter_reinit(unit); 7837 if (BCM_FAILURE(rv)) { 7838 bcmi_esw_global_meter_cleanup(unit); 7839 LOG_ERROR(BSL_LS_BCM_POLICER, 7840 (BSL_META_U(unit, 7841 "Warm boot init failed\n"))); 7842 return BCM_E_INTERNAL; 7843 } 7844 } 7845 #endif /* BCM_WARM_BOOT_SUPPORT */ 7846 global_meter_status[unit].initialised = TRUE; 7847 7848 LOG_VERBOSE(BSL_LS_BCM_POLICER, 7849 (BSL_META_U(unit, 7850 "GLOBAL METER FEATURE initialised\n"))); 7851 /* 7852 * Init default HW values 7853 */ 7854 bcm_policer_global_meter_config_t_init(&global_meter_config_v); 7855 7856 /* 7857 * Enable Global Meter Inter Frame Gap 7858 * IFG value must be configured by switch API 7859 * bcmSwitchMeterAdjustInterframeGap (per port) 7860 */ 7861 global_meter_config_v.ifg_enable = 0; 7862 7863 /* Set order of source tables in the case of conflict source happened. */ 7864 global_meter_config_v.source_order_count = 7; 7865 global_meter_config_v.source_order[0] = 7866 bcmPolicerGlobalMeterSourceFieldStageLookup; 7867 global_meter_config_v.source_order[1] = 7868 bcmPolicerGlobalMeterSourceDstMac; 7869 global_meter_config_v.source_order[2] = 7870 bcmPolicerGlobalMeterSourceSrcMac; 7871 global_meter_config_v.source_order[3] = 7872 bcmPolicerGlobalMeterSourceVlanTranslateFirst; 7873 global_meter_config_v.source_order[4] = 7874 bcmPolicerGlobalMeterSourceVlanTranslateSecond; 7875 global_meter_config_v.source_order[5] = 7876 bcmPolicerGlobalMeterSourceVlan; 7877 global_meter_config_v.source_order[6] = 7878 bcmPolicerGlobalMeterSourcePort; 7879 7880 /* Sets Global Meter Configuration */ 7881 bcm_esw_policer_global_meter_config_set(unit, &global_meter_config_v); 7882 7883 POL_FUNCTION_TRACE(unit, "OUT"); 7884 return rv; 7885 } 7886 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 7887 7888 STATIC 7889 int _bcm_esw_svc_meter_offset_mode_id_check (uint32 unit, uint32 flags, 7890 bcm_policer_group_mode_type_t type, uint32 total_policers, 7891 uint32 num_selectors, 7892 bcm_policer_group_mode_attr_selector_t * attr_selectors, 7893 uint32 *mode_id); 7894 7895 STATIC 7896 int _bcm_esw_policer_group_mode_fillup_values(int unit, uint32 flags, 7897 bcm_policer_group_mode_type_t type, uint32 total_policers, 7898 uint32 num_selectors, 7899 bcm_policer_group_mode_attr_selector_t *attr_selectors, 7900 bcm_policer_attr_selectors_t *pkt_attr_selectors); 7901 7902 STATIC 7903 int _bcm_wb_attr_selectors_copy_to_attr_selectors( 7904 uint32 num_selectors, 7905 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb, 7906 bcm_policer_group_mode_attr_selector_t *attr_selectors); 7907 7908 STATIC 7909 int _bcm_esw_svc_meter_compressed_modes_match(int unit, 7910 compressed_attr_selectors_t *compressed_attr_selectors_v, 7911 bcm_policer_group_mode_t group_mode, 7912 int8 type, 7913 bcm_policer_svc_meter_mode_t *svc_meter_mode); 7914 7915 #ifdef BCM_WARM_BOOT_SUPPORT 7916 STATIC 7917 int _bcm_esw_svc_meter_wb_size_calc(int unit, int *size); 7918 #endif 7919 7920 typedef int (*_bcm_esw_svm_mem_entry_traverse_cb)(int unit, 7921 soc_mem_t mem, uint32 index, void *entry, 7922 void *user_data, uint32 *dirty); 7923 7924 bcm_error_t 7925 _bcm_esw_svm_source_traverse(int unit, soc_mem_t mem, int start_idx, 7926 int end_idx, _bcm_esw_svm_mem_entry_traverse_cb cb, 7927 void *user_data); 7928 7929 /* 7930 * Function: 7931 * check_global_meter_init 7932 * Purpose: 7933 * To check whether the global meter module is initialized or not 7934 * Parameters: 7935 * Unit - (IN) unit number 7936 * Returns: 7937 * BCM_E_INIT 7938 */ 7939 int _check_global_meter_init(int unit) 7940 { 7941 if (!global_meter_status[unit].initialised) { 7942 return BCM_E_INIT; 7943 } else { 7944 return BCM_E_NONE; 7945 } 7946 } 7947 7948 /* 7949 * Function: 7950 * convert_to_bitmask 7951 * Purpose: 7952 * 7953 * Parameters: 7954 * num - number to be converted to bistmask 7955 * Returns: 7956 * bit mask for the number 7957 */ 7958 static int convert_to_bitmask(int num) 7959 { 7960 int bit_mask = 0; 7961 num = num & 0xf; 7962 while (num > 0) { 7963 bit_mask = bit_mask | (1 << (num-1)); 7964 num--; 7965 } 7966 return bit_mask; 7967 } 7968 7969 /* 7970 * Function: 7971 * convert_to_mask 7972 * Purpose: 7973 * Creates a mask with all the bit positon other then the positon 7974 * represented by num 7975 * Parameters: 7976 * num - number 7977 * Returns: 7978 * BCM_E_XXX 7979 */ 7980 static int convert_to_mask(int num) 7981 { 7982 int bit_mask = 0; 7983 num = num & 0xf; 7984 bit_mask = ~(1 << num); 7985 return bit_mask; 7986 } 7987 7988 /* 7989 * Function: 7990 * _bcm_attr_selectors_copy_to_wb_attr_selectors 7991 * Purpose: 7992 * Copy the content of attr_selectors from 7993 * bcm_policer_group_mode_attr_selector_t to 7994 * bcm_policer_group_mode_attr_selector_wb_t 7995 * Parameters: 7996 * num_selectors (IN) - no. of attr_selectors for KT2/TR3/FB4 WB structure 7997 * attr_selectors (IN) - bcm API attr_selectors 7998 * attr_selectors_wb (OUT)- attr_selectors for KT2/TR3/FB4 WB structure 7999 * Returns: 8000 * BCM_E_XXX 8001 */ 8002 STATIC int 8003 _bcm_attr_selectors_copy_to_wb_attr_selectors( 8004 uint32 num_selectors, 8005 bcm_policer_group_mode_attr_selector_t *attr_selectors, 8006 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb) 8007 { 8008 uint32 sel = 0; 8009 8010 if ((NULL == attr_selectors) || 8011 (NULL == attr_selectors_wb)) { 8012 return BCM_E_PARAM; 8013 } 8014 8015 for (sel = 0; sel < num_selectors; sel++) { 8016 attr_selectors_wb[sel].flags = attr_selectors[sel].flags; 8017 attr_selectors_wb[sel].policer_offset = attr_selectors[sel].policer_offset; 8018 attr_selectors_wb[sel].attr = attr_selectors[sel].attr; 8019 attr_selectors_wb[sel].attr_value = attr_selectors[sel].attr_value; 8020 attr_selectors_wb[sel].udf_id = attr_selectors[sel].udf_id; 8021 attr_selectors_wb[sel].offset = attr_selectors[sel].offset; 8022 attr_selectors_wb[sel].width = attr_selectors[sel].width; 8023 } 8024 8025 return BCM_E_NONE; 8026 } 8027 8028 /* 8029 * Function: 8030 * _bcm_wb_attr_selectors_copy_to_attr_selectors 8031 * Purpose: 8032 * Copy the content of attr_selectors from 8033 * bcm_policer_group_mode_attr_selector_wb_t to 8034 * bcm_policer_group_mode_attr_selector_t 8035 * Parameters: 8036 * num_selectors (IN) - no. of attr_selectors for KT2/TR3/FB4 WB structure 8037 * attr_selectors_wb (IN) - attr_selectors for KT2/TR3/FB4 WB structure 8038 * attr_selectors (OUT)- bcm API attr_selectors 8039 * Returns: 8040 * BCM_E_XXX 8041 */ 8042 STATIC int 8043 _bcm_wb_attr_selectors_copy_to_attr_selectors( 8044 uint32 num_selectors, 8045 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb, 8046 bcm_policer_group_mode_attr_selector_t *attr_selectors) 8047 { 8048 uint32 sel = 0; 8049 8050 if (NULL == attr_selectors_wb || NULL == attr_selectors) { 8051 return BCM_E_PARAM; 8052 } 8053 8054 for (sel = 0; sel < num_selectors; sel++) { 8055 attr_selectors[sel].flags = attr_selectors_wb[sel].flags; 8056 attr_selectors[sel].policer_offset = attr_selectors_wb[sel].policer_offset; 8057 attr_selectors[sel].attr = attr_selectors_wb[sel].attr; 8058 attr_selectors[sel].attr_value = attr_selectors_wb[sel].attr_value; 8059 attr_selectors[sel].udf_id = attr_selectors_wb[sel].udf_id; 8060 attr_selectors[sel].offset = attr_selectors_wb[sel].offset; 8061 attr_selectors[sel].width = attr_selectors_wb[sel].width; 8062 } 8063 8064 return BCM_E_NONE; 8065 } 8066 8067 /* 8068 * Function: 8069 * _bcm_attr_selectors_wb_attr_selectors_cmp 8070 * Purpose: 8071 * compare the content of attr_selectors between 8072 * bcm_policer_group_mode_attr_selector_wb_t and 8073 * bcm_policer_group_mode_attr_selector_t 8074 * Parameters: 8075 * num_selectors (IN) - no. of attr_selectors for KT2/TR3/FB4 WB structure. 8076 * attr_selectors (IN) - bcm API attr_selectors 8077 * attr_selectors_wb (IN) - attr_selectors for KT2/TR3/FB4 WB structure 8078 * is_same (OUT) - return if contents are all the same or not 8079 * Returns: 8080 * BCM_E_XXX 8081 */ 8082 STATIC int 8083 _bcm_attr_selectors_wb_attr_selectors_cmp( 8084 uint32 num_selectors, 8085 bcm_policer_group_mode_attr_selector_t *attr_selectors, 8086 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb, 8087 int *is_same) 8088 { 8089 uint32 sel = 0; 8090 8091 if ((NULL == attr_selectors_wb) || 8092 (NULL == attr_selectors) || 8093 (NULL == is_same)) { 8094 return BCM_E_PARAM; 8095 } 8096 8097 *is_same = TRUE; 8098 for (sel = 0; sel < num_selectors; sel++) { 8099 if ((attr_selectors[sel].flags != 8100 attr_selectors_wb[sel].flags) || 8101 (attr_selectors[sel].policer_offset != 8102 attr_selectors_wb[sel].policer_offset) || 8103 (attr_selectors[sel].attr != 8104 attr_selectors_wb[sel].attr) || 8105 (attr_selectors[sel].attr_value != 8106 attr_selectors_wb[sel].attr_value) || 8107 (attr_selectors[sel].udf_id != 8108 attr_selectors_wb[sel].udf_id) || 8109 (attr_selectors[sel].offset != 8110 attr_selectors_wb[sel].offset) || 8111 (attr_selectors[sel].width != 8112 attr_selectors_wb[sel].width)) { 8113 *is_same = FALSE; 8114 break; 8115 } 8116 } 8117 return BCM_E_NONE; 8118 } 8119 8120 /* 8121 * Function: 8122 * get_max_banks_in_a_pool 8123 * Purpose: 8124 * Returns the number of banks per pool 8125 * Parameters: 8126 * unit - unit number 8127 * Returns: 8128 * num_banks 8129 */ 8130 STATIC 8131 int get_max_banks_in_a_pool(int unit) 8132 { 8133 return BCM_SVM_DEV_ATTR(unit)->banks_per_pool; 8134 } 8135 8136 /* 8137 * Function: 8138 * _bcm_policer_flow_info_t_init 8139 * Purpose: 8140 * Init bcm_policer_flow_info_t 8141 * Parameters: 8142 * flow_info : pointer of type _bcm_policer_flow_info_t 8143 * Returns: 8144 * BCM_E_XXX 8145 */ 8146 STATIC 8147 int _bcm_policer_flow_info_t_init(_bcm_policer_flow_info_t *flow_info) 8148 { 8149 flow_info->flow_type = bcmPolicerFlowTypeNormal; 8150 flow_info->req_alloc = FALSE; 8151 flow_info->skip_pool = -1; 8152 flow_info->skip_bank = -1; 8153 flow_info->req_pool = -1; 8154 flow_info->req_base_offset = -1; 8155 8156 return BCM_E_NONE; 8157 } 8158 8159 /* 8160 * Function: 8161 * _bcm_policer_svc_meter_update_udf_selector_keys 8162 * Purpose: 8163 * Internal function for updating udf selector keys 8164 * Parameters: 8165 * Unit - (IN) unit number 8166 * pkt_attr_selector_key - (IN) packet attribute selector key 8167 * udf_pkt_attr - (IN) UDF packet attributes 8168 * total_udf_bits - (OUT) Total number of udf bits used 8169 * Returns: 8170 * BCM_E_XXX 8171 */ 8172 bcm_error_t _bcm_policer_svc_meter_update_udf_selector_keys( 8173 int unit, 8174 soc_reg_t pkt_attr_selector_key, 8175 udf_pkt_attr_selectors_t *udf_pkt_attr, 8176 uint32 *total_udf_bits) 8177 { 8178 uint64 pkt_attr_selector_key_value; 8179 uint32 udf_valid_bits = 0; 8180 uint8 key_bit_selector_position = 0; 8181 uint8 mask = 0; 8182 uint32 index = 0; 8183 8184 COMPILER_64_ZERO(pkt_attr_selector_key_value); 8185 (*total_udf_bits) = 0; 8186 if (!(pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) && 8187 (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r)) { 8188 /* Valid mem value go ahead for setting 8189 ING_FLEX_CTR_PKT_ATTR_SELECTOR_KEY_?r: */ 8190 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 8191 "Invalid memory for packet attribute selector \n"))); 8192 return BCM_E_PARAM; 8193 } 8194 8195 /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */ 8196 SOC_IF_ERROR_RETURN(soc_reg_get(unit, 8197 pkt_attr_selector_key, 8198 REG_PORT_ANY, 8199 0, 8200 &pkt_attr_selector_key_value)); 8201 8202 /* Next set field value for 8203 ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/ 8204 soc_reg64_field32_set( 8205 unit, 8206 pkt_attr_selector_key, 8207 &pkt_attr_selector_key_value, 8208 USE_UDF_KEYf, 8209 1); 8210 udf_valid_bits |= SVC_METER_UDF1_VALID; 8211 udf_valid_bits |= SVC_METER_UDF2_VALID; 8212 8213 soc_reg64_field32_set( 8214 unit, 8215 pkt_attr_selector_key, 8216 &pkt_attr_selector_key_value, 8217 USER_SPECIFIED_UDF_VALIDf, 8218 udf_valid_bits); 8219 8220 /* Now update selector keys 8221 * In udf based offset generation, bit-0 is for drop. 8222 * bit-1 to bit-32 is used for 2 16-bits udf-chunks 8223 */ 8224 if (udf_pkt_attr->drop == 1) { 8225 BCM_IF_ERROR_RETURN( 8226 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 8227 unit, 8228 pkt_attr_selector_key, 8229 &pkt_attr_selector_key_value, 8230 0, /* Start bit of drop */ 8231 1, /* width of drop */ 8232 1, 8233 &key_bit_selector_position)); 8234 } 8235 for (index = 0; index < udf_pkt_attr->total_subdiv; index++) { 8236 mask = (1 << udf_pkt_attr->udf_subdiv[index].width) - 1; 8237 BCM_IF_ERROR_RETURN( 8238 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 8239 unit, 8240 pkt_attr_selector_key, 8241 &pkt_attr_selector_key_value, 8242 udf_pkt_attr->udf_subdiv[index].offset + 1, /* +1 to adjust drop bit */ 8243 udf_pkt_attr->udf_subdiv[index].width, 8244 mask, 8245 &key_bit_selector_position)); 8246 } 8247 8248 /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */ 8249 SOC_IF_ERROR_RETURN(soc_reg_set(unit, 8250 pkt_attr_selector_key, 8251 REG_PORT_ANY, 8252 0, 8253 pkt_attr_selector_key_value)); 8254 return BCM_E_NONE; 8255 } 8256 /* 8257 * Function: 8258 * _bcm_esw_policer_get_offset_table_policer_count 8259 * Purpose: 8260 * set group mode and number of policers in offset table at 8261 * offsets 254 and 255 - for use during warmboot 8262 * 8263 * Parameters: 8264 * Unit - (IN) unit number 8265 * offset_mode - (IN) Offset mode 8266 * mode - (OUT) Policer group mode 8267 * npolicers - (OUT) Total number of policer created 8268 * Returns: 8269 * BCM_E_XXX 8270 */ 8271 bcm_error_t _bcm_esw_policer_get_offset_table_policer_count( 8272 int unit, 8273 bcm_policer_svc_meter_mode_t offset_mode, 8274 bcm_policer_group_mode_t *mode, 8275 int *npolicers) 8276 { 8277 uint32 offset_table_entry = 0; 8278 int max_index = 0; 8279 int meter_enable; 8280 8281 max_index = BCM_POLICER_SVC_METER_MAX_OFFSET; 8282 /* First Get complete value of ING_SVM_METER_OFFSET_TABLE_?m value */ 8283 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 8284 SVM_OFFSET_TABLEm, MEM_BLOCK_ANY, 8285 ((offset_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) | 8286 (max_index - 1)), 8287 &offset_table_entry)); 8288 8289 /* Read meter_enable first, if meter_enable=1, offsets 255,254 have 8290 not stored npolicers and group_mode. 8291 Also, Warmboot vesion BCM_WB_VERSION_1_1 onwards, npolices and group_mode 8292 are stored in scache. */ 8293 soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry, 8294 METER_ENABLEf, (uint32 *)&meter_enable); 8295 if (meter_enable == 1) { 8296 *npolicers = 0; 8297 *mode = 0; 8298 return BCM_E_NONE; 8299 } 8300 8301 soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry, 8302 OFFSETf, (uint32 *)npolicers); 8303 8304 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 8305 SVM_OFFSET_TABLEm, MEM_BLOCK_ANY, 8306 ((offset_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) | 8307 (max_index - 2)), 8308 &offset_table_entry)); 8309 8310 /* Read meter_enable first, if meter_enable=1, offsets 255,254 have 8311 not stored npolicers and group_mode. 8312 Also, Warmboot vesion BCM_WB_VERSION_1_1 onwards, npolices and group_mode 8313 are stored in scache. */ 8314 soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry, 8315 METER_ENABLEf, (uint32 *)&meter_enable); 8316 if (meter_enable == 1) { 8317 *npolicers = 0; 8318 *mode = 0; 8319 return BCM_E_NONE; 8320 } 8321 soc_mem_field_get( unit, SVM_OFFSET_TABLEm, &offset_table_entry, 8322 OFFSETf, (uint32 *)mode); 8323 return BCM_E_NONE; 8324 } 8325 8326 /* 8327 * Function: 8328 * _bcm_esw_svm_offset_table_map_set 8329 * Purpose: 8330 * Write to svm offset table. 8331 * 8332 * Parameters: 8333 * Unit - (IN) unit number 8334 * mem - (IN) memory 8335 * index - (IN) Entry index in memory 8336 * entry - (IN/OUT) entry buffer at mem index 8337 * user_data - (IN) user data - offset map 8338 * dirty - (OUT) entry modified 8339 * Returns: 8340 * BCM_E_XXX 8341 */ 8342 STATIC 8343 int _bcm_esw_svm_offset_table_map_set( 8344 int unit, 8345 soc_mem_t mem, 8346 uint32 index, 8347 void *entry, 8348 void *user_data, 8349 uint32 *dirty) 8350 { 8351 uint32 pool; 8352 uint32 offset_value; 8353 uint32 meter_enable; 8354 offset_table_entry_t *offset_map = NULL; 8355 8356 if (user_data != NULL) { 8357 offset_map = (offset_table_entry_t *) user_data; 8358 } 8359 8360 if (offset_map == NULL) { 8361 pool = 0; 8362 offset_value = 0; 8363 meter_enable = 0; 8364 } else { 8365 index %= BCM_POLICER_SVC_METER_MAX_OFFSET; 8366 pool = offset_map[index].pool; 8367 offset_value = offset_map[index].offset; 8368 meter_enable = offset_map[index].meter_enable; 8369 } 8370 /* Set POOL_OFFSETf */ 8371 soc_mem_field_set(unit, 8372 mem, entry, POOL_OFFSETf, &pool); 8373 /* Set OFFSETf */ 8374 soc_mem_field_set(unit, 8375 mem, entry, OFFSETf, &offset_value); 8376 /* Set METER_ENABLEf */ 8377 soc_mem_field_set(unit, 8378 mem, entry, METER_ENABLEf, &meter_enable); 8379 8380 *dirty = TRUE; 8381 8382 return BCM_E_NONE; 8383 } 8384 8385 /* 8386 * Function: 8387 * _bcm_policer_svc_meter_update_offset_table 8388 * Purpose: 8389 * Internal function to update the SVM offset table 8390 * Parameters: 8391 * Unit - (IN) unit number 8392 * offset_table_mem - (IN) Offset table memory 8393 * svc_meter_mode - (IN) Meter offset mode 8394 * offset_map - (IN) Offset table entry map 8395 * Returns: 8396 * BCM_E_XXX 8397 */ 8398 bcm_error_t _bcm_policer_svc_meter_update_offset_table( 8399 int unit, 8400 soc_mem_t offset_table_mem, 8401 bcm_policer_svc_meter_mode_t svc_meter_mode, 8402 offset_table_entry_t *offset_map) 8403 { 8404 uint32 start_idx = 0; 8405 uint32 end_idx = 0; 8406 uint32 offset_table_entry = 0; 8407 uint32 index = 0; 8408 uint32 zero = 0; 8409 uint32 meter_enable = 0; 8410 if (offset_table_mem != SVM_OFFSET_TABLEm) { 8411 /* Valid mem value go ahead for setting SVM_OFFSET_TABLEm */ 8412 LOG_DEBUG(BSL_LS_BCM_POLICER, 8413 (BSL_META_U(unit, 8414 "Invalid table specified \n"))); 8415 return BCM_E_PARAM; 8416 } 8417 start_idx = (svc_meter_mode << 8418 BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE); 8419 end_idx = start_idx + BCM_POLICER_SVC_METER_MAX_OFFSET - 1; 8420 8421 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 8422 offset_table_mem, start_idx, end_idx, 8423 _bcm_esw_svm_offset_table_map_set, offset_map)); 8424 8425 if(svc_meter_mode == 0) { 8426 index = 0; 8427 meter_enable = 1; 8428 /* SVM_OFFSET_TABLE_?m value */ 8429 SOC_IF_ERROR_RETURN(soc_mem_read(unit, 8430 offset_table_mem, 8431 MEM_BLOCK_ANY, 8432 ((svc_meter_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE)), 8433 &offset_table_entry)); 8434 /* Set OFFSETf */ 8435 soc_mem_field_set( 8436 unit, 8437 offset_table_mem, 8438 &offset_table_entry, 8439 OFFSETf, 8440 &zero); 8441 /* Set METER_ENABLEf */ 8442 soc_mem_field_set( 8443 unit, 8444 offset_table_mem, 8445 &offset_table_entry, 8446 METER_ENABLEf, 8447 &meter_enable); 8448 /* Finally set value for ING_SVM_OFFSET_TABLE_?m?r */ 8449 SOC_IF_ERROR_RETURN(soc_mem_write(unit, 8450 offset_table_mem, 8451 MEM_BLOCK_ALL, 8452 ((svc_meter_mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) | index), 8453 &offset_table_entry)); 8454 } 8455 return BCM_E_NONE; 8456 } 8457 8458 /* 8459 * Function: 8460 * _bcm_policer_svc_meter_update_selector_keys_enable_fields 8461 * Purpose: 8462 * Internal function to set selector key enabled fields 8463 * Parameters: 8464 * Unit - (IN) unit number 8465 * pkt_attr_selector_key - (IN) Pkt attribute selector key 8466 * pkt_attr_selector_key_value - (IN) Value of selector key 8467 * pkt_attr_bit_position - (IN) Packet attribute bit position 8468 * pkt_attr_total_bits - (IN) total number of packet attribute bits 8469 * current_bit_selector_position - (IN) Current bit position 8470 * Returns: 8471 * BCM_E_XXX 8472 */ 8473 bcm_error_t _bcm_policer_svc_meter_update_selector_keys_enable_fields( 8474 int unit, 8475 soc_reg_t pkt_attr_selector_key, 8476 uint64 *pkt_attr_selector_key_value, 8477 uint32 pkt_attr_bit_position, 8478 uint32 pkt_attr_total_bits, 8479 uint8 pkt_attr_field_mask_v, 8480 uint8 *current_bit_selector_position) 8481 { 8482 uint32 index = 0; 8483 uint32 total_field_bits = 0; 8484 uint32 field_index[8] = {0}; 8485 uint32 selector_x_en_field_name[8]= { 8486 SELECTOR_0_ENf, 8487 SELECTOR_1_ENf, 8488 SELECTOR_2_ENf, 8489 SELECTOR_3_ENf, 8490 SELECTOR_4_ENf, 8491 SELECTOR_5_ENf, 8492 SELECTOR_6_ENf, 8493 SELECTOR_7_ENf, 8494 }; 8495 uint32 selector_for_bit_x_field_name[8]={ 8496 SELECTOR_FOR_BIT_0f, 8497 SELECTOR_FOR_BIT_1f, 8498 SELECTOR_FOR_BIT_2f, 8499 SELECTOR_FOR_BIT_3f, 8500 SELECTOR_FOR_BIT_4f, 8501 SELECTOR_FOR_BIT_5f, 8502 SELECTOR_FOR_BIT_6f, 8503 SELECTOR_FOR_BIT_7f, 8504 }; 8505 8506 if ((*current_bit_selector_position) + 8507 pkt_attr_total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 8508 LOG_DEBUG(BSL_LS_BCM_POLICER, 8509 (BSL_META_U(unit, 8510 "Number of slector bits exceeds max allowed \n"))); 8511 return BCM_E_INTERNAL; 8512 } 8513 8514 for (index = 0; index < 8 ; index++) { 8515 if (pkt_attr_field_mask_v & 0x1) { 8516 field_index[total_field_bits] = index; 8517 total_field_bits++; 8518 } 8519 pkt_attr_field_mask_v >>= 1; 8520 } 8521 8522 if (total_field_bits != pkt_attr_total_bits ) { 8523 LOG_ERROR(BSL_LS_BCM_FLEXCTR, 8524 (BSL_META_U(unit, "Total bits exceeding not" 8525 " matching with mask bits \n"))); 8526 return BCM_E_INTERNAL; 8527 } 8528 8529 for (index = 0; index < pkt_attr_total_bits; index++) { 8530 soc_reg64_field32_set( 8531 unit, 8532 pkt_attr_selector_key, 8533 pkt_attr_selector_key_value, 8534 selector_x_en_field_name[*current_bit_selector_position], 8535 1); 8536 soc_reg64_field32_set( 8537 unit, 8538 pkt_attr_selector_key, 8539 pkt_attr_selector_key_value, 8540 selector_for_bit_x_field_name[*current_bit_selector_position], 8541 pkt_attr_bit_position + field_index[index]); 8542 (*current_bit_selector_position) += 1; 8543 } 8544 return BCM_E_NONE; 8545 } 8546 8547 /* 8548 * Function: 8549 * bcm_policer_svc_meter_dec_mode_reference_count 8550 * Purpose: 8551 * Internal function to decrement meter offset mode usage count 8552 * Parameters: 8553 * Unit - (IN) unit number 8554 * svc_meter_mode - (IN) Meter offset mode 8555 * Returns: 8556 * BCM_E_XXX 8557 */ 8558 bcm_error_t bcm_policer_svc_meter_dec_mode_reference_count( 8559 uint32 unit, 8560 bcm_policer_svc_meter_mode_t svc_meter_mode) 8561 { 8562 int rv = BCM_E_NONE; 8563 if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) { 8564 LOG_DEBUG(BSL_LS_BCM_POLICER, 8565 (BSL_META_U(unit, 8566 "Wrong offset mode specified \n"))); 8567 return BCM_E_PARAM; 8568 } 8569 if ( global_meter_offset_mode[unit][svc_meter_mode].reference_count > 0) { 8570 global_meter_offset_mode[unit][svc_meter_mode].reference_count--; 8571 } 8572 if (global_meter_offset_mode[unit][svc_meter_mode].type != -1) { 8573 /* Deletion of the mode is done through 8574 bcm_policer_group_mode_id_destroy */ 8575 return rv; 8576 } 8577 if (global_meter_offset_mode[unit][svc_meter_mode].reference_count == 0) { 8578 rv = _bcm_esw_policer_svc_meter_delete_mode(unit, svc_meter_mode); 8579 } 8580 return rv; 8581 } 8582 8583 /* 8584 * Function: 8585 * bcm_policer_svc_meter_inc_mode_reference_count 8586 * Purpose: 8587 * Internal function to increment meter offset mode usage count 8588 * Parameters: 8589 * Unit - (IN) unit number 8590 * svc_meter_mode - (IN) Meter offset mode 8591 * Returns: 8592 * BCM_E_XXX 8593 */ 8594 bcm_error_t bcm_policer_svc_meter_inc_mode_reference_count( 8595 uint32 unit, 8596 bcm_policer_svc_meter_mode_t svc_meter_mode) 8597 { 8598 if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) { 8599 LOG_DEBUG(BSL_LS_BCM_POLICER, 8600 (BSL_META("Wrong offset mode specified \n"))); 8601 return BCM_E_PARAM; 8602 } 8603 global_meter_offset_mode[unit][svc_meter_mode].reference_count++; 8604 return BCM_E_NONE; 8605 } 8606 8607 /* 8608 * Function: 8609 * _bcm_policer_svc_meter_reserve_mode 8610 * Purpose: 8611 * Internal function to allocate/reserve meter offset mode 8612 * Parameters: 8613 * Unit - (IN) unit number 8614 * svc_meter_mode - (IN) Meter offset mode 8615 * total_bits - (IN) Total number of bits used 8616 * group_mode - (IN) Policer group mode 8617 * meter_attr - (IN) Meter attributes 8618 * Returns: 8619 * BCM_E_XXX 8620 */ 8621 bcm_error_t _bcm_policer_svc_meter_reserve_mode( 8622 uint32 unit, 8623 bcm_policer_svc_meter_mode_t svc_meter_mode, 8624 bcm_policer_group_mode_t group_mode, 8625 bcm_policer_svc_meter_attr_t *meter_attr) 8626 { 8627 if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) { 8628 LOG_DEBUG(BSL_LS_BCM_POLICER, 8629 (BSL_META("Wrong offset mode specified \n"))); 8630 return BCM_E_PARAM; 8631 } 8632 global_meter_offset_mode[unit][svc_meter_mode].used = 1; 8633 global_meter_offset_mode[unit][svc_meter_mode].group_mode = group_mode; 8634 global_meter_offset_mode[unit][svc_meter_mode].type = -1; 8635 global_meter_offset_mode[unit][svc_meter_mode].meter_attr = *meter_attr; 8636 return BCM_E_NONE; 8637 } 8638 8639 /* 8640 * Function: 8641 * _bcm_esw_svm_pkt_compressed_attr_maps_remove 8642 * Purpose: 8643 * Internal function to decrement reference count of required maps and 8644 * remove hardware table content if reference count becomes 0. 8645 * Parameters: 8646 * Unit - (IN) unit number 8647 * compressed_attr_selectors_v - (IN) compressed attribute selectors. 8648 * Returns: 8649 * BCM_E_XXX 8650 */ 8651 STATIC 8652 int _bcm_esw_svm_pkt_compressed_attr_maps_remove( 8653 int unit, 8654 compressed_attr_selectors_t *compressed_attr_selectors_v) 8655 { 8656 int rv = BCM_E_NONE; 8657 uint8 *map_ref_count = NULL; 8658 pkt_attr_bits_t *pkt_attr_bits_v = NULL; 8659 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 8660 8661 pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v; 8662 8663 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 8664 8665 if (cmprsd_attr_maps == NULL) { 8666 return BCM_E_NONE; 8667 } 8668 8669 if ((pkt_attr_bits_v->cng != 0) || 8670 (pkt_attr_bits_v->int_pri != 0) || 8671 (pkt_attr_bits_v->short_int_pri != 0)) { 8672 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map]; 8673 (*map_ref_count)--; 8674 if (*map_ref_count == 0) { 8675 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 8676 ING_SVM_PRI_CNG_MAPm, MEM_BLOCK_ALL, TRUE)); 8677 cmprsd_attr_maps->cng = 0; 8678 cmprsd_attr_maps->int_pri = 0; 8679 cmprsd_attr_maps->combine_cng_flags = 0; 8680 cmprsd_attr_maps->combine_int_pri_flags = 0; 8681 } 8682 } 8683 if ((pkt_attr_bits_v->vlan_format != 0) || 8684 (pkt_attr_bits_v->outer_dot1p != 0) || 8685 (pkt_attr_bits_v->inner_dot1p != 0)) { 8686 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map]; 8687 (*map_ref_count)--; 8688 if (*map_ref_count == 0) { 8689 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 8690 ING_SVM_PKT_PRI_MAPm, MEM_BLOCK_ALL, TRUE)); 8691 cmprsd_attr_maps->vlan_format = 0; 8692 cmprsd_attr_maps->outer_dot1p = 0; 8693 cmprsd_attr_maps->inner_dot1p = 0; 8694 cmprsd_attr_maps->combine_vlan_format_flags = 0; 8695 cmprsd_attr_maps->combine_outer_dot1p_flags = 0; 8696 cmprsd_attr_maps->combine_inner_dot1p_flags = 0; 8697 } 8698 } 8699 if (pkt_attr_bits_v->ing_port != 0) { 8700 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_port_map]; 8701 (*map_ref_count)--; 8702 if (*map_ref_count == 0) { 8703 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 8704 ING_SVM_PORT_MAPm, MEM_BLOCK_ALL, TRUE)); 8705 cmprsd_attr_maps->port = 0; 8706 sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrPort], 8707 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 8708 } 8709 } 8710 if ((pkt_attr_bits_v->tos != 0) || 8711 (pkt_attr_bits_v->tos_ecn != 0)) { 8712 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_tos_map]; 8713 (*map_ref_count)--; 8714 if (*map_ref_count == 0) { 8715 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 8716 ING_SVM_TOS_MAPm, MEM_BLOCK_ALL, TRUE)); 8717 cmprsd_attr_maps->tos_dscp = 0; 8718 cmprsd_attr_maps->tos_ecn = 0; 8719 sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosDscp], 8720 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 8721 sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosEcn], 8722 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 8723 } 8724 } 8725 if ((pkt_attr_bits_v->pkt_resolution != 0) || 8726 (pkt_attr_bits_v->svp_type != 0) || 8727 (pkt_attr_bits_v->drop != 0)) { 8728 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map]; 8729 (*map_ref_count)--; 8730 if (*map_ref_count == 0) { 8731 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 8732 ING_SVM_PKT_RES_MAPm, MEM_BLOCK_ALL, TRUE)); 8733 cmprsd_attr_maps->pkt_resolution = 0; 8734 cmprsd_attr_maps->svp_type = 0; 8735 cmprsd_attr_maps->drop = 0; 8736 cmprsd_attr_maps->combine_pkt_res_flags = 0; 8737 cmprsd_attr_maps->combine_drop_flags = 0; 8738 sal_memset(cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrSvpType], 8739 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 8740 } 8741 } 8742 8743 return rv; 8744 } 8745 8746 /* 8747 * Function: 8748 * _bcm_policer_svc_meter_unreserve_mode 8749 * Purpose: 8750 * Internal function to unreserve meter offset mode 8751 * Parameters: 8752 * Unit - (IN) unit number 8753 * svc_meter_mode - (IN) Meter offset mode 8754 * Returns: 8755 * BCM_E_XXX 8756 */ 8757 bcm_error_t _bcm_policer_svc_meter_unreserve_mode( 8758 uint32 unit, 8759 bcm_policer_svc_meter_mode_t svc_meter_mode) 8760 { 8761 uint64 pkt_attr_selector_key_value; 8762 bcm_policer_svc_meter_mode_type_t mode_type_v; 8763 compressed_attr_selectors_t *compressed_attr_selectors_v = NULL; 8764 8765 COMPILER_64_ZERO(pkt_attr_selector_key_value); 8766 if (!((svc_meter_mode >= 1) && (svc_meter_mode <= 3))) { 8767 LOG_DEBUG(BSL_LS_BCM_POLICER, 8768 (BSL_META_U(unit, 8769 "Wrong offset mode specified \n"))); 8770 return BCM_E_PARAM; 8771 } 8772 if ( global_meter_offset_mode[unit][svc_meter_mode].used == 0) { 8773 LOG_DEBUG(BSL_LS_BCM_POLICER, 8774 (BSL_META_U(unit, 8775 "Wrong offset mode: Mode is not in use\n"))); 8776 return BCM_E_NOT_FOUND; 8777 } 8778 if ( global_meter_offset_mode[unit][svc_meter_mode].reference_count != 0) { 8779 LOG_DEBUG(BSL_LS_BCM_POLICER, 8780 (BSL_META_U(unit, 8781 "Mode is still in use\n"))); 8782 return BCM_E_INTERNAL; 8783 } 8784 8785 /* Step1: Reset selector keys */ 8786 SOC_IF_ERROR_RETURN(soc_reg_set(unit, 8787 _pkt_attr_sel_key_reg[svc_meter_mode], 8788 REG_PORT_ANY, 8789 0, 8790 pkt_attr_selector_key_value)); 8791 8792 /* Step2: Reset Offset table filling */ 8793 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 8794 SVM_OFFSET_TABLEm, 8795 svc_meter_mode, 8796 NULL)); 8797 /* Step3: Cleanup based on mode */ 8798 mode_type_v = global_meter_offset_mode[unit][svc_meter_mode].\ 8799 meter_attr.mode_type_v; 8800 switch (mode_type_v) { 8801 case uncompressed_mode: 8802 break; 8803 case udf_mode: 8804 break; 8805 case cascade_mode: 8806 break; 8807 case compressed_mode: 8808 { 8809 compressed_attr_selectors_v = 8810 &global_meter_offset_mode[unit][svc_meter_mode].\ 8811 meter_attr.compressed_attr_selectors_v; 8812 BCM_IF_ERROR_RETURN(_bcm_esw_svm_pkt_compressed_attr_maps_remove( 8813 unit, compressed_attr_selectors_v)); 8814 break; 8815 } 8816 case udf_cascade_mode: 8817 case udf_cascade_with_coupling_mode: 8818 break; 8819 default: 8820 LOG_DEBUG(BSL_LS_BCM_POLICER, 8821 (BSL_META_U(unit, 8822 "Invalid offset mode\n"))); 8823 return BCM_E_PARAM; 8824 } 8825 /* attr_selectors is allocated memory when mode_id is created explicitly 8826 * via _mode_id_create() API. This is the best place to free this 8827 * memory as after this call mode is set to un-used and can be reused */ 8828 if (global_meter_offset_mode[unit][svc_meter_mode].attr_selectors != NULL) { 8829 sal_free (global_meter_offset_mode[unit][svc_meter_mode].attr_selectors); 8830 global_meter_offset_mode[unit][svc_meter_mode].attr_selectors = NULL; 8831 } 8832 sal_memset (&global_meter_offset_mode[unit][svc_meter_mode], 0, 8833 sizeof(global_meter_offset_mode[unit][svc_meter_mode])); 8834 8835 global_meter_offset_mode[unit][svc_meter_mode].used = 0; 8836 8837 return BCM_E_NONE; 8838 } 8839 8840 /* 8841 * Function: 8842 * _bcm_policer_svc_meter_get_available_mode 8843 * Purpose: 8844 * Internal function to get a free meter offset table entry 8845 * Parameters: 8846 * Unit - (IN) unit number 8847 * svc_meter_mode - (IN) Meter offset mode 8848 * Returns: 8849 * BCM_E_XXX 8850 */ 8851 bcm_error_t _bcm_policer_svc_meter_get_available_mode(uint32 unit, 8852 bcm_policer_svc_meter_mode_t *svc_meter_mode) 8853 { 8854 uint32 mode_index = 1; 8855 for (; mode_index < BCM_POLICER_SVC_METER_MAX_MODE; mode_index++) { 8856 if (global_meter_offset_mode[unit][mode_index].used == 0) { 8857 *svc_meter_mode = mode_index; 8858 return BCM_E_NONE; 8859 } 8860 } 8861 return BCM_E_FULL; 8862 } 8863 8864 typedef enum pkt_attrs_e { 8865 pkt_attr_ip_pkt, 8866 pkt_attr_drop, 8867 pkt_attr_svp_group, 8868 pkt_attr_pkt_resolution, 8869 pkt_attr_tos, 8870 pkt_attr_ing_port, 8871 pkt_attr_inner_dot1p, 8872 pkt_attr_outer_dot1p, 8873 pkt_attr_vlan_format, 8874 pkt_attr_int_pri, 8875 pkt_attr_cng, 8876 pkt_attr_short_int_pri, 8877 pkt_attr_tos_ecn, 8878 pkt_attr_count 8879 } pkt_attrs_t; 8880 8881 static _bcm_policer_pkt_attr_bit_pos_t kt_pkt_attr_bit_pos[pkt_attr_count] = { 8882 {0, 0}, {1, 1}, {2, 2}, {3, 8}, 8883 {11,16}, {17,22}, {23,25}, {26,28}, 8884 {29,30}, {31,34}, {35,36}, {31,33}, 8885 {9,10} 8886 }; 8887 #ifdef BCM_KATANA2_SUPPORT 8888 static _bcm_policer_pkt_attr_bit_pos_t kt2_pkt_attr_bit_pos[pkt_attr_count] = { 8889 {0, 0}, {1, 1}, {2, 4}, {5, 10}, 8890 {13,18}, {19, 26}, {27, 29}, {30,32}, 8891 {33,34}, {35,38}, {39, 40}, {35,37}, 8892 {11,12} 8893 }; 8894 static _bcm_policer_pkt_attr_bit_pos_t kt2_cmprsd_pkt_attr_bit_pos[pkt_attr_count] = { 8895 {0, 0}, {1, 1}, {2, 4}, {5, 8}, 8896 {11,16}, {17, 24}, {25, 27}, {28,30}, 8897 {31,32}, {33,36}, {37, 38}, {33,35}, 8898 {9,10} 8899 }; 8900 #endif 8901 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_SABER2_SUPPORT) 8902 static _bcm_policer_pkt_attr_bit_pos_t sb2_pkt_attr_bit_pos[pkt_attr_count] = { 8903 {0, 0}, {1, 1}, {2, 4}, {5, 10}, 8904 {13,18}, {19, 25}, {27, 29}, {30,32}, 8905 {33,34}, {35,38}, {39, 40}, {35,37}, 8906 {11,12} 8907 }; 8908 static _bcm_policer_pkt_attr_bit_pos_t sb2_cmprsd_pkt_attr_bit_pos[pkt_attr_count] = { 8909 {0, 0}, {1, 1}, {2, 4}, {5, 8}, 8910 {11,16}, {17, 23}, {24, 26}, {27,29}, 8911 {30,31}, {32,35}, {36, 37}, {32,34}, 8912 {9,10} 8913 }; 8914 #endif 8915 8916 /* 8917 * Function: 8918 * _bcm_policer_svc_meter_update_selector_keys 8919 * Purpose: 8920 * Update the selector keys 8921 * Parameters: 8922 * Unit - (IN) unit number 8923 * mode_type_v - (IN) Meter offset mode 8924 * pkt_attr_selector_key - (IN) Selector key 8925 * pkt_attr_bits_v - (IN) Packet attribute bits 8926 * Returns: 8927 * BCM_E_XXX 8928 */ 8929 bcm_error_t _bcm_policer_svc_meter_update_selector_keys( 8930 int unit, 8931 bcm_policer_svc_meter_mode_type_t mode_type_v, 8932 int8 type, 8933 soc_reg_t pkt_attr_selector_key, 8934 pkt_attr_bits_t pkt_attr_bits_v) 8935 { 8936 uint64 pkt_attr_selector_key_value; 8937 uint8 current_bit_position=0; 8938 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 8939 8940 pkt_attr_bit_pos = 8941 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos; 8942 8943 COMPILER_64_ZERO(pkt_attr_selector_key_value); 8944 if (!((pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) && 8945 (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r))) { 8946 LOG_DEBUG(BSL_LS_BCM_POLICER, 8947 (BSL_META_U(unit, 8948 "Invalid Key for packet attribute selector\n"))); 8949 return BCM_E_PARAM; 8950 } 8951 /* BCM_POLICER_SVC_METER_UDF_MODE not supported here */ 8952 if (!((mode_type_v == uncompressed_mode) || 8953 (mode_type_v == compressed_mode))) { 8954 LOG_DEBUG(BSL_LS_BCM_POLICER, 8955 (BSL_META_U(unit, 8956 "UDF mode not supported \n"))); 8957 return BCM_E_PARAM; 8958 } 8959 8960 /* 8961 * Set bit position and mask for packet attruibutes for 8962 * implicit mode Id and explicit mode Id for uncompressed case. 8963 */ 8964 if ((type == -1) || (mode_type_v == uncompressed_mode)) { 8965 pkt_attr_bits_v.ip_pkt_pos = 8966 pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit; 8967 pkt_attr_bits_v.ip_pkt_mask = 8968 (1 << pkt_attr_bits_v.ip_pkt) - 1; 8969 pkt_attr_bits_v.drop_pos = 8970 pkt_attr_bit_pos[pkt_attr_drop].start_bit; 8971 pkt_attr_bits_v.drop_mask = 8972 (1 << pkt_attr_bits_v.drop) - 1; 8973 pkt_attr_bits_v.svp_type_pos = 8974 pkt_attr_bit_pos[pkt_attr_svp_group].start_bit; 8975 pkt_attr_bits_v.svp_type_mask = 8976 (1 << pkt_attr_bits_v.svp_type) - 1; 8977 pkt_attr_bits_v.pkt_res_pos = 8978 pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit; 8979 pkt_attr_bits_v.pkt_res_mask = 8980 (1 << pkt_attr_bits_v.pkt_resolution) - 1; 8981 pkt_attr_bits_v.tos_ecn_pos = 8982 pkt_attr_bit_pos[pkt_attr_tos_ecn].start_bit; 8983 pkt_attr_bits_v.tos_ecn_mask = 8984 (1 << pkt_attr_bits_v.tos_ecn) - 1; 8985 pkt_attr_bits_v.tos_pos = 8986 pkt_attr_bit_pos[pkt_attr_tos].start_bit; 8987 pkt_attr_bits_v.tos_mask = 8988 (1 << pkt_attr_bits_v.tos) - 1; 8989 pkt_attr_bits_v.ing_port_pos = 8990 pkt_attr_bit_pos[pkt_attr_ing_port].start_bit; 8991 pkt_attr_bits_v.ing_port_mask = 8992 (1 << pkt_attr_bits_v.ing_port) - 1; 8993 pkt_attr_bits_v.inner_dot1p_pos = 8994 pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit; 8995 pkt_attr_bits_v.inner_dot1p_mask = 8996 (1 << pkt_attr_bits_v.inner_dot1p) - 1; 8997 pkt_attr_bits_v.outer_dot1p_pos = 8998 pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit; 8999 pkt_attr_bits_v.outer_dot1p_mask = 9000 (1 << pkt_attr_bits_v.outer_dot1p) - 1; 9001 pkt_attr_bits_v.vlan_format_pos = 9002 pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit; 9003 pkt_attr_bits_v.vlan_format_mask = 9004 (1 << pkt_attr_bits_v.vlan_format) - 1; 9005 if (mode_type_v == compressed_mode) { 9006 pkt_attr_bits_v.int_pri_pos = 9007 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos; 9008 } else { 9009 pkt_attr_bits_v.int_pri_pos = 9010 pkt_attr_bit_pos[pkt_attr_int_pri].start_bit; 9011 } 9012 pkt_attr_bits_v.int_pri_mask = 9013 (1 << pkt_attr_bits_v.int_pri) - 1; 9014 pkt_attr_bits_v.cng_pos = 9015 pkt_attr_bit_pos[pkt_attr_cng].start_bit; 9016 pkt_attr_bits_v.cng_mask = 9017 (1 << pkt_attr_bits_v.cng) - 1; 9018 pkt_attr_bits_v.short_int_pri_pos = 9019 pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit; 9020 pkt_attr_bits_v.short_int_pri_mask = 9021 (1 << pkt_attr_bits_v.short_int_pri) - 1; 9022 } 9023 9024 /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */ 9025 SOC_IF_ERROR_RETURN(soc_reg_get(unit, 9026 pkt_attr_selector_key, 9027 REG_PORT_ANY, 9028 0, 9029 &pkt_attr_selector_key_value)); 9030 9031 /* Next set field value for 9032 ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/ 9033 soc_reg64_field32_set( 9034 unit, 9035 pkt_attr_selector_key, 9036 &pkt_attr_selector_key_value, 9037 USER_SPECIFIED_UDF_VALIDf, 9038 0); 9039 soc_reg64_field32_set( 9040 unit, 9041 pkt_attr_selector_key, 9042 &pkt_attr_selector_key_value, 9043 USE_UDF_KEYf, 9044 0); 9045 if (mode_type_v == compressed_mode) { 9046 soc_reg64_field32_set( 9047 unit, 9048 pkt_attr_selector_key, 9049 &pkt_attr_selector_key_value, 9050 USE_COMPRESSED_PKT_KEYf, 9051 1); 9052 } else { 9053 soc_reg64_field32_set( 9054 unit, 9055 pkt_attr_selector_key, 9056 &pkt_attr_selector_key_value, 9057 USE_COMPRESSED_PKT_KEYf, 9058 0); 9059 } 9060 if (pkt_attr_bits_v.ip_pkt != 0) { 9061 BCM_IF_ERROR_RETURN( 9062 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9063 unit, 9064 pkt_attr_selector_key, 9065 &pkt_attr_selector_key_value, 9066 pkt_attr_bits_v.ip_pkt_pos, 9067 pkt_attr_bits_v.ip_pkt, 9068 pkt_attr_bits_v.ip_pkt_mask, 9069 ¤t_bit_position)); 9070 } 9071 if (pkt_attr_bits_v.drop != 0) { 9072 BCM_IF_ERROR_RETURN( 9073 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9074 unit, 9075 pkt_attr_selector_key, 9076 &pkt_attr_selector_key_value, 9077 pkt_attr_bits_v.drop_pos, 9078 pkt_attr_bits_v.drop, 9079 pkt_attr_bits_v.drop_mask, 9080 ¤t_bit_position)); 9081 } 9082 if (pkt_attr_bits_v.svp_type != 0) { 9083 BCM_IF_ERROR_RETURN( 9084 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9085 unit, 9086 pkt_attr_selector_key, 9087 &pkt_attr_selector_key_value, 9088 pkt_attr_bits_v.svp_type_pos, 9089 pkt_attr_bits_v.svp_type, 9090 pkt_attr_bits_v.svp_type_mask, 9091 ¤t_bit_position)); 9092 } 9093 if (pkt_attr_bits_v.pkt_resolution != 0) { 9094 BCM_IF_ERROR_RETURN( 9095 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9096 unit, 9097 pkt_attr_selector_key, 9098 &pkt_attr_selector_key_value, 9099 pkt_attr_bits_v.pkt_res_pos, 9100 pkt_attr_bits_v.pkt_resolution, 9101 pkt_attr_bits_v.pkt_res_mask, 9102 ¤t_bit_position)); 9103 } 9104 if (pkt_attr_bits_v.tos_ecn != 0) { 9105 BCM_IF_ERROR_RETURN( 9106 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9107 unit, 9108 pkt_attr_selector_key, 9109 &pkt_attr_selector_key_value, 9110 pkt_attr_bits_v.tos_ecn_pos, 9111 pkt_attr_bits_v.tos_ecn, 9112 pkt_attr_bits_v.tos_ecn_mask, 9113 ¤t_bit_position)); 9114 } 9115 if (pkt_attr_bits_v.tos != 0) { 9116 BCM_IF_ERROR_RETURN( 9117 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9118 unit, 9119 pkt_attr_selector_key, 9120 &pkt_attr_selector_key_value, 9121 pkt_attr_bits_v.tos_pos, 9122 pkt_attr_bits_v.tos, 9123 pkt_attr_bits_v.tos_mask, 9124 ¤t_bit_position)); 9125 } 9126 if (pkt_attr_bits_v.ing_port != 0) { 9127 BCM_IF_ERROR_RETURN( 9128 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9129 unit, 9130 pkt_attr_selector_key, 9131 &pkt_attr_selector_key_value, 9132 pkt_attr_bits_v.ing_port_pos, 9133 pkt_attr_bits_v.ing_port, 9134 pkt_attr_bits_v.ing_port_mask, 9135 ¤t_bit_position)); 9136 } 9137 if (pkt_attr_bits_v.inner_dot1p != 0) { 9138 BCM_IF_ERROR_RETURN( 9139 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9140 unit, 9141 pkt_attr_selector_key, 9142 &pkt_attr_selector_key_value, 9143 pkt_attr_bits_v.inner_dot1p_pos, 9144 pkt_attr_bits_v.inner_dot1p, 9145 pkt_attr_bits_v.inner_dot1p_mask, 9146 ¤t_bit_position)); 9147 } 9148 if (pkt_attr_bits_v.outer_dot1p != 0) { 9149 BCM_IF_ERROR_RETURN( 9150 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9151 unit, 9152 pkt_attr_selector_key, 9153 &pkt_attr_selector_key_value, 9154 pkt_attr_bits_v.outer_dot1p_pos, 9155 pkt_attr_bits_v.outer_dot1p, 9156 pkt_attr_bits_v.outer_dot1p_mask, 9157 ¤t_bit_position)); 9158 } 9159 if (pkt_attr_bits_v.vlan_format != 0) { 9160 BCM_IF_ERROR_RETURN( 9161 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9162 unit, 9163 pkt_attr_selector_key, 9164 &pkt_attr_selector_key_value, 9165 pkt_attr_bits_v.vlan_format_pos, 9166 pkt_attr_bits_v.vlan_format, 9167 pkt_attr_bits_v.vlan_format_mask, 9168 ¤t_bit_position)); 9169 } 9170 if (pkt_attr_bits_v.int_pri != 0) { 9171 BCM_IF_ERROR_RETURN( 9172 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9173 unit, 9174 pkt_attr_selector_key, 9175 &pkt_attr_selector_key_value, 9176 pkt_attr_bits_v.int_pri_pos, 9177 pkt_attr_bits_v.int_pri, 9178 pkt_attr_bits_v.int_pri_mask, 9179 ¤t_bit_position)); 9180 } 9181 if (pkt_attr_bits_v.cng != 0) { 9182 BCM_IF_ERROR_RETURN( 9183 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9184 unit, 9185 pkt_attr_selector_key, 9186 &pkt_attr_selector_key_value, 9187 pkt_attr_bits_v.cng_pos, 9188 pkt_attr_bits_v.cng, 9189 pkt_attr_bits_v.cng_mask, 9190 ¤t_bit_position)); 9191 } 9192 if (pkt_attr_bits_v.short_int_pri != 0) { 9193 BCM_IF_ERROR_RETURN( 9194 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9195 unit, 9196 pkt_attr_selector_key, 9197 &pkt_attr_selector_key_value, 9198 pkt_attr_bits_v.short_int_pri_pos, 9199 pkt_attr_bits_v.short_int_pri, 9200 pkt_attr_bits_v.short_int_pri_mask, 9201 ¤t_bit_position)); 9202 } 9203 9204 /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */ 9205 SOC_IF_ERROR_RETURN(soc_reg_set(unit, 9206 pkt_attr_selector_key, 9207 REG_PORT_ANY, 9208 0, 9209 pkt_attr_selector_key_value)); 9210 return BCM_E_NONE; 9211 } 9212 9213 /* 9214 * Function: 9215 * _bcm_policer_svm_pkt_compressed_map_bits_get 9216 * Purpose: 9217 * This internal function is used to get the number of 9218 * bits that can be output from the compression table. 9219 * Parameters: 9220 * unit - (IN) unit number 9221 * pkt_attr - (IN) packet attribute 9222 * Returns: 9223 * Number of bits in compressed mode 9224 */ 9225 9226 STATIC 9227 int _bcm_policer_svm_pkt_compressed_map_bits_get( 9228 int unit, 9229 pkt_cmprsd_attrs_map_t attr_map) 9230 { 9231 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 9232 9233 pkt_attr_bit_pos = 9234 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos; 9235 9236 return (pkt_attr_bit_pos[attr_map].end_bit - 9237 pkt_attr_bit_pos[attr_map].start_bit + 1); 9238 } 9239 9240 9241 /* 9242 * Function: 9243 * _bcm_policer_svc_meter_update_selector_keys2 9244 * Purpose: 9245 * Update the selector keys for compressed mode 9246 * taking H/w map format in account 9247 * Parameters: 9248 * Unit - (IN) unit number 9249 * mode_type_v - (IN) Meter offset mode 9250 * pkt_attr_selector_key - (IN) Selector key 9251 * pkt_attr_bits_v - (IN) Packet attribute bits 9252 * Returns: 9253 * BCM_E_XXX 9254 */ 9255 bcm_error_t _bcm_policer_svc_meter_update_selector_keys2( 9256 int unit, 9257 bcm_policer_svc_meter_mode_type_t mode_type_v, 9258 soc_reg_t pkt_attr_selector_key, 9259 pkt_attr_bits_t pkt_attr_bits_v) 9260 { 9261 uint64 pkt_attr_selector_key_value; 9262 uint8 current_bit_position=0; 9263 uint8 mask = 0; 9264 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_map_bit_pos = NULL; 9265 uint32 total_bits_to_set = 0; 9266 9267 pkt_attr_map_bit_pos = 9268 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos; 9269 9270 COMPILER_64_ZERO(pkt_attr_selector_key_value); 9271 if (!((pkt_attr_selector_key >= ING_SVM_PKT_ATTR_SELECTOR_KEY_0r) && 9272 (pkt_attr_selector_key <= ING_SVM_PKT_ATTR_SELECTOR_KEY_3r))) { 9273 LOG_DEBUG(BSL_LS_BCM_POLICER, 9274 (BSL_META_U(unit, 9275 "Invalid Key for packet attribute selector\n"))); 9276 return BCM_E_PARAM; 9277 } 9278 /* BCM_POLICER_SVC_METER_UDF_MODE not supported here */ 9279 if (!(mode_type_v == compressed_mode)) { 9280 return BCM_E_PARAM; 9281 } 9282 /* First Get complete value of ING_SVM_PKT_ATTR_SELECTOR_KEY_?r value */ 9283 SOC_IF_ERROR_RETURN(soc_reg_get(unit, 9284 pkt_attr_selector_key, 9285 REG_PORT_ANY, 9286 0, 9287 &pkt_attr_selector_key_value)); 9288 9289 /* Next set field value for 9290 ING_SVM_PKT_ATTR_SELECTOR_KEY_?r:SELECTOR_KEY field*/ 9291 soc_reg64_field32_set( 9292 unit, 9293 pkt_attr_selector_key, 9294 &pkt_attr_selector_key_value, 9295 USER_SPECIFIED_UDF_VALIDf, 9296 0); 9297 soc_reg64_field32_set( 9298 unit, 9299 pkt_attr_selector_key, 9300 &pkt_attr_selector_key_value, 9301 USE_UDF_KEYf, 9302 0); 9303 soc_reg64_field32_set( 9304 unit, 9305 pkt_attr_selector_key, 9306 &pkt_attr_selector_key_value, 9307 USE_COMPRESSED_PKT_KEYf, 9308 1); 9309 9310 if (pkt_attr_bits_v.ip_pkt != 0) { 9311 BCM_IF_ERROR_RETURN( 9312 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9313 unit, 9314 pkt_attr_selector_key, 9315 &pkt_attr_selector_key_value, 9316 pkt_attr_map_bit_pos[pkt_attr_ip_pkt_map].start_bit, 9317 pkt_attr_bits_v.ip_pkt, 9318 1, 9319 ¤t_bit_position)); 9320 } 9321 if ((pkt_attr_bits_v.drop != 0) || 9322 (pkt_attr_bits_v.svp_type != 0) || 9323 (pkt_attr_bits_v.pkt_resolution != 0)) { 9324 total_bits_to_set = pkt_attr_bits_v.drop + 9325 pkt_attr_bits_v.svp_type + 9326 pkt_attr_bits_v.pkt_resolution; 9327 mask = (1 << total_bits_to_set) - 1; 9328 BCM_IF_ERROR_RETURN( 9329 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9330 unit, 9331 pkt_attr_selector_key, 9332 &pkt_attr_selector_key_value, 9333 pkt_attr_map_bit_pos[pkt_attr_pkt_res_map].start_bit, 9334 total_bits_to_set, 9335 mask, 9336 ¤t_bit_position)); 9337 } 9338 if ((pkt_attr_bits_v.tos != 0) || 9339 (pkt_attr_bits_v.tos_ecn != 0)) { 9340 total_bits_to_set = pkt_attr_bits_v.tos + 9341 pkt_attr_bits_v.tos_ecn; 9342 mask = (1 << total_bits_to_set) - 1; 9343 BCM_IF_ERROR_RETURN( 9344 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9345 unit, 9346 pkt_attr_selector_key, 9347 &pkt_attr_selector_key_value, 9348 pkt_attr_map_bit_pos[pkt_attr_tos_map].start_bit, 9349 total_bits_to_set, 9350 mask, 9351 ¤t_bit_position)); 9352 } 9353 if (pkt_attr_bits_v.ing_port != 0) { 9354 mask = (1 << pkt_attr_bits_v.ing_port) - 1; 9355 BCM_IF_ERROR_RETURN( 9356 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9357 unit, 9358 pkt_attr_selector_key, 9359 &pkt_attr_selector_key_value, 9360 pkt_attr_map_bit_pos[pkt_attr_port_map].start_bit, 9361 pkt_attr_bits_v.ing_port, 9362 mask, 9363 ¤t_bit_position)); 9364 } 9365 if ((pkt_attr_bits_v.inner_dot1p != 0) || 9366 (pkt_attr_bits_v.outer_dot1p != 0) || 9367 (pkt_attr_bits_v.vlan_format != 0)) { 9368 total_bits_to_set = pkt_attr_bits_v.inner_dot1p + 9369 pkt_attr_bits_v.outer_dot1p + 9370 pkt_attr_bits_v.vlan_format; 9371 mask = (1 << total_bits_to_set) - 1; 9372 BCM_IF_ERROR_RETURN( 9373 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9374 unit, 9375 pkt_attr_selector_key, 9376 &pkt_attr_selector_key_value, 9377 pkt_attr_map_bit_pos[pkt_attr_pkt_pri_map].start_bit, 9378 total_bits_to_set, 9379 mask, 9380 ¤t_bit_position)); 9381 } 9382 if ((pkt_attr_bits_v.int_pri != 0) || 9383 (pkt_attr_bits_v.cng != 0)) { 9384 total_bits_to_set = pkt_attr_bits_v.int_pri + pkt_attr_bits_v.cng; 9385 mask = (1 << total_bits_to_set) - 1; 9386 9387 BCM_IF_ERROR_RETURN( 9388 _bcm_policer_svc_meter_update_selector_keys_enable_fields( 9389 unit, 9390 pkt_attr_selector_key, 9391 &pkt_attr_selector_key_value, 9392 pkt_attr_map_bit_pos[pkt_attr_pri_cng_map].start_bit, 9393 total_bits_to_set, 9394 mask, 9395 ¤t_bit_position)); 9396 } 9397 9398 /* Finally set value for ING_SVM_PKT_ATTR_SELECTOR_KEY_?r */ 9399 SOC_IF_ERROR_RETURN(soc_reg_set(unit, 9400 pkt_attr_selector_key, 9401 REG_PORT_ANY, 9402 0, 9403 pkt_attr_selector_key_value)); 9404 return BCM_E_NONE; 9405 } 9406 9407 /* 9408 * Function: 9409 * _bcm_policer_svc_meter_create_cascade_mode 9410 * Purpose: 9411 * Function to create an offset mode with uncompressed packet attributes 9412 * Parameters: 9413 * Unit - (IN) unit number 9414 * uncompressed_attr_selectors_v - (IN) Packet attribute selectors 9415 * group_mode - (IN) Policer group mode 9416 * num_pol - (IN) Number of policers 9417 * svc_meter_mode - (OUT) Allocated meter offset mode 9418 * total_bits - (OUT) Total number of packet attribute bits 9419 * Returns: 9420 * BCM_E_XXX 9421 */ 9422 bcm_error_t _bcm_policer_svc_meter_create_cascade_mode( 9423 int unit, 9424 uncompressed_attr_selectors_t *uncompressed_attr_selectors_v, 9425 bcm_policer_group_mode_t group_mode, 9426 int8 type, 9427 int num_pol, 9428 bcm_policer_svc_meter_mode_t *svc_meter_mode) 9429 { 9430 bcm_error_t bcm_error_v = BCM_E_NONE; 9431 bcm_policer_svc_meter_mode_t bcm_policer_svc_meter_mode = 0; 9432 pkt_attr_bits_t pkt_attr_bits_v = {0}; 9433 uint32 total_bits_used = 0; 9434 uint32 index = 0; 9435 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 9436 uncompressed_attr_selectors_t *un_attr; 9437 int port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE; 9438 int svp_type_attr_size = 0; 9439 9440 /*check if a mode is already configured with these attributes */ 9441 for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 9442 if (_bcm_policer_svc_meter_get_mode_info(unit,index,&mode_info) 9443 == BCM_E_NONE) { 9444 if ((mode_info.meter_attr.mode_type_v != cascade_mode) || 9445 (group_mode != mode_info.group_mode )) { 9446 continue; 9447 } 9448 if (mode_info.no_of_policers != num_pol) { 9449 continue; 9450 } 9451 un_attr = &mode_info.meter_attr.uncompressed_attr_selectors_v; 9452 if (un_attr->uncompressed_attr_bits_selector == 9453 uncompressed_attr_selectors_v->uncompressed_attr_bits_selector) { 9454 *svc_meter_mode = index; 9455 return BCM_E_EXISTS; 9456 } 9457 } 9458 } 9459 9460 bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit, 9461 &bcm_policer_svc_meter_mode); 9462 if (bcm_error_v != BCM_E_NONE) { 9463 LOG_WARN(BSL_LS_BCM_POLICER, 9464 (BSL_META_U(unit, " Offset Table is full\n"))); 9465 return bcm_error_v; 9466 } 9467 9468 /* Step1: Packet Attribute selection */ 9469 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9470 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS) { 9471 pkt_attr_bits_v.cng = BCM_POLICER_SVC_METER_CNG_ATTR_SIZE; 9472 total_bits_used += BCM_POLICER_SVC_METER_CNG_ATTR_SIZE; 9473 } 9474 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9475 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS) { 9476 pkt_attr_bits_v.int_pri = BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE ; 9477 total_bits_used += BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE; 9478 } 9479 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9480 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS) { 9481 pkt_attr_bits_v.short_int_pri = BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE; 9482 total_bits_used += BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE; 9483 } 9484 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9485 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS) { 9486 pkt_attr_bits_v.vlan_format = 9487 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE; 9488 total_bits_used += BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE; 9489 } 9490 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9491 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS) { 9492 pkt_attr_bits_v.outer_dot1p = 9493 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE ; 9494 total_bits_used += BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE; 9495 } 9496 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9497 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS) { 9498 pkt_attr_bits_v.inner_dot1p = 9499 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE; 9500 total_bits_used += BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE; 9501 } 9502 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9503 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS) { 9504 port_attr_size = 9505 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size; 9506 pkt_attr_bits_v.ing_port = port_attr_size; 9507 total_bits_used += port_attr_size; 9508 } 9509 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9510 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS) { 9511 pkt_attr_bits_v.tos = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 9512 total_bits_used += BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 9513 } 9514 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9515 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS) { 9516 pkt_attr_bits_v.pkt_resolution = 9517 BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE; 9518 total_bits_used += BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE; 9519 } 9520 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9521 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS) { 9522 svp_type_attr_size = 9523 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size; 9524 total_bits_used += svp_type_attr_size; 9525 pkt_attr_bits_v.svp_type = svp_type_attr_size; 9526 } 9527 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9528 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS) { 9529 pkt_attr_bits_v.drop = BCM_POLICER_SVC_METER_DROP_ATTR_SIZE; 9530 total_bits_used += BCM_POLICER_SVC_METER_DROP_ATTR_SIZE; 9531 } 9532 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9533 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS) { 9534 pkt_attr_bits_v.ip_pkt = BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE; 9535 total_bits_used += BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE; 9536 } 9537 if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 9538 LOG_DEBUG(BSL_LS_BCM_POLICER, 9539 (BSL_META_U(unit, 9540 "Key size exceeds max allowed size \n"))); 9541 return BCM_E_PARAM; 9542 } 9543 /* Step2: Packet Attribute filling */ 9544 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit, 9545 uncompressed_mode, type, 9546 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode], 9547 pkt_attr_bits_v)); 9548 9549 /* Step3: Offset table filling */ 9550 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 9551 SVM_OFFSET_TABLEm, 9552 bcm_policer_svc_meter_mode, 9553 &uncompressed_attr_selectors_v->offset_map[0])); 9554 9555 /* Step4: Final: reserve mode and return */ 9556 *svc_meter_mode = bcm_policer_svc_meter_mode; 9557 return BCM_E_NONE; 9558 } 9559 /* 9560 * Function: 9561 * _bcm_policer_svc_meter_create_uncompress_mode 9562 * Purpose: 9563 * Function to create an offset mode with uncompressed packet attributes 9564 * Parameters: 9565 * Unit - (IN) unit number 9566 * uncompressed_attr_selectors_v - (IN) Packet attribute selectors 9567 * group_mode - (IN) Policer group mode 9568 * svc_meter_mode - (OUT) Allocated meter offset mode 9569 * total_bits - (OUT) Total number of packet attribute bits 9570 * Returns: 9571 * BCM_E_XXX 9572 */ 9573 bcm_error_t _bcm_policer_svc_meter_create_uncompress_mode( 9574 int unit, 9575 uncompressed_attr_selectors_t *uncompressed_attr_selectors_v, 9576 bcm_policer_group_mode_t group_mode, 9577 int8 type, 9578 bcm_policer_svc_meter_mode_t *svc_meter_mode) 9579 { 9580 bcm_error_t bcm_error_v = BCM_E_NONE; 9581 bcm_policer_svc_meter_mode_t bcm_policer_svc_meter_mode = 0; 9582 pkt_attr_bits_t pkt_attr_bits_v = {0}; 9583 uint32 total_bits_used = 0; 9584 uint32 index = 0; 9585 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 9586 uncompressed_attr_selectors_t *un_attr; 9587 int port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE; 9588 int svp_type_attr_size = 0; 9589 9590 /*check if a mode is already configured with these attributes */ 9591 for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 9592 if (_bcm_policer_svc_meter_get_mode_info(unit,index,&mode_info) 9593 == BCM_E_NONE) { 9594 if ((mode_info.meter_attr.mode_type_v != uncompressed_mode) || 9595 (group_mode != mode_info.group_mode )) { 9596 continue; 9597 } 9598 un_attr = &mode_info.meter_attr.uncompressed_attr_selectors_v; 9599 if (un_attr->uncompressed_attr_bits_selector == 9600 uncompressed_attr_selectors_v->uncompressed_attr_bits_selector) { 9601 *svc_meter_mode = index; 9602 return BCM_E_EXISTS; 9603 } 9604 } 9605 } 9606 9607 bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit, 9608 &bcm_policer_svc_meter_mode); 9609 if (bcm_error_v != BCM_E_NONE) { 9610 LOG_WARN(BSL_LS_BCM_POLICER, 9611 (BSL_META_U(unit, 9612 " Offset Table is full\n"))); 9613 return bcm_error_v; 9614 } 9615 9616 /* Step1: Packet Attribute selection */ 9617 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9618 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS) { 9619 pkt_attr_bits_v.cng = BCM_POLICER_SVC_METER_CNG_ATTR_SIZE; 9620 total_bits_used += BCM_POLICER_SVC_METER_CNG_ATTR_SIZE; 9621 } 9622 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9623 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS) { 9624 pkt_attr_bits_v.int_pri = BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE ; 9625 total_bits_used += BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE; 9626 } 9627 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9628 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS) { 9629 pkt_attr_bits_v.short_int_pri = BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE ; 9630 total_bits_used += BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE; 9631 } 9632 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9633 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS) { 9634 pkt_attr_bits_v.vlan_format = 9635 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE; 9636 total_bits_used += BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE; 9637 } 9638 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9639 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS) { 9640 pkt_attr_bits_v.outer_dot1p = 9641 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE ; 9642 total_bits_used += BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE; 9643 } 9644 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9645 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS) { 9646 pkt_attr_bits_v.inner_dot1p = 9647 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE; 9648 total_bits_used += BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE; 9649 } 9650 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9651 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS) { 9652 port_attr_size = 9653 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size; 9654 pkt_attr_bits_v.ing_port = port_attr_size; 9655 total_bits_used += port_attr_size; 9656 } 9657 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9658 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS) { 9659 pkt_attr_bits_v.tos = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 9660 total_bits_used += BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 9661 } 9662 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9663 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS) { 9664 pkt_attr_bits_v.tos_ecn = BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE; 9665 total_bits_used += BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE; 9666 } 9667 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9668 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS) { 9669 pkt_attr_bits_v.pkt_resolution = 9670 BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE; 9671 total_bits_used += BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE; 9672 } 9673 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9674 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS) { 9675 svp_type_attr_size = 9676 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size; 9677 total_bits_used += svp_type_attr_size; 9678 pkt_attr_bits_v.svp_type = svp_type_attr_size; 9679 } 9680 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9681 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS) { 9682 pkt_attr_bits_v.drop = BCM_POLICER_SVC_METER_DROP_ATTR_SIZE; 9683 total_bits_used += BCM_POLICER_SVC_METER_DROP_ATTR_SIZE; 9684 } 9685 if (uncompressed_attr_selectors_v->uncompressed_attr_bits_selector & 9686 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS) { 9687 pkt_attr_bits_v.ip_pkt = BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE; 9688 total_bits_used += BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE; 9689 } 9690 if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 9691 LOG_DEBUG(BSL_LS_BCM_POLICER, 9692 (BSL_META_U(unit, 9693 "Key size exceeds max allowed size \n"))); 9694 return BCM_E_PARAM; 9695 } 9696 /* Step2: Packet Attribute filling */ 9697 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit, 9698 uncompressed_mode, type, 9699 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode], 9700 pkt_attr_bits_v)); 9701 9702 /* Step3: Offset table filling */ 9703 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 9704 SVM_OFFSET_TABLEm, 9705 bcm_policer_svc_meter_mode, 9706 &uncompressed_attr_selectors_v->offset_map[0])); 9707 9708 /* Step4: Final: reserve mode and return */ 9709 *svc_meter_mode = bcm_policer_svc_meter_mode; 9710 return BCM_E_NONE; 9711 } 9712 9713 9714 /* 9715 * Function: 9716 * _bcm_esw_svm_compressed_map_hw_write 9717 * Purpose: 9718 * Write to compression table. 9719 * 9720 * Parameters: 9721 * Unit - (IN) unit number 9722 * mem - (IN) memory 9723 * index - (IN) Entry index in memory 9724 * entry - (IN/OUT) entry buffer at mem index 9725 * user_data - (IN) user data 9726 * dirty - (OUT) dirty 9727 * Returns: 9728 * BCM_E_XXX 9729 */ 9730 STATIC 9731 int _bcm_esw_svm_compressed_map_hw_write(int unit, 9732 soc_mem_t mem, uint32 index, 9733 void *entry, void *user_data, uint32 *dirty) 9734 { 9735 uint8 map_entry = 0; 9736 soc_field_t field = INVALIDf; 9737 9738 map_entry = ((uint8 *) user_data)[index]; 9739 9740 switch(mem) { 9741 case ING_SVM_PRI_CNG_MAPm: 9742 field = PRI_CNG_FNf; 9743 break; 9744 case ING_SVM_PKT_PRI_MAPm: 9745 field = PKT_PRI_FNf; 9746 break; 9747 case ING_SVM_PORT_MAPm: 9748 field = PORT_FNf; 9749 break; 9750 case ING_SVM_TOS_MAPm: 9751 field = TOS_FNf; 9752 break; 9753 case ING_SVM_PKT_RES_MAPm: 9754 field = PKT_RES_FNf; 9755 break; 9756 default: 9757 break; 9758 } 9759 9760 if (field != INVALIDf) { 9761 soc_mem_field32_set(unit, mem, entry, field, map_entry); 9762 *dirty = 1; 9763 } 9764 9765 return BCM_E_NONE; 9766 } 9767 9768 /* 9769 * Function: 9770 * _bcm_esw_svm_pkt_compressed_attr_maps_add 9771 * Purpose: 9772 * Internal function to increment reference count of required maps and 9773 * and write to hardware tables if reference count becomes 1. 9774 * 9775 * Parameters: 9776 * Unit - (IN) unit number 9777 * compressed_attr_selectors_v - (IN) compressed attribute selectors. 9778 * Returns: 9779 * BCM_E_XXX 9780 */ 9781 STATIC 9782 int _bcm_esw_svm_pkt_compressed_attr_maps_add( 9783 int unit, 9784 compressed_attr_selectors_t *compressed_attr_selectors_v) 9785 { 9786 uint8 index = 0; 9787 uint8 *map_ref_count = NULL; 9788 uint8 ref_counts[pkt_attr_map_count] = {0}; 9789 uint8 cmprsd_maps_to_write[pkt_attr_map_count] = {0}; 9790 pkt_attr_bits_t *pkt_attr_bits_v = NULL; 9791 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 9792 9793 pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v; 9794 9795 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 9796 9797 /* Get reference counts of compression tables. */ 9798 if ((pkt_attr_bits_v->cng != 0) || 9799 (pkt_attr_bits_v->int_pri != 0)) { 9800 cmprsd_maps_to_write[pkt_attr_pri_cng_map] = 1; 9801 ref_counts[pkt_attr_pri_cng_map] = 9802 cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map]; 9803 } 9804 if ((pkt_attr_bits_v->vlan_format != 0) || 9805 (pkt_attr_bits_v->outer_dot1p != 0) || 9806 (pkt_attr_bits_v->inner_dot1p != 0)) { 9807 cmprsd_maps_to_write[pkt_attr_pkt_pri_map] = 1; 9808 ref_counts[pkt_attr_pkt_pri_map] = 9809 cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map]; 9810 } 9811 if (pkt_attr_bits_v->ing_port != 0) { 9812 cmprsd_maps_to_write[pkt_attr_port_map] = 1; 9813 ref_counts[pkt_attr_port_map] = 9814 cmprsd_attr_maps->ref_counts[pkt_attr_port_map]; 9815 } 9816 if ((pkt_attr_bits_v->tos != 0) || 9817 (pkt_attr_bits_v->tos_ecn != 0)) { 9818 cmprsd_maps_to_write[pkt_attr_tos_map] = 1; 9819 ref_counts[pkt_attr_tos_map] = 9820 cmprsd_attr_maps->ref_counts[pkt_attr_tos_map]; 9821 } 9822 if ((pkt_attr_bits_v->pkt_resolution != 0) || 9823 (pkt_attr_bits_v->svp_type != 0) || 9824 (pkt_attr_bits_v->drop != 0)) { 9825 cmprsd_maps_to_write[pkt_attr_pkt_res_map] = 1; 9826 ref_counts[pkt_attr_pkt_res_map] = 9827 cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map]; 9828 } 9829 9830 /* 9831 * If sharing is not allowed, fail when reference count is non-zero 9832 * and user is trying to write to that compression table. 9833 */ 9834 if (!soc_feature(unit, soc_feature_global_meter_compression_share)) { 9835 for (index = pkt_attr_pri_cng_map; 9836 index < pkt_attr_ip_pkt_map; index++) { 9837 if ((cmprsd_maps_to_write[index] == 1) && 9838 (ref_counts[index] != 0)) { 9839 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Compression" 9840 " tables in use and cannot be modified\n"))); 9841 return BCM_E_PARAM; 9842 } 9843 } 9844 } 9845 9846 /* Update compression tables and ref counts */ 9847 if (cmprsd_maps_to_write[pkt_attr_pri_cng_map] != 0) { 9848 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map]; 9849 if (*map_ref_count == 0) { 9850 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 9851 ING_SVM_PRI_CNG_MAPm, -1, -1, 9852 _bcm_esw_svm_compressed_map_hw_write, 9853 (void *) compressed_attr_selectors_v-> 9854 compressed_pri_cnf_attr_map_v)); 9855 cmprsd_attr_maps->cng = 1; 9856 cmprsd_attr_maps->int_pri = 1; 9857 } 9858 (*map_ref_count)++; 9859 } 9860 if (cmprsd_maps_to_write[pkt_attr_pkt_pri_map] != 0) { 9861 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map]; 9862 if (*map_ref_count == 0) { 9863 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 9864 ING_SVM_PKT_PRI_MAPm, -1, -1, 9865 _bcm_esw_svm_compressed_map_hw_write, 9866 (void *) compressed_attr_selectors_v-> 9867 compressed_pkt_pri_attr_map_v)); 9868 cmprsd_attr_maps->vlan_format = 1; 9869 cmprsd_attr_maps->outer_dot1p = 1; 9870 cmprsd_attr_maps->inner_dot1p = 1; 9871 } 9872 (*map_ref_count)++; 9873 } 9874 if (cmprsd_maps_to_write[pkt_attr_port_map] != 0) { 9875 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_port_map]; 9876 if (*map_ref_count == 0) { 9877 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 9878 ING_SVM_PORT_MAPm, -1, -1, 9879 _bcm_esw_svm_compressed_map_hw_write, 9880 (void *) compressed_attr_selectors_v-> 9881 compressed_port_attr_map_v)); 9882 cmprsd_attr_maps->port = 1; 9883 } 9884 (*map_ref_count)++; 9885 } 9886 if (cmprsd_maps_to_write[pkt_attr_tos_map] != 0) { 9887 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_tos_map]; 9888 if (*map_ref_count == 0) { 9889 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 9890 ING_SVM_TOS_MAPm, -1, -1, 9891 _bcm_esw_svm_compressed_map_hw_write, 9892 (void *) compressed_attr_selectors_v-> 9893 compressed_tos_attr_map_v)); 9894 cmprsd_attr_maps->tos_dscp = 1; 9895 cmprsd_attr_maps->tos_ecn = 1; 9896 } 9897 (*map_ref_count)++; 9898 } 9899 if (cmprsd_maps_to_write[pkt_attr_pkt_res_map] != 0) { 9900 map_ref_count = &cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map]; 9901 if (*map_ref_count == 0) { 9902 BCM_IF_ERROR_RETURN(_bcm_esw_svm_source_traverse(unit, 9903 ING_SVM_PKT_RES_MAPm, -1, -1, 9904 _bcm_esw_svm_compressed_map_hw_write, 9905 (void *) compressed_attr_selectors_v-> 9906 compressed_pkt_res_attr_map_v)); 9907 cmprsd_attr_maps->pkt_resolution = 1; 9908 cmprsd_attr_maps->svp_type = 1; 9909 cmprsd_attr_maps->drop = 1; 9910 } 9911 (*map_ref_count)++; 9912 } 9913 return BCM_E_NONE; 9914 } 9915 9916 /* 9917 * Function: 9918 * _bcm_esw_svc_meter_compressed_modes_match_for_share 9919 * Purpose: 9920 * Internal function to match existing mode ids with new input selectors 9921 * for compressed mode when compression table sharing is enabled. 9922 * 9923 * Parameters: 9924 * Unit - (IN) unit number 9925 * compressed_attr_selectors_v - (IN) compressed attribute selectors. 9926 * group_mode - (IN) New Policer Group Mode 9927 * type - (IN) New policer Group Type 9928 * pkt_attr_selectors - (IN) New input attr selectors 9929 * svc_meter_mode - (OUT) svc meter offset mode 9930 * Returns: 9931 * BCM_E_EXISTS - If a match is found 9932 * BCM_E_XXX 9933 */ 9934 STATIC 9935 int _bcm_esw_svc_meter_compressed_modes_match_for_share(int unit, 9936 compressed_attr_selectors_t *compressed_attr_selectors_v, 9937 bcm_policer_group_mode_t group_mode, 9938 int8 type, 9939 bcm_policer_attr_selectors_t *pkt_attr_selectors, 9940 bcm_policer_svc_meter_mode_t *svc_meter_mode) 9941 { 9942 bcm_error_t bcm_error_v=BCM_E_NONE; 9943 uint8 is_equal = FALSE; 9944 uint32 pol = 0; 9945 uint32 index = 0; 9946 uint32 npolicers = 0; 9947 bcm_policer_attr_selectors_t mode_pkt_attr_selectors; 9948 bcm_policer_svc_meter_bookkeep_mode_t *mode_info = NULL; 9949 bcm_policer_group_mode_attr_selector_t *attr_selectors = NULL; 9950 bcm_policer_combine_attr_t *combine_attr_data = NULL; 9951 bcm_policer_combine_attr_t *mode_combine_attr_data = NULL; 9952 9953 /* pkt_attr_selectors is NULL. So, it is not coming from 9954 bcm_policer_group_mode_id_create() API. Go for default comparison. */ 9955 if (pkt_attr_selectors == NULL) { 9956 return _bcm_esw_svc_meter_compressed_modes_match(unit, 9957 compressed_attr_selectors_v, group_mode, 9958 type, svc_meter_mode); 9959 } 9960 mode_info = sal_alloc(sizeof(bcm_policer_svc_meter_bookkeep_mode_t), 9961 "mode bookkeep info"); 9962 if (mode_info == NULL) { 9963 LOG_VERBOSE(BSL_LS_BCM_POLICER, 9964 (BSL_META_U(unit, 9965 "Failed to allocate memory for mode bookkeep " 9966 "info\n"))); 9967 return BCM_E_MEMORY; 9968 } 9969 9970 for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 9971 sal_memset(mode_info, 0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t)); 9972 if (_bcm_policer_svc_meter_get_mode_info( 9973 unit, index, mode_info) == BCM_E_NONE) { 9974 /* If not compressed mode, check next. */ 9975 if (mode_info->meter_attr.mode_type_v != compressed_mode) { 9976 continue; 9977 } 9978 /* If not custom mode Id, check next. */ 9979 if (mode_info->type == -1) { 9980 continue; 9981 } 9982 9983 /* Compare total policers. */ 9984 if (pkt_attr_selectors->total_policers != 9985 mode_info->no_of_policers) { 9986 continue; 9987 } 9988 9989 /* Get pkt attributes fillup info and compare */ 9990 sal_memset(&mode_pkt_attr_selectors, 0, 9991 sizeof(bcm_policer_attr_selectors_t)); 9992 _GLOBAL_METER_XGS3_ALLOC(attr_selectors, 9993 mode_info->no_of_selectors * \ 9994 sizeof(bcm_policer_group_mode_attr_selector_t), 9995 "attr selectors"); 9996 bcm_error_v = _bcm_wb_attr_selectors_copy_to_attr_selectors( 9997 mode_info->no_of_selectors, 9998 mode_info->attr_selectors, attr_selectors); 9999 if (BCM_FAILURE(bcm_error_v)) { 10000 sal_free(mode_info); 10001 sal_free(attr_selectors); 10002 return bcm_error_v; 10003 } 10004 npolicers = mode_info->no_of_policers; 10005 _GLOBAL_METER_XGS3_ALLOC(mode_pkt_attr_selectors.combine_attr_data, 10006 sizeof(bcm_policer_combine_attr_t) * npolicers, 10007 "combine attributes"); 10008 if (mode_pkt_attr_selectors.combine_attr_data == NULL) { 10009 sal_free(mode_info); 10010 sal_free(attr_selectors); 10011 return BCM_E_MEMORY; 10012 } 10013 10014 bcm_error_v = _bcm_esw_policer_group_mode_fillup_values(unit, 0, 10015 mode_info->type, mode_info->no_of_policers, 10016 mode_info->no_of_selectors, &attr_selectors[0], 10017 &mode_pkt_attr_selectors); 10018 if (bcm_error_v != BCM_E_NONE) { 10019 sal_free(mode_info); 10020 sal_free(attr_selectors); 10021 sal_free(mode_pkt_attr_selectors.combine_attr_data); 10022 return bcm_error_v; 10023 } 10024 10025 /* Compare attributes and values */ 10026 is_equal = TRUE; 10027 for (pol = 0; pol < mode_info->no_of_policers; pol++) { 10028 combine_attr_data = 10029 &pkt_attr_selectors->combine_attr_data[pol]; 10030 mode_combine_attr_data = 10031 &mode_pkt_attr_selectors.combine_attr_data[pol]; 10032 10033 if (sal_memcmp(combine_attr_data, mode_combine_attr_data, 10034 sizeof(bcm_policer_combine_attr_t)) != 0) { 10035 is_equal = FALSE; 10036 break; 10037 } 10038 } 10039 if (is_equal == TRUE) { 10040 *svc_meter_mode = index; 10041 sal_free(mode_info); 10042 sal_free(attr_selectors); 10043 sal_free(mode_pkt_attr_selectors.combine_attr_data); 10044 return BCM_E_EXISTS; 10045 } else { 10046 sal_free(attr_selectors); 10047 sal_free(mode_pkt_attr_selectors.combine_attr_data); 10048 attr_selectors = NULL; 10049 mode_pkt_attr_selectors.combine_attr_data = NULL; 10050 } 10051 } 10052 } 10053 10054 if (mode_info != NULL) { 10055 sal_free(mode_info); 10056 } 10057 return BCM_E_NONE; 10058 } 10059 10060 /* 10061 * Function: 10062 * _bcm_esw_svc_meter_compressed_modes_match 10063 * Purpose: 10064 * Internal function to match existing mode ids with new input selectors 10065 * for compressed mode. 10066 * 10067 * Parameters: 10068 * Unit - (IN) unit number 10069 * compressed_attr_selectors_v - (IN) compressed attribute selectors. 10070 * group_mode - (IN) New Policer Group Mode 10071 * type - (IN) New policer Group Type 10072 * svc_meter_mode - (OUT) svc meter offset mode 10073 * Returns: 10074 * BCM_E_EXISTS - If a match is found 10075 * BCM_E_XXX 10076 */ 10077 STATIC int 10078 _bcm_esw_svc_meter_compressed_modes_match(int unit, 10079 compressed_attr_selectors_t *compressed_attr_selectors_v, 10080 bcm_policer_group_mode_t group_mode, 10081 int8 type, 10082 bcm_policer_svc_meter_mode_t *svc_meter_mode) 10083 { 10084 bcm_error_t bcm_error_v=BCM_E_NONE; 10085 pkt_attr_bits_t *config_pkt_attr = NULL; 10086 uint32 total_bits_used = 0; 10087 uint32 index = 0; 10088 bcm_policer_svc_meter_bookkeep_mode_t *mode_info = NULL; 10089 pkt_attr_bits_t *pkt_attr_bits = NULL; 10090 int port_attr_size = 0; 10091 uint32 pri_cng_map_in_use = 0; 10092 uint32 pkt_pri_map_in_use = 0; 10093 uint32 port_map_in_use = 0; 10094 uint32 tos_map_in_use = 0; 10095 uint32 pkt_res_map_in_use = 0; 10096 int svp_type_attr_size = 0; 10097 10098 mode_info = sal_alloc(sizeof(bcm_policer_svc_meter_bookkeep_mode_t), 10099 "mode bookkeep info"); 10100 if (mode_info == NULL) { 10101 LOG_VERBOSE(BSL_LS_BCM_POLICER, 10102 (BSL_META_U(unit, 10103 "Failed to allocate memory for mode bookkeep " 10104 "info\n"))); 10105 return BCM_E_MEMORY; 10106 } 10107 sal_memset(mode_info, 0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t)); 10108 10109 config_pkt_attr = &compressed_attr_selectors_v->pkt_attr_bits_v; 10110 10111 /*check if a mode is already configured with these attributes */ 10112 for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 10113 if (_bcm_policer_svc_meter_get_mode_info( 10114 unit, index, mode_info) == BCM_E_NONE) { 10115 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 10116 if (mode_info->meter_attr.mode_type_v != compressed_mode) { 10117 continue; 10118 } else if ((type == -1) && 10119 (mode_info->type == -1) && 10120 (mode_info->group_mode != group_mode)) { 10121 LOG_DEBUG(BSL_LS_BCM_POLICER, 10122 (BSL_META_U(unit, 10123 "Some other policer group is already " 10124 "using this resource\n"))); 10125 sal_free(mode_info); 10126 return BCM_E_PARAM; 10127 } 10128 } else { 10129 if ((mode_info->meter_attr.mode_type_v != compressed_mode) || 10130 (group_mode != mode_info->group_mode)) { 10131 if (mode_info->meter_attr.mode_type_v == compressed_mode) { 10132 LOG_DEBUG(BSL_LS_BCM_POLICER, 10133 (BSL_META_U(unit, 10134 "Some other policer group is already " 10135 "using this resource\n"))); 10136 sal_free(mode_info); 10137 return BCM_E_PARAM; 10138 } 10139 } 10140 } 10141 pkt_attr_bits = &mode_info->meter_attr.compressed_attr_selectors_v.\ 10142 pkt_attr_bits_v; 10143 if ((pkt_attr_bits->cng == config_pkt_attr->cng) && 10144 (pkt_attr_bits->int_pri == config_pkt_attr->int_pri) && 10145 (pkt_attr_bits->vlan_format == config_pkt_attr->vlan_format) && 10146 (pkt_attr_bits->outer_dot1p == config_pkt_attr->outer_dot1p) && 10147 (pkt_attr_bits->inner_dot1p == config_pkt_attr->inner_dot1p) && 10148 (pkt_attr_bits->ing_port == config_pkt_attr->ing_port) && 10149 (pkt_attr_bits->tos == config_pkt_attr->tos) && 10150 (pkt_attr_bits->tos_ecn == config_pkt_attr->tos_ecn) && 10151 (pkt_attr_bits->pkt_resolution == config_pkt_attr->pkt_resolution) && 10152 (pkt_attr_bits->svp_type == config_pkt_attr->svp_type) && 10153 (pkt_attr_bits->drop == config_pkt_attr->drop) && 10154 (pkt_attr_bits->ip_pkt == config_pkt_attr->ip_pkt)) { 10155 *svc_meter_mode = index; 10156 sal_free(mode_info); 10157 return BCM_E_EXISTS; 10158 } 10159 if ((pkt_attr_bits->cng != 0) || 10160 (pkt_attr_bits->int_pri != 0)) { 10161 pri_cng_map_in_use = 1; 10162 } 10163 if ((pkt_attr_bits->vlan_format != 0) || 10164 (pkt_attr_bits->outer_dot1p != 0) || 10165 (pkt_attr_bits->inner_dot1p != 0)) { 10166 pkt_pri_map_in_use = 1; 10167 } 10168 if (pkt_attr_bits->ing_port != 0) { 10169 port_map_in_use = 1; 10170 } 10171 if ((pkt_attr_bits->tos != 0) || 10172 (pkt_attr_bits->tos_ecn != 0)) { 10173 tos_map_in_use = 1; 10174 } 10175 if ((pkt_attr_bits->pkt_resolution != 0) || 10176 (pkt_attr_bits->svp_type != 0) || 10177 (pkt_attr_bits->drop != 0)) { 10178 pkt_res_map_in_use = 1; 10179 } 10180 } 10181 } /* end of for */ 10182 sal_free(mode_info); 10183 10184 /* Check Packet Attribute selection and compression table usage */ 10185 if (config_pkt_attr->cng != 0) { 10186 if (config_pkt_attr->cng > BCM_POLICER_SVC_METER_CNG_ATTR_SIZE) { 10187 LOG_DEBUG(BSL_LS_BCM_POLICER, 10188 (BSL_META_U(unit, 10189 "CNG attribute size exceeds max allowed size\n"))); 10190 return BCM_E_PARAM; 10191 } 10192 if (pri_cng_map_in_use == 1) { 10193 bcm_error_v = BCM_E_RESOURCE; 10194 } 10195 total_bits_used += config_pkt_attr->cng; 10196 } 10197 if (config_pkt_attr->int_pri != 0) { 10198 if (config_pkt_attr->int_pri > BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE) { 10199 LOG_DEBUG(BSL_LS_BCM_POLICER, 10200 (BSL_META_U(unit, 10201 "int_pri attribute size exceeds max allowed " 10202 "size\n"))); 10203 return BCM_E_PARAM; 10204 } 10205 if (pri_cng_map_in_use == 1) { 10206 bcm_error_v = BCM_E_RESOURCE; 10207 } 10208 total_bits_used += config_pkt_attr->int_pri; 10209 } 10210 if (config_pkt_attr->vlan_format != 0) { 10211 if (config_pkt_attr->vlan_format > 10212 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE) { 10213 LOG_DEBUG(BSL_LS_BCM_POLICER, 10214 (BSL_META_U(unit, 10215 "Vlan attribute size exceeds max allowed " 10216 "size\n"))); 10217 return BCM_E_PARAM; 10218 } 10219 if (pkt_pri_map_in_use == 1) { 10220 bcm_error_v = BCM_E_RESOURCE; 10221 } 10222 total_bits_used += config_pkt_attr->vlan_format; 10223 } 10224 if (config_pkt_attr->outer_dot1p != 0) { 10225 if (config_pkt_attr->outer_dot1p > 10226 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE) { 10227 LOG_DEBUG(BSL_LS_BCM_POLICER, 10228 (BSL_META_U(unit, 10229 "Outer DOT1P attribute size exceeds max allowed " 10230 "size\n"))); 10231 return BCM_E_PARAM; 10232 } 10233 if (pkt_pri_map_in_use == 1) { 10234 bcm_error_v = BCM_E_RESOURCE; 10235 } 10236 total_bits_used += config_pkt_attr->outer_dot1p; 10237 } 10238 if (config_pkt_attr->inner_dot1p != 0) { 10239 if (config_pkt_attr->inner_dot1p > 10240 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE) { 10241 LOG_DEBUG(BSL_LS_BCM_POLICER, 10242 (BSL_META_U(unit, 10243 "Inner DOT1P attribute size exceeds max allowed " 10244 "size\n"))); 10245 return BCM_E_PARAM; 10246 } 10247 if (pkt_pri_map_in_use == 1) { 10248 bcm_error_v = BCM_E_RESOURCE; 10249 } 10250 total_bits_used += config_pkt_attr->inner_dot1p; 10251 } 10252 if (config_pkt_attr->ing_port != 0) { 10253 port_attr_size = 10254 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size; 10255 if (config_pkt_attr->ing_port > port_attr_size) { 10256 LOG_DEBUG(BSL_LS_BCM_POLICER, 10257 (BSL_META_U(unit, 10258 "port attribute size exceeds max allowed " 10259 "size\n"))); 10260 return BCM_E_PARAM; 10261 } 10262 if (port_map_in_use == 1) { 10263 bcm_error_v = BCM_E_RESOURCE; 10264 } 10265 total_bits_used += config_pkt_attr->ing_port; 10266 } 10267 if (config_pkt_attr->tos != 0) { 10268 if (config_pkt_attr->tos > BCM_POLICER_SVC_METER_TOS_ATTR_SIZE) { 10269 LOG_DEBUG(BSL_LS_BCM_POLICER, 10270 (BSL_META_U(unit, 10271 "TOS attribute size exceeds max allowed " 10272 "size\n"))); 10273 return BCM_E_PARAM; 10274 } 10275 if (tos_map_in_use == 1) { 10276 bcm_error_v = BCM_E_RESOURCE; 10277 } 10278 total_bits_used += config_pkt_attr->tos; 10279 } 10280 if (config_pkt_attr->tos_ecn != 0) { 10281 if (config_pkt_attr->tos_ecn > BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE) { 10282 LOG_DEBUG(BSL_LS_BCM_POLICER, 10283 (BSL_META_U(unit, 10284 "TOS ecn attribute size exceeds max allowed " 10285 "size\n"))); 10286 return BCM_E_PARAM; 10287 } 10288 if (tos_map_in_use == 1) { 10289 bcm_error_v = BCM_E_RESOURCE; 10290 } 10291 total_bits_used += config_pkt_attr->tos_ecn; 10292 } 10293 if (config_pkt_attr->pkt_resolution != 0) { 10294 if (config_pkt_attr->pkt_resolution > 10295 BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE) { 10296 LOG_DEBUG(BSL_LS_BCM_POLICER, 10297 (BSL_META_U(unit, 10298 "Pkt resolution attribute size exceeds max " 10299 "allowed size\n"))); 10300 return BCM_E_PARAM; 10301 } 10302 if (pkt_res_map_in_use == 1) { 10303 bcm_error_v = BCM_E_RESOURCE; 10304 } 10305 total_bits_used += config_pkt_attr->pkt_resolution; 10306 } 10307 if (config_pkt_attr->svp_type != 0) { 10308 svp_type_attr_size = 10309 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size; 10310 if (config_pkt_attr->svp_type > svp_type_attr_size) { 10311 LOG_DEBUG(BSL_LS_BCM_POLICER, 10312 (BSL_META_U(unit, 10313 "SVP type attribute size exceeds max allowed " 10314 "size\n"))); 10315 return BCM_E_PARAM; 10316 } 10317 if (pkt_res_map_in_use == 1) { 10318 bcm_error_v = BCM_E_RESOURCE; 10319 } 10320 total_bits_used += config_pkt_attr->svp_type; 10321 } 10322 if (config_pkt_attr->drop != 0) { 10323 if (config_pkt_attr->drop > BCM_POLICER_SVC_METER_DROP_ATTR_SIZE) { 10324 LOG_DEBUG(BSL_LS_BCM_POLICER, 10325 (BSL_META_U(unit, 10326 "DROP attribute size exceeds max allowed " 10327 "size\n"))); 10328 return BCM_E_PARAM; 10329 } 10330 if (pkt_res_map_in_use == 1) { 10331 bcm_error_v = BCM_E_RESOURCE; 10332 } 10333 total_bits_used += config_pkt_attr->drop; 10334 } 10335 if (config_pkt_attr->ip_pkt != 0) { 10336 if (config_pkt_attr->ip_pkt > BCM_POLICER_SVC_METER_IP_PKT_ATTR_SIZE) { 10337 LOG_DEBUG(BSL_LS_BCM_POLICER, 10338 (BSL_META_U(unit, 10339 "IP pkt attribute size exceeds max allowed " 10340 "size\n"))); 10341 return BCM_E_PARAM; 10342 } 10343 total_bits_used += config_pkt_attr->ip_pkt; 10344 } 10345 if (bcm_error_v == BCM_E_RESOURCE) { 10346 LOG_DEBUG(BSL_LS_BCM_POLICER, 10347 (BSL_META_U(unit, "Resource not available\n"))); 10348 return bcm_error_v; 10349 } 10350 10351 if (total_bits_used > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 10352 LOG_DEBUG(BSL_LS_BCM_POLICER, 10353 (BSL_META_U(unit, 10354 "Key size exceeds max allowed " 10355 "size\n"))); 10356 return BCM_E_PARAM; 10357 } 10358 10359 return BCM_E_NONE; 10360 } 10361 10362 /* 10363 * Function: 10364 * _bcm_policer_svc_meter_create_compress_mode 10365 * Purpose: 10366 * Function to create an offset mode with compressed packet attributes 10367 * Parameters: 10368 * Unit - (IN) unit number 10369 * compressed_attr_selectors_v - (IN) Packet attribute selectors 10370 * group_mode - (IN) Policer group mode 10371 * svc_meter_mode - (OUT) Allocated meter offset mode 10372 * total_bits - (OUT) Total number of packet attribute bits 10373 * Returns: 10374 * BCM_E_XXX 10375 */ 10376 bcm_error_t _bcm_policer_svc_meter_create_compress_mode( 10377 int unit, 10378 compressed_attr_selectors_t *compressed_attr_selectors_v, 10379 bcm_policer_group_mode_t group_mode, 10380 int8 type, 10381 bcm_policer_attr_selectors_t *pkt_attr_selectors, 10382 bcm_policer_svc_meter_mode_t *svc_meter_mode) 10383 { 10384 bcm_error_t bcm_error_v=BCM_E_NONE; 10385 bcm_policer_svc_meter_mode_t bcm_policer_svc_meter_mode = 0; 10386 pkt_attr_bits_t *pkt_attr_bits_v = NULL; 10387 10388 /* Step1: Match with existing mode_ids. */ 10389 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 10390 bcm_error_v = _bcm_esw_svc_meter_compressed_modes_match_for_share(unit, 10391 compressed_attr_selectors_v, group_mode, 10392 type, pkt_attr_selectors, svc_meter_mode); 10393 } else { 10394 bcm_error_v = _bcm_esw_svc_meter_compressed_modes_match(unit, 10395 compressed_attr_selectors_v, group_mode, 10396 type, svc_meter_mode); 10397 } 10398 10399 if (BCM_FAILURE(bcm_error_v)) { 10400 return bcm_error_v; 10401 } 10402 10403 bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit, 10404 &bcm_policer_svc_meter_mode); 10405 if (bcm_error_v != BCM_E_NONE) { 10406 return bcm_error_v; 10407 } 10408 10409 /* Step2: Verify and Fill up compression tables */ 10410 bcm_error_v = _bcm_esw_svm_pkt_compressed_attr_maps_add(unit, 10411 compressed_attr_selectors_v); 10412 if (BCM_FAILURE(bcm_error_v)) { 10413 return bcm_error_v; 10414 } 10415 10416 /* Step3: Packet Attribute Selectors filling */ 10417 pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v; 10418 10419 if ((type == -1) || 10420 (soc_feature(unit, soc_feature_global_meter_compression_share))) { 10421 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys(unit, 10422 compressed_mode, type, 10423 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode], 10424 *pkt_attr_bits_v)); 10425 } else { 10426 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_selector_keys2(unit, 10427 compressed_mode, 10428 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode], 10429 *pkt_attr_bits_v)); 10430 } 10431 10432 /* Step4: Offset table filling */ 10433 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 10434 SVM_OFFSET_TABLEm, 10435 bcm_policer_svc_meter_mode, 10436 &compressed_attr_selectors_v->offset_map[0])); 10437 10438 /* Step5: Final: reserve mode and return */ 10439 *svc_meter_mode = bcm_policer_svc_meter_mode; 10440 return BCM_E_NONE; 10441 } 10442 10443 /* 10444 * Function: 10445 * _bcm_policer_svc_meter_create_udf_mode 10446 * Purpose: 10447 * Function to create an offset mode with udf packet attributes 10448 * Parameters: 10449 * Unit - (IN) unit number 10450 * udf_pkt_attr - (IN) Packet attribute selectors 10451 * group_mode - (IN) Policer group mode 10452 * svc_meter_mode - (OUT) Allocated meter offset mode 10453 * total_bits - (OUT) Total number of packet attribute bits 10454 * Returns: 10455 * BCM_E_XXX 10456 */ 10457 bcm_error_t _bcm_policer_svc_meter_create_udf_mode( 10458 int unit, 10459 udf_pkt_attr_selectors_t *udf_pkt_attr, 10460 bcm_policer_group_mode_t group_mode, 10461 int8 type, 10462 bcm_policer_svc_meter_mode_t *svc_meter_mode, 10463 uint32 *total_bits) 10464 { 10465 bcm_error_t bcm_error_v = BCM_E_NONE; 10466 bcm_policer_svc_meter_mode_t bcm_policer_svc_meter_mode = 0; 10467 uint32 total_udf_bits = 0; 10468 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 10469 udf_pkt_attr_selectors_t *udf_attr = NULL; 10470 uint32 index = 0; 10471 bcm_policer_svc_meter_mode_type_t mode_type = 0; 10472 if (type == bcmPolicerGroupModeTypeNormal) { 10473 mode_type = udf_mode; 10474 } else if (type == bcmPolicerGroupModeTypeCascade) { 10475 mode_type = udf_cascade_mode; 10476 } else { 10477 mode_type = udf_cascade_with_coupling_mode; 10478 } 10479 10480 /*check if a mode is already configured with these attributes */ 10481 for (index = 1;index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 10482 if (_bcm_policer_svc_meter_get_mode_info(unit, index, &mode_info) == 10483 BCM_E_NONE) { 10484 if ((mode_info.meter_attr.mode_type_v != mode_type) || 10485 (group_mode != mode_info.group_mode )) { 10486 continue; 10487 } 10488 udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v; 10489 if ((udf_attr->drop == udf_pkt_attr->drop) && 10490 (udf_attr->total_subdiv == udf_pkt_attr->total_subdiv) && 10491 (sal_memcmp(&udf_attr->udf_subdiv[0], &udf_pkt_attr->udf_subdiv[0], 10492 sizeof(bcm_policer_udf_sub_div_t) * SVC_METER_UDF_MAX_SUB_DIVISIONS) == 0) && 10493 (udf_attr->num_selectors == udf_pkt_attr->num_selectors) && 10494 (sal_memcmp(&udf_attr->offset_map[0], 10495 &udf_pkt_attr->offset_map[0], 10496 (BCM_SVC_METER_MAP_SIZE_256 * sizeof(offset_table_entry_t))) == 0)) { 10497 *svc_meter_mode = index; 10498 return BCM_E_EXISTS; 10499 } 10500 } 10501 } 10502 10503 bcm_error_v = _bcm_policer_svc_meter_get_available_mode(unit, 10504 &bcm_policer_svc_meter_mode); 10505 if (bcm_error_v != BCM_E_NONE) { 10506 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 10507 "offset table is full \n"))); 10508 return bcm_error_v; 10509 } 10510 /* Step1: Packet Attribute filling */ 10511 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_udf_selector_keys( 10512 unit, 10513 _pkt_attr_sel_key_reg[bcm_policer_svc_meter_mode], 10514 udf_pkt_attr, 10515 &total_udf_bits)); 10516 10517 /* Step2: Offset table filling */ 10518 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 10519 SVM_OFFSET_TABLEm, 10520 bcm_policer_svc_meter_mode, 10521 &udf_pkt_attr->offset_map[0])); 10522 10523 /* Step3: Final: reserve mode and return */ 10524 *svc_meter_mode = bcm_policer_svc_meter_mode; 10525 return BCM_E_NONE; 10526 } 10527 10528 /* 10529 * Function: 10530 * _bcm_esw_policer_svc_meter_create_mode 10531 * Purpose: 10532 * Function to create an Meter offset mode 10533 * Parameters: 10534 * Unit - (IN) unit number 10535 * meter_attr - (IN) Packet attribute selectors 10536 * group_mode - (IN) Policer group mode 10537 * num_pol - (IN) Number of policers 10538 * svc_meter_mode - (OUT) Allocated meter offset mode 10539 * Returns: 10540 * BCM_E_XXX 10541 */ 10542 int _bcm_esw_policer_svc_meter_create_mode ( 10543 int unit, 10544 bcm_policer_svc_meter_attr_t *meter_attr, 10545 bcm_policer_group_mode_t group_mode, 10546 int8 type, 10547 int num_pol, 10548 bcm_policer_attr_selectors_t *pkt_attr_selectors, 10549 bcm_policer_svc_meter_mode_t *svc_meter_mode) 10550 { 10551 uint32 total_bits; 10552 int rv = BCM_E_NONE; 10553 10554 switch (meter_attr->mode_type_v) 10555 { 10556 case uncompressed_mode: 10557 rv = _bcm_policer_svc_meter_create_uncompress_mode( 10558 unit, 10559 &meter_attr->uncompressed_attr_selectors_v, 10560 group_mode, type, svc_meter_mode); 10561 if (BCM_FAILURE(rv) && (rv == BCM_E_EXISTS)) { 10562 return rv; 10563 } 10564 break; 10565 case compressed_mode: 10566 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_compress_mode( 10567 unit, 10568 &meter_attr->compressed_attr_selectors_v, 10569 group_mode, type, pkt_attr_selectors, svc_meter_mode)); 10570 break; 10571 case udf_mode: 10572 case udf_cascade_mode: 10573 case udf_cascade_with_coupling_mode: 10574 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_udf_mode( 10575 unit, 10576 &meter_attr->udf_pkt_attr_selectors_v, 10577 group_mode, type, svc_meter_mode, &total_bits)); 10578 break; 10579 case cascade_mode: 10580 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_create_cascade_mode( 10581 unit, 10582 &meter_attr->uncompressed_attr_selectors_v, 10583 group_mode, type, num_pol, svc_meter_mode)); 10584 break; 10585 10586 default: 10587 LOG_DEBUG(BSL_LS_BCM_POLICER, 10588 (BSL_META_U(unit, 10589 "Invalid offset mode\n"))); 10590 return BCM_E_PARAM; 10591 } 10592 if (BCM_FAILURE(rv) && ((rv == BCM_E_FULL) || (rv == BCM_E_PARAM))) { 10593 return rv; 10594 } 10595 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_reserve_mode(unit, 10596 *svc_meter_mode, 10597 group_mode, 10598 meter_attr)); 10599 return BCM_E_NONE; 10600 } 10601 10602 /* 10603 * Function: 10604 * _bcm_esw_policer_svc_meter_delete_mode 10605 * Purpose: 10606 * Delete a meter offset mode 10607 * Parameters: 10608 * Unit - (IN) unit number 10609 * svc_meter_mode - (IN) offset mode 10610 * Returns: 10611 * BCM_E_XXX 10612 */ 10613 int _bcm_esw_policer_svc_meter_delete_mode( 10614 int unit, 10615 bcm_policer_svc_meter_mode_t svc_meter_mode) 10616 { 10617 if (svc_meter_mode == 0) { 10618 LOG_DEBUG(BSL_LS_BCM_POLICER, 10619 (BSL_META_U(unit, 10620 "Invalid mode passed: %d \n"), 10621 svc_meter_mode)); 10622 return BCM_E_PARAM; /*0 is Reserved */ 10623 } 10624 if (svc_meter_mode > (BCM_POLICER_SVC_METER_MAX_MODE - 1)) { 10625 LOG_DEBUG(BSL_LS_BCM_POLICER, 10626 (BSL_META_U(unit, 10627 "Invalid mode passed: %d \n"), 10628 svc_meter_mode)); 10629 return BCM_E_PARAM; /* Exceeding max allowed value */ 10630 } 10631 return _bcm_policer_svc_meter_unreserve_mode(unit, svc_meter_mode); 10632 } 10633 10634 /* 10635 * Function: 10636 * _bcm_esw_get_policer_id_from_index_offset 10637 * Purpose: 10638 * Get policer id, given the HW policer index and offset_mode 10639 * Parameters: 10640 * Unit - (IN) unit number 10641 * index - (IN) HW policer index 10642 * offset_mode - (IN) offset mode 10643 * pid - (OUT) policer Id 10644 * Returns: 10645 * BCM_E_XXX 10646 */ 10647 int _bcm_esw_get_policer_id_from_index_offset(int unit, int index, 10648 int offset_mode, 10649 bcm_policer_t *pid) 10650 { 10651 int pool=0, size_of_pool=0; 10652 10653 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 10654 if (soc_feature(unit, soc_feature_global_meter_v2)) { 10655 return bcmi_esw_get_policer_id_from_index_offset( 10656 unit, index, offset_mode, pid); 10657 } 10658 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 10659 10660 size_of_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 10661 if (index > 0) { 10662 pool = index / size_of_pool; 10663 index = index % size_of_pool; 10664 *pid = (((offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT) + 10665 (pool << _shr_popcount(size_of_pool - 1)) + index); 10666 } else { 10667 *pid = 0; 10668 } 10669 return BCM_E_NONE; 10670 } 10671 10672 /* 10673 * Function: 10674 * _bcm_esw_get_policer_table_index 10675 * Purpose: 10676 * Get the HW policer index, given a policer id. 10677 * Parameters: 10678 * Unit - (IN) unit number 10679 * policer - (IN) policer Id 10680 * index - (OUT) HW policer index 10681 * Returns: 10682 * BCM_E_XXX 10683 */ 10684 int _bcm_esw_get_policer_table_index(int unit, bcm_policer_t policer, 10685 int *index) 10686 { 10687 int rv = BCM_E_NONE; 10688 int size_pool = 0, num_pools = 0; 10689 int pool=0; 10690 int offset_mask = 0; 10691 int pool_mask = 0, pool_offset = 0; 10692 10693 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 10694 if (soc_feature(unit, soc_feature_global_meter_v2)) { 10695 return bcmi_esw_policer_table_index_get(unit, policer, index); 10696 } 10697 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 10698 10699 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 10700 num_pools = SOC_INFO(unit).global_meter_pools; 10701 offset_mask = size_pool - 1; 10702 pool_offset = _shr_popcount(offset_mask); 10703 pool_mask = (num_pools - 1) << pool_offset; 10704 pool = ((policer & pool_mask) >> pool_offset); 10705 *index = ((policer & offset_mask) + (pool * size_pool)); 10706 return rv; 10707 } 10708 10709 /* 10710 * Function: 10711 * _bcm_esw_get_corres_policer_for_pool 10712 * Purpose: 10713 * Get the policer Id, corresponding to a given policer id and specified pool. 10714 * Parameters: 10715 * Unit - (IN) unit number 10716 * policer - (IN) policer Id 10717 * new_pool - (IN) new pool for which policer Id required 10718 * new_policer - (OUT) New Policer Id for given pool in policer Id octuple 10719 * Returns: 10720 * BCM_E_XXX 10721 */ 10722 int _bcm_esw_get_corres_policer_for_pool(int unit, bcm_policer_t policer, int new_pool, 10723 bcm_policer_t *new_policer) 10724 { 10725 int size_pool, pool_offset, offset_val; 10726 int num_pools; 10727 10728 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 10729 pool_offset = _shr_popcount(size_pool - 1); 10730 offset_val = policer & BCM_POLICER_GLOBAL_METER_MODE_MASK; 10731 num_pools = SOC_INFO(unit).global_meter_pools; 10732 10733 if ((new_pool < 0) || (new_pool >= num_pools)) { 10734 return BCM_E_INTERNAL; 10735 } 10736 10737 *new_policer = offset_val + (new_pool << pool_offset) + (policer & (size_pool - 1)); 10738 10739 return BCM_E_NONE; 10740 } 10741 10742 /* 10743 * Function: 10744 * _bcm_esw_svm_source_traverse 10745 * Purpose: 10746 * Traverse through all mem entires for a mem and call callback function 10747 * Parameters: 10748 * Unit - (IN) unit number 10749 * mem - (IN) table 10750 * start_idx - (IN) Start index where table traversal to begin 10751 * end_idx - (IN) Last index where table traversal to stop 10752 * cb - (IN) Callback function 10753 * user_data - (IN) Argument to call back function 10754 * Returns: 10755 * BCM_E_XXX 10756 */ 10757 bcm_error_t 10758 _bcm_esw_svm_source_traverse(int unit, soc_mem_t mem, int start_idx, 10759 int end_idx, _bcm_esw_svm_mem_entry_traverse_cb cb, void *user_data) 10760 { 10761 int rv = BCM_E_NONE; 10762 int8 *buffer = NULL; 10763 void *entry = NULL; 10764 uint32 idx = 0, entry_idx = 0; 10765 int mem_min = 0, mem_max = 0; 10766 uint32 entry_dirty = 0, blk_dirty = 0; 10767 uint32 chunk_size = 0, mem_entry_size = 0; 10768 10769 mem_min = soc_mem_index_min(unit, mem); 10770 mem_max = soc_mem_index_max(unit, mem); 10771 10772 end_idx = (end_idx < 0) ? mem_max : end_idx; 10773 start_idx = (start_idx < 0) ? mem_min : start_idx; 10774 10775 if ((start_idx > mem_max) || 10776 (end_idx > mem_max) || 10777 (start_idx > end_idx)) { 10778 return BCM_E_PARAM; 10779 } 10780 10781 chunk_size = ((end_idx - start_idx + 1) > BCM_SVM_DMA_CHUNK_SIZE) ? 10782 BCM_SVM_DMA_CHUNK_SIZE : (end_idx - start_idx + 1); 10783 mem_entry_size = SOC_MEM_WORDS(unit, mem) * sizeof(uint32); 10784 10785 buffer = soc_cm_salloc(unit, mem_entry_size * chunk_size, "svm mem buffer"); 10786 if (buffer == NULL) { 10787 return BCM_E_MEMORY; 10788 } 10789 for (idx = start_idx; idx <= end_idx; idx += chunk_size) { 10790 chunk_size = ((end_idx - idx + 1) > BCM_SVM_DMA_CHUNK_SIZE) ? 10791 BCM_SVM_DMA_CHUNK_SIZE : (end_idx - idx + 1); 10792 10793 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 10794 idx, idx + chunk_size - 1, buffer)) != SOC_E_NONE) { 10795 break; 10796 } 10797 for (entry_idx = 0; entry_idx < chunk_size; entry_idx++) { 10798 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 10799 buffer, entry_idx); 10800 entry_dirty = 0; 10801 rv = (*cb)(unit, mem, idx + entry_idx, entry, user_data, &entry_dirty); 10802 if (BCM_FAILURE(rv)) { 10803 break; 10804 } 10805 if (entry_dirty) { 10806 blk_dirty = 1; 10807 } 10808 } 10809 if (BCM_SUCCESS(rv) && blk_dirty) { 10810 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 10811 idx, idx + chunk_size - 1, buffer); 10812 } 10813 if (BCM_FAILURE(rv)) { 10814 break; 10815 } 10816 } 10817 10818 if (buffer != NULL) { 10819 soc_cm_sfree(unit, buffer); 10820 } 10821 return rv; 10822 } 10823 10824 /* 10825 * Function: 10826 * _bcm_esw_global_meter_cleanup 10827 * Purpose: 10828 * Cleanup the global meter(service meter) internal data structure on 10829 * init failure. 10830 * Parameters: 10831 * Unit - unit number 10832 * Returns: 10833 * BCM_E_XXX 10834 */ 10835 int 10836 _bcm_esw_global_meter_cleanup(int unit) 10837 { 10838 int rv = BCM_E_NONE; 10839 int mode = 0; 10840 int pool_id = 0, num_pools = 0; 10841 int num_banks_per_pool = 1, bank_id = 0, handle_id = 0; 10842 uint64 pkt_attr_selector_key_value; 10843 uint32 svc_meter_mode; 10844 10845 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 10846 if (soc_feature(unit, soc_feature_global_meter_v2)) { 10847 return bcmi_esw_global_meter_cleanup(unit); 10848 } 10849 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 10850 10851 if (0 == global_meter_status[unit].initialised) { 10852 LOG_VERBOSE(BSL_LS_BCM_POLICER, 10853 (BSL_META_U(unit, 10854 "Global meter feature not initialized\n"))); 10855 return rv; 10856 } 10857 /* mutex destroy */ 10858 if (NULL != global_meter_mutex[unit]) { 10859 sal_mutex_destroy(global_meter_mutex[unit]); 10860 global_meter_mutex[unit] = NULL; 10861 } 10862 /* Free handles of index management for meter action */ 10863 if (NULL != meter_action_list_handle[unit]) { 10864 shr_aidxres_list_destroy(meter_action_list_handle[unit]); 10865 meter_action_list_handle[unit] = NULL; 10866 } 10867 /* Free handles of index management for meter table */ 10868 num_pools = SOC_INFO(unit).global_meter_pools; 10869 num_banks_per_pool = get_max_banks_in_a_pool(unit); 10870 10871 for (pool_id = 0; pool_id < num_pools; pool_id++) { 10872 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) { 10873 handle_id = pool_id * num_banks_per_pool + bank_id; 10874 if (NULL != meter_alloc_list_handle[unit][handle_id]) { 10875 shr_aidxres_list_destroy(meter_alloc_list_handle[unit][handle_id]); 10876 meter_alloc_list_handle[unit][handle_id] = NULL; 10877 } 10878 } 10879 } 10880 if (NULL != global_meter_policer_bookkeep[unit]) { 10881 sal_free(global_meter_policer_bookkeep[unit]); 10882 global_meter_policer_bookkeep[unit] = NULL; 10883 } 10884 if (NULL != global_meter_hz_alloc_bookkeep[unit]) { 10885 sal_free(global_meter_hz_alloc_bookkeep[unit]); 10886 global_meter_hz_alloc_bookkeep[unit] = NULL; 10887 } 10888 if (NULL != global_meter_action_bookkeep[unit]) { 10889 sal_free(global_meter_action_bookkeep[unit]); 10890 global_meter_action_bookkeep[unit] = NULL; 10891 } 10892 10893 /* global_meter_offset_mode[][].attr_selectors needs to be freed */ 10894 for (mode = 1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 10895 if (global_meter_offset_mode[unit][mode].used == 1) { 10896 if (global_meter_offset_mode[unit][mode].attr_selectors != NULL) { 10897 sal_free(global_meter_offset_mode[unit][mode].attr_selectors); 10898 global_meter_offset_mode[unit][mode].attr_selectors = NULL; 10899 } 10900 } 10901 } 10902 if (svm_pkt_compressed_attr_maps_g[unit] != NULL) { 10903 sal_free(svm_pkt_compressed_attr_maps_g[unit]); 10904 svm_pkt_compressed_attr_maps_g[unit] = NULL; 10905 } 10906 10907 if (bcm_esw_svm_control[unit] != NULL) { 10908 sal_free(bcm_esw_svm_control[unit]); 10909 bcm_esw_svm_control[unit] = NULL; 10910 } 10911 10912 global_meter_status[unit].initialised = 0; 10913 SOC_IF_ERROR_RETURN( 10914 soc_mem_clear(unit, SVM_OFFSET_TABLEm, MEM_BLOCK_ALL, TRUE)); 10915 SOC_IF_ERROR_RETURN( 10916 soc_mem_clear(unit, SVM_METER_TABLEm, MEM_BLOCK_ALL, TRUE)); 10917 SOC_IF_ERROR_RETURN( 10918 soc_mem_clear(unit, SVM_MACROFLOW_INDEX_TABLEm, MEM_BLOCK_ALL, TRUE)); 10919 SOC_IF_ERROR_RETURN( 10920 soc_mem_clear(unit, SVM_POLICY_TABLEm, MEM_BLOCK_ALL, TRUE)); 10921 10922 COMPILER_64_ZERO(pkt_attr_selector_key_value); 10923 for (svc_meter_mode = 1; 10924 svc_meter_mode < BCM_POLICER_SVC_METER_MAX_MODE; 10925 svc_meter_mode++) { 10926 SOC_IF_ERROR_RETURN(soc_reg_set(unit, 10927 _pkt_attr_sel_key_reg[svc_meter_mode], 10928 REG_PORT_ANY, 10929 0, 10930 pkt_attr_selector_key_value)); 10931 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 10932 SVM_OFFSET_TABLEm, svc_meter_mode, NULL)); 10933 } 10934 LOG_VERBOSE(BSL_LS_BCM_POLICER, 10935 (BSL_META_U(unit, 10936 "Clening up global meter config\n"))); 10937 return rv; 10938 } 10939 10940 #ifdef BCM_APACHE_SUPPORT 10941 static svm_dbg_01_entry_t ap_clr_tr_tbl[32] = \ 10942 {{{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}}, 10943 {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}}, 10944 {{0x44e3}}, {{0x4444}}, {{0x44e3}}, {{0x44ee}}, 10945 {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}}, 10946 {{0x4d22}}, {{0x4444}}, {{0x4d22}}, {{0x4d4d}}, 10947 {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}}, 10948 {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}}, 10949 {{0x0000}}, {{0x0000}}, {{0x0000}}, {{0x0000}}}; 10950 10951 static svm_dbg_02_entry_t ap_clr_hier_tr_tbl[4] = { 10952 {{0x10290435, 0x04104104, 0x29040929}}, 10953 {{0x10274435, 0x04354104, 0x28840929}}, 10954 {{0x10090435, 0x04104104, 0x29043941}}, 10955 {{0x00000000, 0x00000000, 0x00000000}}, 10956 }; 10957 10958 static svm_dbg_03_entry_t ap_hier_cmtd_updt_tr_tbl[32] = \ 10959 {{{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, 10960 {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, 10961 {{0x13}}, {{0x13}}, {{0x13}}, {{0x13}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, 10962 {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}, {{0x00}}}; 10963 10964 /* 10965 * Function: 10966 * _bcm_svm_dbg_clr_tr_tbls 10967 * Purpose: 10968 * Initialize color truth table 10969 * Parameters: 10970 * Unit - unit number 10971 * Returns: 10972 * BCM_E_XXX 10973 */ 10974 STATIC 10975 int _bcm_svm_dbg_clr_tr_tbls (int unit) { 10976 int idx = 0, rv = BCM_E_NONE, max_idx = 0; 10977 10978 max_idx = soc_mem_index_max(unit,SVM_DBG_01m); 10979 for (idx = 0; idx < max_idx; idx++) { 10980 rv = WRITE_SVM_DBG_01m(unit,MEM_BLOCK_ANY,idx,&ap_clr_tr_tbl[idx]); 10981 if (BCM_FAILURE(rv)) { 10982 return (rv); 10983 } 10984 } 10985 10986 max_idx = soc_mem_index_max(unit,SVM_DBG_02m); 10987 for (idx = 0; idx < max_idx; idx++) { 10988 rv = WRITE_SVM_DBG_02m(unit,MEM_BLOCK_ANY,idx,&ap_clr_hier_tr_tbl[idx]); 10989 if (BCM_FAILURE(rv)) { 10990 return (rv); 10991 } 10992 } 10993 10994 max_idx = soc_mem_index_max(unit,SVM_DBG_03m); 10995 for (idx = 0; idx < max_idx; idx++) { 10996 rv = WRITE_SVM_DBG_03m(unit,MEM_BLOCK_ANY,idx, 10997 &ap_hier_cmtd_updt_tr_tbl[idx]); 10998 if (BCM_FAILURE(rv)) { 10999 return (rv); 11000 } 11001 } 11002 11003 return rv; 11004 } 11005 #endif /* BCM_APACHE_SUPPORT */ 11006 11007 /* 11008 * Function: 11009 * _bcm_policer_svm_dev_attr_info_initialize 11010 * Purpose: 11011 * Initialize parmas which varies across devices for 11012 * global service meters 11013 * Parameters: 11014 * Unit - unit number 11015 * Returns: 11016 * BCM_E_XXX 11017 */ 11018 STATIC int 11019 _bcm_policer_svm_dev_attr_info_initialize (int unit) 11020 { 11021 #ifdef BCM_APACHE_SUPPORT 11022 if (SOC_IS_APACHE(unit)) { 11023 BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 2; 11024 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 32; 11025 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size = 11026 BCM_POLICER_SVC_METER_SB2_ING_PORT_ATTR_SIZE; 11027 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size = 11028 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE; 11029 BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &ap_pkt_res[0]; 11030 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos = 11031 &sb2_pkt_attr_bit_pos[0]; 11032 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos = 11033 &sb2_cmprsd_pkt_attr_bit_pos[0]; 11034 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos = 11035 &sb2_pkt_cmprsd_attr_map_bit_pos[0]; 11036 } else 11037 #endif 11038 #ifdef BCM_SABER2_SUPPORT 11039 if (SOC_IS_SABER2(unit)) { 11040 BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1; 11041 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 32; 11042 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size = 11043 BCM_POLICER_SVC_METER_SB2_ING_PORT_ATTR_SIZE; 11044 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size = 11045 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE; 11046 BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &sb2_pkt_res[0]; 11047 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos = 11048 &sb2_pkt_attr_bit_pos[0]; 11049 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos = 11050 &sb2_cmprsd_pkt_attr_bit_pos[0]; 11051 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos = 11052 &sb2_pkt_cmprsd_attr_map_bit_pos[0]; 11053 } else 11054 #endif 11055 #ifdef BCM_KATANA2_SUPPORT 11056 if (SOC_IS_KATANA2(unit)) { 11057 BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1; 11058 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 33; 11059 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size = 11060 BCM_POLICER_SVC_METER_KT2_ING_PORT_ATTR_SIZE; 11061 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size = 11062 BCM_POLICER_SVC_METER_SVP_NETWORK_GROUP_ATTR_SIZE; 11063 BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &kt2_pkt_res[0]; 11064 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos = 11065 &kt2_pkt_attr_bit_pos[0]; 11066 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos = 11067 &kt2_cmprsd_pkt_attr_bit_pos[0]; 11068 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos = 11069 &kt2_pkt_cmprsd_attr_map_bit_pos[0]; 11070 } else 11071 #endif 11072 { /* Default. KT/TR3 */ 11073 BCM_SVM_DEV_ATTR(unit)->banks_per_pool = 1; 11074 BCM_SVM_DEV_ATTR(unit)->compressed_int_pri_bit_pos = 11075 kt_pkt_attr_bit_pos[pkt_attr_int_pri].start_bit; 11076 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size = 11077 BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE; 11078 BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size = 11079 BCM_POLICER_SVC_METER_SVP_TYPE_ATTR_SIZE; 11080 BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &kt_pkt_res[0]; 11081 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos = 11082 &kt_pkt_attr_bit_pos[0]; 11083 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos = 11084 &kt_pkt_attr_bit_pos[0]; 11085 BCM_SVM_DEV_ATTR(unit)->compressed_attr_map_bit_pos = 11086 &kt_pkt_cmprsd_attr_map_bit_pos[0]; 11087 } 11088 11089 #ifdef BCM_TRIUMPH3_SUPPORT 11090 if (SOC_IS_TRIUMPH3(unit)) { 11091 BCM_SVM_DEV_ATTR(unit)->pkt_resolution = &tr3_pkt_res[0]; 11092 } 11093 #endif 11094 return BCM_E_NONE; 11095 } 11096 11097 /* 11098 * Function: 11099 * _bcm_policer_svm_source_initialize 11100 * Purpose: 11101 * Initialize service metering source from various tables 11102 * Parameters: 11103 * Unit - unit number 11104 * Returns: 11105 * BCM_E_XXX 11106 */ 11107 STATIC bcm_error_t 11108 _bcm_policer_svm_source_initialize(int unit) 11109 { 11110 soc_mem_t table; 11111 _bcm_policer_svm_source_type_t mem_index; 11112 11113 for (mem_index = 0; mem_index < _BCM_SVM_MEM_COUNT; mem_index++) { 11114 BCM_SVM_SOURCE(unit, mem_index).table = INVALIDm; 11115 BCM_SVM_SOURCE(unit, mem_index).offset_mode = INVALIDf; 11116 BCM_SVM_SOURCE(unit, mem_index).meter_index = INVALIDf; 11117 table = INVALIDm; 11118 switch(mem_index) { 11119 case _BCM_SVM_MEM_PORT: 11120 table = PORT_TABm; 11121 break; 11122 case _BCM_SVM_MEM_VLAN: 11123 table = VLAN_TABm; 11124 break; 11125 case _BCM_SVM_MEM_VFI: 11126 table = VFIm; 11127 break; 11128 case _BCM_SVM_MEM_SOURCE_VP: 11129 table = SOURCE_VPm; 11130 break; 11131 case _BCM_SVM_MEM_VLAN_XLATE: 11132 table = VLAN_XLATEm; 11133 #ifdef BCM_TRIUMPH3_SUPPORT 11134 if (SOC_IS_TRIUMPH3(unit)) { 11135 table = VLAN_XLATE_EXTDm; 11136 } 11137 #endif 11138 break; 11139 case _BCM_SVM_MEM_VFP_POLICY_TABLE: 11140 table = VFP_POLICY_TABLEm; 11141 break; 11142 /* coverity[dead_error_begin : FALSE] */ 11143 default : 11144 break; 11145 } 11146 BCM_SVM_SOURCE(unit, mem_index).table = table; 11147 #ifdef BCM_TRIUMPH3_SUPPORT 11148 if (SOC_IS_TRIUMPH3(unit) && (mem_index == _BCM_SVM_MEM_VLAN_XLATE)) { 11149 if (SOC_MEM_FIELD_VALID(unit, table, 11150 XLATE__SVC_METER_OFFSET_MODEf)) { 11151 BCM_SVM_SOURCE(unit, mem_index).offset_mode = 11152 XLATE__SVC_METER_OFFSET_MODEf; 11153 } 11154 if (SOC_MEM_FIELD_VALID(unit, table, 11155 XLATE__SVC_METER_INDEXf)) { 11156 BCM_SVM_SOURCE(unit, mem_index).meter_index = 11157 XLATE__SVC_METER_INDEXf; 11158 } 11159 continue; 11160 } 11161 #endif 11162 if (SOC_MEM_FIELD_VALID(unit, table, SVC_METER_OFFSET_MODEf)) { 11163 BCM_SVM_SOURCE(unit, mem_index).offset_mode = 11164 SVC_METER_OFFSET_MODEf; 11165 } 11166 if (SOC_MEM_FIELD_VALID(unit, table, SVC_METER_INDEXf)) { 11167 BCM_SVM_SOURCE(unit, mem_index).meter_index = 11168 SVC_METER_INDEXf; 11169 } 11170 } 11171 return BCM_E_NONE; 11172 } 11173 11174 /* 11175 * Function: 11176 * bcm_esw_global_meter_init 11177 * Purpose: 11178 * Initialise service meter data-structure 11179 * Parameters: 11180 * Unit - unit number 11181 * Returns: 11182 * BCM_E_XXX 11183 */ 11184 int 11185 bcm_esw_global_meter_init(int unit) 11186 { 11187 int rv = BCM_E_NONE; 11188 uint32 service_meter_control = 0; 11189 uint32 ing_svm_control = 0; 11190 int mode = 0; 11191 uint32 num_pools = 0, size_pool = 0, total_size = 0, action_size = 0; 11192 uint32 num_banks_per_pool = 1, handle_id = 0, bank_id = 0; 11193 uint32 size_bank = 0, block_factor = 0; 11194 uint32 max_size_pool = 0; 11195 uint32 pool_id = 0, index = 0; 11196 soc_reg_t arb_reg; 11197 soc_field_t fields[2]; 11198 uint32 vals[2] = {1,1}; 11199 int no_fields = 0; 11200 #ifdef BCM_WARM_BOOT_SUPPORT 11201 int size = 0; 11202 soc_scache_handle_t scache_handle; 11203 uint8 *policer_state; 11204 #endif 11205 11206 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11207 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11208 return bcmi_esw_global_meter_init(unit); 11209 } 11210 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11211 11212 if (1 == global_meter_status[unit].initialised) { 11213 _bcm_esw_global_meter_cleanup(unit); 11214 } 11215 11216 if (!soc_feature(unit, soc_feature_global_meter)) { 11217 return BCM_E_UNAVAIL; 11218 } 11219 11220 if (!soc_property_get(unit, spn_GLOBAL_METER_CONTROL, 1)) { 11221 service_meter_control = BCM_POLICER_GLOBAL_METER_DISABLE; 11222 } 11223 SOC_IF_ERROR_RETURN(soc_reg32_get( unit, 11224 ING_SVM_CONTROLr, 11225 REG_PORT_ANY, 11226 0, 11227 &ing_svm_control)); 11228 11229 soc_reg_field_set(unit, 11230 ING_SVM_CONTROLr, 11231 &ing_svm_control, 11232 BLOCK_DISABLEf, 11233 service_meter_control); 11234 11235 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 11236 ING_SVM_CONTROLr, 11237 REG_PORT_ANY, 11238 0, 11239 ing_svm_control)); 11240 11241 if ( BCM_POLICER_GLOBAL_METER_DISABLE == service_meter_control) { 11242 global_meter_status[unit].initialised = 0; 11243 LOG_WARN(BSL_LS_BCM_POLICER, 11244 (BSL_META_U(unit, 11245 "GLOBAL METER FEATURE disabled " 11246 "at HW for unit %d\n"), unit)); 11247 return rv; 11248 } 11249 11250 _GLOBAL_METER_XGS3_ALLOC(bcm_esw_svm_control[unit], 11251 sizeof(_bcm_policer_global_meter_control_t), 11252 "global service meter control"); 11253 11254 rv = _bcm_policer_svm_dev_attr_info_initialize(unit); 11255 if (BCM_FAILURE(rv)) { 11256 _bcm_esw_global_meter_cleanup(unit); 11257 LOG_ERROR(BSL_LS_BCM_POLICER, 11258 (BSL_META_U(unit, 11259 "Chip Specific init failed\n"))); 11260 return rv; 11261 } 11262 rv = _bcm_policer_svm_source_initialize(unit); 11263 if (BCM_FAILURE(rv)) { 11264 _bcm_esw_global_meter_cleanup(unit); 11265 LOG_ERROR(BSL_LS_BCM_POLICER, 11266 (BSL_META_U(unit, 11267 "SVM source init failed\n"))); 11268 return rv; 11269 } 11270 11271 num_pools = SOC_INFO(unit).global_meter_pools; 11272 size_pool = SOC_INFO(unit).global_meter_size_of_pool; 11273 max_size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 11274 num_banks_per_pool = get_max_banks_in_a_pool(unit); 11275 size_bank = size_pool / num_banks_per_pool; 11276 total_size = num_pools * max_size_pool; 11277 if ((total_size) > (soc_mem_index_max(unit, SVM_METER_TABLEm) + 1)) 11278 { 11279 LOG_ERROR(BSL_LS_BCM_POLICER, 11280 (BSL_META_U(unit, 11281 "Number of global meters exceeding " 11282 "its max value\n"))); 11283 return BCM_E_INTERNAL; 11284 } 11285 11286 action_size = SOC_INFO(unit).global_meter_action_size; 11287 if ((action_size) > (soc_mem_index_max(unit, SVM_POLICY_TABLEm) + 1)) 11288 { 11289 LOG_ERROR(BSL_LS_BCM_POLICER, 11290 (BSL_META_U(unit, 11291 "Global meter actions exceeding " 11292 "its max value\n"))); 11293 return BCM_E_INTERNAL; 11294 } 11295 11296 /* Init the offset table 0 such that it can be used for non-offset 11297 based metering */ 11298 BCM_IF_ERROR_RETURN(_bcm_policer_svc_meter_update_offset_table(unit, 11299 SVM_OFFSET_TABLEm, 0, NULL)); 11300 11301 /* Initialize bookkeeping data structure */ 11302 for (mode=1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 11303 sal_memset(&global_meter_offset_mode[unit][mode], 11304 0, sizeof(bcm_policer_svc_meter_bookkeep_mode_t)); 11305 } 11306 11307 /* Allocate global compression attr map */ 11308 _GLOBAL_METER_XGS3_ALLOC(svm_pkt_compressed_attr_maps_g[unit], 11309 sizeof (_bcm_policer_pkt_compressed_attr_maps_t), 11310 "compressed attr map"); 11311 if (NULL == svm_pkt_compressed_attr_maps_g[unit]) { 11312 _bcm_esw_global_meter_cleanup(unit); 11313 LOG_ERROR(BSL_LS_BCM_POLICER, 11314 (BSL_META_U(unit, 11315 "Unable to allocate memory for policer " 11316 "compressed attribute map data structure\n"))); 11317 return BCM_E_MEMORY; 11318 } 11319 11320 /* Allocate policer lookup hash. */ 11321 _GLOBAL_METER_XGS3_ALLOC(global_meter_policer_bookkeep[unit], 11322 _GLOBAL_METER_HASH_SIZE * \ 11323 sizeof(_global_meter_policer_control_t *), "Global meter hash"); 11324 if (NULL == global_meter_policer_bookkeep[unit]) { 11325 _bcm_esw_global_meter_cleanup(unit); 11326 LOG_ERROR(BSL_LS_BCM_POLICER, 11327 (BSL_META_U(unit, 11328 "Unable to allocate memory for policer bookkeep " 11329 "data structure\n"))); 11330 return (BCM_E_MEMORY); 11331 } 11332 /* Allocate horizontal allocation management data structure */ 11333 _GLOBAL_METER_XGS3_ALLOC(global_meter_hz_alloc_bookkeep[unit], 11334 size_pool * sizeof(_global_meter_horizontal_alloc_t), 11335 "Global meter horizontal alloc"); 11336 if (NULL == global_meter_hz_alloc_bookkeep[unit]) { 11337 _bcm_esw_global_meter_cleanup(unit); 11338 LOG_ERROR(BSL_LS_BCM_POLICER, 11339 (BSL_META_U(unit, 11340 "Unable to allocate memory for hz alloc bookkeep " 11341 "data structure\n"))); 11342 return (BCM_E_MEMORY); 11343 } 11344 11345 for (index = 0; index < size_pool; index++) { 11346 global_meter_hz_alloc_bookkeep[unit][index].alloc_bit_map = 0xff; 11347 } 11348 11349 /* Allocate meter action management data structure */ 11350 _GLOBAL_METER_XGS3_ALLOC(global_meter_action_bookkeep[unit], 11351 action_size * sizeof(bcm_policer_global_meter_action_bookkeep_t), 11352 "Global meter action alloc"); 11353 if (NULL == global_meter_action_bookkeep[unit]) { 11354 _bcm_esw_global_meter_cleanup(unit); 11355 LOG_ERROR(BSL_LS_BCM_POLICER, 11356 (BSL_META_U(unit, 11357 "Unable to allocate memory for meter action bookkeep " 11358 "data structure\n"))); 11359 return (BCM_E_MEMORY); 11360 } 11361 if (global_meter_mutex[unit] == NULL) { 11362 global_meter_mutex[unit] = sal_mutex_create("Global meter mutex"); 11363 if (global_meter_mutex[unit] == NULL) { 11364 _bcm_esw_global_meter_cleanup(unit); 11365 LOG_ERROR(BSL_LS_BCM_POLICER, 11366 (BSL_META_U(unit, 11367 "Unable to create mutex\n"))); 11368 return BCM_E_MEMORY; 11369 } 11370 } 11371 11372 /* Index management for meter action */ 11373 if ( NULL != meter_action_list_handle[unit]) { 11374 shr_aidxres_list_destroy(meter_action_list_handle[unit]); 11375 meter_action_list_handle[unit] = NULL; 11376 } 11377 /* Create it */ 11378 if (shr_aidxres_list_create( 11379 &meter_action_list_handle[unit], 11380 0,(action_size - 1), 11381 0,(action_size - 1), 11382 8, 11383 "global_meter_action") != BCM_E_NONE) { 11384 _bcm_esw_global_meter_cleanup(unit); 11385 LOG_ERROR(BSL_LS_BCM_POLICER, 11386 (BSL_META_U(unit, 11387 "Couldn't create alligned list " 11388 "for global meter action\n"))); 11389 return BCM_E_INTERNAL; 11390 } 11391 /* Reserve the first entry in action table */ 11392 rv = shr_aidxres_list_reserve_block( 11393 meter_action_list_handle[unit],0,1); 11394 if (BCM_FAILURE(rv)) { 11395 _bcm_esw_global_meter_cleanup(unit); 11396 LOG_ERROR(BSL_LS_BCM_POLICER, 11397 (BSL_META_U(unit, 11398 "Not able to reserve first entry " 11399 "in action table\n"))); 11400 return (rv); 11401 } 11402 11403 block_factor = _shr_popcount(size_bank - 1) - 1; 11404 11405 /* Index management for policer */ 11406 for (pool_id = 0; pool_id < num_pools; pool_id++) { 11407 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) { 11408 handle_id = pool_id * num_banks_per_pool + bank_id; 11409 if ( NULL != meter_alloc_list_handle[unit][handle_id]) { 11410 shr_aidxres_list_destroy( 11411 meter_alloc_list_handle[unit][handle_id]); 11412 meter_alloc_list_handle[unit][handle_id] = NULL; 11413 } 11414 /* Create it */ 11415 if (shr_aidxres_list_create( 11416 &meter_alloc_list_handle[unit][handle_id], 11417 0, (size_bank - 1), 0, (size_bank - 1), 11418 block_factor, "global_meter_policer") != BCM_E_NONE) 11419 { 11420 _bcm_esw_global_meter_cleanup(unit); 11421 LOG_ERROR(BSL_LS_BCM_POLICER, 11422 (BSL_META_U(unit, 11423 "Couldn't create alligned list for " 11424 "global meter policer\n"))); 11425 return BCM_E_INTERNAL; 11426 } 11427 } 11428 } 11429 11430 /* 11431 * When SVC_METER_INDEX=0 in source tables it is treated as Disabled. 11432 * A value of 0 for SVC_METER_INDEXf is pointed to (Pool=0, Index=0) in 11433 * SVM_METER_TABLE table as per implementation. Here, reserve the first 11434 * entry in policer table so that user is not allotted this index. All 11435 * other indices in the table is valid and can be used by user. 11436 */ 11437 pool_id = 0; 11438 handle_id = 0; 11439 rv = shr_aidxres_list_reserve_block( 11440 meter_alloc_list_handle[unit][handle_id], 0, 1); 11441 if (BCM_FAILURE(rv)) { 11442 _bcm_esw_global_meter_cleanup(unit); 11443 LOG_ERROR(BSL_LS_BCM_POLICER, 11444 (BSL_META_U(unit, 11445 "Not able to reserve first entry " 11446 "in policer table\n"))); 11447 return (rv); 11448 } 11449 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool_id, 0); 11450 if (!BCM_SUCCESS(rv)) { 11451 rv = shr_aidxres_list_free(meter_alloc_list_handle[unit]\ 11452 [handle_id], 0); 11453 if (!BCM_SUCCESS(rv)) { 11454 _bcm_esw_global_meter_cleanup(unit); 11455 LOG_DEBUG(BSL_LS_BCM_POLICER, 11456 (BSL_META_U(unit, 11457 "Not able to reserve first entry " 11458 "in policer table\n"))); 11459 return BCM_E_INTERNAL; 11460 } 11461 } 11462 #ifdef BCM_APACHE_SUPPORT 11463 if (SOC_IS_APACHE(unit)) { 11464 rv = _bcm_svm_dbg_clr_tr_tbls(unit); 11465 if (BCM_FAILURE(rv)) { 11466 LOG_DEBUG(BSL_LS_BCM_POLICER, 11467 (BSL_META_U(unit, 11468 "Failed to set color truth table\n"))); 11469 return rv; 11470 } 11471 } 11472 #endif /* BCM_APACHE_SUPPORT */ 11473 11474 #ifdef BCM_WARM_BOOT_SUPPORT 11475 if (SOC_WARM_BOOT(unit)) { 11476 rv = _bcm_esw_global_meter_reinit(unit); 11477 if (!BCM_SUCCESS(rv)) { 11478 _bcm_esw_global_meter_cleanup(unit); 11479 LOG_ERROR(BSL_LS_BCM_POLICER, 11480 (BSL_META_U(unit, 11481 "Warm boot init failed\n"))); 11482 return BCM_E_INTERNAL; 11483 } 11484 } else { /* cold boot */ 11485 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 11486 11487 BCM_IF_ERROR_RETURN( 11488 _bcm_esw_svc_meter_wb_size_calc(unit, &size)); 11489 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 11490 size, &policer_state, 11491 BCM_WB_DEFAULT_VERSION, NULL); 11492 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 11493 LOG_DEBUG(BSL_LS_BCM_POLICER, 11494 (BSL_META_U(unit, 11495 "Scache Memory not available\n"))); 11496 return rv; 11497 } 11498 rv = BCM_E_NONE; 11499 } 11500 #endif 11501 global_meter_status[unit].initialised = 1; 11502 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11503 (BSL_META_U(unit, 11504 "GLOBAL METER FEATURE initialised\n"))); 11505 /* coverity[result_independent_of_operands] */ 11506 arb_reg = (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2_64r) ? 11507 AUX_ARB_CONTROL_2_64r : AUX_ARB_CONTROL_2r); 11508 11509 if (SOC_IS_TRIUMPH3(unit)) { 11510 fields[0] = SVC_MTR_REFRESH_ENABLEf; 11511 no_fields = 1; 11512 } else { 11513 fields[0] = SVM_MASTER_REFRESH_RATEf; 11514 fields[1] = SVM_MASTER_REFRESH_ENABLEf; 11515 no_fields = 2; 11516 } 11517 11518 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit,arb_reg,REG_PORT_ANY,\ 11519 no_fields,fields,vals)); 11520 11521 return rv; 11522 } 11523 11524 /* 11525 * Function: 11526 * _bcm_esw_is_global_policer 11527 * Purpose: 11528 * Validate the given policer id 11529 * Parameters: 11530 * Unit - (IN) unit number 11531 * policer - (IN) policer Id 11532 * is_global_policer - (OUT) is globle policer or not 11533 * Returns: 11534 * BCM_E_XXX 11535 */ 11536 int _bcm_esw_is_global_policer( 11537 int unit, 11538 bcm_policer_t policer_id, 11539 int *is_global_policer) 11540 { 11541 POL_CHECK_NULL_PARAMETER(unit, is_global_policer); 11542 *is_global_policer = FALSE; 11543 11544 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11545 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11546 int rv = bcmi_policer_mode_id_validate(unit, 11547 POLICER_ID_MODE_ID_GET(policer_id)); 11548 if (BCM_SUCCESS(rv)) { 11549 *is_global_policer = TRUE; 11550 } else { 11551 *is_global_policer = FALSE; 11552 } 11553 } 11554 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11555 11556 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 11557 defined(BCM_APACHE_SUPPORT) 11558 if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) { 11559 int offset_mode; 11560 offset_mode = ((policer_id & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11561 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11562 *is_global_policer = (offset_mode) ? TRUE : FALSE ; 11563 } 11564 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 11565 BCM_APACHE_SUPPORT */ 11566 11567 return BCM_E_NONE; 11568 } 11569 11570 /* 11571 * Function: 11572 * _bcm_esw_policer_validate 11573 * Purpose: 11574 * Validate the given policer id 11575 * Parameters: 11576 * Unit - (IN) unit number 11577 * policer - (IN) policer Id 11578 * Returns: 11579 * BCM_E_XXX 11580 */ 11581 int _bcm_esw_policer_validate(int unit, bcm_policer_t *policer) 11582 { 11583 int rv = BCM_E_NONE; 11584 int index = 0; 11585 uint32 offset_mode = 0; 11586 11587 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11588 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11589 POL_CHECK_NULL_PARAMETER(unit, policer); 11590 return bcmi_esw_policer_validate(unit, *policer); 11591 } 11592 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11593 11594 if( *policer == 0) { 11595 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11596 (BSL_META_U(unit, 11597 "Policer id passed is 0 \n"))); 11598 return rv; 11599 } 11600 _bcm_esw_get_policer_table_index(unit, *policer, &index); 11601 if (index > (soc_mem_index_max(unit, SVM_METER_TABLEm))) 11602 { 11603 LOG_DEBUG(BSL_LS_BCM_POLICER, 11604 (BSL_META_U(unit, 11605 "Invalid table index for SVM_POLICY_TABLE\n"))); 11606 return BCM_E_PARAM; 11607 } 11608 offset_mode = ((*policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11609 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11610 if (offset_mode >= 1) { 11611 offset_mode = offset_mode - 1; 11612 } 11613 if (offset_mode > BCM_POLICER_SVC_METER_MAX_MODE) 11614 { 11615 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11616 (BSL_META_U(unit, 11617 "Invalid Offset mode \n"))); 11618 return BCM_E_PARAM; 11619 11620 } 11621 return rv; 11622 } 11623 11624 /* 11625 * Function: 11626 * _bcm_global_meter_macro_policer_validate 11627 * Purpose: 11628 * Validate if given policer is configured in the system and 11629 * qualify as MACRO policer 11630 * Parameters: 11631 * unit - (IN) unit number 11632 * policer - (IN) policer Id 11633 * Returns: 11634 * BCM_E_NONE 11635 * BCM_E_CONFIG 11636 * BCM_E_NOT_FOUND 11637 */ 11638 STATIC int 11639 _bcm_global_meter_macro_policer_validate(int unit, bcm_policer_t policer) 11640 { 11641 int rv = BCM_E_NONE; 11642 uint32 offset_mode = 0; 11643 _global_meter_policer_control_t *policer_control = NULL; 11644 11645 rv = _bcm_global_meter_policer_get(unit, policer, &policer_control); 11646 if ((rv != BCM_E_NONE) || (policer_control == NULL)) { 11647 return BCM_E_NOT_FOUND; 11648 } 11649 offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11650 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11651 11652 /* Validate policer control */ 11653 if ((offset_mode > 1) || 11654 (policer_control->no_of_policers != 1) || 11655 (policer_control->grp_mode != bcmPolicerGroupModeSingle) || 11656 (policer_control->direction != GLOBAL_METER_ALLOC_VERTICAL)) { 11657 rv = BCM_E_CONFIG; 11658 } 11659 return rv; 11660 } 11661 11662 /* 11663 * Function: 11664 * _bcm_esw_policer_increment_ref_count 11665 * Purpose: 11666 * Increment the policer usage reference count 11667 * Parameters: 11668 * unit - (IN) unit number 11669 * policer - (IN) policer Id 11670 * Returns: 11671 * BCM_E_XXX 11672 */ 11673 int _bcm_esw_policer_increment_ref_count(int unit, bcm_policer_t policer) 11674 { 11675 int rv = BCM_E_NONE; 11676 int offset_mode = 0; 11677 _global_meter_policer_control_t *policer_control = NULL; 11678 11679 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11680 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11681 return bcmi_esw_policer_increment_ref_count(unit, policer); 11682 } 11683 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11684 11685 /* validate policer id */ 11686 rv = _bcm_esw_policer_validate(unit, &policer); 11687 if (BCM_FAILURE(rv)) { 11688 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11689 (BSL_META_U(unit, 11690 "Invalid policer id passed: %x \n"), 11691 policer)); 11692 return (rv); 11693 } 11694 offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11695 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11696 if (offset_mode >= 1) { 11697 offset_mode = offset_mode - 1; 11698 } 11699 GLOBAL_METER_LOCK(unit); 11700 if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v == 11701 cascade_mode) || 11702 (global_meter_offset_mode[unit][offset_mode].type == 11703 bcmPolicerGroupModeTypeCascade) || 11704 (global_meter_offset_mode[unit][offset_mode].type == 11705 bcmPolicerGroupModeTypeCascadeWithCoupling)) { 11706 /* 11707 * SDK alway allocates 8 policer IDs in cascaded mode, 11708 * and each policer is configurable for the purpose of 11709 * bandwidth sharing. 11710 */ 11711 rv = _bcm_global_meter_policer_get(unit, policer, &policer_control); 11712 } else { 11713 rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control); 11714 } 11715 if (BCM_FAILURE(rv)) { 11716 GLOBAL_METER_UNLOCK(unit); 11717 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11718 (BSL_META_U(unit, 11719 "Unable to get policer control for policer " 11720 "id %d\n"), policer)); 11721 return (rv); 11722 } 11723 policer_control->ref_count++; 11724 GLOBAL_METER_UNLOCK(unit); 11725 return rv; 11726 } 11727 11728 /* 11729 * Function: 11730 * _bcm_esw_policer_decrement_ref_count 11731 * Purpose: 11732 * Decrement the policer usage refernce count 11733 * Parameters: 11734 * unit - (IN) unit number 11735 * policer - (IN) policer Id 11736 * Returns: 11737 * BCM_E_XXX 11738 */ 11739 int _bcm_esw_policer_decrement_ref_count(int unit, bcm_policer_t policer) 11740 { 11741 int rv = BCM_E_NONE; 11742 int offset_mode = 0; 11743 _global_meter_policer_control_t *policer_control = NULL; 11744 11745 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11746 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11747 return bcmi_esw_policer_decrement_ref_count(unit, policer); 11748 } 11749 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11750 11751 /* validate policer id */ 11752 rv = _bcm_esw_policer_validate(unit, &policer); 11753 if (BCM_FAILURE(rv)) { 11754 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11755 (BSL_META_U(unit, 11756 "Invalid policer id passed: %x \n"), 11757 policer)); 11758 return (rv); 11759 } 11760 offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11761 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11762 if (offset_mode >= 1) { 11763 offset_mode = offset_mode - 1; 11764 } 11765 GLOBAL_METER_LOCK(unit); 11766 if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v == 11767 cascade_mode) || 11768 (global_meter_offset_mode[unit][offset_mode].type == 11769 bcmPolicerGroupModeTypeCascade) || 11770 (global_meter_offset_mode[unit][offset_mode].type == 11771 bcmPolicerGroupModeTypeCascadeWithCoupling)) { 11772 /* 11773 * SDK alway allocates 8 policer IDs in cascaded mode, 11774 * and each policer is configurable for the purpose of 11775 * bandwidth sharing. 11776 */ 11777 rv = _bcm_global_meter_policer_get(unit, policer, &policer_control); 11778 } else { 11779 rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control); 11780 } 11781 if (BCM_FAILURE(rv)) { 11782 GLOBAL_METER_UNLOCK(unit); 11783 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11784 (BSL_META_U(unit, 11785 "Unable to get policer control for policer " 11786 "id %d\n"), policer)); 11787 return (rv); 11788 } 11789 if (policer_control->ref_count > 0) { 11790 policer_control->ref_count--; 11791 } 11792 GLOBAL_METER_UNLOCK(unit); 11793 return rv; 11794 } 11795 11796 /* 11797 * Function: 11798 * _bcm_policer_svm_source_index_get 11799 * Purpose: 11800 * Get the Enum value corresponding to memory table 11801 * Parameters: 11802 * unit - (IN) unit number 11803 * table - (IN) Memory table 11804 * mem_index - (OUT) Corresponding Enum 11805 * in _bcm_policer_svm_source_type_t 11806 * Returns: 11807 * BCM_E_XXX 11808 */ 11809 bcm_error_t 11810 _bcm_policer_svm_source_index_get(int unit, soc_mem_t table, 11811 _bcm_policer_svm_source_type_t *mem_index) 11812 { 11813 switch (table) { 11814 case PORT_TABm: 11815 *mem_index = _BCM_SVM_MEM_PORT; 11816 break; 11817 case VLAN_TABm: 11818 *mem_index = _BCM_SVM_MEM_VLAN; 11819 break; 11820 case VFIm: 11821 *mem_index = _BCM_SVM_MEM_VFI; 11822 break; 11823 case SOURCE_VPm: 11824 *mem_index = _BCM_SVM_MEM_SOURCE_VP; 11825 break; 11826 #ifdef BCM_TRIUMPH3_SUPPORT 11827 case VLAN_XLATE_EXTDm: 11828 /* passthru */ 11829 /* coverity[fallthrough: FALSE] */ 11830 #endif 11831 case VLAN_XLATEm: 11832 *mem_index = _BCM_SVM_MEM_VLAN_XLATE; 11833 break; 11834 case VFP_POLICY_TABLEm : 11835 *mem_index = _BCM_SVM_MEM_VFP_POLICY_TABLE; 11836 break; 11837 default : 11838 return BCM_E_INTERNAL; 11839 } 11840 return BCM_E_NONE; 11841 } 11842 11843 /* 11844 * Function: 11845 * _bcm_esw_add_policer_to_table 11846 * Purpose: 11847 * Add policer id to the table entry specified 11848 * Parameters: 11849 * unit - (IN) unit number 11850 * policer - (IN) policer Id 11851 * table - (IN) Table to which the entry needs to be added 11852 * index - (IN) index in the table 11853 * data - (IN) Data to be written 11854 * Returns: 11855 * BCM_E_XXX 11856 */ 11857 int _bcm_esw_add_policer_to_table(int unit,bcm_policer_t policer, 11858 soc_mem_t table, int index, void *data) 11859 { 11860 int offset_mode = 0; 11861 int rv = BCM_E_NONE; 11862 bcm_policer_t current_policer = 0; 11863 _bcm_policer_svm_source_type_t mem_index = 0; 11864 11865 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11866 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11867 return bcmi_esw_add_policer_to_table(unit, 11868 policer, table, index, data); 11869 } 11870 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11871 11872 if (soc_feature(unit, soc_feature_global_meter)) { 11873 /* validate policer id */ 11874 rv = _bcm_esw_policer_validate(unit, &policer); 11875 if (BCM_FAILURE(rv)) { 11876 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11877 (BSL_META_U(unit, 11878 "Invalid policer id passed: %x \n"), 11879 policer)); 11880 return (rv); 11881 } 11882 rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index); 11883 if (BCM_FAILURE(rv)) { 11884 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11885 (BSL_META_U(unit, 11886 "Unable to read the table entry %d at " 11887 "index %d \n"), table, index)); 11888 return (rv); 11889 } 11890 /* updating VFP_POLICY_TABLEm is handled in field module */ 11891 if (mem_index != _BCM_SVM_MEM_VFP_POLICY_TABLE) { 11892 if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) { 11893 return BCM_E_INTERNAL; 11894 } 11895 rv = _bcm_esw_get_policer_from_table(unit, table, index, data, 11896 ¤t_policer, 1); 11897 if (BCM_FAILURE(rv)) { 11898 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11899 (BSL_META_U(unit, 11900 "Unable to read the table entry %d at " 11901 "index %d \n"), table, index)); 11902 return (rv); 11903 } 11904 if (policer == current_policer) { 11905 /* Nothing to do */ 11906 return BCM_E_NONE; 11907 } 11908 /* Set policer id */ 11909 if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 11910 offset_mode = 11911 ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 11912 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 11913 if (offset_mode >= 1) { 11914 offset_mode = offset_mode - 1; 11915 } 11916 if (offset_mode >= 11917 (soc_mem_index_count(unit,SVM_OFFSET_TABLEm) >> 11918 BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE)) { 11919 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11920 (BSL_META_U(unit, 11921 "Offset mode for the policer " 11922 "exceeds max allowed value \n"))); 11923 return BCM_E_PARAM; 11924 } 11925 _bcm_esw_get_policer_table_index(unit, policer, &index); 11926 } else { 11927 index = 0; 11928 offset_mode = 0; 11929 } 11930 if (index >= soc_mem_index_count(unit, SVM_METER_TABLEm)) { 11931 LOG_VERBOSE(BSL_LS_BCM_POLICER, 11932 (BSL_META_U(unit, 11933 "Invalid table index passed for " 11934 "SVM_METER_TABLE\n"))); 11935 return BCM_E_PARAM; 11936 } 11937 soc_mem_field32_set(unit,table, data, 11938 BCM_SVM_SOURCE(unit, mem_index).offset_mode, offset_mode); 11939 soc_mem_field32_set(unit,table, data, 11940 BCM_SVM_SOURCE(unit, mem_index).meter_index, index); 11941 11942 } 11943 /* decrement current policer if any */ 11944 if ((current_policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 11945 rv = _bcm_esw_policer_decrement_ref_count(unit, current_policer); 11946 BCM_IF_ERROR_RETURN(rv); 11947 } 11948 /* increment new policer */ 11949 if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 11950 rv = _bcm_esw_policer_increment_ref_count(unit, policer); 11951 BCM_IF_ERROR_RETURN(rv); 11952 } 11953 } 11954 return rv; 11955 } 11956 11957 /* 11958 * Function: 11959 * _bcm_esw_policer_offset_mode_get 11960 * Purpose: 11961 * Get the offset_mode with given a policer id. 11962 * Parameters: 11963 * Unit - (IN) unit number 11964 * policer_id - (IN) policer Id 11965 * offset_mode - (OUT) HW policer index 11966 * Returns: 11967 * BCM_E_XXX 11968 */ 11969 int 11970 _bcm_esw_policer_offset_mode_get( 11971 int unit, 11972 bcm_policer_t policer_id, 11973 int *offset_mode) 11974 { 11975 int rv = BCM_E_UNAVAIL; 11976 11977 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 11978 if (soc_feature(unit, soc_feature_global_meter_v2)) { 11979 return bcmi_esw_policer_offset_mode_get(unit, 11980 policer_id, offset_mode); 11981 } 11982 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 11983 return rv; 11984 } 11985 11986 /* 11987 * Function: 11988 * _bcm_esw_get_policer_from_table 11989 * Purpose: 11990 * Read the policer id configured in the given table 11991 * Parameters: 11992 * unit - (IN) unit number 11993 * table - (IN) Table from which the entry needs to be got 11994 * index - (IN) index in the table 11995 * data - (IN) Data to be written 11996 * policer - (OUT) policer Id 11997 * skip_read - (IN) Skip reading the policer entry 11998 * Returns: 11999 * BCM_E_XXX 12000 */ 12001 int _bcm_esw_get_policer_from_table(int unit, soc_mem_t table, int index, 12002 void *data, bcm_policer_t *policer, 12003 int skip_read) 12004 { 12005 int rv = BCM_E_NONE; 12006 int offset = 0; 12007 _bcm_policer_svm_source_type_t mem_index; 12008 12009 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12010 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12011 return bcmi_esw_get_policer_from_table(unit, 12012 table, index, data, policer, skip_read); 12013 } 12014 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12015 12016 if (soc_feature(unit, soc_feature_global_meter)) { 12017 12018 if (!global_meter_status[unit].initialised && SOC_WARM_BOOT(unit)) { 12019 return rv; 12020 } 12021 if (!skip_read) { 12022 rv = soc_mem_read(unit, table, MEM_BLOCK_ANY, index, data); 12023 BCM_IF_ERROR_RETURN(rv); 12024 } 12025 if (table == SVM_MACROFLOW_INDEX_TABLEm) { 12026 if (SOC_MEM_FIELD_VALID(unit, table, MACROFLOW_INDEXf)) { 12027 index = soc_mem_field32_get(unit, table, data, 12028 MACROFLOW_INDEXf); 12029 } 12030 } else { 12031 rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index); 12032 if (BCM_FAILURE(rv)) { 12033 LOG_VERBOSE(BSL_LS_BCM_POLICER, 12034 (BSL_META_U(unit, 12035 "Unable to read the table entry %d at " 12036 "index %d \n"), table, index)); 12037 return (rv); 12038 } 12039 if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) { 12040 return BCM_E_INTERNAL; 12041 } 12042 offset = soc_mem_field32_get(unit, table, data, 12043 BCM_SVM_SOURCE(unit,mem_index).offset_mode); 12044 index = soc_mem_field32_get(unit, table, data, 12045 BCM_SVM_SOURCE(unit,mem_index).meter_index); 12046 } 12047 _bcm_esw_get_policer_id_from_index_offset(unit, index, 12048 offset, policer); 12049 } else { 12050 return BCM_E_UNAVAIL; 12051 } 12052 return rv; 12053 } 12054 12055 /* 12056 * Function: 12057 * _bcm_esw_reset_policer_from_table 12058 * Purpose: 12059 * Remove the policer id configured from a table and re-adjust 12060 * policer usage reference count. 12061 * Parameters: 12062 * unit - (IN) unit number 12063 * policer - (IN) policer Id 12064 * table - (IN) Table in which an entry needs to be reset 12065 * index - (IN) index in the table 12066 * data - (IN) Data to be written 12067 * Returns: 12068 * BCM_E_XXX 12069 */ 12070 int _bcm_esw_reset_policer_from_table(int unit, bcm_policer_t policer, 12071 int table, int index, void *data) 12072 { 12073 12074 int rv = BCM_E_NONE; 12075 rv = _bcm_esw_delete_policer_from_table(unit, policer, table, index, data); 12076 if (BCM_FAILURE(rv)) { 12077 LOG_DEBUG(BSL_LS_BCM_POLICER, 12078 (BSL_META_U(unit, 12079 "Unable to delete policer from table %d at " 12080 "index %d \n"), table, index)); 12081 return (rv); 12082 } 12083 rv = soc_mem_write(unit, table, MEM_BLOCK_ANY, index, data); 12084 return rv; 12085 } 12086 12087 /* 12088 * Function: 12089 * _bcm_esw_delete_policer_from_table 12090 * Purpose: 12091 * Remove the policer id configured from a table and re-adjust 12092 * policer usage reference count 12093 * Parameters: 12094 * unit - (IN) unit number 12095 * policer - (IN) policer Id 12096 * table - (IN) Table in which an entry needs to be deleted 12097 * index - (IN) index in the table 12098 * data - (IN) Data to be written 12099 * Returns: 12100 * BCM_E_XXX 12101 */ 12102 int _bcm_esw_delete_policer_from_table(int unit, bcm_policer_t policer, 12103 soc_mem_t table, int index, void *data) 12104 { 12105 int rv = BCM_E_NONE; 12106 bcm_policer_t current_policer = 0; 12107 int offset_mode = 0; 12108 _bcm_policer_svm_source_type_t mem_index; 12109 12110 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12111 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12112 return bcmi_esw_delete_policer_from_table(unit, 12113 policer, table, index, data); 12114 } 12115 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12116 12117 if (soc_feature(unit, soc_feature_global_meter)) { 12118 /* validate policer id */ 12119 rv = _bcm_esw_policer_validate(unit, &policer); 12120 if (BCM_FAILURE(rv)) { 12121 LOG_DEBUG(BSL_LS_BCM_POLICER, 12122 (BSL_META_U(unit, 12123 "Invalid policer id passed: %x \n"), 12124 policer)); 12125 return (rv); 12126 } 12127 rv = _bcm_policer_svm_source_index_get(unit, table, &mem_index); 12128 if (BCM_FAILURE(rv)) { 12129 LOG_VERBOSE(BSL_LS_BCM_POLICER, 12130 (BSL_META_U(unit, 12131 "Unable to read the table entry %d at " 12132 "index %d \n"), table, index)); 12133 return (rv); 12134 } 12135 /* Deleting VFP_POLICY_TABLEm is handled in field module */ 12136 if (mem_index != _BCM_SVM_MEM_VFP_POLICY_TABLE) { 12137 if (BCM_SVM_SOURCE(unit, mem_index).table == INVALIDm) { 12138 return BCM_E_INTERNAL; 12139 } 12140 rv = _bcm_esw_get_policer_from_table(unit, table, index, data, 12141 ¤t_policer, 0); 12142 if (BCM_FAILURE(rv)) { 12143 LOG_DEBUG(BSL_LS_BCM_POLICER, 12144 (BSL_META_U(unit, 12145 "Unable to read the policer from table " 12146 "%d at index %d\n"), table, index)); 12147 return (rv); 12148 } 12149 if (current_policer != policer) { 12150 LOG_DEBUG(BSL_LS_BCM_POLICER, 12151 (BSL_META_U(unit, 12152 "Policer Id passed is different from the " 12153 "one that is configured in the table. configured value is \ 12154 %d \n"), current_policer)); 12155 return BCM_E_INTERNAL; 12156 } 12157 offset_mode = index = 0; 12158 soc_mem_field32_set(unit,table, data, 12159 BCM_SVM_SOURCE(unit, mem_index).offset_mode, offset_mode); 12160 soc_mem_field32_set(unit,table, data, 12161 BCM_SVM_SOURCE(unit, mem_index).meter_index, index); 12162 } 12163 /* decrement current policer if any */ 12164 if ((policer & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 12165 rv = _bcm_esw_policer_decrement_ref_count(unit, policer); 12166 BCM_IF_ERROR_RETURN(rv); 12167 } 12168 } 12169 return rv; 12170 } 12171 12172 /* 12173 * Function: 12174 * _bcm_policer_svc_meter_get_mode_info 12175 * Purpose: 12176 * Get the info related to a configured offset mode 12177 * Parameters: 12178 * unit - (IN) unit number 12179 * meter_mode_v - (IN) Meter offset mode 12180 * mode_info - (OUT) Info of the configured mode 12181 * Returns: 12182 * BCM_E_XXX 12183 */ 12184 12185 bcm_error_t _bcm_policer_svc_meter_get_mode_info( 12186 int unit, 12187 bcm_policer_svc_meter_mode_t meter_mode_v, 12188 bcm_policer_svc_meter_bookkeep_mode_t *mode_info 12189 ) 12190 { 12191 if (!((meter_mode_v >= 1) && 12192 (meter_mode_v < BCM_POLICER_SVC_METER_MAX_MODE))) { 12193 LOG_DEBUG(BSL_LS_BCM_POLICER, 12194 (BSL_META_U(unit, 12195 "Invalid offset mode %d \n"), meter_mode_v)); 12196 return BCM_E_PARAM; 12197 } 12198 if (global_meter_offset_mode[unit][meter_mode_v].used == 0) { 12199 LOG_DEBUG(BSL_LS_BCM_POLICER, 12200 (BSL_META_U(unit, 12201 "Passed mode is not used \n"))); 12202 return BCM_E_NOT_FOUND; 12203 } 12204 *mode_info = global_meter_offset_mode[unit][meter_mode_v]; 12205 return BCM_E_NONE; 12206 } 12207 12208 12209 /* ACTION API's */ 12210 12211 /* 12212 * Function: 12213 * bcm_esw_policer_action_create 12214 * Purpose: 12215 * Create a new action entry in meter action table 12216 * Parameters: 12217 * unit - (IN) unit number 12218 * action_id - (OUT) Action Id created 12219 * Returns: 12220 * BCM_E_XXX 12221 */ 12222 int bcm_esw_policer_action_create( 12223 int unit, 12224 uint32 *action_id) 12225 { 12226 int rv = BCM_E_NONE; 12227 12228 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12229 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12230 return bcmi_esw_policer_action_create(unit, action_id); 12231 } 12232 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12233 12234 if (!soc_feature(unit, soc_feature_global_meter)) { 12235 return BCM_E_UNAVAIL; 12236 } 12237 12238 if (action_id == NULL) { 12239 return (BCM_E_PARAM); 12240 } 12241 12242 CHECK_GLOBAL_METER_INIT(unit); 12243 rv = shr_aidxres_list_alloc_block( 12244 meter_action_list_handle[unit], 1, (uint32 *)action_id); 12245 if (BCM_FAILURE(rv)) { 12246 LOG_ERROR(BSL_LS_BCM_POLICER, 12247 (BSL_META_U(unit, 12248 "Unable to allocate a handle for new " 12249 "action\n"))); 12250 return (rv); 12251 } 12252 global_meter_action_bookkeep[unit][*action_id].used = 1; 12253 return rv; 12254 } 12255 12256 /* 12257 * Function: 12258 * bcm_esw_policer_action_add 12259 * Purpose: 12260 * Add an entry to meter action table 12261 * Parameters: 12262 * unit - (IN) unit number 12263 * action_id - (IN) Action Id created 12264 * action - (IN) Action to be added 12265 * action_id - (IN) Parameter associated with action 12266 * Returns: 12267 * BCM_E_XXX 12268 */ 12269 int bcm_esw_policer_action_add( 12270 int unit, 12271 uint32 action_id, 12272 bcm_policer_action_t action, 12273 uint32 param0) 12274 { 12275 int rv = BCM_E_NONE; 12276 svm_policy_table_entry_t meter_action; 12277 uint32 green_action[1] = {0}, yellow_action[1] = {0}, red_action[1] = {0}; 12278 12279 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12280 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12281 return bcmi_esw_policer_action_add(unit, action_id, action, param0); 12282 } 12283 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12284 12285 if (!soc_feature(unit, soc_feature_global_meter)) { 12286 return BCM_E_UNAVAIL; 12287 } 12288 12289 if (global_meter_action_bookkeep[unit][action_id].used != 1) { 12290 LOG_DEBUG(BSL_LS_BCM_POLICER, 12291 (BSL_META_U(unit, 12292 "Action id is not created \n"))); 12293 return BCM_E_PARAM; 12294 } 12295 12296 GLOBAL_METER_LOCK(unit); 12297 /* read action table entry */ 12298 rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action); 12299 if (BCM_FAILURE(rv)) { 12300 GLOBAL_METER_UNLOCK(unit); 12301 LOG_DEBUG(BSL_LS_BCM_POLICER, 12302 (BSL_META_U(unit, 12303 "Unable to read SVM_POLICY_TABLE for given " 12304 "action id \n"))); 12305 return (rv); 12306 } 12307 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, G_ACTIONSf, 12308 &green_action[0]); 12309 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, Y_ACTIONSf, 12310 &yellow_action[0]); 12311 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, R_ACTIONSf, 12312 &red_action[0]); 12313 12314 12315 switch (action) { 12316 case bcmPolicerActionGpDrop : 12317 SHR_BITSET(green_action, 12318 BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS); 12319 break; 12320 12321 case bcmPolicerActionYpDrop : 12322 SHR_BITSET(yellow_action, 12323 BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS); 12324 break; 12325 12326 case bcmPolicerActionRpDrop : 12327 SHR_BITSET(red_action, 12328 BCM_POLICER_GLOBAL_METER_ACTION_DROP_BIT_POS); 12329 break; 12330 12331 case bcmPolicerActionGpEcnNew : 12332 if (param0 > 0x3) { 12333 GLOBAL_METER_UNLOCK(unit); 12334 LOG_ERROR(BSL_LS_BCM_POLICER, 12335 (BSL_META_U(unit, 12336 "Invalid value for ECN \n"))); 12337 return BCM_E_PARAM; 12338 } 12339 SHR_BITCLR_RANGE(green_action, 12340 BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2); 12341 green_action[0] = green_action[0] | 12342 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS); 12343 SHR_BITSET(green_action, 12344 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS); 12345 break; 12346 12347 case bcmPolicerActionYpEcnNew : 12348 if (param0 > 0x3) { 12349 GLOBAL_METER_UNLOCK(unit); 12350 LOG_ERROR(BSL_LS_BCM_POLICER, 12351 (BSL_META_U(unit, 12352 "Invalid value for ECN \n"))); 12353 return BCM_E_PARAM; 12354 } 12355 SHR_BITCLR_RANGE(yellow_action, 12356 BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2); 12357 yellow_action[0] = yellow_action[0] | 12358 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS); 12359 SHR_BITSET(yellow_action, 12360 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS); 12361 break; 12362 12363 case bcmPolicerActionRpEcnNew : 12364 if (param0 > 0x3) { 12365 GLOBAL_METER_UNLOCK(unit); 12366 LOG_ERROR(BSL_LS_BCM_POLICER, 12367 (BSL_META_U(unit, 12368 "Invalid value for ECN \n"))); 12369 return BCM_E_PARAM; 12370 } 12371 SHR_BITCLR_RANGE(red_action, 12372 BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS, 2); 12373 red_action[0] = red_action[0] | 12374 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_ECN_BIT_POS); 12375 SHR_BITSET(red_action, 12376 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_ECN_BIT_POS); 12377 break; 12378 12379 case bcmPolicerActionGpCngNew : 12380 if (param0 > 0x3) { 12381 GLOBAL_METER_UNLOCK(unit); 12382 LOG_ERROR(BSL_LS_BCM_POLICER, 12383 (BSL_META_U(unit, 12384 "Invalid value for CNG \n"))); 12385 return BCM_E_PARAM; 12386 } 12387 SHR_BITCLR_RANGE(green_action, 12388 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2); 12389 green_action[0] = green_action[0] | 12390 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS); 12391 break; 12392 12393 case bcmPolicerActionYpCngNew : 12394 if (param0 > 0x3) { 12395 GLOBAL_METER_UNLOCK(unit); 12396 LOG_ERROR(BSL_LS_BCM_POLICER, 12397 (BSL_META_U(unit, 12398 "Invalid value for CNG \n"))); 12399 return BCM_E_PARAM; 12400 } 12401 SHR_BITCLR_RANGE(yellow_action, 12402 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2); 12403 yellow_action[0] = yellow_action[0] | 12404 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS); 12405 break; 12406 12407 case bcmPolicerActionRpCngNew : 12408 if (param0 > 0x3) { 12409 GLOBAL_METER_UNLOCK(unit); 12410 LOG_ERROR(BSL_LS_BCM_POLICER, 12411 (BSL_META_U(unit, 12412 "Invalid value for CNG \n"))); 12413 return BCM_E_PARAM; 12414 } 12415 SHR_BITCLR_RANGE(red_action, 12416 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS, 2); 12417 red_action[0] = red_action[0] | 12418 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS); 12419 break; 12420 12421 case bcmPolicerActionGpDscpNew: 12422 if (param0 > 0x3f) { 12423 GLOBAL_METER_UNLOCK(unit); 12424 LOG_ERROR(BSL_LS_BCM_POLICER, 12425 (BSL_META_U(unit, 12426 "Invalid value for DSCP \n"))); 12427 return BCM_E_PARAM; 12428 } 12429 SHR_BITCLR_RANGE(green_action, 12430 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6); 12431 green_action[0] = green_action[0] | 12432 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS); 12433 SHR_BITSET(green_action, 12434 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS); 12435 break; 12436 12437 case bcmPolicerActionYpDscpNew: 12438 if (param0 > 0x3f) { 12439 GLOBAL_METER_UNLOCK(unit); 12440 LOG_ERROR(BSL_LS_BCM_POLICER, 12441 (BSL_META_U(unit, 12442 "Invalid value for DSCP \n"))); 12443 return BCM_E_PARAM; 12444 } 12445 SHR_BITCLR_RANGE(yellow_action, 12446 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6); 12447 yellow_action[0] = yellow_action[0] | 12448 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS); 12449 SHR_BITSET(yellow_action, 12450 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS); 12451 break; 12452 12453 case bcmPolicerActionRpDscpNew: 12454 if (param0 > 0x3f) { 12455 GLOBAL_METER_UNLOCK(unit); 12456 LOG_ERROR(BSL_LS_BCM_POLICER, 12457 (BSL_META_U(unit, 12458 "Invalid value for DSCP \n"))); 12459 return BCM_E_PARAM; 12460 } 12461 SHR_BITCLR_RANGE(red_action, 12462 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS, 6); 12463 red_action[0] = red_action[0] | 12464 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DSCP_BIT_POS); 12465 SHR_BITSET(red_action, 12466 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DSCP_BIT_POS); 12467 break; 12468 12469 case bcmPolicerActionGpPrioIntNew : 12470 if (param0 > 0xf) { 12471 GLOBAL_METER_UNLOCK(unit); 12472 LOG_ERROR(BSL_LS_BCM_POLICER, 12473 (BSL_META_U(unit, 12474 "Invalid value for int pri\n"))); 12475 return BCM_E_PARAM; 12476 } 12477 SHR_BITCLR_RANGE(green_action, 12478 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4); 12479 green_action[0] = green_action[0] | 12480 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS); 12481 SHR_BITSET(green_action, 12482 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS); 12483 break; 12484 12485 case bcmPolicerActionYpPrioIntNew : 12486 if (param0 > 0xf) { 12487 GLOBAL_METER_UNLOCK(unit); 12488 LOG_ERROR(BSL_LS_BCM_POLICER, 12489 (BSL_META_U(unit, 12490 "Invalid value for int pri\n"))); 12491 return BCM_E_PARAM; 12492 } 12493 SHR_BITCLR_RANGE(yellow_action, 12494 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4); 12495 yellow_action[0] = yellow_action[0] | 12496 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS); 12497 SHR_BITSET(yellow_action, 12498 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS); 12499 break; 12500 12501 case bcmPolicerActionRpPrioIntNew : 12502 if (param0 > 0xf) { 12503 GLOBAL_METER_UNLOCK(unit); 12504 LOG_ERROR(BSL_LS_BCM_POLICER, 12505 (BSL_META_U(unit, 12506 "Invalid value for int pri\n"))); 12507 return BCM_E_PARAM; 12508 } 12509 SHR_BITCLR_RANGE(red_action, 12510 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS, 4); 12511 red_action[0] = red_action[0] | 12512 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS); 12513 SHR_BITSET(red_action, 12514 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_INT_PRI_BIT_POS); 12515 break; 12516 12517 12518 case bcmPolicerActionGpVlanPrioNew : 12519 if (param0 > 0x7) { 12520 GLOBAL_METER_UNLOCK(unit); 12521 LOG_ERROR(BSL_LS_BCM_POLICER, 12522 (BSL_META_U(unit, 12523 "Invalid value for vlan pri\n"))); 12524 return BCM_E_PARAM; 12525 } 12526 SHR_BITCLR_RANGE(green_action, 12527 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3); 12528 green_action[0] = green_action[0] | 12529 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS); 12530 SHR_BITSET(green_action, 12531 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS); 12532 break; 12533 12534 case bcmPolicerActionYpVlanPrioNew : 12535 if (param0 > 0x7) { 12536 GLOBAL_METER_UNLOCK(unit); 12537 LOG_ERROR(BSL_LS_BCM_POLICER, 12538 (BSL_META_U(unit, 12539 "Invalid value for vlan pri\n"))); 12540 return BCM_E_PARAM; 12541 } 12542 SHR_BITCLR_RANGE(yellow_action, 12543 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3); 12544 yellow_action[0] = yellow_action[0] | 12545 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS); 12546 SHR_BITSET(yellow_action, 12547 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS); 12548 break; 12549 12550 case bcmPolicerActionRpVlanPrioNew : 12551 if (param0 > 0x7) { 12552 GLOBAL_METER_UNLOCK(unit); 12553 LOG_ERROR(BSL_LS_BCM_POLICER, 12554 (BSL_META_U(unit, 12555 "Invalid value for vlan pri\n"))); 12556 return BCM_E_PARAM; 12557 } 12558 SHR_BITCLR_RANGE(red_action, 12559 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS, 3); 12560 red_action[0] = red_action[0] | 12561 (param0 << BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS); 12562 SHR_BITSET(red_action, 12563 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_DOT1P_BIT_POS); 12564 break; 12565 12566 default: 12567 GLOBAL_METER_UNLOCK(unit); 12568 LOG_ERROR(BSL_LS_BCM_POLICER, 12569 (BSL_META_U(unit, 12570 "Unsupported Action specified\n"))); 12571 return BCM_E_PARAM; 12572 } 12573 12574 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, G_ACTIONSf, 12575 &green_action[0]); 12576 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, Y_ACTIONSf, 12577 &yellow_action[0]); 12578 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, R_ACTIONSf, 12579 &red_action[0]); 12580 12581 rv = WRITE_SVM_POLICY_TABLEm(unit,MEM_BLOCK_ANY,action_id, &meter_action); 12582 if (BCM_FAILURE(rv)) { 12583 GLOBAL_METER_UNLOCK(unit); 12584 LOG_DEBUG(BSL_LS_BCM_POLICER, 12585 (BSL_META_U(unit, 12586 "Unable to write to SVM_POLICY_TABLE at location " 12587 "specified by action_id \n"))); 12588 return (rv); 12589 } 12590 GLOBAL_METER_UNLOCK(unit); 12591 return rv; 12592 } 12593 12594 /* 12595 * Function: 12596 * bcm_esw_policer_action_destroy 12597 * Purpose: 12598 * Delete an entry from meter action table 12599 * Parameters: 12600 * unit - (IN) unit number 12601 * action_id - (IN) Action Id to be destroyed 12602 * Returns: 12603 * BCM_E_XXX 12604 */ 12605 int bcm_esw_policer_action_destroy( 12606 int unit, 12607 uint32 action_id) 12608 { 12609 int rv = BCM_E_NONE; 12610 uint32 reset=0; 12611 svm_policy_table_entry_t meter_action; 12612 12613 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12614 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12615 return bcmi_esw_policer_action_destroy(unit, action_id); 12616 } 12617 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12618 12619 if (!soc_feature(unit, soc_feature_global_meter)) { 12620 return BCM_E_UNAVAIL; 12621 } 12622 12623 if (global_meter_action_bookkeep[unit][action_id].used != 1) 12624 { 12625 LOG_DEBUG(BSL_LS_BCM_POLICER, 12626 (BSL_META_U(unit, 12627 "Action Id specified doesn't exist\n"))); 12628 return BCM_E_PARAM; 12629 } 12630 12631 if (global_meter_action_bookkeep[unit]\ 12632 [action_id].reference_count != 0) 12633 { 12634 LOG_DEBUG(BSL_LS_BCM_POLICER, 12635 (BSL_META_U(unit, 12636 "Action Id specified still being used \n"))); 12637 return BCM_E_BUSY; 12638 } 12639 GLOBAL_METER_LOCK(unit); 12640 /* read action table entry */ 12641 rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action); 12642 if (BCM_FAILURE(rv)) { 12643 GLOBAL_METER_UNLOCK(unit); 12644 LOG_DEBUG(BSL_LS_BCM_POLICER, 12645 (BSL_META_U(unit, 12646 "Unable to read SVM_POLICY_TABLE at location " 12647 "specified by action_id \n"))); 12648 return (rv); 12649 } 12650 12651 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, G_ACTIONSf, &reset); 12652 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, Y_ACTIONSf, &reset); 12653 soc_SVM_POLICY_TABLEm_field_set(unit, &meter_action, R_ACTIONSf, &reset); 12654 12655 rv = WRITE_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action); 12656 if (BCM_FAILURE(rv)) { 12657 GLOBAL_METER_UNLOCK(unit); 12658 LOG_DEBUG(BSL_LS_BCM_POLICER, 12659 (BSL_META_U(unit, 12660 "Unable to write to SVM_POLICY_TABLE at location " 12661 "specified by action_id \n"))); 12662 return (rv); 12663 } 12664 12665 rv = shr_aidxres_list_free(meter_action_list_handle[unit], action_id); 12666 if (BCM_FAILURE(rv)) { 12667 GLOBAL_METER_UNLOCK(unit); 12668 LOG_VERBOSE(BSL_LS_BCM_POLICER, 12669 (BSL_META_U(unit, 12670 "Unable to free action handle \n"))); 12671 return (rv); 12672 } 12673 GLOBAL_METER_UNLOCK(unit); 12674 global_meter_action_bookkeep[unit][action_id].used = 0; 12675 return rv; 12676 12677 } 12678 12679 /* 12680 * Function: 12681 * bcm_esw_policer_action_get 12682 * Purpose: 12683 * get action parameter for a given action 12684 * Parameters: 12685 * unit - (IN) unit number 12686 * action_id - (IN) Action Id 12687 * action - (IN) Action for which param is needed 12688 * param0 - (OUT) Parameter associated with action id 12689 * Returns: 12690 * BCM_E_XXX 12691 */ 12692 int bcm_esw_policer_action_get( 12693 int unit, 12694 uint32 action_id, 12695 bcm_policer_action_t action, 12696 uint32 *param0) 12697 { 12698 int rv = BCM_E_NONE; 12699 svm_policy_table_entry_t meter_action; 12700 uint32 green_action = 0, yellow_action = 0, red_action = 0; 12701 12702 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 12703 if (soc_feature(unit, soc_feature_global_meter_v2)) { 12704 return bcmi_esw_policer_action_get(unit, action_id, action, param0); 12705 } 12706 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 12707 12708 if (!soc_feature(unit, soc_feature_global_meter)) { 12709 return BCM_E_UNAVAIL; 12710 } 12711 12712 if (global_meter_action_bookkeep[unit][action_id].used != 1) 12713 { 12714 LOG_DEBUG(BSL_LS_BCM_POLICER, 12715 (BSL_META_U(unit, 12716 "Action Id specified doesn't exist\n"))); 12717 return BCM_E_PARAM; 12718 } 12719 GLOBAL_METER_LOCK(unit); 12720 /* read action table entry */ 12721 rv = READ_SVM_POLICY_TABLEm(unit, MEM_BLOCK_ANY, action_id, &meter_action); 12722 if (BCM_FAILURE(rv)) { 12723 GLOBAL_METER_UNLOCK(unit); 12724 LOG_DEBUG(BSL_LS_BCM_POLICER, 12725 (BSL_META_U(unit, 12726 "Unable to read SVM_POLICY_TABLE at location " 12727 "specified by action_id \n"))); 12728 return (rv); 12729 } 12730 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, G_ACTIONSf, 12731 &green_action); 12732 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, Y_ACTIONSf, 12733 &yellow_action); 12734 soc_SVM_POLICY_TABLEm_field_get(unit, &meter_action, R_ACTIONSf, 12735 &red_action); 12736 12737 switch (action) { 12738 case bcmPolicerActionGpEcnNew : 12739 *param0 = (green_action & BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK); 12740 break; 12741 12742 case bcmPolicerActionGpDscpNew: 12743 *param0 = (green_action & 12744 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2; 12745 break; 12746 12747 case bcmPolicerActionGpVlanPrioNew: 12748 *param0 = (green_action & 12749 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >> 12750 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS; 12751 break; 12752 12753 case bcmPolicerActionGpPrioIntNew: 12754 *param0 = (green_action & 12755 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >> 12756 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ; 12757 break; 12758 12759 case bcmPolicerActionGpCngNew : 12760 *param0 = (green_action & 12761 BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >> 12762 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ; 12763 break; 12764 12765 case bcmPolicerActionYpEcnNew : 12766 *param0 = (yellow_action & 12767 BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK); 12768 break; 12769 12770 case bcmPolicerActionYpDscpNew: 12771 *param0 = (yellow_action & 12772 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2; 12773 break; 12774 12775 case bcmPolicerActionYpVlanPrioNew: 12776 *param0 = (yellow_action & 12777 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >> 12778 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS; 12779 break; 12780 12781 case bcmPolicerActionYpPrioIntNew: 12782 *param0 = (yellow_action & 12783 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >> 12784 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ; 12785 break; 12786 12787 case bcmPolicerActionYpCngNew : 12788 *param0 = (yellow_action & 12789 BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >> 12790 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ; 12791 break; 12792 12793 case bcmPolicerActionRpEcnNew : 12794 *param0 = (red_action & BCM_POLICER_GLOBAL_METER_ACTION_ECN_MASK); 12795 break; 12796 12797 case bcmPolicerActionRpDscpNew: 12798 *param0 = (red_action & 12799 BCM_POLICER_GLOBAL_METER_ACTION_DSCP_MASK) >> 2; 12800 break; 12801 12802 case bcmPolicerActionRpVlanPrioNew: 12803 *param0 = (red_action & 12804 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_MASK) >> 12805 BCM_POLICER_GLOBAL_METER_ACTION_DOT1P_BIT_POS; 12806 break; 12807 12808 case bcmPolicerActionRpPrioIntNew: 12809 *param0 = (red_action & 12810 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_MASK) >> 12811 BCM_POLICER_GLOBAL_METER_ACTION_INT_PRI_BIT_POS ; 12812 break; 12813 12814 case bcmPolicerActionRpCngNew : 12815 *param0 = (red_action & 12816 BCM_POLICER_GLOBAL_METER_ACTION_CNG_MASK) >> 12817 BCM_POLICER_GLOBAL_METER_ACTION_CHANGE_CNG_BIT_POS ; 12818 break; 12819 12820 default: 12821 LOG_ERROR(BSL_LS_BCM_POLICER, 12822 (BSL_META_U(unit, 12823 "Unsupported Action specified\n"))); 12824 rv = BCM_E_PARAM; 12825 break; 12826 } 12827 GLOBAL_METER_UNLOCK(unit); 12828 return rv; 12829 } 12830 12831 /* end Action API's */ 12832 12833 12834 /* POLICER API's */ 12835 /* 12836 * Function: 12837 * _bcm_global_meter_free_allocated_policer_on_error 12838 * Purpose: 12839 * Clean up the internal data structure in case of error. 12840 * Parameters: 12841 * unit - (IN) unit number 12842 * numbers - (IN) Number of policer to be freed 12843 * offset - (IN) Offset w.r.t base policer 12844 * policer_index - (IN) Base policer id 12845 * Returns: 12846 * BCM_E_XXX 12847 */ 12848 int _bcm_global_meter_free_allocated_policer_on_error(int unit, 12849 uint32 numbers, uint8 *offset, 12850 uint32 policer_index) 12851 { 12852 12853 int rv = BCM_E_NONE; 12854 int index =0; 12855 int pool = 0; 12856 int size_pool; 12857 int num_banks_per_pool = 1, index_bank = 0; 12858 int handle_id = 0, bank_id = 0; 12859 12860 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 12861 num_banks_per_pool = get_max_banks_in_a_pool(unit); 12862 bank_id = (policer_index & (size_pool - 1)) / num_banks_per_pool; 12863 index_bank = (policer_index & (size_pool - 1)) % num_banks_per_pool; 12864 12865 for (index = 0;index < numbers; index++) { 12866 if (index) { 12867 pool = offset[0] + offset[index]; 12868 } else { 12869 pool = offset[0]; 12870 } 12871 12872 handle_id = pool * num_banks_per_pool + bank_id; 12873 rv = shr_aidxres_list_free( 12874 meter_alloc_list_handle[unit][handle_id], index_bank); 12875 if (!BCM_SUCCESS(rv)) { 12876 LOG_DEBUG(BSL_LS_BCM_POLICER, 12877 (BSL_META_U(unit, 12878 "Unable to free policer handle \n"))); 12879 return BCM_E_INTERNAL; 12880 } 12881 12882 rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, pool, policer_index); 12883 if (!BCM_SUCCESS(rv)) { 12884 LOG_DEBUG(BSL_LS_BCM_POLICER, 12885 (BSL_META_U(unit, 12886 "Unable to free policer handle \n"))); 12887 return BCM_E_INTERNAL; 12888 } 12889 } 12890 return rv; 12891 } 12892 12893 static int 12894 max_groups_per_octuple (int unit) 12895 { 12896 return (soc_feature(unit, soc_feature_global_meter_mef_10dot3) ? 4 : 2); 12897 } 12898 12899 /* 12900 * Function: 12901 * _bcm_gloabl_meter_alloc_horizontally 12902 * Purpose: 12903 * Allocate a set of policers such that each of the policers 12904 * created have the same index but differnt pool number. 12905 * Parameters: 12906 * unit - (IN) unit number 12907 * numbers - (IN) Number of policer to be allocated 12908 * pid - (OUT) Base policer id 12909 * offset - (OUT) Offset w.r.t base policer 12910 * Returns: 12911 * BCM_E_XXX 12912 */ 12913 int _bcm_gloabl_meter_alloc_horizontally(int unit, int *numbers, 12914 bcm_policer_t *pid, 12915 uint8 *offset) 12916 { 12917 int rv = BCM_E_NONE; 12918 _global_meter_horizontal_alloc_t *alloc_control; 12919 uint32 allocated_policer = 0; 12920 int max_index = 0, max_pool = 0, index = 0, map = 0, pool = 0; 12921 int policers_available = 0; 12922 int skip_index = 0; 12923 int bank_size = 0, handle_id = 0, bank_index = 0; 12924 int num_banks_per_pool = get_max_banks_in_a_pool(unit); 12925 12926 max_index = SOC_INFO(unit).global_meter_size_of_pool; 12927 max_pool = SOC_INFO(unit).global_meter_pools; 12928 bank_size = max_index / num_banks_per_pool; 12929 12930 alloc_control = global_meter_hz_alloc_bookkeep[unit]; 12931 for (index = 1; index < max_index; index++) { 12932 skip_index = 0; 12933 allocated_policer = 0; 12934 if (alloc_control[index].no_of_groups_allocated == 12935 max_groups_per_octuple(unit)) { 12936 continue; 12937 } else if (alloc_control[index].no_of_groups_allocated > 0) { 12938 /* check if we have enough free policers to allocate */ 12939 map = alloc_control[index].alloc_bit_map; 12940 if (alloc_control[index].first_bit_to_use > 0) { 12941 map = map & 12942 (convert_to_bitmask(alloc_control[index].first_bit_to_use - 1)); 12943 policers_available = _shr_popcount(map); 12944 } else { 12945 policers_available = 0; 12946 } 12947 if (policers_available >= *numbers) { 12948 offset[0] = 0; 12949 /* Use shared aligned index management to allocate policers */ 12950 for (pool = 0; pool <= alloc_control[index].first_bit_to_use; 12951 pool++) { 12952 handle_id = pool * num_banks_per_pool + index / bank_size; 12953 bank_index = index % bank_size; 12954 12955 rv = shr_aidxres_list_reserve_block( 12956 meter_alloc_list_handle[unit][handle_id], bank_index, 1); 12957 if (!BCM_SUCCESS(rv)) { 12958 if (allocated_policer) { 12959 /* free all the allocated policers */ 12960 rv = _bcm_global_meter_free_allocated_policer_on_error(unit, 12961 allocated_policer, offset, index); 12962 12963 skip_index = 1; 12964 allocated_policer = 0; 12965 } 12966 continue; 12967 } 12968 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, 12969 pool, index); 12970 if (!BCM_SUCCESS(rv)) { 12971 rv = shr_aidxres_list_free( 12972 meter_alloc_list_handle[unit][handle_id], bank_index); 12973 if (!BCM_SUCCESS(rv)) { 12974 LOG_DEBUG(BSL_LS_BCM_POLICER, 12975 (BSL_META_U(unit, 12976 "Unable to free policer " 12977 "handle \n"))); 12978 return BCM_E_INTERNAL; 12979 } 12980 continue; 12981 } 12982 if (allocated_policer) { 12983 offset[allocated_policer] = pool - offset[0]; 12984 } else { 12985 offset[allocated_policer] = pool; 12986 } 12987 allocated_policer++; 12988 if (allocated_policer == *numbers) { 12989 alloc_control[index].last_bit_to_use = 12990 alloc_control[index].first_bit_to_use; 12991 alloc_control[index].first_bit_to_use = pool; 12992 break; 12993 } 12994 12995 } 12996 if (allocated_policer != *numbers) { 12997 /* free all the allocated policers */ 12998 rv = _bcm_global_meter_free_allocated_policer_on_error( 12999 unit, allocated_policer, offset, index); 13000 if (skip_index == 0 ) { 13001 LOG_DEBUG(BSL_LS_BCM_POLICER, 13002 (BSL_META_U(unit, 13003 "Unable to free policer " 13004 "handle \n"))); 13005 return BCM_E_INTERNAL; 13006 } 13007 } else if( allocated_policer == *numbers) { 13008 *pid = index; 13009 alloc_control[index].no_of_groups_allocated++; 13010 LOG_DEBUG(BSL_LS_BCM_POLICER, 13011 (BSL_META_U(unit, 13012 "Allocated base policer with " 13013 "index %x \n"), index)); 13014 return BCM_E_NONE; 13015 } 13016 } 13017 map = alloc_control[index].alloc_bit_map; 13018 map = map & 13019 ~(convert_to_bitmask(alloc_control[index].last_bit_to_use)); 13020 policers_available = _shr_popcount(map); 13021 if (policers_available >= *numbers) { 13022 /* Use shared aligned index management to allocate policers */ 13023 for (pool = alloc_control[index].last_bit_to_use + 1; 13024 pool < max_pool; pool++) { 13025 handle_id = pool * num_banks_per_pool + index / bank_size; 13026 bank_index = index % bank_size; 13027 13028 rv = shr_aidxres_list_reserve_block( 13029 meter_alloc_list_handle[unit][handle_id], bank_index, 1); 13030 if (!BCM_SUCCESS(rv)) { 13031 if (allocated_policer) { 13032 /* free all the allocated policers */ 13033 rv = _bcm_global_meter_free_allocated_policer_on_error(unit, 13034 allocated_policer, offset, index); 13035 13036 skip_index = 1; 13037 allocated_policer = 0; 13038 } 13039 continue; 13040 } 13041 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, 13042 pool, index); 13043 if (!BCM_SUCCESS(rv)) { 13044 rv = shr_aidxres_list_free( 13045 meter_alloc_list_handle[unit][handle_id], bank_index); 13046 if (!BCM_SUCCESS(rv)) { 13047 LOG_DEBUG(BSL_LS_BCM_POLICER, 13048 (BSL_META_U(unit, 13049 "Unable to free policer " 13050 "handle \n"))); 13051 return BCM_E_INTERNAL; 13052 } 13053 continue; 13054 } 13055 if (allocated_policer) { 13056 offset[allocated_policer] = pool - offset[0]; 13057 } else { 13058 offset[allocated_policer] = pool; 13059 } 13060 allocated_policer++; 13061 if (allocated_policer == *numbers) { 13062 alloc_control[index].first_bit_to_use = 13063 alloc_control[index].last_bit_to_use; 13064 alloc_control[index].last_bit_to_use = offset[0]; 13065 break; 13066 } 13067 } 13068 if (allocated_policer != *numbers) { 13069 /* free all the allocated policers */ 13070 rv = _bcm_global_meter_free_allocated_policer_on_error( 13071 unit, allocated_policer, offset, index); 13072 if (skip_index == 0 ) { 13073 LOG_DEBUG(BSL_LS_BCM_POLICER, 13074 (BSL_META_U(unit, 13075 "Unable to free policer " 13076 "handle \n"))); 13077 return BCM_E_INTERNAL; 13078 } 13079 } else if( allocated_policer == *numbers) { 13080 *pid = index; 13081 alloc_control[index].no_of_groups_allocated++; 13082 LOG_DEBUG(BSL_LS_BCM_POLICER, 13083 (BSL_META_U(unit, 13084 "Allocated base policer with " 13085 "index %x \n"), index)); 13086 return BCM_E_NONE; 13087 } 13088 } 13089 } else { /* No Cascade group assigned */ 13090 map = alloc_control[index].alloc_bit_map; 13091 policers_available = _shr_popcount(map); 13092 if (policers_available < *numbers) { 13093 continue; 13094 } 13095 offset[0] = 0; 13096 /* Use shared aligned index management to allocate policers */ 13097 for (pool = 0; pool < max_pool; pool++) { 13098 handle_id = pool * num_banks_per_pool + index / bank_size; 13099 bank_index = index % bank_size; 13100 13101 rv = shr_aidxres_list_reserve_block( 13102 meter_alloc_list_handle[unit][handle_id], bank_index, 1); 13103 if (!BCM_SUCCESS(rv)) { 13104 if (allocated_policer) { 13105 /* free all the allocated policers */ 13106 rv = _bcm_global_meter_free_allocated_policer_on_error(unit, 13107 allocated_policer, offset, index); 13108 13109 skip_index = 1; 13110 allocated_policer = 0; 13111 } 13112 continue; 13113 } 13114 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool, 13115 index); 13116 if (!BCM_SUCCESS(rv)) { 13117 rv = shr_aidxres_list_free( 13118 meter_alloc_list_handle[unit][handle_id], bank_index); 13119 if (!BCM_SUCCESS(rv)) { 13120 LOG_DEBUG(BSL_LS_BCM_POLICER, 13121 (BSL_META_U(unit, 13122 "Unable to free policer " 13123 "handle \n"))); 13124 return BCM_E_INTERNAL; 13125 } 13126 continue; 13127 } 13128 if (allocated_policer == 0) { 13129 alloc_control[index].first_bit_to_use = pool; 13130 offset[allocated_policer]=pool; 13131 } else { 13132 offset[allocated_policer] = pool - offset[0]; 13133 } 13134 allocated_policer++; 13135 if (allocated_policer == *numbers) { 13136 alloc_control[index].last_bit_to_use = pool; 13137 break; 13138 } 13139 } 13140 if (allocated_policer != *numbers) { 13141 /* free all the allocated policers */ 13142 rv = _bcm_global_meter_free_allocated_policer_on_error(unit, 13143 allocated_policer, offset, index); 13144 if (skip_index == 0) { 13145 LOG_DEBUG(BSL_LS_BCM_POLICER, 13146 (BSL_META_U(unit, 13147 "Unable to free policer " 13148 "handle \n"))); 13149 return BCM_E_INTERNAL; 13150 } 13151 } else if( allocated_policer == *numbers) { 13152 *pid = index; 13153 alloc_control[index].no_of_groups_allocated++; 13154 LOG_DEBUG(BSL_LS_BCM_POLICER, 13155 (BSL_META_U(unit, 13156 "Allocated base policer with index %x \n"), 13157 index)); 13158 return BCM_E_NONE; 13159 } 13160 } 13161 } 13162 LOG_DEBUG(BSL_LS_BCM_POLICER, 13163 (BSL_META_U(unit, 13164 "Unable to allocate policer as table is full \n"))); 13165 return BCM_E_FULL; 13166 } 13167 13168 /* 13169 * Function: 13170 * _bcm_global_meter_reserve_bloc_horizontally 13171 * Purpose: 13172 * reset the bit in the inernal data structure corresponding 13173 * to the policer that is being reserved. 13174 * Parameters: 13175 * unit - (IN) unit number 13176 * pool_id - (IN) polier pool number 13177 * pid - (IN) policer id 13178 * Returns: 13179 * BCM_E_XXX 13180 */ 13181 13182 int _bcm_global_meter_reserve_bloc_horizontally(int unit, int pool_id, 13183 bcm_policer_t pid) 13184 { 13185 int rv = BCM_E_NONE; 13186 global_meter_hz_alloc_bookkeep[unit][pid].alloc_bit_map \ 13187 &= convert_to_mask(pool_id); 13188 return rv; 13189 } 13190 13191 /* 13192 * Function: 13193 * _bcm_esw_get_policer_control 13194 * Purpose: 13195 * Get the policer control data sructure for a given pool, offset mode 13196 * and index in the pool. 13197 * Parameters: 13198 * unit - (IN) unit number 13199 * pid - (IN) policer id 13200 * pool - (IN) polier pool number 13201 * offset_mode - (IN) meter offset mode 13202 * policer_control - (OUT) polier control info 13203 * Returns: 13204 * BCM_E_XXX 13205 */ 13206 13207 int _bcm_esw_get_policer_control(int unit, bcm_policer_t pid, 13208 int pool, int offset_mode, 13209 _global_meter_policer_control_t **policer_control) 13210 { 13211 int rv = BCM_E_NONE; 13212 bcm_policer_t policer_id = 0; 13213 int size_pool = 0; 13214 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 13215 policer_id = (((offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT) + 13216 (pool << _shr_popcount(size_pool - 1)) + pid); 13217 rv = _bcm_global_meter_policer_get(unit, policer_id, policer_control); 13218 return rv; 13219 } 13220 13221 /* 13222 * Function: 13223 * _bcm_gloabl_meter_free_horizontally 13224 * Purpose: 13225 * Free the bits in the inernal data structure corresponding 13226 * to set of policer that is being destroyed. 13227 * Parameters: 13228 * unit - (IN) unit number 13229 * pool_id - (IN) polier pool number 13230 * pid - (IN) policer id 13231 * numbers - (IN) Number of policers to be freed 13232 * offset - (IN) offset w.r.t pid 13233 * Returns: 13234 * BCM_E_XXX 13235 */ 13236 13237 int _bcm_gloabl_meter_free_horizontally(int unit, int pool_id, 13238 bcm_policer_t pid, 13239 int numbers, uint8 offset[8]) 13240 { 13241 int rv = BCM_E_NONE; 13242 int index = 0; 13243 _global_meter_horizontal_alloc_t *alloc_control; 13244 int num_pol = 0; 13245 int actual_pool = 0; 13246 _global_meter_policer_control_t *policer_control = NULL; 13247 alloc_control = global_meter_hz_alloc_bookkeep[unit]; 13248 actual_pool = pool_id; 13249 for (index = 0; index < numbers; index++) 13250 { 13251 if (index > 0) { 13252 actual_pool = pool_id + offset[index]; 13253 } 13254 alloc_control[pid].alloc_bit_map |= 13255 ((~convert_to_mask(actual_pool)) & 0xFF); 13256 } 13257 if ((numbers > 1) && (alloc_control[pid].no_of_groups_allocated)) { 13258 alloc_control[pid].no_of_groups_allocated--; 13259 if (alloc_control[pid].no_of_groups_allocated == 1) { 13260 if (pool_id + offset[index - 1] == 13261 alloc_control[pid].first_bit_to_use) { 13262 rv = _bcm_esw_get_policer_control(unit, pid, 13263 alloc_control[pid].last_bit_to_use, 13264 0, &policer_control); 13265 if (!BCM_SUCCESS(rv)) { 13266 LOG_DEBUG(BSL_LS_BCM_POLICER, 13267 (BSL_META_U(unit, 13268 "Unable to get policer control for pid " 13269 "%x\n"), pid)); 13270 return rv; 13271 } 13272 alloc_control[pid].first_bit_to_use = 13273 alloc_control[pid].last_bit_to_use; 13274 num_pol = policer_control->no_of_policers; 13275 if (num_pol > 0 ) { 13276 pool_id = policer_control->offset[0] + 13277 policer_control->offset[num_pol-1]; 13278 alloc_control[pid].last_bit_to_use = pool_id; 13279 } else { 13280 LOG_DEBUG(BSL_LS_BCM_POLICER, 13281 (BSL_META_U(unit, 13282 "Number of policers in policer control " 13283 "structure is 0\n"))); 13284 return BCM_E_INTERNAL; 13285 } 13286 } else if (pool_id == alloc_control[pid].last_bit_to_use) { 13287 alloc_control[pid].last_bit_to_use = 13288 alloc_control[pid].first_bit_to_use; 13289 rv = _bcm_esw_get_policer_control(unit, pid, 13290 alloc_control[pid].first_bit_to_use, 13291 0, &policer_control); 13292 if (!BCM_SUCCESS(rv)) { 13293 LOG_DEBUG(BSL_LS_BCM_POLICER, 13294 (BSL_META_U(unit, 13295 "Unable to get policer control for pid " 13296 "%x\n"), pid)); 13297 return rv; 13298 } 13299 num_pol = policer_control->no_of_policers; 13300 if (num_pol > 0 ) { 13301 pool_id = policer_control->offset[0]; 13302 alloc_control[pid].first_bit_to_use = pool_id; 13303 } else { 13304 LOG_DEBUG(BSL_LS_BCM_POLICER, 13305 (BSL_META_U(unit, 13306 "Number of policers in policer control " 13307 "structure is 0\n"))); 13308 return BCM_E_INTERNAL; 13309 } 13310 } 13311 } 13312 } 13313 return rv; 13314 } 13315 13316 /* 13317 * Function: 13318 * _bcm_gloabl_meter_unreserve_bloc_horizontally 13319 * Purpose: 13320 * Free the bit in the inernal data structure corresponding 13321 * to the policer that is being destroyed. 13322 * Parameters: 13323 * unit - (IN) unit number 13324 * pool_id - (IN) polier pool number 13325 * pid - (IN) policer id 13326 * Returns: 13327 * BCM_E_XXX 13328 */ 13329 int _bcm_gloabl_meter_unreserve_bloc_horizontally(int unit, int pool_id, 13330 bcm_policer_t pid) 13331 { 13332 int rv = BCM_E_NONE; 13333 13334 global_meter_hz_alloc_bookkeep[unit][pid].alloc_bit_map \ 13335 |= (~convert_to_mask(pool_id) & 0xFF); 13336 return rv; 13337 } 13338 13339 /* 13340 * Function: 13341 * _global_meter_reserve_policer_id 13342 * Purpose: 13343 * Reserve a given policer id. 13344 * Parameters: 13345 * unit - (IN) unit number 13346 * direction - (IN) Horizontal/Vertical 13347 * numbers - (IN) Number of policers to be reserved 13348 * pid - (IN) base policer id 13349 * pid_offset - (IN) Offset w.r.t base policer 13350 * Returns: 13351 * Returns: 13352 * Returns: 13353 * BCM_E_XXX 13354 */ 13355 int _global_meter_reserve_policer_id(int unit, int direction, int numbers, 13356 bcm_policer_t pid, 13357 uint8 *pid_offset) 13358 { 13359 int rv = BCM_E_NONE; 13360 uint32 index = 0, free_index = 0; 13361 int pool = 0, pol_index = 0, pool_id = 0; 13362 int offset_mask = 0; 13363 int size_pool = 0, num_pools = 0; 13364 int pool_mask = 0, pool_offset = 0; 13365 int bank_size = 0, bank_index = 0, num_banks_per_pool = 1; 13366 int handle_id = 0; 13367 13368 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 13369 num_pools = SOC_INFO(unit).global_meter_pools; 13370 offset_mask = size_pool - 1; 13371 pool_offset = _shr_popcount(offset_mask); 13372 pool_mask = (num_pools - 1) << pool_offset; 13373 13374 pool = (pid & pool_mask) >> pool_offset; 13375 pol_index = pid & offset_mask; 13376 13377 num_banks_per_pool = get_max_banks_in_a_pool(unit); 13378 bank_size = size_pool / num_banks_per_pool; 13379 handle_id = pool * num_banks_per_pool + pol_index / bank_size; 13380 bank_index = pol_index % bank_size; 13381 13382 if (direction == GLOBAL_METER_ALLOC_VERTICAL) { 13383 if (soc_feature(unit, 13384 soc_feature_global_meter_compaction_support)) { 13385 13386 rv = shr_aidxres_list_reserve( 13387 meter_alloc_list_handle[unit][handle_id], 13388 bank_index, bank_index + numbers - 1); 13389 } else { 13390 rv = shr_aidxres_list_reserve_block( 13391 meter_alloc_list_handle[unit][handle_id], 13392 bank_index, numbers); 13393 } 13394 if (!BCM_SUCCESS(rv)) { 13395 LOG_DEBUG(BSL_LS_BCM_POLICER, 13396 (BSL_META_U(unit, 13397 "Unable to reserve policer in shared index " 13398 "management\n"))); 13399 return BCM_E_INTERNAL; 13400 } 13401 for (index = 0; index < numbers; index++) { 13402 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool, 13403 pol_index + index); 13404 if (!BCM_SUCCESS(rv)) { 13405 rv = shr_aidxres_list_free( 13406 meter_alloc_list_handle[unit][handle_id], bank_index); 13407 if (!BCM_SUCCESS(rv)) { 13408 LOG_DEBUG(BSL_LS_BCM_POLICER, 13409 (BSL_META_U(unit, 13410 "Unable to free policer in shared " 13411 "index management\n"))); 13412 return BCM_E_INTERNAL; 13413 } 13414 for (free_index = 0; free_index < index; free_index++) { 13415 rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, 13416 pool, pol_index+index); 13417 if (!BCM_SUCCESS(rv)) { 13418 LOG_DEBUG(BSL_LS_BCM_POLICER, 13419 (BSL_META_U(unit, 13420 "Unable to free policer in hz " 13421 "index management\n"))); 13422 return BCM_E_INTERNAL; 13423 } 13424 } 13425 } 13426 } 13427 13428 } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 13429 for (index = 0; index < numbers; index++) { 13430 if (index > 0) { 13431 pool_id = pool + pid_offset[index]; 13432 } 13433 handle_id = pool_id * num_banks_per_pool + pol_index / bank_size; 13434 bank_index = pol_index % bank_size; 13435 13436 rv = shr_aidxres_list_reserve_block( 13437 meter_alloc_list_handle[unit][handle_id], bank_index, 1); 13438 if (!BCM_SUCCESS(rv)) { 13439 for (free_index = 0; free_index < index; free_index++) { 13440 pool_id = pool + pid_offset[free_index]; 13441 handle_id = pool_id * num_banks_per_pool + pol_index / bank_size; 13442 bank_index = pol_index % bank_size; 13443 13444 rv = shr_aidxres_list_free( 13445 meter_alloc_list_handle[unit][handle_id], bank_index); 13446 13447 if (BCM_SUCCESS(rv)) { 13448 rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, 13449 pool_id, pol_index); 13450 } 13451 if (BCM_FAILURE(rv)) { 13452 break; 13453 } 13454 } 13455 LOG_DEBUG(BSL_LS_BCM_POLICER, 13456 (BSL_META_U(unit, 13457 "Unable to reserve policer in shared " 13458 "index management\n"))); 13459 return BCM_E_INTERNAL; 13460 } 13461 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, 13462 pool_id, pol_index); 13463 if (!BCM_SUCCESS(rv)) { 13464 rv = shr_aidxres_list_free( 13465 meter_alloc_list_handle[unit][handle_id], bank_index); 13466 if (!BCM_SUCCESS(rv)) { 13467 LOG_DEBUG(BSL_LS_BCM_POLICER, 13468 (BSL_META_U(unit, 13469 "Unable to free policer in " 13470 "index management\n"))); 13471 return BCM_E_INTERNAL; 13472 } 13473 for (free_index=0; free_index < index; free_index++) { 13474 rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, 13475 pool_id, pol_index); 13476 if (!BCM_SUCCESS(rv)) { 13477 LOG_DEBUG(BSL_LS_BCM_POLICER, 13478 (BSL_META_U(unit, 13479 "Unable to free policer in hz " 13480 "index management\n"))); 13481 return BCM_E_INTERNAL; 13482 } 13483 } 13484 } 13485 } 13486 } else { 13487 LOG_DEBUG(BSL_LS_BCM_POLICER, 13488 (BSL_META_U(unit, 13489 "Invalid direction for policer allocation \n"))); 13490 return BCM_E_INTERNAL; 13491 } 13492 return rv; 13493 } 13494 13495 /* 13496 * Function: 13497 * _global_meter_policer_id_alloc 13498 * Purpose: 13499 * Allocate a new policer. 13500 * Parameters: 13501 * unit - (IN) unit number 13502 * direction - (IN) Horizontal/Vertical 13503 * numbers - (IN/OUT) Number of policers 13504 * pid - (OUT) base policer id 13505 * flow_info - (IN) information about flow type and skip pool 13506 * pid_offset - (OUT) Offset w.r.t base policer 13507 * Returns: 13508 * BCM_E_XXX 13509 */ 13510 int _global_meter_policer_id_alloc(int unit, int direction, int *numbers, 13511 bcm_policer_t *pid, 13512 _bcm_policer_flow_info_t *flow_info, 13513 uint8 *pid_offset) 13514 { 13515 int rv = BCM_E_NONE; 13516 uint32 index = 0, no_of_pools_checked = 0; 13517 static uint32 pool = 0; 13518 int size_pool = 0, num_pools = 0; 13519 int bank_size = 0, bank_index = 0; 13520 int meter_allocated = 0; 13521 _bcm_policer_flow_type_t flow_type; 13522 int skip_pool, skip_bank, bank_id = 0; 13523 int num_banks_per_pool = 1, handle_id = 0; 13524 13525 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 13526 num_pools = SOC_INFO(unit).global_meter_pools; 13527 13528 flow_type = flow_info->flow_type; 13529 skip_pool = flow_info->skip_pool; 13530 skip_bank = flow_info->skip_bank; 13531 13532 num_banks_per_pool = get_max_banks_in_a_pool(unit); 13533 bank_size = size_pool / num_banks_per_pool; 13534 13535 if (direction == GLOBAL_METER_ALLOC_VERTICAL) { 13536 if ((flow_type == bcmPolicerFlowTypeMacro) || 13537 (flow_type == bcmPolicerFlowTypeNormal)) { 13538 no_of_pools_checked = 0; 13539 for ( ;no_of_pools_checked < num_pools; pool++) { 13540 if (pool >= num_pools) { 13541 pool = 0; 13542 } 13543 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) { 13544 13545 /* For Macro flow use only one bank */ 13546 if (flow_type == bcmPolicerFlowTypeMacro) { 13547 if (bank_id > 0) { 13548 break; 13549 } 13550 } 13551 handle_id = pool * num_banks_per_pool + bank_id; 13552 rv = shr_aidxres_list_alloc_block( 13553 (meter_alloc_list_handle[unit][handle_id]), 13554 *numbers, (uint32 *)&bank_index); 13555 13556 if (BCM_SUCCESS(rv)) { 13557 meter_allocated = 1; 13558 (*pid) = bank_size * bank_id + bank_index; 13559 break; 13560 } 13561 } 13562 if (meter_allocated == 1) { 13563 break; 13564 } 13565 no_of_pools_checked++; 13566 } 13567 } else { 13568 /* flow_type == bcmPolicerFlowTypeMicro */ 13569 if (soc_feature(unit, soc_feature_global_meter_macro_micro_same_pool)) { 13570 /* If this soc feature is defined, it means that micro and macro 13571 * meter must reside in same pool but different bank. A pool is 13572 * divided into 2 banks.*/ 13573 13574 for (bank_id = 0; bank_id < num_banks_per_pool; bank_id++) { 13575 if (skip_bank == bank_id) { 13576 continue; 13577 } 13578 13579 /* micro flow must be in the same pool as Macro flow (skip_pool) */ 13580 pool = skip_pool; 13581 handle_id = skip_pool * num_banks_per_pool + bank_id; 13582 rv = shr_aidxres_list_alloc_block( 13583 (meter_alloc_list_handle[unit][handle_id]), 13584 *numbers, (uint32 *)&bank_index); 13585 13586 if (BCM_SUCCESS(rv)) { 13587 meter_allocated = 1; 13588 (*pid) = bank_size * bank_id + bank_index; 13589 break; 13590 } 13591 } 13592 } else { 13593 /* macro-micro meter must reside in different pools */ 13594 no_of_pools_checked = 0; 13595 for ( ;no_of_pools_checked < num_pools; pool++) { 13596 for (bank_id =0; bank_id < num_banks_per_pool; bank_id++) { 13597 13598 if (pool >= num_pools) { 13599 pool = 0; 13600 } 13601 13602 if (pool == skip_pool) { 13603 no_of_pools_checked++; 13604 continue; 13605 } 13606 13607 handle_id = pool * num_banks_per_pool + bank_id; 13608 rv = shr_aidxres_list_alloc_block( 13609 (meter_alloc_list_handle[unit][handle_id]), 13610 *numbers, (uint32 *)&bank_index); 13611 13612 if (BCM_SUCCESS(rv)) { 13613 meter_allocated = 1; 13614 (*pid) = bank_size * bank_id + bank_index; 13615 break; 13616 } 13617 } 13618 if (meter_allocated == 1) { 13619 break; 13620 } 13621 no_of_pools_checked++; 13622 } 13623 } 13624 } 13625 13626 if (meter_allocated == 0) { 13627 return BCM_E_FULL; 13628 } else { 13629 /* add code to set bits in horizontal allocation datastruture */ 13630 for (index = 0; index < *numbers; index++) { 13631 rv = _bcm_global_meter_reserve_bloc_horizontally(unit, pool, 13632 ((*pid)+index)); 13633 if (!BCM_SUCCESS(rv)) { 13634 for (index = 0; index < *numbers; index++) { 13635 rv = shr_aidxres_list_free( 13636 meter_alloc_list_handle[unit][handle_id], 13637 bank_index + index); 13638 } 13639 LOG_DEBUG(BSL_LS_BCM_POLICER, 13640 (BSL_META_U(unit, 13641 "Unable to free policer in " 13642 "index management\n"))); 13643 return BCM_E_INTERNAL; 13644 } 13645 } 13646 /* Add pool id to make complete policer id */ 13647 *pid = *pid | (pool << _shr_popcount(size_pool - 1)); 13648 pool++; 13649 LOG_DEBUG(BSL_LS_BCM_POLICER, 13650 (BSL_META_U(unit, 13651 "allocated policer with pid %x \n"), 13652 *pid)); 13653 13654 return rv; 13655 } 13656 } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 13657 13658 /* alloc horizontally */ 13659 rv = _bcm_gloabl_meter_alloc_horizontally(unit, numbers, pid, 13660 pid_offset); 13661 if (!BCM_SUCCESS(rv)) { 13662 return BCM_E_FULL; 13663 } 13664 *pid |= (*pid_offset << _shr_popcount(size_pool - 1)); 13665 LOG_DEBUG(BSL_LS_BCM_POLICER, 13666 (BSL_META_U(unit, 13667 "allocated policer with pid %x \n"), 13668 *pid)); 13669 } 13670 return rv; 13671 } 13672 /* 13673 * Function: 13674 * _bcm_global_meter_max_rate_set 13675 * Purpose: 13676 * get CIR/EIR max value. 13677 * Parameters: 13678 * rate - (IN) CIR/EIR 13679 * refreshmax - (IN) refresh_max value 13680 * max_rate - (OUT) CIR/EIR max value 13681 * Returns: 13682 * BCM_E_XXX 13683 */ 13684 void _bcm_global_meter_max_rate_set(uint32 rate, 13685 uint32 refreshmax, uint32 *max_rate) { 13686 if (rate == 0) { 13687 *max_rate = 0; 13688 } 13689 if (refreshmax == GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT) { 13690 *max_rate = 0xffffffff; 13691 } else { 13692 *max_rate = (rate * refresh_max[refreshmax]) / 100; 13693 } 13694 } 13695 13696 /* 13697 * Function: 13698 * _bcm_global_meter_read_config_from_hw 13699 * Purpose: 13700 * Read policer configuration form the HW table entry. 13701 * Parameters: 13702 * unit - (IN) unit number 13703 * policer_id - (IN) policer id 13704 * pol_cfg - (OUT) policer configuration 13705 * Returns: 13706 * BCM_E_XXX 13707 */ 13708 int _bcm_global_meter_read_config_from_hw(int unit, 13709 bcm_policer_t policer_id, 13710 bcm_policer_config_t *pol_cfg) 13711 { 13712 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 13713 svm_meter_table_entry_t data; 13714 int rv = BCM_E_NONE; 13715 uint32 refresh_rate = 0; /* Policer refresh rate. */ 13716 uint32 granularity = 0; /* Policer granularity. */ 13717 uint32 mode = 0, mode_modifier = 0, coupling = 0; 13718 uint32 bucket_count = 0, bucket_size = 0; 13719 int index = 0, cascade_index = 0; 13720 uint32 refreshmax = 0; 13721 uint32 chain = 0; 13722 uint32 pkt_bytes = 0; 13723 _global_meter_policer_control_t *policer_control = NULL; 13724 uint32 flags=0; 13725 13726 /* read HW register */ 13727 _bcm_esw_get_policer_table_index(unit, policer_id, &index); 13728 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,index, &data); 13729 if (!BCM_SUCCESS(rv)) { 13730 LOG_DEBUG(BSL_LS_BCM_POLICER, 13731 (BSL_META_U(unit, 13732 "Unable to read SVM METER TABLE at index %d " 13733 "\n"), index)); 13734 return rv; 13735 } 13736 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) { 13737 soc_SVM_METER_TABLEm_field_get(unit, &data, COUPLING_FLAGf, &coupling); 13738 } 13739 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) { 13740 soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODIFIERf, 13741 &mode_modifier); 13742 if (mode_modifier == 0) { 13743 pol_cfg->flags = BCM_POLICER_COLOR_BLIND; 13744 } else { 13745 pol_cfg->flags = 0; /* color aware */ 13746 } 13747 } 13748 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) { 13749 soc_SVM_METER_TABLEm_field_get(unit, &data, PKT_BYTESf, 13750 &pkt_bytes); 13751 if (pkt_bytes == 0) { 13752 pol_cfg->flags |= BCM_POLICER_MODE_BYTES; 13753 } else { 13754 pol_cfg->flags |= BCM_POLICER_MODE_PACKETS; 13755 } 13756 13757 } 13758 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 13759 soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODEf, &mode); 13760 switch (mode) { 13761 13762 case GLOBAL_METER_MODE_DEFAULT: 13763 if (mode_modifier) { 13764 pol_cfg->mode = bcmPolicerModePassThrough; 13765 } else { 13766 pol_cfg->mode = bcmPolicerModeGreen; 13767 } 13768 break; 13769 13770 case GLOBAL_METER_MODE_SR_TCM: 13771 pol_cfg->mode = bcmPolicerModeSrTcm; 13772 break; 13773 13774 case GLOBAL_METER_MODE_SR_TCM_MODIFIED: 13775 pol_cfg->mode = bcmPolicerModeSrTcmModified; 13776 break; 13777 13778 case GLOBAL_METER_MODE_TR_TCM: 13779 pol_cfg->mode = bcmPolicerModeTrTcm; 13780 break; 13781 13782 case GLOBAL_METER_MODE_TR_TCM_MODIFIED: 13783 pol_cfg->mode = bcmPolicerModeTrTcmDs; 13784 if (coupling) { 13785 pol_cfg->mode = bcmPolicerModeCoupledTrTcmDs; 13786 } 13787 break; 13788 13789 case GLOBAL_METER_MODE_CASCADE: 13790 pol_cfg->mode = bcmPolicerModeCascade; 13791 if (coupling) { 13792 pol_cfg->mode = bcmPolicerModeCoupledCascade; 13793 } 13794 break; 13795 13796 default: 13797 break; 13798 } 13799 } 13800 13801 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_BUCKETCOUNTf)) { 13802 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETCOUNTf, 13803 &bucket_count); 13804 } 13805 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_REFRESHCOUNTf)) { 13806 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHCOUNTf, 13807 &refresh_rate); 13808 } 13809 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COMMITTED_BUCKETSIZEf)) { 13810 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETSIZEf, 13811 &bucket_size); 13812 } 13813 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) { 13814 soc_SVM_METER_TABLEm_field_get(unit, &data, METER_GRANf,&granularity); 13815 } 13816 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHMAXf, 13817 &refreshmax); 13818 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 13819 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 13820 13821 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 13822 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 13823 } 13824 if (pol_cfg->mode == bcmPolicerModeCoupledCascade) { 13825 rv = _bcm_xgs_bucket_encoding_to_kbits 13826 (refresh_rate, bucket_size, granularity, 13827 flags, 13828 &pol_cfg->pkbits_sec, &pol_cfg->pkbits_burst); 13829 if (!BCM_SUCCESS(rv)) { 13830 LOG_DEBUG(BSL_LS_BCM_POLICER, 13831 (BSL_META_U(unit, 13832 "Unable to translate rate in kbps to bucket size " 13833 "and granularity \n"))); 13834 return rv; 13835 } 13836 _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec, 13837 refreshmax, &pol_cfg->max_pkbits_sec); 13838 } else { 13839 rv = _bcm_xgs_bucket_encoding_to_kbits 13840 (refresh_rate, bucket_size, granularity, 13841 flags, 13842 &pol_cfg->ckbits_sec, &pol_cfg->ckbits_burst); 13843 if (!BCM_SUCCESS(rv)) { 13844 LOG_DEBUG(BSL_LS_BCM_POLICER, 13845 (BSL_META_U(unit, 13846 "Unable to translate rate in kbps to bucket size " 13847 "and granularity \n"))); 13848 return rv; 13849 } 13850 _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec, 13851 refreshmax, &pol_cfg->max_ckbits_sec); 13852 } 13853 13854 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) { 13855 soc_SVM_METER_TABLEm_field_get(unit, &data, 13856 METER_SHARING_MODEf, &pol_cfg->sharing_mode); 13857 } 13858 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) { 13859 soc_SVM_METER_TABLEm_field_get(unit, 13860 &data, POLICY_TABLE_INDEXf, &pol_cfg->action_id); 13861 } 13862 13863 if (mode == GLOBAL_METER_MODE_CASCADE) { 13864 soc_SVM_METER_TABLEm_field_get(unit, &data, START_OF_CHAINf, &chain); 13865 if (chain) { 13866 pol_cfg->flags |= BCM_POLICER_BW_SHARING_GROUP_START; 13867 } 13868 soc_SVM_METER_TABLEm_field_get(unit, &data, END_OF_CHAINf, &chain); 13869 if (chain) { 13870 pol_cfg->flags |= BCM_POLICER_BW_SHARING_GROUP_END; 13871 } 13872 } 13873 13874 if (pol_cfg->mode == bcmPolicerModeCoupledCascade) { 13875 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 13876 if (BCM_FAILURE(rv)) { 13877 LOG_DEBUG(BSL_LS_BCM_POLICER, 13878 (BSL_META_U(unit, 13879 "Unable to get policer control for the policer Id " 13880 "passed \n"))); 13881 return (rv); 13882 } 13883 13884 rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit, 13885 policer_id, policer_control, &cascade_index); 13886 BCM_IF_ERROR_RETURN(rv); 13887 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 13888 cascade_index, &data); 13889 if (!BCM_SUCCESS(rv)) { 13890 LOG_DEBUG(BSL_LS_BCM_POLICER, 13891 (BSL_META_U(unit, 13892 "Unable to read SVM METER TABLE at index %d " 13893 "\n"), cascade_index)); 13894 return rv; 13895 } 13896 13897 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHMAXf, 13898 &refreshmax); 13899 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETCOUNTf, 13900 &bucket_count); 13901 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_REFRESHCOUNTf, 13902 &refresh_rate); 13903 soc_SVM_METER_TABLEm_field_get(unit, &data, COMMITTED_BUCKETSIZEf, 13904 &bucket_size); 13905 rv = _bcm_xgs_bucket_encoding_to_kbits 13906 (refresh_rate, bucket_size, granularity, 13907 _BCM_XGS_METER_FLAG_GRANULARITY | 13908 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER, 13909 &pol_cfg->ckbits_sec, &pol_cfg->ckbits_burst); 13910 if (!BCM_SUCCESS(rv)) { 13911 LOG_DEBUG(BSL_LS_BCM_POLICER, 13912 (BSL_META_U(unit, 13913 "Unable to translate rate in kbps to bucket size " 13914 "and granularity \n"))); 13915 return rv; 13916 } 13917 _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec, 13918 refreshmax, &pol_cfg->max_ckbits_sec); 13919 } else { 13920 soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_REFRESHMAXf, 13921 &refreshmax); 13922 soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_BUCKETCOUNTf, 13923 &bucket_count); 13924 soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_REFRESHCOUNTf, 13925 &refresh_rate); 13926 soc_SVM_METER_TABLEm_field_get(unit, &data, EXCESS_BUCKETSIZEf, 13927 &bucket_size); 13928 rv = _bcm_xgs_bucket_encoding_to_kbits 13929 (refresh_rate, bucket_size, granularity, 13930 _BCM_XGS_METER_FLAG_GRANULARITY | 13931 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER, 13932 &pol_cfg->pkbits_sec, &pol_cfg->pkbits_burst); 13933 if (!BCM_SUCCESS(rv)) { 13934 LOG_DEBUG(BSL_LS_BCM_POLICER, 13935 (BSL_META_U(unit, 13936 "Unable to translate rate in kbps to bucket size " 13937 "and granularity \n"))); 13938 return rv; 13939 } 13940 _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec, 13941 refreshmax, &pol_cfg->max_pkbits_sec); 13942 } 13943 13944 return rv; 13945 #else 13946 return BCM_E_UNAVAIL; 13947 #endif 13948 } 13949 13950 #if defined(BCM_APACHE_SUPPORT) 13951 STATIC int 13952 _bcm_global_meter_get_pool_from_policerId (int unit, 13953 bcm_policer_t policer_id) 13954 { 13955 int size_pool = 0, num_pools = 0; 13956 int offset_mask = 0; 13957 int pool_mask = 0, pool_offset = 0; 13958 13959 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 13960 num_pools = SOC_INFO(unit).global_meter_pools; 13961 offset_mask = size_pool - 1; 13962 pool_offset = _shr_popcount(offset_mask); 13963 pool_mask = (num_pools - 1) << pool_offset; 13964 13965 return ((policer_id & pool_mask) >> pool_offset); 13966 } 13967 #endif 13968 13969 /* 13970 * Function: 13971 * _bcm_global_meter_read_config_from_hw_mef_10dot3 13972 * Purpose: 13973 * Read policer configuration form the HW table entry. 13974 * Parameters: 13975 * unit - (IN) unit number 13976 * policer_id - (IN) policer id 13977 * pol_cfg - (OUT) policer configuration 13978 * Returns: 13979 * BCM_E_XXX 13980 */ 13981 int 13982 _bcm_global_meter_read_config_from_hw_mef_10dot3 (int unit, 13983 bcm_policer_t policer_id, 13984 bcm_policer_config_t *pol_cfg) 13985 { 13986 #if defined(BCM_APACHE_SUPPORT) 13987 svm_meter_table_entry_t svm_entry; 13988 int rv = BCM_E_NONE; 13989 uint32 refresh_rate = 0; /* Policer refresh rate. */ 13990 uint32 granularity = 0; /* Policer granularity. */ 13991 uint32 mode = 0, mode_modifier = 0, coupling = 0; 13992 uint32 bucket_count = 0, bucket_size = 0; 13993 int index = 0, cascade_index = 0; 13994 uint32 refreshmax = 0, c_e = 0; 13995 uint32 pkt_bytes = 0, flags = 0; 13996 uint32 nxt_c = 0, nxt_e = 0, pair_e = 0; 13997 uint32 nxt_c_valid = 0, nxt_e_valid = 0, pair_e_valid = 0; 13998 int gcf_mode = 0; 13999 bcm_policer_t corres_policer = 0; 14000 _global_meter_policer_control_t *policer_control = NULL; 14001 14002 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 14003 if (BCM_FAILURE(rv)) { 14004 LOG_DEBUG(BSL_LS_BCM_POLICER, 14005 (BSL_META_U(unit, 14006 "Unable to get policer control for the policer Id " 14007 "passed \n"))); 14008 return (rv); 14009 } 14010 14011 /* read HW register */ 14012 _bcm_esw_get_policer_table_index(unit, policer_id, &index); 14013 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY,index, &svm_entry); 14014 if (!BCM_SUCCESS(rv)) { 14015 LOG_DEBUG(BSL_LS_BCM_POLICER, 14016 (BSL_META_U(unit, 14017 "Unable to read SVM METER TABLE at index %d " 14018 "\n"), index)); 14019 return rv; 14020 } 14021 14022 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COUPLING_FLAGf, &coupling); 14023 14024 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_MODIFIERf, 14025 &mode_modifier); 14026 if (mode_modifier == 0) { 14027 pol_cfg->flags = BCM_POLICER_COLOR_BLIND; 14028 } else { 14029 pol_cfg->flags = 0; /* color aware */ 14030 } 14031 14032 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, PKT_BYTESf, &pkt_bytes); 14033 if (pkt_bytes == 0) { 14034 pol_cfg->flags |= BCM_POLICER_MODE_BYTES; 14035 } else { 14036 pol_cfg->flags |= BCM_POLICER_MODE_PACKETS; 14037 } 14038 14039 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 14040 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_MODEf, &mode); 14041 switch (mode) { 14042 14043 case GLOBAL_METER_MODE_DEFAULT: 14044 if (mode_modifier) { 14045 pol_cfg->mode = bcmPolicerModePassThrough; 14046 } else { 14047 pol_cfg->mode = bcmPolicerModeGreen; 14048 } 14049 break; 14050 14051 case GLOBAL_METER_MODE_SR_TCM: 14052 pol_cfg->mode = bcmPolicerModeSrTcm; 14053 break; 14054 14055 case GLOBAL_METER_MODE_SR_TCM_MODIFIED: 14056 pol_cfg->mode = bcmPolicerModeSrTcmModified; 14057 break; 14058 14059 case GLOBAL_METER_MODE_TR_TCM: 14060 pol_cfg->mode = bcmPolicerModeTrTcm; 14061 break; 14062 14063 case GLOBAL_METER_MODE_TR_TCM_MODIFIED: 14064 pol_cfg->mode = bcmPolicerModeTrTcmDs; 14065 if (coupling) { 14066 pol_cfg->mode = bcmPolicerModeCoupledTrTcmDs; 14067 } 14068 break; 14069 14070 case GLOBAL_METER_MODE_CASCADE: 14071 pol_cfg->mode = bcmPolicerModeCascade; 14072 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, 14073 METER_PAIR_EXCESS_BUCKET_VALIDf)) { 14074 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14075 METER_PAIR_EXCESS_BUCKET_VALIDf, 14076 &pair_e_valid); 14077 } 14078 if (pair_e_valid == 1) { 14079 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, 14080 METER_PAIR_EXCESS_BUCKETf)) { 14081 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14082 METER_PAIR_EXCESS_BUCKETf, 14083 &pair_e); 14084 } 14085 14086 gcf_mode = 0; 14087 if ((policer_control->grp_mode == bcmPolicerGroupModeCascade) || 14088 (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade) || 14089 (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) { 14090 /* Group is non-gcf mode */ 14091 gcf_mode = 0; 14092 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14093 COMMITTED_EXCESSf, &c_e); 14094 if (c_e == 1) { 14095 /* this policer is coupled cascade */ 14096 pol_cfg->mode = bcmPolicerModeCoupledCascade; 14097 } 14098 } else if ((policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling) || 14099 (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 14100 /* Group is GCF mode */ 14101 gcf_mode = 1; 14102 pol_cfg->mode = bcmPolicerModeCoupledCascade; 14103 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14104 COMMITTED_EXCESSf, &c_e); 14105 } 14106 } 14107 break; 14108 14109 default: 14110 break; 14111 } 14112 } 14113 14114 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_BUCKETCOUNTf, 14115 &bucket_count); 14116 14117 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_REFRESHCOUNTf, 14118 &refresh_rate); 14119 14120 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_BUCKETSIZEf, 14121 &bucket_size); 14122 14123 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, METER_GRANf,&granularity); 14124 14125 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, COMMITTED_REFRESHMAXf, 14126 &refreshmax); 14127 14128 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 14129 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 14130 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 14131 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 14132 } 14133 14134 rv = _bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucket_size, 14135 granularity, flags, 14136 &pol_cfg->ckbits_sec, 14137 &pol_cfg->ckbits_burst); 14138 if (!BCM_SUCCESS(rv)) { 14139 LOG_DEBUG(BSL_LS_BCM_POLICER, 14140 (BSL_META_U(unit, 14141 "Unable to translate rate in kbps to bucket size " 14142 "and granularity \n"))); 14143 return rv; 14144 } 14145 _bcm_global_meter_max_rate_set(pol_cfg->ckbits_sec, 14146 refreshmax, &pol_cfg->max_ckbits_sec); 14147 14148 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14149 METER_SHARING_MODEf, 14150 &pol_cfg->sharing_mode); 14151 14152 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, POLICY_TABLE_INDEXf, 14153 &pol_cfg->action_id); 14154 14155 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14156 NXT_EXCESS_BUCKET_VALIDf, 14157 &nxt_e_valid); 14158 if ((gcf_mode == 0) && (nxt_e_valid == 1)) { 14159 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14160 NXT_EXCESS_BUCKETf, 14161 &nxt_e); 14162 rv = _bcm_esw_get_corres_policer_for_pool(unit, policer_id, nxt_e, &corres_policer); 14163 BCM_IF_ERROR_RETURN(rv); 14164 pol_cfg->npoflow_policer_id = corres_policer; 14165 } 14166 14167 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14168 NXT_COMMITTED_BUCKET_VALIDf, 14169 &nxt_c_valid); 14170 if ((gcf_mode == 0) && (nxt_c_valid == 1)) { 14171 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14172 NXT_COMMITTED_BUCKETf, 14173 &nxt_c); 14174 rv = _bcm_esw_get_corres_policer_for_pool(unit, policer_id, nxt_c, &corres_policer); 14175 BCM_IF_ERROR_RETURN(rv); 14176 pol_cfg->ncoflow_policer_id = corres_policer; 14177 } 14178 14179 if (pol_cfg->mode == bcmPolicerModeCoupledCascade) { 14180 if (gcf_mode == 1) { 14181 /* Get the next Committed bucket / Excess bucket */ 14182 if (c_e == 0) { 14183 /* One of the pools from 0-2. Next Commit pool is set in nxt_c 14184 and Next Excess pool will be same */ 14185 if (nxt_c_valid == 1) { 14186 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, 14187 NXT_COMMITTED_BUCKETf, 14188 &nxt_c); 14189 rv = _bcm_esw_get_corres_policer_for_pool(unit, policer_id, nxt_c, &corres_policer); 14190 BCM_IF_ERROR_RETURN(rv); 14191 pol_cfg->ncoflow_policer_id = corres_policer; 14192 pol_cfg->npoflow_policer_id = corres_policer; 14193 } 14194 } 14195 rv = _bcm_global_meter_get_coupled_cascade_policer_index(unit, 14196 policer_id, policer_control, &cascade_index); 14197 } else { 14198 /* Group is configured as cascade but this policer mode is coupled cascade */ 14199 /* Excess bucket of this policer is stored in pool of nxt_c */ 14200 rv = _bcm_esw_get_corres_policer_for_pool(unit, policer_id, nxt_c, &corres_policer); 14201 BCM_IF_ERROR_RETURN(rv); 14202 rv = _bcm_esw_get_policer_table_index(unit, corres_policer, &cascade_index); 14203 } 14204 BCM_IF_ERROR_RETURN(rv); 14205 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 14206 cascade_index, &svm_entry); 14207 if (!BCM_SUCCESS(rv)) { 14208 LOG_DEBUG(BSL_LS_BCM_POLICER, 14209 (BSL_META_U(unit, 14210 "Unable to read SVM METER TABLE at index %d " 14211 "\n"), cascade_index)); 14212 return rv; 14213 } 14214 } 14215 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_REFRESHMAXf, 14216 &refreshmax); 14217 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_BUCKETCOUNTf, 14218 &bucket_count); 14219 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_REFRESHCOUNTf, 14220 &refresh_rate); 14221 soc_SVM_METER_TABLEm_field_get(unit, &svm_entry, EXCESS_BUCKETSIZEf, 14222 &bucket_size); 14223 rv = _bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucket_size, granularity, 14224 _BCM_XGS_METER_FLAG_GRANULARITY | _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER, 14225 &pol_cfg->pkbits_sec, 14226 &pol_cfg->pkbits_burst); 14227 if (!BCM_SUCCESS(rv)) { 14228 LOG_DEBUG(BSL_LS_BCM_POLICER, 14229 (BSL_META_U(unit, 14230 "Unable to translate rate in kbps to bucket size " 14231 "and granularity \n"))); 14232 return rv; 14233 } 14234 _bcm_global_meter_max_rate_set(pol_cfg->pkbits_sec, 14235 refreshmax, &pol_cfg->max_pkbits_sec); 14236 14237 return rv; 14238 #else 14239 return BCM_E_UNAVAIL; 14240 #endif 14241 } 14242 14243 /* 14244 * Function: 14245 * _bcm_esw_policer_action_detach 14246 * Purpose: 14247 * Internal function to Disassociate a policer action from a given 14248 * policer id and readjust reference count. 14249 * Parameters: 14250 * unit - (IN) unit number 14251 * policer_id - (IN) policer id 14252 * action_id - (IN) Action ID 14253 * Returns: 14254 * BCM_E_XXX 14255 */ 14256 int _bcm_esw_policer_action_detach(int unit, bcm_policer_t policer_id, 14257 uint32 action_id) 14258 { 14259 int rv = BCM_E_NONE; 14260 svm_meter_table_entry_t meter_entry; 14261 _global_meter_policer_control_t *policer_control = NULL; 14262 int policer_index = 0; 14263 uint32 policy_index = 0; 14264 int index = 0; 14265 if (!soc_feature(unit, soc_feature_global_meter)) { 14266 return BCM_E_UNAVAIL; 14267 } 14268 CHECK_GLOBAL_METER_INIT(unit); 14269 /* validate policer id */ 14270 rv = _bcm_esw_policer_validate(unit, &policer_id); 14271 if (BCM_FAILURE(rv)) { 14272 LOG_DEBUG(BSL_LS_BCM_POLICER, 14273 (BSL_META_U(unit, 14274 "Invalid Policer Id \n"))); 14275 return (rv); 14276 } 14277 /* validate action id */ 14278 if (action_id > soc_mem_index_max(unit, SVM_POLICY_TABLEm)) { 14279 LOG_ERROR(BSL_LS_BCM_POLICER, 14280 (BSL_META_U(unit, 14281 "Invalid Action Id \n"))); 14282 return BCM_E_PARAM; 14283 } 14284 GLOBAL_METER_LOCK(unit); 14285 14286 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 14287 if (BCM_FAILURE(rv)) { 14288 GLOBAL_METER_UNLOCK(unit); 14289 LOG_DEBUG(BSL_LS_BCM_POLICER, 14290 (BSL_META_U(unit, 14291 "Unable to get policer control for the policer Id " 14292 "passed \n"))); 14293 return (rv); 14294 } 14295 /* read meter table and remove action_id*/ 14296 _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index); 14297 rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index, 14298 &meter_entry); 14299 if (BCM_FAILURE(rv)) { 14300 GLOBAL_METER_UNLOCK(unit); 14301 LOG_DEBUG(BSL_LS_BCM_POLICER, 14302 (BSL_META_U(unit, 14303 "Unable to read SVM_METER_TABLE entry \n"))); 14304 return (rv); 14305 } 14306 /* set action to 0 */ 14307 soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf, 14308 &policy_index); 14309 14310 /* Write to HW*/ 14311 rv = WRITE_SVM_METER_TABLEm(unit,MEM_BLOCK_ANY, policer_index, 14312 &meter_entry); 14313 if (BCM_FAILURE(rv)) { 14314 GLOBAL_METER_UNLOCK(unit); 14315 LOG_DEBUG(BSL_LS_BCM_POLICER, 14316 (BSL_META_U(unit, 14317 "Unable to write SVM_METER_TABLE entry \n"))); 14318 return (rv); 14319 } 14320 /* in case of cascade with coupling we need to configure the second set 14321 as well */ 14322 if ((policer_control->grp_mode == \ 14323 bcmPolicerGroupModeIntPriCascadeWithCoupling) || 14324 (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) { 14325 14326 rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit, 14327 policer_id, policer_control, &index); 14328 /* read meter table and remove action_id*/ 14329 rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, index, 14330 &meter_entry); 14331 if (BCM_FAILURE(rv)) { 14332 GLOBAL_METER_UNLOCK(unit); 14333 LOG_DEBUG(BSL_LS_BCM_POLICER, 14334 (BSL_META_U(unit, 14335 "Unable to read SVM_METER_TABLE entry \n"))); 14336 return (rv); 14337 } 14338 /* set action to 0 */ 14339 soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf, 14340 &policy_index); 14341 /* write to hW */ 14342 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, 14343 &meter_entry); 14344 if (BCM_FAILURE(rv)) { 14345 LOG_DEBUG(BSL_LS_BCM_POLICER, 14346 (BSL_META_U(unit, 14347 "Unable to write SVM_METER_TABLE entry \n"))); 14348 GLOBAL_METER_UNLOCK(unit); 14349 return (rv); 14350 } 14351 } 14352 14353 /* decrement action usage reference count */ 14354 if (global_meter_action_bookkeep[unit][action_id].reference_count > 0) { 14355 global_meter_action_bookkeep[unit][action_id].reference_count--; 14356 } 14357 /* reset action id in policer control */ 14358 policer_control->action_id = 0; 14359 GLOBAL_METER_UNLOCK(unit); 14360 return rv; 14361 } 14362 14363 14364 /* 14365 * Function: 14366 * _bcm_global_meter_refresh_max_get 14367 * Purpose: 14368 * get refresh max value. 14369 * Parameters: 14370 * rate - (IN) CIR/EIR 14371 * max_rate - (IN) CIRmax/EIRmax 14372 * refreshmax - (OUT) REFRESH_MAX value 14373 * Returns: 14374 * BCM_E_XXX 14375 */ 14376 int _bcm_global_meter_refresh_max_get(uint32 rate, 14377 uint32 max_rate, uint32 *refreshmax) { 14378 int found = 0; 14379 int multiplier = 0, i = 0; 14380 if (rate == 0 && max_rate > 0) { 14381 *refreshmax = GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT; 14382 } else if (rate >= max_rate) { 14383 *refreshmax = 0; 14384 } else { 14385 multiplier = ((max_rate * 100) / rate); 14386 while ((refresh_max[i] != 0) && (found == 0)) { 14387 if (refresh_max[i] == multiplier) { 14388 *refreshmax = i; 14389 found = 1; 14390 } else if ((refresh_max[i] > multiplier) && (i > 0)) { 14391 if (((refresh_max[i - 1] + refresh_max[i]) / 2) >= multiplier) { 14392 *refreshmax = (i - 1); 14393 } else { 14394 *refreshmax = i; 14395 } 14396 found = 1; 14397 } 14398 i++; 14399 } 14400 if (found == 0) { 14401 *refreshmax = GLOBAL_METER_REFRESH_MAX_DISABLE_LIMIT; 14402 } 14403 } 14404 return BCM_E_NONE; 14405 } 14406 14407 14408 /* 14409 * Function: 14410 * _bcm_global_meter_write_config_to_hw 14411 * Purpose: 14412 * Write policer configuraton to meter table. 14413 * Parameters: 14414 * unit - (IN) unit number 14415 * pol_cfg - (IN) policer configuration 14416 * policer_id - (IN) policer id 14417 * policer_control - (IN) Policer control info 14418 * Returns: 14419 * BCM_E_XXX 14420 */ 14421 int _bcm_global_meter_write_config_to_hw(int unit, 14422 bcm_policer_config_t *pol_cfg, 14423 bcm_policer_t policer_id, 14424 _global_meter_policer_control_t *policer_control) 14425 { 14426 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 14427 int rv = BCM_E_NONE; 14428 svm_meter_table_entry_t data; 14429 uint32 flags=0; 14430 uint32 c_bucketsize = 0, e_bucketsize = 0; /* Bucket size. */ 14431 uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate.*/ 14432 uint32 granularity = 0; /* Policer granularity. */ 14433 uint32 refresh_bitsize; /* Number of bits for the 14434 refresh rate field. */ 14435 uint32 bucket_max_bitsize; /* Number of bits for the 14436 bucket max field. */ 14437 uint32 c_bucketcount = 0, e_bucketcount=0, bucket_cnt_bitsize = 0; 14438 uint32 mode = 0, mode_modifier = 0; 14439 uint32 coupling = 0, policy_index = 0; 14440 uint32 c_refreshmax = 0, e_refreshmax = 0; 14441 int index = 0; 14442 uint32 current_action_id = 0; 14443 bcm_policer_t macro_meter_policer = 0; 14444 int macro_flow_meter_index = 0; 14445 svm_macroflow_index_table_entry_t macro_flow_entry; 14446 uint32 start_of_chain = 0, end_of_chain = 0; 14447 uint32 pkt_bytes = 0; 14448 int incr_reqd = 0; 14449 /* read HW register */ 14450 _bcm_esw_get_policer_table_index(unit, policer_id, &index); 14451 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &data); 14452 BCM_IF_ERROR_RETURN(rv); 14453 policy_index = pol_cfg->action_id; 14454 14455 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) { 14456 soc_SVM_METER_TABLEm_field_get(unit, 14457 &data, POLICY_TABLE_INDEXf, ¤t_action_id); 14458 if( policy_index != current_action_id ) { 14459 if(current_action_id != 0) { 14460 /* detach the existing action and 14461 * decrement reference count 14462 */ 14463 _bcm_esw_policer_action_detach(unit, policer_id, 14464 current_action_id); 14465 } 14466 soc_SVM_METER_TABLEm_field_set(unit, &data, 14467 POLICY_TABLE_INDEXf, &policy_index); 14468 if (policy_index != 0) { 14469 incr_reqd = 1; 14470 } 14471 } 14472 } 14473 14474 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 14475 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 14476 14477 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 14478 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 14479 } else { 14480 flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE; 14481 } 14482 refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14483 COMMITTED_REFRESHCOUNTf); 14484 bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14485 COMMITTED_BUCKETSIZEf); 14486 14487 /* Calculate policer bucket size/refresh_rate/granularity. */ 14488 if (pol_cfg->pkbits_sec > pol_cfg->ckbits_sec) { 14489 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec, 14490 pol_cfg->pkbits_burst, 14491 flags, refresh_bitsize, 14492 bucket_max_bitsize, 14493 &c_refresh_rate, &c_bucketsize, 14494 &granularity); 14495 BCM_IF_ERROR_RETURN(rv); 14496 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 14497 pol_cfg->ckbits_sec, 14498 pol_cfg->ckbits_burst, 14499 flags, refresh_bitsize, 14500 bucket_max_bitsize, 14501 &c_refresh_rate, &c_bucketsize, 14502 &granularity); 14503 BCM_IF_ERROR_RETURN(rv); 14504 } else { 14505 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->ckbits_sec, 14506 pol_cfg->ckbits_burst, 14507 flags, refresh_bitsize, 14508 bucket_max_bitsize, 14509 &c_refresh_rate, &c_bucketsize, 14510 &granularity); 14511 BCM_IF_ERROR_RETURN(rv); 14512 } 14513 14514 /* Calculate initial backet count. 14515 * bucket size << (bit count diff - 1(sign) -1 (overflow)) - 1 14516 */ 14517 bucket_cnt_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14518 COMMITTED_BUCKETCOUNTf); 14519 if (c_bucketsize == 0 && c_refresh_rate == 0) { 14520 /* Committed should always be out of profile */ 14521 c_bucketcount = (1 << bucket_cnt_bitsize) - 1; 14522 } else if (c_bucketsize) { 14523 c_bucketcount = 14524 (c_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1; 14525 c_bucketcount &= ((1 << bucket_cnt_bitsize) - 1); 14526 } else { 14527 c_bucketcount = 0; 14528 } 14529 rv =_bcm_global_meter_refresh_max_get(pol_cfg->ckbits_sec, 14530 pol_cfg->max_ckbits_sec, &c_refreshmax); 14531 BCM_IF_ERROR_RETURN(rv); 14532 14533 if (pol_cfg->mode == bcmPolicerModeCoupledCascade) { 14534 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHMAXf, 14535 &e_refreshmax); 14536 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETCOUNTf, 14537 &e_bucketcount); 14538 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHCOUNTf, 14539 &e_refresh_rate); 14540 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETSIZEf, 14541 &e_bucketsize); 14542 } else { 14543 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf, 14544 &c_refreshmax); 14545 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf, 14546 &c_bucketcount); 14547 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf, 14548 &c_refresh_rate); 14549 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf, 14550 &c_bucketsize); 14551 } 14552 14553 refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14554 EXCESS_REFRESHCOUNTf); 14555 bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14556 EXCESS_BUCKETSIZEf); 14557 14558 if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) { 14559 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec, 14560 pol_cfg->pkbits_burst, 14561 flags, refresh_bitsize, 14562 bucket_max_bitsize, 14563 &e_refresh_rate, &e_bucketsize, 14564 &granularity); 14565 14566 } else { 14567 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 14568 pol_cfg->pkbits_sec, 14569 pol_cfg->pkbits_burst, 14570 flags, refresh_bitsize, 14571 bucket_max_bitsize, 14572 &e_refresh_rate, &e_bucketsize, 14573 &granularity); 14574 } 14575 BCM_IF_ERROR_RETURN(rv); 14576 /* Calculate initial backet count. 14577 * bucket size << (bit count diff - 1(sign) -1 (overflow)) - 1 14578 */ 14579 bucket_cnt_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14580 EXCESS_BUCKETCOUNTf); 14581 if (e_bucketsize == 0 && e_refresh_rate == 0) { 14582 /* Excess should always be out of profile */ 14583 e_bucketcount = (1 << bucket_cnt_bitsize) - 1; 14584 } else if (e_bucketsize) { 14585 e_bucketcount = 14586 (e_bucketsize << (bucket_cnt_bitsize - bucket_max_bitsize - 2)) - 1; 14587 e_bucketcount &= ((1 << bucket_cnt_bitsize) - 1); 14588 } else { 14589 e_bucketcount = 0; 14590 } 14591 /* Set HW register */ 14592 14593 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) { 14594 soc_SVM_METER_TABLEm_field_set(unit, &data, METER_GRANf, &granularity); 14595 } 14596 14597 rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec, 14598 pol_cfg->max_pkbits_sec, &e_refreshmax); 14599 BCM_IF_ERROR_RETURN(rv); 14600 14601 if (pol_cfg->mode == bcmPolicerModeCoupledCascade) { 14602 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf, 14603 &e_refreshmax); 14604 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf, 14605 &e_bucketcount); 14606 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf, 14607 &e_refresh_rate); 14608 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf, 14609 &e_bucketsize); 14610 } else { 14611 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHMAXf, 14612 &e_refreshmax); 14613 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETCOUNTf, 14614 &e_bucketcount); 14615 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_REFRESHCOUNTf, 14616 &e_refresh_rate); 14617 soc_SVM_METER_TABLEm_field_set(unit, &data, EXCESS_BUCKETSIZEf, 14618 &e_bucketsize); 14619 } 14620 /* PKT/BYTE - by default BYTE counter */ 14621 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) { 14622 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 14623 pkt_bytes = 1; 14624 soc_SVM_METER_TABLEm_field_set(unit, &data, PKT_BYTESf, &pkt_bytes); 14625 } 14626 } 14627 /* MIN/MAX/MIN_MAX */ 14628 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) { 14629 soc_SVM_METER_TABLEm_field_set(unit, &data, METER_SHARING_MODEf, 14630 &pol_cfg->sharing_mode); 14631 } 14632 if (pol_cfg->flags & BCM_POLICER_COLOR_BLIND) { 14633 mode_modifier = 0; /* color blind */ 14634 } else { 14635 mode_modifier = 1; /* color aware */ 14636 } 14637 14638 switch (pol_cfg->mode) { 14639 case bcmPolicerModeGreen: 14640 mode = GLOBAL_METER_MODE_DEFAULT; 14641 mode_modifier = 0; 14642 break; 14643 14644 case bcmPolicerModePassThrough: 14645 mode = GLOBAL_METER_MODE_DEFAULT; 14646 mode_modifier = 1; 14647 break; 14648 14649 case bcmPolicerModeSrTcm: 14650 mode = GLOBAL_METER_MODE_SR_TCM; 14651 break; 14652 14653 case bcmPolicerModeSrTcmModified: 14654 mode = GLOBAL_METER_MODE_SR_TCM_MODIFIED; 14655 break; 14656 14657 case bcmPolicerModeTrTcm: 14658 mode = GLOBAL_METER_MODE_TR_TCM; 14659 break; 14660 14661 case bcmPolicerModeTrTcmDs: 14662 mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED; 14663 break; 14664 14665 case bcmPolicerModeCoupledTrTcmDs: 14666 mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED; 14667 coupling = 1; 14668 break; 14669 14670 case bcmPolicerModeCascade: 14671 mode = GLOBAL_METER_MODE_CASCADE; 14672 coupling = 0; 14673 break; 14674 14675 case bcmPolicerModeCoupledCascade: 14676 mode = GLOBAL_METER_MODE_CASCADE; 14677 coupling = 1; 14678 break; 14679 14680 default: 14681 LOG_DEBUG(BSL_LS_BCM_POLICER, 14682 (BSL_META_U(unit, 14683 "Invalid policer mode \n"))); 14684 return BCM_E_PARAM; 14685 break; 14686 } 14687 /* SRTCM TrTcm Modified SrTcm, Modified TrTcm, cascade, default */ 14688 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 14689 soc_SVM_METER_TABLEm_field_set(unit, &data, METER_MODEf, &mode); 14690 } 14691 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) { 14692 soc_SVM_METER_TABLEm_field_set(unit, &data, METER_MODIFIERf, 14693 &mode_modifier); 14694 } 14695 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) { 14696 soc_SVM_METER_TABLEm_field_set(unit, &data, COUPLING_FLAGf, &coupling); 14697 } 14698 /* Read START/END of the chain info and set table accordingly */ 14699 if (mode == GLOBAL_METER_MODE_CASCADE) { 14700 if (pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_START) { 14701 start_of_chain = 1; 14702 } 14703 if (pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) { 14704 end_of_chain = 1; 14705 } 14706 } 14707 soc_SVM_METER_TABLEm_field_set(unit, &data, 14708 START_OF_CHAINf, &start_of_chain); 14709 soc_SVM_METER_TABLEm_field_set(unit, &data, END_OF_CHAINf, &end_of_chain); 14710 14711 /* write to hW */ 14712 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &data); 14713 BCM_IF_ERROR_RETURN(rv); 14714 /* increment action usage reference count */ 14715 if (incr_reqd) { 14716 global_meter_action_bookkeep[unit][policy_index].reference_count++; 14717 } 14718 /* in case of cascade with coupling we need to configure the second set 14719 as well */ 14720 if ((coupling == 1) && (mode == GLOBAL_METER_MODE_CASCADE)) { 14721 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHMAXf, 14722 &c_refreshmax); 14723 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETCOUNTf, 14724 &c_bucketcount); 14725 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_REFRESHCOUNTf, 14726 &c_refresh_rate); 14727 soc_SVM_METER_TABLEm_field_set(unit, &data, COMMITTED_BUCKETSIZEf, 14728 &c_bucketsize); 14729 rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit, 14730 policer_id, policer_control, &index); 14731 /* write to hW */ 14732 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 14733 index, &data); 14734 if (!BCM_SUCCESS(rv)) { 14735 LOG_DEBUG(BSL_LS_BCM_POLICER, 14736 (BSL_META_U(unit, 14737 "Unable to configure the cascaded pair of " 14738 "policers \n"))); 14739 return rv; 14740 } 14741 } 14742 if (pol_cfg->flags & BCM_POLICER_MIXED_MICRO_MACRO) { 14743 rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 14744 index, ¯o_flow_entry); 14745 if (!(BCM_SUCCESS(rv))) { 14746 LOG_DEBUG(BSL_LS_BCM_COMMON, 14747 (BSL_META_U(unit, 14748 "Unable to access macro flow table at the index provided\n"))); 14749 return rv; 14750 } 14751 14752 soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *) ¯o_flow_entry, 14753 MACROFLOW_INDEXf, (uint32 *)¯o_flow_meter_index); 14754 if (macro_flow_meter_index > 0) { 14755 _bcm_esw_get_policer_id_from_index_offset(unit, 14756 macro_flow_meter_index, 0, ¯o_meter_policer); 14757 rv = _bcm_esw_policer_decrement_ref_count(unit, 14758 macro_meter_policer); 14759 if (BCM_FAILURE(rv)) { 14760 LOG_DEBUG(BSL_LS_BCM_COMMON, 14761 (BSL_META_U(unit, 14762 "%u : Unable to decrement ref count"), 14763 macro_flow_meter_index)); 14764 return rv; 14765 } 14766 macro_flow_meter_index = 0; /* clear macro flow index entry */ 14767 soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, ¯o_flow_entry, 14768 MACROFLOW_INDEXf, (uint32 *)¯o_flow_meter_index); 14769 rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 14770 index, ¯o_flow_entry); 14771 if (!(BCM_SUCCESS(rv))) { 14772 LOG_DEBUG(BSL_LS_BCM_COMMON, \ 14773 (BSL_META_U(unit, 14774 "Unable to write to macro flow table at index \ 14775 provided\n"))); 14776 return rv; 14777 } 14778 } 14779 } 14780 14781 return rv; 14782 #else 14783 return BCM_E_UNAVAIL; 14784 #endif 14785 } 14786 14787 /* 14788 * Function: 14789 * _bcm_global_meter_write_config_mef_10dot3_to_hw 14790 * Purpose: 14791 * Write policer configuraton to meter table. 14792 * Parameters: 14793 * unit - (IN) unit number 14794 * pol_cfg - (IN) policer configuration 14795 * policer_id - (IN) policer id 14796 * policer_control - (IN) Policer control info 14797 * Returns: 14798 * BCM_E_XXX 14799 */ 14800 int 14801 _bcm_global_meter_write_config_mef_10dot3_to_hw (int unit, 14802 bcm_policer_config_t *pol_cfg, 14803 bcm_policer_t policer_id, 14804 _global_meter_policer_control_t *policer_control) 14805 { 14806 #if defined(BCM_APACHE_SUPPORT) 14807 int rv = BCM_E_NONE; 14808 uint32 flags=0; 14809 uint32 c_bucketsize = 0, e_bucketsize = 0; /* Bucket size. */ 14810 uint32 c_refresh_rate = 0, e_refresh_rate = 0; /* Policer refresh rate */ 14811 uint32 granularity = 0; /* Policer granularity. */ 14812 uint32 refresh_bitsize; /* Number of bits for the 14813 refresh rate field. */ 14814 uint32 bucket_max_bitsize; /* Number of bits for the 14815 bucket max field. */ 14816 uint32 mode = 0, mode_modifier = 0; 14817 uint32 coupling = 0, policy_index = 0; 14818 uint32 c_refreshmax = 0, e_refreshmax = 0; 14819 int index = 0, pool = 0, pair_index = 0; 14820 uint32 current_action_id = 0; 14821 uint32 pkt_bytes = 0; 14822 uint32 nc_pool_valid = 0, nc_pool = 0, ne_pool_valid = 0, ne_pool = 0; 14823 uint32 c_e = 0, pair_exc = 0, pair_exc_valid = 0; 14824 bcm_policer_t macro_meter_policer = 0; 14825 int macro_flow_meter_index = 0; 14826 svm_macroflow_index_table_entry_t macro_flow_entry; 14827 svm_meter_table_entry_t svm_entry; 14828 int incr_reqd = 0; 14829 14830 pool = _bcm_global_meter_get_pool_from_policerId(unit, policer_id); 14831 /* read HW register */ 14832 _bcm_esw_get_policer_table_index(unit, policer_id, &index); 14833 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &svm_entry); 14834 BCM_IF_ERROR_RETURN(rv); 14835 14836 policy_index = pol_cfg->action_id; 14837 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) { 14838 soc_SVM_METER_TABLEm_field_get(unit, 14839 &svm_entry, POLICY_TABLE_INDEXf, ¤t_action_id); 14840 if( policy_index != current_action_id ) { 14841 if(current_action_id != 0) { 14842 /* detach the existing action and 14843 * decrement reference count 14844 */ 14845 _bcm_esw_policer_action_detach(unit, policer_id, 14846 current_action_id); 14847 } 14848 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 14849 POLICY_TABLE_INDEXf, &policy_index); 14850 if(policy_index != 0) { 14851 incr_reqd = 1; 14852 } 14853 } 14854 } 14855 14856 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 14857 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 14858 14859 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 14860 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 14861 } else { 14862 flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE; 14863 } 14864 14865 refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14866 COMMITTED_REFRESHCOUNTf); 14867 bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14868 COMMITTED_BUCKETSIZEf); 14869 14870 if (pol_cfg->mode == bcmPolicerModeTrTcm) { 14871 /* SW-WAR: In this mode CIR and PIR need swapping */ 14872 uint32 tmp; 14873 tmp = pol_cfg->pkbits_sec; 14874 pol_cfg->pkbits_sec = pol_cfg->ckbits_sec; 14875 pol_cfg->ckbits_sec = tmp; 14876 } 14877 14878 /* Calculate policer bucket size/refresh_rate/granularity. */ 14879 if (pol_cfg->pkbits_sec > pol_cfg->ckbits_sec) { 14880 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec, 14881 pol_cfg->pkbits_burst, 14882 flags, refresh_bitsize, 14883 bucket_max_bitsize, 14884 &c_refresh_rate, &c_bucketsize, 14885 &granularity); 14886 BCM_IF_ERROR_RETURN(rv); 14887 14888 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 14889 pol_cfg->ckbits_sec, 14890 pol_cfg->ckbits_burst, 14891 flags, refresh_bitsize, 14892 bucket_max_bitsize, 14893 &c_refresh_rate, &c_bucketsize, 14894 &granularity); 14895 BCM_IF_ERROR_RETURN(rv); 14896 } else { 14897 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->ckbits_sec, 14898 pol_cfg->ckbits_burst, 14899 flags, refresh_bitsize, 14900 bucket_max_bitsize, 14901 &c_refresh_rate, &c_bucketsize, 14902 &granularity); 14903 BCM_IF_ERROR_RETURN(rv); 14904 } 14905 14906 rv =_bcm_global_meter_refresh_max_get(pol_cfg->ckbits_sec, 14907 pol_cfg->max_ckbits_sec, 14908 &c_refreshmax); 14909 BCM_IF_ERROR_RETURN(rv); 14910 14911 14912 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_REFRESHMAXf, 14913 &c_refreshmax); 14914 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_REFRESHCOUNTf, 14915 &c_refresh_rate); 14916 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COMMITTED_BUCKETSIZEf, 14917 &c_bucketsize); 14918 14919 14920 refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14921 EXCESS_REFRESHCOUNTf); 14922 14923 bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 14924 EXCESS_BUCKETSIZEf); 14925 14926 if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) { 14927 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec, 14928 pol_cfg->pkbits_burst, 14929 flags, refresh_bitsize, 14930 bucket_max_bitsize, 14931 &e_refresh_rate, &e_bucketsize, 14932 &granularity); 14933 14934 } else { 14935 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 14936 pol_cfg->pkbits_sec, 14937 pol_cfg->pkbits_burst, 14938 flags, refresh_bitsize, 14939 bucket_max_bitsize, 14940 &e_refresh_rate, &e_bucketsize, 14941 &granularity); 14942 } 14943 BCM_IF_ERROR_RETURN(rv); 14944 14945 /* Set HW register */ 14946 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) { 14947 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_GRANf, &granularity); 14948 } 14949 14950 rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec, 14951 pol_cfg->max_pkbits_sec, 14952 &e_refreshmax); 14953 BCM_IF_ERROR_RETURN(rv); 14954 14955 if ((policer_control->grp_mode == \ 14956 bcmPolicerGroupModeIntPriCascadeWithCoupling) || 14957 (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) { 14958 14959 } else { /* non-GCF mode */ 14960 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHMAXf, 14961 &e_refreshmax); 14962 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHCOUNTf, 14963 &e_refresh_rate); 14964 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_BUCKETSIZEf, 14965 &e_bucketsize); 14966 } 14967 14968 /* PKT/BYTE - by default BYTE counter */ 14969 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) { 14970 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 14971 pkt_bytes = 1; 14972 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, PKT_BYTESf, &pkt_bytes); 14973 } 14974 } 14975 /* MIN/MAX/MIN_MAX */ 14976 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_SHARING_MODEf)) { 14977 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_SHARING_MODEf, 14978 &pol_cfg->sharing_mode); 14979 } 14980 if (pol_cfg->flags & BCM_POLICER_COLOR_BLIND) { 14981 mode_modifier = 0; /* color blind */ 14982 } else { 14983 mode_modifier = 1; /* color aware */ 14984 } 14985 14986 switch (pol_cfg->mode) { 14987 case bcmPolicerModeGreen: 14988 mode = GLOBAL_METER_MODE_DEFAULT; 14989 mode_modifier = 0; 14990 break; 14991 14992 case bcmPolicerModePassThrough: 14993 mode = GLOBAL_METER_MODE_DEFAULT; 14994 mode_modifier = 1; 14995 break; 14996 14997 case bcmPolicerModeSrTcm: 14998 mode = GLOBAL_METER_MODE_SR_TCM; 14999 break; 15000 15001 case bcmPolicerModeSrTcmModified: 15002 /* This mode is not supported in APACHE */ 15003 return BCM_E_PARAM; 15004 15005 case bcmPolicerModeTrTcm: 15006 mode = GLOBAL_METER_MODE_TR_TCM; 15007 break; 15008 15009 case bcmPolicerModeTrTcmDs: 15010 mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED; 15011 break; 15012 15013 case bcmPolicerModeCoupledTrTcmDs: 15014 mode = GLOBAL_METER_MODE_TR_TCM_MODIFIED; 15015 coupling = 1; 15016 break; 15017 15018 case bcmPolicerModeCascade: 15019 mode = GLOBAL_METER_MODE_CASCADE; 15020 /* If policer is part of non-GCF chain, adjust overflow params */ 15021 if ((policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade) 15022 || (policer_control->grp_mode == bcmPolicerGroupModeCascade) 15023 || (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) { 15024 /* Check if next committed pool is supplied */ 15025 if (pol_cfg->ncoflow_policer_id != 0) { 15026 nc_pool = _bcm_global_meter_get_pool_from_policerId(unit, 15027 pol_cfg->ncoflow_policer_id); 15028 } else { 15029 nc_pool = pool + 1; 15030 } 15031 15032 /* Check if next excess pool is supplied */ 15033 if (pol_cfg->npoflow_policer_id != 0) { 15034 ne_pool = _bcm_global_meter_get_pool_from_policerId(unit, 15035 pol_cfg->npoflow_policer_id); 15036 } else { 15037 ne_pool = pool + 1; 15038 } 15039 15040 if (ne_pool < nc_pool) { 15041 /* Excess pool is high priority than commit pool 15042 Shouldn't happen */ 15043 return BCM_E_PARAM; 15044 } 15045 15046 if ((pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) || 15047 ((SOC_INFO(unit).global_meter_pools -1 ) == pool)) { 15048 /* Last policer in chain, make next committed and 15049 excess pools invalid */ 15050 nc_pool_valid = nc_pool = 0; 15051 ne_pool_valid = ne_pool = 0; 15052 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15053 NXT_COMMITTED_BUCKET_VALIDf, 15054 &nc_pool_valid); 15055 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15056 NXT_EXCESS_BUCKET_VALIDf, 15057 &ne_pool_valid); 15058 } 15059 15060 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15061 NXT_COMMITTED_BUCKETf, 15062 &nc_pool); 15063 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15064 NXT_EXCESS_BUCKETf, 15065 &ne_pool); 15066 } /* group mode check */ 15067 break; 15068 15069 case bcmPolicerModeCoupledCascade: 15070 mode = GLOBAL_METER_MODE_CASCADE; 15071 /* If policer is part of non-GCF chain, adjust overflow params */ 15072 if ((policer_control->grp_mode == bcmPolicerGroupModeIntPriCascade) 15073 || (policer_control->grp_mode == bcmPolicerGroupModeCascade) 15074 || (policer_control->grp_mode == bcmPolicerGroupModeCascadeDroppedPktExclude)) { 15075 /* Enable COMMITEED_EXCESS in HW */ 15076 c_e = 1; 15077 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15078 COMMITTED_EXCESSf, &c_e); 15079 nc_pool_valid = 1; /* Already in HW during group config */ 15080 nc_pool = pool; /* Implicit requirement */ 15081 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15082 NXT_COMMITTED_BUCKETf, 15083 &nc_pool); 15084 15085 /* Check if next excess pool is supplied */ 15086 if (pol_cfg->npoflow_policer_id != 0) { 15087 ne_pool = _bcm_global_meter_get_pool_from_policerId(unit, 15088 pol_cfg->npoflow_policer_id); 15089 } else { 15090 ne_pool = pool + 1; 15091 } 15092 15093 if ((pol_cfg->flags & BCM_POLICER_BW_SHARING_GROUP_END) || 15094 ((SOC_INFO(unit).global_meter_pools -1 ) == pool)) { 15095 /* Last policer is chain, disable excess pool validity */ 15096 ne_pool = 0; 15097 ne_pool_valid = 0; 15098 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15099 NXT_EXCESS_BUCKET_VALIDf, 15100 &ne_pool_valid); 15101 } 15102 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15103 NXT_EXCESS_BUCKETf, 15104 &ne_pool); 15105 } /* End - "if" group mode check */ 15106 break; 15107 15108 default: 15109 LOG_DEBUG(BSL_LS_BCM_POLICER, 15110 (BSL_META_U(unit, 15111 "Invalid policer mode \n"))); 15112 return BCM_E_PARAM; 15113 break; 15114 } 15115 /* SRTCM TrTcm Modified SrTcm, Modified TrTcm, cascade, default */ 15116 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 15117 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODEf, &mode); 15118 } 15119 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) { 15120 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODIFIERf, 15121 &mode_modifier); 15122 } 15123 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) { 15124 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, COUPLING_FLAGf, &coupling); 15125 } 15126 15127 if ((policer_control->grp_mode != \ 15128 bcmPolicerGroupModeIntPriCascadeWithCoupling) && 15129 (policer_control->grp_mode != bcmPolicerGroupModeCascadeWithCoupling)) { 15130 /* Set METER_PAIR_EXCESS for all other modes here */ 15131 pair_exc_valid = 1; 15132 pair_exc = pool; 15133 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15134 METER_PAIR_EXCESS_BUCKETf, 15135 &pair_exc); 15136 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 15137 METER_PAIR_EXCESS_BUCKET_VALIDf, 15138 &pair_exc_valid); 15139 } 15140 15141 /* write to hW */ 15142 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, &svm_entry); 15143 BCM_IF_ERROR_RETURN(rv); 15144 /* increment action usage reference count */ 15145 if (incr_reqd) { 15146 global_meter_action_bookkeep[unit][policy_index].reference_count++; 15147 } 15148 /* in case of cascade with coupling we need to configure the second set 15149 as well - GCF Mode */ 15150 if ((policer_control->grp_mode == \ 15151 bcmPolicerGroupModeIntPriCascadeWithCoupling) || 15152 (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) { 15153 rv = _bcm_global_meter_get_coupled_cascade_policer_index(unit, 15154 policer_id, policer_control, &pair_index); 15155 BCM_IF_ERROR_RETURN(rv); 15156 15157 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 15158 pair_index, &svm_entry); 15159 BCM_IF_ERROR_RETURN(rv); 15160 15161 policy_index = pol_cfg->action_id; 15162 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) { 15163 soc_SVM_METER_TABLEm_field_get(unit, 15164 &svm_entry, POLICY_TABLE_INDEXf, ¤t_action_id); 15165 /* detach the existing action and decrement reference count */ 15166 if (current_action_id) { 15167 _bcm_esw_policer_action_detach(unit, policer_id, 15168 current_action_id); 15169 } 15170 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, POLICY_TABLE_INDEXf, 15171 &policy_index); 15172 } 15173 15174 flags = _BCM_XGS_METER_FLAG_GRANULARITY | 15175 _BCM_XGS_METER_FLAG_GLOBAL_METER_POLICER; 15176 15177 refresh_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 15178 EXCESS_REFRESHCOUNTf); 15179 15180 bucket_max_bitsize = soc_mem_field_length(unit, SVM_METER_TABLEm, 15181 EXCESS_BUCKETSIZEf); 15182 15183 if ((pol_cfg->ckbits_sec == 0) && (pol_cfg->ckbits_burst == 0)) { 15184 rv = _bcm_xgs_kbits_to_bucket_encoding(pol_cfg->pkbits_sec, 15185 pol_cfg->pkbits_burst, 15186 flags, refresh_bitsize, 15187 bucket_max_bitsize, 15188 &e_refresh_rate, 15189 &e_bucketsize, 15190 &granularity); 15191 15192 } else { 15193 rv = _bcm_xgs_kbits_to_bucket_encoding_with_granularity( 15194 pol_cfg->pkbits_sec, 15195 pol_cfg->pkbits_burst, 15196 flags, refresh_bitsize, 15197 bucket_max_bitsize, 15198 &e_refresh_rate, &e_bucketsize, 15199 &granularity); 15200 } 15201 BCM_IF_ERROR_RETURN(rv); 15202 15203 /* Set HW register */ 15204 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_GRANf)) { 15205 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_GRANf, &granularity); 15206 } 15207 15208 rv = _bcm_global_meter_refresh_max_get(pol_cfg->pkbits_sec, 15209 pol_cfg->max_pkbits_sec, 15210 &e_refreshmax); 15211 BCM_IF_ERROR_RETURN(rv); 15212 15213 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHMAXf, 15214 &e_refreshmax); 15215 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_REFRESHCOUNTf, 15216 &e_refresh_rate); 15217 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, EXCESS_BUCKETSIZEf, 15218 &e_bucketsize); 15219 /* PKT/BYTE - by default BYTE counter */ 15220 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, PKT_BYTESf)) { 15221 if (pol_cfg->flags & BCM_POLICER_MODE_PACKETS) { 15222 pkt_bytes = 1; 15223 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, PKT_BYTESf, &pkt_bytes); 15224 } 15225 } 15226 15227 mode = GLOBAL_METER_MODE_CASCADE; 15228 15229 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 15230 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODEf, &mode); 15231 } 15232 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODIFIERf)) { 15233 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, METER_MODIFIERf, 15234 &mode_modifier); 15235 } 15236 15237 /* write to hW */ 15238 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 15239 pair_index, &svm_entry); 15240 if (!BCM_SUCCESS(rv)) { 15241 LOG_DEBUG(BSL_LS_BCM_POLICER, 15242 (BSL_META_U(unit, 15243 "Unable to configure the cascaded pair of " 15244 "policers \n"))); 15245 return rv; 15246 } 15247 } /* end if for GCF mode check */ 15248 15249 if (pol_cfg->flags & BCM_POLICER_MIXED_MICRO_MACRO) { 15250 rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 15251 index, ¯o_flow_entry); 15252 if (!(BCM_SUCCESS(rv))) { 15253 LOG_DEBUG(BSL_LS_BCM_COMMON, 15254 (BSL_META_U(unit, 15255 "Unable to access macro flow table at the index provided\n"))); 15256 return rv; 15257 } 15258 15259 soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *) ¯o_flow_entry, 15260 MACROFLOW_INDEXf, (uint32 *)¯o_flow_meter_index); 15261 if (macro_flow_meter_index > 0) { 15262 _bcm_esw_get_policer_id_from_index_offset(unit, 15263 macro_flow_meter_index, 0, ¯o_meter_policer); 15264 rv = _bcm_esw_policer_decrement_ref_count(unit, 15265 macro_meter_policer); 15266 if (BCM_FAILURE(rv)) { 15267 LOG_DEBUG(BSL_LS_BCM_COMMON, 15268 (BSL_META_U(unit, 15269 "%u : Unable to decrement ref count"), 15270 macro_flow_meter_index)); 15271 return rv; 15272 } 15273 macro_flow_meter_index = 0; /* clear macro flow index entry */ 15274 soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, ¯o_flow_entry, 15275 MACROFLOW_INDEXf, (uint32 *)¯o_flow_meter_index); 15276 rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 15277 index, ¯o_flow_entry); 15278 if (!(BCM_SUCCESS(rv))) { 15279 LOG_DEBUG(BSL_LS_BCM_COMMON, \ 15280 (BSL_META_U(unit, 15281 "Unable to write to macro flow table at index \ 15282 provided\n"))); 15283 return rv; 15284 } 15285 } 15286 } 15287 15288 return rv; 15289 #else 15290 return BCM_E_UNAVAIL; 15291 #endif 15292 } 15293 /* 15294 * Function: 15295 * _bcm_global_meter_get_coupled_cascade_policer_index 15296 * Purpose: 15297 * In case of cascade with coupling get the index of the coupled 15298 * pair 15299 * Parameters: 15300 * unit - (IN) unit number 15301 * policer_id - (IN) policer id 15302 * policer_control - (IN) Policer control info 15303 * new_index - (OUT) Policer index 15304 * Returns: 15305 * BCM_E_XXX 15306 */ 15307 int _bcm_global_meter_get_coupled_cascade_policer_index(int unit, 15308 bcm_policer_t policer_id, 15309 _global_meter_policer_control_t *policer_control, 15310 int *new_index) 15311 { 15312 15313 int rv = BCM_E_NONE; 15314 int offset1 = 0, pool1 = 0, pool2 = 0; 15315 int new_offset = 0; 15316 int size_pool = 0, num_pools = 0; 15317 int index = 0, index_max = 0; 15318 int offset_mask = 0; 15319 int pool_mask = 0, pool_offset = 0; 15320 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 15321 num_pools = SOC_INFO(unit).global_meter_pools; 15322 offset_mask = size_pool - 1; 15323 pool_offset = _shr_popcount(offset_mask); 15324 pool_mask = (num_pools - 1) << pool_offset; 15325 15326 offset1 = policer_control->pid & offset_mask; 15327 15328 pool1 = (policer_control->pid & pool_mask) >> pool_offset; 15329 pool2 = (policer_id & pool_mask) >> pool_offset; 15330 15331 if (!soc_feature(unit ,soc_feature_global_meter_mef_10dot3)) { 15332 index_max = policer_control->no_of_policers/2; 15333 if (pool1 == pool2) { 15334 new_offset = policer_control->offset[index_max]; 15335 *new_index = offset1 + (new_offset * size_pool); 15336 return rv; 15337 } 15338 for (index = 1; index < index_max; index++) { 15339 if ((pool1 + policer_control->offset[index]) == pool2) { 15340 if ((index_max + index) < MAX_POLICER_OFFSETS) { 15341 new_offset = policer_control->offset[index_max + index]; 15342 *new_index = offset1 + (new_offset * size_pool); 15343 } else { 15344 return BCM_E_RESOURCE; 15345 } 15346 } 15347 } 15348 } else { /* MEF 10.3 onward device */ 15349 new_offset = pool2 + 4; 15350 /* In GCF mode, SDK assumes its always chain of 4 policers. 15351 * Not much choice left but to carry on this legacy assumption 15352 * as no GCF mode functionality change is expected in MEF10.3 15353 */ 15354 *new_index = offset1 + (new_offset * size_pool); 15355 } 15356 15357 return rv; 15358 } 15359 15360 /* 15361 * Function: 15362 * _bcm_global_meter_base_policer_get 15363 * Purpose: 15364 * Get the internal data structure for a given polier id if 15365 * it is base policer. 15366 * Parameters: 15367 * unit - (IN) unit number 15368 * pid - (IN) policer id 15369 * policer_p - (OUT) Policer control info 15370 * Returns: 15371 * BCM_E_XXX 15372 */ 15373 int _bcm_global_meter_base_policer_get(int unit, bcm_policer_t pid, 15374 _global_meter_policer_control_t **policer_p) 15375 { 15376 _global_meter_policer_control_t *global_meter_pl = NULL; 15377 uint32 hash_index; /* Entry hash. */ 15378 /* Input parameters check. */ 15379 if (NULL == policer_p) { 15380 LOG_DEBUG(BSL_LS_BCM_POLICER, 15381 (BSL_META_U(unit, 15382 "Policer control is null \n"))); 15383 return (BCM_E_PARAM); 15384 } 15385 hash_index = pid & _GLOBAL_METER_HASH_MASK; 15386 global_meter_pl = global_meter_policer_bookkeep[unit][hash_index]; 15387 while (NULL != global_meter_pl) { 15388 /* Match entry id. */ 15389 if (global_meter_pl->pid == pid) { 15390 *policer_p = global_meter_pl; 15391 return (BCM_E_NONE); 15392 } 15393 global_meter_pl = global_meter_pl->next; 15394 } 15395 /* Policer with pid == pid was not found. */ 15396 return (BCM_E_NOT_FOUND); 15397 } 15398 15399 /* 15400 * Function: 15401 * _bcm_global_meter_policer_get 15402 * Purpose: 15403 * Get the internal control data structure for a given policer id. 15404 * Parameters: 15405 * unit - (IN) unit number 15406 * pid - (IN) policer id 15407 * policer_p - (OUT) Policer control info 15408 * Returns: 15409 * BCM_E_XXX 15410 */ 15411 15412 int _bcm_global_meter_policer_get(int unit, bcm_policer_t pid, 15413 _global_meter_policer_control_t **policer_p) 15414 { 15415 _global_meter_policer_control_t *global_meter_pl = NULL; 15416 uint32 hash_index; /* Entry hash */ 15417 int offset1 = 0, offset2 = 0; 15418 int pool1 = 0, pool2 = 0; 15419 uint32 index = 0, index_max = 0; 15420 int rv = BCM_E_NONE; 15421 int hash_max = 0; 15422 int offset_mask = 0; 15423 int size_pool = 0, num_pools = 0; 15424 int pool_mask = 0, pool_offset = 0; 15425 /* Input parameters check. */ 15426 if (NULL == policer_p) { 15427 LOG_DEBUG(BSL_LS_BCM_POLICER, 15428 (BSL_META_U(unit, 15429 "Policer control is null \n"))); 15430 return (BCM_E_PARAM); 15431 } 15432 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 15433 num_pools = SOC_INFO(unit).global_meter_pools; 15434 offset_mask = size_pool - 1; 15435 pool_offset = _shr_popcount(offset_mask); 15436 pool_mask = (num_pools - 1) << pool_offset; 15437 15438 rv = _bcm_global_meter_base_policer_get(unit, pid, policer_p); 15439 if (BCM_E_NOT_FOUND == rv) { 15440 hash_max = pid & _GLOBAL_METER_HASH_MASK; 15441 for (hash_index=0; hash_index <= hash_max; hash_index++) { 15442 global_meter_pl = 15443 global_meter_policer_bookkeep[unit][hash_index]; 15444 while (NULL != global_meter_pl) { 15445 offset1 = global_meter_pl->pid & offset_mask; 15446 offset2 = pid & offset_mask; 15447 15448 pool1 = (global_meter_pl->pid & pool_mask) >> pool_offset; 15449 pool2 = (pid & pool_mask) >> pool_offset; 15450 15451 /* in case of cascade policers, only pool number is diferent */ 15452 if (global_meter_pl->direction == 15453 GLOBAL_METER_ALLOC_HORIZONTAL) { 15454 if (offset1 == offset2) { 15455 index_max = global_meter_pl->no_of_policers; 15456 for (index = 1; index < index_max; index++) { 15457 if ((pool1 + global_meter_pl->offset[index]) == 15458 pool2) { 15459 *policer_p = global_meter_pl; 15460 return (BCM_E_NONE); 15461 } 15462 } 15463 } 15464 } else { 15465 if (pool1 == pool2) { 15466 if (offset2 > offset1 && offset2 < 15467 (offset1 + global_meter_pl->no_of_policers)) { 15468 *policer_p = global_meter_pl; 15469 return (BCM_E_NONE); 15470 } 15471 } 15472 15473 } 15474 global_meter_pl = global_meter_pl->next; 15475 } 15476 } 15477 /* Policer with pid == pid was not found. */ 15478 return (BCM_E_NOT_FOUND); 15479 } else { 15480 return rv; 15481 } 15482 return BCM_E_NONE; 15483 } 15484 15485 /* 15486 * Function: 15487 * _bcm_esw_global_meter_policer_get 15488 * Purpose: 15489 * Get the configuration info for a given policer id 15490 * Parameters: 15491 * unit - (IN) unit number 15492 * pid - (IN) policer id 15493 * policer_p - (OUT) Policer control info 15494 * Returns: 15495 * BCM_E_XXX 15496 */ 15497 int _bcm_esw_global_meter_policer_get(int unit, bcm_policer_t policer_id, 15498 bcm_policer_config_t *pol_cfg) 15499 { 15500 int rv = BCM_E_NONE; 15501 _global_meter_policer_control_t *policer_control = NULL; 15502 15503 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 15504 if (soc_feature(unit, soc_feature_global_meter_v2)) { 15505 return bcmi_esw_global_meter_policer_get(unit, 15506 policer_id, pol_cfg); 15507 } 15508 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 15509 15510 /* validate policer id */ 15511 rv = _bcm_esw_policer_validate(unit, &policer_id); 15512 if (BCM_FAILURE(rv)) { 15513 LOG_DEBUG(BSL_LS_BCM_POLICER, 15514 (BSL_META_U(unit, 15515 "Invalid policer id %x \n"), 15516 policer_id)); 15517 return (rv); 15518 } 15519 GLOBAL_METER_LOCK(unit); 15520 /* we come here from bcm_esw_policer_get, 15521 only when policer id indicates : global meter */ 15522 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 15523 if (BCM_SUCCESS(rv)) { 15524 rv = (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) ? 15525 _bcm_global_meter_read_config_from_hw_mef_10dot3(unit, policer_id, 15526 pol_cfg) : 15527 _bcm_global_meter_read_config_from_hw(unit, policer_id, pol_cfg); 15528 15529 if (BCM_FAILURE(rv)) { 15530 LOG_DEBUG(BSL_LS_BCM_POLICER, 15531 (BSL_META_U(unit, 15532 "Unable to read policer config from hw %x\n"), 15533 policer_id)); 15534 GLOBAL_METER_UNLOCK(unit); 15535 return (rv); 15536 } 15537 } 15538 GLOBAL_METER_UNLOCK(unit); 15539 return rv; 15540 } 15541 15542 /* 15543 * Function: 15544 * _bcm_global_meter_min_burst_size_set 15545 * Purpose: 15546 * If the passed burst size is less than the minimum required, set it to 15547 * minimum required value. 15548 * Parameters: 15549 * unit - (IN) unit number 15550 * policer_id - (IN) policer id 15551 * pol_cfg - (IN) Policer control info 15552 * Returns: 15553 * BCM_E_XXX 15554 */ 15555 15556 int _bcm_global_meter_min_burst_size_set(bcm_policer_config_t *pol_cfg) 15557 { 15558 uint32 min_burst = 0; 15559 /* min burst should be 15560 max (MTU size + metering rate * refresh interval, 15561 2 * metering rate * refresh interval) */ 15562 15563 min_burst = (MIN_BURST_MULTIPLE * 15564 ((pol_cfg->ckbits_sec * METER_REFRESH_INTERVAL) / 15565 CONVERT_SECOND_TO_MICROSECOND)); 15566 if (min_burst > pol_cfg->ckbits_burst) { 15567 LOG_ERROR(BSL_LS_BCM_POLICER, 15568 (BSL_META("Commited burst is less than the minimum required " 15569 "value. \n"))); 15570 return (BCM_E_PARAM); 15571 } 15572 min_burst = (MIN_BURST_MULTIPLE * 15573 ((pol_cfg->pkbits_sec * METER_REFRESH_INTERVAL) / 15574 CONVERT_SECOND_TO_MICROSECOND)); 15575 if (min_burst > pol_cfg->pkbits_burst) { 15576 LOG_ERROR(BSL_LS_BCM_POLICER, 15577 (BSL_META("Peak burst is less than the minimum required " 15578 "value. \n"))); 15579 return (BCM_E_PARAM); 15580 } 15581 return (BCM_E_NONE); 15582 } 15583 15584 /* 15585 * Function: 15586 * _bcm_esw_global_meter_policer_set 15587 * Purpose: 15588 * Configure the parmeters for a policer already created. 15589 * Parameters: 15590 * unit - (IN) unit number 15591 * policer_id - (IN) policer id 15592 * pol_cfg - (IN) Policer control info 15593 * Returns: 15594 * BCM_E_XXX 15595 */ 15596 15597 int _bcm_esw_global_meter_policer_set(int unit, bcm_policer_t policer_id, 15598 bcm_policer_config_t *pol_cfg) 15599 { 15600 int rv = BCM_E_NONE; 15601 _global_meter_policer_control_t *policer_control = NULL; 15602 15603 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 15604 if (soc_feature(unit, soc_feature_global_meter_v2)) { 15605 return bcmi_esw_global_meter_policer_set(unit, 15606 policer_id, pol_cfg); 15607 } 15608 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 15609 15610 /* validate policer id */ 15611 rv = _bcm_esw_policer_validate(unit, &policer_id); 15612 if (BCM_FAILURE(rv)) { 15613 LOG_DEBUG(BSL_LS_BCM_POLICER, 15614 (BSL_META_U(unit, 15615 "Invalid policer id %x \n"), 15616 policer_id)); 15617 return (rv); 15618 } 15619 GLOBAL_METER_LOCK(unit); 15620 15621 /* we come here from bcm_esw_policer_get, 15622 only when policer id indicates : global meter */ 15623 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 15624 if (BCM_SUCCESS(rv)) { 15625 /* Check whether the burst size is >= min required. If not, set it 15626 to minimum required value */ 15627 rv = _bcm_global_meter_min_burst_size_set(pol_cfg); 15628 15629 /* Add code to write this to HW */ 15630 if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 15631 rv = _bcm_global_meter_write_config_mef_10dot3_to_hw(unit, pol_cfg, 15632 policer_id, policer_control); 15633 } else { 15634 rv = _bcm_global_meter_write_config_to_hw(unit, pol_cfg, 15635 policer_id, policer_control); 15636 } 15637 if (BCM_FAILURE(rv)) { 15638 LOG_DEBUG(BSL_LS_BCM_POLICER, 15639 (BSL_META_U(unit, 15640 "Unable to write policer config to hw %x\n"), 15641 policer_id)); 15642 GLOBAL_METER_UNLOCK(unit); 15643 return (rv); 15644 } 15645 } 15646 GLOBAL_METER_UNLOCK(unit); 15647 return rv; 15648 } 15649 15650 /* 15651 * Function: 15652 * _bcm_esw_global_meter_policer_destroy_all 15653 * Purpose: 15654 * Destroy all the policers. 15655 * Parameters: 15656 * unit - (IN) unit number 15657 * Returns: 15658 * BCM_E_XXX 15659 */ 15660 int _bcm_esw_global_meter_policer_destroy_all(int unit) 15661 { 15662 15663 int rv = BCM_E_NONE; 15664 int idx = 0; 15665 _global_meter_policer_control_t *policer_control = NULL; 15666 15667 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 15668 if (soc_feature(unit, soc_feature_global_meter_v2)) { 15669 return bcmi_esw_global_meter_policer_destroy_all(unit); 15670 } 15671 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 15672 15673 if (global_meter_status[unit].initialised == 0) { 15674 return rv; 15675 } 15676 if (global_meter_mutex[unit] != NULL) { 15677 GLOBAL_METER_LOCK(unit); 15678 } 15679 /* Iterate over all hash buckets. */ 15680 for (idx = 0; idx < _GLOBAL_METER_HASH_SIZE; idx++) { 15681 policer_control = global_meter_policer_bookkeep[unit][idx]; 15682 /* Destroy entries in each bucket. */ 15683 while (NULL != policer_control) { 15684 rv = _bcm_esw_global_meter_policer_destroy2(unit, policer_control); 15685 if (BCM_FAILURE(rv)) { 15686 break; 15687 } 15688 policer_control = global_meter_policer_bookkeep[unit][idx]; 15689 } 15690 if (BCM_FAILURE(rv)) { 15691 break; 15692 } 15693 } 15694 if (global_meter_mutex[unit] != NULL) { 15695 GLOBAL_METER_UNLOCK(unit); 15696 } 15697 return rv; 15698 } 15699 15700 /* 15701 * Function: 15702 * _bcm_esw_global_meter_policer_traverse 15703 * Purpose: 15704 * Traverse through all the policers that are configured and 15705 * call the given call back function with policer configuration. 15706 * Parameters: 15707 * unit - (IN) unit number 15708 * cb - (IN) Call back function 15709 * user_data - (OUT) Data for callback function 15710 * Returns: 15711 * BCM_E_XXX 15712 */ 15713 int _bcm_esw_global_meter_policer_traverse(int unit, 15714 bcm_policer_traverse_cb cb, void *user_data) 15715 { 15716 int rv = BCM_E_NONE; 15717 int idx = 0; 15718 bcm_policer_config_t cfg; /* Policer configuration. */ 15719 _global_meter_policer_control_t *policer_control = NULL; 15720 15721 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 15722 if (soc_feature(unit, soc_feature_global_meter_v2)) { 15723 return bcmi_esw_global_meter_policer_traverse(unit, cb, user_data); 15724 } 15725 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 15726 15727 /* Iterate over all hash buckets. */ 15728 for (idx = 0; idx < _GLOBAL_METER_HASH_SIZE; idx++) { 15729 policer_control = global_meter_policer_bookkeep[unit][idx]; 15730 /* Destroy entries in each bucket. */ 15731 while (NULL != policer_control) { 15732 rv = _bcm_esw_global_meter_policer_get(unit, policer_control->pid, 15733 &cfg); 15734 if (BCM_FAILURE(rv)) { 15735 break; 15736 } 15737 rv = (*cb)(unit, policer_control->pid, &cfg, user_data); 15738 if (BCM_FAILURE(rv)) { 15739 break; 15740 } 15741 policer_control = policer_control->next; 15742 } 15743 if (BCM_FAILURE(rv)) { 15744 break; 15745 } 15746 } 15747 return rv; 15748 } 15749 15750 /* 15751 * Function: 15752 * _bcm_esw_global_meter_policer_destroy 15753 * Purpose: 15754 * Destroys a policer and readjusts action 15755 * usage reference count and policer allocation management data struture. 15756 * Parameters: 15757 * unit - (IN) unit number 15758 * policer_id - (IN) policer id 15759 * Returns: 15760 * BCM_E_XXX 15761 */ 15762 int _bcm_esw_global_meter_policer_destroy(int unit, bcm_policer_t policer_id) 15763 { 15764 int rv = BCM_E_NONE; 15765 _global_meter_policer_control_t *policer_control = NULL; 15766 15767 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 15768 if (soc_feature(unit, soc_feature_global_meter_v2)) { 15769 return bcmi_esw_global_meter_policer_destroy(unit, policer_id); 15770 } 15771 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 15772 15773 if (!soc_feature(unit, soc_feature_global_meter)) { 15774 return BCM_E_UNAVAIL; 15775 } 15776 /* validate policer id */ 15777 rv = _bcm_esw_policer_validate(unit, &policer_id); 15778 if (BCM_FAILURE(rv)) { 15779 LOG_VERBOSE(BSL_LS_BCM_POLICER, 15780 (BSL_META_U(unit, 15781 "Invalid policer id %x \n"), 15782 policer_id)); 15783 return (rv); 15784 } 15785 GLOBAL_METER_LOCK(unit); 15786 rv = _bcm_global_meter_base_policer_get(unit, 15787 policer_id, &policer_control); 15788 if (BCM_FAILURE(rv)) { 15789 GLOBAL_METER_UNLOCK(unit); 15790 LOG_VERBOSE(BSL_LS_BCM_POLICER, 15791 (BSL_META_U(unit, 15792 "Unable to get policer control for policer id %x\n"), 15793 policer_id)); 15794 return (rv); 15795 } 15796 rv = _bcm_esw_global_meter_policer_destroy2(unit, policer_control); 15797 GLOBAL_METER_UNLOCK(unit); 15798 return rv; 15799 } 15800 15801 /* 15802 * Function: 15803 * _bcm_esw_global_meter_policer_destroy2 15804 * Purpose: 15805 * Internal function that destroys a policer and readjusts action 15806 * usage reference count and policer allocation management data struture. 15807 * Parameters: 15808 * unit - (IN) unit number 15809 * policer_id - (IN) policer id 15810 * policer_control - (IN) policer control info 15811 * Returns: 15812 * BCM_E_XXX 15813 */ 15814 int _bcm_esw_global_meter_policer_destroy2(int unit, 15815 _global_meter_policer_control_t *policer_control) 15816 { 15817 int index = 0; 15818 uint32 pool = 0, pid = 0, numbers = 0; 15819 int rv=BCM_E_NONE; 15820 int offset_mode = 0; 15821 int pool_id = 0; 15822 int offset_mask = 0; 15823 int size_pool = 0, num_pools = 0; 15824 int pool_mask = 0, pool_offset = 0; 15825 int bank_size = 0, num_banks_per_pool = 1, bank_index = 0; 15826 int handle_id = 0; 15827 bcm_policer_t macro_meter_policer = 0; 15828 int macro_flow_meter_index = 0; 15829 svm_macroflow_index_table_entry_t *buf; 15830 svm_macroflow_index_table_entry_t *entry; 15831 int entry_mem_size; /* Size of table entry. */ 15832 int entry_index = 0; 15833 int entry_index_max = 0; 15834 int entry_modified = 0; 15835 svm_meter_table_entry_t svm_meter_entry; 15836 svm_meter_table_entry_t *svm_meter_buf; 15837 int base_index = 0; 15838 int offset = 0; 15839 15840 /* Make sure policer is not attached to any entry. */ 15841 if (0 != policer_control->ref_count) { 15842 LOG_DEBUG(BSL_LS_BCM_POLICER, 15843 (BSL_META_U(unit, 15844 "Policer is still in use \n"))); 15845 return (BCM_E_BUSY); 15846 } 15847 if (global_meter_action_bookkeep[unit]\ 15848 [policer_control->action_id].reference_count > 0) 15849 { 15850 global_meter_action_bookkeep[unit]\ 15851 [policer_control->action_id].reference_count--; 15852 } 15853 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 15854 num_pools = SOC_INFO(unit).global_meter_pools; 15855 num_banks_per_pool = get_max_banks_in_a_pool(unit); 15856 offset_mask = size_pool - 1; 15857 pool_offset = _shr_popcount(offset_mask); 15858 pool_mask = (num_pools - 1) << pool_offset; 15859 15860 pid = policer_control->pid & offset_mask; 15861 pool = (policer_control->pid & pool_mask) >> pool_offset; 15862 numbers = policer_control->no_of_policers; 15863 bank_size = size_pool / num_banks_per_pool; 15864 15865 offset_mode = 15866 ((policer_control->pid & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 15867 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 15868 if (offset_mode >= 1) { 15869 offset_mode = offset_mode - 1; 15870 } 15871 15872 /* get the HW index for the policer to be deleted */ 15873 rv = _bcm_esw_get_policer_table_index(unit, policer_control->pid, 15874 &base_index); 15875 if (BCM_FAILURE(rv)) { 15876 LOG_DEBUG(BSL_LS_BCM_POLICER, 15877 (BSL_META_U(unit, 15878 "Unable to Get policer index for " 15879 "policer \n"))); 15880 return rv; 15881 } 15882 15883 /* check horizontal or vertical allocation and then free the policer */ 15884 if (policer_control->direction == GLOBAL_METER_ALLOC_VERTICAL) { 15885 15886 handle_id = (pool * num_banks_per_pool) + (pid / bank_size); 15887 bank_index = pid % bank_size; 15888 15889 if (soc_feature(unit, soc_feature_global_meter_compaction_support)) { 15890 for (offset = 0; offset < numbers; offset++) { 15891 rv = shr_aidxres_list_free( 15892 meter_alloc_list_handle[unit][handle_id], 15893 bank_index + offset); 15894 if (BCM_FAILURE(rv)) { 15895 LOG_DEBUG(BSL_LS_BCM_POLICER, 15896 (BSL_META_U(unit, "Unable to free policer" 15897 " shared index handle\n"))); 15898 return rv; 15899 } 15900 } 15901 } else { 15902 rv = shr_aidxres_list_free( 15903 meter_alloc_list_handle[unit][handle_id], bank_index); 15904 } 15905 if (BCM_FAILURE(rv)) { 15906 LOG_DEBUG(BSL_LS_BCM_POLICER, 15907 (BSL_META_U(unit, 15908 "Unable to free policer handle\n"))); 15909 return (rv); 15910 } 15911 for (index = 0; index < numbers; index++) { 15912 rv = _bcm_gloabl_meter_unreserve_bloc_horizontally(unit, 15913 pool, pid+index); 15914 if (!BCM_SUCCESS(rv)) { 15915 LOG_DEBUG(BSL_LS_BCM_POLICER, 15916 (BSL_META_U(unit, 15917 "Unable to free policer handle in hz " 15918 "index management\n"))); 15919 return BCM_E_INTERNAL; 15920 } 15921 } 15922 15923 entry_mem_size = sizeof(svm_meter_table_entry_t); 15924 entry_index_max = base_index + numbers - 1; 15925 svm_meter_buf = soc_cm_salloc(unit, entry_mem_size * numbers, 15926 "svm meter table entry"); 15927 if (svm_meter_buf == NULL) { 15928 return BCM_E_MEMORY; 15929 } 15930 sal_memset(svm_meter_buf, 0, entry_mem_size * numbers); 15931 15932 rv = soc_mem_write_range(unit, SVM_METER_TABLEm, 15933 MEM_BLOCK_ALL, base_index, 15934 entry_index_max, svm_meter_buf); 15935 if (svm_meter_buf != NULL) { 15936 soc_cm_sfree(unit, svm_meter_buf); 15937 } 15938 if (BCM_FAILURE(rv)) { 15939 return rv; 15940 } 15941 } else if (policer_control->direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 15942 pool_id = pool; 15943 sal_memset(&svm_meter_entry, 0, sizeof(svm_meter_entry)); 15944 for (index = 0;index < numbers; index++) { 15945 if (index > 0) { 15946 pool_id = pool + policer_control->offset[index]; 15947 } 15948 handle_id = (pool_id * num_banks_per_pool) + (pid / bank_size); 15949 bank_index = pid % bank_size; 15950 rv = shr_aidxres_list_free( 15951 meter_alloc_list_handle[unit][handle_id], bank_index); 15952 if (BCM_FAILURE(rv)) { 15953 LOG_DEBUG(BSL_LS_BCM_POLICER, 15954 (BSL_META_U(unit, 15955 "Unable to free policer handle\n"))); 15956 return (rv); 15957 } 15958 rv = WRITE_SVM_METER_TABLEm (unit, MEM_BLOCK_ALL, 15959 base_index + (pool_id * size_pool), 15960 &svm_meter_entry); 15961 if (BCM_FAILURE(rv)) { 15962 LOG_DEBUG(BSL_LS_BCM_POLICER, 15963 (BSL_META_U(unit, 15964 "Unable to write to memory\n"))); 15965 return (rv); 15966 } 15967 15968 } 15969 rv = _bcm_gloabl_meter_free_horizontally(unit, pool, pid, numbers, 15970 policer_control->offset); 15971 if (BCM_FAILURE(rv)) { 15972 LOG_DEBUG(BSL_LS_BCM_POLICER, 15973 (BSL_META_U(unit, 15974 "Unable to free policer handle in hz " 15975 "index management\n"))); 15976 return (rv); 15977 } 15978 } 15979 15980 /* Delete policer from policers hash. */ 15981 _GLOBAL_METER_HASH_REMOVE(global_meter_policer_bookkeep[unit], 15982 _global_meter_policer_control_t, 15983 policer_control, (pid & _GLOBAL_METER_HASH_MASK)); 15984 /* decrement mode reference count */ 15985 if (offset_mode) { 15986 bcm_policer_svc_meter_dec_mode_reference_count(unit, offset_mode); 15987 } 15988 15989 index = base_index; 15990 15991 /* Write the index of the macro-meter at "micro_flow_index" location 15992 of SVM_MACROFLOW_INDEX_TABLE */ 15993 if (policer_control->direction == GLOBAL_METER_ALLOC_VERTICAL) { 15994 15995 entry_mem_size = sizeof(svm_macroflow_index_table_entry_t); 15996 entry_index_max = index + numbers - 1; 15997 15998 /* Allocate buffer to store the DMAed table entries. */ 15999 buf = soc_cm_salloc(unit, entry_mem_size * numbers, 16000 "svm macro flow index table entry buffer"); 16001 if (NULL == buf) { 16002 return (BCM_E_MEMORY); 16003 } 16004 /* Initialize the entry buffer. */ 16005 sal_memset(buf, 0, sizeof(entry_mem_size) * numbers); 16006 16007 /* Read the table entries into the buffer. */ 16008 rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 16009 MEM_BLOCK_ALL, index, 16010 entry_index_max, buf); 16011 if (BCM_FAILURE(rv)) { 16012 if (buf) { 16013 soc_cm_sfree(unit, buf); 16014 } 16015 return rv; 16016 } 16017 16018 /* Iterate over the table entries. */ 16019 for (entry_index = 0; entry_index < numbers; entry_index++) { 16020 entry = soc_mem_table_idx_to_pointer(unit, 16021 SVM_MACROFLOW_INDEX_TABLEm, 16022 svm_macroflow_index_table_entry_t *, 16023 buf, entry_index); 16024 soc_mem_field_get(unit, SVM_MACROFLOW_INDEX_TABLEm, (void *)entry, 16025 MACROFLOW_INDEXf, (uint32 *)¯o_flow_meter_index); 16026 if (macro_flow_meter_index > 0) { 16027 _bcm_esw_get_policer_id_from_index_offset(unit, 16028 macro_flow_meter_index, 0, ¯o_meter_policer); 16029 rv = _bcm_esw_policer_decrement_ref_count(unit, 16030 macro_meter_policer); 16031 if (BCM_FAILURE(rv)) { 16032 LOG_VERBOSE(BSL_LS_BCM_POLICER, 16033 (BSL_META_U(unit, 16034 "Unable to decrement ref count " 16035 "for macro meter provided\n"))); 16036 if (buf) { 16037 soc_cm_sfree(unit, buf); 16038 } 16039 return rv; 16040 } 16041 macro_flow_meter_index = 0; /* clear macro flow index entry */ 16042 soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm, 16043 (void *)entry, MACROFLOW_INDEXf, 16044 (uint32 *)¯o_flow_meter_index); 16045 entry_modified = 1; 16046 } 16047 } 16048 if (entry_modified) { 16049 if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 16050 MEM_BLOCK_ALL, index, 16051 entry_index_max, buf)) < 0) { 16052 if (BCM_FAILURE(rv)) { 16053 LOG_VERBOSE(BSL_LS_BCM_POLICER, 16054 (BSL_META_U(unit, 16055 "Unable to write to macro flow " 16056 "index table at index provided\n"))); 16057 if (buf) { 16058 soc_cm_sfree(unit, buf); 16059 } 16060 return rv; 16061 } 16062 } 16063 } 16064 if (buf) { 16065 soc_cm_sfree(unit, buf); 16066 } 16067 } 16068 /* De-allocate policer descriptor. */ 16069 sal_free(policer_control); 16070 16071 return rv; 16072 } 16073 16074 /* 16075 * Function: 16076 * _bcm_esw_global_meter_set_cascade_info_to_hw 16077 * Purpose: 16078 * In case of cascade meter, write configuration info that is 16079 * specific to cascade meters to HW 16080 * Parameters: 16081 * unit - (IN) unit number 16082 * numbers - (IN) Number of policers 16083 * policer_id - (IN) base policer id 16084 * mode - (IN) policer group mode 16085 * pid_offset - (IN) Offset w.r.t base policer 16086 * Returns: 16087 * BCM_E_XXX 16088 */ 16089 int _bcm_esw_global_meter_set_cascade_info_to_hw(int unit,int numbers, 16090 bcm_policer_t policer_id, 16091 bcm_policer_group_mode_t mode, uint8 *pid_offset) 16092 { 16093 int rv = BCM_E_NONE; 16094 svm_meter_table_entry_t data; 16095 int index = 0; 16096 uint32 start_of_chain = 0, end_of_chain = 0, meter_mode = 0; 16097 uint32 coupling_flag = 0; 16098 int size_pool; 16099 int policer_index = 0; 16100 int table_offset = 0; 16101 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 16102 16103 _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index); 16104 16105 for (index=0; index < numbers; index++) { 16106 if (index > 0) { 16107 table_offset = policer_index + (pid_offset[index] * size_pool); 16108 } else { 16109 table_offset = policer_index; 16110 } 16111 /* read HW register */ 16112 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 16113 table_offset, &data); 16114 if (BCM_FAILURE(rv)) { 16115 LOG_DEBUG(BSL_LS_BCM_POLICER, 16116 (BSL_META_U(unit, 16117 "Unable to read SVC METER TABLE at " 16118 "offset %d\n"), table_offset)); 16119 return (rv); 16120 } 16121 switch (mode) { 16122 case bcmPolicerGroupModeCascade: 16123 case bcmPolicerGroupModeIntPriCascade: 16124 case bcmPolicerGroupModeCascadeDroppedPktExclude: 16125 if (index == 0) { 16126 end_of_chain = 1; 16127 } else { 16128 end_of_chain = 0; 16129 } 16130 if (index == (numbers - 1)) { 16131 start_of_chain = 1; 16132 } else { 16133 start_of_chain = 0; 16134 } 16135 meter_mode = 1; 16136 coupling_flag = 0; 16137 break; 16138 16139 16140 case bcmPolicerGroupModeCascadeWithCoupling: 16141 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 16142 if ((index == 0) || (index == (numbers / 2))) { 16143 end_of_chain = 1; 16144 } else { 16145 end_of_chain = 0; 16146 } 16147 if ((index == (numbers - 1)) || (index == ((numbers/2) - 1))) { 16148 start_of_chain = 1; 16149 } else { 16150 start_of_chain = 0; 16151 } 16152 meter_mode = 1; 16153 coupling_flag = 1; 16154 break; 16155 16156 default: 16157 LOG_DEBUG(BSL_LS_BCM_POLICER, 16158 (BSL_META_U(unit, 16159 "Invalid mode passed \n"))); 16160 return BCM_E_NONE; 16161 break; 16162 } 16163 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, START_OF_CHAINf)) { 16164 soc_SVM_METER_TABLEm_field_set(unit, &data, 16165 START_OF_CHAINf, &start_of_chain); 16166 } 16167 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, END_OF_CHAINf)) { 16168 soc_SVM_METER_TABLEm_field_set(unit, &data, 16169 END_OF_CHAINf, &end_of_chain); 16170 } 16171 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 16172 soc_SVM_METER_TABLEm_field_set(unit, &data, 16173 METER_MODEf, &meter_mode); 16174 } 16175 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) { 16176 soc_SVM_METER_TABLEm_field_set(unit, &data, 16177 COUPLING_FLAGf, &coupling_flag); 16178 } 16179 /* write to hW */ 16180 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 16181 table_offset, &data); 16182 if (BCM_FAILURE(rv)) { 16183 LOG_DEBUG(BSL_LS_BCM_POLICER, 16184 (BSL_META_U(unit, 16185 "Unable to write SVC METER TABLE at " 16186 "offset %d\n"), table_offset)); 16187 return (rv); 16188 } 16189 } 16190 return rv; 16191 } 16192 16193 /* 16194 * Function: 16195 * _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw 16196 * Purpose: 16197 * In case of MEF 10.3 cascade meter, write configuration info that is 16198 * specific to cascade meters to HW 16199 * Parameters: 16200 * unit - (IN) unit number 16201 * numbers - (IN) Number of policers 16202 * policer_id - (IN) base policer id 16203 * mode - (IN) policer group mode 16204 * pid_offset - (IN) Offset w.r.t base policer 16205 * Returns: 16206 * BCM_E_XXX 16207 */ 16208 int 16209 _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw (int unit, 16210 int numbers, 16211 bcm_policer_t policer_id, 16212 bcm_policer_group_mode_t mode, 16213 uint8 *pid_offset) 16214 { 16215 int rv = BCM_E_NONE; 16216 int pool = 0; 16217 uint32 nxt_c = 0, nxt_e = 0, c_e = 0, pair_e = 0; 16218 uint32 nxt_c_valid = 0, nxt_e_valid = 0, pair_e_valid = 0; 16219 uint32 meter_mode = 0; 16220 int size_pool; 16221 int policer_index = 0; 16222 int table_offset = 0; 16223 svm_meter_table_entry_t svm_entry; 16224 16225 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 16226 _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index); 16227 16228 for (pool = 0; pool < numbers; pool++) { 16229 if (pool > 0) { 16230 table_offset = policer_index + (pid_offset[pool] * size_pool); 16231 } else { 16232 table_offset = policer_index; 16233 } 16234 16235 /* read HW register */ 16236 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 16237 table_offset, &svm_entry); 16238 if (BCM_FAILURE(rv)) { 16239 LOG_DEBUG(BSL_LS_BCM_POLICER, 16240 (BSL_META_U(unit, 16241 "Unable to read SVC METER TABLE at " 16242 "offset %d\n"), table_offset)); 16243 return (rv); 16244 } 16245 16246 meter_mode = 1; 16247 16248 switch (mode) { 16249 case bcmPolicerGroupModeCascade: 16250 case bcmPolicerGroupModeIntPriCascade: 16251 case bcmPolicerGroupModeCascadeDroppedPktExclude: 16252 { 16253 /* For non GCF mode, overflow fields need to be over written 16254 * during individual policer_set if policer mode is passed 16255 * as CoupledCascaded 16256 */ 16257 c_e = 0; 16258 nxt_c_valid = 1; /* Should the last C_Valid always be true? */ 16259 nxt_e_valid = (pool == (numbers -1)) ? 0 : 1; 16260 nxt_c = nxt_e = (pool == (numbers -1)) ? 0 : pool + 1; 16261 } 16262 break; 16263 16264 case bcmPolicerGroupModeCascadeWithCoupling: /* Pass through */ 16265 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 16266 { 16267 /* Set GCF configuration, it is 2 stage process 16268 * Stage 1 - Set committed cascaded chain 16269 * Stage 2 - Set excess cascaded chain 16270 */ 16271 16272 if (pool < 4) { 16273 /* Stage 1 - committed chain */ 16274 c_e = (pool == (numbers/2 -1)) ? 1 : 0; 16275 nxt_c_valid = 1; 16276 nxt_c = pool + 1; 16277 nxt_e_valid = 0; 16278 nxt_e = 0; 16279 pair_e_valid = 1; 16280 pair_e = pool + 4; 16281 } else { 16282 /* Stage 2 - excess chain */ 16283 c_e = 0; 16284 nxt_c_valid = 0; 16285 nxt_c = 0; 16286 nxt_e_valid = (pool == (numbers -1)) ? 0 : 1; 16287 nxt_e = (pool == (numbers -1)) ? 0 : pool + 1; 16288 pair_e_valid = 0; 16289 pair_e = 0; 16290 } 16291 16292 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16293 METER_PAIR_EXCESS_BUCKETf, 16294 &pair_e); 16295 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16296 METER_PAIR_EXCESS_BUCKET_VALIDf, 16297 &pair_e_valid); 16298 } 16299 break; 16300 16301 default: 16302 LOG_DEBUG(BSL_LS_BCM_POLICER, 16303 (BSL_META_U(unit, 16304 "Invalid mode passed \n"))); 16305 return BCM_E_NONE; 16306 } 16307 16308 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16309 NXT_EXCESS_BUCKETf, 16310 &nxt_e); 16311 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16312 NXT_EXCESS_BUCKET_VALIDf, 16313 &nxt_e_valid); 16314 16315 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16316 NXT_COMMITTED_BUCKETf, 16317 &nxt_c); 16318 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16319 NXT_COMMITTED_BUCKET_VALIDf, 16320 &nxt_c_valid); 16321 16322 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16323 COMMITTED_EXCESSf, 16324 &c_e); 16325 16326 soc_SVM_METER_TABLEm_field_set(unit, &svm_entry, 16327 METER_MODEf, &meter_mode); 16328 16329 /* write to hW */ 16330 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 16331 table_offset, &svm_entry); 16332 if (BCM_FAILURE(rv)) { 16333 LOG_DEBUG(BSL_LS_BCM_POLICER, 16334 (BSL_META_U(unit, 16335 "Unable to write SVC METER TABLE at " 16336 "offset %d\n"), table_offset)); 16337 return (rv); 16338 } 16339 } /* End for loop */ 16340 16341 return rv; 16342 } 16343 16344 /* 16345 * Function: 16346 * _bcm_esw_policer_set_offset_table_map_to_increasing_value 16347 * Purpose: 16348 * Set first n entires of the offset table with a incremental value. 16349 * starting from 0 16350 * Parameters: 16351 * num_offsets - (IN) Number of offsets 16352 * offset_map - (IN/OUT) Offset Map 16353 * Returns: 16354 * BCM_E_XXX 16355 */ 16356 int _bcm_esw_policer_set_offset_table_map_to_increasing_value(uint32 num_offsets, 16357 offset_table_entry_t *offset_map) 16358 { 16359 int rv = BCM_E_NONE; 16360 int i = 0; 16361 if (num_offsets >= BCM_SVC_METER_MAP_SIZE_256) { 16362 LOG_DEBUG(BSL_LS_BCM_POLICER, 16363 (BSL_META("Number of offsets passed is more than map table " 16364 "size %d\n"), num_offsets)); 16365 return BCM_E_INTERNAL; 16366 } 16367 for(i = 0; i < num_offsets; i++) { 16368 offset_map[i].offset= i; 16369 offset_map[i].meter_enable = 1; 16370 } 16371 return rv; 16372 } 16373 16374 /* 16375 * Function: 16376 * _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool 16377 * Purpose: 16378 * Set first n entires of the offset table with a specified value. 16379 * Parameters: 16380 * unit - (IN) unit number 16381 * Coupling - (IN) Coupling flag 16382 * num_offsets - (IN) Number of offsets 16383 * value - (IN) Value to be set 16384 * offset_map - (IN/OUT) Offset Map 16385 * Returns: 16386 * BCM_E_XXX 16387 */ 16388 int _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool(int unit, 16389 int coupling, 16390 uint32 num_offsets, 16391 uint32 value, 16392 offset_table_entry_t *offset_map) 16393 { 16394 int rv = BCM_E_NONE; 16395 int i = 0, j = 0; 16396 int pool_offset_limit; 16397 16398 pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 : 16399 BCM_POLICER_GLOBAL_METER_MAX_POOL; 16400 if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) { 16401 LOG_DEBUG(BSL_LS_BCM_POLICER, 16402 (BSL_META("Number of offsets passed is more than map table " 16403 "size %d\n"), num_offsets)); 16404 return BCM_E_INTERNAL; 16405 } 16406 if (num_offsets) { 16407 if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 16408 /* pre MEF 10.3 device */ 16409 i = num_offsets - 1; 16410 for(; i >= 0; i--) { 16411 if (coupling) { 16412 offset_map[j].pool = j + 4; 16413 } else { 16414 offset_map[j].pool = j; 16415 } 16416 offset_map[j].offset= value; 16417 offset_map[j].meter_enable = 1; 16418 j++; 16419 } 16420 } else { 16421 /* MEF 10.3 onward device */ 16422 for (j = 0; j < num_offsets; j++) { 16423 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending)) { 16424 offset_map[j].pool = pool_offset_limit - j - 1; 16425 } else { 16426 offset_map[j].pool = j; 16427 } 16428 offset_map[j].offset= value; 16429 offset_map[j].meter_enable = 1; 16430 } 16431 } 16432 } 16433 return rv; 16434 } 16435 16436 /* 16437 * Function: 16438 * _bcm_esw_policer_set_offset_table_map_flex_pool 16439 * Purpose: 16440 * Set first n entires of the offset table with a specified value. 16441 * Parameters: 16442 * unit - (IN) unit number 16443 * Coupling - (IN) Coupling flag 16444 * num_offsets - (IN) Number of offsets 16445 * pool_offset - (IN) Values to be set as offsets 16446 * offset_map - (IN/OUT) Offset Map 16447 * Returns: 16448 * BCM_E_XXX 16449 */ 16450 int _bcm_esw_policer_set_offset_table_map_flex_pool(int unit, 16451 int coupling, 16452 uint32 num_offsets, 16453 uint32 *pool_offset, 16454 offset_table_entry_t *offset_map) 16455 { 16456 int rv = BCM_E_NONE; 16457 int i = 0, j = 0; 16458 int pool_offset_limit; 16459 16460 if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) { 16461 LOG_DEBUG(BSL_LS_BCM_POLICER, 16462 (BSL_META("Number of offsets passed is more than map table " 16463 "size %d\n"), num_offsets)); 16464 return BCM_E_INTERNAL; 16465 } 16466 16467 pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 : 16468 BCM_POLICER_GLOBAL_METER_MAX_POOL; 16469 16470 if (num_offsets) { 16471 if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 16472 i = num_offsets - 1; 16473 for(; i >= 0; i--) { 16474 if (coupling) { 16475 offset_map[j].pool = pool_offset[j] + 4; 16476 } else { 16477 offset_map[j].pool = pool_offset[j]; 16478 } 16479 offset_map[j].offset= 0; 16480 offset_map[j].meter_enable = 1; 16481 j++; 16482 } 16483 } else { 16484 /* MEF 10.3 onward devices */ 16485 for (j = 0; j < num_offsets; j++) { 16486 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending)) { 16487 offset_map[j].pool = pool_offset_limit - pool_offset[j] - 1; 16488 } else { 16489 offset_map[j].pool = pool_offset[j]; 16490 } 16491 offset_map[j].offset = 0; 16492 offset_map[j].meter_enable = 1; 16493 } 16494 } 16495 } 16496 return rv; 16497 } 16498 16499 /* 16500 * Function: 16501 * _bcm_esw_policer_set_offset_table_map_to_a_value 16502 * Purpose: 16503 * Set first n entires of the offset table with a specified value. 16504 * Parameters: 16505 * num_offsets - (IN) Number of offsets 16506 * value - (IN) Value to be set 16507 * offset_map - (IN/OUT) Offset Map 16508 * Returns: 16509 * BCM_E_XXX 16510 */ 16511 int _bcm_esw_policer_set_offset_table_map_to_a_value(uint32 num_offsets, 16512 uint32 value, 16513 offset_table_entry_t *offset_map) 16514 { 16515 int rv = BCM_E_NONE; 16516 int i = 0; 16517 if (num_offsets >= BCM_SVC_METER_MAP_SIZE_256) { 16518 LOG_DEBUG(BSL_LS_BCM_POLICER, 16519 (BSL_META("Number of offsets passed is more than map table " 16520 "size %d\n"), num_offsets)); 16521 return BCM_E_INTERNAL; 16522 } 16523 for(i = 0; i < num_offsets; i++) { 16524 offset_map[i].offset= value; 16525 offset_map[i].meter_enable = 1; 16526 } 16527 return rv; 16528 } 16529 16530 /* 16531 * Function: 16532 * _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool 16533 * Purpose: 16534 * Create the map of offset table with varying pool of policers that needs 16535 * to be written to different offsets 16536 * Parameters: 16537 * unit - (IN) unit number 16538 * Coupling - (IN) Coupling flag 16539 * num_offsets - (IN) Number of offsets 16540 * table_offset - (IN) Offset positons 16541 * pool_offset - (IN) Values to be set as offsets 16542 * offset_map - (IN/OUT) Offset Map 16543 * Returns: 16544 * BCM_E_XXX 16545 */ 16546 16547 int _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool(int unit, 16548 int coupling, 16549 uint32 num_offsets, 16550 uint32 *table_offset, 16551 uint32 *pool_offset, 16552 offset_table_entry_t *offset_map) 16553 { 16554 int rv = BCM_E_NONE; 16555 int i = 0, j = 0; 16556 int pool_offset_limit; 16557 16558 if (num_offsets > BCM_SVC_METER_MAP_SIZE_256) { 16559 LOG_DEBUG(BSL_LS_BCM_POLICER, 16560 (BSL_META("Number of offsets passed is more than map table " 16561 "size %d\n"), num_offsets)); 16562 return BCM_E_INTERNAL; 16563 } 16564 16565 pool_offset_limit = (coupling) ? BCM_POLICER_GLOBAL_METER_MAX_POOL/2 : 16566 BCM_POLICER_GLOBAL_METER_MAX_POOL; 16567 16568 if (num_offsets) { 16569 if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 16570 i = num_offsets - 1; 16571 for(j = 0; j <= i; j++) { 16572 if ((table_offset[j] >= BCM_SVC_METER_MAP_SIZE_256) || 16573 (pool_offset[j] >= pool_offset_limit)) { 16574 LOG_DEBUG(BSL_LS_BCM_POLICER, 16575 (BSL_META("Offset/pool passed is out of range " 16576 "size %d %d\n"), table_offset[j], pool_offset[j])); 16577 return BCM_E_PARAM; 16578 } 16579 16580 if (coupling) { 16581 offset_map[table_offset[j]].pool = pool_offset[j] + 4; 16582 } else { 16583 offset_map[table_offset[j]].pool = pool_offset[j]; 16584 } 16585 offset_map[table_offset[j]].offset= 0; 16586 offset_map[table_offset[j]].meter_enable = 1; 16587 } 16588 } else { 16589 /* MEF 10.3 onward devices */ 16590 for (j = 0; j < num_offsets; j++) { 16591 if ((table_offset[j] >= BCM_SVC_METER_MAP_SIZE_256) || 16592 (pool_offset[j] >= pool_offset_limit)) { 16593 LOG_DEBUG(BSL_LS_BCM_POLICER, 16594 (BSL_META("Offset/pool passed is out of range " 16595 "size %d %d\n"), table_offset[j], pool_offset[j])); 16596 return BCM_E_PARAM; 16597 } 16598 16599 if (soc_feature(unit, soc_feature_global_meter_pool_priority_descending)) { 16600 offset_map[table_offset[j]].pool = pool_offset_limit - pool_offset[j] - 1; 16601 } else { 16602 offset_map[table_offset[j]].pool = pool_offset[j]; 16603 } 16604 offset_map[table_offset[j]].offset = 0; 16605 offset_map[table_offset[j]].meter_enable = 1; 16606 } 16607 } 16608 } 16609 return rv; 16610 } 16611 16612 /* 16613 * Function: 16614 * _bcm_esw_policer_set_offset_table_map 16615 * Purpose: 16616 * Create the map of policer offsets that needs to be written to offset 16617 * table 16618 * Parameters: 16619 * num_offsets - (IN) Number of offsets 16620 * table_offset - (IN) Offset positons 16621 * value - (IN) Values to be set 16622 * offset_map - (IN/OUT) Offset Map 16623 * Returns: 16624 * BCM_E_XXX 16625 */ 16626 int _bcm_esw_policer_set_offset_table_map(uint32 num_offsets, 16627 uint32 *table_offset, 16628 uint32 *value, 16629 offset_table_entry_t *offset_map) 16630 { 16631 int rv = BCM_E_NONE; 16632 int i = 0; 16633 for(i = 0; i < num_offsets; i++) { 16634 if ((table_offset[i] >= BCM_SVC_METER_MAP_SIZE_256) || 16635 (value[i] >= BCM_SVC_METER_MAP_SIZE_256)) { 16636 LOG_DEBUG(BSL_LS_BCM_POLICER, 16637 (BSL_META("Offset/value passed is more than map table " 16638 "size %d %d\n"), table_offset[i], value[i])); 16639 return BCM_E_INTERNAL; 16640 } 16641 offset_map[table_offset[i]].offset= value[i]; 16642 offset_map[table_offset[i]].meter_enable = 1; 16643 } 16644 return rv; 16645 } 16646 16647 /* 16648 * Function: 16649 * _bcm_esw_policer_group_set_mode_and_map 16650 * Purpose: 16651 * 16652 * Parameters: 16653 * unit - (IN) unit number 16654 * mode - (IN) Policer group mode 16655 * npolicers - (IN) Number of policers 16656 * direction - (IN) Horizontal/Vertical 16657 * mode_attr - (IN) Offset mode attributes 16658 * Returns: 16659 * BCM_E_XXX 16660 */ 16661 int _bcm_esw_policer_group_set_mode_and_map( int unit, 16662 bcm_policer_group_mode_t mode, 16663 int *npolicers, bcm_policer_map_t *mapping, 16664 uint32 *direction, 16665 bcm_policer_svc_meter_attr_t *mode_attr) 16666 { 16667 int rv = BCM_E_NONE; 16668 int num_pools = 0; 16669 uint32 table_offset[16] = { 0 }; 16670 uint32 value[16] = { 0 }; 16671 pkt_attr_bits_t *pkt_attr = NULL; 16672 uint32 map_index = 0; 16673 compressed_pkt_res_attr_map_t *pkt_res_map = NULL; 16674 compressed_pri_cnf_attr_map_t *pri_cnf_map = NULL; 16675 offset_table_entry_t *offset_map = NULL; 16676 uint32 type = 0; 16677 uint32 offset = 0; 16678 uint8 *pkt_res = NULL; 16679 int no_entries_to_populate = 0; 16680 int shift_bits = 0; 16681 int index_max = 0; 16682 int i = 0; 16683 uint8 *val = NULL; 16684 16685 mode_attr->mode_type_v = uncompressed_mode; 16686 num_pools = SOC_INFO(unit).global_meter_pools; 16687 if (mapping != NULL) { 16688 val = mapping->offset_map; 16689 } 16690 16691 if (BCM_SVM_DEV_ATTR(unit)->pkt_resolution != NULL) { 16692 pkt_res = BCM_SVM_DEV_ATTR(unit)->pkt_resolution; 16693 } else { 16694 /* 16695 * Other devices do not support service meters, return error. 16696 */ 16697 return (BCM_E_UNAVAIL); 16698 } 16699 16700 switch (mode) { 16701 /* A single policer used for all traffic types */ 16702 case bcmPolicerGroupModeSingle: 16703 { 16704 *npolicers = 1; 16705 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 16706 FP_RESOLUTION_MAX, 0, 16707 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16708 BCM_IF_ERROR_RETURN(rv); 16709 break; 16710 } 16711 /* ********************************************************************/ 16712 /* A dedicated policer per traffic type Unicast,multicast,broadcast */ 16713 /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT */ 16714 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT*/ 16715 /* 3) L2BC_PKT| */ 16716 /* *******************************************************************/ 16717 case bcmPolicerGroupModeTrafficType: 16718 { 16719 *npolicers = 3; 16720 mode_attr->uncompressed_attr_selectors_v.\ 16721 uncompressed_attr_bits_selector = 16722 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16723 table_offset[0] = pkt_res[KNOWN_L2UC_PKT]; 16724 table_offset[1] = pkt_res[KNOWN_L3UC_PKT]; 16725 table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT]; 16726 table_offset[3] = pkt_res[KNOWN_L2MC_PKT]; 16727 table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT]; 16728 table_offset[5] = pkt_res[L2BC_PKT]; 16729 table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT]; 16730 table_offset[7] = pkt_res[UNKNOWN_IPMC_PKT]; 16731 table_offset[8] = pkt_res[KNOWN_IPMC_PKT]; 16732 value[3] = 1; 16733 value[4] = 1; 16734 value[5] = 2; 16735 value[7] = 1; 16736 value[8] = 1; 16737 16738 rv = _bcm_esw_policer_set_offset_table_map(9, &table_offset[0], 16739 &value[0], 16740 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16741 BCM_IF_ERROR_RETURN(rv); 16742 break; 16743 } 16744 /************************************************************** */ 16745 /* A pair of policers where the base policer is used for dlf and */ 16746 /* the other is used for all traffic types */ 16747 /* 1) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 16748 /* 2) UNKNOWN_PKT | CONTROL_PKT|BPDU_PKT|L2BC_PKT|L2UC_PKT| */ 16749 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 16750 /* UNKNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 16751 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 16752 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 16753 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 16754 /* ************************************************************* */ 16755 16756 case bcmPolicerGroupModeDlfAll: 16757 { 16758 *npolicers = 2; 16759 mode_attr->uncompressed_attr_selectors_v.\ 16760 uncompressed_attr_bits_selector = 16761 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16762 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 16763 FP_RESOLUTION_MAX, 1, 16764 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16765 BCM_IF_ERROR_RETURN(rv); 16766 table_offset[0] = pkt_res[UNKNOWN_L2UC_PKT]; 16767 value[0] = 0; 16768 rv = _bcm_esw_policer_set_offset_table_map(1, &table_offset[0], 16769 &value[0], 16770 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16771 BCM_IF_ERROR_RETURN(rv); 16772 break; 16773 } 16774 /* ******************************************************* */ 16775 /* A dedicated policer for unknown unicast, known unicast, */ 16776 /* multicast, broadcast */ 16777 /* 1) UNKNOWN_L3UC_PKT */ 16778 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 16779 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT | */ 16780 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 16781 /* 4) L2BC_PKT */ 16782 /* ******************************************************* */ 16783 case bcmPolicerGroupModeTyped: 16784 { 16785 *npolicers = 4; 16786 mode_attr->uncompressed_attr_selectors_v.\ 16787 uncompressed_attr_bits_selector = 16788 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16789 table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT]; 16790 table_offset[1] = pkt_res[KNOWN_L3UC_PKT]; 16791 table_offset[2] = pkt_res[KNOWN_L2UC_PKT]; 16792 table_offset[3] = pkt_res[KNOWN_L2MC_PKT]; 16793 table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT]; 16794 table_offset[5] = pkt_res[L2BC_PKT]; 16795 table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT]; 16796 table_offset[7] = pkt_res[UNKNOWN_IPMC_PKT]; 16797 table_offset[8] = pkt_res[KNOWN_IPMC_PKT]; 16798 value[1] = 1; 16799 value[2] = 1; 16800 value[3] = 2; 16801 value[4] = 2; 16802 value[5] = 3; 16803 value[7] = 2; 16804 value[8] = 2; 16805 rv = _bcm_esw_policer_set_offset_table_map(9, &table_offset[0], 16806 &value[0], 16807 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16808 BCM_IF_ERROR_RETURN(rv); 16809 break; 16810 } 16811 /* ******************************************************* */ 16812 /* A dedicated policer for unknown unicast, known unicast, */ 16813 /* multicast, broadcast and one for all traffic(not already*/ 16814 /* counted) */ 16815 /* 1) UNKNOWN_L3UC_PKT */ 16816 /* 2) L2UC_PKT | KNOWN_L3UC_PKT */ 16817 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 16818 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 16819 /* 4) L2BC_PKT */ 16820 /* 5) UNKNOWN_PKT|CONTROL_PKT|BPDU_PKT|L2DLF_PKT| */ 16821 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_MPLS_PKT | */ 16822 /* KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT */ 16823 /* KNOWN_MIM_PKT|UNKNOWN_MIM_PKT| */ 16824 /* KNOWN_MPLS_MULTICAST_PKT */ 16825 /* ******************************************************* */ 16826 case bcmPolicerGroupModeTypedAll: 16827 { 16828 *npolicers = 5; 16829 mode_attr->uncompressed_attr_selectors_v.\ 16830 uncompressed_attr_bits_selector = 16831 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16832 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 16833 FP_RESOLUTION_MAX, 4, 16834 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16835 BCM_IF_ERROR_RETURN(rv); 16836 table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT]; 16837 table_offset[1] = pkt_res[KNOWN_L3UC_PKT]; 16838 table_offset[2] = pkt_res[KNOWN_L2UC_PKT]; 16839 table_offset[3] = pkt_res[KNOWN_L2MC_PKT]; 16840 table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT]; 16841 table_offset[5] = pkt_res[L2BC_PKT]; 16842 table_offset[6] = pkt_res[UNKNOWN_L2UC_PKT]; 16843 table_offset[7] = pkt_res[KNOWN_IPMC_PKT]; 16844 table_offset[8] = pkt_res[UNKNOWN_IPMC_PKT]; 16845 value[1] = 1; 16846 value[2] = 1; 16847 value[3] = 2; 16848 value[4] = 2; 16849 value[5] = 3; 16850 value[7] = 2; 16851 value[8] = 2; 16852 rv = _bcm_esw_policer_set_offset_table_map(9, &table_offset[0], 16853 &value[0], 16854 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16855 BCM_IF_ERROR_RETURN(rv); 16856 break; 16857 } 16858 /* ************************************************************** */ 16859 /* A single policer used for all traffic types with an additional */ 16860 /* policer for control traffic */ 16861 /* 1) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT|L2DLF_PKT| */ 16862 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 16863 /* UNKNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 16864 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 16865 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 16866 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 16867 /* 2) CONTROL_PKT|BPDU_PKT */ 16868 /* ************************************************************** */ 16869 case bcmPolicerGroupModeSingleWithControl: 16870 { 16871 *npolicers = 2; 16872 mode_attr->uncompressed_attr_selectors_v.\ 16873 uncompressed_attr_bits_selector = 16874 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16875 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 16876 FP_RESOLUTION_MAX, 0, 16877 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16878 BCM_IF_ERROR_RETURN(rv); 16879 table_offset[0] = pkt_res[CONTROL_PKT]; 16880 table_offset[1] = pkt_res[BPDU_PKT]; 16881 value[0] = 1; 16882 value[1] = 1; 16883 rv = _bcm_esw_policer_set_offset_table_map(2, &table_offset[0], 16884 &value[0], 16885 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16886 BCM_IF_ERROR_RETURN(rv); 16887 break; 16888 } 16889 /* ******************************************************** */ 16890 /* A dedicated policer per traffic type unicast, multicast, */ 16891 /* broadcast with an additional counter for control traffic */ 16892 /* 1) L2UC_PKT | KNOWN_L3UC_PKT | UNKNOWN_L3UC_PKT */ 16893 /* 2) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| */ 16894 /* KNOWN_IPMC_PKT | UNKNOWN_IPMC_PKT */ 16895 /* 3) L2BC_PKT| */ 16896 /* 4) CONTROL_PKT|BPDU_PKT */ 16897 /* ******************************************************** */ 16898 case bcmPolicerGroupModeTrafficTypeWithControl: 16899 { 16900 *npolicers = 4; 16901 mode_attr->uncompressed_attr_selectors_v.\ 16902 uncompressed_attr_bits_selector = 16903 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16904 table_offset[0] = pkt_res[UNKNOWN_L3UC_PKT]; 16905 table_offset[1] = pkt_res[KNOWN_L3UC_PKT]; 16906 table_offset[2] = pkt_res[KNOWN_L2UC_PKT]; 16907 table_offset[3] = pkt_res[KNOWN_L2MC_PKT]; 16908 table_offset[4] = pkt_res[UNKNOWN_L2MC_PKT]; 16909 table_offset[5] = pkt_res[L2BC_PKT]; 16910 table_offset[6] = pkt_res[CONTROL_PKT]; 16911 table_offset[7] = pkt_res[BPDU_PKT]; 16912 table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT]; 16913 table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT]; 16914 table_offset[10] = pkt_res[KNOWN_IPMC_PKT]; 16915 value[3] = 1; 16916 value[4] = 1; 16917 value[5] = 2; 16918 value[6] = 3; 16919 value[7] = 3; 16920 value[9] = 1; 16921 value[10] = 1; 16922 rv = _bcm_esw_policer_set_offset_table_map(11, &table_offset[0], 16923 &value[0], 16924 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16925 BCM_IF_ERROR_RETURN(rv); 16926 break; 16927 } 16928 /* ************************************************************** */ 16929 /* A set of 3 policers where the base policer is used for control,*/ 16930 /* the next one for dlf and the other counter is used for all */ 16931 /* traffic types */ 16932 /* 1) CONTROL_PKT|BPDU_PKT */ 16933 /* 2) L2DLF_PKT(UNKNOWN_L2UC_PKT) */ 16934 /* 3) UNKNOWN_PKT|L2BC_PKT|L2UC_PKT| */ 16935 /* UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT|KNOWN_L2MC_PKT| */ 16936 /* UNKNOWN_L2MC_PKT|KNOWN_L3UC_PKT| */ 16937 /* UNKNOWN_L3UC_PKT|KNOWN_MPLS_PKT|KNOWN_MPLS_L3_PKT| */ 16938 /* KNOWN_MPLS_L2_PKT|UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT| */ 16939 /* UNKNOWN_MIM_PKT|KNOWN_MPLS_MULTICAST_PKT */ 16940 /* ************************************************************** */ 16941 case bcmPolicerGroupModeDlfAllWithControl: 16942 { 16943 *npolicers = 3; 16944 mode_attr->uncompressed_attr_selectors_v.\ 16945 uncompressed_attr_bits_selector = 16946 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16947 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 16948 FP_RESOLUTION_MAX, 2, 16949 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16950 BCM_IF_ERROR_RETURN(rv); 16951 table_offset[0] = pkt_res[CONTROL_PKT]; 16952 table_offset[1] = pkt_res[BPDU_PKT]; 16953 table_offset[2] = pkt_res[UNKNOWN_L2UC_PKT]; 16954 value[2] = 1; 16955 rv = _bcm_esw_policer_set_offset_table_map(3, &table_offset[0], 16956 &value[0], 16957 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 16958 BCM_IF_ERROR_RETURN(rv); 16959 break; 16960 } 16961 /* **************************************************************** */ 16962 /* A dedicated policer for control, unknown unicast, known unicast, */ 16963 /* multicast, broadcast */ 16964 /* 1) CONTROL_PKT|BPDU_PKT */ 16965 /* 2) UNKNOWN_L3UC_PKT */ 16966 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 16967 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT| */ 16968 /* KNOWN_IPMC_PKT| UNKNOWN_IPMC_PKT */ 16969 /* 5) L2BC_PKT */ 16970 /* **************************************************************** */ 16971 case bcmPolicerGroupModeTypedWithControl: 16972 { 16973 *npolicers = 5; 16974 mode_attr->uncompressed_attr_selectors_v.\ 16975 uncompressed_attr_bits_selector = 16976 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 16977 table_offset[0] = pkt_res[CONTROL_PKT]; 16978 table_offset[1] = pkt_res[BPDU_PKT]; 16979 table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT]; 16980 table_offset[3] = pkt_res[KNOWN_L2UC_PKT]; 16981 table_offset[4] = pkt_res[KNOWN_L3UC_PKT]; 16982 table_offset[5] = pkt_res[KNOWN_L2MC_PKT]; 16983 table_offset[6] = pkt_res[UNKNOWN_L2MC_PKT]; 16984 table_offset[7] = pkt_res[L2BC_PKT]; 16985 table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT]; 16986 table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT]; 16987 table_offset[10] = pkt_res[KNOWN_IPMC_PKT]; 16988 value[2] = 1; 16989 value[3] = 2; 16990 value[4] = 2; 16991 value[5] = 3; 16992 value[6] = 3; 16993 value[7] = 4; 16994 value[8] = 1; 16995 value[9] = 3; 16996 value[10] = 3; 16997 rv = _bcm_esw_policer_set_offset_table_map(11, &table_offset[0], 16998 &value[0], 16999 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17000 BCM_IF_ERROR_RETURN(rv); 17001 break; 17002 } 17003 /* ***************************************************************** */ 17004 /* A dedicated policer for control, unknown unicast, known unicast, */ 17005 /* multicast, broadcast and one for all traffic (not already policed)*/ 17006 /* 1) CONTROL_PKT|BPDU_PKT */ 17007 /* 2) UNKNOWN_L3UC_PKT */ 17008 /* 3) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 17009 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT|KNOWN_IPMC_PKT|UNKNOWN_IPMC_PKT*/ 17010 /* 5) L2BC_PKT */ 17011 /* 6) UNKNOWN_PKT|L2DLF_PKT|UNKNOWN_IPMC_PKT|KNOWN_IPMC_PKT */ 17012 /* KNOWN_MPLS_PKT | KNOWN_MPLS_L3_PKT|KNOWN_MPLS_L2_PKT| */ 17013 /* UNKNOWN_MPLS_PKT|KNOWN_MIM_PKT|UNKNOWN_MIM_PKT| */ 17014 /* KNOWN_MPLS_MULTICAST_PKT */ 17015 /* ***************************************************************** */ 17016 case bcmPolicerGroupModeTypedAllWithControl: 17017 { 17018 *npolicers = 6; 17019 mode_attr->uncompressed_attr_selectors_v.\ 17020 uncompressed_attr_bits_selector = 17021 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 17022 rv = _bcm_esw_policer_set_offset_table_map_to_a_value( 17023 FP_RESOLUTION_MAX, 5, 17024 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17025 BCM_IF_ERROR_RETURN(rv); 17026 table_offset[0] = pkt_res[CONTROL_PKT]; 17027 table_offset[1] = pkt_res[BPDU_PKT]; 17028 table_offset[2] = pkt_res[UNKNOWN_L3UC_PKT]; 17029 table_offset[3] = pkt_res[KNOWN_L2UC_PKT]; 17030 table_offset[4] = pkt_res[KNOWN_L3UC_PKT]; 17031 table_offset[5] = pkt_res[KNOWN_L2MC_PKT]; 17032 table_offset[6] = pkt_res[UNKNOWN_L2MC_PKT]; 17033 table_offset[7] = pkt_res[L2BC_PKT]; 17034 table_offset[8] = pkt_res[UNKNOWN_L2UC_PKT]; 17035 table_offset[9] = pkt_res[UNKNOWN_IPMC_PKT]; 17036 table_offset[10] = pkt_res[KNOWN_IPMC_PKT]; 17037 value[2] = 1; 17038 value[3] = 2; 17039 value[4] = 2; 17040 value[5] = 3; 17041 value[6] = 3; 17042 value[7] = 4; 17043 value[8] = 1; 17044 value[9] = 3; 17045 value[10] = 3; 17046 rv = _bcm_esw_policer_set_offset_table_map(11, &table_offset[0], 17047 &value[0], 17048 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17049 BCM_IF_ERROR_RETURN(rv); 17050 break; 17051 } 17052 /* ******************************************************** */ 17053 /* A set of 8(2^3) policers selected based on outer Vlan pri*/ 17054 /* outer_dot1p; 3 bits 1..8 */ 17055 /* ******************************************************** */ 17056 17057 case bcmPolicerGroupModeDot1P: 17058 { 17059 *npolicers = 8; 17060 mode_attr->uncompressed_attr_selectors_v.\ 17061 uncompressed_attr_bits_selector = 17062 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS; 17063 if (mapping == NULL) { 17064 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17065 *npolicers, 17066 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17067 } else { 17068 for (i = 0; i < mapping->count; i++) { 17069 table_offset[i] = i; 17070 value[i] = *val; 17071 val++; 17072 } 17073 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17074 &table_offset[0], 17075 &value[0], 17076 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17077 } 17078 17079 BCM_IF_ERROR_RETURN(rv); 17080 break; 17081 } 17082 /* ******************************************************** */ 17083 /* A set of 8(2^3) policers selected based on inner Vlan pri*/ 17084 /* inner_dot1p; 3 bits 1..8 */ 17085 /* ******************************************************** */ 17086 17087 case bcmPolicerGroupModeInnerDot1P: 17088 { 17089 *npolicers = 8; 17090 mode_attr->uncompressed_attr_selectors_v.\ 17091 uncompressed_attr_bits_selector = 17092 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS; 17093 if (mapping == NULL) { 17094 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17095 *npolicers, 17096 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17097 } else { 17098 for (i = 0; i < mapping->count; i++) { 17099 table_offset[i] = i; 17100 value[i] = *val; 17101 val++; 17102 } 17103 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17104 &table_offset[0], 17105 &value[0], 17106 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17107 } 17108 17109 BCM_IF_ERROR_RETURN(rv); 17110 break; 17111 } 17112 /* **************************************************** */ 17113 /* A set of 16(2^4) policers based on internal priority */ 17114 /* 1..16 INT_PRI bits: 4bits */ 17115 /* **************************************************** */ 17116 case bcmPolicerGroupModeIntPri: 17117 { 17118 *npolicers = 16; 17119 mode_attr->uncompressed_attr_selectors_v.\ 17120 uncompressed_attr_bits_selector = 17121 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS; 17122 if (mapping == NULL) { 17123 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17124 *npolicers, 17125 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17126 } else { 17127 for (i = 0; i < mapping->count; i++) { 17128 table_offset[i] = i; 17129 value[i] = *val; 17130 val++; 17131 } 17132 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17133 &table_offset[0], 17134 &value[0], 17135 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17136 } 17137 BCM_IF_ERROR_RETURN(rv); 17138 break; 17139 } 17140 /* ********************************************************** */ 17141 /* set of 64 policers(2^(4+2)) based on Internal priority+CNG */ 17142 /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits */ 17143 /* 1..64 (INT_PRI bits: 4bits + CNG 2 bits */ 17144 /* ********************************************************** */ 17145 case bcmPolicerGroupModeIntPriCng: 17146 { 17147 *npolicers = 64; 17148 mode_attr->uncompressed_attr_selectors_v.\ 17149 uncompressed_attr_bits_selector = 17150 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS | 17151 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS; 17152 if (mapping == NULL) { 17153 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17154 *npolicers, 17155 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17156 } else { 17157 for (i = 0; i < mapping->count; i++) { 17158 table_offset[i] = i; 17159 value[i] = *val; 17160 val++; 17161 } 17162 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17163 &table_offset[0], 17164 &value[0], 17165 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17166 } 17167 BCM_IF_ERROR_RETURN(rv); 17168 break; 17169 } 17170 /* ********************************************************** */ 17171 /* set of 8 policers(2^3) based on Internal priority */ 17172 /* 1..8 INT_PRI bits: 3bits */ 17173 /* ********************************************************** */ 17174 case bcmPolicerGroupModeShortIntPri: 17175 { 17176 *npolicers = 8; 17177 mode_attr->uncompressed_attr_selectors_v.\ 17178 uncompressed_attr_bits_selector = 17179 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS; 17180 if (mapping == NULL) { 17181 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17182 8, 17183 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17184 } else { 17185 for (i = 0; i < mapping->count; i++) { 17186 table_offset[i] = i; 17187 value[i] = *val; 17188 val++; 17189 } 17190 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17191 &table_offset[0], 17192 &value[0], 17193 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17194 } 17195 17196 BCM_IF_ERROR_RETURN(rv); 17197 break; 17198 } 17199 /* ****************************************** */ 17200 /* A set of 2 policers(2^1) based on SVP type */ 17201 /* 1..2 (SVP 1 bit). In case of KT2, SVP is 3 */ 17202 /* 3 bits and hence no of policers is 8 */ 17203 /* ********************************************/ 17204 case bcmPolicerGroupModeSvpType: 17205 { 17206 *npolicers = (1 << BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size); 17207 mode_attr->uncompressed_attr_selectors_v.\ 17208 uncompressed_attr_bits_selector = 17209 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS; 17210 if (mapping == NULL) { 17211 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17212 *npolicers, 17213 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17214 } else { 17215 for (i = 0; i < mapping->count; i++) { 17216 table_offset[i] = i; 17217 value[i] = *val; 17218 val++; 17219 } 17220 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17221 &table_offset[0], &value[0], 17222 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17223 } 17224 BCM_IF_ERROR_RETURN(rv); 17225 break; 17226 } 17227 17228 /* ******************************************** */ 17229 /* A set of 64 policers(2^6) based on DSCP bits */ 17230 /* 1..64 (6 bits from TOS 8 bits) */ 17231 /* ******************************************** */ 17232 case bcmPolicerGroupModeDscp: 17233 17234 { 17235 *npolicers = 64; 17236 mode_attr->uncompressed_attr_selectors_v.\ 17237 uncompressed_attr_bits_selector = 17238 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS; 17239 if (mapping == NULL) { 17240 rv = _bcm_esw_policer_set_offset_table_map_to_increasing_value( 17241 *npolicers, 17242 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17243 } else { 17244 for (i = 0; i < mapping->count; i++) { 17245 table_offset[i] = i; 17246 value[i] = *val; 17247 val++; 17248 } 17249 rv = _bcm_esw_policer_set_offset_table_map(*npolicers, 17250 &table_offset[0], &value[0], 17251 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17252 } 17253 BCM_IF_ERROR_RETURN(rv); 17254 break; 17255 } 17256 /* ******************************************** */ 17257 /* A set of n policers based on user input */ 17258 /* ******************************************** */ 17259 case bcmPolicerGroupModeCascade: 17260 if ((*npolicers > num_pools) || (*npolicers == 0 )) { 17261 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17262 (BSL_META_U(unit, 17263 "Invalid number of Policers \n"))); 17264 return BCM_E_PARAM; 17265 } 17266 *npolicers = 8; /* Numbers of meters in a cascade chain is 8 */ 17267 *direction = GLOBAL_METER_ALLOC_HORIZONTAL; 17268 mode_attr->mode_type_v = cascade_mode; 17269 mode_attr->uncompressed_attr_selectors_v.\ 17270 uncompressed_attr_bits_selector = 17271 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS; 17272 if (mapping == NULL) { 17273 rv = _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool( 17274 unit, 0, *npolicers, 0, 17275 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17276 } else { 17277 for (i = 0; i < mapping->count; i++) { 17278 table_offset[i] = i; 17279 value[i] = *val; 17280 val++; 17281 } 17282 rv = _bcm_esw_policer_set_offset_table_map_flex_pool( 17283 unit, 0, *npolicers, &value[0] , 17284 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17285 } 17286 BCM_IF_ERROR_RETURN(rv); 17287 break; 17288 /* ************************************************************* */ 17289 /* A set of n policers based on user input, with dropped packets */ 17290 /* not eligible for metering */ 17291 /* ************************************************************* */ 17292 case bcmPolicerGroupModeCascadeDroppedPktExclude: 17293 if ((*npolicers > num_pools) || (*npolicers == 0 )) { 17294 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17295 (BSL_META_U(unit, 17296 "Invalid number of Policers \n"))); 17297 return BCM_E_PARAM; 17298 } 17299 *npolicers = 8; /* Numbers of meters in a cascade chain is 8 */ 17300 *direction = GLOBAL_METER_ALLOC_HORIZONTAL; 17301 mode_attr->mode_type_v = cascade_mode; 17302 mode_attr->uncompressed_attr_selectors_v.\ 17303 uncompressed_attr_bits_selector = 17304 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS | 17305 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS; 17306 if (mapping == NULL) { 17307 for (i = 0; i < *npolicers; i++) { 17308 table_offset[i] = i*2; 17309 value[i] = i; 17310 } 17311 } else { 17312 for (i = 0; i < mapping->count; i++) { 17313 table_offset[i] = i*2; 17314 value[i] = *val; 17315 val++; 17316 } 17317 } 17318 rv = _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool( 17319 unit, 0, *npolicers, &table_offset[0], &value[0], 17320 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17321 BCM_IF_ERROR_RETURN(rv); 17322 break; 17323 /* ******************************************** */ 17324 /* A set of n policers based on user input based on IntPri*/ 17325 /* ******************************************** */ 17326 case bcmPolicerGroupModeIntPriCascade: 17327 { 17328 if ((*npolicers > num_pools) || (*npolicers == 0 )) { 17329 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17330 (BSL_META_U(unit, 17331 "Invalid number of Policers \n"))); 17332 return BCM_E_PARAM; 17333 } 17334 *npolicers = 8; /* Numbers of meters in a cascade chain is 8 */ 17335 *direction = GLOBAL_METER_ALLOC_HORIZONTAL; 17336 mode_attr->mode_type_v = cascade_mode; 17337 mode_attr->uncompressed_attr_selectors_v.\ 17338 uncompressed_attr_bits_selector = 17339 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS; 17340 if (mapping == NULL) { 17341 rv = _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool( 17342 unit, 0, *npolicers, 0, 17343 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17344 } else { 17345 for (i = 0; i < mapping->count; i++) { 17346 table_offset[i] = i; 17347 value[i] = *val; 17348 val++; 17349 } 17350 rv = _bcm_esw_policer_set_offset_table_map_flex_pool( 17351 unit, 0, *npolicers, &value[0] , 17352 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17353 } 17354 17355 BCM_IF_ERROR_RETURN(rv); 17356 break; 17357 } 17358 17359 /* ******************************************** */ 17360 /* A set of n policers based on user input */ 17361 /* ******************************************** */ 17362 case bcmPolicerGroupModeCascadeWithCoupling: 17363 { 17364 if ((*npolicers > 0 ) && 17365 ((*npolicers * 2) <= num_pools)) { 17366 *direction = GLOBAL_METER_ALLOC_HORIZONTAL; 17367 *npolicers = 8; /* Allocate all the 8 policers */ 17368 } else { 17369 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17370 (BSL_META_U(unit, 17371 "Invalid number of Policers \n"))); 17372 return BCM_E_PARAM; 17373 } 17374 mode_attr->mode_type_v = cascade_mode; 17375 mode_attr->uncompressed_attr_selectors_v.\ 17376 uncompressed_attr_bits_selector = 17377 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS; 17378 if (mapping == NULL) { 17379 rv = _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool( 17380 unit, 1, *npolicers/2, 0, 17381 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17382 } else { 17383 for (i = 0; i < mapping->count; i++) { 17384 table_offset[i] = i; 17385 value[i] = *val; 17386 val++; 17387 } 17388 rv = _bcm_esw_policer_set_offset_table_map_flex_pool( 17389 unit, 1, *npolicers/2, &value[0] , 17390 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17391 } 17392 17393 BCM_IF_ERROR_RETURN(rv); 17394 break; 17395 } 17396 /* ******************************************** */ 17397 /* A set of n policers based on user input */ 17398 /* ******************************************** */ 17399 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 17400 { 17401 if ((*npolicers > 0 ) && 17402 ((*npolicers * 2) <= num_pools)) { 17403 *direction = GLOBAL_METER_ALLOC_HORIZONTAL; 17404 *npolicers = 8; 17405 } else { 17406 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17407 (BSL_META_U(unit, 17408 "Invalid number of Policers \n"))); 17409 return BCM_E_PARAM; 17410 } 17411 mode_attr->mode_type_v = cascade_mode; 17412 mode_attr->uncompressed_attr_selectors_v.\ 17413 uncompressed_attr_bits_selector = 17414 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SHORT_INT_PRI_ATTR_BITS; 17415 if (mapping == NULL) { 17416 rv = _bcm_esw_policer_set_offset_table_map_to_a_value_with_pool( 17417 unit, 1, *npolicers/2, 0, 17418 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17419 } else { 17420 for (i = 0; i < mapping->count; i++) { 17421 table_offset[i] = i; 17422 value[i] = *val; 17423 val++; 17424 } 17425 rv = _bcm_esw_policer_set_offset_table_map_flex_pool( 17426 unit, 1, *npolicers/2, &value[0] , 17427 &mode_attr->uncompressed_attr_selectors_v.offset_map[0]); 17428 } 17429 17430 BCM_IF_ERROR_RETURN(rv); 17431 break; 17432 } 17433 17434 /* ************************************************************** */ 17435 /* N+1 policers where in the base counter is used for dlf and next N */ 17436 /* are used as per Cos */ 17437 /* 1) L2_DLF(UNKNOWN_L2UC_PKT) */ 17438 /* 2..17) INT_PRI bits: 4bits */ 17439 /* ************************************************************** */ 17440 case bcmPolicerGroupModeDlfIntPri: 17441 { 17442 *npolicers = 17; 17443 mode_attr->mode_type_v = compressed_mode; 17444 pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v; 17445 pkt_attr->pkt_resolution = 1; 17446 pkt_attr->int_pri = 4; 17447 17448 /* Reset pkt_resolution map */ 17449 pkt_res_map = &mode_attr->compressed_attr_selectors_v.\ 17450 compressed_pkt_res_attr_map_v[0]; 17451 index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm); 17452 for (map_index = 0; map_index <= index_max; map_index++) { 17453 pkt_res_map[map_index] = 0; 17454 } 17455 /* set pkt_resoltion map for DLF to 1. 17456 * PKT_RES_MAPm == [ pkt_res | svp_type | drop ] 17457 * So, Don't care for bits corresponding to svp_type and drop */ 17458 shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1; 17459 no_entries_to_populate = (1 << shift_bits); 17460 17461 for (offset = 0; offset < no_entries_to_populate; offset++) { 17462 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + \ 17463 offset] = 1 << shift_bits; 17464 } 17465 /* Reset pri_cnf map */ 17466 pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\ 17467 compressed_pri_cnf_attr_map_v[0]; 17468 index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm); 17469 for (map_index = 0; map_index <= index_max; map_index++) { 17470 pri_cnf_map[map_index] = 0; 17471 } 17472 /* set pri_cnf map for 16 policers */ 17473 for (offset = 0; offset < 4; offset++) { 17474 for (map_index = 0; map_index < 16; map_index++) { 17475 pri_cnf_map[offset << 4 | map_index] = map_index; 17476 } 17477 } 17478 17479 /* Reset all Offset table fields */ 17480 offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0]; 17481 for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256; 17482 map_index++) { 17483 offset_map[map_index].offset = 0; 17484 offset_map[map_index].meter_enable = 0; 17485 } 17486 /* Set DLF policer indexes considering INT_PRI bits don't care */ 17487 for(map_index = 0; map_index < 16; map_index++) { 17488 offset_map[(map_index << 1) | 1].offset = 0; 17489 offset_map[(map_index << 1) | 1].meter_enable = 1; 17490 } 17491 /* Set Int pri policer indexes considering DLF=0 */ 17492 for(map_index = 0; map_index < 16; map_index++) { 17493 offset_map[map_index << 1].offset = map_index + 1; 17494 offset_map[map_index << 1].meter_enable = 1; 17495 } 17496 break; 17497 } 17498 /* *************************************************************** */ 17499 /* A dedicated policer for unknown unicast, known unicast, */ 17500 /* multicast,broadcast and N internal priority policers for traffic*/ 17501 /* (not already policed) */ 17502 /* 1) UNKNOWN_L3UC_PKT */ 17503 /* 2) KNOWN_L2UC_PKT | KNOWN_L3UC_PKT */ 17504 /* 3) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 17505 /* 4) L2BC_PKT */ 17506 /* 5..20) INT_PRI bits: 4bits */ 17507 /* *************************************************************** */ 17508 case bcmPolicerGroupModeTypedIntPri: 17509 { 17510 *npolicers = 20; 17511 mode_attr->mode_type_v = compressed_mode; 17512 pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v; 17513 pkt_attr->pkt_resolution = 3; 17514 pkt_attr->int_pri = 4; 17515 /* Reset pkt_resolution map */ 17516 pkt_res_map = &mode_attr->compressed_attr_selectors_v.\ 17517 compressed_pkt_res_attr_map_v[0]; 17518 index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm); 17519 for (map_index = 0; map_index <= index_max; map_index++) { 17520 pkt_res_map[map_index] = 0; 17521 } 17522 /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ] 17523 * So, Don't care for bits corresponding to svp_type and drop */ 17524 shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1; 17525 no_entries_to_populate = (1 << shift_bits); 17526 17527 for (offset = 0; offset < no_entries_to_populate; offset++) { 17528 pkt_res_map[(pkt_res[UNKNOWN_L3UC_PKT] << shift_bits) + offset] 17529 = 1 << shift_bits; 17530 pkt_res_map[(pkt_res[KNOWN_L2UC_PKT] << shift_bits) + offset] 17531 = 2 << shift_bits; 17532 pkt_res_map[(pkt_res[KNOWN_L3UC_PKT] << shift_bits) + offset] 17533 = 2 << shift_bits; 17534 pkt_res_map[(pkt_res[KNOWN_L2MC_PKT] << shift_bits) + offset] 17535 = 3 << shift_bits; 17536 pkt_res_map[(pkt_res[UNKNOWN_L2MC_PKT] << shift_bits) + offset] 17537 = 3 << shift_bits; 17538 pkt_res_map[(pkt_res[L2BC_PKT] << shift_bits) + offset] 17539 = 4 << shift_bits; 17540 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + offset] 17541 = 1 << shift_bits; 17542 } 17543 /* Reset pri_cng map */ 17544 pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\ 17545 compressed_pri_cnf_attr_map_v[0]; 17546 index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm); 17547 for (map_index = 0; map_index <= index_max; map_index++) { 17548 pri_cnf_map[map_index] = 0; 17549 } 17550 /* set pri_cnf map for 16 policers */ 17551 for (map_index = 0; map_index < 16; map_index++) { 17552 pri_cnf_map[map_index] = map_index; 17553 } 17554 17555 /* Reset all Offset table fields */ 17556 offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0]; 17557 for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256; 17558 map_index++) { 17559 offset_map[map_index].offset = 0; 17560 offset_map[map_index].meter_enable = 0; 17561 } 17562 /* Set Int pri policer indexes considering Type fields = 0 */ 17563 for(map_index = 0; map_index < 16; map_index++) { 17564 for(type = 0; type < 8; type++) { 17565 offset_map[type + (8 * map_index)].offset = map_index + 4; 17566 offset_map[type + (8 * map_index)].meter_enable = 1; 17567 } 17568 } 17569 /* Set Type based indexes considering INT_PRI bits don't care */ 17570 for(type = 0; type < 4; type++) { 17571 for(map_index = 0; map_index < 16; map_index++) { 17572 offset_map[(map_index << 3) | (type + 1)].offset = type; 17573 offset_map[(map_index << 3) | (type + 1)].meter_enable = 1; 17574 } 17575 } 17576 break; 17577 } 17578 /* ************************************************************* */ 17579 /* N+2 policers where the base policers is used for control, the */ 17580 /* next one for dlf and next N are used per Cos */ 17581 /* 1) CONTROL_PKT|BPDU_PKT */ 17582 /* 2) L2_DLF */ 17583 /* 3..18) INT_PRI bits: 4bits */ 17584 /* ************************************************************* */ 17585 case bcmPolicerGroupModeDlfIntPriWithControl: 17586 { 17587 *npolicers = 18; 17588 mode_attr->mode_type_v = compressed_mode; 17589 pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v; 17590 pkt_attr->pkt_resolution = 2; 17591 pkt_attr->int_pri = 4; 17592 /* Reset pkt_resolution map */ 17593 pkt_res_map = &mode_attr->compressed_attr_selectors_v.\ 17594 compressed_pkt_res_attr_map_v[0]; 17595 index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm); 17596 for (map_index = 0; map_index <= index_max; map_index++) { 17597 pkt_res_map[map_index] = 0; 17598 } 17599 /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ] 17600 * So, Don't care for bits corresponding to svp_type and drop */ 17601 shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1; 17602 no_entries_to_populate = (1 << shift_bits); 17603 17604 /* set pkt_resolution map */ 17605 for (offset = 0; offset < no_entries_to_populate; offset++) { 17606 pkt_res_map[(pkt_res[CONTROL_PKT] << shift_bits) + offset] 17607 = 1 << shift_bits; 17608 pkt_res_map[(pkt_res[BPDU_PKT] << shift_bits) + offset] 17609 = 1 << shift_bits; 17610 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits) + offset] 17611 = 2 << shift_bits; 17612 } 17613 /* Reset pri_cng map */ 17614 pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\ 17615 compressed_pri_cnf_attr_map_v[0]; 17616 index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm); 17617 for (map_index = 0; map_index <= index_max; map_index++) { 17618 pri_cnf_map[map_index] = 0; 17619 } 17620 /* set pri_cnf map for 16 policers */ 17621 for (map_index = 0; map_index < 16; map_index++) { 17622 pri_cnf_map[map_index] = map_index; 17623 } 17624 17625 /* Reset all Offset table fields */ 17626 offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0]; 17627 for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256; 17628 map_index++) { 17629 offset_map[map_index].offset = 0; 17630 offset_map[map_index].meter_enable = 0; 17631 } 17632 /* Set Int pri policer indexes considering Type fields = 0 */ 17633 for(map_index = 0; map_index < 16; map_index++) { 17634 for(type = 0; type < 4; type++) { 17635 offset_map[type + (4 * map_index)].offset = map_index + 2; 17636 offset_map[type + (4 * map_index)].meter_enable = 1; 17637 } 17638 } 17639 /* Set Type based indexes considering INT_PRI bits don't care */ 17640 for(type = 0; type < 2; type++) { 17641 for(map_index = 0; map_index < 16; map_index++) { 17642 offset_map[(map_index << 2) | (type + 1)].offset = type; 17643 offset_map[(map_index << 2) | (type + 1)].meter_enable = 1; 17644 } 17645 } 17646 break; 17647 } 17648 /* *************************************************************** */ 17649 /* A dedicated counter for control, unknown unicast, known unicast */ 17650 /* , multicast, broadcast and N internal priority counters for */ 17651 /* traffic (not already counted) */ 17652 /* 1) CONTROL_PKT|BPDU_PKT */ 17653 /* 2) UNKNOWN_L3UC_PKT */ 17654 /* 3) L2UC_PKT | KNOWN_L3UC_PKT */ 17655 /* 4) KNOWN_L2MC_PKT|UNKNOWN_L2MC_PKT */ 17656 /* 5) L2BC_PKT */ 17657 /* 6..21) INT_PRI bits: 4bits */ 17658 /* *************************************************************** */ 17659 case bcmPolicerGroupModeTypedIntPriWithControl: 17660 { 17661 *npolicers = 21; 17662 mode_attr->mode_type_v = compressed_mode; 17663 pkt_attr = &mode_attr->compressed_attr_selectors_v.pkt_attr_bits_v; 17664 pkt_attr->pkt_resolution = 3; 17665 pkt_attr->int_pri = 4; 17666 /* Reset pkt_resolution map */ 17667 pkt_res_map = &mode_attr->compressed_attr_selectors_v.\ 17668 compressed_pkt_res_attr_map_v[0]; 17669 index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm); 17670 for (map_index = 0; map_index <= index_max; map_index++) { 17671 pkt_res_map[map_index] = 0; 17672 } 17673 /* PKT_RES_MAPm == [ pkt_res | svp_type | drop ] 17674 * So, Don't care for bits corresponding to svp_type and drop */ 17675 shift_bits = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size + 1; 17676 no_entries_to_populate = (1 << shift_bits); 17677 17678 /* set pkt_resolution map */ 17679 for (offset = 0; offset < no_entries_to_populate; offset++) { 17680 pkt_res_map[(pkt_res[CONTROL_PKT] << shift_bits) + offset] 17681 = 1 << shift_bits; 17682 pkt_res_map[(pkt_res[BPDU_PKT] << shift_bits) + offset] 17683 = 1 << shift_bits; 17684 pkt_res_map[(pkt_res[UNKNOWN_L3UC_PKT] << shift_bits)+ offset] 17685 = 2 << shift_bits; 17686 pkt_res_map[(pkt_res[KNOWN_L2UC_PKT] << shift_bits) + offset] 17687 = 3 << shift_bits; 17688 pkt_res_map[(pkt_res[KNOWN_L3UC_PKT] << shift_bits) + offset] 17689 = 3 << shift_bits; 17690 pkt_res_map[(pkt_res[KNOWN_L2MC_PKT] << shift_bits) + offset] 17691 = 4 << shift_bits; 17692 pkt_res_map[(pkt_res[UNKNOWN_L2MC_PKT] << shift_bits) + offset] 17693 = 4 << shift_bits; 17694 pkt_res_map[(pkt_res[L2BC_PKT] << shift_bits) + offset] 17695 = 5 << shift_bits; 17696 pkt_res_map[(pkt_res[UNKNOWN_L2UC_PKT] << shift_bits)+ offset] 17697 = 2 << shift_bits; 17698 } 17699 /* Reset pri_cnf map */ 17700 pri_cnf_map = &mode_attr->compressed_attr_selectors_v.\ 17701 compressed_pri_cnf_attr_map_v[0]; 17702 index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm); 17703 for (map_index = 0; map_index <= index_max; map_index++) { 17704 pri_cnf_map[map_index] = 0; 17705 } 17706 /* set pri_cnf map for 16 policers */ 17707 for (map_index = 0; map_index < 16; map_index++) { 17708 pri_cnf_map[map_index] = map_index; 17709 } 17710 17711 /* Reset all Offset table fields */ 17712 offset_map = &mode_attr->compressed_attr_selectors_v.offset_map[0]; 17713 for (map_index = 0; map_index < BCM_SVC_METER_MAP_SIZE_256; 17714 map_index++) { 17715 offset_map[map_index].offset = 0; 17716 offset_map[map_index].meter_enable = 0; 17717 } 17718 /* Set Int pri policer indexes considering Type fields = 0 */ 17719 for(map_index = 0; map_index < 16; map_index++) { 17720 for(type = 0; type < 8; type++) { 17721 offset_map[type + (8 * map_index)].offset = map_index + 5; 17722 offset_map[type + (8 * map_index)].meter_enable = 1; 17723 } 17724 } 17725 /* Set Type based indexes considering INT_PRI bits don't care */ 17726 for(type = 0; type < 5; type++) { 17727 for(map_index = 0; map_index < 16; map_index++) { 17728 offset_map[(map_index << 3) | (type + 1)].offset = type; 17729 offset_map[(map_index << 3) | (type + 1)].meter_enable = 1; 17730 } 17731 } 17732 break; 17733 } 17734 17735 default: 17736 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17737 (BSL_META_U(unit, 17738 "Invalid policer group mode\n"))); 17739 return BCM_E_PARAM; 17740 17741 } 17742 return rv; 17743 } 17744 17745 /* 17746 * Function: 17747 * _bcm_esw_policer_group_create 17748 * Purpose: 17749 * Create a group of policers based on the mode. 17750 * Parameters: 17751 * unit - (IN) unit number 17752 * mode - (IN) Policer group mode 17753 * flow_info - (IN) Information regarding flow type and skip pool 17754 * offset_map - (IN) Attr_value to policer_offset mapping 17755 * policer_id - (OUT) Base policer id 17756 * npolicers - (OUT) Number of policers 17757 * Returns: 17758 * BCM_E_XXX 17759 */ 17760 int _bcm_esw_policer_group_create(int unit, bcm_policer_group_mode_t mode, 17761 _bcm_policer_flow_info_t *flow_info, 17762 bcm_policer_map_t *offset_map, 17763 bcm_policer_t *policer_id, int *npolicers) 17764 { 17765 int rv = BCM_E_NONE; 17766 uint32 direction = 0; 17767 int index = 0; 17768 bcm_policer_svc_meter_mode_t offset_mode = 0; 17769 uint8 pid_offset[BCM_POLICER_GLOBAL_METER_MAX_POOL] = {0}; 17770 _global_meter_policer_control_t *policer_control = NULL; 17771 bcm_policer_svc_meter_attr_t *mode_attr = NULL; 17772 int offset_mask = 0; 17773 17774 if (!soc_feature(unit, soc_feature_global_meter)) { 17775 return BCM_E_UNAVAIL; 17776 } 17777 if (soc_feature(unit, soc_feature_global_meter_compaction_support)) { 17778 return BCM_E_UNAVAIL; 17779 } 17780 17781 mode_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t),"meter mode attr"); 17782 if ( mode_attr == NULL) { 17783 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17784 (BSL_META_U(unit, 17785 "Failed to allocate memory for svc meter attr \n"))); 17786 return BCM_E_MEMORY; 17787 } 17788 sal_memset(mode_attr, 0, sizeof(bcm_policer_svc_meter_attr_t)); 17789 17790 direction = GLOBAL_METER_ALLOC_VERTICAL; 17791 17792 rv = _bcm_esw_policer_group_set_mode_and_map(unit, mode, npolicers, offset_map, 17793 &direction, mode_attr); 17794 if (!(BCM_SUCCESS(rv))) { 17795 sal_free(mode_attr); 17796 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17797 (BSL_META_U(unit, 17798 "Failed to set mode and map\n"))); 17799 return rv; 17800 } 17801 17802 GLOBAL_METER_LOCK(unit); 17803 17804 if (((direction == GLOBAL_METER_ALLOC_VERTICAL) && (*npolicers > 1)) || 17805 ((direction == GLOBAL_METER_ALLOC_HORIZONTAL))) { 17806 rv = _bcm_esw_policer_svc_meter_create_mode(unit, mode_attr, mode, 17807 -1, *npolicers, NULL, &offset_mode); 17808 if (BCM_FAILURE(rv) && (rv != BCM_E_EXISTS)) { 17809 GLOBAL_METER_UNLOCK(unit); 17810 sal_free(mode_attr); 17811 return rv; 17812 } else { 17813 global_meter_offset_mode[unit][offset_mode].no_of_policers = 17814 *npolicers; 17815 } 17816 } 17817 sal_free(mode_attr); 17818 rv = _global_meter_policer_id_alloc(unit, direction, npolicers, 17819 policer_id, flow_info, &pid_offset[0]); 17820 if (!(BCM_SUCCESS(rv))) { 17821 GLOBAL_METER_UNLOCK(unit); 17822 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17823 (BSL_META_U(unit, 17824 "Failed to allocate policer\n"))); 17825 return rv; 17826 } 17827 offset_mask = SOC_INFO(unit).global_meter_max_size_of_pool - 1; 17828 17829 /* Allocate policer descriptor. */ 17830 _GLOBAL_METER_XGS3_ALLOC(policer_control, 17831 sizeof (_global_meter_policer_control_t), "Global meter policer"); 17832 if (NULL == policer_control) { 17833 _bcm_global_meter_free_allocated_policer_on_error(unit, *npolicers, 17834 &pid_offset[0], (*policer_id & offset_mask)); 17835 GLOBAL_METER_UNLOCK(unit); 17836 LOG_VERBOSE(BSL_LS_BCM_POLICER, 17837 (BSL_META_U(unit, 17838 "Unable to allocate memeory for policer control \n"))); 17839 return (BCM_E_MEMORY); 17840 } 17841 17842 /* Add mode info to the policer index */ 17843 *policer_id |= (offset_mode + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT; 17844 17845 /* Set policer configuration */ 17846 policer_control->direction = direction; 17847 policer_control->pid = *policer_id; 17848 policer_control->grp_mode = mode; 17849 policer_control->no_of_policers = *npolicers; 17850 17851 if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 17852 index = 0; 17853 do { 17854 policer_control->offset[index] = pid_offset[index]; 17855 index++; 17856 } while (index < (*npolicers)); 17857 17858 if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 17859 rv = _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw(unit, 17860 *npolicers, *policer_id, mode, &pid_offset[0]); 17861 } else { 17862 rv = _bcm_esw_global_meter_set_cascade_info_to_hw(unit, 17863 *npolicers, *policer_id, mode, &pid_offset[0]); 17864 } 17865 if (!(BCM_SUCCESS(rv))) { 17866 /* free all the allocated policers */ 17867 _bcm_global_meter_free_allocated_policer_on_error(unit, *npolicers, 17868 &pid_offset[0], (*policer_id & offset_mask)); 17869 /* De-allocate policer descriptor. */ 17870 sal_free(policer_control); 17871 GLOBAL_METER_UNLOCK(unit); 17872 return rv; 17873 } 17874 } 17875 if ((mode == bcmPolicerGroupModeCascadeWithCoupling) || 17876 (mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 17877 *npolicers = *npolicers / 2; 17878 } 17879 /* increment mode reference count for new policer */ 17880 if (offset_mode) { 17881 rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, offset_mode); 17882 if (!(BCM_SUCCESS(rv))) { 17883 /* free all the allocated policers */ 17884 _bcm_global_meter_free_allocated_policer_on_error(unit,*npolicers, 17885 &pid_offset[0], (*policer_id & offset_mask)); 17886 /* De-allocate policer descriptor. */ 17887 sal_free(policer_control); 17888 GLOBAL_METER_UNLOCK(unit); 17889 return rv; 17890 } 17891 } 17892 17893 17894 /* Insert policer into policers hash. */ 17895 _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit], 17896 policer_control, 17897 (*policer_id & _GLOBAL_METER_HASH_MASK)); 17898 17899 GLOBAL_METER_UNLOCK(unit); 17900 LOG_DEBUG(BSL_LS_BCM_POLICER, 17901 (BSL_META_U(unit, 17902 "create policer with id %x\n"), 17903 *policer_id)); 17904 17905 return rv; 17906 } 17907 17908 /* 17909 * Function: 17910 * bcm_esw_policer_envelop_create 17911 * Purpose: 17912 * Create a single policer in Envelop mode. The policer created is 17913 * micro or a macro meter depending on the configuration. 17914 * Parameters: 17915 * unit - (IN) unit number 17916 * flags - (IN) Indicates micro/macro flow policer 17917 * macro_flow_policer_id - (IN) macro flow policer id 17918 * policer_id - (OUT) policer Id 17919 * Returns: 17920 * BCM_E_XXX 17921 */ 17922 int bcm_esw_policer_envelop_create(int unit, uint32 flags, 17923 bcm_policer_t macro_flow_policer_id, 17924 bcm_policer_t *policer_id) 17925 { 17926 int rv = BCM_E_NONE; 17927 int index = 0; 17928 int micro_flow_index = 0; 17929 int pool = 0; 17930 int numbers = 1; 17931 svm_macroflow_index_table_entry_t macro_flow_entry; 17932 int size_pool = 0, num_pools = 0; 17933 int pool_mask = 0, pool_offset = 0; 17934 _bcm_policer_flow_info_t flow_info; 17935 int bank_size = 0, num_banks_per_pool = 1; 17936 17937 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 17938 if (soc_feature(unit, soc_feature_global_meter_v2)) { 17939 return bcmi_esw_policer_envelop_create(unit, 17940 flags, macro_flow_policer_id, policer_id); 17941 } 17942 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 17943 17944 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 17945 num_pools = SOC_INFO(unit).global_meter_pools; 17946 pool_offset = _shr_popcount(size_pool - 1); 17947 pool_mask = (num_pools - 1) << pool_offset; 17948 num_banks_per_pool = get_max_banks_in_a_pool(unit); 17949 bank_size = size_pool / num_banks_per_pool; 17950 17951 _bcm_policer_flow_info_t_init(&flow_info); 17952 if (flags == BCM_POLICER_GLOBAL_METER_ENVELOP_MACRO_FLOW) { 17953 flow_info.flow_type = bcmPolicerFlowTypeMacro; 17954 rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle, 17955 &flow_info, NULL, policer_id, &numbers); 17956 if (!(BCM_SUCCESS(rv))) { 17957 LOG_DEBUG(BSL_LS_BCM_POLICER, 17958 (BSL_META_U(unit, 17959 "Unable to create macro flow policer\n"))); 17960 return rv; 17961 } 17962 } else if (flags == BCM_POLICER_GLOBAL_METER_ENVELOP_MICRO_FLOW) { 17963 /* validate macroflow policer id */ 17964 rv = _bcm_esw_policer_validate(unit, ¯o_flow_policer_id); 17965 if (!(BCM_SUCCESS(rv))) { 17966 LOG_DEBUG(BSL_LS_BCM_POLICER, 17967 (BSL_META_U(unit, 17968 "Invalid policer Id passed\n"))); 17969 return rv; 17970 } 17971 rv = _bcm_esw_get_policer_table_index(unit, macro_flow_policer_id, 17972 &index); 17973 if (!(BCM_SUCCESS(rv))) { 17974 LOG_DEBUG(BSL_LS_BCM_POLICER, 17975 (BSL_META_U(unit, 17976 "Unable to Get policer index for macro flow " 17977 "policer \n"))); 17978 return rv; 17979 } 17980 pool = (macro_flow_policer_id & pool_mask) >> pool_offset; 17981 flow_info.flow_type = bcmPolicerFlowTypeMicro; 17982 flow_info.skip_pool = pool; 17983 flow_info.skip_bank = (macro_flow_policer_id & (size_pool - 1)) / bank_size; 17984 rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle, &flow_info, 17985 NULL, policer_id, &numbers); 17986 if (!(BCM_SUCCESS(rv))) { 17987 LOG_DEBUG(BSL_LS_BCM_POLICER, 17988 (BSL_META_U(unit, 17989 "Unable to create micro flow policer\n"))); 17990 return rv; 17991 } 17992 rv = _bcm_esw_policer_increment_ref_count(unit, macro_flow_policer_id); 17993 if (!(BCM_SUCCESS(rv))) { 17994 LOG_DEBUG(BSL_LS_BCM_POLICER, 17995 (BSL_META_U(unit, 17996 "Unable to increment ref count for micro flow " 17997 "policer\n"))); 17998 return rv; 17999 } 18000 /* get the HW index for the micro flow policer created */ 18001 rv = _bcm_esw_get_policer_table_index(unit, *policer_id, 18002 µ_flow_index); 18003 if (!(BCM_SUCCESS(rv))) { 18004 LOG_DEBUG(BSL_LS_BCM_POLICER, 18005 (BSL_META_U(unit, 18006 "Unable to Get policer index for micro flow " 18007 "policer \n"))); 18008 return rv; 18009 } 18010 /* Write the index of the macro-meter at "micro_flow_index" location 18011 of SVM_MACROFLOW_INDEX_TABLE */ 18012 rv = READ_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 18013 micro_flow_index, ¯o_flow_entry); 18014 if (!(BCM_SUCCESS(rv))) { 18015 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18016 (BSL_META_U(unit, 18017 "Unable to access macro flow table at the index " 18018 "provided\n"))); 18019 return rv; 18020 } 18021 if (SOC_MEM_FIELD_VALID(unit, SVM_MACROFLOW_INDEX_TABLEm, 18022 MACROFLOW_INDEXf)) { 18023 soc_SVM_MACROFLOW_INDEX_TABLEm_field_set(unit, ¯o_flow_entry, 18024 MACROFLOW_INDEXf, (uint32 *)&index); 18025 } 18026 rv = WRITE_SVM_MACROFLOW_INDEX_TABLEm(unit, MEM_BLOCK_ANY, 18027 micro_flow_index, ¯o_flow_entry); 18028 if (!(BCM_SUCCESS(rv))) { 18029 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18030 (BSL_META_U(unit, 18031 "Unable to write to macro flow table at index " 18032 "provided\n"))); 18033 return rv; 18034 } 18035 } else { 18036 LOG_ERROR(BSL_LS_BCM_POLICER, 18037 (BSL_META_U(unit, 18038 "Invalid flag passed \n"))); 18039 return BCM_E_PARAM; 18040 } 18041 return rv; 18042 } 18043 18044 /* 18045 * Function: 18046 * bcm_esw_policer_group_create 18047 * Purpose: 18048 * Create a group of policers based on the mode. 18049 * Parameters: 18050 * unit - (IN) unit number 18051 * mode - (IN) policer group mode 18052 * policer_id - (OUT)Base policer Id 18053 * npolicers - (OUT) Number of policers created 18054 * Returns: 18055 * BCM_E_XXX 18056 */ 18057 int bcm_esw_policer_group_create(int unit, bcm_policer_group_mode_t mode, 18058 bcm_policer_t *policer_id, int *npolicers) 18059 { 18060 int rv = BCM_E_NONE; 18061 int num_pools = 0; 18062 _bcm_policer_flow_info_t flow_info; 18063 num_pools = SOC_INFO(unit).global_meter_pools; 18064 18065 _bcm_policer_flow_info_t_init(&flow_info); 18066 flow_info.flow_type = bcmPolicerFlowTypeNormal; 18067 flow_info.skip_pool = num_pools; 18068 18069 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 18070 if (soc_feature(unit, soc_feature_global_meter_v2)) { 18071 rv = bcmi_esw_policer_group_create(unit, mode, &flow_info, NULL, 18072 policer_id, npolicers); 18073 } else 18074 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 18075 { 18076 rv = _bcm_esw_policer_group_create(unit, mode, &flow_info, NULL, 18077 policer_id, npolicers); 18078 } 18079 if (BCM_FAILURE(rv)) { 18080 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18081 (BSL_META_U(unit, 18082 "Unable to create policer with " 18083 "given mode(%d)\n"), 18084 mode)); 18085 return (rv); 18086 } 18087 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18088 (BSL_META_U(unit, 18089 "Created policer group of %d with base policer %x \n"), 18090 *npolicers, *policer_id)); 18091 return rv; 18092 } 18093 18094 /* 18095 * Function: 18096 * bcm_esw_policer_group_create 18097 * Purpose: 18098 * Create a group of policers based on the mode. 18099 * Parameters: 18100 * unit - (IN) unit number 18101 * mode - (IN) policer group mode 18102 * policer_id - (OUT)Base policer Id 18103 * npolicers - (OUT) Number of policers created 18104 * Returns: 18105 * BCM_E_XXX 18106 */ 18107 int bcm_esw_policer_group_create_with_map(int unit, 18108 bcm_policer_group_mode_t mode, 18109 bcm_policer_map_t *offset_map, 18110 bcm_policer_t *policer_id, 18111 int *num_policers) 18112 { 18113 int rv = BCM_E_NONE; 18114 int num_pools = 0; 18115 _bcm_policer_flow_info_t flow_info; 18116 num_pools = SOC_INFO(unit).global_meter_pools; 18117 18118 _bcm_policer_flow_info_t_init(&flow_info); 18119 flow_info.flow_type = bcmPolicerFlowTypeNormal; 18120 flow_info.skip_pool = num_pools; 18121 18122 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 18123 if (soc_feature(unit, soc_feature_global_meter_v2)) { 18124 rv = bcmi_esw_policer_group_create(unit, mode, &flow_info, offset_map, 18125 policer_id, num_policers); 18126 } else 18127 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 18128 { 18129 rv = _bcm_esw_policer_group_create(unit, mode, &flow_info, offset_map, 18130 policer_id, num_policers); 18131 } 18132 18133 if (BCM_FAILURE(rv)) { 18134 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18135 (BSL_META_U(unit, 18136 "Unable to create policer for given mode %d \n"), 18137 mode)); 18138 return (rv); 18139 } 18140 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18141 (BSL_META_U(unit, 18142 "Created policer group of %d with base policer %x \n"), 18143 *num_policers, *policer_id)); 18144 return rv; 18145 } 18146 18147 /* 18148 * Function: 18149 * bcm_esw_policer_envelop_group_create 18150 * Purpose: 18151 * Create a group of policers based on the mode. 18152 * Parameters: 18153 * unit - (IN) unit number 18154 * flags - (IN) Indicates micro/macro flow policer 18155 * mode - (IN) policer group mode 18156 * macro_flow_policer_id - (IN) macro flow policer id 18157 * policer_id - (OUT)Base policer Id 18158 * npolicers - (OUT) Number of policers created 18159 * Returns: 18160 * BCM_E_XXX 18161 */ 18162 int bcm_esw_policer_envelop_group_create(int unit, uint32 flag, 18163 bcm_policer_group_mode_t mode, 18164 bcm_policer_t macro_flow_policer_id, 18165 bcm_policer_t *policer_id, 18166 int *npolicers) 18167 { 18168 int rv = BCM_E_NONE; 18169 int index = 0; 18170 int micro_flow_index = 0; 18171 int pool = 0; 18172 int numbers = 1; 18173 int size_pool = 0, num_pools = 0; 18174 int pool_mask = 0, pool_offset = 0; 18175 svm_macroflow_index_table_entry_t *buf; 18176 svm_macroflow_index_table_entry_t *entry; 18177 int entry_mem_size; /* Size of table entry. */ 18178 int entry_index = 0; 18179 int entry_index_max = 0; 18180 _bcm_policer_flow_info_t flow_info; 18181 int bank_size, num_banks_per_pool = 1; 18182 18183 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 18184 if (soc_feature(unit, soc_feature_global_meter_v2)) { 18185 return bcmi_esw_policer_envelop_group_create(unit, 18186 flag, mode, macro_flow_policer_id, policer_id, npolicers); 18187 } 18188 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 18189 18190 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 18191 num_pools = SOC_INFO(unit).global_meter_pools; 18192 pool_offset = _shr_popcount(size_pool - 1); 18193 pool_mask = (num_pools - 1) << pool_offset; 18194 num_banks_per_pool = get_max_banks_in_a_pool(unit); 18195 bank_size = size_pool / num_banks_per_pool; 18196 _bcm_policer_flow_info_t_init(&flow_info); 18197 18198 if (flag == BCM_POLICER_GLOBAL_METER_ENVELOP_MACRO_FLOW) { 18199 flow_info.flow_type = bcmPolicerFlowTypeMacro; 18200 flow_info.skip_pool = num_pools; 18201 rv = _bcm_esw_policer_group_create(unit, bcmPolicerGroupModeSingle, 18202 &flow_info, NULL, policer_id, &numbers); 18203 if (!(BCM_SUCCESS(rv))) { 18204 LOG_DEBUG(BSL_LS_BCM_POLICER, 18205 (BSL_META_U(unit, 18206 "Unable to create macro flow policer\n"))); 18207 return rv; 18208 } 18209 } else if (flag == BCM_POLICER_GLOBAL_METER_ENVELOP_MICRO_FLOW) { 18210 18211 if ((mode == bcmPolicerGroupModeCascade) || 18212 (mode == bcmPolicerGroupModeCascadeWithCoupling) || 18213 (mode == bcmPolicerGroupModeCascadeDroppedPktExclude) || 18214 (mode == bcmPolicerGroupModeIntPriCascade) || 18215 (mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 18216 LOG_ERROR(BSL_LS_BCM_POLICER, 18217 (BSL_META_U(unit, 18218 "Unable to create micro flow policers " 18219 "due to unsupported mode\n"))); 18220 return (BCM_E_PARAM); 18221 } 18222 /* validate macroflow policer id */ 18223 rv = _bcm_esw_policer_validate(unit, ¯o_flow_policer_id); 18224 if (!(BCM_SUCCESS(rv))) { 18225 LOG_DEBUG(BSL_LS_BCM_POLICER, 18226 (BSL_META_U(unit, 18227 "Invalid policer Id passed\n"))); 18228 return rv; 18229 } 18230 rv = _bcm_esw_get_policer_table_index(unit, macro_flow_policer_id, 18231 &index); 18232 if (BCM_FAILURE(rv)) { 18233 LOG_DEBUG(BSL_LS_BCM_POLICER, 18234 (BSL_META_U(unit, 18235 "Unable to Get policer index for macro flow " 18236 "policer \n"))); 18237 return rv; 18238 } 18239 18240 pool = (macro_flow_policer_id & pool_mask) >> pool_offset; 18241 18242 flow_info.flow_type = bcmPolicerFlowTypeMicro; 18243 flow_info.skip_pool = pool; 18244 flow_info.skip_bank = (macro_flow_policer_id & (size_pool - 1)) / bank_size; 18245 rv = _bcm_esw_policer_group_create(unit, mode, &flow_info, 18246 NULL, policer_id, &numbers); 18247 if (BCM_FAILURE(rv)) { 18248 LOG_DEBUG(BSL_LS_BCM_POLICER, 18249 (BSL_META_U(unit, 18250 "Unable to create micro flow policers\n"))); 18251 return rv; 18252 } 18253 /* get the HW index for the micro flow policer created */ 18254 rv = _bcm_esw_get_policer_table_index(unit, *policer_id, 18255 µ_flow_index); 18256 if (BCM_FAILURE(rv)) { 18257 LOG_DEBUG(BSL_LS_BCM_POLICER, 18258 (BSL_META_U(unit, 18259 "Unable to Get policer index for micro flow " 18260 "policer \n"))); 18261 return rv; 18262 } 18263 /* Write the index of the macro-meter at "micro_flow_index" location 18264 of SVM_MACROFLOW_INDEX_TABLE */ 18265 18266 entry_mem_size = sizeof(svm_macroflow_index_table_entry_t); 18267 entry_index_max = micro_flow_index + numbers - 1; 18268 /* Allocate buffer to store the DMAed table entries. */ 18269 buf = soc_cm_salloc(unit, entry_mem_size * numbers, 18270 "svm macro flow index table entry buffer"); 18271 if (NULL == buf) { 18272 return (BCM_E_MEMORY); 18273 } 18274 /* Initialize the entry buffer. */ 18275 sal_memset(buf, 0, sizeof(entry_mem_size) * numbers); 18276 18277 /* Read the table entries into the buffer. */ 18278 rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 18279 MEM_BLOCK_ALL, micro_flow_index, 18280 entry_index_max, buf); 18281 if (BCM_FAILURE(rv)) { 18282 if (buf) { 18283 soc_cm_sfree(unit, buf); 18284 } 18285 return rv; 18286 } 18287 18288 /* Iterate over the table entries. */ 18289 for (entry_index = 0; entry_index < numbers; entry_index++) { 18290 entry = soc_mem_table_idx_to_pointer(unit, 18291 SVM_MACROFLOW_INDEX_TABLEm, 18292 svm_macroflow_index_table_entry_t *, 18293 buf, entry_index); 18294 soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm, 18295 (void *)entry, MACROFLOW_INDEXf, (uint32 *)&index); 18296 rv = _bcm_esw_policer_increment_ref_count(unit, 18297 macro_flow_policer_id); 18298 if (BCM_FAILURE(rv)) { 18299 LOG_DEBUG(BSL_LS_BCM_POLICER, 18300 (BSL_META_U(unit, 18301 "Unable to increment ref count for micro flow " 18302 "policer\n"))); 18303 if (buf) { 18304 soc_cm_sfree(unit, buf); 18305 } 18306 return rv; 18307 } 18308 } 18309 if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 18310 MEM_BLOCK_ALL, micro_flow_index, 18311 entry_index_max, buf)) < 0) { 18312 if (BCM_FAILURE(rv)) { 18313 LOG_VERBOSE(BSL_LS_BCM_POLICER, 18314 (BSL_META_U(unit, 18315 "Unable to write to macro flow table at index " 18316 "provided\n"))); 18317 if (buf) { 18318 soc_cm_sfree(unit, buf); 18319 } 18320 return rv; 18321 } 18322 } 18323 if (buf) { 18324 soc_cm_sfree(unit, buf); 18325 } 18326 } else { 18327 LOG_ERROR(BSL_LS_BCM_POLICER, 18328 (BSL_META_U(unit, 18329 "Invalid flag passed \n"))); 18330 return BCM_E_PARAM; 18331 } 18332 *npolicers = numbers; 18333 return rv; 18334 } 18335 18336 18337 18338 int 18339 _bcm_esw_policer_udf_group_set_offset_map( 18340 int unit, 18341 bcm_policer_group_mode_type_t type, 18342 uint32 npolicers, 18343 uint32 num_selectors, 18344 bcm_policer_group_mode_attr_selector_t *attr_selectors, 18345 bcm_policer_svc_meter_attr_t *mode_attr) 18346 { 18347 int rv = BCM_E_NONE; 18348 int num_pools = 0; 18349 offset_table_entry_t *offset_map = NULL; 18350 int i = 0; 18351 uint32 value[256] = { 0 }; 18352 uint32 table_offset[256] = { 0 }; 18353 num_pools = SOC_INFO(unit).global_meter_pools; 18354 18355 offset_map = &mode_attr->udf_pkt_attr_selectors_v.offset_map[0]; 18356 18357 switch (type) { 18358 case bcmPolicerGroupModeTypeNormal: 18359 for (i = 0; i < num_selectors; i++) { 18360 offset_map[attr_selectors[i].attr_value].offset 18361 = attr_selectors[i].policer_offset; 18362 offset_map[attr_selectors[i].attr_value].meter_enable = 1; 18363 } 18364 break; 18365 18366 case bcmPolicerGroupModeTypeCascade: 18367 for (i = 0; i < num_selectors; i++) { 18368 if (attr_selectors[i].policer_offset >= num_pools) { 18369 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18370 "Invalid policer offset \n"))); 18371 return BCM_E_PARAM; 18372 } 18373 value[i] = attr_selectors[i].policer_offset; 18374 table_offset[i] = attr_selectors[i].attr_value; 18375 } 18376 rv = _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool( 18377 unit, 0, num_selectors, &table_offset[0], 18378 &value[0], offset_map); 18379 BCM_IF_ERROR_RETURN(rv); 18380 break; 18381 18382 case bcmPolicerGroupModeTypeCascadeWithCoupling: 18383 for (i = 0; i < num_selectors; i++) { 18384 if (attr_selectors[i].policer_offset >= num_pools/2) { 18385 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18386 "Invalid policer offset \n"))); 18387 return BCM_E_PARAM; 18388 } 18389 value[i] = attr_selectors[i].policer_offset; 18390 table_offset[i] = attr_selectors[i].attr_value; 18391 } 18392 rv = _bcm_esw_policer_set_offset_table_map_at_offsets_with_flex_pool( 18393 unit, 1, num_selectors, &table_offset[0], 18394 &value[0], offset_map); 18395 BCM_IF_ERROR_RETURN(rv); 18396 break; 18397 18398 default : 18399 rv = BCM_E_PARAM; 18400 18401 } 18402 return rv; 18403 } 18404 18405 /* 18406 * Function: 18407 * _bcm_esw_svc_meter_offset_map_update 18408 * Purpose: 18409 * Update offset map based on attributes 18410 * Parameters: 18411 * unit - (IN) unit number 18412 * attr - (IN/OUT) Offset mode attributes 18413 * offset - (IN) Index in Offset Map 18414 * policer_offset - (IN) value to be updated 18415 * Returns: 18416 * NONE 18417 */ 18418 STATIC int 18419 _bcm_esw_svc_meter_offset_map_update( 18420 uint32 unit, 18421 bcm_policer_svc_meter_attr_t *attr, 18422 bcm_policer_group_mode_t group_mode, 18423 uint32 offset, 18424 uint32 policer_offset) 18425 { 18426 uint8 pool = 0; 18427 uint8 pool_offset_limit = 0; 18428 uint8 dir = 0; 18429 uint8 coupling_offset = 0; 18430 offset_table_entry_t *offset_map_ptr = NULL; 18431 18432 switch (attr->mode_type_v) { 18433 case udf_mode: 18434 case udf_cascade_mode: 18435 case udf_cascade_with_coupling_mode: 18436 offset_map_ptr = 18437 &(attr->udf_pkt_attr_selectors_v.offset_map[0]); 18438 break; 18439 case compressed_mode: 18440 offset_map_ptr = 18441 &(attr->compressed_attr_selectors_v.offset_map[0]); 18442 break; 18443 case uncompressed_mode: 18444 offset_map_ptr = 18445 &(attr->uncompressed_attr_selectors_v.offset_map[0]); 18446 break; 18447 default : 18448 break; 18449 } 18450 if (offset_map_ptr != NULL) { 18451 if (group_mode == bcmPolicerGroupModeSingle) { 18452 if ((offset_map_ptr[offset].meter_enable == 1) && 18453 (offset_map_ptr[offset].offset != policer_offset)) { 18454 LOG_ERROR(BSL_LS_BCM_POLICER, 18455 (BSL_META_U(unit, 18456 "Policer offset(%d) is overwriting policer" 18457 " offset(%d) at index = %d\n"), policer_offset, 18458 offset_map_ptr[offset].offset, offset)); 18459 return BCM_E_CONFIG; 18460 } 18461 offset_map_ptr[offset].offset = policer_offset; 18462 offset_map_ptr[offset].pool = 0; 18463 offset_map_ptr[offset].meter_enable = 1; 18464 } else { 18465 if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 18466 coupling_offset = 0; 18467 } else { 18468 coupling_offset = 18469 (group_mode == bcmPolicerGroupModeCascade) ? 0 : 4; 18470 } 18471 if (soc_feature(unit, 18472 soc_feature_global_meter_pool_priority_descending)) { 18473 pool_offset_limit = (group_mode == bcmPolicerGroupModeCascade) ? 18474 (BCM_POLICER_GLOBAL_METER_MAX_POOL - 1) : 18475 (BCM_POLICER_GLOBAL_METER_MAX_POOL/2 - 1); 18476 dir = -1; 18477 } else { 18478 pool_offset_limit = 0; 18479 dir = 1; 18480 } 18481 pool = pool_offset_limit + dir * policer_offset + coupling_offset; 18482 if ((offset_map_ptr[offset].meter_enable == 1) && 18483 (offset_map_ptr[offset].pool != pool)) { 18484 uint32 curr_pol_offset = 0; 18485 curr_pol_offset = offset_map_ptr[offset].pool; 18486 curr_pol_offset -= (coupling_offset + pool_offset_limit); 18487 curr_pol_offset /= dir; 18488 LOG_ERROR(BSL_LS_BCM_POLICER, 18489 (BSL_META_U(unit, 18490 "Policer offset(%d) is overwriting policer" 18491 " offset(%d) at index = %d\n"), policer_offset, 18492 curr_pol_offset, offset)); 18493 return BCM_E_CONFIG; 18494 } 18495 offset_map_ptr[offset].offset = 0; 18496 offset_map_ptr[offset].pool = pool; 18497 offset_map_ptr[offset].meter_enable = 1; 18498 } 18499 } 18500 return BCM_E_NONE; 18501 } 18502 18503 /* 18504 * Function: 18505 * _bcm_esw_svc_meter_offset_mode_id_check 18506 * Purpose: 18507 * Check if given attribute selectors list is already 18508 * configured or not 18509 * Parameters: 18510 * unit - (IN) unit number 18511 * flags - (IN) flags 18512 * type - (IN) type of group mode 18513 * total_policers - (IN) total policers 18514 * num_selectors - (IN) number of selectors 18515 * attr_selectors - (IN) list of attributes selectors 18516 * mode_id - (OUT) pointer to offset mode index 18517 * Returns: 18518 * BCM_E_XXX 18519 */ 18520 STATIC int 18521 _bcm_esw_svc_meter_offset_mode_id_check( 18522 uint32 unit, 18523 uint32 flags, 18524 bcm_policer_group_mode_type_t type, 18525 uint32 total_policers, 18526 uint32 num_selectors, 18527 bcm_policer_group_mode_attr_selector_t *attr_selectors, 18528 uint32 *mode_id) 18529 { 18530 uint32 index = 0; 18531 int rv = BCM_E_NONE; 18532 int is_same = FALSE; 18533 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 18534 18535 /* Loop through all offset mode index and find match */ 18536 for (index = 1; index < BCM_POLICER_SVC_METER_MAX_MODE; index++) { 18537 if (_bcm_policer_svc_meter_get_mode_info(unit, index, &mode_info) 18538 == BCM_E_NONE) { 18539 if (mode_info.type != type) { 18540 continue; 18541 } 18542 18543 /* check num selectors */ 18544 if (mode_info.no_of_selectors == num_selectors) { 18545 if (mode_info.attr_selectors != NULL) { 18546 rv = _bcm_attr_selectors_wb_attr_selectors_cmp( 18547 num_selectors, attr_selectors, 18548 mode_info.attr_selectors, &is_same); 18549 BCM_IF_ERROR_RETURN(rv); 18550 if (is_same == TRUE) { 18551 /* all the selectors are the same */ 18552 *mode_id = index; 18553 return BCM_E_EXISTS; 18554 } 18555 } 18556 } 18557 } 18558 } 18559 return BCM_E_NONE; 18560 } 18561 18562 /* 18563 * Function: 18564 * _bcm_policer_svc_meter_group_offset_mode_info_update 18565 * Purpose: 18566 * update offset mode info 18567 * Parameters: 18568 * unit - (IN) unit number 18569 * mode - (IN) offset mode index 18570 * num_selectors - (IN) number of selectors 18571 * attr_selectors - (IN) list of attributes selectors 18572 * Returns: 18573 * BCM_E_XXX 18574 */ 18575 int _bcm_policer_svc_meter_group_offset_mode_info_update ( 18576 int unit, 18577 bcm_policer_svc_meter_mode_t mode, 18578 int8 type, 18579 int num_selectors, 18580 bcm_policer_group_mode_attr_selector_t *attr_selectors) 18581 { 18582 int rv = BCM_E_NONE; 18583 18584 if ((num_selectors == 0) || (attr_selectors == NULL)) { 18585 /* Free if allocated */ 18586 if (global_meter_offset_mode[unit][mode].attr_selectors != 18587 NULL) { 18588 sal_free(global_meter_offset_mode[unit][mode].attr_selectors); 18589 } 18590 global_meter_offset_mode[unit][mode].attr_selectors = NULL; 18591 } else { 18592 global_meter_offset_mode[unit][mode].type = type; 18593 global_meter_offset_mode[unit][mode].no_of_selectors = num_selectors; 18594 18595 global_meter_offset_mode[unit][mode].attr_selectors = 18596 sal_alloc(num_selectors * 18597 sizeof(bcm_policer_group_mode_attr_selector_t), 18598 "attr selectors"); 18599 if (NULL == global_meter_offset_mode[unit][mode].attr_selectors) { 18600 return BCM_E_MEMORY; 18601 } 18602 rv = _bcm_attr_selectors_copy_to_wb_attr_selectors( 18603 num_selectors, attr_selectors, 18604 global_meter_offset_mode[unit][mode].attr_selectors); 18605 BCM_IF_ERROR_RETURN(rv); 18606 } 18607 return BCM_E_NONE; 18608 } 18609 18610 /* 18611 * Function: 18612 * _bcm_esw_policer_group_udf_mode_fillup_values 18613 * Purpose: 18614 * Fill up temporary structures in appropriate order for efficient 18615 * management of user input 18616 * Parameters: 18617 * unit - (IN) unit number 18618 * flags - (IN) flags 18619 * type - (IN) type of group mode 18620 * total_policers - (IN) total policers 18621 * num_selectors - (IN) number of selectors 18622 * attr_selectors - (IN) list of attributes selectors 18623 * udf_attr_selectors - (OUT) fill up this structure 18624 * Returns: 18625 * BCM_E_XXX 18626 */ 18627 STATIC int 18628 _bcm_esw_policer_group_udf_mode_fillup_values ( 18629 int unit, 18630 uint32 flags, 18631 bcm_policer_group_mode_type_t type, 18632 uint32 total_policers, 18633 uint32 num_selectors, 18634 bcm_policer_group_mode_attr_selector_t *attr_selectors, 18635 bcm_policer_udf_attr_selectors_t *udf_attr_selectors) 18636 { 18637 int rv = BCM_E_NONE; 18638 uint32 sel = 0; 18639 uint32 index = 0; 18640 uint32 drop =0; 18641 int udf_id = 0; 18642 uint32 offset = 0, width = 0, attr_value = 0, policer_offset = 0; 18643 uint32 is_subdiv_new = 0, subdiv_first_bit = 0, subdiv_last_bit = 0; 18644 uint32 selectors = 0, udf_subdiv_present = 0; 18645 bcm_policer_group_mode_attr_t attr; 18646 bcm_policer_udf_pkt_combine_attr_t *udf_combine_attr_data = NULL; 18647 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 18648 bcmi_xgs4_udf_offset_info_t *udf_offset_node = NULL; 18649 int grp_udf_id = -1; 18650 #endif 18651 18652 for (sel = 0; sel < num_selectors; sel++) { 18653 policer_offset = attr_selectors[sel].policer_offset; 18654 attr = attr_selectors[sel].attr; 18655 attr_value = attr_selectors[sel].attr_value; 18656 udf_id = attr_selectors[sel].udf_id; 18657 offset = attr_selectors[sel].offset; 18658 width = attr_selectors[sel].width; 18659 18660 if (policer_offset >= total_policers) { 18661 return BCM_E_PARAM; 18662 } 18663 18664 switch(attr) { 18665 case bcmPolicerGroupModeAttrUdf : 18666 { 18667 if (!(attr_selectors[sel].flags & 18668 BCM_POLICER_ATTR_WIDTH_OFFSET)) { 18669 return (BCM_E_PARAM); 18670 } 18671 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT) 18672 /* Validate UDF Id passed */ 18673 if (grp_udf_id == -1) { 18674 rv = bcmi_xgs4_udf_offset_node_get(unit, 18675 attr_selectors[sel].udf_id, &udf_offset_node); 18676 if (BCM_FAILURE(rv)) { 18677 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18678 "Failed to get info related to UDF Id \n"))); 18679 return rv; 18680 } 18681 18682 /* Matching node not found */ 18683 if (udf_offset_node == NULL) { 18684 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18685 "Failed to get info related to UDF Id \n"))); 18686 return BCM_E_NOT_FOUND; 18687 } 18688 18689 if (!((udf_offset_node->hw_bmap & 0x1) || 18690 (udf_offset_node->hw_bmap & 0x2))) { 18691 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18692 "UDF is not properly configured for policer use\n"))); 18693 return BCM_E_PARAM; 18694 } 18695 grp_udf_id = udf_id; 18696 } else if (udf_id != grp_udf_id) { 18697 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18698 "Mismatch of UDFs in two attribute selectors\n"))); 18699 return BCM_E_PARAM; 18700 } 18701 #endif 18702 /* width = 0 means ING_SVM_PKT_ATTR_SELECTOR_KEY_Xr is not 18703 * updated with required values, makes no sense */ 18704 if ((width > 8) || (width <= 0)) { 18705 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18706 "Invalid width passed for UDF \n"))); 18707 return BCM_E_PARAM; 18708 } 18709 /* offset value range from 0 to 31 */ 18710 if (offset >= SVC_METER_UDF1_MAX_BIT_POSITION) { 18711 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18712 "Invalid offset passed for UDF \n"))); 18713 return (BCM_E_PARAM); 18714 } 18715 /* offset+width should not exceed 32 - size of (UDF0 + UDF1) 18716 * For eg. if offset=31, width can be 1 (selecting msb 18717 * of udf1) making sum 32 */ 18718 if ((offset + width) > SVC_METER_UDF1_MAX_BIT_POSITION) { 18719 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18720 "Invalid offset and width pair passed for UDF \n"))); 18721 return (BCM_E_PARAM); 18722 } 18723 /* Verify that given offset-width does not overlap 18724 * 0-not used, 1-start offset in udf, 2-rest bits upto width */ 18725 if (udf_attr_selectors->udf_bits[offset] == 0) { 18726 is_subdiv_new = 1; 18727 } 18728 subdiv_first_bit = offset; 18729 subdiv_last_bit = offset + width - 1; 18730 if (subdiv_last_bit >= SVC_METER_UDF1_MAX_BIT_POSITION) { 18731 subdiv_last_bit = SVC_METER_UDF1_MAX_BIT_POSITION - 1; 18732 } 18733 for (index = subdiv_first_bit; index <= subdiv_last_bit; index++) { 18734 if (index == subdiv_first_bit) { 18735 if (is_subdiv_new == 1) { 18736 udf_attr_selectors->udf_bits[index] = 1; 18737 } else if (udf_attr_selectors->udf_bits[index] != 1) { 18738 rv = BCM_E_PARAM; 18739 break; 18740 } 18741 } else { 18742 if (((is_subdiv_new == 1) && 18743 (udf_attr_selectors->udf_bits[index] != 0)) || 18744 ((is_subdiv_new == 0) && 18745 (udf_attr_selectors->udf_bits[index] != 2))) { 18746 rv = BCM_E_PARAM; 18747 break; 18748 } else { 18749 udf_attr_selectors->udf_bits[index] = 2; 18750 } 18751 } 18752 } 18753 if ((rv == BCM_E_NONE) && 18754 (index != SVC_METER_UDF1_MAX_BIT_POSITION) && 18755 (udf_attr_selectors->udf_bits[index] == 2)) { 18756 rv = BCM_E_PARAM; 18757 } 18758 if (BCM_FAILURE(rv)) { 18759 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18760 "Overlapped offset/width pair for UDF not allowed\n"))); 18761 return rv; 18762 } 18763 /* Attribute value should not exceed size as given in width */ 18764 if (attr_value >= (1 << width)) { 18765 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18766 "Attribute value passed exceeds range of 'width' bits\n"))); 18767 return BCM_E_PARAM; 18768 } 18769 18770 if (is_subdiv_new == 1) { 18771 index = udf_attr_selectors->total_subdiv; 18772 udf_attr_selectors->udf_subdiv[index].udf_id = udf_id; 18773 udf_attr_selectors->udf_subdiv[index].offset = offset; 18774 udf_attr_selectors->udf_subdiv[index].width = width; 18775 udf_attr_selectors->total_subdiv = index + 1; 18776 is_subdiv_new = 0; 18777 } 18778 udf_combine_attr_data = 18779 &(udf_attr_selectors->combine_attr_data[policer_offset]); 18780 selectors = udf_combine_attr_data->selectors; 18781 udf_combine_attr_data->udf_subdiv[selectors].udf_id = udf_id; 18782 udf_combine_attr_data->udf_subdiv[selectors].offset = offset; 18783 udf_combine_attr_data->udf_subdiv[selectors].width = width; 18784 udf_combine_attr_data->attr_value[selectors] = attr_value; 18785 udf_combine_attr_data->selectors = selectors + 1; 18786 break; 18787 } 18788 case bcmPolicerGroupModeAttrDrop : 18789 { 18790 udf_attr_selectors->drop = 1; 18791 udf_combine_attr_data = 18792 &(udf_attr_selectors->combine_attr_data[policer_offset]); 18793 drop = attr_selectors[sel].attr_value; 18794 switch(drop) { 18795 case 0: 18796 udf_combine_attr_data->drop_flags = 18797 _BCM_POLICER_DROP_DISABLE; 18798 break; 18799 case 1: 18800 udf_combine_attr_data->drop_flags = 18801 _BCM_POLICER_DROP_ENABLE; 18802 break; 18803 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 18804 udf_combine_attr_data->drop_flags = 18805 _BCM_POLICER_DROP_DISABLE | 18806 _BCM_POLICER_DROP_ENABLE; 18807 break; 18808 default : 18809 return BCM_E_PARAM; 18810 } 18811 break; 18812 } 18813 default : 18814 return BCM_E_PARAM; 18815 } 18816 } 18817 18818 /* All policer offset must have atleast 1 selector for each sub-division*/ 18819 for (policer_offset = 0; policer_offset < total_policers; policer_offset++) { 18820 udf_combine_attr_data = &(udf_attr_selectors->combine_attr_data[policer_offset]); 18821 if (udf_attr_selectors->drop) { 18822 if (udf_combine_attr_data->drop_flags == 0) { 18823 return BCM_E_PARAM; 18824 } 18825 } 18826 for (index = 0; index < udf_attr_selectors->total_subdiv; index++) { 18827 udf_subdiv_present = 0; 18828 for (selectors = 0; udf_combine_attr_data->selectors; selectors++) { 18829 if (udf_attr_selectors->udf_subdiv[index].offset == \ 18830 udf_combine_attr_data->udf_subdiv[selectors].offset) { 18831 udf_subdiv_present = 1; 18832 break; 18833 } 18834 } 18835 if (udf_subdiv_present == 0) { 18836 return BCM_E_PARAM; 18837 } 18838 } 18839 } 18840 return BCM_E_NONE; 18841 } 18842 18843 /* 18844 * Function: 18845 * _bcm_esw_policer_group_mode_fillup_values 18846 * Purpose: 18847 * Fill up temporary structures in appropriate order for efficient 18848 * management of user input 18849 * Parameters: 18850 * unit - (IN) unit number 18851 * flags - (IN) flags 18852 * type - (IN) type of group mode 18853 * total_policers - (IN) total policers 18854 * num_selectors - (IN) number of selectors 18855 * attr_selectors - (IN) list of attributes selectors 18856 * pkt_attr_selectors - (OUT) fill up this structure 18857 * Returns: 18858 * BCM_E_XXX 18859 */ 18860 STATIC int 18861 _bcm_esw_policer_group_mode_fillup_values ( 18862 int unit, 18863 uint32 flags, 18864 bcm_policer_group_mode_type_t type, 18865 uint32 total_policers, 18866 uint32 num_selectors, 18867 bcm_policer_group_mode_attr_selector_t *attr_selectors, 18868 bcm_policer_attr_selectors_t *pkt_attr_selectors) 18869 { 18870 uint32 sel = 0, pol_offset = 0; 18871 uint32 attr_value = 0; 18872 uint32 value = 0, max_value = 0; 18873 uint32 attr_size = 0; 18874 uint32 index = 0; 18875 uint32 prio_range_first = 0, prio_range_last = 0; 18876 bcm_policer_group_mode_attr_t attr; 18877 bcm_policer_combine_attr_t *combine_attr_data = NULL; 18878 18879 for (sel = 0; sel < num_selectors; sel++) { 18880 pol_offset = attr_selectors[sel].policer_offset; 18881 attr = attr_selectors[sel].attr; 18882 attr_value = attr_selectors[sel].attr_value; 18883 if (pol_offset >= total_policers) { 18884 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18885 "Bad Param : sel=%d : offset (%d) more than" 18886 " total_policer=%d \n"), 18887 sel, pol_offset, total_policers)); 18888 return BCM_E_PARAM; 18889 } 18890 combine_attr_data = 18891 &pkt_attr_selectors->combine_attr_data[pol_offset]; 18892 switch(attr) { 18893 case bcmPolicerGroupModeAttrFieldIngressColor : 18894 pkt_attr_selectors->cng = 1; 18895 switch(attr_value) { 18896 case bcmColorGreen : 18897 combine_attr_data->cng_flags |= 18898 _BCM_POLICER_COLOR_GREEN; 18899 break; 18900 case bcmColorYellow : 18901 combine_attr_data->cng_flags |= 18902 _BCM_POLICER_COLOR_YELLOW; 18903 break; 18904 case bcmColorRed : 18905 combine_attr_data->cng_flags |= 18906 _BCM_POLICER_COLOR_RED; 18907 break; 18908 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 18909 combine_attr_data->cng_flags |= 18910 (_BCM_POLICER_COLOR_GREEN | 18911 _BCM_POLICER_COLOR_YELLOW | 18912 _BCM_POLICER_COLOR_RED); 18913 break; 18914 default : 18915 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18916 "BAD PARAM(cng) : sel=%d " 18917 "offset=%d, attr=%d value=%d \n"), 18918 sel, pol_offset, attr, attr_value)); 18919 return BCM_E_PARAM; 18920 } 18921 pkt_attr_selectors->combine_cng_flags |= 18922 combine_attr_data->cng_flags; 18923 break; 18924 18925 case bcmPolicerGroupModeAttrIntPri : 18926 pkt_attr_selectors->int_pri = 1; 18927 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) { 18928 prio_range_first = _BCM_POLICER_PKT_PRI0; 18929 prio_range_last = _BCM_POLICER_PKT_PRI15; 18930 } else if (attr_value <= _BCM_POLICER_PKT_PRI15) { 18931 prio_range_first = prio_range_last = attr_value; 18932 } else { 18933 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18934 "BAD PARAM(int_pri) : sel=%d " 18935 "offset=%d, attr=%d value=%d \n"), 18936 sel, pol_offset, attr, attr_value)); 18937 return BCM_E_PARAM; 18938 } 18939 for (index = prio_range_first; index <= prio_range_last; index++) { 18940 combine_attr_data->int_pri_flags |= (1 << index); 18941 } 18942 pkt_attr_selectors->combine_int_pri_flags |= 18943 combine_attr_data->int_pri_flags; 18944 break; 18945 18946 case bcmPolicerGroupModeAttrVlan: 18947 pkt_attr_selectors->vlan_format = 1; 18948 switch(attr_value) { 18949 case bcmPolicerGroupModeAttrVlanUnTagged : 18950 combine_attr_data->vlan_format_flags |= 18951 _BCM_POLICER_VLAN_FORMAT_UNTAGGED; 18952 break; 18953 case bcmPolicerGroupModeAttrVlanInnerTag : 18954 combine_attr_data->vlan_format_flags |= 18955 _BCM_POLICER_VLAN_FORMAT_INNER; 18956 break; 18957 case bcmPolicerGroupModeAttrVlanOuterTag : 18958 combine_attr_data->vlan_format_flags |= 18959 _BCM_POLICER_VLAN_FORMAT_OUTER; 18960 break; 18961 case bcmPolicerGroupModeAttrVlanStackedTag : 18962 combine_attr_data->vlan_format_flags |= 18963 _BCM_POLICER_VLAN_FORMAT_BOTH; 18964 break; 18965 case bcmPolicerGroupModeAttrVlanAll : 18966 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 18967 combine_attr_data->vlan_format_flags |= 18968 (_BCM_POLICER_VLAN_FORMAT_UNTAGGED | 18969 _BCM_POLICER_VLAN_FORMAT_INNER | 18970 _BCM_POLICER_VLAN_FORMAT_OUTER | 18971 _BCM_POLICER_VLAN_FORMAT_BOTH); 18972 break; 18973 default : 18974 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18975 "BAD PARAM(vlan_format) : sel=%d " 18976 "offset=%d, attr=%d value=%d \n"), 18977 sel, pol_offset, attr, attr_value)); 18978 return BCM_E_PARAM; 18979 } 18980 pkt_attr_selectors->combine_vlan_format_flags |= 18981 combine_attr_data->vlan_format_flags; 18982 break; 18983 18984 case bcmPolicerGroupModeAttrOuterPri: 18985 pkt_attr_selectors->outer_dot1p = 1; 18986 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) { 18987 prio_range_first = _BCM_POLICER_PKT_PRI0; 18988 prio_range_last = _BCM_POLICER_PKT_PRI7; 18989 } else if (attr_value <= _BCM_POLICER_PKT_PRI7) { 18990 prio_range_first = prio_range_last = attr_value; 18991 } else { 18992 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 18993 "BAD PARAM(outer_dot1p) : sel=%d " 18994 "offset=%d, attr=%d value=%d \n"), 18995 sel, pol_offset, attr, attr_value)); 18996 return BCM_E_PARAM; 18997 } 18998 for (index = prio_range_first; index <= prio_range_last; index++) { 18999 combine_attr_data->outer_dot1p_flags |= (1 << index); 19000 } 19001 pkt_attr_selectors->combine_outer_dot1p_flags |= 19002 combine_attr_data->outer_dot1p_flags; 19003 break; 19004 19005 case bcmPolicerGroupModeAttrInnerPri : 19006 pkt_attr_selectors->inner_dot1p = 1; 19007 if (attr_value == BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES) { 19008 prio_range_first = _BCM_POLICER_PKT_PRI0; 19009 prio_range_last = _BCM_POLICER_PKT_PRI7; 19010 } else if (attr_value <= _BCM_POLICER_PKT_PRI7) { 19011 prio_range_first = prio_range_last = attr_value; 19012 } else { 19013 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19014 "BAD PARAM(inner_dot1p) : sel=%d " 19015 "offset=%d, attr=%d value=%d \n"), 19016 sel, pol_offset, attr, attr_value)); 19017 return BCM_E_PARAM; 19018 } 19019 for (index = prio_range_first; index <= prio_range_last; index++) { 19020 combine_attr_data->inner_dot1p_flags |= (1 << index); 19021 } 19022 pkt_attr_selectors->combine_inner_dot1p_flags |= 19023 combine_attr_data->inner_dot1p_flags; 19024 break; 19025 19026 case bcmPolicerGroupModeAttrPort : 19027 pkt_attr_selectors->port = 1; 19028 max_value = soc_mem_index_max(unit, ING_SVM_PORT_MAPm); 19029 switch (attr_value) { 19030 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19031 for (value = 0; value <= max_value; value++) { 19032 _BCM_POLICER_VALUE_SET(combine_attr_data-> 19033 value_array[_bcmPolicerAttrPort], value); 19034 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19035 combine_value_array[_bcmPolicerAttrPort], value); 19036 } 19037 break; 19038 default : 19039 if (attr_value > max_value) { 19040 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19041 "BAD PARAM(port) : sel=%d " 19042 "offset=%d, attr=%d value=%d \n"), 19043 sel, pol_offset, attr, attr_value)); 19044 return BCM_E_PARAM; 19045 } 19046 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19047 value_array[_bcmPolicerAttrPort], attr_value); 19048 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19049 combine_value_array[_bcmPolicerAttrPort], attr_value); 19050 } 19051 break; 19052 case bcmPolicerGroupModeAttrTosDscp : 19053 pkt_attr_selectors->tos_dscp = 1; 19054 attr_size = BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 19055 max_value = (1 << attr_size) - 1; 19056 switch (attr_value) { 19057 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19058 for (value = 0; value <= max_value; value++) { 19059 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19060 value_array[_bcmPolicerAttrTosDscp], value); 19061 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19062 combine_value_array[_bcmPolicerAttrTosDscp], value); 19063 } 19064 break; 19065 default : 19066 if (attr_value > max_value) { 19067 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19068 "BAD PARAM(tos_dscp) : sel=%d " 19069 "offset=%d, attr=%d value=%d \n"), 19070 sel, pol_offset, attr, attr_value)); 19071 return BCM_E_PARAM; 19072 } 19073 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19074 value_array[_bcmPolicerAttrTosDscp], attr_value); 19075 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19076 combine_value_array[_bcmPolicerAttrTosDscp], attr_value); 19077 } 19078 break; 19079 case bcmPolicerGroupModeAttrTosEcn : 19080 pkt_attr_selectors->tos_ecn = 1; 19081 attr_size = BCM_POLICER_SVC_METER_TOS_ECN_ATTR_SIZE; 19082 max_value = (1 << attr_size) - 1; 19083 switch (attr_value) { 19084 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19085 for (value = 0; value <= max_value; value++) { 19086 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19087 value_array[_bcmPolicerAttrTosEcn], value); 19088 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19089 combine_value_array[_bcmPolicerAttrTosEcn], value); 19090 } 19091 break; 19092 default : 19093 if (attr_value > max_value) { 19094 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19095 "BAD PARAM(tos_ecn) : sel=%d " 19096 "offset=%d, attr=%d value=%d \n"), 19097 sel, pol_offset, attr, attr_value)); 19098 return BCM_E_PARAM; 19099 } 19100 _BCM_POLICER_VALUE_SET(combine_attr_data-> 19101 value_array[_bcmPolicerAttrTosEcn], attr_value); 19102 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19103 combine_value_array[_bcmPolicerAttrTosEcn], attr_value); 19104 } 19105 break; 19106 case bcmPolicerGroupModeAttrPktType : 19107 pkt_attr_selectors->pkt_resolution = 1; 19108 switch(attr_value) { 19109 case bcmPolicerGroupModeAttrPktTypeUnknown : 19110 combine_attr_data->pkt_resolution_flags |= 19111 _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT; 19112 break; 19113 case bcmPolicerGroupModeAttrPktTypeControl : 19114 combine_attr_data->pkt_resolution_flags |= 19115 _BCM_POLICER_PKT_TYPE_CONTROL_PKT; 19116 break; 19117 case bcmPolicerGroupModeAttrPktTypeOAM : 19118 combine_attr_data->pkt_resolution_flags |= 19119 _BCM_POLICER_PKT_TYPE_OAM_PKT; 19120 break; 19121 case bcmPolicerGroupModeAttrPktTypeBFD : 19122 combine_attr_data->pkt_resolution_flags |= 19123 _BCM_POLICER_PKT_TYPE_BFD_PKT; 19124 break; 19125 case bcmPolicerGroupModeAttrPktTypeBPDU : 19126 combine_attr_data->pkt_resolution_flags |= 19127 _BCM_POLICER_PKT_TYPE_BPDU_PKT; 19128 break; 19129 case bcmPolicerGroupModeAttrPktTypeICNM : 19130 combine_attr_data->pkt_resolution_flags |= 19131 _BCM_POLICER_PKT_TYPE_ICNM_PKT; 19132 break; 19133 case bcmPolicerGroupModeAttrPktType1588 : 19134 combine_attr_data->pkt_resolution_flags |= 19135 _BCM_POLICER_PKT_TYPE_PKT_IS_1588; 19136 break; 19137 case bcmPolicerGroupModeAttrPktTypeKnownL2UC : 19138 combine_attr_data->pkt_resolution_flags |= 19139 _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT; 19140 break; 19141 case bcmPolicerGroupModeAttrPktTypeUnknownL2UC : 19142 combine_attr_data->pkt_resolution_flags |= 19143 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT; 19144 break; 19145 case bcmPolicerGroupModeAttrPktTypeL2BC : 19146 combine_attr_data->pkt_resolution_flags |= 19147 _BCM_POLICER_PKT_TYPE_L2BC_PKT; 19148 break; 19149 case bcmPolicerGroupModeAttrPktTypeKnownL2MC : 19150 combine_attr_data->pkt_resolution_flags |= 19151 _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT; 19152 break; 19153 case bcmPolicerGroupModeAttrPktTypeUnknownL2MC : 19154 combine_attr_data->pkt_resolution_flags |= 19155 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT; 19156 break; 19157 case bcmPolicerGroupModeAttrPktTypeKnownL3UC : 19158 combine_attr_data->pkt_resolution_flags |= 19159 _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT; 19160 break; 19161 case bcmPolicerGroupModeAttrPktTypeUnknownL3UC : 19162 combine_attr_data->pkt_resolution_flags |= 19163 _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT; 19164 break; 19165 case bcmPolicerGroupModeAttrPktTypeKnownIPMC : 19166 combine_attr_data->pkt_resolution_flags |= 19167 _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT; 19168 break; 19169 case bcmPolicerGroupModeAttrPktTypeUnknownIPMC : 19170 combine_attr_data->pkt_resolution_flags |= 19171 _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT; 19172 break; 19173 case bcmPolicerGroupModeAttrPktTypeKnownMplsL2 : 19174 combine_attr_data->pkt_resolution_flags |= 19175 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT; 19176 break; 19177 case bcmPolicerGroupModeAttrPktTypeKnownMplsL3 : 19178 combine_attr_data->pkt_resolution_flags |= 19179 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT; 19180 break; 19181 case bcmPolicerGroupModeAttrPktTypeKnownMpls : 19182 combine_attr_data->pkt_resolution_flags |= 19183 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT; 19184 break; 19185 case bcmPolicerGroupModeAttrPktTypeUnknownMpls : 19186 combine_attr_data->pkt_resolution_flags |= 19187 _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT; 19188 break; 19189 case bcmPolicerGroupModeAttrPktTypeKnownMplsMulticast : 19190 combine_attr_data->pkt_resolution_flags |= 19191 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT; 19192 break; 19193 case bcmPolicerGroupModeAttrPktTypeKnownMim : 19194 combine_attr_data->pkt_resolution_flags |= 19195 _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT; 19196 break; 19197 case bcmPolicerGroupModeAttrPktTypeUnknownMim : 19198 combine_attr_data->pkt_resolution_flags |= 19199 _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT; 19200 break; 19201 case bcmPolicerGroupModeAttrPktTypeKnownTrill : 19202 combine_attr_data->pkt_resolution_flags |= 19203 _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT; 19204 break; 19205 case bcmPolicerGroupModeAttrPktTypeUnknownTrill : 19206 combine_attr_data->pkt_resolution_flags |= 19207 _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT; 19208 break; 19209 case bcmPolicerGroupModeAttrPktTypeKnownNiv : 19210 combine_attr_data->pkt_resolution_flags |= 19211 _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT; 19212 break; 19213 case bcmPolicerGroupModeAttrPktTypeUnknownNiv : 19214 combine_attr_data->pkt_resolution_flags |= 19215 _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT; 19216 break; 19217 case bcmPolicerGroupModeAttrPktTypeAll : 19218 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19219 combine_attr_data->pkt_resolution_flags |= 19220 (_BCM_POLICER_PKT_TYPE_UNKNOWN_PKT | 19221 _BCM_POLICER_PKT_TYPE_CONTROL_PKT | 19222 _BCM_POLICER_PKT_TYPE_OAM_PKT | 19223 _BCM_POLICER_PKT_TYPE_BFD_PKT | 19224 _BCM_POLICER_PKT_TYPE_BPDU_PKT | 19225 _BCM_POLICER_PKT_TYPE_ICNM_PKT | 19226 _BCM_POLICER_PKT_TYPE_PKT_IS_1588 | 19227 _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT | 19228 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT | 19229 _BCM_POLICER_PKT_TYPE_L2BC_PKT | 19230 _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT | 19231 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT | 19232 _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT | 19233 _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT | 19234 _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT | 19235 _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT | 19236 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT | 19237 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT | 19238 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT | 19239 _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT | 19240 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT | 19241 _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT | 19242 _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT | 19243 _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT | 19244 _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT | 19245 _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT | 19246 _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT); 19247 break; 19248 default : 19249 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19250 "BAD PARAM(port) : sel=%d " 19251 "offset=%d, attr=%d value=%d \n"), 19252 sel, pol_offset, attr, attr_value)); 19253 return BCM_E_PARAM; 19254 } 19255 pkt_attr_selectors->combine_pkt_res_flags |= 19256 combine_attr_data->pkt_resolution_flags; 19257 break; 19258 19259 case bcmPolicerGroupModeAttrIngNetworkGroup : 19260 pkt_attr_selectors->svp_type = 1; 19261 attr_size = BCM_SVM_DEV_ATTR(unit)->uncompressed_svp_type_size; 19262 max_value = (1 << attr_size) - 1; 19263 switch (attr_value) { 19264 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19265 for (value = 0; value <= max_value; value++) { 19266 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19267 value_array[_bcmPolicerAttrSvpType], value); 19268 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19269 combine_value_array[_bcmPolicerAttrSvpType], value); 19270 } 19271 break; 19272 default : 19273 if (attr_value > max_value) { 19274 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19275 "BAD PARAM(svm_group) : sel=%d " 19276 "offset=%d, attr=%d value=%d \n"), 19277 sel, pol_offset, attr, attr_value)); 19278 return BCM_E_PARAM; 19279 } 19280 _BCM_POLICER_VALUE_SET (combine_attr_data-> 19281 value_array[_bcmPolicerAttrSvpType], attr_value); 19282 _BCM_POLICER_VALUE_SET(pkt_attr_selectors-> 19283 combine_value_array[_bcmPolicerAttrSvpType], attr_value); 19284 } 19285 break; 19286 19287 case bcmPolicerGroupModeAttrDrop : 19288 pkt_attr_selectors->drop = 1; 19289 switch(attr_value) { 19290 case 0 : 19291 combine_attr_data->drop_flags |= 19292 _BCM_POLICER_DROP_DISABLE; 19293 break; 19294 case 1 : 19295 combine_attr_data->drop_flags |= 19296 _BCM_POLICER_DROP_ENABLE; 19297 break; 19298 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19299 combine_attr_data->drop_flags |= 19300 (_BCM_POLICER_DROP_DISABLE | 19301 _BCM_POLICER_DROP_ENABLE); 19302 break; 19303 default : 19304 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19305 "BAD PARAM(drop) : sel=%d " 19306 "offset=%d, attr=%d value=%d \n"), 19307 sel, pol_offset, attr, attr_value)); 19308 return BCM_E_PARAM; 19309 } 19310 pkt_attr_selectors->combine_drop_flags |= 19311 combine_attr_data->drop_flags; 19312 break; 19313 19314 case bcmPolicerGroupModeAttrPacketTypeIp : 19315 pkt_attr_selectors->ip_pkt = 1; 19316 switch(attr_value) { 19317 case 0 : 19318 combine_attr_data->ip_pkt_flags |= 19319 _BCM_POLICER_IP_PKT_DISABLE; 19320 break; 19321 case 1 : 19322 combine_attr_data->ip_pkt_flags |= 19323 _BCM_POLICER_IP_PKT_ENABLE; 19324 break; 19325 case BCM_POLICER_GROUP_MODE_ATTR_ALL_VALUES : 19326 combine_attr_data->ip_pkt_flags |= 19327 (_BCM_POLICER_IP_PKT_DISABLE | 19328 _BCM_POLICER_IP_PKT_ENABLE); 19329 break; 19330 default : 19331 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19332 "BAD PARAM(ip_pkt) : sel=%d " 19333 "offset=%d, attr=%d value=%d \n"), 19334 sel, pol_offset, attr, attr_value)); 19335 return BCM_E_PARAM; 19336 } 19337 pkt_attr_selectors->combine_ip_pkt_flags |= 19338 combine_attr_data->ip_pkt_flags; 19339 break; 19340 19341 default : 19342 return BCM_E_PARAM; 19343 } 19344 combine_attr_data = NULL; 19345 } 19346 19347 /* Check that all policer offset have all configured attributes */ 19348 for (pol_offset = 0; pol_offset < total_policers; pol_offset++) { 19349 if (pkt_attr_selectors->cng) { 19350 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19351 cng_flags == 0) { 19352 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19353 "color : combination issue... Check" 19354 "params and assign dummy value\n"))); 19355 return BCM_E_PARAM; 19356 } 19357 } 19358 if (pkt_attr_selectors->int_pri) { 19359 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19360 int_pri_flags == 0) { 19361 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19362 "int_pri : combination issue... Check" 19363 "params and assign dummy value\n"))); 19364 return BCM_E_PARAM; 19365 } 19366 } 19367 if (pkt_attr_selectors->vlan_format) { 19368 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19369 vlan_format_flags == 0) { 19370 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19371 "vlan_format : combination issue... Check" 19372 "params and assign dummy value\n"))); 19373 return BCM_E_PARAM; 19374 } 19375 } 19376 if (pkt_attr_selectors->outer_dot1p) { 19377 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19378 outer_dot1p_flags == 0) { 19379 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19380 "outer_dot1p : combination issue... Check" 19381 "params and assign dummy value\n"))); 19382 return BCM_E_PARAM; 19383 } 19384 } 19385 if (pkt_attr_selectors->inner_dot1p) { 19386 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19387 inner_dot1p_flags == 0) { 19388 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19389 "inner_dot1p : combination issue... Check" 19390 "params and assign dummy value\n"))); 19391 return BCM_E_PARAM; 19392 } 19393 } 19394 if (pkt_attr_selectors->port) { 19395 for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) { 19396 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19397 value_array[_bcmPolicerAttrPort][index] != 0) { 19398 break; 19399 } 19400 } 19401 if (index == _BCM_POLICER_BIT_ARRAY_SIZE) { 19402 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19403 "ing_port : combination issue... Check" 19404 "params and assign dummy value\n"))); 19405 return BCM_E_PARAM; 19406 } 19407 } 19408 if (pkt_attr_selectors->tos_dscp) { 19409 for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) { 19410 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19411 value_array[_bcmPolicerAttrTosDscp][index] != 0) { 19412 break; 19413 } 19414 } 19415 if (index == _BCM_POLICER_BIT_ARRAY_SIZE) { 19416 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19417 "tos_dscp : combination issue... Check" 19418 "params and assign dummy value\n"))); 19419 return BCM_E_PARAM; 19420 } 19421 } 19422 if (pkt_attr_selectors->tos_ecn) { 19423 for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) { 19424 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19425 value_array[_bcmPolicerAttrTosEcn][index] != 0) { 19426 break; 19427 } 19428 } 19429 if (index == _BCM_POLICER_BIT_ARRAY_SIZE) { 19430 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19431 "tos_ecn : combination issue... Check" 19432 "params and assign dummy value\n"))); 19433 return BCM_E_PARAM; 19434 } 19435 } 19436 if (pkt_attr_selectors->pkt_resolution) { 19437 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19438 pkt_resolution_flags == 0) { 19439 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19440 "pkt_res : combination issue... Check" 19441 "params and assign dummy value\n"))); 19442 return BCM_E_PARAM; 19443 } 19444 } 19445 if (pkt_attr_selectors->svp_type) { 19446 for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) { 19447 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19448 value_array[_bcmPolicerAttrSvpType][index] != 0) { 19449 break; 19450 } 19451 } 19452 if (index == _BCM_POLICER_BIT_ARRAY_SIZE) { 19453 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19454 "svp_type : combination issue... Check" 19455 "params and assign dummy value\n"))); 19456 return BCM_E_PARAM; 19457 } 19458 } 19459 if (pkt_attr_selectors->drop) { 19460 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19461 drop_flags == 0) { 19462 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19463 "drop : combination issue... Check" 19464 "params and assign dummy value\n"))); 19465 return BCM_E_PARAM; 19466 } 19467 } 19468 if (pkt_attr_selectors->ip_pkt) { 19469 if (pkt_attr_selectors->combine_attr_data[pol_offset]. 19470 ip_pkt_flags == 0) { 19471 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 19472 "ip_pkt : combination issue... Check" 19473 "params and assign dummy value\n"))); 19474 return BCM_E_PARAM; 19475 } 19476 } 19477 } 19478 pkt_attr_selectors->total_policers = total_policers; 19479 pkt_attr_selectors->total_selectors = num_selectors; 19480 return BCM_E_NONE; 19481 } 19482 19483 /* 19484 * Function: 19485 * _bcm_policer_group_mode_offset_map_generate 19486 * Purpose: 19487 * This internal function is used to calculate final offset locations 19488 * in offset_map where policer_offset needs to be put 19489 * Parameters: 19490 * unit - (IN) unit number 19491 * meter_attr - (IN/OUT) Meter attributes 19492 * group_mode - (IN) group mode of policer group 19493 * policer_policers - (IN) policer offset 19494 * offset_array - (IN) 2D array which stores shifted attr_values 19495 * Returns: 19496 * NONE 19497 */ 19498 STATIC 19499 int _bcm_policer_group_mode_offset_map_generate( 19500 int unit, 19501 bcm_policer_svc_meter_attr_t *meter_attr, 19502 bcm_policer_group_mode_t group_mode, 19503 int pol_offset, 19504 uint8 **offset_array) 19505 { 19506 int rv = BCM_E_NONE; 19507 uint32 offset = 0, final_offset = 0; 19508 uint32 count = 0, row = 0, index = 0; 19509 uint32 stack_offset[SVC_METER_MAX_SELECTOR_BITS] = {0}; 19510 uint32 stack_index[SVC_METER_MAX_SELECTOR_BITS] = {0}; 19511 uint32 top = 0; 19512 19513 /* To generate final offset index at which policer_offset value 19514 * needs to be written in SVM_OFFSET_TABLE, attr_value belonging to 19515 * different sub-groups have AND relationship. 19516 * Following code block generate final offset using OR operator as 19517 * the caller function already left-shifted values by required number 19518 * of bits. 19519 * At offset_array[X][0], count of (left-shifted) attr_values 19520 * is stored. Actual attr_value is stored from index 1. 19521 * 'top' is index in stack at which next data is inserted. 19522 * 'row' denotes moving row-wise in offset_array[][]. Each row in 19523 * offset_array[][] denotes different sub-group for attr_value 19524 * stack_offset[row] stores ORed offset computed at till [row-1] (from 0) 19525 * stack_index[row] stores the index in offset_array[X] upto 19526 * which, we have used is used to calculate offset in this row. 19527 */ 19528 /* Example : For offset_array 19529 * offset_array[0] = {2, 0, 1} 19530 * offset_array[1] = {3, 2, 3, 4} 19531 * offset_array[2] = {1, 5} 19532 * offset_array[3] = {2, 6, 7} 19533 * offset_array[4] = {0} 19534 * Final_offsets calculated 19535 * = 0|2|5|6, 0|2|5|7, 0|3|5|6, 0|3|5|7, 19536 * 0|4|5|6, 0|4|5|7, 1|2|5|6, 1|2|5|7, 19537 * 1|3|5|6, 1|3|5|7, 1|4|5|6, 1|4|5|7, 19538 */ 19539 /* Insert default value in stack, both stack_offset[] and stack_index[] 19540 * is initialized with 0 as none of the index is used to compute offset 19541 */ 19542 if (offset_array[0][0] != 0) { 19543 stack_offset[top] = 0; 19544 stack_index[top] = 0; 19545 top++; 19546 } 19547 19548 while (top != 0) { 19549 row = top - 1; 19550 /* Get data from Stack */ 19551 index = stack_index[row]; 19552 offset = stack_offset[row]; 19553 19554 if (index == offset_array[row][0]) { 19555 /* All attr_values at this row is used up to calculate 19556 * offset, go back one row */ 19557 /* Intentionally left blank */ 19558 ; 19559 } 19560 else if ((row < (SVC_METER_MAX_SELECTOR_BITS - 1)) 19561 && (offset_array[row + 1][0] != 0)) { 19562 /* Next row have data, push current row to stack */ 19563 stack_offset[top] = offset | 19564 offset_array[row][index + 1]; 19565 stack_index[top] = 0; 19566 top++; 19567 continue; 19568 } else { 19569 /* This is last row which have data. Need to compute final 19570 * index and populate offset_map */ 19571 for (count = 0; 19572 count < offset_array[row][0]; 19573 count++) { 19574 final_offset = offset | offset_array[row][ count + 1]; 19575 rv = _bcm_esw_svc_meter_offset_map_update(unit, 19576 meter_attr, group_mode, final_offset, pol_offset); 19577 BCM_IF_ERROR_RETURN(rv); 19578 } 19579 } 19580 /* Pop last row */ 19581 top--; 19582 if (top != 0) { 19583 /* Increment index for this row */ 19584 row = top - 1; 19585 stack_index[row] = stack_index[row] + 1; 19586 } 19587 } 19588 19589 return BCM_E_NONE; 19590 } 19591 19592 /* 19593 * Function: 19594 * _bcm_policer_svm_pkt_attr_bits_get 19595 * Purpose: 19596 * This internal function is used to get the number of 19597 * bits required for attribute in uncompressed mode 19598 * Parameters: 19599 * unit - (IN) unit number 19600 * pkt_attr - (IN) packet attribute 19601 * Returns: 19602 * Number of bits in uncompressed mode 19603 */ 19604 19605 STATIC 19606 int _bcm_policer_svm_pkt_attr_bits_get( 19607 int unit, 19608 pkt_attrs_t pkt_attr) 19609 { 19610 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 19611 19612 pkt_attr_bit_pos = 19613 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos; 19614 19615 return (pkt_attr_bit_pos[pkt_attr].end_bit - 19616 pkt_attr_bit_pos[pkt_attr].start_bit + 1); 19617 } 19618 19619 /* 19620 * Function: 19621 * _bcm_policer_svm_cmprsd_pkt_attr_bits_get 19622 * Purpose: 19623 * This internal function is used to get the number of 19624 * bits required for attribute in compressed mode 19625 * Parameters: 19626 * unit - (IN) unit number 19627 * pkt_attr - (IN) packet attribute 19628 * Returns: 19629 * Number of bits in uncompressed mode 19630 */ 19631 19632 STATIC 19633 int _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 19634 int unit, 19635 pkt_attrs_t pkt_attr) 19636 { 19637 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 19638 19639 pkt_attr_bit_pos = 19640 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos; 19641 19642 return (pkt_attr_bit_pos[pkt_attr].end_bit - 19643 pkt_attr_bit_pos[pkt_attr].start_bit + 1); 19644 } 19645 19646 /* 19647 * Function: 19648 * _bcm_policer_num_of_bits_get 19649 * Purpose: 19650 * This internal function is used to determine number 19651 * of bits required for the given value 19652 * Parameters: 19653 * value - (IN) number 19654 * Returns: 19655 * Number of bits 19656 */ 19657 STATIC 19658 uint8 _bcm_policer_num_of_bits_get(uint8 values) 19659 { 19660 if (values <= 2) { 19661 return 1; 19662 } 19663 if (values <= 4) { 19664 return 2; 19665 } 19666 if (values <= 8) { 19667 return 3; 19668 } 19669 if (values <= 16) { 19670 return 4; 19671 } 19672 if (values <= 32) { 19673 return 5; 19674 } 19675 if (values <= 64) { 19676 return 6; 19677 } 19678 if (values <= 128) { 19679 return 7; 19680 } 19681 19682 return 8; 19683 } 19684 19685 /* 19686 * Function: 19687 * _bcm_esw_svm_pkt_compressed_attr_maps_match 19688 * Purpose: 19689 * This internal function is used to match attributes and its 19690 * corresponding values with global compressed attr maps. If the 19691 * matchin creteria is not satisfied, error is returned. Else 19692 * combined attr selectors are updated with global attr value flags 19693 * for further processing. 19694 * Parameters: 19695 * uint - (IN) Unit number 19696 * pkt_attr_selectors - (IN/OUT) packet attribute selectors 19697 * Returns: 19698 * BCM_E_PARAM, if match fails 19699 * BCM_E_XXX 19700 */ 19701 STATIC 19702 int _bcm_esw_svm_pkt_compressed_attr_maps_validate( 19703 int unit, 19704 bcm_policer_attr_selectors_t *pkt_attr_selectors) 19705 { 19706 int rv = BCM_E_NONE; 19707 uint32 i = 0; 19708 uint32 combine_flags1 = 0; 19709 uint32 combine_flags2 = 0; 19710 uint32 combine_flags3 = 0; 19711 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 19712 19713 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 19714 19715 if ((pkt_attr_selectors->cng != 0) || 19716 (pkt_attr_selectors->int_pri != 0)) { 19717 /* If ref_count is non-zero, match attribute values. */ 19718 if (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map] != 0) { 19719 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_cng_flags, 19720 &cmprsd_attr_maps->combine_cng_flags, 19721 0, 32, &combine_flags1); 19722 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_int_pri_flags, 19723 &cmprsd_attr_maps->combine_int_pri_flags, 19724 0, 32, &combine_flags2); 19725 19726 if ((combine_flags1 != 19727 cmprsd_attr_maps->combine_cng_flags) || 19728 (combine_flags2 != 19729 cmprsd_attr_maps->combine_int_pri_flags)) { 19730 return BCM_E_PARAM; 19731 } 19732 /* Update combined flags */ 19733 pkt_attr_selectors->combine_cng_flags = combine_flags1; 19734 pkt_attr_selectors->combine_int_pri_flags = combine_flags2; 19735 } 19736 } 19737 19738 if ((pkt_attr_selectors->vlan_format != 0) || 19739 (pkt_attr_selectors->outer_dot1p) || 19740 (pkt_attr_selectors->inner_dot1p)) { 19741 /* If ref_count is non-zero, match attribute values. */ 19742 if (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map] != 0) { 19743 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_vlan_format_flags, 19744 &cmprsd_attr_maps->combine_vlan_format_flags, 19745 0, 32, &combine_flags1); 19746 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_outer_dot1p_flags, 19747 &cmprsd_attr_maps->combine_outer_dot1p_flags, 19748 0, 32, &combine_flags2); 19749 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_inner_dot1p_flags, 19750 &cmprsd_attr_maps->combine_inner_dot1p_flags, 19751 0, 32, &combine_flags3); 19752 19753 if ((combine_flags1 != 19754 cmprsd_attr_maps->combine_vlan_format_flags) || 19755 (combine_flags2 != 19756 cmprsd_attr_maps->combine_outer_dot1p_flags) || 19757 (combine_flags3 != 19758 cmprsd_attr_maps->combine_inner_dot1p_flags)) { 19759 return BCM_E_PARAM; 19760 } 19761 /* Update combined flags */ 19762 pkt_attr_selectors->combine_vlan_format_flags = combine_flags1; 19763 pkt_attr_selectors->combine_outer_dot1p_flags = combine_flags2; 19764 pkt_attr_selectors->combine_inner_dot1p_flags = combine_flags3; 19765 } 19766 } 19767 19768 if (pkt_attr_selectors->port != 0) { 19769 /* If ref_count is non-zero, match attribute values */ 19770 if (cmprsd_attr_maps->ref_counts[pkt_attr_port_map] != 0) { 19771 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19772 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array 19773 [_bcmPolicerAttrPort][i], 19774 &cmprsd_attr_maps->combine_value_array 19775 [_bcmPolicerAttrPort][i], 19776 0, 32, & combine_flags1); 19777 if (combine_flags1 != cmprsd_attr_maps->combine_value_array 19778 [_bcmPolicerAttrPort][i]) { 19779 return BCM_E_PARAM; 19780 } 19781 /* Update combined flags */ 19782 pkt_attr_selectors->combine_value_array 19783 [_bcmPolicerAttrPort][i] = combine_flags1; 19784 } 19785 } 19786 } 19787 19788 if ((pkt_attr_selectors->tos_dscp != 0) || 19789 (pkt_attr_selectors->tos_ecn)) { 19790 /* If ref_count is non-zero, match attribute values. */ 19791 if (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map] != 0) { 19792 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19793 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array 19794 [_bcmPolicerAttrTosDscp][i], 19795 &cmprsd_attr_maps->combine_value_array 19796 [_bcmPolicerAttrTosDscp][i], 19797 0, 32, & combine_flags1); 19798 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array 19799 [_bcmPolicerAttrTosEcn][i], 19800 &cmprsd_attr_maps->combine_value_array 19801 [_bcmPolicerAttrTosEcn][i], 19802 0, 32, & combine_flags2); 19803 if ((combine_flags1 != cmprsd_attr_maps->combine_value_array 19804 [_bcmPolicerAttrTosDscp][i]) || 19805 (combine_flags2 != cmprsd_attr_maps->combine_value_array 19806 [_bcmPolicerAttrTosEcn][i])) { 19807 return BCM_E_PARAM; 19808 } 19809 /* Update combined flags */ 19810 pkt_attr_selectors->combine_value_array 19811 [_bcmPolicerAttrTosDscp][i] = combine_flags1; 19812 pkt_attr_selectors->combine_value_array 19813 [_bcmPolicerAttrTosEcn][i] = combine_flags2; 19814 } 19815 } 19816 } 19817 19818 if ((pkt_attr_selectors->pkt_resolution != 0) || 19819 (pkt_attr_selectors->svp_type) || 19820 (pkt_attr_selectors->drop)) { 19821 /* If ref_count is non-zero, match */ 19822 if (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map] != 0) { 19823 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_pkt_res_flags, 19824 &cmprsd_attr_maps->combine_pkt_res_flags, 19825 0, 32, &combine_flags1); 19826 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_drop_flags, 19827 &cmprsd_attr_maps->combine_drop_flags, 19828 0, 32, &combine_flags2); 19829 if ((combine_flags1 != cmprsd_attr_maps->combine_pkt_res_flags) || 19830 (combine_flags2 != cmprsd_attr_maps->combine_drop_flags)) { 19831 return BCM_E_PARAM; 19832 } 19833 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19834 SHR_BITOR_RANGE(&pkt_attr_selectors->combine_value_array 19835 [_bcmPolicerAttrSvpType][i], 19836 &cmprsd_attr_maps->combine_value_array 19837 [_bcmPolicerAttrSvpType][i], 19838 0, 32, & combine_flags3); 19839 if (combine_flags3 != cmprsd_attr_maps->combine_value_array 19840 [_bcmPolicerAttrSvpType][i]) { 19841 return BCM_E_PARAM; 19842 } 19843 /* Update combined flags */ 19844 pkt_attr_selectors->combine_value_array 19845 [_bcmPolicerAttrSvpType][i] = combine_flags3; 19846 } 19847 /* Update combine_xxx_flags */ 19848 pkt_attr_selectors->combine_pkt_res_flags = combine_flags1; 19849 pkt_attr_selectors->combine_drop_flags = combine_flags2; 19850 } 19851 } 19852 19853 return rv; 19854 } 19855 19856 /* 19857 * Function: 19858 * _bcm_esw_svm_pkt_compressed_attr_maps_update 19859 * Purpose: 19860 * This internal function is used to update global compressed attr maps 19861 * with pkt attr selectors. 19862 * Parameters: 19863 * uint - (IN) Unit number 19864 * pkt_attr_selectors - (IN) packet attribute selectors 19865 * Returns: 19866 * BCM_E_XXX 19867 */ 19868 STATIC 19869 int _bcm_esw_svm_pkt_compressed_attr_maps_update( 19870 int unit, 19871 bcm_policer_attr_selectors_t *pkt_attr_selectors) 19872 { 19873 int rv = BCM_E_NONE; 19874 uint32 i = 0; 19875 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 19876 19877 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 19878 19879 if (pkt_attr_selectors->cng) { 19880 cmprsd_attr_maps->combine_cng_flags = 19881 pkt_attr_selectors->combine_cng_flags; 19882 } 19883 if (pkt_attr_selectors->int_pri != 0) { 19884 cmprsd_attr_maps->combine_int_pri_flags = 19885 pkt_attr_selectors->combine_int_pri_flags; 19886 } 19887 if (pkt_attr_selectors->vlan_format != 0) { 19888 cmprsd_attr_maps->combine_vlan_format_flags = 19889 pkt_attr_selectors->combine_vlan_format_flags; 19890 } 19891 if (pkt_attr_selectors->outer_dot1p != 0) { 19892 cmprsd_attr_maps->combine_outer_dot1p_flags = 19893 pkt_attr_selectors->combine_outer_dot1p_flags; 19894 } 19895 if (pkt_attr_selectors->inner_dot1p != 0) { 19896 cmprsd_attr_maps->combine_inner_dot1p_flags = 19897 pkt_attr_selectors->combine_inner_dot1p_flags; 19898 } 19899 if (pkt_attr_selectors->port != 0) { 19900 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19901 cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrPort][i] = 19902 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrPort][i]; 19903 } 19904 } 19905 if (pkt_attr_selectors->tos_dscp != 0) { 19906 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19907 cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosDscp][i] = 19908 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrTosDscp][i]; 19909 } 19910 } 19911 if (pkt_attr_selectors->tos_ecn != 0) { 19912 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19913 cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrTosEcn][i] = 19914 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrTosEcn][i]; 19915 } 19916 } 19917 if (pkt_attr_selectors->pkt_resolution != 0) { 19918 cmprsd_attr_maps->combine_pkt_res_flags = 19919 pkt_attr_selectors->combine_pkt_res_flags; 19920 } 19921 if (pkt_attr_selectors->svp_type != 0) { 19922 for (i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 19923 cmprsd_attr_maps->combine_value_array[_bcmPolicerAttrSvpType][i] = 19924 pkt_attr_selectors->combine_value_array[_bcmPolicerAttrSvpType][i]; 19925 } 19926 } 19927 if (pkt_attr_selectors->drop != 0) { 19928 cmprsd_attr_maps->combine_drop_flags = 19929 pkt_attr_selectors->combine_drop_flags; 19930 } 19931 if (pkt_attr_selectors->ip_pkt != 0) { 19932 cmprsd_attr_maps->combine_ip_pkt_flags = 19933 pkt_attr_selectors->combine_ip_pkt_flags; 19934 } 19935 19936 return rv; 19937 } 19938 19939 /* 19940 * Function: 19941 * _bcm_esw_policer_group_mode_id_associate 19942 * Purpose: 19943 * This function is used to 19944 * 1. Create offset map for compressed or uncompressed mode 19945 * based on number of bits required for the given input selectors 19946 * 2. Reserve svm meter mode and update h/w register/table 19947 * Parameters: 19948 * unit - (IN) unit number 19949 * flags - (IN) flags 19950 * type - (IN) type of group mode 19951 * pkt_attr_selectors - (IN) stores data about selectors 19952 * mode_id - (OUT) mode which used by policer group 19953 * Returns: 19954 * BCM_E_XXX 19955 */ 19956 STATIC 19957 bcm_error_t _bcm_esw_policer_group_mode_id_associate( 19958 int unit, 19959 uint32 flags, 19960 uint32 type, 19961 bcm_policer_attr_selectors_t *pkt_attr_selectors, 19962 uint32 *mode_id) 19963 { 19964 int rv = BCM_E_NONE; 19965 uint8 invalid_index0 = FALSE; 19966 uint8 invalid_index1 = FALSE; 19967 uint8 invalid_index2 = FALSE; 19968 uint8 unused_found = FALSE; 19969 uint32 pol_offset = 0; 19970 uint32 total_bits = 0; 19971 uint32 shift_by_bits = 0; 19972 uint32 cng_bits = 0; 19973 uint32 int_pri_bits = 0; 19974 uint32 vlan_format_bits = 0; 19975 uint32 outer_dot1p_bits = 0; 19976 uint32 inner_dot1p_bits = 0; 19977 uint32 ing_port_bits = 0; 19978 uint32 pkt_res_bits = 0; 19979 uint32 svp_type_bits = 0; 19980 uint32 drop_bits = 0; 19981 uint32 ip_pkt_bits = 0; 19982 uint32 tos_dscp_bits = 0; 19983 uint32 tos_ecn_bits = 0; 19984 uint32 max_bits = 0; 19985 uint32 loop = 0; 19986 uint32 temp_count = 0; 19987 uint32 value = 0; 19988 uint32 invalid_map_value = 0; 19989 uint32 logical_group_bits = 0; 19990 uint32 values = 0, values_max = 0; 19991 uint32 index0 = 0, index1 = 0, index2 = 0; 19992 uint32 final_index = 0, final_mapped_value = 0; 19993 uint32 mapped_value0 = 0, mapped_value1 = 0, mapped_value2 = 0; 19994 uint32 cng_cmprsd_bits = 0; 19995 uint32 int_pri_cmprsd_bits = 0; 19996 uint32 vlan_format_cmprsd_bits = 0; 19997 uint32 outer_dot1p_cmprsd_bits = 0; 19998 uint32 inner_dot1p_cmprsd_bits = 0; 19999 uint32 ing_port_cmprsd_bits = 0, ing_port_attrs = 0; 20000 uint32 pkt_res_cmprsd_bits = 0; 20001 uint32 svp_type_cmprsd_bits = 0, svp_type_attrs = 0; 20002 uint32 drop_cmprsd_bits = 0; 20003 uint32 ip_pkt_cmprsd_bits = 0; 20004 uint32 tos_dscp_cmprsd_bits = 0, tos_dscp_attrs = 0; 20005 uint32 tos_ecn_cmprsd_bits = 0, tos_ecn_attrs = 0; 20006 uint8 *pkt_res = NULL; 20007 uint8 *map_array[bcmPolicerGroupModeAttrCount] = {NULL}; 20008 uint8 *offset_array[SVC_METER_MAX_SELECTOR_BITS] = {NULL}; 20009 uncompressed_attr_selectors_t *uncmprsd_attr_selectors = NULL; 20010 compressed_attr_selectors_t *cmprsd_attr_selectors = NULL; 20011 bcm_policer_svc_meter_attr_t *meter_attr = NULL; 20012 bcm_policer_group_mode_t group_mode; 20013 bcm_policer_combine_attr_t *combine_attr_data = NULL; 20014 _bcm_policer_pkt_attr_bit_pos_t *cmprsd_pkt_attr_bit_pos = NULL; 20015 20016 if (BCM_SVM_DEV_ATTR(unit)->pkt_resolution != NULL) { 20017 pkt_res = BCM_SVM_DEV_ATTR(unit)->pkt_resolution; 20018 } else { 20019 return (BCM_E_UNAVAIL); 20020 } 20021 20022 meter_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t), 20023 "meter mode attr"); 20024 if (meter_attr == NULL) { 20025 LOG_VERBOSE(BSL_LS_BCM_POLICER, 20026 (BSL_META_U(unit, 20027 "Failed to allocate memory for meter attr\n"))); 20028 return BCM_E_MEMORY; 20029 } 20030 sal_memset(meter_attr, 0, sizeof(bcm_policer_svc_meter_attr_t)); 20031 20032 /* bcm_policer_group_mode_t should be based on type */ 20033 if (type == bcmPolicerGroupModeTypeNormal) { 20034 group_mode = bcmPolicerGroupModeSingle; 20035 } else if (type == bcmPolicerGroupModeTypeCascade) { 20036 group_mode = bcmPolicerGroupModeCascade; 20037 } else { /* type == bcmPolicerGroupModeTypeCascadeWithCoupling */ 20038 group_mode = bcmPolicerGroupModeCascadeWithCoupling; 20039 } 20040 20041 /* Calcuate total bits req. to determine compressed/uncompressed mode */ 20042 if (pkt_attr_selectors->cng == 1) { 20043 total_bits += (cng_bits = _bcm_policer_svm_pkt_attr_bits_get( 20044 unit, pkt_attr_cng)); 20045 } 20046 if (pkt_attr_selectors->int_pri == 1) { 20047 total_bits += (int_pri_bits = _bcm_policer_svm_pkt_attr_bits_get( 20048 unit, pkt_attr_int_pri)); 20049 } 20050 if (pkt_attr_selectors->vlan_format == 1) { 20051 total_bits += (vlan_format_bits = _bcm_policer_svm_pkt_attr_bits_get( 20052 unit, pkt_attr_vlan_format)); 20053 } 20054 if (pkt_attr_selectors->outer_dot1p == 1) { 20055 total_bits += (outer_dot1p_bits = _bcm_policer_svm_pkt_attr_bits_get( 20056 unit, pkt_attr_outer_dot1p)); 20057 } 20058 if (pkt_attr_selectors->inner_dot1p == 1) { 20059 total_bits += (inner_dot1p_bits = _bcm_policer_svm_pkt_attr_bits_get( 20060 unit, pkt_attr_inner_dot1p)); 20061 } 20062 if (pkt_attr_selectors->port == 1) { 20063 total_bits += (ing_port_bits = _bcm_policer_svm_pkt_attr_bits_get( 20064 unit, pkt_attr_ing_port)); 20065 } 20066 if (pkt_attr_selectors->tos_dscp == 1) { 20067 total_bits += (tos_dscp_bits = _bcm_policer_svm_pkt_attr_bits_get( 20068 unit, pkt_attr_tos)); 20069 } 20070 if (pkt_attr_selectors->tos_ecn == 1) { 20071 total_bits += (tos_ecn_bits = _bcm_policer_svm_pkt_attr_bits_get( 20072 unit, pkt_attr_tos_ecn)); 20073 } 20074 if (pkt_attr_selectors->pkt_resolution == 1) { 20075 total_bits += (pkt_res_bits = _bcm_policer_svm_pkt_attr_bits_get( 20076 unit, pkt_attr_pkt_resolution)); 20077 } 20078 if (pkt_attr_selectors->svp_type == 1) { 20079 total_bits += (svp_type_bits = _bcm_policer_svm_pkt_attr_bits_get( 20080 unit, pkt_attr_drop)); 20081 } 20082 if (pkt_attr_selectors->drop == 1) { 20083 total_bits += (drop_bits = _bcm_policer_svm_pkt_attr_bits_get( 20084 unit, pkt_attr_drop)); 20085 } 20086 if (pkt_attr_selectors->ip_pkt == 1) { 20087 total_bits += (ip_pkt_bits = _bcm_policer_svm_pkt_attr_bits_get( 20088 unit, pkt_attr_ip_pkt)); 20089 } 20090 20091 if (total_bits <= BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 20092 /* Mode : Uncompressed */ 20093 uncmprsd_attr_selectors = &(meter_attr->uncompressed_attr_selectors_v); 20094 meter_attr->mode_type_v = uncompressed_mode; 20095 20096 /* Fill uncompressed_attr_bits_selector */ 20097 if (pkt_attr_selectors->cng == 1) { 20098 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20099 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_CNG_ATTR_BITS; 20100 } 20101 if (pkt_attr_selectors->int_pri == 1) { 20102 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20103 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INT_PRI_ATTR_BITS; 20104 } 20105 if (pkt_attr_selectors->vlan_format == 1) { 20106 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20107 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_VLAN_FORMAT_ATTR_BITS; 20108 } 20109 if (pkt_attr_selectors->outer_dot1p == 1) { 20110 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20111 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_OUTER_DOT1P_ATTR_BITS; 20112 } 20113 if (pkt_attr_selectors->inner_dot1p == 1) { 20114 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20115 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INNER_DOT1P_ATTR_BITS; 20116 } 20117 if (pkt_attr_selectors->port == 1) { 20118 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20119 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_INGRESS_PORT_ATTR_BITS; 20120 } 20121 if (pkt_attr_selectors->tos_dscp == 1) { 20122 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20123 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ATTR_BITS; 20124 } 20125 if (pkt_attr_selectors->tos_ecn == 1) { 20126 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20127 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_TOS_ECN_ATTR_BITS; 20128 } 20129 if (pkt_attr_selectors->pkt_resolution == 1) { 20130 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20131 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_PKT_RESOLUTION_ATTR_BITS; 20132 } 20133 if (pkt_attr_selectors->svp_type == 1) { 20134 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20135 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS; 20136 } 20137 if (pkt_attr_selectors->drop == 1) { 20138 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20139 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS; 20140 } 20141 if (pkt_attr_selectors->ip_pkt == 1) { 20142 uncmprsd_attr_selectors->uncompressed_attr_bits_selector |= 20143 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS; 20144 } 20145 20146 /* Fill offset_map field of uncompressed_attr_selectors_v */ 20147 /* Step 1 Reset all values in offset_map */ 20148 sal_memset(uncmprsd_attr_selectors->offset_map, 0, 20149 sizeof (uncmprsd_attr_selectors->offset_map)); 20150 20151 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 20152 offset_array[loop] = (uint8 *) sal_alloc( 20153 BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1,"offset_array"); 20154 if (offset_array[loop] == NULL) { 20155 rv = BCM_E_MEMORY; 20156 break; 20157 } 20158 } 20159 if (BCM_FAILURE(rv)) { 20160 /* Free offset_array */ 20161 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 20162 if (offset_array[loop] != NULL) { 20163 sal_free(offset_array[loop]); 20164 } 20165 } 20166 sal_free(meter_attr); 20167 return rv; 20168 } 20169 20170 /* Step 2 Calculate offset value for each policer_offset */ 20171 for (pol_offset = 0; 20172 pol_offset < pkt_attr_selectors->total_policers; 20173 pol_offset++ ) { 20174 combine_attr_data = 20175 &pkt_attr_selectors->combine_attr_data[pol_offset]; 20176 /* Step 2.1 : Reset offset_array */ 20177 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 20178 sal_memset(offset_array[loop], 0, 20179 BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1); 20180 } 20181 loop = 0; 20182 20183 /* Step 2.2 : Parse through each attr type and save values */ 20184 if ((pkt_attr_selectors->cng == 1) && 20185 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20186 shift_by_bits = int_pri_bits + 20187 vlan_format_bits + 20188 outer_dot1p_bits + 20189 inner_dot1p_bits + 20190 ing_port_bits + 20191 tos_dscp_bits + 20192 tos_ecn_bits + 20193 pkt_res_bits + 20194 svp_type_bits + 20195 drop_bits + 20196 ip_pkt_bits; 20197 20198 temp_count = offset_array[loop][0]; 20199 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_GREEN) { 20200 offset_array[loop][temp_count + 1] = (0 << shift_by_bits); 20201 temp_count++; 20202 } 20203 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_YELLOW) { 20204 offset_array[loop][temp_count + 1] = (1 << shift_by_bits); 20205 temp_count++; 20206 } 20207 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_RED) { 20208 offset_array[loop][temp_count + 1] = (3 << shift_by_bits); 20209 temp_count++; 20210 } 20211 offset_array[loop][0] = temp_count; 20212 loop++; 20213 } 20214 if ((pkt_attr_selectors->int_pri == 1) && 20215 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20216 shift_by_bits = vlan_format_bits + 20217 outer_dot1p_bits + 20218 inner_dot1p_bits + 20219 ing_port_bits + 20220 tos_dscp_bits + 20221 tos_ecn_bits + 20222 pkt_res_bits + 20223 svp_type_bits + 20224 drop_bits + 20225 ip_pkt_bits; 20226 20227 temp_count = offset_array[loop][0]; 20228 for(index0 = _BCM_POLICER_PKT_PRI0; 20229 index0 <= _BCM_POLICER_PKT_PRI15; index0++) { 20230 if (combine_attr_data->int_pri_flags & (1 << index0)) { 20231 offset_array[loop][temp_count + 1] = 20232 (index0 << shift_by_bits); 20233 temp_count++; 20234 } 20235 } 20236 offset_array[loop][0] = temp_count; 20237 loop++; 20238 } 20239 if ((pkt_attr_selectors->vlan_format == 1) && 20240 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20241 shift_by_bits = outer_dot1p_bits + 20242 inner_dot1p_bits + 20243 ing_port_bits + 20244 tos_dscp_bits + 20245 tos_ecn_bits + 20246 pkt_res_bits + 20247 svp_type_bits + 20248 drop_bits + 20249 ip_pkt_bits; 20250 temp_count = offset_array[loop][0]; 20251 if(combine_attr_data->vlan_format_flags & 20252 _BCM_POLICER_VLAN_FORMAT_UNTAGGED) { 20253 offset_array[loop][temp_count + 1] = (0 << shift_by_bits); 20254 temp_count++; 20255 } 20256 if(combine_attr_data->vlan_format_flags & 20257 _BCM_POLICER_VLAN_FORMAT_INNER) { 20258 offset_array[loop][temp_count + 1] = (1 << shift_by_bits); 20259 temp_count++; 20260 } 20261 if(combine_attr_data->vlan_format_flags & 20262 _BCM_POLICER_VLAN_FORMAT_OUTER) { 20263 offset_array[loop][temp_count + 1] = (2 << shift_by_bits); 20264 temp_count++; 20265 } 20266 if(combine_attr_data->vlan_format_flags & 20267 _BCM_POLICER_VLAN_FORMAT_BOTH) { 20268 offset_array[loop][temp_count + 1] = (3 << shift_by_bits); 20269 temp_count++; 20270 } 20271 offset_array[loop][0] = temp_count; 20272 loop++; 20273 } 20274 if ((pkt_attr_selectors->outer_dot1p == 1) && 20275 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20276 shift_by_bits = inner_dot1p_bits + 20277 ing_port_bits + 20278 tos_dscp_bits + 20279 tos_ecn_bits + 20280 pkt_res_bits + 20281 svp_type_bits + 20282 drop_bits + 20283 ip_pkt_bits; 20284 temp_count = offset_array[loop][0]; 20285 for(index0 = _BCM_POLICER_PKT_PRI0; 20286 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 20287 if (combine_attr_data->outer_dot1p_flags & (1 << index0)) { 20288 offset_array[loop][temp_count + 1] = (index0 << shift_by_bits); 20289 temp_count++; 20290 } 20291 } 20292 offset_array[loop][0] = temp_count; 20293 loop++; 20294 } 20295 if ((pkt_attr_selectors->inner_dot1p == 1) && 20296 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20297 shift_by_bits = ing_port_bits + 20298 tos_dscp_bits + 20299 tos_ecn_bits + 20300 pkt_res_bits + 20301 svp_type_bits + 20302 drop_bits + 20303 ip_pkt_bits; 20304 temp_count = offset_array[loop][0]; 20305 for(index0 = _BCM_POLICER_PKT_PRI0; 20306 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 20307 if (combine_attr_data->inner_dot1p_flags & (1 << index0)) { 20308 offset_array[loop][temp_count + 1] = (index0 << shift_by_bits); 20309 temp_count++; 20310 } 20311 } 20312 offset_array[loop][0] = temp_count; 20313 loop++; 20314 } 20315 if ((pkt_attr_selectors->port == 1) && 20316 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20317 shift_by_bits = tos_dscp_bits + 20318 tos_ecn_bits + 20319 pkt_res_bits + 20320 svp_type_bits + 20321 drop_bits + 20322 ip_pkt_bits; 20323 ing_port_attrs = soc_mem_index_max(unit, ING_SVM_PORT_MAPm) + 1; 20324 for (index0 = 0; index0 < ing_port_attrs; index0++) { 20325 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 20326 value_array[_bcmPolicerAttrPort], index0)) { 20327 temp_count = offset_array[loop][0]; 20328 offset_array[loop][temp_count + 1] = index0 << shift_by_bits; 20329 offset_array[loop][0] = temp_count + 1; 20330 } 20331 } 20332 loop++; 20333 } 20334 if ((pkt_attr_selectors->tos_dscp == 1) && 20335 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20336 shift_by_bits = tos_ecn_bits + 20337 pkt_res_bits + 20338 svp_type_bits + 20339 drop_bits + 20340 ip_pkt_bits; 20341 tos_dscp_attrs = 1 << tos_dscp_bits; 20342 for (index0 = 0; index0 < tos_dscp_attrs; index0++) { 20343 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 20344 value_array[_bcmPolicerAttrTosDscp], index0)) { 20345 temp_count = offset_array[loop][0]; 20346 offset_array[loop][temp_count + 1] = index0 << shift_by_bits; 20347 offset_array[loop][0] = temp_count + 1; 20348 } 20349 } 20350 loop++; 20351 } 20352 if ((pkt_attr_selectors->tos_ecn == 1) && 20353 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20354 shift_by_bits = pkt_res_bits + 20355 svp_type_bits + 20356 drop_bits + 20357 ip_pkt_bits; 20358 tos_ecn_attrs = 1 << tos_ecn_bits; 20359 for (index0 = 0; index0 < tos_ecn_attrs; index0++) { 20360 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 20361 value_array[_bcmPolicerAttrTosEcn], index0)) { 20362 temp_count = offset_array[loop][0]; 20363 offset_array[loop][temp_count + 1] = index0 << shift_by_bits; 20364 offset_array[loop][0] = temp_count + 1; 20365 } 20366 } 20367 loop++; 20368 } 20369 if ((pkt_attr_selectors->pkt_resolution == 1) && 20370 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20371 shift_by_bits = svp_type_bits + 20372 drop_bits + 20373 ip_pkt_bits; 20374 temp_count = offset_array[loop][0]; 20375 if (combine_attr_data->pkt_resolution_flags & 20376 _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) { 20377 offset_array[loop][temp_count + 1] = 20378 (pkt_res[UNKNOWN_PKT] << shift_by_bits); 20379 temp_count++; 20380 } 20381 if (combine_attr_data->pkt_resolution_flags & 20382 _BCM_POLICER_PKT_TYPE_CONTROL_PKT) { 20383 offset_array[loop][temp_count + 1] = 20384 (pkt_res[CONTROL_PKT] << shift_by_bits); 20385 temp_count++; 20386 } 20387 if (combine_attr_data->pkt_resolution_flags & 20388 _BCM_POLICER_PKT_TYPE_OAM_PKT) { 20389 offset_array[loop][temp_count + 1] = 20390 (pkt_res[OAM_PKT] << shift_by_bits); 20391 temp_count++; 20392 } 20393 if (combine_attr_data->pkt_resolution_flags & 20394 _BCM_POLICER_PKT_TYPE_BFD_PKT) { 20395 offset_array[loop][temp_count + 1] = 20396 (pkt_res[BFD_PKT] << shift_by_bits); 20397 temp_count++; 20398 } 20399 if (combine_attr_data->pkt_resolution_flags & 20400 _BCM_POLICER_PKT_TYPE_BPDU_PKT) { 20401 offset_array[loop][temp_count + 1] = 20402 (pkt_res[BPDU_PKT] << shift_by_bits); 20403 temp_count++; 20404 } 20405 if (combine_attr_data->pkt_resolution_flags & 20406 _BCM_POLICER_PKT_TYPE_ICNM_PKT) { 20407 offset_array[loop][temp_count + 1] = 20408 (pkt_res[ICNM_PKT] << shift_by_bits); 20409 temp_count++; 20410 } 20411 if (combine_attr_data->pkt_resolution_flags & 20412 _BCM_POLICER_PKT_TYPE_PKT_IS_1588) { 20413 offset_array[loop][temp_count + 1] = 20414 (pkt_res[PKT_IS_1588] << shift_by_bits); 20415 temp_count++; 20416 } 20417 if (combine_attr_data->pkt_resolution_flags & 20418 _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) { 20419 offset_array[loop][temp_count + 1] = 20420 (pkt_res[KNOWN_L2UC_PKT] << shift_by_bits); 20421 temp_count++; 20422 } 20423 if (combine_attr_data->pkt_resolution_flags & 20424 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) { 20425 offset_array[loop][temp_count + 1] = 20426 (pkt_res[UNKNOWN_L2UC_PKT] << shift_by_bits); 20427 temp_count++; 20428 } 20429 if (combine_attr_data->pkt_resolution_flags & 20430 _BCM_POLICER_PKT_TYPE_L2BC_PKT) { 20431 offset_array[loop][temp_count + 1] = 20432 (pkt_res[L2BC_PKT] << shift_by_bits); 20433 temp_count++; 20434 } 20435 if (combine_attr_data->pkt_resolution_flags & 20436 _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) { 20437 offset_array[loop][temp_count + 1] = 20438 (pkt_res[KNOWN_L2MC_PKT] << shift_by_bits); 20439 temp_count++; 20440 } 20441 if (combine_attr_data->pkt_resolution_flags & 20442 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) { 20443 offset_array[loop][temp_count + 1] = 20444 (pkt_res[UNKNOWN_L2MC_PKT] << shift_by_bits); 20445 temp_count++; 20446 } 20447 if (combine_attr_data->pkt_resolution_flags & 20448 _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) { 20449 offset_array[loop][temp_count + 1] = 20450 (pkt_res[KNOWN_L3UC_PKT] << shift_by_bits); 20451 temp_count++; 20452 } 20453 if (combine_attr_data->pkt_resolution_flags & 20454 _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) { 20455 offset_array[loop][temp_count + 1] = 20456 (pkt_res[UNKNOWN_L3UC_PKT] << shift_by_bits); 20457 temp_count++; 20458 } 20459 if (combine_attr_data->pkt_resolution_flags & 20460 _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) { 20461 offset_array[loop][temp_count + 1] = 20462 (pkt_res[KNOWN_IPMC_PKT] << shift_by_bits); 20463 temp_count++; 20464 } 20465 if (combine_attr_data->pkt_resolution_flags & 20466 _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) { 20467 offset_array[loop][temp_count + 1] = 20468 (pkt_res[UNKNOWN_IPMC_PKT] << shift_by_bits); 20469 temp_count++; 20470 } 20471 if (combine_attr_data->pkt_resolution_flags & 20472 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) { 20473 offset_array[loop][temp_count + 1] = 20474 (pkt_res[KNOWN_MPLS_L2_PKT] << shift_by_bits); 20475 temp_count++; 20476 } 20477 if (combine_attr_data->pkt_resolution_flags & 20478 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) { 20479 offset_array[loop][temp_count + 1] = 20480 (pkt_res[KNOWN_MPLS_L3_PKT] << shift_by_bits); 20481 temp_count++; 20482 } 20483 if (combine_attr_data->pkt_resolution_flags & 20484 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) { 20485 offset_array[loop][temp_count + 1] = 20486 (pkt_res[KNOWN_MPLS_PKT] << shift_by_bits); 20487 temp_count++; 20488 } 20489 if (combine_attr_data->pkt_resolution_flags & 20490 _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) { 20491 offset_array[loop][temp_count + 1] = 20492 (pkt_res[UNKNOWN_MPLS_PKT] << shift_by_bits); 20493 temp_count++; 20494 } 20495 if (combine_attr_data->pkt_resolution_flags & 20496 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) { 20497 offset_array[loop][temp_count + 1] = 20498 (pkt_res[KNOWN_MPLS_MULTICAST_PKT] << shift_by_bits); 20499 temp_count++; 20500 } 20501 if (combine_attr_data->pkt_resolution_flags & 20502 _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) { 20503 offset_array[loop][temp_count + 1] = 20504 (pkt_res[KNOWN_MIM_PKT] << shift_by_bits); 20505 temp_count++; 20506 } 20507 if (combine_attr_data->pkt_resolution_flags & 20508 _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) { 20509 offset_array[loop][temp_count + 1] = 20510 (pkt_res[UNKNOWN_MIM_PKT] << shift_by_bits); 20511 temp_count++; 20512 } 20513 if (combine_attr_data->pkt_resolution_flags & 20514 _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) { 20515 offset_array[loop][temp_count + 1] = 20516 (pkt_res[KNOWN_TRILL_PKT] << shift_by_bits); 20517 temp_count++; 20518 } 20519 if (combine_attr_data->pkt_resolution_flags & 20520 _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) { 20521 offset_array[loop][temp_count + 1] = 20522 (pkt_res[UNKNOWN_TRILL_PKT] << shift_by_bits); 20523 temp_count++; 20524 } 20525 if (combine_attr_data->pkt_resolution_flags & 20526 _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) { 20527 offset_array[loop][temp_count + 1] = 20528 (pkt_res[KNOWN_NIV_PKT] << shift_by_bits); 20529 temp_count++; 20530 } 20531 if (combine_attr_data->pkt_resolution_flags & 20532 _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) { 20533 offset_array[loop][temp_count + 1] = 20534 (pkt_res[UNKNOWN_NIV_PKT] << shift_by_bits); 20535 temp_count++; 20536 } 20537 offset_array[loop][0] = temp_count; 20538 loop++; 20539 } 20540 if ((pkt_attr_selectors->svp_type == 1) && 20541 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20542 shift_by_bits = drop_bits + 20543 ip_pkt_bits; 20544 svp_type_attrs = 1 << svp_type_bits; 20545 for (index0 = 0; index0 < svp_type_attrs; index0++) { 20546 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 20547 value_array[_bcmPolicerAttrSvpType], index0)) { 20548 temp_count = offset_array[loop][0]; 20549 offset_array[loop][temp_count + 1] = index0 << 20550 shift_by_bits; 20551 offset_array[loop][0] = temp_count + 1; 20552 } 20553 } 20554 loop++; 20555 } 20556 if ((pkt_attr_selectors->drop == 1) && 20557 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20558 shift_by_bits = ip_pkt_bits; 20559 temp_count = offset_array[loop][0]; 20560 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_DISABLE) { 20561 offset_array[loop][temp_count + 1] = (0 << shift_by_bits); 20562 temp_count++; 20563 } 20564 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_ENABLE) { 20565 offset_array[loop][temp_count + 1] = (1 << shift_by_bits); 20566 temp_count++; 20567 } 20568 offset_array[loop][0] = temp_count; 20569 loop++; 20570 } 20571 if ((pkt_attr_selectors->ip_pkt == 1) && 20572 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 20573 shift_by_bits = 0; 20574 temp_count = offset_array[loop][0]; 20575 if (combine_attr_data->ip_pkt_flags & 20576 _BCM_POLICER_IP_PKT_DISABLE) { 20577 offset_array[loop][temp_count + 1] = (0 << shift_by_bits); 20578 temp_count++; 20579 } 20580 if (combine_attr_data->ip_pkt_flags & 20581 _BCM_POLICER_IP_PKT_ENABLE) { 20582 offset_array[loop][temp_count + 1] = (1 << shift_by_bits); 20583 temp_count++; 20584 } 20585 offset_array[loop][0] = temp_count; 20586 loop++; 20587 } 20588 20589 /* Step 2.3 : compute final offset value */ 20590 rv = _bcm_policer_group_mode_offset_map_generate(unit, 20591 meter_attr, group_mode, pol_offset, offset_array); 20592 if (rv != BCM_E_NONE) { 20593 break; 20594 } 20595 } 20596 } else { 20597 /* Mode : Compressed */ 20598 meter_attr->mode_type_v = compressed_mode; 20599 cmprsd_attr_selectors = &(meter_attr->compressed_attr_selectors_v); 20600 20601 cng_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20602 unit, pkt_attr_cng); 20603 20604 int_pri_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20605 unit, pkt_attr_int_pri); 20606 20607 vlan_format_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20608 unit, pkt_attr_vlan_format); 20609 20610 outer_dot1p_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20611 unit, pkt_attr_outer_dot1p); 20612 20613 inner_dot1p_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20614 unit, pkt_attr_inner_dot1p); 20615 20616 tos_dscp_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20617 unit, pkt_attr_tos); 20618 tos_dscp_attrs = 1 << tos_dscp_bits; 20619 20620 tos_ecn_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20621 unit, pkt_attr_tos_ecn); 20622 tos_ecn_attrs = 1 << tos_ecn_bits; 20623 20624 pkt_res_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20625 unit, pkt_attr_pkt_resolution); 20626 20627 svp_type_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20628 unit, pkt_attr_svp_group); 20629 svp_type_attrs = 1 << svp_type_bits; 20630 20631 drop_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20632 unit, pkt_attr_drop); 20633 20634 ip_pkt_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get(unit, 20635 pkt_attr_ip_pkt); 20636 20637 ing_port_bits = _bcm_policer_svm_cmprsd_pkt_attr_bits_get( 20638 unit, pkt_attr_ing_port); 20639 /* Number of port is device dependent. So, get the size from h/w */ 20640 ing_port_attrs = soc_mem_index_max(unit, ING_SVM_PORT_MAPm) + 1; 20641 20642 cmprsd_pkt_attr_bit_pos = 20643 BCM_SVM_DEV_ATTR(unit)->compressed_pkt_attr_bit_pos; 20644 20645 /* 20646 * If compression tables sharing is supported, match packet 20647 * attributes and it corresponding values to global compression maps. 20648 */ 20649 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 20650 rv = _bcm_esw_svm_pkt_compressed_attr_maps_validate(unit, 20651 pkt_attr_selectors); 20652 if (BCM_FAILURE(rv)) { 20653 sal_free(meter_attr); 20654 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Sharing of" 20655 " Compression tables are not possible" 20656 " with given input attribute selectors\n"))); 20657 return rv; 20658 } 20659 } 20660 20661 sal_memset(map_array, 0, sizeof(uint8 *) * bcmPolicerGroupModeAttrCount); 20662 20663 /* Step 1 : Create a separate map for each attribute type */ 20664 /* 0XFF means that index is not in use */ 20665 if (pkt_attr_selectors->cng == 1) { 20666 _GLOBAL_METER_XGS3_ALLOC( 20667 map_array[bcmPolicerGroupModeAttrFieldIngressColor], 20668 256 + 1, "cng map_array values"); 20669 20670 sal_memset(map_array[bcmPolicerGroupModeAttrFieldIngressColor], 20671 0xFF, 256); 20672 temp_count = 0; 20673 if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_GREEN) { 20674 map_array[bcmPolicerGroupModeAttrFieldIngressColor][0] = temp_count; 20675 temp_count++; 20676 } 20677 if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_YELLOW) { 20678 map_array[bcmPolicerGroupModeAttrFieldIngressColor][1] = temp_count; 20679 temp_count++; 20680 } 20681 if (pkt_attr_selectors->combine_cng_flags & _BCM_POLICER_COLOR_RED) { 20682 map_array[bcmPolicerGroupModeAttrFieldIngressColor][3] = temp_count; 20683 temp_count++; 20684 } 20685 map_array[bcmPolicerGroupModeAttrFieldIngressColor][256] = temp_count; 20686 } 20687 if (pkt_attr_selectors->int_pri == 1) { 20688 _GLOBAL_METER_XGS3_ALLOC( 20689 map_array[bcmPolicerGroupModeAttrIntPri], 20690 256 + 1, "int_pri map_array values"); 20691 20692 sal_memset(map_array[bcmPolicerGroupModeAttrIntPri], 20693 0xFF, 256); 20694 temp_count = 0; 20695 for (index0 = _BCM_POLICER_PKT_PRI0; 20696 index0 <= _BCM_POLICER_PKT_PRI15; index0++) { 20697 if (pkt_attr_selectors->combine_int_pri_flags & (1 << index0)) { 20698 map_array[bcmPolicerGroupModeAttrIntPri][index0] = temp_count; 20699 temp_count++; 20700 } 20701 } 20702 map_array[bcmPolicerGroupModeAttrIntPri][256] = temp_count; 20703 } 20704 if (pkt_attr_selectors->vlan_format == 1) { 20705 _GLOBAL_METER_XGS3_ALLOC( 20706 map_array[bcmPolicerGroupModeAttrVlan], 20707 256 + 1, "vlan_format map_array values"); 20708 20709 sal_memset(map_array[bcmPolicerGroupModeAttrVlan], 20710 0xFF, 256); 20711 temp_count = 0; 20712 if(pkt_attr_selectors->combine_vlan_format_flags & 20713 _BCM_POLICER_VLAN_FORMAT_UNTAGGED) { 20714 map_array[bcmPolicerGroupModeAttrVlan][0] = temp_count; 20715 temp_count++; 20716 } 20717 if(pkt_attr_selectors->combine_vlan_format_flags & 20718 _BCM_POLICER_VLAN_FORMAT_INNER) { 20719 map_array[bcmPolicerGroupModeAttrVlan][1] = temp_count; 20720 temp_count++; 20721 } 20722 if(pkt_attr_selectors->combine_vlan_format_flags & 20723 _BCM_POLICER_VLAN_FORMAT_OUTER) { 20724 map_array[bcmPolicerGroupModeAttrVlan][2] = temp_count; 20725 temp_count++; 20726 } 20727 if(pkt_attr_selectors->combine_vlan_format_flags & 20728 _BCM_POLICER_VLAN_FORMAT_BOTH) { 20729 map_array[bcmPolicerGroupModeAttrVlan][3] = temp_count; 20730 temp_count++; 20731 } 20732 map_array[bcmPolicerGroupModeAttrVlan][256] = temp_count; 20733 } 20734 if (pkt_attr_selectors->outer_dot1p == 1) { 20735 _GLOBAL_METER_XGS3_ALLOC( 20736 map_array[bcmPolicerGroupModeAttrOuterPri], 20737 256 + 1, "outer_dot1p map_array values"); 20738 20739 sal_memset(map_array[bcmPolicerGroupModeAttrOuterPri], 20740 0xFF, 256); 20741 temp_count = 0; 20742 for (index0 = _BCM_POLICER_PKT_PRI0; 20743 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 20744 if (pkt_attr_selectors->combine_outer_dot1p_flags & (1 << index0)) { 20745 map_array[bcmPolicerGroupModeAttrOuterPri][index0] = temp_count; 20746 temp_count++; 20747 } 20748 } 20749 map_array[bcmPolicerGroupModeAttrOuterPri][256] = temp_count; 20750 } 20751 if (pkt_attr_selectors->inner_dot1p == 1) { 20752 _GLOBAL_METER_XGS3_ALLOC( 20753 map_array[bcmPolicerGroupModeAttrInnerPri], 20754 256 + 1, "inner_dot1p map_array values"); 20755 20756 sal_memset(map_array[bcmPolicerGroupModeAttrInnerPri], 20757 0xFF, 256); 20758 temp_count = 0; 20759 for (index0 = _BCM_POLICER_PKT_PRI0; 20760 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 20761 if (pkt_attr_selectors->combine_inner_dot1p_flags & (1 << index0)) { 20762 map_array[bcmPolicerGroupModeAttrInnerPri][index0] = temp_count; 20763 temp_count++; 20764 } 20765 } 20766 map_array[bcmPolicerGroupModeAttrInnerPri][256] = temp_count; 20767 } 20768 if (pkt_attr_selectors->port == 1) { 20769 _GLOBAL_METER_XGS3_ALLOC( 20770 map_array[bcmPolicerGroupModeAttrPort], 20771 256 + 1, "port map_array values"); 20772 20773 sal_memset(map_array[bcmPolicerGroupModeAttrPort], 20774 0xFF, 256); 20775 temp_count = 0; 20776 for (value = 0; value < ing_port_attrs; value++) { 20777 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors-> 20778 combine_value_array[_bcmPolicerAttrPort], value)) { 20779 map_array[bcmPolicerGroupModeAttrPort][value] = temp_count; 20780 temp_count++; 20781 } 20782 } 20783 map_array[bcmPolicerGroupModeAttrPort][256] = temp_count; 20784 } 20785 if (pkt_attr_selectors->tos_dscp == 1) { 20786 _GLOBAL_METER_XGS3_ALLOC( 20787 map_array[bcmPolicerGroupModeAttrTosDscp], 20788 256 + 1, "tos_dscp map_array values"); 20789 20790 sal_memset(map_array[bcmPolicerGroupModeAttrTosDscp], 20791 0xFF, 256); 20792 temp_count = 0; 20793 for (value = 0; value < tos_dscp_attrs; value++) { 20794 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors-> 20795 combine_value_array[_bcmPolicerAttrTosDscp], value)) { 20796 map_array[bcmPolicerGroupModeAttrTosDscp][value] = temp_count; 20797 temp_count++; 20798 } 20799 } 20800 map_array[bcmPolicerGroupModeAttrTosDscp][256] = temp_count; 20801 } 20802 if (pkt_attr_selectors->tos_ecn == 1) { 20803 _GLOBAL_METER_XGS3_ALLOC( 20804 map_array[bcmPolicerGroupModeAttrTosEcn], 20805 256 + 1, "tos_ecn map_array values"); 20806 20807 sal_memset(map_array[bcmPolicerGroupModeAttrTosEcn], 20808 0xFF, 256); 20809 temp_count = 0; 20810 for (value = 0; value < tos_ecn_attrs; value++) { 20811 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors-> 20812 combine_value_array[_bcmPolicerAttrTosEcn], value)) { 20813 map_array[bcmPolicerGroupModeAttrTosEcn][value] = temp_count; 20814 temp_count++; 20815 } 20816 } 20817 map_array[bcmPolicerGroupModeAttrTosEcn][256] = temp_count; 20818 } 20819 if (pkt_attr_selectors->pkt_resolution == 1) { 20820 _GLOBAL_METER_XGS3_ALLOC( 20821 map_array[bcmPolicerGroupModeAttrPktType], 20822 256 + 1, "pkt_res map_array values"); 20823 20824 sal_memset(map_array[bcmPolicerGroupModeAttrPktType], 20825 0xFF, 256); 20826 temp_count = 0; 20827 if (pkt_attr_selectors->combine_pkt_res_flags & 20828 _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) { 20829 map_array[bcmPolicerGroupModeAttrPktType] 20830 [pkt_res[UNKNOWN_PKT]] = temp_count; 20831 temp_count++; 20832 } 20833 if (pkt_attr_selectors->combine_pkt_res_flags & 20834 _BCM_POLICER_PKT_TYPE_CONTROL_PKT) { 20835 map_array[bcmPolicerGroupModeAttrPktType] 20836 [pkt_res[CONTROL_PKT]] = temp_count; 20837 temp_count++; 20838 } 20839 if (pkt_attr_selectors->combine_pkt_res_flags & 20840 _BCM_POLICER_PKT_TYPE_OAM_PKT) { 20841 map_array[bcmPolicerGroupModeAttrPktType] 20842 [pkt_res[OAM_PKT]] = temp_count; 20843 temp_count++; 20844 } 20845 if (pkt_attr_selectors->combine_pkt_res_flags & 20846 _BCM_POLICER_PKT_TYPE_BFD_PKT) { 20847 map_array[bcmPolicerGroupModeAttrPktType] 20848 [pkt_res[BFD_PKT]] = temp_count; 20849 temp_count++; 20850 } 20851 if (pkt_attr_selectors->combine_pkt_res_flags & 20852 _BCM_POLICER_PKT_TYPE_BPDU_PKT) { 20853 map_array[bcmPolicerGroupModeAttrPktType] 20854 [pkt_res[BPDU_PKT]] = temp_count; 20855 temp_count++; 20856 } 20857 if (pkt_attr_selectors->combine_pkt_res_flags & 20858 _BCM_POLICER_PKT_TYPE_ICNM_PKT) { 20859 map_array[bcmPolicerGroupModeAttrPktType] 20860 [pkt_res[ICNM_PKT]] = temp_count; 20861 temp_count++; 20862 } 20863 if (pkt_attr_selectors->combine_pkt_res_flags & 20864 _BCM_POLICER_PKT_TYPE_PKT_IS_1588) { 20865 map_array[bcmPolicerGroupModeAttrPktType] 20866 [pkt_res[PKT_IS_1588]] = temp_count; 20867 temp_count++; 20868 } 20869 if (pkt_attr_selectors->combine_pkt_res_flags & 20870 _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) { 20871 map_array[bcmPolicerGroupModeAttrPktType] 20872 [pkt_res[KNOWN_L2UC_PKT]] = temp_count; 20873 temp_count++; 20874 } 20875 if (pkt_attr_selectors->combine_pkt_res_flags & 20876 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) { 20877 map_array[bcmPolicerGroupModeAttrPktType] 20878 [pkt_res[UNKNOWN_L2UC_PKT]] = temp_count; 20879 temp_count++; 20880 } 20881 if (pkt_attr_selectors->combine_pkt_res_flags & 20882 _BCM_POLICER_PKT_TYPE_L2BC_PKT) { 20883 map_array[bcmPolicerGroupModeAttrPktType] 20884 [pkt_res[L2BC_PKT]] = temp_count; 20885 temp_count++; 20886 } 20887 if (pkt_attr_selectors->combine_pkt_res_flags & 20888 _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) { 20889 map_array[bcmPolicerGroupModeAttrPktType] 20890 [pkt_res[KNOWN_L2MC_PKT]] = temp_count; 20891 temp_count++; 20892 } 20893 if (pkt_attr_selectors->combine_pkt_res_flags & 20894 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) { 20895 map_array[bcmPolicerGroupModeAttrPktType] 20896 [pkt_res[UNKNOWN_L2MC_PKT]] = temp_count; 20897 temp_count++; 20898 } 20899 if (pkt_attr_selectors->combine_pkt_res_flags & 20900 _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) { 20901 map_array[bcmPolicerGroupModeAttrPktType] 20902 [pkt_res[KNOWN_L3UC_PKT]] = temp_count; 20903 temp_count++; 20904 } 20905 if (pkt_attr_selectors->combine_pkt_res_flags & 20906 _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) { 20907 map_array[bcmPolicerGroupModeAttrPktType] 20908 [pkt_res[UNKNOWN_L3UC_PKT]] = temp_count; 20909 temp_count++; 20910 } 20911 if (pkt_attr_selectors->combine_pkt_res_flags & 20912 _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) { 20913 map_array[bcmPolicerGroupModeAttrPktType] 20914 [pkt_res[KNOWN_IPMC_PKT]] = temp_count; 20915 temp_count++; 20916 } 20917 if (pkt_attr_selectors->combine_pkt_res_flags & 20918 _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) { 20919 map_array[bcmPolicerGroupModeAttrPktType] 20920 [pkt_res[UNKNOWN_IPMC_PKT]] = temp_count; 20921 temp_count++; 20922 } 20923 if (pkt_attr_selectors->combine_pkt_res_flags & 20924 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) { 20925 map_array[bcmPolicerGroupModeAttrPktType] 20926 [pkt_res[KNOWN_MPLS_L2_PKT]] = temp_count; 20927 temp_count++; 20928 } 20929 if (pkt_attr_selectors->combine_pkt_res_flags & 20930 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) { 20931 map_array[bcmPolicerGroupModeAttrPktType] 20932 [pkt_res[KNOWN_MPLS_L3_PKT]] = temp_count; 20933 temp_count++; 20934 } 20935 if (pkt_attr_selectors->combine_pkt_res_flags & 20936 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) { 20937 map_array[bcmPolicerGroupModeAttrPktType] 20938 [pkt_res[KNOWN_MPLS_PKT]] = temp_count; 20939 temp_count++; 20940 } 20941 if (pkt_attr_selectors->combine_pkt_res_flags & 20942 _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) { 20943 map_array[bcmPolicerGroupModeAttrPktType] 20944 [pkt_res[UNKNOWN_MPLS_PKT]] = temp_count; 20945 temp_count++; 20946 } 20947 if (pkt_attr_selectors->combine_pkt_res_flags & 20948 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) { 20949 map_array[bcmPolicerGroupModeAttrPktType] 20950 [pkt_res[KNOWN_MPLS_MULTICAST_PKT]] = temp_count; 20951 temp_count++; 20952 } 20953 if (pkt_attr_selectors->combine_pkt_res_flags & 20954 _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) { 20955 map_array[bcmPolicerGroupModeAttrPktType] 20956 [pkt_res[KNOWN_MIM_PKT]] = temp_count; 20957 temp_count++; 20958 } 20959 if (pkt_attr_selectors->combine_pkt_res_flags & 20960 _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) { 20961 map_array[bcmPolicerGroupModeAttrPktType] 20962 [pkt_res[UNKNOWN_MIM_PKT]] = temp_count; 20963 temp_count++; 20964 } 20965 if (pkt_attr_selectors->combine_pkt_res_flags & 20966 _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) { 20967 map_array[bcmPolicerGroupModeAttrPktType] 20968 [pkt_res[KNOWN_TRILL_PKT]] = temp_count; 20969 temp_count++; 20970 } 20971 if (pkt_attr_selectors->combine_pkt_res_flags & 20972 _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) { 20973 map_array[bcmPolicerGroupModeAttrPktType] 20974 [pkt_res[UNKNOWN_TRILL_PKT]] = temp_count; 20975 temp_count++; 20976 } 20977 if (pkt_attr_selectors->combine_pkt_res_flags & 20978 _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) { 20979 map_array[bcmPolicerGroupModeAttrPktType] 20980 [pkt_res[KNOWN_NIV_PKT]] = temp_count; 20981 temp_count++; 20982 } 20983 if (pkt_attr_selectors->combine_pkt_res_flags & 20984 _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) { 20985 map_array[bcmPolicerGroupModeAttrPktType] 20986 [pkt_res[UNKNOWN_NIV_PKT]] = temp_count; 20987 temp_count++; 20988 } 20989 map_array[bcmPolicerGroupModeAttrPktType][256] = temp_count; 20990 } 20991 if (pkt_attr_selectors->svp_type == 1) { 20992 _GLOBAL_METER_XGS3_ALLOC( 20993 map_array[bcmPolicerGroupModeAttrIngNetworkGroup], 20994 256 + 1, "svp_type map_array values"); 20995 20996 sal_memset(map_array[bcmPolicerGroupModeAttrIngNetworkGroup], 20997 0xFF, 256); 20998 temp_count = 0; 20999 for (value = 0; value < svp_type_attrs; value++) { 21000 if (_BCM_POLICER_VALUE_GET (pkt_attr_selectors-> 21001 combine_value_array[_bcmPolicerAttrSvpType], value)) { 21002 map_array[bcmPolicerGroupModeAttrIngNetworkGroup][value] = temp_count; 21003 temp_count++; 21004 } 21005 } 21006 map_array[bcmPolicerGroupModeAttrIngNetworkGroup][256] = temp_count; 21007 } 21008 if (pkt_attr_selectors->drop == 1) { 21009 _GLOBAL_METER_XGS3_ALLOC( 21010 map_array[bcmPolicerGroupModeAttrDrop], 21011 256 + 1, "drop map_array values"); 21012 21013 sal_memset(map_array[bcmPolicerGroupModeAttrDrop], 21014 0xFF, 256); 21015 temp_count = 0; 21016 if (pkt_attr_selectors->combine_drop_flags & _BCM_POLICER_DROP_DISABLE) { 21017 map_array[bcmPolicerGroupModeAttrDrop][0] = temp_count; 21018 temp_count++; 21019 } 21020 if (pkt_attr_selectors->combine_drop_flags & _BCM_POLICER_DROP_ENABLE) { 21021 map_array[bcmPolicerGroupModeAttrDrop][1] = temp_count; 21022 temp_count++; 21023 } 21024 map_array[bcmPolicerGroupModeAttrDrop][256] = temp_count; 21025 } 21026 if (pkt_attr_selectors->ip_pkt == 1) { 21027 _GLOBAL_METER_XGS3_ALLOC( 21028 map_array[bcmPolicerGroupModeAttrPacketTypeIp], 21029 256 + 1, "ip_pkt map_array values"); 21030 21031 sal_memset(map_array[bcmPolicerGroupModeAttrDrop], 21032 0xFF, 256); 21033 temp_count = 0; 21034 if (pkt_attr_selectors->combine_ip_pkt_flags & 21035 _BCM_POLICER_IP_PKT_DISABLE) { 21036 map_array[bcmPolicerGroupModeAttrPacketTypeIp][0] = temp_count; 21037 temp_count++; 21038 } 21039 if (pkt_attr_selectors->combine_ip_pkt_flags & 21040 _BCM_POLICER_IP_PKT_ENABLE) { 21041 map_array[bcmPolicerGroupModeAttrPacketTypeIp][1] = temp_count; 21042 temp_count++; 21043 } 21044 map_array[bcmPolicerGroupModeAttrPacketTypeIp][256] = temp_count; 21045 } 21046 21047 /* 21048 * Step 2: Calculate total bits required. 21049 * In service meter, compressed mode is handled via compression 21050 * hardware tables. These compression tables are mapped to one or 21051 * more packet attributes. 21052 * Total bits required for the compressed mode is calculated per 21053 * compression table (Logical groups). 21054 * For Each Logical Group, 21055 * 1. Based on number of attribute values per attribute belonging 21056 * to that logical group, required bits are calculated per 21057 * attribute. 21058 * 2. To represent invalid scenario, one more value is required per 21059 * logical group. For anyone of attribute in this logical group, 21060 * if the bits calculated can accomodate this extra value i.e 21061 * number formed by this many bits is more that number of values 21062 * required in that attribute, this extra value can be be used in 21063 * invalid scenario. 21064 * 3. If none of the attributes in this logical table have spare value 21065 * then increment in number of bits for one of the attibute is 21066 * required to represent invalid scenario. 21067 * 4. If bits for no attribute could be incremented, then no extra 21068 * value is required for the logical group as all indices 21069 * are valid. This scenario is highly unlikely. 21070 * 5. Total bits for the logical group is again compared with the 21071 * maximum number of bits that the compression table can support. 21072 * 21073 * If total bits calucated for all logical groups exceed 8, then we 21074 * cannot use even compressed mode. 21075 */ 21076 /* Logical Group-1 cng / int_pri */ 21077 if ((map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) || 21078 (map_array[bcmPolicerGroupModeAttrIntPri] != NULL)) { 21079 unused_found = FALSE; 21080 if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) { 21081 values = map_array[bcmPolicerGroupModeAttrFieldIngressColor][256]; 21082 cng_cmprsd_bits = _bcm_policer_num_of_bits_get(values); 21083 values_max = 1 << cng_cmprsd_bits; 21084 unused_found = (values < values_max) ? TRUE : unused_found; 21085 } 21086 if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) { 21087 values = map_array[bcmPolicerGroupModeAttrIntPri][256]; 21088 int_pri_cmprsd_bits = _bcm_policer_num_of_bits_get(values); 21089 values_max = 1 << int_pri_cmprsd_bits; 21090 unused_found = (values < values_max) ? TRUE : unused_found; 21091 } 21092 if (!unused_found) { 21093 if ((cng_cmprsd_bits != 0) && 21094 (cng_cmprsd_bits < cng_bits)) { 21095 cng_cmprsd_bits++; 21096 } else if ((int_pri_cmprsd_bits != 0) && 21097 (int_pri_cmprsd_bits < int_pri_bits)) { 21098 int_pri_cmprsd_bits++; 21099 } else { 21100 /* 21101 * All values are valid for each attribute in this 21102 * logical group. Hence, increment is not required. 21103 */ 21104 ; 21105 } 21106 } 21107 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21108 unit, pkt_attr_pri_cng_map); 21109 if (logical_group_bits < (cng_cmprsd_bits + int_pri_cmprsd_bits)) { 21110 rv = BCM_E_PARAM; 21111 } 21112 } 21113 21114 /* Logical Group-2 vlan format / outer_dot1p /inner_dot1p */ 21115 if ((map_array[bcmPolicerGroupModeAttrVlan] != NULL) || 21116 (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) || 21117 (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL)) { 21118 unused_found = FALSE; 21119 if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) { 21120 values = map_array[bcmPolicerGroupModeAttrVlan][256]; 21121 vlan_format_cmprsd_bits = 21122 _bcm_policer_num_of_bits_get(values); 21123 values_max = 1 << vlan_format_cmprsd_bits; 21124 unused_found = (values < values_max) ? TRUE : unused_found; 21125 } 21126 if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) { 21127 values = map_array[bcmPolicerGroupModeAttrOuterPri][256]; 21128 outer_dot1p_cmprsd_bits = 21129 _bcm_policer_num_of_bits_get(values); 21130 values_max = 1 << outer_dot1p_cmprsd_bits; 21131 unused_found = (values < values_max) ? TRUE : unused_found; 21132 } 21133 if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) { 21134 values = map_array[bcmPolicerGroupModeAttrInnerPri][256]; 21135 inner_dot1p_cmprsd_bits = 21136 _bcm_policer_num_of_bits_get(values); 21137 values_max = 1 << inner_dot1p_cmprsd_bits; 21138 unused_found = (values < values_max) ? TRUE : unused_found; 21139 } 21140 if (!unused_found) { 21141 if ((vlan_format_cmprsd_bits != 0) && 21142 (vlan_format_cmprsd_bits < vlan_format_bits)) { 21143 vlan_format_cmprsd_bits++; 21144 } else if ((outer_dot1p_cmprsd_bits != 0) && 21145 (outer_dot1p_cmprsd_bits < outer_dot1p_bits)) { 21146 outer_dot1p_cmprsd_bits++; 21147 } else if ((inner_dot1p_cmprsd_bits != 0) && 21148 (inner_dot1p_cmprsd_bits < inner_dot1p_bits)) { 21149 inner_dot1p_cmprsd_bits++; 21150 } else { 21151 /* 21152 * All values are valid for each attribute in this 21153 * logical group. Hence, increment is not required. 21154 */ 21155 ; 21156 } 21157 } 21158 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21159 unit, pkt_attr_pkt_pri_map); 21160 if (logical_group_bits < (vlan_format_cmprsd_bits + 21161 outer_dot1p_cmprsd_bits + inner_dot1p_cmprsd_bits)) { 21162 rv = BCM_E_PARAM; 21163 } 21164 } 21165 21166 /* Logical Group-3 port */ 21167 if (map_array[bcmPolicerGroupModeAttrPort] != NULL) { 21168 ing_port_cmprsd_bits = _bcm_policer_num_of_bits_get( 21169 map_array[bcmPolicerGroupModeAttrPort][256] + 1); 21170 if (ing_port_cmprsd_bits > ing_port_bits) { 21171 ing_port_cmprsd_bits = ing_port_bits; 21172 } 21173 } 21174 21175 /* Logical Group-4 tos_dscp / tos_ecn */ 21176 if ((map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) || 21177 (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL)) { 21178 unused_found = FALSE; 21179 if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) { 21180 values = map_array[bcmPolicerGroupModeAttrTosDscp][256]; 21181 tos_dscp_cmprsd_bits = 21182 _bcm_policer_num_of_bits_get(values); 21183 values_max = 1 << tos_dscp_cmprsd_bits; 21184 unused_found = (values < values_max) ? TRUE : unused_found; 21185 } 21186 if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) { 21187 values = map_array[bcmPolicerGroupModeAttrTosEcn][256]; 21188 tos_ecn_cmprsd_bits = 21189 _bcm_policer_num_of_bits_get(values); 21190 values_max = 1 << tos_ecn_cmprsd_bits; 21191 unused_found = (values < values_max) ? TRUE : unused_found; 21192 } 21193 if (!unused_found) { 21194 if ((tos_dscp_cmprsd_bits != 0) && 21195 (tos_dscp_cmprsd_bits < tos_dscp_bits)) { 21196 tos_dscp_cmprsd_bits++; 21197 } else if ((tos_ecn_cmprsd_bits != 0) && 21198 (tos_ecn_cmprsd_bits < tos_ecn_bits)) { 21199 tos_ecn_cmprsd_bits++; 21200 } else { 21201 /* 21202 * All values are valid for each attribute in this 21203 * logical group. Hence, increment is not required. 21204 */ 21205 ; 21206 } 21207 } 21208 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21209 unit, pkt_attr_tos_map); 21210 if (logical_group_bits < (tos_dscp_cmprsd_bits + 21211 tos_ecn_cmprsd_bits)) { 21212 rv = BCM_E_PARAM; 21213 } 21214 } 21215 21216 /* Logical Group-5 pkt_resolution / network group(svp type) / drop */ 21217 if ((map_array[bcmPolicerGroupModeAttrPktType] != NULL) || 21218 (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) || 21219 (map_array[bcmPolicerGroupModeAttrDrop] != NULL)) { 21220 unused_found = FALSE; 21221 if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) { 21222 values = map_array[bcmPolicerGroupModeAttrPktType][256]; 21223 pkt_res_cmprsd_bits = 21224 _bcm_policer_num_of_bits_get(values); 21225 values_max = 1 << pkt_res_cmprsd_bits; 21226 unused_found = (values < values_max) ? TRUE : unused_found; 21227 } 21228 if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) { 21229 values = map_array[bcmPolicerGroupModeAttrIngNetworkGroup][256]; 21230 svp_type_cmprsd_bits = 21231 _bcm_policer_num_of_bits_get(values); 21232 values_max = 1 << svp_type_cmprsd_bits; 21233 unused_found = (values < values_max) ? TRUE : unused_found; 21234 } 21235 if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) { 21236 values = map_array[bcmPolicerGroupModeAttrDrop][256]; 21237 drop_cmprsd_bits = 21238 _bcm_policer_num_of_bits_get(values); 21239 values_max = 1 << drop_cmprsd_bits; 21240 unused_found = (values < values_max) ? TRUE : unused_found; 21241 } 21242 if (!unused_found) { 21243 if ((pkt_res_cmprsd_bits != 0) && 21244 (pkt_res_cmprsd_bits < pkt_res_bits)) { 21245 pkt_res_cmprsd_bits++; 21246 } else if ((svp_type_cmprsd_bits != 0) && 21247 (svp_type_cmprsd_bits < svp_type_bits)) { 21248 svp_type_cmprsd_bits++; 21249 } else if ((drop_cmprsd_bits != 0) && 21250 (drop_cmprsd_bits < drop_bits)) { 21251 drop_cmprsd_bits++; 21252 } else { 21253 /* 21254 * All values are valid for each attribute in this 21255 * logical group. Hence, increment is not required. 21256 */ 21257 ; 21258 } 21259 } 21260 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21261 unit, pkt_attr_pkt_res_map); 21262 if (logical_group_bits < (pkt_res_cmprsd_bits + 21263 svp_type_cmprsd_bits + drop_cmprsd_bits)) { 21264 rv = BCM_E_PARAM; 21265 } 21266 } 21267 21268 if (map_array[bcmPolicerGroupModeAttrPacketTypeIp] != NULL) { 21269 ip_pkt_cmprsd_bits = _bcm_policer_num_of_bits_get( 21270 map_array[bcmPolicerGroupModeAttrPacketTypeIp][256]); 21271 if (ip_pkt_cmprsd_bits > ip_pkt_bits) { 21272 ip_pkt_cmprsd_bits = ip_pkt_cmprsd_bits; 21273 } 21274 } 21275 21276 total_bits = cng_cmprsd_bits + int_pri_cmprsd_bits + 21277 vlan_format_cmprsd_bits + outer_dot1p_cmprsd_bits + 21278 inner_dot1p_cmprsd_bits + ing_port_cmprsd_bits + 21279 tos_dscp_cmprsd_bits + tos_ecn_cmprsd_bits + 21280 pkt_res_cmprsd_bits + svp_type_cmprsd_bits + 21281 drop_cmprsd_bits + ip_pkt_cmprsd_bits; 21282 21283 if (total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 21284 /* Free map_array */ 21285 for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) { 21286 if (map_array[loop] != NULL) { 21287 sal_free(map_array[loop]); 21288 } 21289 } 21290 sal_free(meter_attr); 21291 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Number of bits" 21292 " required is more than 8 even for compressed mode\n"))); 21293 return BCM_E_PARAM; 21294 } 21295 21296 /* 21297 * Step 3 : Filling up Logical Groups 21298 * For Each Logical Group, 21299 * 1. Loop though each value of all attributes 21300 * 2. If value is not part of attribute selector, all indices formed 21301 * for that attribute value is marked as Invalid. 21302 * 3. Invalid value is derived by setting all bits to 1. 21303 * 4. Else, final value at the index is calculated via left shift 21304 * operation on values present in map_aray[] and number of 21305 * bits required. 21306 */ 21307 /* Logical Group-1 cng / int_pri */ 21308 if ((pkt_attr_selectors->cng == 1) || 21309 (pkt_attr_selectors->int_pri == 1)) { 21310 if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) { 21311 max_bits = cng_cmprsd_bits; 21312 cmprsd_attr_selectors->pkt_attr_bits_v.cng = max_bits; 21313 cmprsd_attr_selectors->pkt_attr_bits_v.cng_mask = 21314 (1 << max_bits) - 1; 21315 cmprsd_attr_selectors->pkt_attr_bits_v.cng_pos = 21316 cmprsd_pkt_attr_bit_pos[pkt_attr_cng].start_bit; 21317 } 21318 if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) { 21319 max_bits = int_pri_cmprsd_bits; 21320 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri = max_bits; 21321 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri_mask = 21322 (1 << max_bits) - 1; 21323 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri_pos = 21324 cmprsd_pkt_attr_bit_pos[pkt_attr_int_pri].start_bit; 21325 } 21326 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21327 unit, pkt_attr_pri_cng_map); 21328 invalid_map_value = (1 << logical_group_bits) - 1; 21329 21330 mapped_value0 = mapped_value1 = 0; 21331 for (index0 = 0; index0 < (1 << cng_bits); index0++) { 21332 invalid_index0 = FALSE; 21333 if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] != NULL) { 21334 if (map_array[bcmPolicerGroupModeAttrFieldIngressColor] 21335 [index0] == 0xFF) { 21336 invalid_index0 = TRUE; 21337 } else { 21338 mapped_value0 = map_array 21339 [bcmPolicerGroupModeAttrFieldIngressColor][index0]; 21340 } 21341 } 21342 for (index1 = 0; index1 < (1 << int_pri_bits); index1++) { 21343 invalid_index1 = FALSE; 21344 if (map_array[bcmPolicerGroupModeAttrIntPri] != NULL) { 21345 if (map_array[bcmPolicerGroupModeAttrIntPri] 21346 [index1] == 0xFF) { 21347 invalid_index1 = TRUE; 21348 } else { 21349 mapped_value1 = map_array 21350 [bcmPolicerGroupModeAttrIntPri][index1]; 21351 } 21352 } 21353 final_index = (index0 << int_pri_bits) + index1; 21354 if (invalid_index0 || invalid_index1) { 21355 final_mapped_value = invalid_map_value; 21356 } else if (soc_feature(unit, 21357 soc_feature_global_meter_compression_share)) { 21358 final_mapped_value = (mapped_value0 << int_pri_bits) + 21359 mapped_value1; 21360 } else { 21361 final_mapped_value = 21362 (mapped_value0 << int_pri_cmprsd_bits) + 21363 mapped_value1; 21364 } 21365 cmprsd_attr_selectors->compressed_pri_cnf_attr_map_v 21366 [final_index] = final_mapped_value; 21367 } 21368 } 21369 } 21370 21371 /* Logical Group-2 vlan format / outer_dot1p /inner_dot1p */ 21372 if ((pkt_attr_selectors->vlan_format == 1) || 21373 (pkt_attr_selectors->outer_dot1p == 1) || 21374 (pkt_attr_selectors->inner_dot1p == 1)) { 21375 if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) { 21376 max_bits = vlan_format_cmprsd_bits; 21377 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format = max_bits; 21378 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format_mask = 21379 (1 << max_bits) - 1; 21380 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format_pos = 21381 cmprsd_pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit; 21382 } 21383 if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) { 21384 max_bits = outer_dot1p_cmprsd_bits; 21385 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p = max_bits; 21386 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p_mask = 21387 (1 << max_bits) - 1; 21388 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p_pos = 21389 cmprsd_pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit; 21390 } 21391 if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) { 21392 max_bits = inner_dot1p_cmprsd_bits; 21393 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p = max_bits; 21394 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p_mask = 21395 (1 << max_bits) - 1; 21396 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p_pos = 21397 cmprsd_pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit; 21398 } 21399 21400 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21401 unit, pkt_attr_pkt_pri_map); 21402 invalid_map_value = (1 << logical_group_bits) - 1; 21403 21404 mapped_value0 = mapped_value1 = mapped_value2 = 0; 21405 for (index0 = 0; index0 < (1 << vlan_format_bits); index0++) { 21406 invalid_index0 = FALSE; 21407 if (map_array[bcmPolicerGroupModeAttrVlan] != NULL) { 21408 if (map_array[bcmPolicerGroupModeAttrVlan][index0] == 0xFF) { 21409 invalid_index0 = TRUE; 21410 } else { 21411 mapped_value0 = 21412 map_array[bcmPolicerGroupModeAttrVlan][index0]; 21413 } 21414 } 21415 for (index1 = 0; index1 < (1 << outer_dot1p_bits); index1++) { 21416 invalid_index1 = FALSE; 21417 if (map_array[bcmPolicerGroupModeAttrOuterPri] != NULL) { 21418 if (map_array[bcmPolicerGroupModeAttrOuterPri][index1] == 0xFF) { 21419 invalid_index1 = TRUE; 21420 } else { 21421 mapped_value1 = map_array 21422 [bcmPolicerGroupModeAttrOuterPri][index1]; 21423 } 21424 } 21425 for (index2 = 0; index2 < (1 << inner_dot1p_bits); index2++) { 21426 invalid_index2 = FALSE; 21427 if (map_array[bcmPolicerGroupModeAttrInnerPri] != NULL) { 21428 if (map_array[bcmPolicerGroupModeAttrInnerPri] 21429 [index2] == 0xFF) { 21430 invalid_index2 = TRUE; 21431 } else { 21432 mapped_value2 = map_array 21433 [bcmPolicerGroupModeAttrInnerPri][index2]; 21434 } 21435 } 21436 final_index = (index0 << (outer_dot1p_bits + inner_dot1p_bits)) + 21437 (index1 << inner_dot1p_bits) + index2; 21438 if (invalid_index0 || invalid_index1 || invalid_index2) { 21439 final_mapped_value = invalid_map_value; 21440 } else if (soc_feature(unit, 21441 soc_feature_global_meter_compression_share)) { 21442 final_mapped_value = (mapped_value0 << 21443 (outer_dot1p_bits + inner_dot1p_bits)) + 21444 (mapped_value1 << inner_dot1p_bits) + mapped_value2; 21445 } else { 21446 final_mapped_value = (mapped_value0 << 21447 (outer_dot1p_cmprsd_bits + 21448 inner_dot1p_cmprsd_bits)) + 21449 (mapped_value1 << inner_dot1p_cmprsd_bits) + 21450 mapped_value2; 21451 } 21452 cmprsd_attr_selectors->compressed_pkt_pri_attr_map_v[final_index] = 21453 final_mapped_value; 21454 } 21455 } 21456 } 21457 } 21458 21459 /* Logical Group-3 port */ 21460 if (pkt_attr_selectors->port == 1) { 21461 if (map_array[bcmPolicerGroupModeAttrPort] != NULL) { 21462 max_bits = ing_port_cmprsd_bits; 21463 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port = max_bits; 21464 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port_mask = 21465 (1 << max_bits) - 1; 21466 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port_pos = 21467 cmprsd_pkt_attr_bit_pos[pkt_attr_ing_port].start_bit; 21468 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21469 unit, pkt_attr_port_map); 21470 invalid_map_value = (1 << logical_group_bits) - 1; 21471 21472 mapped_value0 = 0; 21473 /* Use ing_port_attrs as it is device dependent */ 21474 for (index0 =0; index0 < ing_port_attrs; index0++ ) { 21475 invalid_index0 = FALSE; 21476 if (map_array[bcmPolicerGroupModeAttrPort][index0] == 0xFF) { 21477 invalid_index0 = TRUE; 21478 } else { 21479 mapped_value0 = 21480 map_array[bcmPolicerGroupModeAttrPort][index0]; 21481 } 21482 final_index = index0; 21483 if (invalid_index0) { 21484 final_mapped_value = invalid_map_value; 21485 } else { 21486 final_mapped_value = mapped_value0; 21487 } 21488 cmprsd_attr_selectors->compressed_port_attr_map_v 21489 [final_index] = final_mapped_value; 21490 } 21491 } 21492 } 21493 21494 /* Logical Group-4 tos_dscp / tos_ecn */ 21495 if ((pkt_attr_selectors->tos_dscp == 1) || 21496 (pkt_attr_selectors->tos_ecn == 1)) { 21497 if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) { 21498 max_bits = tos_dscp_cmprsd_bits; 21499 cmprsd_attr_selectors->pkt_attr_bits_v.tos = max_bits; 21500 cmprsd_attr_selectors->pkt_attr_bits_v.tos_mask = 21501 (1 << max_bits) - 1; 21502 cmprsd_attr_selectors->pkt_attr_bits_v.tos_pos = 21503 cmprsd_pkt_attr_bit_pos[pkt_attr_tos].start_bit; 21504 } 21505 if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) { 21506 max_bits = tos_ecn_cmprsd_bits; 21507 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn = max_bits; 21508 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn_mask = 21509 (1 << max_bits) - 1; 21510 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn_pos = 21511 cmprsd_pkt_attr_bit_pos[pkt_attr_tos_ecn].start_bit; 21512 } 21513 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21514 unit, pkt_attr_tos_map); 21515 invalid_map_value = (1 << logical_group_bits) - 1; 21516 21517 mapped_value0 = mapped_value1 = 0; 21518 for (index0 = 0; index0 < (1 << tos_dscp_bits); index0++) { 21519 invalid_index0 = FALSE; 21520 if (map_array[bcmPolicerGroupModeAttrTosDscp] != NULL) { 21521 if (map_array[bcmPolicerGroupModeAttrTosDscp][index0] == 0xFF) { 21522 invalid_index0 = TRUE; 21523 } else { 21524 mapped_value0 = 21525 map_array[bcmPolicerGroupModeAttrTosDscp][index0]; 21526 } 21527 } 21528 for (index1 = 0; index1 < (1 << tos_ecn_bits); index1++) { 21529 invalid_index1 = FALSE; 21530 if (map_array[bcmPolicerGroupModeAttrTosEcn] != NULL) { 21531 if (map_array[bcmPolicerGroupModeAttrTosEcn][index1] == 0xFF) { 21532 invalid_index1 = TRUE; 21533 } else { 21534 mapped_value1 = map_array 21535 [bcmPolicerGroupModeAttrTosEcn][index1]; 21536 } 21537 } 21538 final_index = (index0 << tos_ecn_bits) + index1; 21539 if (invalid_index0 || invalid_index1) { 21540 final_mapped_value = invalid_map_value; 21541 } else if (soc_feature(unit, 21542 soc_feature_global_meter_compression_share)) { 21543 final_mapped_value = (mapped_value0 << 21544 tos_ecn_bits) + mapped_value1; 21545 } else { 21546 final_mapped_value = (mapped_value0 << 21547 tos_ecn_cmprsd_bits) + mapped_value1; 21548 } 21549 cmprsd_attr_selectors->compressed_tos_attr_map_v 21550 [final_index] = final_mapped_value; 21551 } 21552 } 21553 } 21554 21555 /* Logical Group-5 pkt_resolution / network group(svp type) / drop */ 21556 if ((pkt_attr_selectors->pkt_resolution == 1) || 21557 (pkt_attr_selectors->svp_type == 1) || 21558 (pkt_attr_selectors->drop ==1)) { 21559 if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) { 21560 max_bits = pkt_res_cmprsd_bits; 21561 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_resolution = max_bits; 21562 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_res_mask = 21563 (1 << max_bits) - 1; 21564 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_res_pos = 21565 cmprsd_pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit; 21566 } 21567 if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) { 21568 max_bits = svp_type_cmprsd_bits; 21569 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type = max_bits; 21570 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type_mask = 21571 (1 << max_bits) - 1; 21572 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type_pos = 21573 cmprsd_pkt_attr_bit_pos[pkt_attr_svp_group].start_bit; 21574 } 21575 if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) { 21576 max_bits = drop_cmprsd_bits; 21577 cmprsd_attr_selectors->pkt_attr_bits_v.drop = max_bits; 21578 cmprsd_attr_selectors->pkt_attr_bits_v.drop_mask = 21579 (1 << max_bits) - 1; 21580 cmprsd_attr_selectors->pkt_attr_bits_v.drop_pos = 21581 cmprsd_pkt_attr_bit_pos[pkt_attr_drop].start_bit; 21582 } 21583 21584 logical_group_bits = _bcm_policer_svm_pkt_compressed_map_bits_get( 21585 unit, pkt_attr_pkt_res_map); 21586 invalid_map_value = (1 << logical_group_bits) - 1; 21587 21588 /* 21589 * pkt_res_bits in compressed and uncompressed mode is different 21590 * and map_array is populated based on bit positions of pkt_type 21591 * in Hw and are not sequential. Use pkt_res_bits of uncompressed 21592 * mode to cover all bit positions. 21593 */ 21594 pkt_res_bits = _bcm_policer_svm_pkt_attr_bits_get( 21595 unit, pkt_attr_pkt_resolution); 21596 21597 mapped_value0 = mapped_value1 = mapped_value2 = 0; 21598 for (index0 = 0; index0 < (1 << pkt_res_bits); index0++) { 21599 invalid_index0 = FALSE; 21600 if (map_array[bcmPolicerGroupModeAttrPktType] != NULL) { 21601 if (map_array[bcmPolicerGroupModeAttrPktType][index0] == 0xFF) { 21602 invalid_index0 = TRUE; 21603 } else { 21604 mapped_value0 = map_array 21605 [bcmPolicerGroupModeAttrPktType][index0]; 21606 } 21607 } 21608 for (index1 = 0; index1 < (1 << svp_type_bits); index1++) { 21609 invalid_index1 = FALSE; 21610 if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup] != NULL) { 21611 if (map_array[bcmPolicerGroupModeAttrIngNetworkGroup][index1] == 0xFF) { 21612 invalid_index1 = TRUE; 21613 } else { 21614 mapped_value1 = map_array 21615 [bcmPolicerGroupModeAttrIngNetworkGroup][index1]; 21616 } 21617 } 21618 for (index2 = 0; index2 < (1 << drop_bits); index2++) { 21619 invalid_index2 = FALSE; 21620 if (map_array[bcmPolicerGroupModeAttrDrop] != NULL) { 21621 if (map_array[bcmPolicerGroupModeAttrDrop][index2] == 0xFF) { 21622 invalid_index2 = TRUE; 21623 } else { 21624 mapped_value2 = map_array 21625 [bcmPolicerGroupModeAttrDrop][index2]; 21626 } 21627 } 21628 final_index = (index0 << (svp_type_bits + drop_bits)) + 21629 (index1 << drop_bits) + index2; 21630 if (invalid_index0 || invalid_index1 || invalid_index2) { 21631 final_mapped_value = invalid_map_value; 21632 } else if (soc_feature(unit, 21633 soc_feature_global_meter_compression_share)) { 21634 final_mapped_value = 21635 (mapped_value0 << (svp_type_bits + drop_bits)) + 21636 (mapped_value1 << drop_bits) + mapped_value2; 21637 } else { 21638 final_mapped_value = 21639 (mapped_value0 << (svp_type_cmprsd_bits + 21640 drop_cmprsd_bits)) + 21641 (mapped_value1 << drop_cmprsd_bits) + 21642 mapped_value2; 21643 } 21644 cmprsd_attr_selectors->compressed_pkt_res_attr_map_v 21645 [final_index] = final_mapped_value; 21646 } 21647 } 21648 } 21649 } 21650 21651 if (pkt_attr_selectors->ip_pkt == 1) { 21652 max_bits = ip_pkt_cmprsd_bits; 21653 cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt = max_bits; 21654 cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt_mask = 21655 (1 << max_bits) - 1; 21656 cmprsd_attr_selectors->pkt_attr_bits_v.ip_pkt_pos = 21657 cmprsd_pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit; 21658 } 21659 21660 /* Step 4 : Compute offset_map */ 21661 /* Fill offset_map field of uncompressed_attr_selectors_v */ 21662 /* Step 4.1 : Reset all values in offset_map */ 21663 sal_memset(cmprsd_attr_selectors->offset_map, 0, 21664 sizeof (cmprsd_attr_selectors->offset_map)); 21665 21666 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 21667 offset_array[loop] = 21668 (uint8 *) sal_alloc(BCM_SVC_METER_MAP_SIZE_256 + 1, 21669 "offset_array"); 21670 if (offset_array[loop] == NULL) { 21671 rv = BCM_E_MEMORY; 21672 break; 21673 } 21674 } 21675 if (BCM_FAILURE(rv)) { 21676 /* Free offset_array */ 21677 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 21678 if (offset_array[loop] != NULL) { 21679 sal_free(offset_array[loop]); 21680 } 21681 } 21682 /* free map_array */ 21683 for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) { 21684 if (map_array[loop] != NULL) { 21685 sal_free(map_array[loop]); 21686 } 21687 } 21688 sal_free(meter_attr); 21689 return rv; 21690 } 21691 21692 /* Step 4.2 : Calculate offset value for each pol_offset */ 21693 for (pol_offset = 0; 21694 pol_offset < pkt_attr_selectors->total_policers ; 21695 pol_offset++ ) { 21696 combine_attr_data = 21697 &pkt_attr_selectors->combine_attr_data[pol_offset]; 21698 /* Step 4.2.1 : Reset offset_array */ 21699 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 21700 sal_memset(offset_array[loop], 0, 21701 BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1); 21702 } 21703 loop = 0; 21704 21705 /* Step 4.2.2 : Parse each attr types and save values */ 21706 if ((pkt_attr_selectors->cng == 1) && 21707 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21708 shift_by_bits = int_pri_cmprsd_bits + 21709 vlan_format_cmprsd_bits + 21710 outer_dot1p_cmprsd_bits + 21711 inner_dot1p_cmprsd_bits + 21712 ing_port_cmprsd_bits + 21713 tos_dscp_cmprsd_bits + 21714 tos_ecn_cmprsd_bits + 21715 pkt_res_cmprsd_bits + 21716 svp_type_cmprsd_bits + 21717 drop_cmprsd_bits + 21718 ip_pkt_cmprsd_bits; 21719 21720 temp_count = offset_array[loop][0]; 21721 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_GREEN) { 21722 offset_array[loop][temp_count + 1] = 21723 (map_array[bcmPolicerGroupModeAttrFieldIngressColor][0] << 21724 shift_by_bits); 21725 temp_count++; 21726 } 21727 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_YELLOW) { 21728 offset_array[loop][temp_count + 1] = 21729 (map_array[bcmPolicerGroupModeAttrFieldIngressColor][1] << 21730 shift_by_bits); 21731 temp_count++; 21732 } 21733 if (combine_attr_data->cng_flags & _BCM_POLICER_COLOR_RED) { 21734 offset_array[loop][temp_count + 1] = 21735 (map_array[bcmPolicerGroupModeAttrFieldIngressColor][3] << 21736 shift_by_bits); 21737 temp_count++; 21738 } 21739 offset_array[loop][0] = temp_count; 21740 loop++; 21741 } 21742 if ((pkt_attr_selectors->int_pri == 1) && 21743 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21744 shift_by_bits = vlan_format_cmprsd_bits + 21745 outer_dot1p_cmprsd_bits + 21746 inner_dot1p_cmprsd_bits + 21747 ing_port_cmprsd_bits + 21748 tos_dscp_cmprsd_bits + 21749 tos_ecn_cmprsd_bits + 21750 pkt_res_cmprsd_bits + 21751 svp_type_cmprsd_bits + 21752 drop_cmprsd_bits + 21753 ip_pkt_cmprsd_bits; 21754 21755 temp_count = offset_array[loop][0]; 21756 for (index0 = _BCM_POLICER_PKT_PRI0; 21757 index0 <= _BCM_POLICER_PKT_PRI15; index0++) { 21758 if(combine_attr_data->int_pri_flags & (1 << index0)) { 21759 offset_array[loop][temp_count + 1] = 21760 (map_array[bcmPolicerGroupModeAttrIntPri][index0] << 21761 shift_by_bits); 21762 temp_count++; 21763 } 21764 } 21765 offset_array[loop][0] = temp_count; 21766 loop++; 21767 } 21768 if ((pkt_attr_selectors->vlan_format == 1) && 21769 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21770 shift_by_bits = outer_dot1p_cmprsd_bits + 21771 inner_dot1p_cmprsd_bits + 21772 ing_port_cmprsd_bits + 21773 tos_dscp_cmprsd_bits + 21774 tos_ecn_cmprsd_bits + 21775 pkt_res_cmprsd_bits + 21776 svp_type_cmprsd_bits + 21777 drop_cmprsd_bits + 21778 ip_pkt_cmprsd_bits; 21779 21780 temp_count = offset_array[loop][0]; 21781 if(combine_attr_data->vlan_format_flags & 21782 _BCM_POLICER_VLAN_FORMAT_UNTAGGED) { 21783 offset_array[loop][temp_count + 1] = 21784 (map_array[bcmPolicerGroupModeAttrVlan][0] << 21785 shift_by_bits); 21786 temp_count++; 21787 } 21788 if(combine_attr_data->vlan_format_flags & 21789 _BCM_POLICER_VLAN_FORMAT_INNER) { 21790 offset_array[loop][temp_count + 1] = 21791 (map_array[bcmPolicerGroupModeAttrVlan][1] << 21792 shift_by_bits); 21793 temp_count++; 21794 } 21795 if(combine_attr_data->vlan_format_flags & 21796 _BCM_POLICER_VLAN_FORMAT_OUTER) { 21797 offset_array[loop][temp_count + 1] = 21798 (map_array[bcmPolicerGroupModeAttrVlan][2] << 21799 shift_by_bits); 21800 temp_count++; 21801 } 21802 if(combine_attr_data->vlan_format_flags & 21803 _BCM_POLICER_VLAN_FORMAT_BOTH) { 21804 offset_array[loop][temp_count + 1] = 21805 (map_array[bcmPolicerGroupModeAttrVlan][3] << 21806 shift_by_bits); 21807 temp_count++; 21808 } 21809 offset_array[loop][0] = temp_count; 21810 loop++; 21811 } 21812 if ((pkt_attr_selectors->outer_dot1p == 1) && 21813 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21814 shift_by_bits = inner_dot1p_cmprsd_bits + 21815 ing_port_cmprsd_bits + 21816 tos_dscp_cmprsd_bits + 21817 tos_ecn_cmprsd_bits + 21818 pkt_res_cmprsd_bits + 21819 svp_type_cmprsd_bits + 21820 drop_cmprsd_bits + 21821 ip_pkt_cmprsd_bits; 21822 21823 temp_count = offset_array[loop][0]; 21824 for (index0 = _BCM_POLICER_PKT_PRI0; 21825 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 21826 if(combine_attr_data->outer_dot1p_flags & (1 << index0)) { 21827 offset_array[loop][temp_count + 1] = 21828 (map_array[bcmPolicerGroupModeAttrOuterPri][index0] << 21829 shift_by_bits); 21830 temp_count++; 21831 } 21832 } 21833 offset_array[loop][0] = temp_count; 21834 loop++; 21835 } 21836 if ((pkt_attr_selectors->inner_dot1p == 1) && 21837 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21838 shift_by_bits = ing_port_cmprsd_bits + 21839 tos_dscp_cmprsd_bits + 21840 tos_ecn_cmprsd_bits + 21841 pkt_res_cmprsd_bits + 21842 svp_type_cmprsd_bits + 21843 drop_cmprsd_bits + 21844 ip_pkt_cmprsd_bits; 21845 21846 temp_count = offset_array[loop][0]; 21847 for (index0 = _BCM_POLICER_PKT_PRI0; 21848 index0 <= _BCM_POLICER_PKT_PRI7; index0++) { 21849 if(combine_attr_data->inner_dot1p_flags & (1 << index0)) { 21850 offset_array[loop][temp_count + 1] = 21851 (map_array[bcmPolicerGroupModeAttrInnerPri][index0] << 21852 shift_by_bits); 21853 temp_count++; 21854 } 21855 } 21856 offset_array[loop][0] = temp_count; 21857 loop++; 21858 } 21859 if ((pkt_attr_selectors->port == 1) && 21860 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21861 shift_by_bits = tos_dscp_cmprsd_bits + 21862 tos_ecn_cmprsd_bits + 21863 pkt_res_cmprsd_bits + 21864 svp_type_cmprsd_bits + 21865 drop_cmprsd_bits + 21866 ip_pkt_cmprsd_bits; 21867 21868 for (index0 = 0; index0 < ing_port_attrs; index0++) { 21869 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 21870 value_array[_bcmPolicerAttrPort], index0)) { 21871 temp_count = offset_array[loop][0]; 21872 offset_array[loop][temp_count + 1] = 21873 map_array[bcmPolicerGroupModeAttrPort][index0] << 21874 shift_by_bits; 21875 offset_array[loop][0] = temp_count + 1; 21876 } 21877 } 21878 loop++; 21879 } 21880 if ((pkt_attr_selectors->tos_dscp == 1) && 21881 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21882 shift_by_bits = tos_ecn_cmprsd_bits + 21883 pkt_res_cmprsd_bits + 21884 svp_type_cmprsd_bits + 21885 drop_cmprsd_bits + 21886 ip_pkt_cmprsd_bits; 21887 21888 for (index0 = 0; index0 < tos_dscp_attrs; index0++) { 21889 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 21890 value_array[_bcmPolicerAttrTosDscp], index0)) { 21891 temp_count = offset_array[loop][0]; 21892 offset_array[loop][temp_count + 1] = 21893 map_array[bcmPolicerGroupModeAttrTosDscp][index0] << 21894 shift_by_bits; 21895 offset_array[loop][0] = temp_count + 1; 21896 } 21897 } 21898 loop++; 21899 } 21900 if ((pkt_attr_selectors->tos_ecn == 1) && 21901 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21902 shift_by_bits = pkt_res_cmprsd_bits + 21903 svp_type_cmprsd_bits + 21904 drop_cmprsd_bits + 21905 ip_pkt_cmprsd_bits; 21906 21907 for (index0 = 0; index0 < tos_ecn_attrs; index0++) { 21908 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 21909 value_array[_bcmPolicerAttrTosEcn], index0)) { 21910 temp_count = offset_array[loop][0]; 21911 offset_array[loop][temp_count + 1] = 21912 map_array[bcmPolicerGroupModeAttrTosEcn][index0] << 21913 shift_by_bits; 21914 offset_array[loop][0] = temp_count + 1; 21915 } 21916 } 21917 loop++; 21918 } 21919 if ((pkt_attr_selectors->pkt_resolution == 1) && 21920 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 21921 shift_by_bits = svp_type_cmprsd_bits + 21922 drop_cmprsd_bits + 21923 ip_pkt_cmprsd_bits; 21924 21925 temp_count = offset_array[loop][0]; 21926 if (combine_attr_data->pkt_resolution_flags & 21927 _BCM_POLICER_PKT_TYPE_UNKNOWN_PKT) { 21928 offset_array[loop][temp_count + 1] = 21929 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_PKT]] << 21930 shift_by_bits); 21931 temp_count++; 21932 } 21933 if (combine_attr_data->pkt_resolution_flags & 21934 _BCM_POLICER_PKT_TYPE_CONTROL_PKT) { 21935 offset_array[loop][temp_count + 1] = 21936 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[CONTROL_PKT]] << 21937 shift_by_bits); 21938 temp_count++; 21939 } 21940 if (combine_attr_data->pkt_resolution_flags & 21941 _BCM_POLICER_PKT_TYPE_OAM_PKT) { 21942 offset_array[loop][temp_count + 1] = 21943 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[OAM_PKT]] << 21944 shift_by_bits); 21945 temp_count++; 21946 } 21947 if (combine_attr_data->pkt_resolution_flags & 21948 _BCM_POLICER_PKT_TYPE_BFD_PKT) { 21949 offset_array[loop][temp_count + 1] = 21950 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[BFD_PKT]] << 21951 shift_by_bits); 21952 temp_count++; 21953 } 21954 if (combine_attr_data->pkt_resolution_flags & 21955 _BCM_POLICER_PKT_TYPE_BPDU_PKT) { 21956 offset_array[loop][temp_count + 1] = 21957 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[BPDU_PKT]] << 21958 shift_by_bits); 21959 temp_count++; 21960 } 21961 if (combine_attr_data->pkt_resolution_flags & 21962 _BCM_POLICER_PKT_TYPE_ICNM_PKT) { 21963 offset_array[loop][temp_count + 1] = 21964 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[ICNM_PKT]] << 21965 shift_by_bits); 21966 temp_count++; 21967 } 21968 if (combine_attr_data->pkt_resolution_flags & 21969 _BCM_POLICER_PKT_TYPE_PKT_IS_1588) { 21970 offset_array[loop][temp_count + 1] = 21971 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[PKT_IS_1588]] << 21972 shift_by_bits); 21973 temp_count++; 21974 } 21975 if (combine_attr_data->pkt_resolution_flags & 21976 _BCM_POLICER_PKT_TYPE_KNOWN_L2UC_PKT) { 21977 offset_array[loop][temp_count + 1] = 21978 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L2UC_PKT]] << 21979 shift_by_bits); 21980 temp_count++; 21981 } 21982 if (combine_attr_data->pkt_resolution_flags & 21983 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2UC_PKT) { 21984 offset_array[loop][temp_count + 1] = 21985 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L2UC_PKT]] << 21986 shift_by_bits); 21987 temp_count++; 21988 } 21989 if (combine_attr_data->pkt_resolution_flags & 21990 _BCM_POLICER_PKT_TYPE_L2BC_PKT) { 21991 offset_array[loop][temp_count + 1] = 21992 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[L2BC_PKT]] << 21993 shift_by_bits); 21994 temp_count++; 21995 } 21996 if (combine_attr_data->pkt_resolution_flags & 21997 _BCM_POLICER_PKT_TYPE_KNOWN_L2MC_PKT) { 21998 offset_array[loop][temp_count + 1] = 21999 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L2MC_PKT]] << 22000 shift_by_bits); 22001 temp_count++; 22002 } 22003 if (combine_attr_data->pkt_resolution_flags & 22004 _BCM_POLICER_PKT_TYPE_UNKNOWN_L2MC_PKT) { 22005 offset_array[loop][temp_count + 1] = 22006 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L2MC_PKT]] << 22007 shift_by_bits); 22008 temp_count++; 22009 } 22010 if (combine_attr_data->pkt_resolution_flags & 22011 _BCM_POLICER_PKT_TYPE_KNOWN_L3UC_PKT) { 22012 offset_array[loop][temp_count + 1] = 22013 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_L3UC_PKT]] << 22014 shift_by_bits); 22015 temp_count++; 22016 } 22017 if (combine_attr_data->pkt_resolution_flags & 22018 _BCM_POLICER_PKT_TYPE_UNKNOWN_L3UC_PKT) { 22019 offset_array[loop][temp_count + 1] = 22020 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_L3UC_PKT]] << 22021 shift_by_bits); 22022 temp_count++; 22023 } 22024 if (combine_attr_data->pkt_resolution_flags & 22025 _BCM_POLICER_PKT_TYPE_KNOWN_IPMC_PKT) { 22026 offset_array[loop][temp_count + 1] = 22027 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_IPMC_PKT]] << 22028 shift_by_bits); 22029 temp_count++; 22030 } 22031 if (combine_attr_data->pkt_resolution_flags & 22032 _BCM_POLICER_PKT_TYPE_UNKNOWN_IPMC_PKT) { 22033 offset_array[loop][temp_count + 1] = 22034 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_IPMC_PKT]] << 22035 shift_by_bits); 22036 temp_count++; 22037 } 22038 if (combine_attr_data->pkt_resolution_flags & 22039 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L2_PKT) { 22040 offset_array[loop][temp_count + 1] = 22041 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_L2_PKT]] << 22042 shift_by_bits); 22043 temp_count++; 22044 } 22045 if (combine_attr_data->pkt_resolution_flags & 22046 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_L3_PKT) { 22047 offset_array[loop][temp_count + 1] = 22048 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_L3_PKT]] << 22049 shift_by_bits); 22050 temp_count++; 22051 } 22052 if (combine_attr_data->pkt_resolution_flags & 22053 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_PKT) { 22054 offset_array[loop][temp_count + 1] = 22055 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_PKT]] << 22056 shift_by_bits); 22057 temp_count++; 22058 } 22059 if (combine_attr_data->pkt_resolution_flags & 22060 _BCM_POLICER_PKT_TYPE_UNKNOWN_MPLS_PKT) { 22061 offset_array[loop][temp_count + 1] = 22062 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_MPLS_PKT]] << 22063 shift_by_bits); 22064 temp_count++; 22065 } 22066 if (combine_attr_data->pkt_resolution_flags & 22067 _BCM_POLICER_PKT_TYPE_KNOWN_MPLS_MULTICAST_PKT) { 22068 offset_array[loop][temp_count + 1] = 22069 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MPLS_MULTICAST_PKT]] << 22070 shift_by_bits); 22071 temp_count++; 22072 } 22073 if (combine_attr_data->pkt_resolution_flags & 22074 _BCM_POLICER_PKT_TYPE_KNOWN_MIM_PKT) { 22075 offset_array[loop][temp_count + 1] = 22076 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_MIM_PKT]] << 22077 shift_by_bits); 22078 temp_count++; 22079 } 22080 if (combine_attr_data->pkt_resolution_flags & 22081 _BCM_POLICER_PKT_TYPE_UNKNOWN_MIM_PKT) { 22082 offset_array[loop][temp_count + 1] = 22083 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_MIM_PKT]] << 22084 shift_by_bits); 22085 temp_count++; 22086 } 22087 if (combine_attr_data->pkt_resolution_flags & 22088 _BCM_POLICER_PKT_TYPE_KNOWN_TRILL_PKT) { 22089 offset_array[loop][temp_count + 1] = 22090 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_TRILL_PKT]] << 22091 shift_by_bits); 22092 temp_count++; 22093 } 22094 if (combine_attr_data->pkt_resolution_flags & 22095 _BCM_POLICER_PKT_TYPE_UNKNOWN_TRILL_PKT) { 22096 offset_array[loop][temp_count + 1] = 22097 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_TRILL_PKT]] << 22098 shift_by_bits); 22099 temp_count++; 22100 } 22101 if (combine_attr_data->pkt_resolution_flags & 22102 _BCM_POLICER_PKT_TYPE_KNOWN_NIV_PKT) { 22103 offset_array[loop][temp_count + 1] = 22104 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[KNOWN_NIV_PKT]] << 22105 shift_by_bits); 22106 temp_count++; 22107 } 22108 if (combine_attr_data->pkt_resolution_flags & 22109 _BCM_POLICER_PKT_TYPE_UNKNOWN_NIV_PKT) { 22110 offset_array[loop][temp_count + 1] = 22111 (map_array[bcmPolicerGroupModeAttrPktType][pkt_res[UNKNOWN_NIV_PKT]] << 22112 shift_by_bits); 22113 temp_count++; 22114 } 22115 offset_array[loop][0] = temp_count; 22116 loop++; 22117 } 22118 if ((pkt_attr_selectors->svp_type == 1) && 22119 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 22120 shift_by_bits = drop_cmprsd_bits + 22121 ip_pkt_cmprsd_bits; 22122 22123 for (index0 = 0; index0 < svp_type_attrs; index0++) { 22124 if (_BCM_POLICER_VALUE_GET(combine_attr_data-> 22125 value_array[_bcmPolicerAttrSvpType], index0)) { 22126 temp_count = offset_array[loop][0]; 22127 offset_array[loop][temp_count + 1] = 22128 map_array[bcmPolicerGroupModeAttrIngNetworkGroup][index0] << 22129 shift_by_bits; 22130 offset_array[loop][0] = temp_count + 1; 22131 } 22132 } 22133 loop++; 22134 } 22135 if ((pkt_attr_selectors->drop == 1) && 22136 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 22137 shift_by_bits = ip_pkt_cmprsd_bits; 22138 22139 temp_count = offset_array[loop][0]; 22140 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_DISABLE) { 22141 offset_array[loop][temp_count + 1] = 22142 (map_array[bcmPolicerGroupModeAttrDrop][0] << 22143 shift_by_bits); 22144 temp_count++; 22145 } 22146 if (combine_attr_data->drop_flags & _BCM_POLICER_DROP_ENABLE) { 22147 offset_array[loop][temp_count + 1] = 22148 (map_array[bcmPolicerGroupModeAttrDrop][1] << 22149 shift_by_bits); 22150 temp_count++; 22151 } 22152 offset_array[loop][0] = temp_count; 22153 loop++; 22154 } 22155 if ((pkt_attr_selectors->ip_pkt == 1) && 22156 (loop <= (SVC_METER_MAX_SELECTOR_BITS - 2))) { 22157 shift_by_bits = 0; 22158 temp_count = offset_array[loop][0]; 22159 if (combine_attr_data->ip_pkt_flags & _BCM_POLICER_IP_PKT_DISABLE) { 22160 offset_array[loop][temp_count + 1] = 22161 (map_array[bcmPolicerGroupModeAttrPacketTypeIp][0] << 22162 shift_by_bits); 22163 temp_count++; 22164 } 22165 if (combine_attr_data->ip_pkt_flags & _BCM_POLICER_IP_PKT_ENABLE) { 22166 offset_array[loop][temp_count + 1] = 22167 (map_array[bcmPolicerGroupModeAttrPacketTypeIp][1] << 22168 shift_by_bits); 22169 temp_count++; 22170 } 22171 offset_array[loop][0] = temp_count; 22172 loop++; 22173 } 22174 22175 /* Step 4.2.3 : compute final offset value */ 22176 rv = _bcm_policer_group_mode_offset_map_generate(unit, 22177 meter_attr, group_mode, pol_offset, offset_array); 22178 if (rv != BCM_E_NONE) { 22179 break; 22180 } 22181 } 22182 } 22183 22184 if (BCM_FAILURE(rv)) { 22185 goto cleanup; 22186 } 22187 22188 GLOBAL_METER_LOCK(unit); 22189 rv = _bcm_esw_policer_svc_meter_create_mode (unit, meter_attr, group_mode, 22190 type, pkt_attr_selectors->total_policers, pkt_attr_selectors, mode_id); 22191 GLOBAL_METER_UNLOCK(unit); 22192 22193 cleanup: 22194 22195 /* Free map_array */ 22196 for (loop = 0; loop < bcmPolicerGroupModeAttrCount; loop++) { 22197 if (map_array[loop] != NULL) { 22198 sal_free(map_array[loop]); 22199 } 22200 } 22201 /* Free offset_array */ 22202 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 22203 if (offset_array[loop] != NULL) { 22204 sal_free(offset_array[loop]); 22205 } 22206 } 22207 22208 /* Free meter_attr */ 22209 if (meter_attr != NULL) { 22210 sal_free(meter_attr); 22211 } 22212 22213 if ((rv == BCM_E_EXISTS) && 22214 (soc_feature(unit, soc_feature_global_meter_compression_share))) { 22215 rv = BCM_E_NONE; 22216 } 22217 22218 return rv; 22219 } 22220 22221 /* 22222 * Function: 22223 * _bcm_policer_custom_group_mode_id_create 22224 * Purpose: 22225 * This function is used to configure customnized group mode 22226 * Parameters: 22227 * unit - (IN) unit number 22228 * flags - (IN) flags 22229 * type - (IN) type of group mode 22230 * total_policers - (IN) total policers 22231 * num_selectors - (IN) number of selectors 22232 * attr_selectors - (IN) list of attributes selectors 22233 * mode_id - (OUT) pointer to offset mode index 22234 * Returns: 22235 * BCM_E_XXX 22236 */ 22237 int 22238 _bcm_policer_custom_group_mode_id_create( 22239 int unit, 22240 uint32 flags, 22241 bcm_policer_group_mode_type_t type, 22242 uint32 total_policers, 22243 uint32 num_selectors, 22244 bcm_policer_group_mode_attr_selector_t *attr_selectors, 22245 uint32 *mode_id) 22246 { 22247 int rv = BCM_E_NONE; 22248 bcm_policer_attr_selectors_t pkt_attr_selectors; 22249 uint32 npolicers = 0; 22250 22251 npolicers = total_policers; 22252 if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) { 22253 npolicers = total_policers/2; 22254 } 22255 22256 /* Check if mode info already exists */ 22257 rv = _bcm_esw_svc_meter_offset_mode_id_check(unit, flags, type, 22258 total_policers, num_selectors, attr_selectors, mode_id); 22259 BCM_IF_ERROR_RETURN(rv); 22260 22261 sal_memset(&pkt_attr_selectors, 0, sizeof(bcm_policer_attr_selectors_t)); 22262 pkt_attr_selectors.combine_attr_data = 22263 sal_alloc(sizeof(bcm_policer_combine_attr_t) * npolicers, 22264 "combine attributes"); 22265 if (pkt_attr_selectors.combine_attr_data == NULL) { 22266 return BCM_E_MEMORY; 22267 } 22268 sal_memset(pkt_attr_selectors.combine_attr_data, 0, 22269 sizeof(bcm_policer_combine_attr_t) * npolicers); 22270 22271 rv = _bcm_esw_policer_group_mode_fillup_values (unit, flags, type, 22272 npolicers, num_selectors, attr_selectors, &pkt_attr_selectors); 22273 if (rv != BCM_E_NONE) { 22274 sal_free(pkt_attr_selectors.combine_attr_data); 22275 return rv; 22276 } 22277 22278 rv = _bcm_esw_policer_group_mode_id_associate(unit, flags, 22279 type, &pkt_attr_selectors, mode_id); 22280 if (rv != BCM_E_NONE) { 22281 sal_free(pkt_attr_selectors.combine_attr_data); 22282 return rv; 22283 } 22284 22285 GLOBAL_METER_LOCK(unit); 22286 /* In case of group type is cascade/cascadewithcoupling, total_policers 22287 * must be set to 8. This requirement is due to the fact that in these 22288 * two cases, meter index allocation is one complete octuple */ 22289 if ((type == bcmPolicerGroupModeTypeCascade) || 22290 (type == bcmPolicerGroupModeTypeCascadeWithCoupling)) { 22291 global_meter_offset_mode[unit][*mode_id].no_of_policers = 8; 22292 } else { 22293 global_meter_offset_mode[unit][*mode_id].no_of_policers = 22294 total_policers; 22295 } 22296 rv = _bcm_policer_svc_meter_group_offset_mode_info_update (unit, *mode_id, 22297 type, num_selectors, attr_selectors); 22298 if (BCM_FAILURE(rv)) { 22299 _bcm_policer_svc_meter_unreserve_mode (unit, *mode_id); 22300 GLOBAL_METER_UNLOCK(unit); 22301 return rv; 22302 } 22303 /* Update compressed attribute maps */ 22304 if (global_meter_offset_mode[unit][*mode_id].meter_attr.mode_type_v == 22305 compressed_mode) { 22306 (void) _bcm_esw_svm_pkt_compressed_attr_maps_update(unit, 22307 &pkt_attr_selectors); 22308 } 22309 GLOBAL_METER_UNLOCK(unit); 22310 return rv; 22311 } 22312 22313 /* 22314 * Function: 22315 * _bcm_esw_policer_udf_custom_group_create 22316 * Purpose: 22317 * This function is used to configure udf based 22318 * group mode 22319 * Parameters: 22320 * unit - (IN) unit number 22321 * flags - (IN) flags 22322 * type - (IN) type of group mode 22323 * total_policers - (IN) total policers 22324 * num_selectors - (IN) number of selectors 22325 * attr_selectors - (IN) list of attributes selectors 22326 * mode_id - (OUT) pointer to offset mode index 22327 * Returns: 22328 * BCM_E_XXX 22329 */ 22330 int 22331 _bcm_esw_policer_udf_custom_group_create( 22332 int unit, 22333 uint32 flags, 22334 bcm_policer_group_mode_type_t type, 22335 uint32 total_policers, 22336 uint32 num_selectors, 22337 bcm_policer_group_mode_attr_selector_t *attr_selectors, 22338 uint32 *mode_id) 22339 { 22340 int rv = BCM_E_NONE; 22341 bcm_policer_udf_attr_selectors_t udf_attr_selectors; 22342 bcm_policer_udf_pkt_combine_attr_t *udf_combine_data = NULL; 22343 bcm_policer_udf_sub_div_t dummy_data; 22344 22345 bcm_policer_svc_meter_attr_t *meter_attr = NULL; 22346 bcm_policer_group_mode_t group_mode; 22347 bcm_policer_svc_meter_mode_type_t mode_type_v; 22348 uint32 npolicers = 0; 22349 22350 uint8 shift_by_bits_array[SVC_METER_UDF1_MAX_BIT_POSITION] = {0}; 22351 int8 loop_index_array[SVC_METER_UDF1_MAX_BIT_POSITION] = {-1}; 22352 uint8 *offset_array[SVC_METER_MAX_SELECTOR_BITS] = {NULL}; 22353 uint32 sorted = 0, total_bits = 0, shift_by_bits = 0; 22354 uint32 index0 = 0, index1 = 0; 22355 uint32 loop_index = 0, loop =0; 22356 uint32 offset = 0, total_offsets = 0; 22357 uint32 pol_offset = 0; 22358 22359 npolicers = total_policers; 22360 if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) { 22361 npolicers = total_policers/2; 22362 } 22363 22364 /* Check if mode info already exists */ 22365 rv = _bcm_esw_svc_meter_offset_mode_id_check(unit, flags, type, 22366 total_policers, num_selectors, attr_selectors, mode_id); 22367 BCM_IF_ERROR_RETURN(rv); 22368 22369 sal_memset (&udf_attr_selectors, 0, 22370 sizeof(bcm_policer_udf_attr_selectors_t)); 22371 udf_attr_selectors.combine_attr_data = 22372 sal_alloc(sizeof(bcm_policer_udf_pkt_combine_attr_t) * npolicers, 22373 "combine attributes"); 22374 22375 if (udf_attr_selectors.combine_attr_data == NULL) { 22376 return BCM_E_MEMORY; 22377 } 22378 sal_memset(udf_attr_selectors.combine_attr_data, 0, 22379 sizeof(bcm_policer_udf_pkt_combine_attr_t) * npolicers); 22380 22381 rv = _bcm_esw_policer_group_udf_mode_fillup_values (unit, flags, type, 22382 npolicers, num_selectors, attr_selectors, &udf_attr_selectors); 22383 if (rv != BCM_E_NONE) { 22384 sal_free(udf_attr_selectors.combine_attr_data); 22385 return rv; 22386 } 22387 22388 /* Below block of code is intended to sort the input offset/width 22389 * in ascending order of udf offsets numerically. 22390 * 'total_bits' required is also calculated to check if creating mode 22391 * with given attr_selectors is possible or not. 22392 * Also, shift bits needs to be calculated which is later used to 22393 * generate offset to be indexed for SVM_OFFSET_TABLE 22394 */ 22395 sorted = total_bits = shift_by_bits = 0; 22396 if (udf_attr_selectors.drop) { 22397 total_bits++; 22398 shift_by_bits = 1; 22399 } 22400 /* Loop through lower offset to higher offset index to calculate shift */ 22401 for (index0 = 0; index0 < SVC_METER_UDF1_MAX_BIT_POSITION; index0++) { 22402 if (udf_attr_selectors.udf_bits[index0] == 1) { 22403 for (index1 = sorted; index1 < udf_attr_selectors.total_subdiv; index1++) { 22404 if (udf_attr_selectors.udf_subdiv[index1].offset == index0) { 22405 /* Swap to rearrange */ 22406 sal_memcpy(&dummy_data, &udf_attr_selectors.udf_subdiv[index1], 22407 sizeof (bcm_policer_udf_sub_div_t)); 22408 sal_memcpy(&udf_attr_selectors.udf_subdiv[index1], 22409 &udf_attr_selectors.udf_subdiv[sorted], 22410 sizeof(bcm_policer_udf_sub_div_t)); 22411 sal_memcpy(&udf_attr_selectors.udf_subdiv[sorted], &dummy_data, 22412 sizeof (bcm_policer_udf_sub_div_t)); 22413 total_bits += udf_attr_selectors.udf_subdiv[sorted].width; 22414 shift_by_bits_array[index0] = shift_by_bits; 22415 shift_by_bits += udf_attr_selectors.udf_subdiv[sorted].width; 22416 sorted++; 22417 break; 22418 } 22419 } 22420 } 22421 } 22422 22423 if (total_bits > BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) { 22424 sal_free(udf_attr_selectors.combine_attr_data); 22425 return BCM_E_PARAM; 22426 } 22427 22428 meter_attr = sal_alloc(sizeof(bcm_policer_svc_meter_attr_t),"meter mode attr"); 22429 if ( meter_attr == NULL) { 22430 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22431 "Failed to allocate memory for svc meter attr \n"))); 22432 sal_free(udf_attr_selectors.combine_attr_data); 22433 return BCM_E_MEMORY; 22434 } 22435 sal_memset (meter_attr, 0, sizeof(bcm_policer_svc_meter_attr_t)); 22436 22437 /* bcm_policer_group_mode_t should be based on type */ 22438 if (type == bcmPolicerGroupModeTypeNormal) { 22439 mode_type_v = udf_mode; 22440 group_mode = bcmPolicerGroupModeSingle; 22441 } else if (type == bcmPolicerGroupModeTypeCascade) { 22442 mode_type_v = udf_cascade_mode; 22443 group_mode = bcmPolicerGroupModeCascade; 22444 } else { /* type == bcmPolicerGroupModeTypeCascadeWithCoupling */ 22445 mode_type_v = udf_cascade_with_coupling_mode; 22446 group_mode = bcmPolicerGroupModeCascadeWithCoupling; 22447 } 22448 meter_attr->udf_pkt_attr_selectors_v.num_selectors = num_selectors; 22449 meter_attr->udf_pkt_attr_selectors_v.udf_id = attr_selectors[0].udf_id; 22450 meter_attr->mode_type_v = mode_type_v; 22451 22452 if (udf_attr_selectors.drop == 1) { 22453 meter_attr->udf_pkt_attr_selectors_v.drop = 1; 22454 } 22455 if (udf_attr_selectors.total_subdiv > 0) { 22456 meter_attr->udf_pkt_attr_selectors_v.total_subdiv = 22457 udf_attr_selectors.total_subdiv; 22458 sal_memcpy(&meter_attr->udf_pkt_attr_selectors_v.udf_subdiv[0], 22459 &udf_attr_selectors.udf_subdiv[0], 22460 sizeof(udf_attr_selectors.udf_subdiv)); 22461 } 22462 22463 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 22464 offset_array[loop] = 22465 (uint8 *) sal_alloc(BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1, 22466 "offset_array"); 22467 if (offset_array[loop] == NULL) { 22468 rv = BCM_E_MEMORY; 22469 break; 22470 } 22471 } 22472 if (BCM_FAILURE(rv)) { 22473 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 22474 if (offset_array[loop] != NULL) { 22475 sal_free(offset_array[loop]); 22476 } 22477 } 22478 sal_free(meter_attr); 22479 sal_free(udf_attr_selectors.combine_attr_data); 22480 return rv; 22481 } 22482 /* Loop through all policer offset and compute offset map */ 22483 for (pol_offset = 0; pol_offset < npolicers; pol_offset++) { 22484 sal_memset(&loop_index_array[0], -1, sizeof (loop_index_array)); 22485 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 22486 sal_memset(offset_array[loop], 0, 22487 BCM_POLICER_SVC_METER_MAX_ATTR_SELECTORS + 1); 22488 } 22489 loop = loop_index = 0; 22490 udf_combine_data = &udf_attr_selectors.combine_attr_data[pol_offset]; 22491 /* Loop through all udf sub-division per policer offset */ 22492 for (index1 = 0; index1 < udf_combine_data->selectors; index1++) { 22493 offset = udf_combine_data->udf_subdiv[index1].offset; 22494 /* Get loop_index */ 22495 if (loop_index_array[offset] == -1) { 22496 loop_index_array[offset] = loop_index; 22497 loop_index++; 22498 } 22499 loop = loop_index_array[offset]; 22500 22501 /* get current count */ 22502 total_offsets = offset_array[loop][0]; 22503 /* Save the value */ 22504 offset_array[loop][total_offsets + 1] = 22505 udf_combine_data->attr_value[index1] << shift_by_bits_array[offset]; 22506 offset_array[loop][0] = total_offsets + 1; 22507 } 22508 if (udf_attr_selectors.drop == 1) { 22509 loop = loop_index; 22510 total_offsets = offset_array[loop][0]; 22511 if ((udf_combine_data->drop_flags & _BCM_POLICER_DROP_DISABLE) != 0) { 22512 offset_array[loop][total_offsets + 1] = 0; 22513 total_offsets++; 22514 } 22515 if ((udf_combine_data->drop_flags & _BCM_POLICER_DROP_ENABLE) != 0) { 22516 offset_array[loop][total_offsets + 1] = 1; 22517 total_offsets++; 22518 } 22519 offset_array[loop][0] = total_offsets; 22520 } 22521 22522 /* Make final offset calculation */ 22523 rv = _bcm_policer_group_mode_offset_map_generate(unit, meter_attr, 22524 group_mode, pol_offset, offset_array); 22525 if (rv != BCM_E_NONE) { 22526 break; 22527 } 22528 } 22529 22530 for (loop = 0; loop < SVC_METER_MAX_SELECTOR_BITS; loop++) { 22531 if (offset_array[loop] != NULL) { 22532 sal_free(offset_array[loop]); 22533 } 22534 } 22535 if (udf_attr_selectors.combine_attr_data != NULL) { 22536 sal_free(udf_attr_selectors.combine_attr_data); 22537 } 22538 22539 GLOBAL_METER_LOCK(unit); 22540 rv = _bcm_esw_policer_svc_meter_create_mode (unit, meter_attr, group_mode, 22541 type, total_policers, NULL, mode_id); 22542 if (BCM_FAILURE(rv) && (rv != BCM_E_EXISTS)) { 22543 GLOBAL_METER_UNLOCK(unit); 22544 sal_free(meter_attr); 22545 return rv; 22546 } else if (rv == BCM_E_EXISTS) { 22547 GLOBAL_METER_UNLOCK(unit); 22548 sal_free(meter_attr); 22549 return BCM_E_NONE; 22550 } else { 22551 /* In case of group type is cascade/cascadewithcoupling, total_policers 22552 * must be set to 8. This requirement is due to the fact that in these 22553 * two cases, meter index allocation is whole octuple */ 22554 if ((type == bcmPolicerGroupModeTypeCascade) || 22555 (type == bcmPolicerGroupModeTypeCascadeWithCoupling)) { 22556 global_meter_offset_mode[unit][*mode_id].no_of_policers = 8; 22557 } else { 22558 global_meter_offset_mode[unit][*mode_id].no_of_policers = 22559 total_policers; 22560 } 22561 22562 rv = _bcm_policer_svc_meter_group_offset_mode_info_update (unit, 22563 *mode_id, type, num_selectors, attr_selectors); 22564 if (BCM_FAILURE(rv)) { 22565 _bcm_policer_svc_meter_unreserve_mode (unit, *mode_id); 22566 GLOBAL_METER_UNLOCK(unit); 22567 sal_free(meter_attr); 22568 return rv; 22569 } 22570 } 22571 GLOBAL_METER_UNLOCK(unit); 22572 sal_free(meter_attr); 22573 return rv; 22574 } 22575 22576 /* 22577 * Function: 22578 * bcm_esw_policer_group_mode_id_create 22579 * Purpose: 22580 * Create Customized Policer Group mode for given Policer Attributes 22581 * Parameters: 22582 * unit - (IN) unit number 22583 * flags - (IN) flags 22584 * type - (IN) modes of policer group creation - 22585 * normal/cascade/cascade with coupling. 22586 * total_policers - (IN) Total Policers in Policer Group Mode 22587 * num_selectors - (IN) Number of Selectors for policer Group Mode 22588 * attr_selectors - (IN) Attribute Selectors for Policer Group Mode 22589 * mode_id - (OUT) Created mode Id for Policer Group Mode 22590 * Returns: 22591 * BCM_E_XXX 22592 */ 22593 int 22594 bcm_esw_policer_group_mode_id_create( 22595 int unit, 22596 uint32 flags, 22597 bcm_policer_group_mode_type_t type, 22598 uint32 total_policers, 22599 uint32 num_selectors, 22600 bcm_policer_group_mode_attr_selector_t *attr_selectors, 22601 uint32 *mode_id) 22602 { 22603 int rv = BCM_E_NONE; 22604 int num_pools = 0; 22605 uint32 index = 0; 22606 int8 custom_group_udf_type = -1; 22607 22608 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 22609 if (soc_feature(unit, soc_feature_global_meter_v2)) { 22610 return bcmi_esw_policer_group_mode_id_create(unit, 22611 flags, type, total_policers, num_selectors, 22612 attr_selectors, mode_id); 22613 } 22614 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 22615 22616 num_pools = SOC_INFO(unit).global_meter_pools; 22617 22618 if (!soc_feature(unit, soc_feature_global_meter)) { 22619 return BCM_E_UNAVAIL; 22620 } 22621 22622 if (type >= bcmPolicerGroupModeTypeCount) { 22623 return (BCM_E_PARAM); 22624 } 22625 22626 /* Attribute selectors are used for selecting one of the policers created in 22627 * policer group. For total_policer=1 there is just one policer. 22628 * Hence, attribute selectors have no significance. 22629 * All other IN parameters are set fixed to avoid any confusion 22630 * while fetching group policer config via bcm_policer_group_mode_id_get() 22631 */ 22632 if (total_policers == 1) { 22633 if ((type == bcmPolicerGroupModeTypeNormal) && 22634 (attr_selectors == NULL) && 22635 (num_selectors == 0)) { 22636 *mode_id = 1; 22637 return (BCM_E_NONE); 22638 } else if ((type != bcmPolicerGroupModeTypeNormal) || 22639 !soc_feature(unit, 22640 soc_feature_global_meter_compaction_support)) { 22641 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, "Single policer" 22642 " with ModeType Not Normal is not allowed\n"))); 22643 return (BCM_E_PARAM); 22644 } 22645 } 22646 22647 if ((total_policers == 0) || (num_selectors == 0)) { 22648 return (BCM_E_PARAM); 22649 } 22650 if ((type == bcmPolicerGroupModeTypeNormal) && (total_policers > 256)) { 22651 return (BCM_E_PARAM); 22652 } 22653 if ((type == bcmPolicerGroupModeTypeCascade) 22654 && (total_policers > num_pools)) { 22655 return (BCM_E_PARAM); 22656 } 22657 if (type == bcmPolicerGroupModeTypeCascadeWithCoupling) { 22658 if (total_policers > (num_pools/2)) { 22659 return (BCM_E_PARAM); 22660 } 22661 total_policers = 8; 22662 } 22663 22664 if (attr_selectors == NULL) { 22665 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22666 "Packet attributes selector(s) is(are) not provided\n"))); 22667 return (BCM_E_PARAM); 22668 } 22669 22670 /* loop through attr_selectors[x].attr to determine correct internal API call */ 22671 for (index = 0; index < num_selectors; index++) { 22672 if (attr_selectors[index].attr == bcmPolicerGroupModeAttrUdf) { 22673 if (custom_group_udf_type == 0) { 22674 rv = BCM_E_PARAM; 22675 break; 22676 } 22677 custom_group_udf_type = 1; 22678 } else if (attr_selectors[index].attr != bcmPolicerGroupModeAttrDrop) { 22679 if (custom_group_udf_type == 1) { 22680 rv = BCM_E_PARAM; 22681 break; 22682 } 22683 custom_group_udf_type = 0; 22684 } 22685 } 22686 if (rv == BCM_E_PARAM) { 22687 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22688 "Mix of UDF and other attributes not allowed\n"))); 22689 return rv; 22690 } 22691 22692 if (custom_group_udf_type == 0) { 22693 rv = _bcm_policer_custom_group_mode_id_create(unit, flags, type, 22694 total_policers, num_selectors, 22695 attr_selectors, mode_id); 22696 } else { 22697 rv = _bcm_esw_policer_udf_custom_group_create(unit, flags, type, 22698 total_policers, num_selectors, 22699 attr_selectors, mode_id); 22700 } 22701 if (rv == BCM_E_EXISTS) { 22702 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 22703 *mode_id = *mode_id + 1; 22704 } 22705 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22706 " policer group mode id exists, mode id 8x%x\n"), *mode_id)); 22707 return (rv); 22708 } else if (BCM_FAILURE(rv)) { 22709 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22710 "Unable to create policer group \n"))); 22711 return (rv); 22712 } 22713 *mode_id = *mode_id + 1; 22714 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22715 "Created policer group with mode id 0x%x \n"), *mode_id)); 22716 return rv; 22717 22718 } 22719 22720 /* 22721 * Function: 22722 * bcm_esw_policer_group_mode_id_destroy 22723 * Purpose: 22724 * Destroy Customized Policer Group mode with given mode_id. 22725 * Parameters: 22726 * unit - (IN) unit number 22727 * mode_id - (IN) Created mode Id for Policer Group Mode 22728 * Returns: 22729 * BCM_E_XXX 22730 */ 22731 int 22732 bcm_esw_policer_group_mode_id_destroy( 22733 int unit, 22734 uint32 mode_id) 22735 { 22736 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 22737 int rv = BCM_E_NONE; 22738 22739 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 22740 if (soc_feature(unit, soc_feature_global_meter_v2)) { 22741 return bcmi_esw_policer_group_mode_id_destroy(unit, mode_id); 22742 } 22743 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 22744 22745 if (!soc_feature(unit, soc_feature_global_meter)) { 22746 return BCM_E_UNAVAIL; 22747 } 22748 if ((mode_id == 0) || (mode_id > BCM_POLICER_SVC_METER_MAX_MODE)) { 22749 return (BCM_E_PARAM); 22750 } 22751 mode_id -= 1; 22752 if (mode_id == 0) { 22753 return (BCM_E_NONE); 22754 } 22755 22756 sal_memset(&mode_info, 0, sizeof(mode_info)); 22757 rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id, &mode_info); 22758 BCM_IF_ERROR_RETURN(rv); 22759 22760 if (mode_info.reference_count > 0) { 22761 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 22762 "Policer group mode is still in use \n"))); 22763 return (BCM_E_BUSY); 22764 } else { 22765 rv = _bcm_esw_policer_svc_meter_delete_mode(unit, mode_id); 22766 } 22767 return rv; 22768 } 22769 22770 /* 22771 * Function: 22772 * bcm_esw_policer_group_mode_id_get 22773 * Purpose: 22774 * Retrieves Customized Policer Group mode Attributes for given mode_id. 22775 * Parameters: 22776 * unit - (IN) unit number 22777 * mode_id - (IN) Created mode Id for Policer Group Mode 22778 * num_selectors - (IN) Number of Selectors for policer Group Mode 22779 * flags - (OUT) flags 22780 * type - (OUT) modes of policer group creation - 22781 * normal/cascade/cascade with coupling. 22782 * total_policers - (OUT) Total Policers in Policer Group Mode 22783 * attr_selectors - (OUT) Attribute Selectors for Policer Group Mode 22784 * actual_num_selectors - (OUT) Actual Number of Selectors for Policer 22785 * Group Mode 22786 * Returns: 22787 * BCM_E_XXX 22788 */ 22789 int 22790 bcm_esw_policer_group_mode_id_get( 22791 int unit, 22792 uint32 mode_id, 22793 uint32 num_selectors, 22794 uint32 *flags, 22795 bcm_policer_group_mode_type_t *type, 22796 uint32 *total_policers, 22797 bcm_policer_group_mode_attr_selector_t *attr_selectors, 22798 uint32 *actual_num_selectors) 22799 { 22800 int rv = BCM_E_NONE; 22801 bcm_policer_svc_meter_bookkeep_mode_t mode_info; 22802 udf_pkt_attr_selectors_t *udf_attr = NULL; 22803 int i, j; 22804 int pool_offset_limit; 22805 bcm_policer_svc_meter_mode_type_t mode_type_v; 22806 22807 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 22808 if (soc_feature(unit, soc_feature_global_meter_v2)) { 22809 return bcmi_esw_policer_group_mode_id_get(unit, 22810 mode_id, num_selectors, flags, type, total_policers, 22811 attr_selectors, actual_num_selectors); 22812 } 22813 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 22814 22815 if (!soc_feature(unit, soc_feature_global_meter)) { 22816 return BCM_E_UNAVAIL; 22817 } 22818 if ((mode_id == 0) || (mode_id > BCM_POLICER_SVC_METER_MAX_MODE)) { 22819 return (BCM_E_PARAM); 22820 } 22821 if (mode_id == 1) { 22822 *flags = 0; 22823 *type = bcmPolicerGroupModeTypeNormal; 22824 *actual_num_selectors = 0; 22825 *total_policers = 1; 22826 return BCM_E_NONE; 22827 } 22828 22829 sal_memset (&mode_info, 0, sizeof(mode_info)); 22830 rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id - 1, &mode_info); 22831 BCM_IF_ERROR_RETURN(rv); 22832 22833 *total_policers = mode_info.no_of_policers; 22834 if (mode_info.group_mode == bcmPolicerGroupModeCascadeWithCoupling) { 22835 *total_policers = mode_info.no_of_policers / 2; 22836 } 22837 22838 *flags = 0; 22839 mode_type_v = mode_info.meter_attr.mode_type_v; 22840 if ((mode_info.type != -1) && 22841 (mode_info.attr_selectors != NULL)) { 22842 *type = mode_info.type; 22843 *actual_num_selectors = mode_info.no_of_selectors; 22844 22845 if (mode_info.attr_selectors != NULL) { 22846 rv = _bcm_wb_attr_selectors_copy_to_attr_selectors( 22847 mode_info.no_of_selectors, 22848 mode_info.attr_selectors, attr_selectors); 22849 BCM_IF_ERROR_RETURN(rv); 22850 } 22851 return BCM_E_NONE; 22852 } 22853 22854 switch (mode_type_v) { 22855 case udf_mode: 22856 { 22857 udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v; 22858 *type = bcmPolicerGroupModeTypeNormal; 22859 *actual_num_selectors = mode_info.no_of_selectors; 22860 if (num_selectors > *actual_num_selectors) { 22861 num_selectors = *actual_num_selectors; 22862 } 22863 j = 0; 22864 for (i = 0; i < BCM_SVC_METER_MAP_SIZE_256; i++) { 22865 if (udf_attr->offset_map[i].meter_enable == 1) { 22866 attr_selectors[j].attr_value = i; 22867 attr_selectors[j].policer_offset = 22868 udf_attr->offset_map[i].offset; 22869 attr_selectors[j].udf_id = udf_attr->udf_id; 22870 attr_selectors[j].width = udf_attr->udf_subdiv[0].width; 22871 attr_selectors[j].flags |= BCM_POLICER_ATTR_WIDTH_OFFSET; 22872 attr_selectors[j].attr = bcmPolicerGroupModeAttrUdf; 22873 attr_selectors[j].offset = udf_attr->udf_subdiv[0].offset; 22874 22875 j++; 22876 } 22877 } 22878 break; 22879 } 22880 case udf_cascade_mode: 22881 case udf_cascade_with_coupling_mode: 22882 { 22883 udf_attr = &mode_info.meter_attr.udf_pkt_attr_selectors_v; 22884 pool_offset_limit = 22885 (mode_info.group_mode == bcmPolicerGroupModeCascade) ? 22886 BCM_POLICER_GLOBAL_METER_MAX_POOL : 22887 BCM_POLICER_GLOBAL_METER_MAX_POOL/2; 22888 *type = (mode_type_v == udf_cascade_mode) ? 22889 bcmPolicerGroupModeTypeCascade : 22890 bcmPolicerGroupModeTypeCascadeWithCoupling; 22891 *actual_num_selectors = mode_info.no_of_selectors; 22892 if (num_selectors > *actual_num_selectors) { 22893 num_selectors = *actual_num_selectors; 22894 } 22895 j = 0; 22896 for (i = 0; i < BCM_SVC_METER_MAP_SIZE_256; i++) { 22897 if (udf_attr->offset_map[i].meter_enable == 1) { 22898 attr_selectors[j].attr_value = i; 22899 attr_selectors[j].udf_id = udf_attr->udf_id; 22900 attr_selectors[j].width = udf_attr->udf_subdiv[0].width; 22901 attr_selectors[j].flags |= BCM_POLICER_ATTR_WIDTH_OFFSET; 22902 attr_selectors[j].attr = bcmPolicerGroupModeAttrUdf; 22903 attr_selectors[j].offset = udf_attr->udf_subdiv[0].offset; 22904 22905 if (soc_feature(unit, 22906 soc_feature_global_meter_pool_priority_descending)) { 22907 attr_selectors[j].policer_offset = (pool_offset_limit - 22908 udf_attr->offset_map[i].pool - 1); 22909 } else { 22910 attr_selectors[j].policer_offset = 22911 udf_attr->offset_map[i].pool; 22912 } 22913 j++; 22914 } 22915 } 22916 break; 22917 } 22918 default: 22919 return BCM_E_UNAVAIL; 22920 break; 22921 } 22922 return BCM_E_NONE; 22923 } 22924 22925 STATIC int 22926 _global_meter_policer_group_alloc( 22927 int unit, 22928 int direction, 22929 int numbers, 22930 bcm_policer_t *pid, 22931 _bcm_policer_flow_info_t *flow_info, 22932 uint8 *pid_offset) 22933 { 22934 int rv = BCM_E_NONE; 22935 int index = 0; 22936 int base_idx = 0; 22937 int num_pools = 0; 22938 int size_pool = 0; 22939 int req_bank = 0; 22940 int bank_size = 0; 22941 int num_banks_per_pool = 0; 22942 bcm_policer_t policer_id = 0; 22943 22944 num_pools = SOC_INFO(unit).global_meter_pools; 22945 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 22946 num_banks_per_pool = get_max_banks_in_a_pool(unit); 22947 bank_size = size_pool / num_banks_per_pool; 22948 22949 if (flow_info->req_alloc == TRUE) { 22950 if (flow_info->req_pool >= num_pools) { 22951 return BCM_E_PARAM; 22952 } 22953 base_idx = (flow_info->req_pool * size_pool); 22954 base_idx += flow_info->req_base_offset; 22955 22956 rv = _bcm_esw_get_policer_id_from_index_offset(unit, 22957 base_idx, flow_info->mode_id, &policer_id); 22958 BCM_IF_ERROR_RETURN(rv); 22959 22960 if (direction == GLOBAL_METER_ALLOC_VERTICAL) { 22961 /* Check Boundary condition */ 22962 if ((flow_info->req_base_offset + numbers) > size_pool) { 22963 rv = BCM_E_RESOURCE; 22964 LOG_DEBUG(BSL_LS_BCM_POLICER, 22965 (BSL_META_U(unit, "Number of policers in requested" 22966 " group exceeds pool size with given" 22967 " base offset.\n"))); 22968 } else if (flow_info->flow_type == bcmPolicerFlowTypeMicro) { 22969 /* Check Micro policer conditions */ 22970 req_bank = flow_info->req_base_offset / bank_size; 22971 22972 if (soc_feature(unit, 22973 soc_feature_global_meter_macro_micro_same_pool)) { 22974 if ((flow_info->req_pool != flow_info->skip_pool) || 22975 ((flow_info->req_pool == flow_info->skip_pool) && 22976 (req_bank == flow_info->skip_bank))) { 22977 rv = BCM_E_PARAM; 22978 LOG_DEBUG(BSL_LS_BCM_POLICER, 22979 (BSL_META_U(unit, "Micro policer cannot be" 22980 " present in same" 22981 " bank as macropolicer.\n"))); 22982 } 22983 } else { 22984 if (flow_info->req_pool == flow_info->skip_pool) { 22985 rv = BCM_E_PARAM; 22986 LOG_DEBUG(BSL_LS_BCM_POLICER, 22987 (BSL_META_U(unit, "Micro policer cannot be" 22988 " present in same" 22989 " pool as macropolicer.\n"))); 22990 } 22991 } 22992 } 22993 } else if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 22994 /* Check Boundary condition */ 22995 if (flow_info->req_base_offset >= size_pool) { 22996 LOG_DEBUG(BSL_LS_BCM_POLICER, 22997 (BSL_META_U(unit, "Number of policers in requested" 22998 " group exceeds pool size with given" 22999 " base offset.\n"))); 23000 rv = BCM_E_RESOURCE; 23001 } else if (flow_info->req_pool != 0) { 23002 LOG_DEBUG(BSL_LS_BCM_POLICER, 23003 (BSL_META_U(unit, "ModeType cascade and" 23004 " CascadeWithCoupling should" 23005 " have pool set to 0.\n"))); 23006 rv = BCM_E_PARAM; 23007 } 23008 for (index = 0; index < 8; index++) { 23009 pid_offset[index] = index; 23010 } 23011 } 23012 BCM_IF_ERROR_RETURN(rv); 23013 23014 rv = _global_meter_reserve_policer_id(unit, 23015 direction, numbers, policer_id, &pid_offset[0]); 23016 if (rv == BCM_E_INTERNAL) { 23017 rv = BCM_E_RESOURCE; 23018 } 23019 } else { 23020 rv = _global_meter_policer_id_alloc(unit, direction, 23021 &numbers, &policer_id, flow_info, &pid_offset[0]); 23022 } 23023 23024 *pid = policer_id; 23025 23026 return rv; 23027 } 23028 23029 /* Create custom policer group */ 23030 int 23031 _bcm_esw_policer_custom_group_id_create( 23032 int unit, 23033 uint32 flags, 23034 uint32 mode_id, 23035 bcm_policer_t macro_flow_policer_id, 23036 bcm_policer_group_info_t *policer_group_info) 23037 { 23038 int rv = BCM_E_NONE; 23039 int num_banks_per_pool = 0; 23040 int index = 0; 23041 int size_pool = 0, num_pools = 0; 23042 int pool_mask = 0, pool_offset = 0; 23043 int micro_flow_index = 0; 23044 int macro_flow_index = 0; 23045 int npolicers = 0; 23046 int pool_id = 0; 23047 int bank_size = 0; 23048 int offset_mask = 0; 23049 int skip_pool = 0, skip_bank = 0; 23050 int req_alloc = FALSE; 23051 int req_pool = 0, req_base_offset = 0; 23052 int entry_mem_size = 0; 23053 int entry_index = 0; 23054 int entry_index_max = 0; 23055 uint32 direction = 0; 23056 bcm_policer_t policer_id = 0; 23057 bcm_policer_group_mode_t mode = 0; 23058 bcm_policer_svc_meter_bookkeep_mode_t *mode_info = NULL; 23059 _global_meter_policer_control_t *policer_control = NULL; 23060 uint8 pid_offset[BCM_POLICER_GLOBAL_METER_MAX_POOL] = {0}; 23061 _bcm_policer_flow_type_t flow_type = bcmPolicerFlowTypeNormal; 23062 _bcm_policer_flow_info_t flow_info; 23063 svm_macroflow_index_table_entry_t *buf = NULL; 23064 svm_macroflow_index_table_entry_t *entry = NULL; 23065 23066 if (!soc_feature(unit, soc_feature_global_meter)) { 23067 return BCM_E_UNAVAIL; 23068 } 23069 23070 if ((mode_id == 0) || 23071 (mode_id > BCM_POLICER_SVC_METER_MAX_MODE) || 23072 (policer_group_info == NULL)) { 23073 return (BCM_E_PARAM); 23074 } 23075 23076 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 23077 num_pools = SOC_INFO(unit).global_meter_pools; 23078 offset_mask = size_pool - 1; 23079 pool_offset = _shr_popcount(offset_mask); 23080 pool_mask = (num_pools - 1) << pool_offset; 23081 23082 (void) _bcm_policer_flow_info_t_init(&flow_info); 23083 num_banks_per_pool = get_max_banks_in_a_pool(unit); 23084 bank_size = size_pool / num_banks_per_pool; 23085 23086 if (soc_feature(unit, 23087 soc_feature_global_meter_compaction_support)) { 23088 if ((policer_group_info->pool_id == 0) && 23089 (policer_group_info->base_offset == 0)) { 23090 LOG_DEBUG(BSL_LS_BCM_POLICER, 23091 (BSL_META_U(unit, 23092 "pool id 0 and base offset 0 " 23093 " is reserved and cannot be used\n"))); 23094 return BCM_E_PARAM; 23095 } 23096 req_alloc = TRUE; 23097 req_pool = policer_group_info->pool_id; 23098 req_base_offset = policer_group_info->base_offset; 23099 } else { 23100 req_alloc = FALSE; 23101 req_pool = num_pools; 23102 req_base_offset = size_pool; 23103 } 23104 23105 _GLOBAL_METER_XGS3_ALLOC(mode_info, 23106 sizeof (bcm_policer_svc_meter_bookkeep_mode_t), "mode bookkeep info"); 23107 if (mode_info == NULL) { 23108 LOG_DEBUG(BSL_LS_BCM_POLICER, 23109 (BSL_META_U(unit, "Failure to allocate memory.\n"))); 23110 return (BCM_E_MEMORY); 23111 } 23112 23113 mode_id -= 1; 23114 if (mode_id == 0) { 23115 npolicers = 1; 23116 } else { 23117 rv = _bcm_policer_svc_meter_get_mode_info(unit, mode_id, mode_info); 23118 if (rv != BCM_E_NONE) { 23119 sal_free(mode_info); 23120 LOG_DEBUG(BSL_LS_BCM_POLICER, 23121 (BSL_META_U(unit, "Mode Id get failed.\n"))); 23122 return rv; 23123 } 23124 /* Allow only when Group mode Id is created explicitly */ 23125 if (mode_info->type == -1) { 23126 sal_free(mode_info); 23127 LOG_DEBUG(BSL_LS_BCM_POLICER, 23128 (BSL_META_U(unit, "Mode Id is not created.\n"))); 23129 return BCM_E_PARAM; 23130 } 23131 npolicers = mode_info->no_of_policers; 23132 } 23133 23134 direction = GLOBAL_METER_ALLOC_VERTICAL; 23135 mode = bcmPolicerGroupModeSingle; 23136 if (npolicers != 1) { 23137 if (mode_info->group_mode == bcmPolicerGroupModeCascade) { 23138 direction = GLOBAL_METER_ALLOC_HORIZONTAL; 23139 mode = bcmPolicerGroupModeCascade; 23140 } else if (mode_info->group_mode == 23141 bcmPolicerGroupModeCascadeWithCoupling) { 23142 direction = GLOBAL_METER_ALLOC_HORIZONTAL; 23143 mode = bcmPolicerGroupModeCascadeWithCoupling; 23144 } 23145 } 23146 23147 /* Free mode_info */ 23148 if (mode_info != NULL) { 23149 sal_free(mode_info); 23150 } 23151 23152 if (macro_flow_policer_id > 0) { 23153 skip_pool = (macro_flow_policer_id & pool_mask) >> pool_offset; 23154 skip_bank = (macro_flow_policer_id & offset_mask) / bank_size; 23155 flow_type = bcmPolicerFlowTypeMicro; 23156 } else { 23157 skip_pool = num_pools; 23158 skip_bank = num_banks_per_pool; 23159 flow_type = bcmPolicerFlowTypeNormal; 23160 } 23161 /* Validate flowtype */ 23162 if (flow_type == bcmPolicerFlowTypeMicro) { 23163 /* Validate Mode */ 23164 if ((mode == bcmPolicerGroupModeCascade) || 23165 (mode == bcmPolicerGroupModeCascadeWithCoupling)) { 23166 LOG_ERROR(BSL_LS_BCM_POLICER, 23167 (BSL_META_U(unit, 23168 "Unable to create micro flow policers " 23169 "due to unsupported mode\n"))); 23170 return (BCM_E_PARAM); 23171 } 23172 23173 /* Validate Macro policer */ 23174 rv = _bcm_esw_policer_validate(unit, ¯o_flow_policer_id); 23175 if (!(BCM_SUCCESS(rv))) { 23176 LOG_DEBUG(BSL_LS_BCM_POLICER, 23177 (BSL_META_U(unit, 23178 "Invalid Macro policer Id passed\n"))); 23179 return rv; 23180 } 23181 rv = _bcm_global_meter_macro_policer_validate(unit, 23182 macro_flow_policer_id); 23183 if (!(BCM_SUCCESS(rv))) { 23184 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23185 "Macro flow policer Id = %d is not found or" 23186 " not configured properly to be used as macro" 23187 " policer\n"), macro_flow_policer_id)); 23188 return rv; 23189 } 23190 rv = _bcm_esw_get_policer_table_index(unit, 23191 macro_flow_policer_id, ¯o_flow_index); 23192 if (!(BCM_SUCCESS(rv))) { 23193 LOG_DEBUG(BSL_LS_BCM_POLICER, 23194 (BSL_META_U(unit, 23195 "Unable to Get policer index for macro flow " 23196 "policer \n"))); 23197 return rv; 23198 } 23199 } 23200 23201 /* Populate flow info */ 23202 flow_info.mode_id = mode_id; 23203 flow_info.flow_type = flow_type; 23204 flow_info.req_alloc = req_alloc; 23205 flow_info.skip_pool = skip_pool; 23206 flow_info.skip_bank = skip_bank; 23207 flow_info.req_pool = req_pool; 23208 flow_info.req_base_offset = req_base_offset; 23209 23210 GLOBAL_METER_LOCK(unit); 23211 rv = _global_meter_policer_group_alloc(unit, 23212 direction, npolicers, &policer_id, 23213 &flow_info, &pid_offset[0]); 23214 if (!(BCM_SUCCESS(rv))) { 23215 GLOBAL_METER_UNLOCK(unit); 23216 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23217 "Failed to allocate policer \n"))); 23218 return rv; 23219 } 23220 offset_mask = SOC_INFO(unit).global_meter_max_size_of_pool - 1; 23221 23222 /* Allocate policer descriptor. */ 23223 _GLOBAL_METER_XGS3_ALLOC(policer_control, 23224 sizeof (_global_meter_policer_control_t), "Global meter policer"); 23225 23226 if (NULL == policer_control) { 23227 _bcm_global_meter_free_allocated_policer_on_error(unit, npolicers, 23228 &pid_offset[0], (policer_id & offset_mask)); 23229 GLOBAL_METER_UNLOCK(unit); 23230 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23231 "Unable to allocate memeory for policer control \n"))); 23232 return (BCM_E_MEMORY); 23233 } 23234 23235 /* Add mode info to the policer index */ 23236 policer_id |= (mode_id + 1) << BCM_POLICER_GLOBAL_METER_MODE_SHIFT; 23237 23238 /* Set policer configuration */ 23239 policer_control->direction = direction; 23240 policer_control->pid = policer_id; 23241 policer_control->no_of_policers = npolicers; 23242 policer_control->grp_mode = mode; 23243 23244 if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 23245 index = 0; 23246 do { 23247 policer_control->offset[index] = pid_offset[index]; 23248 index++; 23249 } while (index < (npolicers)); 23250 23251 if (soc_feature(unit, soc_feature_global_meter_mef_10dot3)) { 23252 rv = _bcm_esw_global_meter_set_cascade_info_mef_10dot3_to_hw(unit, 23253 npolicers, policer_id, mode, &pid_offset[0]); 23254 } else { 23255 rv = _bcm_esw_global_meter_set_cascade_info_to_hw(unit, 23256 npolicers, policer_id, mode, &pid_offset[0]); 23257 } 23258 23259 if (!(BCM_SUCCESS(rv))) { 23260 /* free all the allocated policers */ 23261 _bcm_global_meter_free_allocated_policer_on_error(unit, npolicers, 23262 &pid_offset[0], (policer_id & offset_mask)); 23263 /* De-allocate policer descriptor. */ 23264 sal_free(policer_control); 23265 GLOBAL_METER_UNLOCK(unit); 23266 LOG_DEBUG(BSL_LS_BCM_POLICER, 23267 (BSL_META_U(unit, "Failed to create cascade chain" 23268 " in meter table.\n"))); 23269 return rv; 23270 } 23271 } 23272 23273 /* increment mode reference count for new policer */ 23274 if (mode_id) { 23275 rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, mode_id); 23276 if (!(BCM_SUCCESS(rv))) { 23277 /* free all the allocated policers */ 23278 _bcm_global_meter_free_allocated_policer_on_error(unit,npolicers, 23279 &pid_offset[0], (policer_id & offset_mask)); 23280 /* De-allocate policer descriptor. */ 23281 sal_free(policer_control); 23282 GLOBAL_METER_UNLOCK(unit); 23283 LOG_DEBUG(BSL_LS_BCM_POLICER, 23284 (BSL_META_U(unit, "Failed to update reference" 23285 " for group mode id.\n"))); 23286 return rv; 23287 } 23288 } 23289 if (mode == bcmPolicerGroupModeCascadeWithCoupling) { 23290 npolicers = npolicers / 2; 23291 } 23292 23293 /* Insert policer into policers hash. */ 23294 _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit], 23295 policer_control, (policer_id & _GLOBAL_METER_HASH_MASK)); 23296 23297 /* Configure SVM_MACROFLOW_INDEX table */ 23298 if (flow_type == bcmPolicerFlowTypeMicro) { 23299 /* get the HW index for the micro flow policer created */ 23300 rv = _bcm_esw_get_policer_table_index(unit, policer_id, 23301 µ_flow_index); 23302 if (BCM_FAILURE(rv)) { 23303 LOG_DEBUG(BSL_LS_BCM_POLICER, 23304 (BSL_META_U(unit, 23305 "Unable to Get policer index for micro flow " 23306 "policer \n"))); 23307 goto cleanup; 23308 } 23309 entry_mem_size = sizeof(svm_macroflow_index_table_entry_t); 23310 entry_index_max = micro_flow_index + npolicers - 1; 23311 /* Allocate buffer to store the DMAed table entries. */ 23312 buf = soc_cm_salloc(unit, entry_mem_size * npolicers, 23313 "svm macro flow index table entry buffer"); 23314 if (NULL == buf) { 23315 rv = BCM_E_MEMORY; 23316 LOG_DEBUG(BSL_LS_BCM_POLICER, 23317 (BSL_META_U(unit, "Failed to allocate memory" 23318 " for macroflow index table.\n"))); 23319 goto cleanup; 23320 } 23321 /* Initialize the entry buffer. */ 23322 sal_memset(buf, 0, sizeof(entry_mem_size) * npolicers); 23323 23324 /* Read the table entries into the buffer. */ 23325 rv = soc_mem_read_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 23326 MEM_BLOCK_ALL, micro_flow_index, 23327 entry_index_max, buf); 23328 if (BCM_FAILURE(rv)) { 23329 goto cleanup; 23330 } 23331 23332 /* Iterate over the table entries. */ 23333 for (entry_index = 0; entry_index < npolicers; entry_index++) { 23334 entry = soc_mem_table_idx_to_pointer(unit, 23335 SVM_MACROFLOW_INDEX_TABLEm, 23336 svm_macroflow_index_table_entry_t *, 23337 buf, entry_index); 23338 soc_mem_field_set(unit, SVM_MACROFLOW_INDEX_TABLEm, 23339 (void *)entry, MACROFLOW_INDEXf, 23340 (uint32 *)¯o_flow_index); 23341 rv = _bcm_esw_policer_increment_ref_count(unit, 23342 macro_flow_policer_id); 23343 if (BCM_FAILURE(rv)) { 23344 LOG_DEBUG(BSL_LS_BCM_POLICER, 23345 (BSL_META_U(unit, 23346 "Unable to increment ref count for micro flow " 23347 "policer\n"))); 23348 goto cleanup; 23349 } 23350 } 23351 if ((rv = soc_mem_write_range(unit, SVM_MACROFLOW_INDEX_TABLEm, 23352 MEM_BLOCK_ALL, micro_flow_index, 23353 entry_index_max, buf)) < 0) { 23354 if (BCM_FAILURE(rv)) { 23355 LOG_VERBOSE(BSL_LS_BCM_POLICER, 23356 (BSL_META_U(unit, 23357 "Unable to write to macro flow table at index " 23358 "provided\n"))); 23359 goto cleanup; 23360 } 23361 } 23362 } 23363 23364 cleanup: 23365 23366 GLOBAL_METER_UNLOCK(unit); 23367 23368 if (buf) { 23369 soc_cm_sfree(unit, buf); 23370 } 23371 23372 if (rv != BCM_E_NONE) { 23373 (void) _bcm_esw_global_meter_policer_destroy(unit, policer_id); 23374 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23375 "create failed with error=%d\n"), rv)); 23376 } else { 23377 /* Fill up policer group info */ 23378 (void) _bcm_esw_get_policer_table_index(unit, policer_id, &index); 23379 pool_id = (policer_id & pool_mask) >> pool_offset; 23380 23381 policer_group_info->policer_id = policer_id; 23382 policer_group_info->mode_id = (mode_id + 1); 23383 policer_group_info->mode = mode; 23384 policer_group_info->base_offset = index - (size_pool * pool_id); 23385 23386 if (direction == GLOBAL_METER_ALLOC_HORIZONTAL) { 23387 policer_group_info->direction = 23388 bcmPolicerGroupDirectionHorizontal; 23389 policer_group_info->pool_id = 0; 23390 policer_group_info->num_policers = npolicers; 23391 policer_group_info->num_offset_reserved = 8; 23392 policer_group_info->macro_policer_id = 0; 23393 } else { 23394 policer_group_info->pool_id = (uint32) pool_id; 23395 policer_group_info->direction = 23396 bcmPolicerGroupDirectionVertical; 23397 policer_group_info->num_policers = npolicers; 23398 policer_group_info->num_offset_reserved = npolicers; 23399 policer_group_info->macro_policer_id = macro_flow_policer_id; 23400 } 23401 23402 LOG_DEBUG(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23403 "create policer with id %x \n"), policer_id)); 23404 } 23405 return rv; 23406 } 23407 23408 /* 23409 * Function: 23410 * bcm_esw_policer_custom_group_create 23411 * Purpose: 23412 * Create a group of policers based on the mode. 23413 * Parameters: 23414 * unit - (IN) unit number 23415 * flags - (IN) flags 23416 * mode_id - (IN) Created Mode Id for Policer Group Mode 23417 * macro_flow_policer_id - (IN) Is an optional parameter and needs to be 23418 * passed only while creating the micro flow 23419 * policers of a hierarchical groupi 23420 * (2 stage policers). 23421 * policer_id - (OUT)Base policer Id 23422 * npolicers - (OUT) Number of policers created 23423 * Returns: 23424 * BCM_E_XXX 23425 */ 23426 int 23427 bcm_esw_policer_custom_group_create( 23428 int unit, 23429 uint32 flags, 23430 uint32 mode_id, 23431 bcm_policer_t macro_flow_policer_id, 23432 bcm_policer_t *policer_id, 23433 uint32 *npolicers) 23434 { 23435 bcm_policer_group_info_t policer_group_info; 23436 23437 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 23438 if (soc_feature(unit, soc_feature_global_meter_v2)) { 23439 return bcmi_esw_policer_custom_group_create(unit, 23440 flags, mode_id, macro_flow_policer_id, policer_id, npolicers); 23441 } 23442 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 23443 23444 if (soc_feature(unit, soc_feature_global_meter_compaction_support)) { 23445 return BCM_E_UNAVAIL; 23446 } 23447 23448 bcm_policer_group_info_t_init(&policer_group_info); 23449 23450 BCM_IF_ERROR_RETURN(_bcm_esw_policer_custom_group_id_create(unit, 23451 flags, mode_id, macro_flow_policer_id, &policer_group_info)); 23452 23453 *policer_id = policer_group_info.policer_id; 23454 *npolicers = policer_group_info.num_policers; 23455 23456 return BCM_E_NONE; 23457 } 23458 23459 /* 23460 * Function: 23461 * bcm_esw_policer_group_get 23462 * Purpose: 23463 * Get the list of policer members for a given policer group represented 23464 * by its base policer id 23465 * Parameters: 23466 * unit - (IN) unit number 23467 * policer_id - (IN) Base policer Id 23468 * member_max - (IN) Maximum number of policers to return in 23469 * the member_array parameter 23470 * member_array - (OUT) Place to store policer members of the 23471 * given policer group represented by its base_policer_id. 23472 * Memory need to be allocated by the end user before 23473 * calling the API 23474 * member_count - (OUT) Place to store total number of policers 23475 * configured in the given policer group represented 23476 * by base_policer_id 23477 23478 * Returns: 23479 * BCM_E_XXX 23480 */ 23481 int bcm_esw_policer_group_get ( 23482 int unit, 23483 bcm_policer_t base_policer_id, 23484 int member_max, 23485 bcm_policer_t *member_array, 23486 int *member_count) 23487 { 23488 int rv = BCM_E_NONE; 23489 int index, policer_offset, indices_to_fill; 23490 _global_meter_policer_control_t *policer_control = NULL; 23491 23492 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 23493 if (soc_feature(unit, soc_feature_global_meter_v2)) { 23494 return bcmi_esw_policer_group_get(unit, 23495 base_policer_id, member_max, member_array, member_count); 23496 } 23497 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 23498 23499 if (!soc_feature(unit, soc_feature_global_meter)) { 23500 return BCM_E_UNAVAIL; 23501 } 23502 CHECK_GLOBAL_METER_INIT(unit); 23503 23504 /* verify arguments */ 23505 if ((base_policer_id == 0) || (member_count == NULL)) { 23506 return BCM_E_PARAM; 23507 } 23508 if ((member_max > 0) && (member_array == NULL)) { 23509 return BCM_E_PARAM; 23510 } 23511 23512 rv = _bcm_esw_policer_validate(unit, &base_policer_id); 23513 BCM_IF_ERROR_RETURN(rv); 23514 23515 GLOBAL_METER_LOCK(unit); 23516 rv = _bcm_global_meter_base_policer_get(unit, base_policer_id, &policer_control); 23517 if (BCM_FAILURE(rv)) { 23518 GLOBAL_METER_UNLOCK(unit); 23519 LOG_DEBUG(BSL_LS_BCM_POLICER, 23520 (BSL_META_U(unit, 23521 "Unable to get policer control for the policer Id " 23522 "passed \n"))); 23523 return (rv); 23524 } 23525 23526 if ((policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling) || 23527 (policer_control->grp_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 23528 *member_count = policer_control->no_of_policers/2; 23529 } else { 23530 *member_count = policer_control->no_of_policers; 23531 } 23532 23533 if (member_max <= 0) { 23534 GLOBAL_METER_UNLOCK(unit); 23535 return rv; 23536 } 23537 23538 indices_to_fill = (member_max < *member_count) ? member_max : *member_count; 23539 23540 switch(policer_control->grp_mode) { 23541 case bcmPolicerGroupModeCascade: 23542 case bcmPolicerGroupModeCascadeWithCoupling: 23543 case bcmPolicerGroupModeCascadeDroppedPktExclude: 23544 case bcmPolicerGroupModeIntPriCascade: 23545 case bcmPolicerGroupModeIntPriCascadeWithCoupling: 23546 { 23547 for (index = 0; index < indices_to_fill; index++) { 23548 /* policer_control->offset[] stores offset/pool from 0 to 7 */ 23549 if (soc_feature(unit, 23550 soc_feature_global_meter_pool_priority_descending)) { 23551 policer_offset = *member_count - index - 1; 23552 } else { 23553 policer_offset = index; 23554 } 23555 23556 member_array[index] = base_policer_id + 23557 (policer_control->offset[policer_offset] * 23558 SOC_INFO(unit).global_meter_max_size_of_pool); 23559 } 23560 break; 23561 } 23562 default: 23563 { 23564 /* For every other modes, member policers are in same pool */ 23565 for (index = 0; index < indices_to_fill; index++) { 23566 member_array[index] = base_policer_id + index; 23567 } 23568 break; 23569 } 23570 } 23571 GLOBAL_METER_UNLOCK(unit); 23572 23573 return BCM_E_NONE; 23574 } 23575 23576 STATIC int 23577 _bcm_global_meter_copy_horizontally( 23578 int unit, 23579 bcm_policer_group_info_t *old_policer_group_info, 23580 bcm_policer_group_info_t *new_policer_group_info) 23581 { 23582 int rv = BCM_E_NONE; 23583 int noffsets = 0; 23584 int index = 0; 23585 int entry_index = 0; 23586 int size_pool = 0; 23587 uint32 action_id = 0; 23588 uint32 old_base_idx = 0, old_pool_id = 0; 23589 uint32 new_base_idx = 0, new_pool_id = 0; 23590 soc_mem_t mem = SVM_METER_TABLEm; 23591 svm_meter_table_entry_t entry_buf; 23592 23593 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 23594 noffsets = old_policer_group_info->num_offset_reserved; 23595 23596 old_base_idx = old_policer_group_info->pool_id * size_pool + 23597 old_policer_group_info->base_offset; 23598 old_pool_id = 0; 23599 23600 new_base_idx = old_policer_group_info->pool_id * size_pool + 23601 new_policer_group_info->base_offset; 23602 new_pool_id = 0; 23603 23604 mem = SVM_METER_TABLEm; 23605 for (index = 0; index < noffsets; index++) { 23606 entry_index = old_base_idx + (index + old_pool_id) * size_pool; 23607 23608 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, entry_index, &entry_buf); 23609 BCM_IF_ERROR_RETURN(rv); 23610 23611 action_id = soc_mem_field32_get(unit, 23612 mem, &entry_buf, POLICY_TABLE_INDEXf); 23613 23614 if (global_meter_action_bookkeep[unit][action_id].used == 1) { 23615 global_meter_action_bookkeep[unit][action_id].reference_count++; 23616 } 23617 23618 entry_index = new_base_idx + (index + new_pool_id) * size_pool; 23619 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, entry_index, &entry_buf); 23620 BCM_IF_ERROR_RETURN(rv); 23621 } 23622 23623 return rv; 23624 } 23625 23626 STATIC int 23627 _bcm_global_meter_copy_vertically( 23628 int unit, 23629 bcm_policer_group_info_t *old_policer_group_info, 23630 bcm_policer_group_info_t *new_policer_group_info) 23631 { 23632 int rv = BCM_E_NONE; 23633 int noffsets = 0; 23634 int entry_index = 0; 23635 int size_pool = 0; 23636 int write_required = FALSE; 23637 int macroflow_index = 0; 23638 uint32 action_id = 0; 23639 uint32 old_base_idx = 0; 23640 uint32 new_base_idx = 0; 23641 soc_mem_t mem = INVALIDm; 23642 bcm_policer_t macroflow_policer = 0; 23643 bcm_policer_t old_macroflow_policer = 0; 23644 svm_meter_table_entry_t *buffer = NULL; 23645 svm_meter_table_entry_t *entry_buf = NULL; 23646 svm_macroflow_index_table_entry_t *macroflow_buffer = NULL; 23647 svm_macroflow_index_table_entry_t *macroflow_entry_buf = NULL; 23648 23649 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 23650 noffsets = old_policer_group_info->num_offset_reserved; 23651 old_macroflow_policer = old_policer_group_info->macro_policer_id; 23652 23653 old_base_idx = old_policer_group_info->pool_id * size_pool + 23654 old_policer_group_info->base_offset; 23655 new_base_idx = new_policer_group_info->pool_id * size_pool + 23656 new_policer_group_info->base_offset; 23657 23658 /* Update SVM_MACROFLOW_INDEX table */ 23659 macroflow_buffer = soc_cm_salloc(unit, 23660 sizeof(svm_macroflow_index_table_entry_t) * noffsets, 23661 "svm macroflow mem buffer"); 23662 if (NULL == macroflow_buffer) { 23663 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23664 "Failed to allocate memory for Macroflow buffer\n"))); 23665 return (BCM_E_MEMORY); 23666 } 23667 23668 /* Initialize the entry buffer. */ 23669 sal_memset(macroflow_buffer, 0, 23670 sizeof(svm_macroflow_index_table_entry_t) * noffsets); 23671 23672 mem = SVM_MACROFLOW_INDEX_TABLEm; 23673 23674 /* Read the table entries into the buffer. */ 23675 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 23676 old_base_idx, old_base_idx + noffsets - 1, 23677 macroflow_buffer); 23678 if (BCM_FAILURE(rv)) { 23679 if (macroflow_buffer != NULL) { 23680 soc_cm_sfree(unit, macroflow_buffer); 23681 } 23682 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23683 "Failed to read Macroflow Index table\n"))); 23684 return rv; 23685 } 23686 23687 /* Loop through each Macroflow Index */ 23688 for (entry_index = 0; entry_index < noffsets; entry_index++) { 23689 macroflow_entry_buf = soc_mem_table_idx_to_pointer(unit, 23690 mem, svm_macroflow_index_table_entry_t *, 23691 macroflow_buffer, entry_index); 23692 23693 macroflow_index = soc_mem_field32_get(unit, mem, 23694 macroflow_entry_buf, MACROFLOW_INDEXf); 23695 if (macroflow_index > 0) { 23696 (void) _bcm_esw_get_policer_id_from_index_offset(unit, 23697 macroflow_index, 0, ¯oflow_policer); 23698 if (macroflow_policer != old_macroflow_policer) { 23699 soc_mem_field32_set(unit, mem, macroflow_entry_buf, 23700 MACROFLOW_INDEXf, (uint32) macroflow_index); 23701 write_required = TRUE; 23702 /* Decrement count for old macro policer */ 23703 rv = _bcm_esw_policer_decrement_ref_count(unit, 23704 old_macroflow_policer); 23705 /* Increment count for new macor policer */ 23706 if (BCM_SUCCESS(rv)) { 23707 rv = _bcm_esw_policer_increment_ref_count(unit, 23708 macroflow_policer); 23709 } 23710 if (BCM_FAILURE(rv)) { 23711 LOG_DEBUG(BSL_LS_BCM_COMMON, 23712 (BSL_META_U(unit, 23713 "%u : Unable to increment ref count"), 23714 macroflow_index)); 23715 goto cleanup; 23716 } 23717 } 23718 } 23719 } 23720 23721 /* Write back at new location */ 23722 if (write_required == TRUE) { 23723 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 23724 new_base_idx, new_base_idx + noffsets - 1, macroflow_buffer); 23725 } 23726 23727 if (macroflow_buffer != NULL) { 23728 soc_cm_sfree(unit, macroflow_buffer); 23729 macroflow_buffer = NULL; 23730 } 23731 BCM_IF_ERROR_RETURN(rv); 23732 23733 buffer = soc_cm_salloc(unit, 23734 sizeof(svm_meter_table_entry_t) * noffsets, "svm mem buffer"); 23735 if (NULL == buffer) { 23736 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23737 "Failed to allocate memory for SVM buffer\n"))); 23738 return (BCM_E_MEMORY); 23739 } 23740 23741 mem = SVM_METER_TABLEm; 23742 23743 /* Initialize the entry buffer. */ 23744 sal_memset(buffer, 0, sizeof(svm_meter_table_entry_t) * noffsets); 23745 23746 /* Read the table entries into the buffer. */ 23747 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, 23748 old_base_idx, old_base_idx + noffsets - 1, buffer); 23749 if (BCM_FAILURE(rv)) { 23750 if (buffer) { 23751 soc_cm_sfree(unit, buffer); 23752 } 23753 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23754 "Failed to read meter table\n"))); 23755 return rv; 23756 } 23757 23758 for (entry_index = 0; entry_index < noffsets; entry_index++) { 23759 entry_buf = soc_mem_table_idx_to_pointer(unit, mem, 23760 svm_meter_table_entry_t *, buffer, entry_index); 23761 23762 action_id = soc_mem_field32_get(unit, 23763 mem, entry_buf, POLICY_TABLE_INDEXf); 23764 23765 if (global_meter_action_bookkeep[unit][action_id].used == 1) { 23766 global_meter_action_bookkeep[unit][action_id].reference_count++; 23767 } 23768 } 23769 23770 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, 23771 new_base_idx, new_base_idx + noffsets - 1, buffer); 23772 23773 cleanup: 23774 23775 if (macroflow_buffer != NULL) { 23776 soc_cm_sfree(unit, macroflow_buffer); 23777 macroflow_buffer = NULL; 23778 } 23779 if (buffer != NULL) { 23780 soc_cm_sfree(unit, buffer); 23781 buffer = NULL; 23782 } 23783 23784 return rv; 23785 } 23786 23787 /* 23788 * Function: 23789 * bcm_esw_policer_custom_group_id_create 23790 * Purpose: 23791 * Create a group of policers using mode id. 23792 * Parameters: 23793 * unit - (IN) unit number 23794 * flags - (IN) flags 23795 * mode_id - (IN) Created Mode Id for Policer Group Mode 23796 * macro_flow_policer_id - (IN) Is an optional parameter and needs to be 23797 * passed only while creating the micro flow 23798 * policers of a hierarchical groupi 23799 * (2 stage policers). 23800 * policer_group_info - (INOUT) Policer group info. 23801 * Returns: 23802 * BCM_E_XXX 23803 */ 23804 int 23805 bcm_esw_policer_custom_group_id_create( 23806 int unit, 23807 uint32 flags, 23808 uint32 mode_id, 23809 bcm_policer_t macro_flow_policer_id, 23810 bcm_policer_group_info_t *policer_group_info) 23811 { 23812 int rv = BCM_E_UNAVAIL; 23813 23814 if (soc_feature(unit, soc_feature_global_meter_compaction_support)) { 23815 rv = _bcm_esw_policer_custom_group_id_create(unit, 23816 flags, mode_id, macro_flow_policer_id, policer_group_info); 23817 } 23818 23819 return rv; 23820 } 23821 23822 /* 23823 * Function: 23824 * bcm_esw_policer_custom_group_id_copy 23825 * Purpose: 23826 * Copy all policer offsets in the old policer group 23827 * to new hardware indices. 23828 * Parameters: 23829 * unit - (IN) unit number. 23830 * old_policer_group_info - (IN) Policer group info for old location. 23831 * new_policer_group_info - (INOUT) Policer group info for new location. 23832 * Returns: 23833 * BCM_E_XXX 23834 */ 23835 int 23836 bcm_esw_policer_custom_group_id_copy( 23837 int unit, 23838 bcm_policer_group_info_t *old_policer_group_info, 23839 bcm_policer_group_info_t *new_policer_group_info) 23840 { 23841 int rv = BCM_E_NONE; 23842 bcm_policer_t policer_id = 0; 23843 int size_pool = 0, base_idx = 0; 23844 _global_meter_policer_control_t *policer_control = NULL; 23845 23846 if ((old_policer_group_info == NULL) || 23847 (new_policer_group_info == NULL)) { 23848 return BCM_E_PARAM; 23849 } 23850 23851 if (!soc_feature(unit, 23852 soc_feature_global_meter_compaction_support)) { 23853 return BCM_E_UNAVAIL; 23854 } 23855 23856 if(new_policer_group_info->mode_id != 23857 old_policer_group_info->mode_id) { 23858 return BCM_E_CONFIG; 23859 } 23860 if (sal_memcmp(old_policer_group_info, 23861 new_policer_group_info, 23862 sizeof(bcm_policer_group_info_t)) == 0) { 23863 return BCM_E_NONE; 23864 } 23865 23866 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 23867 base_idx = (old_policer_group_info->pool_id * size_pool); 23868 base_idx += old_policer_group_info->base_offset; 23869 _bcm_esw_get_policer_id_from_index_offset(unit, 23870 base_idx, 23871 old_policer_group_info->mode_id-1,&policer_id); 23872 23873 if (_bcm_global_meter_base_policer_get(unit, policer_id, 23874 &policer_control) == BCM_E_NOT_FOUND) { 23875 return BCM_E_PARAM; 23876 } 23877 23878 if ((policer_control != NULL) && 23879 (old_policer_group_info->policer_id != 23880 policer_control->pid)) { 23881 return BCM_E_PARAM; 23882 } 23883 23884 /* Create custom group */ 23885 rv = _bcm_esw_policer_custom_group_id_create(unit, 23886 0, old_policer_group_info->mode_id, 23887 old_policer_group_info->macro_policer_id, 23888 new_policer_group_info); 23889 BCM_IF_ERROR_RETURN(rv); 23890 23891 /* Copy policer config from old to new location */ 23892 if (old_policer_group_info->direction == 23893 bcmPolicerGroupDirectionHorizontal) { 23894 rv = _bcm_global_meter_copy_horizontally(unit, 23895 old_policer_group_info, new_policer_group_info); 23896 } else if (old_policer_group_info->direction == 23897 bcmPolicerGroupDirectionVertical) { 23898 rv = _bcm_global_meter_copy_vertically(unit, 23899 old_policer_group_info, new_policer_group_info); 23900 } 23901 23902 if (BCM_FAILURE(rv)) { 23903 LOG_VERBOSE(BSL_LS_BCM_POLICER, (BSL_META_U(unit, 23904 "Failed to copy policer to new offsets\n"))); 23905 (void) _bcm_esw_global_meter_policer_destroy(unit, 23906 new_policer_group_info->policer_id); 23907 } 23908 return rv; 23909 } 23910 23911 /* 23912 * Function: 23913 * bcm_esw_policer_action_attach_get 23914 * Purpose: 23915 * Get the action id associated with a given policer. 23916 * Parameters: 23917 * unit - (IN) unit number 23918 * policer_id - (IN) Base policer Id 23919 * action_id - (OUT) action id 23920 * Returns: 23921 * BCM_E_XXX 23922 */ 23923 int bcm_esw_policer_action_attach_get(int unit, bcm_policer_t policer_id, 23924 uint32 *action_id) 23925 { 23926 int rv = BCM_E_NONE; 23927 svm_meter_table_entry_t meter_entry; 23928 _global_meter_policer_control_t *policer_control = NULL; 23929 int policer_index = 0; 23930 23931 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 23932 if (soc_feature(unit, soc_feature_global_meter_v2)) { 23933 return bcmi_esw_policer_action_attach_get(unit, policer_id, action_id); 23934 } 23935 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 23936 23937 if (!soc_feature(unit, soc_feature_global_meter)) { 23938 return BCM_E_UNAVAIL; 23939 } 23940 CHECK_GLOBAL_METER_INIT(unit); 23941 /* validate policer id */ 23942 rv = _bcm_esw_policer_validate(unit, &policer_id); 23943 if (BCM_FAILURE(rv)) { 23944 return (rv); 23945 } 23946 GLOBAL_METER_LOCK(unit); 23947 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 23948 if (BCM_FAILURE(rv)) { 23949 GLOBAL_METER_UNLOCK(unit); 23950 LOG_DEBUG(BSL_LS_BCM_POLICER, 23951 (BSL_META_U(unit, 23952 "Unable to get policer control for the policer Id " 23953 "passed \n"))); 23954 return (rv); 23955 } 23956 /* read meter table action_id*/ 23957 _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index); 23958 rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index, 23959 &meter_entry); 23960 if (BCM_FAILURE(rv)) { 23961 GLOBAL_METER_UNLOCK(unit); 23962 LOG_DEBUG(BSL_LS_BCM_POLICER, 23963 (BSL_META_U(unit, 23964 "Unable to read SVM_METER_TABLE entry \n"))); 23965 return (rv); 23966 } 23967 /* get action id */ 23968 soc_SVM_METER_TABLEm_field_get(unit, &meter_entry, POLICY_TABLE_INDEXf, 23969 action_id); 23970 GLOBAL_METER_UNLOCK(unit); 23971 return rv; 23972 } 23973 23974 /* 23975 * Function: 23976 * bcm_esw_policer_action_detach 23977 * Purpose: 23978 * Disassociate a policer action from a given policer id and 23979 * readjust reference count. 23980 * Parameters: 23981 * unit - (IN) unit number 23982 * policer_id - (IN) Base policer Id 23983 * action_id - (IN) action id 23984 * Returns: 23985 * BCM_E_XXX 23986 */ 23987 int bcm_esw_policer_action_detach(int unit, bcm_policer_t policer_id, 23988 uint32 action_id) 23989 { 23990 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 23991 if (soc_feature(unit, soc_feature_global_meter_v2)) { 23992 return bcmi_esw_policer_action_detach(unit, policer_id, action_id); 23993 } 23994 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 23995 return _bcm_esw_policer_action_detach(unit, policer_id, action_id); 23996 } 23997 23998 /* 23999 * Function: 24000 * bcm_esw_policer_action_attach 24001 * Purpose: 24002 * Associate a policer action with a given policer id and 24003 * increment action usage reference count. 24004 * Parameters: 24005 * unit - (IN) unit number 24006 * policer_id - (IN) Base policer Id 24007 * action_id - (IN) action id 24008 * Returns: 24009 * BCM_E_XXX 24010 */ 24011 24012 int bcm_esw_policer_action_attach(int unit, bcm_policer_t policer_id, 24013 uint32 action_id) 24014 { 24015 int rv = BCM_E_NONE; 24016 svm_meter_table_entry_t meter_entry; 24017 _global_meter_policer_control_t *policer_control = NULL; 24018 int policer_index = 0; 24019 int index = 0; 24020 24021 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 24022 if (soc_feature(unit, soc_feature_global_meter_v2)) { 24023 return bcmi_esw_policer_action_attach(unit, policer_id, action_id); 24024 } 24025 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 24026 24027 if (!soc_feature(unit, soc_feature_global_meter)) { 24028 return BCM_E_UNAVAIL; 24029 } 24030 CHECK_GLOBAL_METER_INIT(unit); 24031 /* validate policer id */ 24032 rv = _bcm_esw_policer_validate(unit, &policer_id); 24033 if (BCM_FAILURE(rv)) { 24034 LOG_DEBUG(BSL_LS_BCM_POLICER, 24035 (BSL_META_U(unit, 24036 "Invalid Policer Id \n"))); 24037 return (rv); 24038 } 24039 /* validate action id */ 24040 if (action_id > soc_mem_index_max(unit, SVM_POLICY_TABLEm)) { 24041 LOG_ERROR(BSL_LS_BCM_POLICER, 24042 (BSL_META_U(unit, 24043 "Invalid Action Id \n"))); 24044 return BCM_E_PARAM; 24045 } 24046 24047 GLOBAL_METER_LOCK(unit); 24048 rv = _bcm_global_meter_policer_get(unit, policer_id, &policer_control); 24049 if (BCM_FAILURE(rv)) { 24050 GLOBAL_METER_UNLOCK(unit); 24051 LOG_DEBUG(BSL_LS_BCM_POLICER, 24052 (BSL_META_U(unit, 24053 "Unable to get policer control for the policer Id " 24054 "passed \n"))); 24055 return (rv); 24056 } 24057 24058 if (policer_control->action_id == action_id) { 24059 GLOBAL_METER_UNLOCK(unit); 24060 LOG_VERBOSE(BSL_LS_BCM_POLICER, 24061 (BSL_META_U(unit, 24062 "Action Id passed is different from the one in " 24063 "policer control-%x\n"), policer_control->action_id)); 24064 return (BCM_E_NONE); 24065 } 24066 /* check if action id is allocated */ 24067 if (global_meter_action_bookkeep[unit][action_id].used !=1) 24068 { 24069 GLOBAL_METER_UNLOCK(unit); 24070 LOG_DEBUG(BSL_LS_BCM_POLICER, 24071 (BSL_META_U(unit, 24072 "Action Id is not created \n"))); 24073 return BCM_E_PARAM; 24074 } 24075 /* read meter table and add action_id*/ 24076 _bcm_esw_get_policer_table_index(unit, policer_id, &policer_index); 24077 rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index, 24078 &meter_entry); 24079 if (BCM_FAILURE(rv)) { 24080 GLOBAL_METER_UNLOCK(unit); 24081 LOG_DEBUG(BSL_LS_BCM_POLICER, 24082 (BSL_META_U(unit, 24083 "Unable to read SVM_METER_TABLE entry \n"))); 24084 return (rv); 24085 } 24086 soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf, 24087 &action_id); 24088 /* detach the existing action and decrement reference count */ 24089 if (policer_control->action_id) { 24090 _bcm_esw_policer_action_detach(unit, policer_id, 24091 policer_control->action_id); 24092 } 24093 /* Write to HW*/ 24094 rv = WRITE_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, policer_index, 24095 &meter_entry); 24096 if (BCM_FAILURE(rv)) { 24097 GLOBAL_METER_UNLOCK(unit); 24098 LOG_DEBUG(BSL_LS_BCM_POLICER, 24099 (BSL_META_U(unit, 24100 "Unable to write SVM_METER_TABLE entry \n"))); 24101 return (rv); 24102 } 24103 /* in case of cascade with coupling we need to configure the second set 24104 as well */ 24105 if ((policer_control->grp_mode == \ 24106 bcmPolicerGroupModeIntPriCascadeWithCoupling) || 24107 (policer_control->grp_mode == bcmPolicerGroupModeCascadeWithCoupling)) { 24108 rv =_bcm_global_meter_get_coupled_cascade_policer_index(unit, 24109 policer_id, policer_control, &index); 24110 rv = READ_SVM_METER_TABLEm(unit, MEM_BLOCK_ANY, index, 24111 &meter_entry); 24112 if (BCM_FAILURE(rv)) { 24113 GLOBAL_METER_UNLOCK(unit); 24114 LOG_DEBUG(BSL_LS_BCM_POLICER, 24115 (BSL_META_U(unit, 24116 "Unable to read SVM_METER_TABLE entry \n"))); 24117 return (rv); 24118 } 24119 soc_SVM_METER_TABLEm_field_set(unit, &meter_entry, POLICY_TABLE_INDEXf, 24120 &action_id); 24121 /* write to hW */ 24122 rv = soc_mem_write(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, index, 24123 &meter_entry); 24124 if (BCM_FAILURE(rv)) { 24125 LOG_DEBUG(BSL_LS_BCM_POLICER, 24126 (BSL_META_U(unit, 24127 "Unable to write SVM_METER_TABLE entry \n"))); 24128 GLOBAL_METER_UNLOCK(unit); 24129 return (rv); 24130 } 24131 } 24132 /* increment action usage reference count */ 24133 global_meter_action_bookkeep[unit][action_id].reference_count++; 24134 policer_control->action_id = action_id; 24135 GLOBAL_METER_UNLOCK(unit); 24136 return rv; 24137 } 24138 24139 /* 24140 * Function: 24141 * bcm_esw_policer_global_meter_config_set 24142 * Purpose: 24143 * Set the Global Meter Configuration 24144 * Parameters: 24145 * unit - (IN) Unit number 24146 * config - (IN) Global Meter Configuration 24147 * Returns: 24148 * BCM_E_xxx 24149 */ 24150 int bcm_esw_policer_global_meter_config_set( 24151 int unit, 24152 bcm_policer_global_meter_config_t *config) 24153 { 24154 int rv = BCM_E_UNAVAIL; 24155 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 24156 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 24157 24158 POL_FUNCTION_TRACE(unit, "IN"); 24159 24160 /* Parameter NULL error handling */ 24161 POL_CHECK_NULL_PARAMETER(unit, config); 24162 24163 (void)bcmi_global_meter_dump_config(unit, "[set]", config); 24164 24165 if (1 < config->ifg_enable) { 24166 return BCM_E_PARAM; 24167 } 24168 24169 /* Initialization check */ 24170 CHECK_GLOBAL_METER_INIT(unit); 24171 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 24172 24173 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 24174 /* Check if the chip specific function existed */ 24175 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->ifg_set); 24176 24177 GLOBAL_METER_LOCK(unit); 24178 rv = gm_dev_info->ifg_set(unit, config->ifg_enable); 24179 if (BCM_FAILURE(rv)) { 24180 GLOBAL_METER_UNLOCK(unit); 24181 LOG_ERROR(BSL_LS_BCM_POLICER, 24182 (BSL_META_U(unit, 24183 "ifg_set failed(rv = %d)\n"), 24184 rv)); 24185 return rv; 24186 } 24187 24188 /* Check if the chip specific function existed */ 24189 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->source_order_set); 24190 24191 rv = gm_dev_info->source_order_set(unit, 24192 config->source_order, 24193 config->source_order_count); 24194 if (BCM_FAILURE(rv)) { 24195 GLOBAL_METER_UNLOCK(unit); 24196 LOG_ERROR(BSL_LS_BCM_POLICER, 24197 (BSL_META_U(unit, 24198 "source_order_set failed(rv = %d)\n"), 24199 rv)); 24200 return rv; 24201 } 24202 GLOBAL_METER_UNLOCK(unit); 24203 24204 POL_FUNCTION_TRACE(unit, "OUT"); 24205 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 24206 return rv; 24207 } 24208 24209 /* 24210 * Function: 24211 * bcm_esw_policer_global_meter_config_get 24212 * Purpose: 24213 * Get the Global Meter Configuration 24214 * Parameters: 24215 * unit - (IN) Unit number 24216 * config - (OUT) Global Meter Configuration 24217 * Returns: 24218 * BCM_E_xxx 24219 */ 24220 int bcm_esw_policer_global_meter_config_get( 24221 int unit, 24222 bcm_policer_global_meter_config_t *config) 24223 { 24224 int rv = BCM_E_UNAVAIL; 24225 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 24226 const bcmi_global_meter_dev_info_t *gm_dev_info = NULL; 24227 24228 POL_FUNCTION_TRACE(unit, "IN"); 24229 24230 /* Parameter NULL error handling */ 24231 POL_CHECK_NULL_PARAMETER(unit, config); 24232 24233 /* Initialization check */ 24234 CHECK_GLOBAL_METER_INIT(unit); 24235 CHECK_GLOBAL_METER_DEV_INFO_INIT(unit); 24236 24237 gm_dev_info = BCM_SVM_DEV_INFO_GET(unit); 24238 24239 /* Check if the chip specific function existed */ 24240 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->ifg_get); 24241 24242 GLOBAL_METER_LOCK(unit); 24243 24244 rv = gm_dev_info->ifg_get(unit, &config->ifg_enable); 24245 if (BCM_FAILURE(rv)) { 24246 GLOBAL_METER_UNLOCK(unit); 24247 LOG_ERROR(BSL_LS_BCM_POLICER, 24248 (BSL_META_U(unit, 24249 "HW Operation failed(rv = %d)\n"), 24250 rv)); 24251 return rv; 24252 } 24253 24254 /* Check if the chip specific function existed */ 24255 POL_CHECK_NULL_DEV_INSTANCE(unit, gm_dev_info->source_order_get); 24256 24257 rv = gm_dev_info->source_order_get(unit, 24258 config->source_order_count, 24259 config->source_order); 24260 24261 if (BCM_FAILURE(rv)) { 24262 GLOBAL_METER_UNLOCK(unit); 24263 LOG_ERROR(BSL_LS_BCM_POLICER, 24264 (BSL_META_U(unit, 24265 "HW Operation failed(rv = %d)\n"), 24266 rv)); 24267 return rv; 24268 } 24269 GLOBAL_METER_UNLOCK(unit); 24270 (void)bcmi_global_meter_dump_config(unit, "[get]", config); 24271 24272 POL_FUNCTION_TRACE(unit, "OUT"); 24273 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 24274 return rv; 24275 } 24276 /* END POLICER API's */ 24277 24278 #ifdef BCM_WARM_BOOT_SUPPORT 24279 24280 /* 24281 * Function: 24282 * _bcm_esw_svc_meter_wb_size_calc 24283 * Purpose: 24284 * Calculates scache size for policer module. 24285 * Parameters: 24286 * Unit - (IN) unit number 24287 * size - (OUT) scache size 24288 * Returns: 24289 * BCM_E_XXX 24290 */ 24291 STATIC int 24292 _bcm_esw_svc_meter_wb_size_calc(int unit, int *size) 24293 { 24294 int temp_size = 0; 24295 24296 /* BCM_WB_VERSION_1_0 */ 24297 temp_size = sizeof(int32) * BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES; 24298 24299 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 24300 /* 24301 * Following fields of global_meter_offset_mode needs to be saved in 24302 * scache. no_of_policer, group_mode and 24303 * meter_attr.udf_pkt_attr_selectors_v.udf_id. Rest all fields can be 24304 * recovered from hardware. 24305 */ 24306 temp_size += (sizeof(uint32) * BCM_POLICER_SVC_METER_MAX_MODE * 3); 24307 } 24308 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 24309 /* 24310 * Support for non-continuous bit selection in Udf mode. 24311 * we need to store attr_selectors information for each group 24312 * offset mode. 24313 */ 24314 temp_size += (sizeof(bcm_policer_group_mode_attr_selectors_info_t) * 24315 BCM_GLOBAL_METER_MAX_SCACHEABLE_GROUP_MODE); 24316 } 24317 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 24318 /* 24319 * Support for sharing of compression tables. 24320 * A global structure is maintained to save current status of 24321 * of compression table which includes reference counts, attribute 24322 * values flag (bitmap) per attribute. This structure is saved in 24323 * scache as it cannot be recovered from hardware tables. 24324 * Structure to save - _bcm_policer_pkt_compressed_attr_maps_t 24325 */ 24326 24327 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 24328 temp_size += sizeof(uint32); /* combine_cng_flags */ 24329 temp_size += sizeof(uint32); /* combine_int_pri_flags */ 24330 temp_size += sizeof(uint32); /* combine_vlan_format_flags */ 24331 temp_size += sizeof(uint32); /* combine_outer_dot1p_flags */ 24332 temp_size += sizeof(uint32); /* combine_inner_dot1p_flags */ 24333 temp_size += sizeof(uint32); /* combine_pkt_res_flags */ 24334 temp_size += sizeof(uint32); /* combine_drop_flags */ 24335 temp_size += sizeof(uint32); /* combine_ip_pkt_flags */ 24336 24337 /* Attributes which are Array */ 24338 temp_size += sizeof(uint32); /* Array Size */ 24339 temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE; 24340 /* _bcmPolicerAttrPort */ 24341 temp_size += sizeof(uint32); /* Array Size */ 24342 temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE; 24343 /* _bcmPolicerAttrTosDscp */ 24344 temp_size += sizeof(uint32); /* Array Size */ 24345 temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE; 24346 /* _bcmPolicerAttrTosEcn */ 24347 temp_size += sizeof(uint32); /* Array Size */ 24348 temp_size += sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE; 24349 /* _bcmPolicerAttrSvpType */ 24350 } 24351 } 24352 24353 *size = temp_size; 24354 24355 return BCM_E_NONE; 24356 } 24357 24358 /* 24359 * Function: 24360 * _bcm_esw_policer_config_from_meter_table 24361 * Purpose: 24362 * For a given policer, read the configuraton info from meter table 24363 * Parameters: 24364 * unit - (IN) unit number 24365 * policer - (IN) Base policer Id 24366 * policer_control - (OUT) Policer control info 24367 * Returns: 24368 * BCM_E_XXX 24369 */ 24370 int _bcm_esw_policer_config_from_meter_table(int unit, bcm_policer_t policer, 24371 _global_meter_policer_control_t *policer_control) 24372 { 24373 svm_meter_table_entry_t data; 24374 int index = 0, numbers = 0; 24375 uint32 mode = 0, coupling_flag = 0, pool = 0; 24376 bcm_policer_svc_meter_mode_t meter_mode; 24377 uint32 pol_index = 0, offset_mode = 0; 24378 uint32 end_of_chain = 0, first_end_of_chain = 0; 24379 int rv = BCM_E_NONE; 24380 int policer_index = 0; 24381 int size_pool = 0, num_pools = 0; 24382 int pool_mask = 0, pool_offset = 0; 24383 int offset_mask = 0; 24384 int multi_chain = 0; 24385 uint32 action_id = 0; 24386 24387 size_pool = SOC_INFO(unit).global_meter_max_size_of_pool; 24388 num_pools = SOC_INFO(unit).global_meter_pools; 24389 offset_mask = size_pool - 1; 24390 pool_offset = _shr_popcount(offset_mask); 24391 pool_mask = (num_pools - 1) << pool_offset; 24392 24393 offset_mode = ((policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) >> 24394 BCM_POLICER_GLOBAL_METER_MODE_SHIFT); 24395 if (offset_mode >= 1) { 24396 offset_mode = offset_mode - 1; 24397 if ((offset_mode) && 24398 (global_meter_offset_mode[unit][offset_mode].no_of_policers == 0)) { 24399 return rv; 24400 } 24401 } 24402 if ((global_meter_offset_mode[unit][offset_mode].meter_attr.mode_type_v == 24403 cascade_mode) || 24404 (global_meter_offset_mode[unit][offset_mode].type == 24405 bcmPolicerGroupModeTypeCascade) || 24406 (global_meter_offset_mode[unit][offset_mode].type == 24407 bcmPolicerGroupModeTypeCascadeWithCoupling)) { 24408 /* 24409 * Get the base policer ID for cascaded mode, then SDK will 24410 * recover policer_control stuct according to the base policer ID 24411 */ 24412 policer = (policer & BCM_POLICER_GLOBAL_METER_MODE_MASK) | 24413 (policer & offset_mask); 24414 multi_chain = 1; 24415 } 24416 /* Lets first try to get policer_control */ 24417 if (multi_chain == 1) { 24418 rv = _bcm_global_meter_policer_get(unit, policer, &policer_control); 24419 } else { 24420 rv = _bcm_global_meter_base_policer_get(unit, policer, &policer_control); 24421 } 24422 if (BCM_SUCCESS(rv)) { 24423 return rv; 24424 } 24425 /* read meter table to get policer configuration */ 24426 _bcm_esw_get_policer_table_index(unit, policer, &policer_index); 24427 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 24428 policer_index, &data); 24429 BCM_IF_ERROR_RETURN(rv); 24430 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, METER_MODEf)) { 24431 soc_SVM_METER_TABLEm_field_get(unit, &data, METER_MODEf, &mode); 24432 } 24433 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, COUPLING_FLAGf)) { 24434 soc_SVM_METER_TABLEm_field_get(unit, &data, COUPLING_FLAGf, 24435 &coupling_flag); 24436 } 24437 pool = (policer & pool_mask) >> pool_offset; 24438 /* Allocate policer descriptor. */ 24439 _GLOBAL_METER_XGS3_ALLOC(policer_control, 24440 sizeof (_global_meter_policer_control_t), "Global meter policer"); 24441 if (NULL == policer_control) { 24442 LOG_DEBUG(BSL_LS_BCM_POLICER, 24443 (BSL_META_U(unit, 24444 "Unable to allocate memory for Policer control data " 24445 "structure\n"))); 24446 return (BCM_E_MEMORY); 24447 } 24448 24449 if (SOC_MEM_FIELD_VALID(unit, SVM_METER_TABLEm, POLICY_TABLE_INDEXf)) { 24450 soc_SVM_METER_TABLEm_field_get(unit, 24451 &data, POLICY_TABLE_INDEXf, &action_id); 24452 /* increment action usage reference count */ 24453 if (action_id) { 24454 policer_control->action_id = action_id; 24455 global_meter_action_bookkeep[unit]\ 24456 [policer_control->action_id].reference_count++; 24457 } 24458 } 24459 24460 /* Set the grp_mode for policer control. In case offset_mode=0, 24461 * global_meter_offset_mode[0][0].group_mode will have by 24462 * default 0 (bcmPolicerGroupModeSingle) */ 24463 policer_control->grp_mode = 24464 global_meter_offset_mode[unit][offset_mode].group_mode; 24465 24466 if((soc_feature(unit, soc_feature_global_meter_mef_10dot3)) && 24467 (mode == GLOBAL_METER_MODE_CASCADE)) { 24468 /* Handling recovery of Cascade/Coupledcascade Mode in Apache 24469 * octuple is allocated for cascade/coupledcascade group mode */ 24470 policer_control->direction = GLOBAL_METER_ALLOC_HORIZONTAL; 24471 policer_control->pid = policer; 24472 policer_control->offset[0] = pool; 24473 if ((policer_control->grp_mode == 24474 bcmPolicerGroupModeCascadeWithCoupling) || 24475 (policer_control->grp_mode == 24476 bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 24477 end_of_chain = 4; 24478 } 24479 pol_index = policer_index; 24480 for (index = pool + 1; index < num_pools; index++) { 24481 policer_control->offset[index] = index; 24482 24483 if (index == end_of_chain) { 24484 first_end_of_chain = 1; 24485 } 24486 /* increment action usage reference count */ 24487 /* In case of cascade coupled, use only one chain */ 24488 if (first_end_of_chain == 0) { 24489 /* Read index to get policy_index, if any */ 24490 policer_index = pol_index + (index << _shr_popcount(size_pool - 1)); 24491 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 24492 policer_index, &data); 24493 if (!BCM_SUCCESS(rv)) { 24494 sal_free(policer_control); 24495 LOG_DEBUG(BSL_LS_BCM_POLICER, 24496 (BSL_META_U(unit, 24497 "Unable to read SVM meter table at " 24498 "index %x\n"), policer_index)); 24499 return rv; 24500 } 24501 action_id = 0; 24502 soc_SVM_METER_TABLEm_field_get(unit, &data, 24503 POLICY_TABLE_INDEXf, &action_id); 24504 if (action_id != 0) { 24505 global_meter_action_bookkeep[unit]\ 24506 [action_id].reference_count++; 24507 } 24508 } 24509 } 24510 policer_control->no_of_policers = index; 24511 } else if (!soc_feature(unit, soc_feature_global_meter_mef_10dot3) && 24512 (mode == GLOBAL_METER_MODE_CASCADE)) { 24513 policer_control->direction = GLOBAL_METER_ALLOC_HORIZONTAL; 24514 policer_control->pid = policer; 24515 policer_control->offset[numbers] = 0; 24516 numbers++; 24517 pol_index = policer_index; 24518 for (index = pool + 1; index < num_pools; index++) { 24519 policer_index = pol_index + (index << _shr_popcount(size_pool - 1)); 24520 rv = soc_mem_read(unit, SVM_METER_TABLEm, MEM_BLOCK_ANY, 24521 policer_index, &data); 24522 if (!BCM_SUCCESS(rv)) { 24523 sal_free(policer_control); 24524 LOG_DEBUG(BSL_LS_BCM_POLICER, 24525 (BSL_META_U(unit, 24526 "Unable to read SVM meter table at " 24527 "index %x\n"), policer_index)); 24528 return rv; 24529 } 24530 /* increment action usage reference count */ 24531 /* In case of cascade coupled, use only one chain */ 24532 if (first_end_of_chain == 0) { 24533 action_id = 0; 24534 soc_SVM_METER_TABLEm_field_get(unit, &data, 24535 POLICY_TABLE_INDEXf, &action_id); 24536 if (action_id != 0) { 24537 global_meter_action_bookkeep[unit]\ 24538 [action_id].reference_count++; 24539 } 24540 } 24541 soc_SVM_METER_TABLEm_field_get(unit, &data, 24542 END_OF_CHAINf, &end_of_chain); 24543 soc_SVM_METER_TABLEm_field_get(unit, &data, 24544 METER_MODEf, &meter_mode); 24545 if ((meter_mode == GLOBAL_METER_MODE_CASCADE) && 24546 (end_of_chain != 1)) { 24547 policer_control->offset[numbers] = index - pool; 24548 } 24549 if (!(coupling_flag) && 24550 (meter_mode == GLOBAL_METER_MODE_CASCADE) && 24551 (end_of_chain == 1)) { 24552 policer_control->offset[numbers] = index - pool; 24553 if (!multi_chain) { 24554 /* 24555 * In cascaded mode there may be multi chains in one policer 24556 * group, and each policer group contains 8 policer IDs. SDK 24557 * should recover all these 8 policer IDs. 24558 */ 24559 index = num_pools; 24560 } 24561 } 24562 if ((coupling_flag) && 24563 (meter_mode == GLOBAL_METER_MODE_CASCADE) && 24564 (end_of_chain) && (first_end_of_chain)) { 24565 policer_control->offset[numbers] = index - pool; 24566 index = num_pools; 24567 } 24568 if ((coupling_flag) && 24569 (meter_mode == GLOBAL_METER_MODE_CASCADE) && 24570 (end_of_chain) && (first_end_of_chain == 0)) { 24571 policer_control->offset[numbers] = index - pool; 24572 first_end_of_chain = 1; 24573 } 24574 numbers++; 24575 } /* end of for */ 24576 policer_control->no_of_policers = numbers; 24577 } else if (offset_mode >= 1) { 24578 policer_control->direction = GLOBAL_METER_ALLOC_VERTICAL; 24579 policer_control->pid = policer; 24580 /* add code to get the number of policers for this mode */ 24581 policer_control->no_of_policers = 24582 global_meter_offset_mode[unit][offset_mode].no_of_policers; 24583 } else { 24584 policer_control->direction = GLOBAL_METER_ALLOC_VERTICAL; 24585 policer_control->pid = policer; 24586 policer_control->no_of_policers = 1; 24587 } 24588 rv = _global_meter_reserve_policer_id(unit, policer_control->direction, 24589 policer_control->no_of_policers, 24590 policer, &policer_control->offset[0]); 24591 if (!BCM_SUCCESS(rv)) { 24592 /* De-allocate policer descriptor. */ 24593 sal_free(policer_control); 24594 LOG_DEBUG(BSL_LS_BCM_POLICER, 24595 (BSL_META_U(unit, 24596 "Unable to allocate policers with base id %x\n"), 24597 policer)); 24598 return BCM_E_INTERNAL; 24599 } 24600 /* Insert policer into policers hash. */ 24601 _GLOBAL_METER_HASH_INSERT(global_meter_policer_bookkeep[unit], 24602 policer_control,(policer & _GLOBAL_METER_HASH_MASK)); 24603 /* increment mode reference count for new policer */ 24604 if (offset_mode) { 24605 rv = bcm_policer_svc_meter_inc_mode_reference_count(unit, offset_mode); 24606 } 24607 return rv; 24608 } 24609 24610 /* 24611 * Function: 24612 * _bcm_esw_policer_config_reinit_from_table 24613 * Purpose: 24614 * Read entry from table and re-init policer if present 24615 * Parameters: 24616 * unit - (IN) unit number 24617 * mem - (IN) table 24618 * index - (IN) Index in table for entry 24619 * entry - (IN) one entry in table 24620 * user_data - (IN) data passed by calling function 24621 * dirty - (OUT) Set if entry is modified 24622 * Returns: 24623 * BCM_E_XXX 24624 */ 24625 STATIC int 24626 _bcm_esw_policer_config_reinit_from_table(int unit, soc_mem_t mem, uint32 index, 24627 void *entry, void *user_data, uint32 *dirty) 24628 { 24629 int rv = BCM_E_NONE; 24630 bcm_policer_t policer; 24631 uint32 offset_mode = 0, meter_index = 0; 24632 _bcm_policer_svm_source_type_t mem_index; 24633 _global_meter_policer_control_t *policer_control = NULL; 24634 24635 if (entry == NULL) { 24636 return BCM_E_INTERNAL; 24637 } 24638 _bcm_policer_svm_source_index_get(unit, mem, &mem_index); 24639 if (mem == SVM_MACROFLOW_INDEX_TABLEm) { 24640 offset_mode = meter_index = 0; 24641 if (SOC_MEM_FIELD_VALID(unit, mem, MACROFLOW_INDEXf)) { 24642 meter_index = soc_mem_field32_get(unit, mem, entry, 24643 MACROFLOW_INDEXf); 24644 } 24645 } else { 24646 offset_mode = soc_mem_field32_get(unit, mem, entry, 24647 BCM_SVM_SOURCE(unit, mem_index).offset_mode); 24648 meter_index = soc_mem_field32_get(unit, mem, entry, 24649 BCM_SVM_SOURCE(unit, mem_index).meter_index); 24650 } 24651 _bcm_esw_get_policer_id_from_index_offset(unit, meter_index, 24652 offset_mode, &policer); 24653 if (policer != 0) { 24654 policer_control = NULL; 24655 rv = _bcm_esw_policer_config_from_meter_table(unit, policer, 24656 policer_control); 24657 if (BCM_SUCCESS(rv)) { 24658 rv = _bcm_esw_policer_increment_ref_count(unit, policer); 24659 } 24660 } 24661 return rv; 24662 } 24663 24664 /* 24665 * Function: 24666 * _bcm_esw_svm_action_reinit_from_table 24667 * Purpose: 24668 * Called via a svm table traversal function to reinit action if present 24669 * Parameters: 24670 * unit - (IN) unit number 24671 * mem - (IN) memory 24672 * index - (IN) Index in Memory 24673 * entry - (IN) Buffer of mem entry at index in Memory 24674 * user_data - (IN) user specific info 24675 * dirty - (OUT) Is entry modified 24676 * Returns: 24677 * BCM_E_XXX 24678 */ 24679 STATIC int 24680 _bcm_esw_svm_action_reinit_from_table(int unit, soc_mem_t mem, uint32 index, 24681 void *entry, void *user_data, uint32 *dirty) 24682 { 24683 int rv = BCM_E_NONE; 24684 uint32 green_action[1] = {0}, yellow_action[1] = {0}, red_action[1] = {0}; 24685 24686 soc_SVM_POLICY_TABLEm_field_get(unit, entry, G_ACTIONSf, &green_action[0]); 24687 soc_SVM_POLICY_TABLEm_field_get(unit, entry, Y_ACTIONSf, &yellow_action[0]); 24688 soc_SVM_POLICY_TABLEm_field_get(unit, entry, R_ACTIONSf, &red_action[0]); 24689 24690 if ((green_action[0] > 0) || (yellow_action[0] > 0) || 24691 (red_action[0] > 0) || 24692 (global_meter_action_bookkeep[unit][index].reference_count != 0)) 24693 { 24694 global_meter_action_bookkeep[unit][index].used = 1; 24695 /* Reserve the the action table entry */ 24696 rv = shr_aidxres_list_reserve_block( 24697 meter_action_list_handle[unit], index, 1); 24698 if (BCM_FAILURE(rv)) { 24699 LOG_DEBUG(BSL_LS_BCM_POLICER, 24700 (BSL_META_U(unit, 24701 "Unable to reserve action id %d in " 24702 "index management list\n"), index)); 24703 return (rv); 24704 } 24705 } 24706 return rv; 24707 } 24708 24709 /* 24710 * Function: 24711 * _bcm_policer_config_reinit 24712 * Purpose: 24713 * go through all the table entries that support service meter 24714 * and get policer configuration for those policers that are 24715 * configured in HW to rebuild SDK internal data strutcure on 24716 * warm boot. 24717 * Parameters: 24718 * unit - (IN) unit number 24719 * Returns: 24720 * BCM_E_XXX 24721 */ 24722 int _bcm_policer_config_reinit(int unit) 24723 { 24724 int rv = BCM_E_NONE; 24725 soc_mem_t table; 24726 _bcm_policer_svm_source_type_t mem_index; 24727 24728 for (mem_index = 0; mem_index < _BCM_SVM_MEM_COUNT; mem_index++) { 24729 table = BCM_SVM_SOURCE(unit, mem_index).table; 24730 if (table == INVALIDm) { 24731 continue; 24732 } 24733 rv = _bcm_esw_svm_source_traverse (unit, table, -1, -1, 24734 _bcm_esw_policer_config_reinit_from_table, NULL); 24735 BCM_IF_ERROR_RETURN(rv); 24736 } 24737 24738 if (BCM_SUCCESS(rv)) { 24739 table = SVM_MACROFLOW_INDEX_TABLEm; 24740 rv = _bcm_esw_svm_source_traverse (unit, table, -1, -1, 24741 _bcm_esw_policer_config_reinit_from_table, NULL); 24742 } 24743 return rv; 24744 } 24745 24746 /* 24747 * Function: 24748 * _bcm_esw_global_meter_uncompressed_offset_mode_reinit 24749 * Purpose: 24750 * Recover un-coompessed offset mode information from HW and re-configure 24751 * SDK data structures on warm boot 24752 * Parameters: 24753 * unit - (IN) unit number 24754 * mode - (IN) meter offset mode 24755 * selector_count - (IN) Number of selectors 24756 * selector_for_bit_x_en_field_value - (IN) selector field enable 24757 * selector_for_bit_x_field_value - (IN) selector field 24758 * Returns: 24759 * BCM_E_XXX 24760 */ 24761 int _bcm_esw_global_meter_uncompressed_offset_mode_reinit( 24762 int unit, 24763 int mode, 24764 uint32 selector_count, 24765 uint32 selector_for_bit_x_en_field_value[8], 24766 uint32 selector_for_bit_x_field_value[8]) 24767 { 24768 uint32 uncompressed_attr_bits_selector = 0; 24769 uint32 index = 0; 24770 int rv = BCM_E_NONE; 24771 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 24772 int port_attr_size = BCM_POLICER_SVC_METER_ING_PORT_ATTR_SIZE; 24773 24774 pkt_attr_bit_pos = BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos; 24775 24776 global_meter_offset_mode[unit][mode].used = 1; 24777 global_meter_offset_mode[unit][mode].reference_count = 0; 24778 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = 24779 uncompressed_mode; 24780 for (uncompressed_attr_bits_selector = 0, index = 0; index < 8; index++) 24781 { 24782 if (selector_for_bit_x_en_field_value[index] != 0) 24783 { 24784 if ( selector_for_bit_x_field_value[index] == 24785 pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit) 24786 { 24787 uncompressed_attr_bits_selector |= 24788 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_IP_PKT_ATTR_BITS; 24789 continue; 24790 } 24791 if ( selector_for_bit_x_field_value[index] == 24792 pkt_attr_bit_pos[pkt_attr_drop].start_bit) 24793 { 24794 uncompressed_attr_bits_selector |= 24795 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_DROP_ATTR_BITS; 24796 continue; 24797 } 24798 if (( selector_for_bit_x_field_value[index] == 24799 pkt_attr_bit_pos[pkt_attr_svp_group].start_bit) && 24800 ( selector_for_bit_x_field_value[index] <= 24801 pkt_attr_bit_pos[pkt_attr_svp_group].end_bit)) 24802 { 24803 uncompressed_attr_bits_selector |= 24804 BCM_POLICER_SVC_METER_UNCOMPRESSED_USE_SVP_TYPE_ATTR_BITS; 24805 continue; 24806 } 24807 if (( selector_for_bit_x_field_value[index] >= 24808 pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit) && 24809 ( selector_for_bit_x_field_value[index] <= 24810 pkt_attr_bit_pos[pkt_attr_pkt_resolution].end_bit)) 24811 24812 { 24813 uncompressed_attr_bits_selector |= 24814 BCM_POLICER_SVC_METER_PKT_REOLUTION_ATTR_SIZE; 24815 continue; 24816 } 24817 if (( selector_for_bit_x_field_value[index] >= 24818 pkt_attr_bit_pos[pkt_attr_tos].start_bit) && 24819 ( selector_for_bit_x_field_value[index] <= 24820 pkt_attr_bit_pos[pkt_attr_tos].end_bit)) 24821 { 24822 uncompressed_attr_bits_selector |= 24823 BCM_POLICER_SVC_METER_TOS_ATTR_SIZE; 24824 continue; 24825 } 24826 if (( selector_for_bit_x_field_value[index] >= 24827 pkt_attr_bit_pos[pkt_attr_ing_port].start_bit) && 24828 ( selector_for_bit_x_field_value[index] <= 24829 pkt_attr_bit_pos[pkt_attr_ing_port].end_bit)) 24830 { 24831 port_attr_size = 24832 BCM_SVM_DEV_ATTR(unit)->uncompressed_ing_port_size; 24833 uncompressed_attr_bits_selector |= port_attr_size; 24834 continue; 24835 } 24836 if (( selector_for_bit_x_field_value[index] >= 24837 pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit) && 24838 ( selector_for_bit_x_field_value[index] <= 24839 pkt_attr_bit_pos[pkt_attr_inner_dot1p].end_bit)) 24840 { 24841 uncompressed_attr_bits_selector |= 24842 BCM_POLICER_SVC_METER_INNER_DOT1P_ATTR_SIZE; 24843 continue; 24844 } 24845 if (( selector_for_bit_x_field_value[index] >= 24846 pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit) && 24847 ( selector_for_bit_x_field_value[index] <= 24848 pkt_attr_bit_pos[pkt_attr_outer_dot1p].end_bit)) 24849 { 24850 uncompressed_attr_bits_selector |= 24851 BCM_POLICER_SVC_METER_OUTER_DOT1P_ATTR_SIZE; 24852 continue; 24853 } 24854 if (( selector_for_bit_x_field_value[index] >= 24855 pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit) && 24856 ( selector_for_bit_x_field_value[index] <= 24857 pkt_attr_bit_pos[pkt_attr_vlan_format].end_bit)) 24858 { 24859 uncompressed_attr_bits_selector |= 24860 BCM_POLICER_SVC_METER_VLAN_FORMAT_ATTR_SIZE; 24861 continue; 24862 } 24863 if (( selector_for_bit_x_field_value[index] >= 24864 pkt_attr_bit_pos[pkt_attr_int_pri].start_bit) && 24865 ( selector_for_bit_x_field_value[index] <= 24866 pkt_attr_bit_pos[pkt_attr_int_pri].end_bit)) 24867 { 24868 uncompressed_attr_bits_selector |= 24869 BCM_POLICER_SVC_METER_INT_PRI_ATTR_SIZE; 24870 continue; 24871 } 24872 if (( selector_for_bit_x_field_value[index] >= 24873 pkt_attr_bit_pos[pkt_attr_cng].start_bit) && 24874 ( selector_for_bit_x_field_value[index] <= 24875 pkt_attr_bit_pos[pkt_attr_cng].end_bit)) 24876 { 24877 uncompressed_attr_bits_selector |= 24878 BCM_POLICER_SVC_METER_CNG_ATTR_SIZE; 24879 continue; 24880 } 24881 if (( selector_for_bit_x_field_value[index] >= 24882 pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit) && 24883 ( selector_for_bit_x_field_value[index] <= 24884 pkt_attr_bit_pos[pkt_attr_short_int_pri].end_bit)) 24885 { 24886 uncompressed_attr_bits_selector |= 24887 BCM_POLICER_SVC_METER_SHORT_INT_PRI_ATTR_SIZE; 24888 continue; 24889 } 24890 24891 } 24892 } 24893 global_meter_offset_mode[unit][mode].meter_attr.\ 24894 uncompressed_attr_selectors_v.uncompressed_attr_bits_selector = 24895 uncompressed_attr_bits_selector; 24896 return rv; 24897 } 24898 24899 /* 24900 * Function: 24901 * _bcm_esw_global_meter_compressed_offset_mode_reinit 24902 * Purpose: 24903 * Recover Compessed offset mode information from HW and re-configure SDK 24904 * data structures on warm boot 24905 * 24906 * Parameters: 24907 * unit - (IN) unit number 24908 * mode - (IN) meter offset mode 24909 * selector_count - (IN) Number of selectors 24910 * selector_for_bit_x_en_field_value - (IN) selector field enable 24911 * selector_for_bit_x_field_value - (IN) selector field 24912 * Returns: 24913 * BCM_E_XXX 24914 */ 24915 int _bcm_esw_global_meter_compressed_offset_mode_reinit( 24916 int unit, 24917 int mode, 24918 uint32 selector_count, 24919 uint32 selector_for_bit_x_en_field_value[8], 24920 uint32 selector_for_bit_x_field_value[8]) 24921 { 24922 uint32 index = 0; 24923 int rv = BCM_E_NONE; 24924 compressed_attr_selectors_t *comp_pkt_attr_sel; 24925 pkt_attr_bits_t *pkt_attr_bits; 24926 _bcm_policer_pkt_attr_bit_pos_t *pkt_attr_bit_pos = NULL; 24927 int index_max = 0; 24928 24929 pkt_attr_bit_pos = 24930 BCM_SVM_DEV_ATTR(unit)->uncompressed_pkt_attr_bit_pos; 24931 24932 global_meter_offset_mode[unit][mode].used = 1; 24933 global_meter_offset_mode[unit][mode].reference_count = 0; 24934 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = 24935 compressed_mode; 24936 pkt_attr_bits = &(global_meter_offset_mode[unit][mode].meter_attr.\ 24937 compressed_attr_selectors_v.pkt_attr_bits_v); 24938 comp_pkt_attr_sel = &(global_meter_offset_mode[unit][mode].meter_attr.\ 24939 compressed_attr_selectors_v); 24940 for (index = 0; index < 8; index++) 24941 { 24942 if (selector_for_bit_x_en_field_value[index] != 0) 24943 { 24944 if ( selector_for_bit_x_field_value[index] == 24945 pkt_attr_bit_pos[pkt_attr_ip_pkt].start_bit) 24946 { 24947 pkt_attr_bits->ip_pkt = 1; 24948 continue; 24949 } 24950 if ( selector_for_bit_x_field_value[index] == 24951 pkt_attr_bit_pos[pkt_attr_drop].start_bit) 24952 { 24953 pkt_attr_bits->drop = 1; 24954 continue; 24955 } 24956 if (( selector_for_bit_x_field_value[index] >= 24957 pkt_attr_bit_pos[pkt_attr_svp_group].start_bit) && 24958 ( selector_for_bit_x_field_value[index] <= 24959 pkt_attr_bit_pos[pkt_attr_svp_group].end_bit)) 24960 { 24961 pkt_attr_bits->svp_type++ ; 24962 continue; 24963 } 24964 if (( selector_for_bit_x_field_value[index] >= 24965 pkt_attr_bit_pos[pkt_attr_pkt_resolution].start_bit) && 24966 ( selector_for_bit_x_field_value[index] <= 24967 pkt_attr_bit_pos[pkt_attr_pkt_resolution].end_bit)) 24968 24969 { 24970 pkt_attr_bits->pkt_resolution++; 24971 continue; 24972 } 24973 if (( selector_for_bit_x_field_value[index] >= 24974 pkt_attr_bit_pos[pkt_attr_tos].start_bit) && 24975 ( selector_for_bit_x_field_value[index] <= 24976 pkt_attr_bit_pos[pkt_attr_tos].end_bit)) 24977 { 24978 pkt_attr_bits->tos++; 24979 continue; 24980 } 24981 if (( selector_for_bit_x_field_value[index] >= 24982 pkt_attr_bit_pos[pkt_attr_ing_port].start_bit) && 24983 ( selector_for_bit_x_field_value[index] <= 24984 pkt_attr_bit_pos[pkt_attr_ing_port].end_bit)) 24985 { 24986 pkt_attr_bits->ing_port++; 24987 continue; 24988 } 24989 if (( selector_for_bit_x_field_value[index] >= 24990 pkt_attr_bit_pos[pkt_attr_inner_dot1p].start_bit) && 24991 ( selector_for_bit_x_field_value[index] <= 24992 pkt_attr_bit_pos[pkt_attr_inner_dot1p].end_bit)) 24993 { 24994 pkt_attr_bits->inner_dot1p++; 24995 continue; 24996 } 24997 if (( selector_for_bit_x_field_value[index] >= 24998 pkt_attr_bit_pos[pkt_attr_outer_dot1p].start_bit) && 24999 ( selector_for_bit_x_field_value[index] <= 25000 pkt_attr_bit_pos[pkt_attr_outer_dot1p].end_bit)) 25001 { 25002 pkt_attr_bits->outer_dot1p++; 25003 continue; 25004 } 25005 if (( selector_for_bit_x_field_value[index] >= 25006 pkt_attr_bit_pos[pkt_attr_vlan_format].start_bit) && 25007 ( selector_for_bit_x_field_value[index] <= 25008 pkt_attr_bit_pos[pkt_attr_vlan_format].end_bit)) 25009 { 25010 pkt_attr_bits->vlan_format++; 25011 continue; 25012 } 25013 if (( selector_for_bit_x_field_value[index] >= 25014 pkt_attr_bit_pos[pkt_attr_int_pri].start_bit) && 25015 ( selector_for_bit_x_field_value[index] <= 25016 pkt_attr_bit_pos[pkt_attr_int_pri].end_bit)) 25017 { 25018 pkt_attr_bits->int_pri++; 25019 continue; 25020 } 25021 if (( selector_for_bit_x_field_value[index] >= 25022 pkt_attr_bit_pos[pkt_attr_cng].start_bit) && 25023 ( selector_for_bit_x_field_value[index] <= 25024 pkt_attr_bit_pos[pkt_attr_cng].end_bit)) 25025 { 25026 pkt_attr_bits->cng++; 25027 continue; 25028 } 25029 if (( selector_for_bit_x_field_value[index] >= 25030 pkt_attr_bit_pos[pkt_attr_short_int_pri].start_bit) && 25031 ( selector_for_bit_x_field_value[index] <= 25032 pkt_attr_bit_pos[pkt_attr_short_int_pri].end_bit)) 25033 { 25034 pkt_attr_bits->short_int_pri++; 25035 continue; 25036 } 25037 25038 } 25039 } 25040 25041 if ((pkt_attr_bits->cng) || (pkt_attr_bits->int_pri)) 25042 { 25043 index_max = soc_mem_index_max(unit, ING_SVM_PRI_CNG_MAPm); 25044 for (index = 0; index <= index_max; index++) { 25045 SOC_IF_ERROR_RETURN(soc_mem_read( 25046 unit, 25047 ING_SVM_PRI_CNG_MAPm, 25048 MEM_BLOCK_ANY, 25049 index, 25050 &comp_pkt_attr_sel->compressed_pri_cnf_attr_map_v[index])); 25051 } 25052 } 25053 if ((pkt_attr_bits->vlan_format) || (pkt_attr_bits->outer_dot1p) || 25054 (pkt_attr_bits->inner_dot1p)) 25055 { 25056 index_max = soc_mem_index_max(unit, ING_SVM_PKT_PRI_MAPm); 25057 for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) { 25058 SOC_IF_ERROR_RETURN(soc_mem_read( 25059 unit, 25060 ING_SVM_PKT_PRI_MAPm, 25061 MEM_BLOCK_ANY, 25062 index, 25063 &comp_pkt_attr_sel->compressed_pkt_pri_attr_map_v[index])); 25064 } 25065 } 25066 25067 if ((pkt_attr_bits->ing_port)) 25068 { 25069 index_max = soc_mem_index_max(unit, ING_SVM_PORT_MAPm); 25070 for (index = 0; index <= index_max; index++) { 25071 SOC_IF_ERROR_RETURN(soc_mem_read( 25072 unit, 25073 ING_SVM_PORT_MAPm, 25074 MEM_BLOCK_ANY, 25075 index, 25076 &comp_pkt_attr_sel->compressed_port_attr_map_v[index])); 25077 } 25078 } 25079 25080 if (pkt_attr_bits->tos) 25081 { 25082 index_max = soc_mem_index_max(unit, ING_SVM_TOS_MAPm); 25083 for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) { 25084 SOC_IF_ERROR_RETURN(soc_mem_read( 25085 unit, 25086 ING_SVM_TOS_MAPm, 25087 MEM_BLOCK_ANY, 25088 index, 25089 &comp_pkt_attr_sel->compressed_tos_attr_map_v[index])); 25090 } 25091 } 25092 25093 if ((pkt_attr_bits->pkt_resolution) || (pkt_attr_bits->svp_type) || 25094 (pkt_attr_bits->drop)) 25095 { 25096 index_max = soc_mem_index_max(unit, ING_SVM_PKT_RES_MAPm); 25097 for (index = 0; index < BCM_SVC_METER_MAP_SIZE_256; index++) { 25098 SOC_IF_ERROR_RETURN(soc_mem_read( 25099 unit, 25100 ING_SVM_PKT_RES_MAPm, 25101 MEM_BLOCK_ANY, 25102 index, 25103 &comp_pkt_attr_sel->compressed_pkt_res_attr_map_v[index])); 25104 } 25105 } 25106 return rv; 25107 } 25108 25109 /* 25110 * Function: 25111 * _bcm_esw_global_meter_udf_offset_mode_reinit 25112 * Purpose: 25113 * Recover UDF offset mode information from HW and re-configure SDK 25114 * data structures on warm boot 25115 * Parameters: 25116 * unit - (IN) unit number 25117 * mode - (IN) meter offset mode 25118 * selector_count - (IN) Number of selectors 25119 * selector_for_bit_x_en_field_value - (IN) selector field enable 25120 * selector_for_bit_x_field_value - (IN) selector field 25121 * Returns: 25122 * BCM_E_XXX 25123 */ 25124 int _bcm_esw_global_meter_udf_offset_mode_reinit( 25125 int unit, 25126 int mode, 25127 uint32 selector_count, 25128 uint32 selector_for_bit_x_en_field_value[8], 25129 uint32 selector_for_bit_x_field_value[8]) 25130 { 25131 int rv = BCM_E_NONE; 25132 uint16 udf0 = 0; 25133 uint16 udf1 = 0; 25134 uint32 index = 0; 25135 udf_pkt_attr_selectors_t *udf_attr = NULL; 25136 svm_offset_table_entry_t *buf; 25137 svm_offset_table_entry_t *entry; 25138 int entry_index = 0; 25139 uint32 offset, pool_offset, meter_enable; 25140 25141 udf_attr = 25142 &global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v; 25143 if (selector_for_bit_x_field_value[0] == 0) { 25144 udf_attr->drop = 1; 25145 index++; 25146 } 25147 for (udf0 = 0, udf1 = 0; index < 8; index++) { 25148 if (selector_for_bit_x_field_value[index] != 0) { 25149 udf_attr->udf_subdiv[0].width += 1; 25150 if ( selector_for_bit_x_field_value[index] <= 16) { 25151 udf0 |= (1 << (selector_for_bit_x_field_value[index] - 1)); 25152 } else { 25153 udf1 |= (1 << (selector_for_bit_x_field_value[index]- 16 - 1)); 25154 } 25155 } 25156 } 25157 25158 global_meter_offset_mode[unit][mode].used = 1; 25159 global_meter_offset_mode[unit][mode].reference_count = 0; 25160 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = udf_mode; 25161 global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v.\ 25162 udf_pkt_attr_bits_v.udf0 = udf0; 25163 global_meter_offset_mode[unit][mode].meter_attr.udf_pkt_attr_selectors_v.\ 25164 udf_pkt_attr_bits_v.udf1 = udf1; 25165 25166 udf_attr->total_subdiv = 1; 25167 offset = (udf_attr->drop == 1) ? 25168 selector_for_bit_x_field_value[1] : selector_for_bit_x_field_value[0]; 25169 /* Since udf0 bits start from bit-1 in the selector bit vector */ 25170 udf_attr->udf_subdiv[0].offset = offset - 1; 25171 25172 /* Allocate buffer to store the DMAed table entries. */ 25173 buf = soc_cm_salloc(unit, sizeof(svm_offset_table_entry_t) * 256, 25174 "svm macro flow index table entry buffer"); 25175 if (NULL == buf) { 25176 return (BCM_E_MEMORY); 25177 } 25178 /* Initialize the entry buffer. */ 25179 sal_memset(buf, 0, sizeof(svm_offset_table_entry_t) * 256); 25180 25181 /* Read the table entries into the buffer. */ 25182 rv = soc_mem_read_range(unit, SVM_OFFSET_TABLEm, 25183 MEM_BLOCK_ALL, 25184 ((mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE)), 25185 ((mode << BCM_POLICER_SVC_METER_OFFSET_TABLE_KEY_SIZE) + 256), 25186 buf); 25187 if (BCM_FAILURE(rv)) { 25188 if (buf) { 25189 soc_cm_sfree(unit, buf); 25190 } 25191 return rv; 25192 } 25193 25194 /* Iterate over the table entries. */ 25195 for (entry_index = 0; entry_index < 256; entry_index++) { 25196 entry = soc_mem_table_idx_to_pointer(unit, 25197 SVM_OFFSET_TABLEm, 25198 svm_offset_table_entry_t *, 25199 buf, entry_index); 25200 soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, OFFSETf, &offset); 25201 soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, POOL_OFFSETf, &pool_offset); 25202 soc_SVM_OFFSET_TABLEm_field_get (unit, (void *)entry, METER_ENABLEf, &meter_enable); 25203 25204 udf_attr->offset_map[entry_index].offset = offset; 25205 udf_attr->offset_map[entry_index].pool = pool_offset; 25206 udf_attr->offset_map[entry_index].meter_enable = meter_enable; 25207 25208 if(udf_attr->offset_map[entry_index].meter_enable == 1) { 25209 udf_attr->num_selectors += 1; 25210 } 25211 } 25212 if (buf) { 25213 soc_cm_sfree(unit, buf); 25214 } 25215 return rv; 25216 } 25217 25218 /* 25219 * Function: 25220 * _bcm_esw_svm_pkt_compressed_attr_maps_reference 25221 * Purpose: 25222 * Update reference count of compression attr maps after recover. 25223 * Parameters: 25224 * unit - (IN) unit number 25225 * compressed_attr_selectors_v - (IN) compressed attribute selectors. 25226 * pkt_attr_selectors - (IN) Packet attribute selectors 25227 * Returns: 25228 * BCM_E_XXX 25229 */ 25230 int _bcm_esw_svm_pkt_compressed_attr_maps_reference(int unit, 25231 compressed_attr_selectors_t *compressed_attr_selectors_v, 25232 bcm_policer_attr_selectors_t *pkt_attr_selectors) 25233 { 25234 pkt_attr_bits_t *pkt_attr_bits_v = NULL; 25235 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 25236 25237 pkt_attr_bits_v = &compressed_attr_selectors_v->pkt_attr_bits_v; 25238 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 25239 25240 if (cmprsd_attr_maps == NULL) { 25241 return BCM_E_NONE; 25242 } 25243 25244 /* update reference count for policer group created via group_mode */ 25245 if (pkt_attr_bits_v != NULL) { 25246 if ((pkt_attr_bits_v->cng != 0) || 25247 (pkt_attr_bits_v->int_pri != 0)) { 25248 (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map])++; 25249 cmprsd_attr_maps->cng = 1; 25250 cmprsd_attr_maps->int_pri = 1; 25251 } 25252 if ((pkt_attr_bits_v->vlan_format != 0) || 25253 (pkt_attr_bits_v->outer_dot1p != 0) || 25254 (pkt_attr_bits_v->inner_dot1p != 0)) { 25255 (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map])++; 25256 cmprsd_attr_maps->vlan_format = 1; 25257 cmprsd_attr_maps->outer_dot1p = 1; 25258 cmprsd_attr_maps->inner_dot1p = 1; 25259 } 25260 if (pkt_attr_bits_v->ing_port != 0) { 25261 (cmprsd_attr_maps->ref_counts[pkt_attr_port_map])++; 25262 cmprsd_attr_maps->port = 1; 25263 } 25264 if ((pkt_attr_bits_v->tos != 0) || 25265 (pkt_attr_bits_v->tos_ecn != 0)) { 25266 (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map])++; 25267 cmprsd_attr_maps->tos_dscp = 1; 25268 cmprsd_attr_maps->tos_ecn = 1; 25269 } 25270 if ((pkt_attr_bits_v->pkt_resolution != 0) || 25271 (pkt_attr_bits_v->svp_type != 0) || 25272 (pkt_attr_bits_v->drop != 0)) { 25273 (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map])++; 25274 cmprsd_attr_maps->pkt_resolution = 1; 25275 cmprsd_attr_maps->svp_type = 1; 25276 cmprsd_attr_maps->drop = 1; 25277 } 25278 } else if (pkt_attr_selectors != NULL) { 25279 if ((pkt_attr_selectors->cng != 0) || 25280 (pkt_attr_selectors->int_pri != 0)) { 25281 (cmprsd_attr_maps->ref_counts[pkt_attr_pri_cng_map])++; 25282 cmprsd_attr_maps->cng = 1; 25283 cmprsd_attr_maps->int_pri = 1; 25284 } 25285 if ((pkt_attr_selectors->vlan_format != 0) || 25286 (pkt_attr_selectors->outer_dot1p != 0) || 25287 (pkt_attr_selectors->inner_dot1p != 0)) { 25288 (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_pri_map])++; 25289 cmprsd_attr_maps->vlan_format = 1; 25290 cmprsd_attr_maps->outer_dot1p = 1; 25291 cmprsd_attr_maps->inner_dot1p = 1; 25292 } 25293 if (pkt_attr_selectors->port != 0) { 25294 (cmprsd_attr_maps->ref_counts[pkt_attr_port_map])++; 25295 cmprsd_attr_maps->port = 1; 25296 } 25297 if ((pkt_attr_selectors->tos_dscp != 0) || 25298 (pkt_attr_selectors->tos_ecn != 0)) { 25299 (cmprsd_attr_maps->ref_counts[pkt_attr_tos_map])++; 25300 cmprsd_attr_maps->tos_dscp = 1; 25301 cmprsd_attr_maps->tos_ecn = 1; 25302 } 25303 if ((pkt_attr_selectors->pkt_resolution != 0) || 25304 (pkt_attr_selectors->svp_type != 0) || 25305 (pkt_attr_selectors->drop != 0)) { 25306 (cmprsd_attr_maps->ref_counts[pkt_attr_pkt_res_map])++; 25307 cmprsd_attr_maps->pkt_resolution = 1; 25308 cmprsd_attr_maps->svp_type = 1; 25309 cmprsd_attr_maps->drop = 1; 25310 } 25311 } 25312 return BCM_E_NONE; 25313 } 25314 25315 /* 25316 * Function: 25317 * _bcm_esw_global_policer_offset_mode_update 25318 * Purpose: 25319 * Update global_meter_offset_mode information based on values retrieve 25320 * from scache on warmboot 25321 * Parameters: 25322 * unit - (IN) unit number 25323 * mode - (IN) meter offset mode 25324 * Returns: 25325 * BCM_E_XXX 25326 */ 25327 int _bcm_esw_global_policer_offset_mode_update(int unit, uint32 mode) 25328 { 25329 int rv; 25330 uint32 offset; 25331 uint32 width; 25332 int udf_id; 25333 uint32 num_selectors =0; 25334 uint32 total_subdiv=0, sel, index=0, index1=0, sorted; 25335 udf_pkt_attr_selectors_t *udf_pkt_attr = NULL; 25336 bcm_policer_group_mode_attr_selector_t *attr_selectors = NULL; 25337 bcm_policer_group_mode_attr_selector_wb_t *attr_selectors_wb = NULL; 25338 uint8 udf_set_bits[SVC_METER_UDF1_MAX_BIT_POSITION] = {0}; 25339 bcm_policer_udf_sub_div_t dummy_data; 25340 bcm_policer_udf_sub_div_t udf_subdiv[SVC_METER_UDF_MAX_SUB_DIVISIONS] = {{0,0,0}}; 25341 compressed_attr_selectors_t *cmprsd_attr_selectors = NULL; 25342 bcm_policer_attr_selectors_t pkt_attr_selectors; 25343 uint32 attr_count = 0; 25344 uint32 total_policers = 0; 25345 uint32 npolicers = 0; 25346 uint32 port_attr_count = 0; 25347 uint32 tos_dscp_attr_count = 0; 25348 uint32 tos_ecn_attr_count = 0; 25349 uint32 svp_type_attr_count = 0; 25350 25351 num_selectors = global_meter_offset_mode[unit][mode].no_of_selectors; 25352 attr_selectors_wb = global_meter_offset_mode[unit][mode].attr_selectors; 25353 total_policers = global_meter_offset_mode[unit][mode].no_of_policers; 25354 if ((global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \ 25355 udf_mode) || 25356 (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \ 25357 udf_cascade_mode) || 25358 (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == \ 25359 udf_cascade_with_coupling_mode)) { 25360 25361 /* Re-populate udf_subdiv based on attr_selectors */ 25362 udf_pkt_attr = &(global_meter_offset_mode[unit][mode].meter_attr. 25363 udf_pkt_attr_selectors_v); 25364 for (sel = 0; sel < num_selectors; sel++) { 25365 udf_id = attr_selectors_wb[sel].udf_id; 25366 offset = attr_selectors_wb[sel].offset; 25367 width = attr_selectors_wb[sel].width; 25368 25369 if (udf_set_bits[offset] == 0) { 25370 index = total_subdiv; 25371 udf_subdiv[index].udf_id = udf_id; 25372 udf_subdiv[index].offset = offset; 25373 udf_subdiv[index].width = width; 25374 total_subdiv++; 25375 udf_set_bits[offset] = 1; 25376 } 25377 } 25378 25379 /* Sort */ 25380 sorted = 0; 25381 for (index = 0; index < SVC_METER_UDF1_MAX_BIT_POSITION; index++) { 25382 if (udf_set_bits[index] == 1) { 25383 for (index1 = sorted; index1 < total_subdiv; index1++) { 25384 if (udf_subdiv[index1].offset == index) { 25385 /* Swap to rearrange */ 25386 sal_memcpy(&dummy_data, &udf_subdiv[index1], 25387 sizeof (bcm_policer_udf_sub_div_t)); 25388 sal_memcpy(&udf_subdiv[index1], 25389 &udf_subdiv[sorted], 25390 sizeof(bcm_policer_udf_sub_div_t)); 25391 sal_memcpy(&udf_subdiv[sorted], &dummy_data, 25392 sizeof (bcm_policer_udf_sub_div_t)); 25393 sorted++; 25394 break; 25395 } 25396 } 25397 } 25398 } 25399 /* Save */ 25400 memcpy (&(udf_pkt_attr->udf_subdiv[0]), &udf_subdiv[0], sizeof(udf_subdiv)); 25401 udf_pkt_attr->total_subdiv = total_subdiv; 25402 } else if (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == 25403 compressed_mode) { 25404 25405 /* If attr_selectors is NULL, update reference count from pkt_attr_bits_v */ 25406 if (attr_selectors_wb == NULL) { 25407 cmprsd_attr_selectors = &(global_meter_offset_mode[unit][mode]. 25408 meter_attr.compressed_attr_selectors_v); 25409 return _bcm_esw_svm_pkt_compressed_attr_maps_reference(unit, 25410 cmprsd_attr_selectors, NULL); 25411 } 25412 25413 npolicers = total_policers; 25414 if (global_meter_offset_mode[unit][mode].type == 25415 bcmPolicerGroupModeTypeCascadeWithCoupling) { 25416 npolicers = total_policers/2; 25417 } 25418 sal_memset(&pkt_attr_selectors, 0, sizeof(bcm_policer_attr_selectors_t)); 25419 pkt_attr_selectors.combine_attr_data = 25420 sal_alloc(sizeof(bcm_policer_combine_attr_t) * npolicers, 25421 "combine attributes"); 25422 if (pkt_attr_selectors.combine_attr_data == NULL) { 25423 return BCM_E_MEMORY; 25424 } 25425 sal_memset(pkt_attr_selectors.combine_attr_data, 0, 25426 sizeof(bcm_policer_combine_attr_t) * npolicers); 25427 25428 /* 25429 * allocate temp memory for convert attr_selectors_wb to attr_selectors 25430 * _bcm_esw_policer_group_mode_fillup_values 25431 */ 25432 attr_selectors = sal_alloc( 25433 sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors, 25434 "bcm_policer_group_mode_attr_selector_t"); 25435 if (attr_selectors == NULL) { 25436 return BCM_E_MEMORY; 25437 } 25438 sal_memset(attr_selectors, 0, 25439 sizeof(bcm_policer_group_mode_attr_selector_t) * num_selectors); 25440 25441 rv = _bcm_wb_attr_selectors_copy_to_attr_selectors( 25442 num_selectors, attr_selectors_wb, attr_selectors); 25443 if (BCM_FAILURE(rv)) { 25444 sal_free(attr_selectors); 25445 return (rv); 25446 } 25447 25448 _bcm_esw_policer_group_mode_fillup_values (unit, 0, 25449 global_meter_offset_mode[unit][mode].type, 25450 npolicers, num_selectors, attr_selectors, &pkt_attr_selectors); 25451 sal_free(attr_selectors); 25452 /* Update reference counts . */ 25453 (void) _bcm_esw_svm_pkt_compressed_attr_maps_reference(unit, 25454 NULL, &pkt_attr_selectors); 25455 25456 cmprsd_attr_selectors = &(global_meter_offset_mode[unit][mode]. 25457 meter_attr.compressed_attr_selectors_v); 25458 sal_memset (&cmprsd_attr_selectors->pkt_attr_bits_v, 0, 25459 sizeof(cmprsd_attr_selectors->pkt_attr_bits_v)); 25460 if (pkt_attr_selectors.cng != 0) { 25461 attr_count = _shr_popcount(pkt_attr_selectors.combine_cng_flags); 25462 cmprsd_attr_selectors->pkt_attr_bits_v.cng = 25463 _bcm_policer_num_of_bits_get(attr_count); 25464 } 25465 if (pkt_attr_selectors.int_pri != 0) { 25466 attr_count = _shr_popcount(pkt_attr_selectors.combine_int_pri_flags); 25467 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri = 25468 _bcm_policer_num_of_bits_get(attr_count); 25469 } 25470 if (pkt_attr_selectors.vlan_format != 0) { 25471 attr_count = _shr_popcount(pkt_attr_selectors.combine_vlan_format_flags); 25472 cmprsd_attr_selectors->pkt_attr_bits_v.vlan_format = 25473 _bcm_policer_num_of_bits_get(attr_count); 25474 } 25475 if (pkt_attr_selectors.outer_dot1p != 0) { 25476 attr_count = _shr_popcount(pkt_attr_selectors.combine_outer_dot1p_flags); 25477 cmprsd_attr_selectors->pkt_attr_bits_v.outer_dot1p = 25478 _bcm_policer_num_of_bits_get(attr_count); 25479 } 25480 if (pkt_attr_selectors.inner_dot1p != 0) { 25481 attr_count = _shr_popcount(pkt_attr_selectors.combine_inner_dot1p_flags); 25482 cmprsd_attr_selectors->pkt_attr_bits_v.inner_dot1p = 25483 _bcm_policer_num_of_bits_get(attr_count); 25484 } 25485 if (pkt_attr_selectors.pkt_resolution != 0) { 25486 attr_count = _shr_popcount(pkt_attr_selectors.combine_pkt_res_flags); 25487 cmprsd_attr_selectors->pkt_attr_bits_v.pkt_resolution = 25488 _bcm_policer_num_of_bits_get(attr_count); 25489 } 25490 if (pkt_attr_selectors.drop != 0) { 25491 attr_count = _shr_popcount(pkt_attr_selectors.combine_drop_flags); 25492 cmprsd_attr_selectors->pkt_attr_bits_v.drop = 25493 _bcm_policer_num_of_bits_get(attr_count); 25494 } 25495 if (pkt_attr_selectors.int_pri != 0) { 25496 attr_count = _shr_popcount(pkt_attr_selectors.combine_ip_pkt_flags); 25497 cmprsd_attr_selectors->pkt_attr_bits_v.int_pri = 25498 _bcm_policer_num_of_bits_get(attr_count); 25499 } 25500 for (index = 0; index < _BCM_POLICER_BIT_ARRAY_SIZE; index++) { 25501 port_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array 25502 [_bcmPolicerAttrPort][index]); 25503 tos_dscp_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array 25504 [_bcmPolicerAttrTosDscp][index]); 25505 tos_ecn_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array 25506 [_bcmPolicerAttrTosEcn][index]); 25507 svp_type_attr_count += _shr_popcount(pkt_attr_selectors.combine_value_array 25508 [_bcmPolicerAttrSvpType][index]); 25509 } 25510 cmprsd_attr_selectors->pkt_attr_bits_v.ing_port = 25511 _bcm_policer_num_of_bits_get(port_attr_count); 25512 cmprsd_attr_selectors->pkt_attr_bits_v.tos = 25513 _bcm_policer_num_of_bits_get(tos_dscp_attr_count); 25514 cmprsd_attr_selectors->pkt_attr_bits_v.tos_ecn = 25515 _bcm_policer_num_of_bits_get(tos_ecn_attr_count); 25516 cmprsd_attr_selectors->pkt_attr_bits_v.svp_type = 25517 _bcm_policer_num_of_bits_get(svp_type_attr_count); 25518 25519 sal_free(pkt_attr_selectors.combine_attr_data); 25520 } 25521 return BCM_E_NONE; 25522 } 25523 25524 /* 25525 * Function: 25526 * _bcm_esw_global_meter_offset_mode_reinit 25527 * Purpose: 25528 * Recover the service meter offset mode configuration information 25529 * from HW on warm boot 25530 * Parameters: 25531 * unit - (IN) unit number 25532 * Returns: 25533 * BCM_E_XXX 25534 */ 25535 int _bcm_esw_global_meter_offset_mode_reinit(int unit) 25536 { 25537 int rv = BCM_E_NONE; 25538 int mode = 0; 25539 bcm_policer_group_mode_t group_mode = 0; 25540 int npolicers = 0; 25541 uint64 selector_key_value; 25542 uint32 selector_count = 0, index = 0; 25543 uint32 selector_for_bit_x_en_field_value[8] = {0}; 25544 uint32 selector_for_bit_x_en_field_name[8] = { 25545 SELECTOR_0_ENf, 25546 SELECTOR_1_ENf, 25547 SELECTOR_2_ENf, 25548 SELECTOR_3_ENf, 25549 SELECTOR_4_ENf, 25550 SELECTOR_5_ENf, 25551 SELECTOR_6_ENf, 25552 SELECTOR_7_ENf, 25553 }; 25554 uint32 selector_for_bit_x_field_value[8] = {0}; 25555 uint32 selector_for_bit_x_field_name[8] = { 25556 SELECTOR_FOR_BIT_0f, 25557 SELECTOR_FOR_BIT_1f, 25558 SELECTOR_FOR_BIT_2f, 25559 SELECTOR_FOR_BIT_3f, 25560 SELECTOR_FOR_BIT_4f, 25561 SELECTOR_FOR_BIT_5f, 25562 SELECTOR_FOR_BIT_6f, 25563 SELECTOR_FOR_BIT_7f, 25564 }; 25565 bcm_policer_svc_meter_mode_type_t mode_type = 0; 25566 25567 COMPILER_64_ZERO(selector_key_value); 25568 for (mode = 1; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 25569 BCM_IF_ERROR_RETURN(soc_reg64_get(unit, 25570 _pkt_attr_sel_key_reg[mode], 25571 REG_PORT_ANY, 25572 0, 25573 &selector_key_value) 25574 ); 25575 if (!COMPILER_64_IS_ZERO(selector_key_value)) 25576 { 25577 for (selector_count = 0, index = 0; index < 8; index++) 25578 { 25579 selector_for_bit_x_en_field_value[index] = soc_reg64_field32_get( 25580 unit, 25581 _pkt_attr_sel_key_reg[mode], 25582 selector_key_value, 25583 selector_for_bit_x_en_field_name[index]); 25584 selector_count += selector_for_bit_x_en_field_value[index]; 25585 selector_for_bit_x_field_value[index] = 0; 25586 if (selector_for_bit_x_en_field_value[index] != 0) 25587 { 25588 selector_for_bit_x_field_value[index] = 25589 soc_reg64_field32_get( 25590 unit, 25591 _pkt_attr_sel_key_reg[mode], 25592 selector_key_value, 25593 selector_for_bit_x_field_name[index]); 25594 } 25595 } 25596 25597 if (soc_reg64_field32_get(unit, 25598 _pkt_attr_sel_key_reg[mode], 25599 selector_key_value, USE_UDF_KEYf)) 25600 { 25601 mode_type = udf_mode; 25602 rv = _bcm_esw_global_meter_udf_offset_mode_reinit(unit, mode, 25603 selector_count, selector_for_bit_x_en_field_value, 25604 selector_for_bit_x_field_value); 25605 if (BCM_FAILURE(rv)) { 25606 LOG_DEBUG(BSL_LS_BCM_POLICER, 25607 (BSL_META_U(unit, 25608 "Unable to re-init UDF offset mode\n"))); 25609 return (rv); 25610 } 25611 } else if (soc_reg64_field32_get(unit, 25612 _pkt_attr_sel_key_reg[mode], 25613 selector_key_value, 25614 USE_COMPRESSED_PKT_KEYf)) 25615 { 25616 rv = _bcm_esw_global_meter_compressed_offset_mode_reinit(unit, 25617 mode, selector_count, 25618 selector_for_bit_x_en_field_value, 25619 selector_for_bit_x_field_value); 25620 if (BCM_FAILURE(rv)) { 25621 LOG_DEBUG(BSL_LS_BCM_POLICER, 25622 (BSL_META_U(unit, 25623 "Unable to re-init compressed offset " 25624 "mode\n"))); 25625 return (rv); 25626 } 25627 } else { 25628 rv = _bcm_esw_global_meter_uncompressed_offset_mode_reinit( 25629 unit, mode, selector_count, 25630 selector_for_bit_x_en_field_value, 25631 selector_for_bit_x_field_value); 25632 if (BCM_FAILURE(rv)) { 25633 LOG_VERBOSE(BSL_LS_BCM_POLICER, 25634 (BSL_META_U(unit, 25635 "Unable to re-init uncompressed offset " 25636 "mode\n"))); 25637 return (rv); 25638 } 25639 } 25640 /* get the number of policers allocated for this mode */ 25641 /* Warmboot version BCM_WB_VERSION_1_1 onwards, npolicers and 25642 group_mode are stored in scache. This function call is still 25643 left here for backward compatibility */ 25644 rv = _bcm_esw_policer_get_offset_table_policer_count(unit, 25645 mode, &group_mode, &npolicers); 25646 if (BCM_FAILURE(rv)) { 25647 LOG_DEBUG(BSL_LS_BCM_POLICER, 25648 (BSL_META_U(unit, 25649 "Unable to re-init number of policers " 25650 "to be allcated in this mode\n"))); 25651 return (rv); 25652 } 25653 25654 /* If npolicers is ZERO, group mode is also not stored */ 25655 if (npolicers == 0) { 25656 continue; 25657 } 25658 global_meter_offset_mode[unit][mode].no_of_policers = npolicers; 25659 global_meter_offset_mode[unit][mode].group_mode = group_mode; 25660 if ((group_mode == bcmPolicerGroupModeCascade) || 25661 (group_mode == bcmPolicerGroupModeCascadeWithCoupling) || 25662 (group_mode == bcmPolicerGroupModeCascadeDroppedPktExclude) || 25663 (group_mode == bcmPolicerGroupModeIntPriCascade) || 25664 (group_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 25665 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = 25666 cascade_mode; 25667 } 25668 if (mode_type == udf_cascade_mode) { 25669 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = 25670 udf_cascade_mode; 25671 } 25672 if (mode_type == udf_cascade_with_coupling_mode) { 25673 global_meter_offset_mode[unit][mode].meter_attr.mode_type_v = 25674 udf_cascade_with_coupling_mode; 25675 } 25676 } 25677 } 25678 return rv; 25679 } 25680 25681 /* 25682 * Function: 25683 * _bcm_esw_global_meter_action_reinit 25684 * Purpose: 25685 * Recover the policer action table entries on warm boot 25686 * Parameters: 25687 * unit - (IN) unit number 25688 * Returns: 25689 * BCM_E_XXX 25690 */ 25691 int _bcm_esw_global_meter_action_reinit(int unit) 25692 { 25693 int rv = BCM_E_NONE; 25694 int total_size = SOC_INFO(unit).global_meter_action_size; 25695 25696 GLOBAL_METER_LOCK(unit); 25697 rv = _bcm_esw_svm_source_traverse (unit, SVM_POLICY_TABLEm, -1, total_size - 1, 25698 _bcm_esw_svm_action_reinit_from_table, NULL); 25699 GLOBAL_METER_UNLOCK(unit); 25700 return rv; 25701 } 25702 25703 /* 25704 * Function: 25705 * _bcm_esw_svm_pkt_compressed_attr_maps_sync 25706 * Purpose: 25707 * Sync compressed attr maps to scache. 25708 * Parameters: 25709 * unit - (IN) unit number 25710 * scache_position - (IN/OUT) Scache position 25711 * Returns: 25712 * BCM_E_XXX 25713 */ 25714 int 25715 _bcm_esw_svm_pkt_compressed_attr_maps_sync(int unit, uint8 **scache_position) 25716 { 25717 int i = 0; 25718 uint8 *scache_ptr = NULL; 25719 uint32 array_size = 0; 25720 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_map = NULL; 25721 25722 scache_ptr = *scache_position; 25723 25724 cmprsd_attr_map = svm_pkt_compressed_attr_maps_g[unit]; 25725 25726 if (cmprsd_attr_map->cng != 0) { 25727 sal_memcpy(scache_ptr, 25728 &cmprsd_attr_map->combine_cng_flags, 25729 sizeof(uint32)); 25730 } else { 25731 sal_memset(scache_ptr, 0, sizeof(uint32)); 25732 } 25733 scache_ptr += sizeof(uint32); 25734 25735 if (cmprsd_attr_map->int_pri != 0) { 25736 sal_memcpy(scache_ptr, 25737 &cmprsd_attr_map->combine_int_pri_flags, 25738 sizeof(uint32)); 25739 } else { 25740 sal_memset(scache_ptr, 0, sizeof(uint32)); 25741 } 25742 scache_ptr += sizeof(uint32); 25743 25744 if (cmprsd_attr_map->vlan_format != 0) { 25745 sal_memcpy(scache_ptr, 25746 &cmprsd_attr_map->combine_vlan_format_flags, 25747 sizeof(uint32)); 25748 } else { 25749 sal_memset(scache_ptr, 0, sizeof(uint32)); 25750 } 25751 scache_ptr += sizeof(uint32); 25752 25753 if (cmprsd_attr_map->outer_dot1p != 0) { 25754 sal_memcpy(scache_ptr, 25755 &cmprsd_attr_map->combine_outer_dot1p_flags, 25756 sizeof(uint32)); 25757 } else { 25758 sal_memset(scache_ptr, 0, sizeof(uint32)); 25759 } 25760 scache_ptr += sizeof(uint32); 25761 25762 if (cmprsd_attr_map->inner_dot1p != 0) { 25763 sal_memcpy(scache_ptr, 25764 &cmprsd_attr_map->combine_inner_dot1p_flags, 25765 sizeof(uint32)); 25766 } else { 25767 sal_memset(scache_ptr, 0, sizeof(uint32)); 25768 } 25769 scache_ptr += sizeof(uint32); 25770 25771 if (cmprsd_attr_map->pkt_resolution != 0) { 25772 sal_memcpy(scache_ptr, 25773 &cmprsd_attr_map->combine_pkt_res_flags, 25774 sizeof(uint32)); 25775 } else { 25776 sal_memset(scache_ptr, 0, sizeof(uint32)); 25777 } 25778 scache_ptr += sizeof(uint32); 25779 25780 if (cmprsd_attr_map->drop != 0) { 25781 sal_memcpy(scache_ptr, 25782 &cmprsd_attr_map->combine_drop_flags, 25783 sizeof(uint32)); 25784 } else { 25785 sal_memset(scache_ptr, 0, sizeof(uint32)); 25786 } 25787 scache_ptr += sizeof(uint32); 25788 25789 if (cmprsd_attr_map->ip_pkt != 0) { 25790 sal_memcpy(scache_ptr, 25791 &cmprsd_attr_map->combine_ip_pkt_flags, 25792 sizeof(uint32)); 25793 } else { 25794 sal_memset(scache_ptr, 0, sizeof(uint32)); 25795 } 25796 scache_ptr += sizeof(uint32); 25797 25798 /* Syncing Attributes which are array. */ 25799 if (cmprsd_attr_map->port != 0) { 25800 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25801 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25802 scache_ptr += sizeof(uint32); 25803 for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 25804 sal_memcpy(scache_ptr, 25805 &cmprsd_attr_map->combine_value_array 25806 [_bcmPolicerAttrPort][i], sizeof(uint32)); 25807 scache_ptr += sizeof(uint32); 25808 } 25809 } else { 25810 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25811 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25812 scache_ptr += sizeof(uint32); 25813 sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25814 scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25815 } 25816 25817 if (cmprsd_attr_map->tos_dscp != 0) { 25818 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25819 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25820 scache_ptr += sizeof(uint32); 25821 for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 25822 sal_memcpy(scache_ptr, 25823 &cmprsd_attr_map->combine_value_array 25824 [_bcmPolicerAttrTosDscp][i], sizeof(uint32)); 25825 scache_ptr += sizeof(uint32); 25826 } 25827 } else { 25828 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25829 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25830 scache_ptr += sizeof(uint32); 25831 sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25832 scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25833 } 25834 25835 if (cmprsd_attr_map->tos_ecn != 0) { 25836 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25837 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25838 scache_ptr += sizeof(uint32); 25839 for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 25840 sal_memcpy(scache_ptr, 25841 &cmprsd_attr_map->combine_value_array 25842 [_bcmPolicerAttrTosEcn][i], 25843 sizeof(uint32)); 25844 scache_ptr += sizeof(uint32); 25845 } 25846 } else { 25847 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25848 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25849 scache_ptr += sizeof(uint32); 25850 sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25851 scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25852 } 25853 25854 if (cmprsd_attr_map->svp_type != 0) { 25855 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25856 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25857 scache_ptr += sizeof(uint32); 25858 for(i = 0; i < _BCM_POLICER_BIT_ARRAY_SIZE; i++) { 25859 sal_memcpy(scache_ptr, 25860 &cmprsd_attr_map->combine_value_array 25861 [_bcmPolicerAttrSvpType][i], 25862 sizeof(uint32)); 25863 scache_ptr += sizeof(uint32); 25864 } 25865 } else { 25866 array_size = _BCM_POLICER_BIT_ARRAY_SIZE; 25867 sal_memcpy(scache_ptr, &array_size, sizeof(uint32)); 25868 scache_ptr += sizeof(uint32); 25869 sal_memset(scache_ptr, 0, sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25870 scache_ptr += (sizeof(uint32) * _BCM_POLICER_BIT_ARRAY_SIZE); 25871 } 25872 25873 *scache_position = scache_ptr; 25874 25875 return BCM_E_NONE; 25876 } 25877 25878 /* 25879 * Function: 25880 * _bcm_esw_global_meter_policer_sync 25881 * Purpose: 25882 * Write poliers which are created but not yet used in any 25883 * table to scache so that we can recover the configuration 25884 * on warm boot 25885 * Parameters: 25886 * unit - (IN) unit number 25887 * Returns: 25888 * BCM_E_XXX 25889 */ 25890 int 25891 _bcm_esw_global_meter_policer_sync(int unit) 25892 { 25893 int rv = BCM_E_NONE; 25894 soc_scache_handle_t scache_handle; 25895 _global_meter_policer_control_t *global_meter_pl = NULL; 25896 uint32 hash_index; /* Entry hash */ 25897 int policer_id = 0; 25898 uint8 *policer_state = NULL; 25899 uint32 npolicers, group, udf_id; 25900 uint8 type; 25901 int mode; 25902 int size = 0, count = 0; 25903 bcm_policer_svc_meter_attr_t *meter_attr = NULL; 25904 bcm_policer_group_mode_attr_selectors_info_t *attr_selectors_info = NULL; 25905 25906 #if defined(BCM_GLOBAL_METER_V2_SUPPORT) 25907 if (soc_feature(unit, soc_feature_global_meter_v2)) { 25908 return bcmi_esw_global_meter_policer_sync(unit); 25909 } 25910 #endif /* BCM_GLOBAL_METER_V2_SUPPORT */ 25911 25912 if (!soc_feature(unit, soc_feature_global_meter)) { 25913 return BCM_E_UNAVAIL; 25914 } 25915 25916 CHECK_GLOBAL_METER_INIT(unit); 25917 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 25918 25919 BCM_IF_ERROR_RETURN(_bcm_esw_svc_meter_wb_size_calc(unit, &size)); 25920 SOC_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 25921 FALSE, size, &policer_state, 25922 BCM_WB_DEFAULT_VERSION, NULL)); 25923 25924 if (NULL == policer_state) { 25925 LOG_VERBOSE(BSL_LS_BCM_POLICER, 25926 (BSL_META_U(unit, 25927 "SCACHE Memory not available \n"))); 25928 return BCM_E_MEMORY; 25929 } 25930 25931 attr_selectors_info = 25932 sal_alloc(sizeof(bcm_policer_group_mode_attr_selectors_info_t), 25933 "attr selector info"); 25934 if (NULL == attr_selectors_info) { 25935 LOG_VERBOSE(BSL_LS_BCM_POLICER, 25936 (BSL_META_U(unit, 25937 "Memory not available \n"))); 25938 return BCM_E_MEMORY; 25939 } 25940 sal_memset(attr_selectors_info, 0, 25941 sizeof(bcm_policer_group_mode_attr_selectors_info_t)); 25942 25943 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 25944 /* Iterate through global_meter_offset_mode to store 25945 npolicers,group_mode,udf_id */ 25946 for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 25947 if (global_meter_offset_mode[unit][mode].used == 1) { 25948 npolicers = global_meter_offset_mode[unit][mode].no_of_policers; 25949 sal_memcpy(policer_state, &npolicers, sizeof(uint32)); 25950 policer_state += sizeof(uint32); 25951 25952 /* Using same 32-bit for saving group mode and type. 25953 * group mode (0-23), type (24-31) */ 25954 group = (uint32)global_meter_offset_mode[unit][mode].group_mode; 25955 type = (global_meter_offset_mode[unit][mode].type == -1) ? 25956 0 : (global_meter_offset_mode[unit][mode].type + 1); 25957 group |= (type << BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_SHIFT); 25958 sal_memcpy(policer_state, &group, sizeof(uint32)); 25959 policer_state += sizeof(uint32); 25960 25961 meter_attr = &global_meter_offset_mode[unit][mode].meter_attr; 25962 udf_id = meter_attr->udf_pkt_attr_selectors_v.udf_id; 25963 sal_memcpy(policer_state, &udf_id, sizeof(uint32)); 25964 policer_state += sizeof(uint32); 25965 25966 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) { 25967 if (global_meter_offset_mode[unit][mode].type == -1) { 25968 sal_memset(policer_state, 0, 25969 sizeof(bcm_policer_group_mode_attr_selectors_info_t)); 25970 policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t); 25971 continue; 25972 } 25973 25974 /*Save attr_selectors info */ 25975 if (global_meter_offset_mode[unit][mode].attr_selectors != NULL) { 25976 attr_selectors_info->flags = 0; 25977 attr_selectors_info->num_selectors = 25978 global_meter_offset_mode[unit][mode].no_of_selectors; 25979 sal_memcpy(&(attr_selectors_info->attr_selectors)[0], 25980 &global_meter_offset_mode[unit][mode].attr_selectors[0], 25981 sizeof(bcm_policer_group_mode_attr_selector_wb_t) * \ 25982 attr_selectors_info->num_selectors); 25983 sal_memcpy(policer_state, attr_selectors_info, 25984 sizeof(bcm_policer_group_mode_attr_selectors_info_t)); 25985 } 25986 policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t); 25987 } 25988 } 25989 } 25990 } 25991 25992 if (NULL != attr_selectors_info) { 25993 sal_free(attr_selectors_info); 25994 } 25995 25996 /* go through policer control bookkeep structure and get policer 25997 entries with ref_count=0 */ 25998 for (hash_index = 0; hash_index < _GLOBAL_METER_HASH_SIZE; hash_index++) { 25999 global_meter_pl = global_meter_policer_bookkeep[unit][hash_index]; 26000 while ((NULL != global_meter_pl) && 26001 (count < BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES)) { 26002 /* Match entry id. */ 26003 if (global_meter_pl->ref_count == 0) { 26004 policer_id = global_meter_pl->pid; 26005 sal_memcpy(policer_state, &policer_id, sizeof(bcm_policer_t)); 26006 policer_state += sizeof(bcm_policer_t); 26007 count++; 26008 } 26009 global_meter_pl = global_meter_pl->next; 26010 } 26011 if (count == BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES) { 26012 return rv; 26013 } 26014 } 26015 policer_state += 26016 (sizeof(bcm_policer_t) * (BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES - count)); 26017 26018 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) { 26019 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 26020 BCM_IF_ERROR_RETURN(_bcm_esw_svm_pkt_compressed_attr_maps_sync(unit, 26021 &policer_state)); 26022 } 26023 } 26024 return rv; 26025 } 26026 26027 /* 26028 * Function: 26029 * _bcm_esw_svm_pkt_compressed_attr_maps_recover 26030 * Purpose: 26031 * Recover compressed attr maps from scache. 26032 * Parameters: 26033 * unit - (IN) unit number 26034 * recovered_ver - (IN) recovered wb version 26035 * scache_position - (IN/OUT) Scache position 26036 * Returns: 26037 * BCM_E_XXX 26038 */ 26039 int _bcm_esw_svm_pkt_compressed_attr_maps_recover(int unit, 26040 uint16 recovered_ver, 26041 uint8 **scache_position) 26042 { 26043 int i = 0; 26044 uint8 *scache_ptr = NULL; 26045 uint32 array_size = 0; 26046 _bcm_policer_pkt_compressed_attr_maps_t *cmprsd_attr_maps = NULL; 26047 26048 scache_ptr = *scache_position; 26049 26050 cmprsd_attr_maps = svm_pkt_compressed_attr_maps_g[unit]; 26051 26052 /* combine_cng_flags. */ 26053 sal_memcpy(&cmprsd_attr_maps->combine_cng_flags, 26054 scache_ptr, sizeof(uint32)); 26055 scache_ptr += sizeof(uint32); 26056 26057 /* combine_int_pri_flags */ 26058 sal_memcpy(&cmprsd_attr_maps->combine_int_pri_flags, 26059 scache_ptr, sizeof(uint32)); 26060 scache_ptr += sizeof(uint32); 26061 26062 /* combine_vlan_format_flags */ 26063 sal_memcpy(&cmprsd_attr_maps->combine_vlan_format_flags, 26064 scache_ptr, sizeof(uint32)); 26065 scache_ptr += sizeof(uint32); 26066 26067 /* combine_outer_dot1p_flags */ 26068 sal_memcpy(&cmprsd_attr_maps->combine_outer_dot1p_flags, 26069 scache_ptr, sizeof(uint32)); 26070 scache_ptr += sizeof(uint32); 26071 26072 /* combine_inner_dot1p_flags */ 26073 sal_memcpy(&cmprsd_attr_maps->combine_inner_dot1p_flags, 26074 scache_ptr, sizeof(uint32)); 26075 scache_ptr += sizeof(uint32); 26076 26077 /* combine_pkt_res_flags */ 26078 sal_memcpy(&cmprsd_attr_maps->combine_pkt_res_flags, 26079 scache_ptr, sizeof(uint32)); 26080 scache_ptr += sizeof(uint32); 26081 26082 /* combine_drop_flags */ 26083 sal_memcpy(&cmprsd_attr_maps->combine_drop_flags, 26084 scache_ptr, sizeof(uint32)); 26085 scache_ptr += sizeof(uint32); 26086 26087 /* combine_ip_pkt_flags */ 26088 sal_memcpy(&cmprsd_attr_maps->combine_ip_pkt_flags, 26089 scache_ptr, sizeof(uint32)); 26090 scache_ptr += sizeof(uint32); 26091 26092 /* Recovering Attributes which are array. */ 26093 sal_memcpy(&array_size, scache_ptr, sizeof(uint32)); 26094 scache_ptr += sizeof(uint32); 26095 for(i = 0; i < array_size; i++) { 26096 sal_memcpy(&cmprsd_attr_maps->combine_value_array 26097 [_bcmPolicerAttrPort][i], scache_ptr, sizeof(uint32)); 26098 scache_ptr += sizeof(uint32); 26099 } 26100 sal_memcpy(&array_size, scache_ptr, sizeof(uint32)); 26101 scache_ptr += sizeof(uint32); 26102 for(i = 0; i < array_size; i++) { 26103 sal_memcpy(&cmprsd_attr_maps->combine_value_array 26104 [_bcmPolicerAttrTosDscp][i], scache_ptr, sizeof(uint32)); 26105 scache_ptr += sizeof(uint32); 26106 } 26107 sal_memcpy(&array_size, scache_ptr, sizeof(uint32)); 26108 scache_ptr += sizeof(uint32); 26109 for(i = 0; i < array_size; i++) { 26110 sal_memcpy(&cmprsd_attr_maps->combine_value_array 26111 [_bcmPolicerAttrTosEcn][i], scache_ptr, sizeof(uint32)); 26112 scache_ptr += sizeof(uint32); 26113 } 26114 sal_memcpy(&array_size, scache_ptr, sizeof(uint32)); 26115 scache_ptr += sizeof(uint32); 26116 for(i = 0; i < array_size; i++) { 26117 sal_memcpy(&cmprsd_attr_maps->combine_value_array 26118 [_bcmPolicerAttrSvpType][i], scache_ptr, sizeof(uint32)); 26119 scache_ptr += sizeof(uint32); 26120 } 26121 26122 *scache_position = scache_ptr; 26123 26124 return BCM_E_NONE; 26125 } 26126 26127 /* 26128 * Function: 26129 * _bcm_esw_global_meter_policer_recover_from_scache 26130 * Purpose: 26131 * Recover policers which are not configured in HW from 26132 * Scache as part of warm boot 26133 * Parameters: 26134 * unit - (IN) unit number 26135 * Returns: 26136 * BCM_E_XXX 26137 */ 26138 int _bcm_esw_global_meter_policer_recover_from_scache(int unit) 26139 { 26140 int rv = BCM_E_NONE; 26141 int stable_size; 26142 uint16 recovered_ver; 26143 int policer_id = 0; 26144 uint8 *policer_state = NULL; 26145 uint32 npolicers, udf_id; 26146 uint32 group = 0; 26147 uint8 type = 0; 26148 int mode=0; 26149 int size = 0, scache_index = 0; 26150 uint32 num_selectors = 0; 26151 soc_scache_handle_t scache_handle; 26152 _global_meter_policer_control_t *policer_control = NULL; 26153 bcm_policer_svc_meter_attr_t *meter_attr = NULL; 26154 bcm_policer_group_mode_attr_selectors_info_t *attr_sel_info; 26155 bcm_policer_group_mode_t group_mode; 26156 26157 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_POLICER, 0); 26158 BCM_IF_ERROR_RETURN(_bcm_esw_svc_meter_wb_size_calc(unit, &size)); 26159 26160 if (SOC_WARM_BOOT(unit)) { 26161 /* Warm Boot */ 26162 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 26163 if (stable_size > size) { 26164 SOC_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 26165 FALSE, size, &policer_state, 26166 BCM_WB_DEFAULT_VERSION, &recovered_ver)); 26167 26168 if (NULL == policer_state) { 26169 LOG_DEBUG(BSL_LS_BCM_POLICER, 26170 (BSL_META_U(unit, 26171 "SCACHE Memory not available \n"))); 26172 return BCM_E_MEMORY; 26173 } 26174 26175 /* Read from scache and populate fields for global_meter_offset_mode first */ 26176 if (recovered_ver >= BCM_WB_VERSION_1_1) { 26177 for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 26178 if (global_meter_offset_mode[unit][mode].used == 1) { 26179 sal_memcpy(&npolicers, policer_state, sizeof(uint32)); 26180 global_meter_offset_mode[unit][mode].no_of_policers = npolicers; 26181 policer_state += (sizeof(uint32)); 26182 26183 sal_memcpy(&group, policer_state, sizeof(uint32)); 26184 group_mode = (group & (~(BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_MASK))); 26185 global_meter_offset_mode[unit][mode].group_mode = group_mode; 26186 type = (group & BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_MASK) >> 26187 BCM_POLICER_GLOBAL_METER_GROUP_MODE_TYPE_SHIFT; 26188 if (type == 0) { 26189 global_meter_offset_mode[unit][mode].type = -1; 26190 } else { 26191 global_meter_offset_mode[unit][mode].type = type - 1; 26192 } 26193 policer_state+=(sizeof(uint32)); 26194 26195 meter_attr = &global_meter_offset_mode[unit][mode].meter_attr; 26196 sal_memcpy(&udf_id, policer_state, sizeof(uint32)); 26197 meter_attr->udf_pkt_attr_selectors_v.udf_id = udf_id; 26198 policer_state += (sizeof(uint32)); 26199 26200 if (recovered_ver >= BCM_WB_VERSION_1_2) { 26201 if (global_meter_offset_mode[unit][mode].type != -1) { 26202 attr_sel_info = (bcm_policer_group_mode_attr_selectors_info_t *) policer_state; 26203 num_selectors = attr_sel_info->num_selectors; 26204 global_meter_offset_mode[unit][mode].no_of_selectors = num_selectors; 26205 26206 if (num_selectors != 0) { 26207 global_meter_offset_mode[unit][mode].attr_selectors = 26208 sal_alloc(sizeof(bcm_policer_group_mode_attr_selector_wb_t) * num_selectors, 26209 "attr selector info"); 26210 if (global_meter_offset_mode[unit][mode].attr_selectors == NULL) { 26211 _bcm_esw_global_meter_cleanup(unit); 26212 return BCM_E_MEMORY; 26213 } 26214 sal_memcpy(&(global_meter_offset_mode[unit][mode].attr_selectors[0]), 26215 &(attr_sel_info->attr_selectors[0]), 26216 sizeof(bcm_policer_group_mode_attr_selector_wb_t) * num_selectors); 26217 } 26218 if (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v != 26219 compressed_mode) { 26220 _bcm_esw_global_policer_offset_mode_update(unit, mode); 26221 } 26222 } 26223 policer_state += sizeof(bcm_policer_group_mode_attr_selectors_info_t); 26224 } 26225 /* handling mode_type_v/type for udf based policers */ 26226 if (meter_attr->mode_type_v == udf_mode) { 26227 global_meter_offset_mode[unit][mode].type = bcmPolicerGroupModeTypeNormal; 26228 if (group_mode == bcmPolicerGroupModeCascade) { 26229 meter_attr->mode_type_v = udf_cascade_mode; 26230 global_meter_offset_mode[unit][mode].type = 26231 bcmPolicerGroupModeTypeCascade; 26232 } else if (group_mode == bcmPolicerGroupModeCascadeWithCoupling) { 26233 meter_attr->mode_type_v = udf_cascade_with_coupling_mode; 26234 global_meter_offset_mode[unit][mode].type = 26235 bcmPolicerGroupModeTypeCascadeWithCoupling; 26236 } 26237 } else if (global_meter_offset_mode[unit][mode].type != -1) { 26238 /* Here, for group type Cascade/CascadeWithCoupling, there is 26239 * no need to modfy mode_type_v. Lets keep it compressed/uncompressed. */ 26240 ; 26241 } else { 26242 if ((group_mode == bcmPolicerGroupModeCascade) || 26243 (group_mode == bcmPolicerGroupModeCascadeWithCoupling) || 26244 (group_mode == bcmPolicerGroupModeIntPriCascade) || 26245 (group_mode == bcmPolicerGroupModeCascadeDroppedPktExclude) || 26246 (group_mode == bcmPolicerGroupModeIntPriCascadeWithCoupling)) { 26247 meter_attr->mode_type_v = cascade_mode; 26248 } 26249 } 26250 } 26251 } 26252 } 26253 26254 /* read from scache and create policer bookkeep data structure */ 26255 for (scache_index = 0; scache_index < 26256 BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES; scache_index++) { 26257 sal_memcpy(&policer_id, 26258 &policer_state[scache_index * sizeof(int)], 26259 sizeof(int)); 26260 if ((policer_id & BCM_POLICER_GLOBAL_METER_INDEX_MASK) > 0) { 26261 policer_control = NULL; 26262 rv = _bcm_esw_policer_config_from_meter_table(unit, 26263 policer_id, policer_control); 26264 } 26265 } 26266 policer_state += (BCM_GLOBAL_METER_MAX_SCACHE_ENTRIES * sizeof(int)); 26267 26268 if (recovered_ver >= BCM_WB_VERSION_1_3) { 26269 if (soc_feature(unit, soc_feature_global_meter_compression_share)) { 26270 /* Recover combined flags for compressd mode */ 26271 (void) _bcm_esw_svm_pkt_compressed_attr_maps_recover(unit, 26272 recovered_ver, &policer_state); 26273 } 26274 } 26275 26276 /* Loop through all modes and update for compressed mode. */ 26277 for (mode = 0; mode < BCM_POLICER_SVC_METER_MAX_MODE; mode++) { 26278 if ((global_meter_offset_mode[unit][mode].used == 1) && 26279 (global_meter_offset_mode[unit][mode].meter_attr.mode_type_v == 26280 compressed_mode)) { 26281 _bcm_esw_global_policer_offset_mode_update(unit, mode); 26282 } 26283 } 26284 } 26285 } else { 26286 /* Cold Boot */ 26287 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 26288 size, &policer_state, 26289 BCM_WB_DEFAULT_VERSION, NULL); 26290 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 26291 LOG_DEBUG(BSL_LS_BCM_POLICER, 26292 (BSL_META_U(unit, 26293 "Scache Memory not available\n"))); 26294 return rv; 26295 } 26296 } 26297 return BCM_E_NONE; 26298 } 26299 26300 /* 26301 * Function: 26302 * _bcm_esw_global_meter_reinit 26303 * Purpose: 26304 * Reinit all the global meter internal data structures on warm boot 26305 * Parameters: 26306 * unit - (IN) unit number 26307 * Returns: 26308 * BCM_E_XXX 26309 */ 26310 int _bcm_esw_global_meter_reinit(int unit) 26311 { 26312 int rv = BCM_E_NONE; 26313 26314 rv = _bcm_esw_global_meter_offset_mode_reinit(unit); 26315 if (BCM_FAILURE(rv)) { 26316 LOG_VERBOSE(BSL_LS_BCM_POLICER, 26317 (BSL_META_U(unit, 26318 "Unable to reinit offset modes\n"))); 26319 return (rv); 26320 } 26321 /* go through scache and recover policer configuration */ 26322 rv = _bcm_esw_global_meter_policer_recover_from_scache(unit); 26323 if (BCM_FAILURE(rv)) { 26324 LOG_VERBOSE(BSL_LS_BCM_POLICER, 26325 (BSL_META_U(unit, 26326 "Unable to reinit policer configuration\n"))); 26327 return (rv); 26328 } 26329 /* go through all policer entries to increment action reference count 26330 and set policer configuration parameter */ 26331 rv = _bcm_policer_config_reinit(unit); 26332 if (BCM_FAILURE(rv)) { 26333 LOG_VERBOSE(BSL_LS_BCM_POLICER, 26334 (BSL_META_U(unit, 26335 "Unable to reinit policer configuration\n"))); 26336 return (rv); 26337 } 26338 /* reinit action table bookkeep data structure */ 26339 rv = _bcm_esw_global_meter_action_reinit(unit); 26340 if (BCM_FAILURE(rv)) { 26341 LOG_VERBOSE(BSL_LS_BCM_POLICER, 26342 (BSL_META_U(unit, 26343 "Unable to reinit meter action configuration\n"))); 26344 return (rv); 26345 } 26346 return BCM_E_NONE; 26347 } 26348 26349 #endif /* BCM_WARM_BOOT_SUPPORT */ 26350 26351