bregex.c (149676B)
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 * COS Queue Management 8 * Purpose: API to program Regex engine for flow tracking 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <sal/core/libc.h> 14 #if defined(INCLUDE_REGEX) 15 16 #include <soc/drv.h> 17 #include <soc/mem.h> 18 19 #include <bcm/error.h> 20 #include <bcm/cosq.h> 21 22 #include <bcm_int/esw/mbcm.h> 23 #include <bcm_int/esw/stack.h> 24 #include <bcm_int/esw/firebolt.h> 25 #include <bcm_int/esw/triumph.h> 26 #include <bcm_int/esw/triumph2.h> 27 #include <bcm_int/esw/policer.h> 28 #include <bcm_int/esw/mirror.h> 29 #include <bcm_int/esw/fb4regex.h> 30 #include <bcm_int/esw/bregex.h> 31 #include <bcm/bregex.h> 32 #include <bcm_int/esw_dispatch.h> 33 34 STATIC _bcm_esw_regex_device_info_t *_regex_info[BCM_MAX_NUM_UNITS] = {0}; 35 36 #define ESW_REGEX_INFO(_unit) _regex_info[_unit] 37 #define ESW_REGEX_LOCK(_unit) _regex_lock(_unit) 38 #define ESW_REGEX_UNLOCK(_unit) _regex_unlock(_unit) 39 40 /* This macro will return one less than the physical number of policies because the first 41 * policy entry is reserved for the default policy. */ 42 #define ESW_REGEX_POLICIES_MAX(_unit) (ESW_REGEX_INFO(_unit)->policy_index_max - ESW_REGEX_INFO(_unit)->policy_index_min) 43 /* This macro will return one more than the first index since the first entry is reserved 44 * for the default policy. */ 45 #define ESW_REGEX_POLICIES_FIRST(_unit) (ESW_REGEX_INFO(_unit)->policy_index_min + 1) 46 #define ESW_REGEX_POLICIES_LAST(_unit) (ESW_REGEX_INFO(_unit)->policy_index_max) 47 48 #define IS_FLOW_MODE(f_pl) \ 49 ((f_pl)->cfg.mode == bcmPolicerModeCommitted || \ 50 (f_pl)->cfg.mode == bcmPolicerModePeak) 51 52 #define IS_MOD_TRTCM_MODE(f_pl) \ 53 ((f_pl)->cfg.mode == bcmPolicerModeTrTcmDs || \ 54 (f_pl)->cfg.mode == bcmPolicerModeCoupledTrTcmDs) 55 56 STATIC int last_allocated_policy = 0; 57 58 STATIC int _regex_policy_create_id(int unit, bcm_regex_policy_t policy); 59 STATIC int _regex_policy_install(int unit, bcm_regex_policy_t policy); 60 61 STATIC int _regex_lock(int unit) 62 { 63 _bcm_esw_regex_device_info_t *device; 64 65 device = ESW_REGEX_INFO(unit); 66 if (NULL == device) { 67 return BCM_E_INIT; 68 } 69 70 sal_mutex_take(device->regex_esw_mutex, sal_mutex_FOREVER); 71 return BCM_E_NONE; 72 } 73 74 STATIC void _regex_unlock(int unit) 75 { 76 _bcm_esw_regex_device_info_t *device; 77 78 device = ESW_REGEX_INFO(unit); 79 sal_mutex_give(device->regex_esw_mutex); 80 } 81 82 void _bcm_esw_regex_policy_action_t_init(_regex_policy_action_t *pa) 83 { 84 sal_memset(pa, 0, sizeof(*pa)); 85 pa->hw_index = _REGEX_INVALID_INDEX; 86 pa->old_index = _REGEX_INVALID_INDEX; 87 } 88 89 void _bcm_esw_regex_policy_t_init(_regex_policy_t *policy) 90 { 91 int idx; 92 93 sal_memset(policy, 0, sizeof(*policy)); 94 95 policy->statistic.sid = _REGEX_INVALID_INDEX; 96 /* Initialize policer ids as invalid for all policer levels. */ 97 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 98 policy->policer[idx].pid = _REGEX_INVALID_INDEX; 99 } 100 } 101 102 void _bcm_esw_regex_device_info_t_init(_bcm_esw_regex_device_info_t *info) 103 { 104 sal_memset(info, 0, sizeof(*info)); 105 } 106 107 /* 108 * Function: 109 * _regex_policy_action_name 110 * Purpose: 111 * Return text name of indicated action enum value. 112 */ 113 STATIC char *_regex_policy_action_name(bcm_field_action_t action) 114 { 115 /* Text names of Actions. These are used for debugging output and CLIs. 116 * Note that the order needs to match the bcm_field_action_t enum order. 117 */ 118 static char *action_text[] = BCM_FIELD_ACTION_STRINGS; 119 assert(COUNTOF(action_text) == bcmFieldActionCount); 120 121 return (action >= bcmFieldActionCount ? "??" : action_text[action]); 122 } 123 124 /* 125 * Function: 126 * _bcm_regex_policy_action_dest_check 127 * Purpose: 128 * Verify destination prameters for fp actions 129 * Parameters: 130 * unit - (IN) BCM device number 131 * fa - (IN) Field action structure. 132 * Returns: 133 * BCM_E_XXX 134 */ 135 int _bcm_regex_policy_action_dest_check(int unit, _regex_policy_action_t *pa) 136 { 137 int port_out; /* Calculated port value. */ 138 int modid_out; /* Calculated module id. */ 139 int rv; /* Operation return value. */ 140 141 /* Input parameters check. */ 142 if (NULL == pa) { 143 return (BCM_E_PARAM); 144 } 145 146 /* No checks for Mirror/Mpls/Mim/Wlan gports */ 147 if (BCM_GPORT_IS_SET(pa->param[1])) { 148 return (BCM_E_NONE); 149 } 150 151 /* Modport/Trunk were resolved in _field_params_api_to_hw_adapt call.*/ 152 if (bcmFieldActionRedirectTrunk == pa->action) { 153 return _bcm_trunk_id_validate(unit, pa->param[0]); 154 } 155 156 /* Check destination module id / port. */ 157 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 158 pa->param[0], pa->param[1], 159 &modid_out, &port_out); 160 BCM_IF_ERROR_RETURN(rv); 161 162 if (!SOC_MODID_ADDRESSABLE(unit, modid_out)) { 163 return (BCM_E_PARAM); 164 } 165 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 166 return (BCM_E_PORT); 167 } 168 return (BCM_E_NONE); 169 } 170 171 int bcm_esw_regex_config_set(int unit, bcm_regex_config_t *config) 172 { 173 _bcm_esw_regex_device_info_t *device; 174 175 if (!soc_feature(unit, soc_feature_regex)) { 176 return BCM_E_UNAVAIL; 177 } 178 179 if (NULL == config) { 180 return BCM_E_PARAM; 181 } 182 183 device = ESW_REGEX_INFO(unit); 184 if (NULL == device) { 185 return BCM_E_INIT; 186 } 187 188 device->flags = config->flags; 189 device->report_buffer_size = config->report_buffer_size; 190 191 #if defined(BCM_TRIUMPH3_SUPPORT) 192 if (SOC_IS_TRIUMPH3(unit)) { 193 return _bcm_tr3_regex_config_set(unit, config); 194 } 195 #endif /* BCM_TRIUMPH3_SUPPORT */ 196 197 return BCM_E_UNAVAIL; 198 } 199 200 int bcm_esw_regex_config_get(int unit, bcm_regex_config_t *config) 201 { 202 _bcm_esw_regex_device_info_t *device; 203 204 if (!soc_feature(unit, soc_feature_regex)) { 205 return BCM_E_UNAVAIL; 206 } 207 208 if (NULL == config) { 209 return BCM_E_PARAM; 210 } 211 212 device = ESW_REGEX_INFO(unit); 213 if (NULL == device) { 214 return BCM_E_INIT; 215 } 216 217 config->flags = device->flags; 218 config->report_buffer_size = device->report_buffer_size; 219 220 #if defined(BCM_TRIUMPH3_SUPPORT) 221 if (SOC_IS_TRIUMPH3(unit)) { 222 return _bcm_tr3_regex_config_get(unit, config); 223 } 224 #endif /* BCM_TRIUMPH3_SUPPORT */ 225 226 return BCM_E_UNAVAIL; 227 } 228 229 int bcm_esw_regex_exclude_add(int unit, uint8 protocol, 230 uint16 l4_start, uint16 l4_end) 231 { 232 if (!soc_feature(unit, soc_feature_regex)) { 233 return BCM_E_UNAVAIL; 234 } 235 236 #if defined(BCM_TRIUMPH3_SUPPORT) 237 if (SOC_IS_TRIUMPH3(unit)) { 238 return _bcm_tr3_regex_exclude_add(unit, protocol, l4_start, l4_end); 239 } 240 #endif /* BCM_TRIUMPH3_SUPPORT */ 241 242 return BCM_E_UNAVAIL; 243 } 244 245 int bcm_esw_regex_exclude_delete(int unit, uint8 protocol, 246 uint16 l4_start, uint16 l4_end) 247 { 248 if (!soc_feature(unit, soc_feature_regex)) { 249 return BCM_E_UNAVAIL; 250 } 251 252 #if defined(BCM_TRIUMPH3_SUPPORT) 253 if (SOC_IS_TRIUMPH3(unit)) { 254 return _bcm_tr3_regex_exclude_delete(unit, protocol, l4_start, l4_end); 255 } 256 #endif /* BCM_TRIUMPH3_SUPPORT */ 257 258 return BCM_E_UNAVAIL; 259 } 260 261 int bcm_esw_regex_exclude_delete_all(int unit) 262 { 263 if (!soc_feature(unit, soc_feature_regex)) { 264 return BCM_E_UNAVAIL; 265 } 266 267 #if defined(BCM_TRIUMPH3_SUPPORT) 268 if (SOC_IS_TRIUMPH3(unit)) { 269 return _bcm_tr3_regex_exclude_delete_all(unit); 270 } 271 #endif /* BCM_TRIUMPH3_SUPPORT */ 272 273 return BCM_E_UNAVAIL; 274 } 275 276 int bcm_esw_regex_exclude_get(int unit, int array_size, uint8 *protocol, 277 uint16 *l4low, uint16 *l4high, int *array_count) 278 { 279 if (!soc_feature(unit, soc_feature_regex)) { 280 return BCM_E_UNAVAIL; 281 } 282 283 if (!(array_size && protocol && l4low && l4high && array_count)) { 284 return BCM_E_PARAM; 285 } 286 287 #if defined(BCM_TRIUMPH3_SUPPORT) 288 if (SOC_IS_TRIUMPH3(unit)) { 289 return _bcm_tr3_regex_exclude_get(unit, array_size, protocol, 290 l4low, l4high, array_count); 291 } 292 #endif /* BCM_TRIUMPH3_SUPPORT */ 293 294 return BCM_E_UNAVAIL; 295 } 296 297 int bcm_esw_regex_engine_create(int unit, bcm_regex_engine_config_t *config, 298 bcm_regex_engine_t *engid) 299 { 300 if (!soc_feature(unit, soc_feature_regex)) { 301 return BCM_E_UNAVAIL; 302 } 303 304 #if defined(BCM_TRIUMPH3_SUPPORT) 305 if (SOC_IS_TRIUMPH3(unit)) { 306 return _bcm_tr3_regex_engine_create(unit, config, engid); 307 } 308 #endif /* BCM_TRIUMPH3_SUPPORT */ 309 310 return BCM_E_UNAVAIL; 311 } 312 313 int bcm_esw_regex_engine_destroy(int unit, bcm_regex_engine_t engid) 314 { 315 if (!soc_feature(unit, soc_feature_regex)) { 316 return BCM_E_UNAVAIL; 317 } 318 319 #if defined(BCM_TRIUMPH3_SUPPORT) 320 if (SOC_IS_TRIUMPH3(unit)) { 321 return _bcm_tr3_regex_engine_destroy(unit, engid); 322 } 323 #endif /* BCM_TRIUMPH3_SUPPORT */ 324 325 return BCM_E_UNAVAIL; 326 } 327 328 int bcm_esw_regex_engine_traverse(int unit, bcm_regex_engine_traverse_cb cb, 329 void *user_data) 330 { 331 if (!soc_feature(unit, soc_feature_regex)) { 332 return BCM_E_UNAVAIL; 333 } 334 335 #if defined(BCM_TRIUMPH3_SUPPORT) 336 if (SOC_IS_TRIUMPH3(unit)) { 337 return _bcm_tr3_regex_engine_traverse(unit, cb, user_data); 338 } 339 #endif /* BCM_TRIUMPH3_SUPPORT */ 340 341 return BCM_E_UNAVAIL; 342 } 343 344 int bcm_esw_regex_engine_get(int unit, bcm_regex_engine_t engid, 345 bcm_regex_engine_config_t *config) 346 { 347 if (!soc_feature(unit, soc_feature_regex)) { 348 return BCM_E_UNAVAIL; 349 } 350 351 #if defined(BCM_TRIUMPH3_SUPPORT) 352 if (SOC_IS_TRIUMPH3(unit)) { 353 return _bcm_tr3_regex_engine_get(unit, engid, config); 354 } 355 #endif /* BCM_TRIUMPH3_SUPPORT */ 356 357 return BCM_E_UNAVAIL; 358 } 359 360 int bcm_esw_regex_match_check(int unit, bcm_regex_match_t* match, 361 int count, int* metric) 362 { 363 if (!soc_feature(unit, soc_feature_regex)) { 364 return BCM_E_UNAVAIL; 365 } 366 367 #if defined(BCM_TRIUMPH3_SUPPORT) 368 if (SOC_IS_TRIUMPH3(unit)) { 369 return _bcm_tr3_regex_match_check(unit, match, count, metric); 370 371 } 372 #endif /* BCM_TRIUMPH3_SUPPORT */ 373 374 return BCM_E_UNAVAIL; 375 } 376 377 int _regex_policy_get(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p); 378 379 int bcm_esw_regex_match_set(int unit, bcm_regex_engine_t engid, 380 bcm_regex_match_t* match, int count) 381 { 382 _bcm_esw_regex_device_info_t *device; 383 384 #if defined(BCM_TRIUMPH3_SUPPORT) 385 int i, rv; 386 _regex_policy_t *p_policy; 387 #endif 388 389 if (!soc_feature(unit, soc_feature_regex)) { 390 return BCM_E_UNAVAIL; 391 } 392 393 device = ESW_REGEX_INFO(unit); 394 if (NULL == device) { 395 return BCM_E_INIT; 396 } 397 398 #if defined(BCM_TRIUMPH3_SUPPORT) 399 if (SOC_IS_TRIUMPH3(unit)) { 400 if (count > 0) { 401 for (i = 0; i < count; i++) { 402 if (match[i].action_flags & BCM_REGEX_MATCH_ACTION_NON_POLICY_ACTIONS) { 403 if (0 != (device->flags & BCM_REGEX_USE_POLICY_ID)) { 404 return BCM_E_PARAM; 405 } 406 if (match[i].policy_id != -1) { 407 return BCM_E_PARAM; 408 } 409 } 410 else 411 { 412 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 413 return BCM_E_PARAM; 414 } 415 if (match[i].policy_id == -1) { 416 return BCM_E_PARAM; 417 } 418 rv = _regex_policy_get(unit, match[i].policy_id, &p_policy); 419 BCM_IF_ERROR_RETURN(rv); 420 421 if ((p_policy->flags & _REGEX_POLICY_INSTALLED) == 0) { 422 return BCM_E_PARAM; 423 } 424 } 425 } 426 } 427 428 return _bcm_tr3_regex_match_set(unit, engid, match, count); 429 } 430 #endif /* BCM_TRIUMPH3_SUPPORT */ 431 432 return BCM_E_UNAVAIL; 433 } 434 435 436 int bcm_esw_regex_get_match_id(int unit, int signature_id, int *match_id) 437 { 438 if (!soc_feature(unit, soc_feature_regex)) { 439 return BCM_E_UNAVAIL; 440 } 441 442 #if defined(BCM_TRIUMPH3_SUPPORT) 443 if (SOC_IS_TRIUMPH3(unit)) { 444 return _bcm_tr3_get_match_id(unit, signature_id, match_id); 445 } 446 #endif /* BCM_TRIUMPH3_SUPPORT */ 447 448 return BCM_E_UNAVAIL; 449 } 450 451 452 int bcm_esw_regex_get_sig_id(int unit, int match_id, int *signature_id) 453 { 454 if (!soc_feature(unit, soc_feature_regex)) { 455 return BCM_E_UNAVAIL; 456 } 457 458 #if defined(BCM_TRIUMPH3_SUPPORT) 459 if (SOC_IS_TRIUMPH3(unit)) { 460 return _bcm_tr3_get_sig_id(unit, match_id, signature_id); 461 } 462 #endif /* BCM_TRIUMPH3_SUPPORT */ 463 464 return BCM_E_UNAVAIL; 465 } 466 467 #define BCM_REGEX_NUM_SLOT_PER_CPS 16 468 469 typedef struct _bcm_regex_cps_obj_pub_s { 470 uint32 flags; 471 int foff; 472 int alloc_map[BCM_REGEX_NUM_SLOT_PER_CPS]; 473 int refcnt[BCM_REGEX_NUM_SLOT_PER_CPS]; 474 int from_line; 475 int req_lsz; 476 } _bcm_regex_cps_obj_pub_t; 477 478 int bcm_esw_regex_engine_info_get(int unit, int engine_id, 479 bcm_regex_engine_info_t *engine_info) 480 { 481 if (!soc_feature(unit, soc_feature_regex)) { 482 return BCM_E_UNAVAIL; 483 } 484 485 #if defined(BCM_TRIUMPH3_SUPPORT) 486 if (SOC_IS_TRIUMPH3(unit)) { 487 return _bcm_tr3_get_engine_size_info(unit, engine_id, engine_info); 488 } 489 #endif /* BCM_TRIUMPH3_SUPPORT */ 490 491 return BCM_E_UNAVAIL; 492 } 493 494 495 int bcm_esw_regex_info_get(int unit, bcm_regex_info_t *regex_info) 496 { 497 #if defined(BCM_TRIUMPH3_SUPPORT) 498 _bcm_esw_regex_device_info_t *device; 499 #endif 500 501 if (!soc_feature(unit, soc_feature_regex)) { 502 return BCM_E_UNAVAIL; 503 } 504 505 #if defined(BCM_TRIUMPH3_SUPPORT) 506 if (SOC_IS_TRIUMPH3(unit)) { 507 /* 508 Assume we are using the new policy tables. If not, 509 these values will be overwritten by the old values. 510 */ 511 regex_info->policy_size = ESW_REGEX_POLICIES_MAX(unit) + 1; 512 device = ESW_REGEX_INFO(unit); 513 regex_info->policy_free_size = regex_info->policy_size - device->num_policies; 514 515 return _bcm_tr3_regex_info_get(unit, regex_info); 516 } 517 #endif /* BCM_TRIUMPH3_SUPPORT */ 518 519 return BCM_E_UNAVAIL; 520 } 521 522 523 int bcm_esw_regex_report_register(int unit, uint32 reports, 524 bcm_regex_report_cb callback, void *user_data) 525 { 526 if (!soc_feature(unit, soc_feature_regex)) { 527 return BCM_E_UNAVAIL; 528 } 529 530 #if defined(BCM_TRIUMPH3_SUPPORT) 531 if (SOC_IS_TRIUMPH3(unit)) { 532 return _bcm_esw_regex_report_register(unit, reports, 533 callback, user_data); 534 } 535 #endif /* BCM_TRIUMPH3_SUPPORT */ 536 537 return BCM_E_UNAVAIL; 538 } 539 540 int bcm_esw_regex_stat_get(int unit, bcm_regex_stat_t type, uint64 *val) 541 { 542 if (!soc_feature(unit, soc_feature_regex)) { 543 return BCM_E_UNAVAIL; 544 } 545 546 #if defined(BCM_TRIUMPH3_SUPPORT) 547 if (SOC_IS_TRIUMPH3(unit)) { 548 return _bcm_tr3_regex_stat_get(unit, type, val); 549 } 550 #endif /* BCM_TRIUMPH3_SUPPORT */ 551 552 return BCM_E_UNAVAIL; 553 } 554 555 int bcm_esw_regex_stat_set(int unit, bcm_regex_stat_t type, uint64 val) 556 { 557 if (!soc_feature(unit, soc_feature_regex)) { 558 return BCM_E_UNAVAIL; 559 } 560 561 #if defined(BCM_TRIUMPH3_SUPPORT) 562 if (SOC_IS_TRIUMPH3(unit)) { 563 return _bcm_tr3_regex_stat_set(unit, type, val); 564 } 565 #endif /* BCM_TRIUMPH3_SUPPORT */ 566 567 return BCM_E_UNAVAIL; 568 } 569 570 int bcm_esw_regex_report_unregister(int unit, uint32 reports, 571 bcm_regex_report_cb callback, void *user_data) 572 { 573 if (!soc_feature(unit, soc_feature_regex)) { 574 return BCM_E_UNAVAIL; 575 } 576 577 #if defined(BCM_TRIUMPH3_SUPPORT) 578 if (SOC_IS_TRIUMPH3(unit)) { 579 return _bcm_esw_regex_report_unregister(unit, reports, 580 callback, user_data); 581 } 582 #endif /* BCM_TRIUMPH3_SUPPORT */ 583 584 return BCM_E_UNAVAIL; 585 } 586 587 int bcm_esw_regex_init(int unit) 588 { 589 int rv = BCM_E_UNAVAIL; 590 _bcm_esw_regex_device_info_t *info; 591 _field_stage_t *field_stage; 592 593 if (!soc_feature(unit, soc_feature_regex)) { 594 return BCM_E_UNAVAIL; 595 } 596 597 last_allocated_policy = 0; 598 /* Init regex info. */ 599 info = ESW_REGEX_INFO(unit); 600 if (NULL == info) { 601 info = sal_alloc(sizeof(*info), "_regex_info"); 602 if (NULL == info) { 603 return BCM_E_MEMORY; 604 } 605 ESW_REGEX_INFO(unit) = info; 606 _bcm_esw_regex_device_info_t_init(info); 607 } 608 609 #if defined(BCM_TRIUMPH3_SUPPORT) 610 if (SOC_IS_TRIUMPH3(unit)) { 611 rv = _bcm_tr3_regex_init(unit, &info->functions); 612 } 613 #endif 614 if (BCM_FAILURE(rv)) { 615 return rv; 616 } 617 618 info->regex_esw_mutex = sal_mutex_create("regex_esw_mutex"); 619 620 info->policy_index_min = info->functions->policy_index_min_get(unit); 621 info->policy_index_max = info->functions->policy_index_max_get(unit); 622 623 /* The last meter pool is reserved for use by the regex component so the Field 624 * Processor will only have (total pools - 1). Calculate the starting HW index of the 625 * last pool and ensure that it is valid. */ 626 BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &field_stage)); 627 info->meter_base_hw_index = field_stage->num_meter_pools * field_stage->meter_pool[_FP_DEF_INST][0]->pool_size; 628 info->meter_pool = field_stage->num_meter_pools; 629 assert(soc_mem_index_count(unit, FP_METER_TABLEm) > info->meter_base_hw_index); 630 631 /* 632 * Initialize default policy (which does nothing): 633 * _bcm_tr3_regex_init creates a empty policy entry 0 (by calling legacy function 634 * _bcm_tr3_install_action_policy). Initialize the policy 0 data here. 635 */ 636 _regex_policy_create_id(unit, _REGEX_DEFAULT_POLICY_ID); 637 _regex_policy_install(unit, _REGEX_DEFAULT_POLICY_ID); 638 639 return BCM_E_NONE; 640 } 641 642 int _bcm_esw_regex_sync(int unit) 643 { 644 #ifdef BCM_WARM_BOOT_SUPPORT 645 #if defined(BCM_TRIUMPH3_SUPPORT) 646 if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_regex)) { 647 return _bcm_esw_tr3_regex_sync(unit); 648 } 649 #endif 650 #endif 651 return BCM_E_UNAVAIL; 652 } 653 654 /* 655 * Function: 656 * _regex_policy_dirty 657 * Purpose: 658 * Check if policy was modified after last installation 659 * Parameters: 660 * unit - (IN) BCM device number. 661 * p_ent - (IN) Regex policy pointer. 662 * dirty - (OUT) Entry dirty flag. 663 * Returns: 664 * BCM_E_XXX 665 */ 666 int _regex_policy_dirty(int unit, _regex_policy_t *p_ent, int *dirty) 667 { 668 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 669 _field_policer_t *f_pl; /* Field policer descriptor. */ 670 int rv; /* Operation return status. */ 671 int idx; 672 673 /* Input parameters check. */ 674 if ((NULL == p_ent) || (NULL == dirty)) { 675 return (BCM_E_PARAM); 676 } 677 678 *dirty = (p_ent->flags & _REGEX_POLICY_DIRTY) ? TRUE : FALSE; 679 680 if (0 == (*dirty)) { 681 /* Policer configuration updates check. */ 682 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 683 f_ent_pl = p_ent->policer + idx; 684 /* Skip invalid policers. */ 685 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 686 continue; 687 } 688 /* Read policer configuration.*/ 689 rv = _bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl); 690 BCM_IF_ERROR_RETURN(rv); 691 692 /* Check if policer was modified. */ 693 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 694 *dirty = TRUE; 695 break; 696 } 697 } 698 } 699 700 return (BCM_E_NONE); 701 } 702 703 /* 704 * Function: 705 * _regex_policy_t_compare 706 * Purpose: 707 * Compare entry id in _regex_policy_t structure. 708 * Parameters: 709 * b - (IN) first compared qualifier. 710 * a - (IN) second compared qualifier. 711 * Returns: 712 * a<=>b 713 */ 714 STATIC int _regex_policy_t_compare(void *a, void *b) 715 { 716 _regex_policy_t **first; /* First compared entry. */ 717 _regex_policy_t **second; /* Second compared entry. */ 718 719 first = (_regex_policy_t **)a; 720 second = (_regex_policy_t **)b; 721 722 if ((*first)->eid < (*second)->eid) { 723 return (-1); 724 } else if ((*first)->eid > (*second)->eid) { 725 return (1); 726 } 727 return (0); 728 } 729 730 /* 731 * Function: 732 * _regex_policy_get 733 * Purpose: 734 * Lookup a policy (entry) from a unit ID and policy id choice. 735 * Parmeters: 736 * unit - (IN) BCM device number. 737 * policy - (IN) Policy id. 738 * policy_p - (OUT) Entry lookup result. 739 * Returns: 740 * BCM_E_XXX 741 */ 742 int _regex_policy_get(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p) 743 { 744 _regex_policy_t target; /* Entry lookup pointer. */ 745 _regex_policy_t *p_ent; /* Entry lookup pointer. */ 746 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 747 int idx; /* Entry index. */ 748 749 /* Reset target entry */ 750 target.eid = policy; 751 p_ent = ⌖ 752 753 device = ESW_REGEX_INFO(unit); 754 if (NULL == device) { 755 return BCM_E_INIT; 756 } 757 758 if (NULL == device->policies) { 759 return (BCM_E_NOT_FOUND); 760 } 761 762 ESW_REGEX_LOCK(unit); 763 764 idx = _shr_bsearch(device->policies, device->num_policies, 765 sizeof(device->policies[0]), &p_ent, 766 _regex_policy_t_compare); 767 ESW_REGEX_UNLOCK(unit); 768 769 if (idx >= 0) { 770 if (NULL != policy_p) { 771 *policy_p = device->policies[idx]; 772 } 773 return (BCM_E_NONE); 774 } 775 776 /* Rule with id == eid not found. */ 777 return (BCM_E_NOT_FOUND); 778 } 779 780 /* 781 * Function: 782 * _regex_policy_add 783 * Purpose: 784 * Insert an entry to info entry array. 785 * Parmeters: 786 * unit - (IN) BCM device number. 787 * policy - (IN) Policy entry. 788 * Returns: 789 * BCM_E_XXX 790 */ 791 int _regex_policy_add(int unit, _regex_policy_t *policy) 792 { 793 int idx; /* Entry insertion index. */ 794 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 795 _regex_policy_t **policy_array; 796 797 /* Input parameters check */ 798 if (NULL == policy) { 799 return (BCM_E_PARAM); 800 } 801 802 device = ESW_REGEX_INFO(unit); 803 if (NULL == device) { 804 return BCM_E_INIT; 805 } 806 807 /* Verify if entry already present in the group . */ 808 if (BCM_E_NONE == _regex_policy_get(unit, policy->eid, NULL)) { 809 /* Entry already IN. */ 810 return (BCM_E_NONE); 811 } 812 813 /* Check if group has enough room for new entry */ 814 if (ESW_REGEX_POLICIES_MAX(unit) > device->num_policies) { 815 816 policy_array = sal_alloc(sizeof(policy_array[0]) * (device->num_policies + 1), "regex_policy_array"); 817 if (NULL == policy_array) { 818 return (BCM_E_MEMORY); 819 } 820 821 /* Copy original array to newly allocated one. */ 822 if (NULL != device->policies) { 823 sal_memcpy(policy_array, device->policies, sizeof(policy_array[0]) * device->num_policies); 824 sal_free(device->policies); 825 } 826 827 device->policies = policy_array; 828 device->num_policies++; 829 } else { 830 return (BCM_E_RESOURCE); 831 } 832 833 /* Insert entry in sorted order. Note that if the loop breaks, idx will be one less 834 * than the index at which to add the new policy. If the loop runs to completion, idx 835 * will be -1 so the new entry will be inserted at entry 0 (idx + 1) which is 836 * appropriate since the new entry is less than all the other entries. */ 837 idx = device->num_policies - 2; 838 if (idx >= 0) { 839 do { 840 if (_regex_policy_t_compare(&device->policies[idx], &policy) < 0) { 841 break; 842 } 843 844 device->policies[idx + 1] = device->policies[idx]; 845 idx--; 846 } while (idx >= 0); 847 device->policies[idx + 1] = policy; 848 } else { 849 device->policies[0] = policy; 850 } 851 852 return (BCM_E_NONE); 853 } 854 855 /* 856 * Function: 857 * _regex_policy_delete 858 * Purpose: 859 * Remove an entry from field group entry array. 860 * Parmeters: 861 * unit - (IN)BCM device number. 862 * fg - (IN)Field group structure. 863 * f_ent - (IN)Removed entry structure. 864 * Returns: 865 * BCM_E_XXX 866 */ 867 STATIC int _regex_policy_delete(int unit, _regex_policy_t *policy) 868 { 869 int idx; /* Entry insertion index. */ 870 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 871 872 /* Input parameters check */ 873 if (NULL == policy) { 874 return (BCM_E_PARAM); 875 } 876 877 device = ESW_REGEX_INFO(unit); 878 if (NULL == device) { 879 return BCM_E_INIT; 880 } 881 882 /* Make sure policy array was not deallocated. */ 883 if (NULL == device->policies) { 884 return (BCM_E_INTERNAL); 885 } 886 887 /* Verify if entry already present in the group . */ 888 ESW_REGEX_LOCK(unit); 889 idx = _shr_bsearch(device->policies, device->num_policies, 890 sizeof(device->policies[0]), &policy, 891 _regex_policy_t_compare); 892 if (idx < 0) { 893 ESW_REGEX_UNLOCK(unit); 894 return (BCM_E_NOT_FOUND); 895 } 896 897 if (device->num_policies <= 1) { 898 sal_free(device->policies); 899 device->policies = NULL; 900 device->num_policies = 0; 901 } else { 902 /* Make room for inserted entry */ 903 while (idx < device->num_policies - 1) { 904 device->policies[idx] = device->policies[idx + 1]; 905 idx++; 906 } 907 device->num_policies--; 908 device->policies[device->num_policies] = NULL; 909 } 910 911 ESW_REGEX_UNLOCK(unit); 912 913 return (BCM_E_NONE); 914 } 915 916 /* 917 * Function: _regex_policy_params_hw_to_api_adapt 918 * 919 * Purpose: 920 * Adapts action parameters from HW to API space. 921 * 922 * Parameters: 923 * unit - (IN) BCM device number 924 * action - (IN)Action to adapt parameters for (bcmFieldActionXXX) 925 * param0 - (IN/OUT)Action parameter 926 * param1 - (IN/OUT)Action parameter 927 * 928 * Returns: 929 * BCM_E_NONE - No errors. 930 * BCM_E_XXX - Otherwise. 931 */ 932 STATIC int _regex_policy_params_hw_to_api_adapt(int unit, bcm_field_action_t action, 933 uint32 *param0, uint32 *param1) 934 { 935 int isGport; 936 _bcm_gport_dest_t dest; 937 938 _bcm_gport_dest_t_init(&dest); 939 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 940 941 switch (action) { 942 case bcmFieldActionRedirect: 943 if (isGport) { 944 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 945 dest.modid = *param0; 946 dest.port = *param1; 947 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, (bcm_gport_t *)param1)); 948 *param0 = -1; /* If gport requested param0 should be ignored */ 949 } 950 break; 951 case bcmFieldActionRedirectTrunk: 952 if (isGport) { 953 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 954 dest.tgid = *param0; 955 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, (bcm_gport_t *)param0)); 956 *param1 = -1; /* If gport requested param1 should be ignored */ 957 } 958 break; 959 default: 960 break; 961 } 962 return (BCM_E_NONE); 963 } 964 965 /* 966 * Function: _regex_policy_params_api_to_hw_adapt 967 * 968 * Purpose: 969 * Adapts action parameters from API to HW space. 970 * 971 * Parameters: 972 * unit - (IN) BCM device number 973 * action - (IN)Action to adapt parameters for (bcmFieldActionXXX) 974 * param0 - (IN/OUT)Action parameter 975 * param1 - (IN/OUT)Action parameter 976 * 977 * Returns: 978 * BCM_E_NONE - No errors. 979 * BCM_E_XXX - Otherwise. 980 */ 981 STATIC int _regex_policy_params_api_to_hw_adapt(int unit, bcm_field_action_t action, 982 uint32 *param0, uint32 *param1) 983 { 984 bcm_module_t l_modid; 985 bcm_trunk_t l_tgid; 986 bcm_port_t l_port; 987 int id; 988 989 switch (action) { 990 case bcmFieldActionRedirect: 991 if (BCM_GPORT_IS_SET(*param1)) { 992 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, *param1, &l_modid, &l_port, &l_tgid, &id)); 993 /* Do not modify param0 and param1 if id != -1 */ 994 if (-1 == id) { 995 if (BCM_TRUNK_INVALID != l_tgid) { 996 return BCM_E_PARAM; 997 } 998 *param1 = l_port; 999 *param0 = l_modid; 1000 } 1001 } 1002 break; 1003 case bcmFieldActionRedirectTrunk: 1004 if (BCM_GPORT_IS_SET(*param0)) { 1005 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, *param0, &l_modid, &l_port, &l_tgid, &id)); 1006 if ((-1 != id) || (BCM_TRUNK_INVALID == l_tgid) ){ 1007 return BCM_E_PARAM; 1008 } 1009 *param0 = l_tgid; 1010 *param1 = -1; /* if param0 is trunk, param1 ignored */ 1011 } 1012 break; 1013 default: 1014 break; 1015 } 1016 1017 return (BCM_E_NONE); 1018 } 1019 1020 /* 1021 * Function: 1022 * _regex_policy_phys_create 1023 * Purpose: 1024 * Initialize a physical policy structure. 1025 * Parameters: 1026 * unit - (IN) BCM device number. 1027 * policy - (IN) Policy id. 1028 * policy_p - (OUT)Allocated & initialized entry. 1029 * Returns 1030 * BCM_E_XXX 1031 */ 1032 STATIC int _regex_policy_phys_create(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p) 1033 { 1034 int rv; /* Operation return status. */ 1035 _regex_policy_t *policy_ent; /* Field entry structure. */ 1036 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 1037 1038 LOG_DEBUG(BSL_LS_BCM_REGEX, 1039 (BSL_META_U(unit, 1040 "FT(unit %d) vverb: BEGIN %s(policy=%d)\n"), 1041 unit, FUNCTION_NAME(), policy)); 1042 1043 if (NULL == policy_p) { 1044 return (BCM_E_PARAM); 1045 } 1046 1047 /* Get the device info structure. */ 1048 device = ESW_REGEX_INFO(unit); 1049 if (NULL == device) { 1050 return BCM_E_INIT; 1051 } 1052 1053 /* Check if free entries are available in the slice. */ 1054 if (device->num_policies >= ESW_REGEX_POLICIES_MAX(unit)) { 1055 LOG_ERROR(BSL_LS_BCM_REGEX, 1056 (BSL_META_U(unit, 1057 "FT(unit %d) Error: No room.\n"), 1058 unit)); 1059 return (BCM_E_RESOURCE); 1060 } 1061 1062 policy_ent = sal_alloc(sizeof(*policy_ent), "regex_policy"); 1063 if (policy_ent == NULL) { 1064 LOG_ERROR(BSL_LS_BCM_REGEX, 1065 (BSL_META_U(unit, 1066 "FT(unit %d) Error: allocation failure for policy_entry\n"), 1067 unit)); 1068 return (BCM_E_MEMORY); 1069 } 1070 1071 _bcm_esw_regex_policy_t_init(policy_ent); 1072 1073 /* Fill in entry primitives. */ 1074 policy_ent->eid = policy; 1075 1076 #if 0 1077 /* Do we want to have a default setting for the FT? */ 1078 1079 /* Enable color independent actions based on field control. */ 1080 if (fc->flags & _FP_COLOR_INDEPENDENT) { 1081 policy_ent->flags |= _REGEX_POLICY_COLOR_INDEPENDENT; 1082 } 1083 #endif 1084 1085 /* Mark entry dirty. */ 1086 policy_ent->flags |= _REGEX_POLICY_DIRTY; 1087 1088 /* Insert the entry into group entry array. */ 1089 rv = _regex_policy_add(unit, policy_ent); 1090 if (BCM_FAILURE(rv)) { 1091 sal_free(policy_ent); 1092 return (rv); 1093 } 1094 1095 /* Return allocated/filled entry structure to the caller. */ 1096 *policy_p = policy_ent; 1097 return (BCM_E_NONE); 1098 } 1099 1100 /* 1101 * Function: 1102 * _regex_policy_phys_destroy 1103 * 1104 * Purpose: 1105 * Destroy a physical policy. Note that this does not remove 1106 * the policy from the hardware. 1107 * 1108 * Parameters: 1109 * unit - BCM device number 1110 * policy - Policy ID to remove 1111 * 1112 * Returns: 1113 * BCM_E_NONE - Success 1114 */ 1115 STATIC int _regex_policy_phys_destroy(int unit, _regex_policy_t *p_ent) 1116 { 1117 int rv; /* Operation return status. */ 1118 1119 if (NULL == p_ent) { 1120 return (BCM_E_PARAM); 1121 } 1122 1123 /* Remove the entry from group entry array. */ 1124 rv = _regex_policy_delete(unit, p_ent); 1125 sal_free(p_ent); 1126 return (rv); 1127 } 1128 1129 /* 1130 * Function: 1131 * _regex_policy_mirror_dest_delete 1132 * Purpose: 1133 * Unset mirroring destination & disable mirroring for rule matching 1134 * packets. 1135 * Parameters: 1136 * unit - (IN) BCM device number 1137 * fa - (IN) Field action descriptor. 1138 * Returns: 1139 * BCM_E_XXX 1140 */ 1141 STATIC int _regex_policy_mirror_dest_delete(int unit, _regex_policy_t *p_ent, 1142 _regex_policy_action_t *pa, uint32 flags) 1143 { 1144 uint32 mirror_flags; /* Mirror module flags. */ 1145 int rv; 1146 1147 /* Input parameters check */ 1148 if ((NULL == pa) || (NULL == p_ent)) { 1149 return (BCM_E_PARAM); 1150 } 1151 1152 /* Set mirror flags. */ 1153 if (bcmFieldActionMirrorIngress == pa->action) { 1154 mirror_flags = BCM_MIRROR_PORT_INGRESS; 1155 } else if (bcmFieldActionMirrorEgress == pa->action) { 1156 /* Stage Ingress */ 1157 mirror_flags = BCM_MIRROR_PORT_EGRESS; 1158 } else { 1159 return (BCM_E_PARAM); 1160 } 1161 1162 if ((flags & _REGEX_ACTION_RESOURCE_FREE) && 1163 (_REGEX_INVALID_INDEX != pa->hw_index)) { 1164 rv = _bcm_esw_mirror_fp_dest_delete(unit, pa->hw_index, mirror_flags); 1165 BCM_IF_ERROR_RETURN(rv); 1166 pa->hw_index = _REGEX_INVALID_INDEX; 1167 } 1168 1169 if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) && 1170 (_REGEX_INVALID_INDEX != pa->old_index)) { 1171 rv = _bcm_esw_mirror_fp_dest_delete(unit, pa->old_index, mirror_flags); 1172 BCM_IF_ERROR_RETURN(rv); 1173 pa->old_index = _REGEX_INVALID_INDEX; 1174 } 1175 return (BCM_E_NONE); 1176 } 1177 1178 /* 1179 * Function: 1180 * _regex_policy_mirror_dest_add 1181 * Purpose: 1182 * Set mirroring destination & enable mirroring for rule matching 1183 * packets. 1184 * Parameters: 1185 * unit - (IN) BCM device number 1186 * fa - (IN) field action 1187 * Returns: 1188 * BCM_E_XXX 1189 */ 1190 STATIC int _regex_policy_mirror_dest_add(int unit, _regex_policy_t *p_ent, 1191 _regex_policy_action_t *pa) 1192 { 1193 uint32 mirror_flags; /* Mirror module flags. */ 1194 1195 /* Input parameters check. */ 1196 if ((NULL == pa) || (NULL == p_ent)) { 1197 return (BCM_E_PARAM); 1198 } 1199 1200 /* Set mirror flags. */ 1201 if (bcmFieldActionMirrorIngress == pa->action) { 1202 mirror_flags = BCM_MIRROR_PORT_INGRESS; 1203 } else if (bcmFieldActionMirrorEgress == pa->action) { 1204 /* Stage Ingress */ 1205 mirror_flags = BCM_MIRROR_PORT_EGRESS; 1206 } else { 1207 return (BCM_E_PARAM); 1208 } 1209 1210 return _bcm_esw_mirror_fp_dest_add(unit, pa->param[0], pa->param[1], 1211 mirror_flags, &pa->hw_index); 1212 } 1213 1214 #if defined(INCLUDE_L3) 1215 /* 1216 * Function: 1217 * _bcm_regex_policy_set_l3_nh_resolve 1218 * Purpose: 1219 * Install l3 forwarding policy entry. 1220 * Parameters: 1221 * unit - (IN) BCM device number 1222 * value - (IN) Egress object id or combined next hop information. 1223 * Returns: 1224 * BCM_E_XXX 1225 */ 1226 int _bcm_regex_policy_set_l3_nh_resolve(int unit, int value, 1227 uint32 *flags, int *nh_ecmp_id) 1228 { 1229 int rv; /* Operation return value. */ 1230 1231 /* Check if egress forwarding mode is enabled. */ 1232 rv = bcm_xgs3_l3_egress_id_parse(unit, value, flags, nh_ecmp_id); 1233 if (rv == BCM_E_DISABLED) { 1234 if (_REGEX_L3_ACTION_UNPACK_ECMP_MODE((value))) { 1235 *flags = BCM_L3_MULTIPATH; 1236 *nh_ecmp_id = _REGEX_L3_ACTION_UNPACK_ECMP_PTR((value)); 1237 } else { 1238 *flags = 0; 1239 *nh_ecmp_id = _REGEX_L3_ACTION_UNPACK_NEXT_HOP((value)); 1240 } 1241 rv = BCM_E_NONE; 1242 } 1243 return (rv); 1244 } 1245 1246 /* 1247 * Function: 1248 * _regex_policy_l2_actions_nh_destroy 1249 * 1250 * Purpose: 1251 * Free l3 next hop and egress interface for 1252 * l2 fields update action. 1253 * Parameters: 1254 * unit - (IN) BCM device number. 1255 * nh_index - (IN) Next hop index. 1256 * egr_intf_set - (IN) Egress interface allocated. 1257 * Returns: 1258 * BCM_E_XXX 1259 */ 1260 STATIC int _regex_policy_l2_actions_nh_destroy(int unit, int nh_index, int egr_intf_set) 1261 { 1262 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry buffer. */ 1263 bcm_l3_egress_t egr; /* Egress forwarding object. */ 1264 uint32 intf; /* Egress L3 interface id. */ 1265 1266 /* Initialization. */ 1267 bcm_l3_egress_t_init(&egr); 1268 1269 /* Read next hop. */ 1270 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1271 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ANY, 1272 nh_index, hw_buf)); 1273 1274 /* clear egress interface information + free interface resource */ 1275 if (1 == egr_intf_set) { 1276 /* Get interface id. */ 1277 intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, hw_buf, INTF_NUMf); 1278 /* Reset interface entry in hw. */ 1279 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1280 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 1281 intf, hw_buf)); 1282 /* Free interface id. */ 1283 BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_free(unit, intf)); 1284 } 1285 1286 /* clear egress next hop table information + free next hop index */ 1287 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1288 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1289 SOC_BLOCK_ALL, nh_index, hw_buf)); 1290 1291 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_index)); 1292 return (BCM_E_NONE); 1293 } 1294 1295 /* 1296 * Function: 1297 * _regex_policy_l2_actions_nh_create 1298 * 1299 * Purpose: 1300 * Free l3 next hop and egress interface for 1301 * l2 fields update action. 1302 * Parameters: 1303 * unit - (IN) BCM device number. 1304 * da_pa - (IN) Update destination mac action. 1305 * sa_pa - (IN) Update source mac action. 1306 * vid_pa - (IN) Update outer vid action. 1307 * vn_new_pa - (IN) Change VN tag action. 1308 * vn_del_pa - (IN) Delete VN tag action. 1309 * Returns: 1310 * BCM_E_XXX 1311 */ 1312 STATIC int _regex_policy_l2_actions_nh_create(int unit, 1313 _regex_policy_action_t *da_pa, 1314 _regex_policy_action_t *sa_pa, 1315 _regex_policy_action_t *vid_pa, 1316 _regex_policy_action_t *vn_new_pa, 1317 _regex_policy_action_t *vn_del_pa) 1318 { 1319 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry buffer. */ 1320 bcm_l3_egress_t egr; /* Egress forwarding object. */ 1321 _bcm_l3_intf_cfg_t intf; /* Egress L3 interface id. */ 1322 int nh_index; /* Next hop index. */ 1323 int nh_flags = 0; /* Next hop flags. */ 1324 int rv = BCM_E_NONE; /* Operation return status. */ 1325 1326 /* Initialization. */ 1327 bcm_l3_egress_t_init(&egr); 1328 sal_memset(&intf, 0, sizeof(_bcm_l3_intf_cfg_t)); 1329 1330 /* Extract the policy info from the entry structure. */ 1331 if (NULL != da_pa) { 1332 SAL_MAC_ADDR_FROM_UINT32(egr.mac_addr, da_pa->param); 1333 } 1334 1335 if (NULL != sa_pa) { 1336 SAL_MAC_ADDR_FROM_UINT32(intf.l3i_mac_addr, sa_pa->param); 1337 } 1338 1339 if (NULL != vid_pa) { 1340 intf.l3i_vid = vid_pa->param[0]; 1341 } 1342 1343 /* Create egress l3 interface. */ 1344 BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit, &intf)); 1345 1346 /* Write egress interface to the hw. */ 1347 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1348 1349 /* Set mac address. */ 1350 soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf, 1351 MAC_ADDRESSf, intf.l3i_mac_addr); 1352 1353 /* Set vlan id. */ 1354 soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid); 1355 1356 /* Write interface configuration to the HW. */ 1357 rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 1358 intf.l3i_index, hw_buf); 1359 if (BCM_FAILURE(rv)) { 1360 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 1361 return rv; 1362 } 1363 1364 /* Allocate next hop entry. */ 1365 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 1366 rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index); 1367 if (BCM_FAILURE(rv)) { 1368 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1369 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 1370 intf.l3i_index, hw_buf); 1371 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 1372 return (rv); 1373 } 1374 1375 /* Write egress next hop entry. */ 1376 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1377 1378 /* Set next hop mac address. */ 1379 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1380 MAC_ADDRESSf, egr.mac_addr); 1381 1382 /* Set interface id. */ 1383 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1384 INTF_NUMf, intf.l3i_index); 1385 1386 /* Set Disable flags. */ 1387 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1388 L3__L3_UC_TTL_DISABLEf, 0x1); 1389 1390 if (NULL == vid_pa) { 1391 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1392 L3__L3_UC_VLAN_DISABLEf, 0x1); 1393 } 1394 1395 if (NULL == sa_pa) { 1396 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1397 L3__L3_UC_SA_DISABLEf, 0x1); 1398 } 1399 1400 if (NULL == da_pa) { 1401 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf, 1402 L3__L3_UC_DA_DISABLEf, 0x1); 1403 } 1404 1405 if (SOC_IS_TRIUMPH3(unit)) { 1406 soc_mem_field32_set(unit, 1407 EGR_L3_NEXT_HOPm, 1408 hw_buf, 1409 ENTRY_TYPEf, 1410 6); 1411 } 1412 1413 1414 /* Insert next hop information. */ 1415 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL, 1416 nh_index, hw_buf); 1417 if (BCM_FAILURE(rv)) { 1418 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 1419 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL, 1420 intf.l3i_index, hw_buf); 1421 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index); 1422 return (rv); 1423 } 1424 1425 /* Preserve next hop index in the action structure. */ 1426 if (NULL != vid_pa) { 1427 vid_pa->hw_index = nh_index; 1428 } 1429 1430 if (NULL != sa_pa) { 1431 sa_pa->hw_index = nh_index; 1432 } 1433 1434 if (NULL != da_pa) { 1435 da_pa->hw_index = nh_index; 1436 } 1437 1438 if (NULL != vn_new_pa) { 1439 vn_new_pa->hw_index = nh_index; 1440 } 1441 1442 if (NULL != vn_del_pa) { 1443 vn_del_pa->hw_index = nh_index; 1444 } 1445 return (BCM_E_NONE); 1446 } 1447 1448 /* 1449 * Function: 1450 * _regex_policy_l2_actions_hw_alloc 1451 * 1452 * Purpose: 1453 * Allocate l3 next hop and egress interface for 1454 * l2 fields update action. 1455 * Parameters: 1456 * unit - (IN) BCM device number. 1457 * p_ent - (IN) Regex policy descriptor. 1458 * Returns: 1459 * BCM_E_XXX 1460 */ 1461 STATIC int _regex_policy_l2_actions_hw_alloc(int unit, _regex_policy_t *p_ent) 1462 { 1463 _regex_policy_action_t *vid_pa; /* Update outer vid action. */ 1464 _regex_policy_action_t *sa_pa; /* Update source mac action. */ 1465 _regex_policy_action_t *da_pa; /* Update destination mac action.*/ 1466 _regex_policy_action_t *vn_new_pa; /* Change VN tag. */ 1467 _regex_policy_action_t *vn_del_pa; /* Delete VN tag action. */ 1468 _regex_policy_action_t *pa; /* Field action descriptor. */ 1469 1470 /* 1471 * Applicable to stage ingress on devices which support 1472 * soc_feature_field_action_l2_change feature. 1473 */ 1474 1475 /* Initialization. */ 1476 sa_pa = da_pa = vid_pa = vn_new_pa = vn_del_pa = NULL; 1477 1478 /* Extract the policy info from the entry structure. */ 1479 for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) { 1480 switch (pa->action) { 1481 case bcmFieldActionSrcMacNew: 1482 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1483 pa->old_index = pa->hw_index; 1484 } 1485 sa_pa = pa; 1486 break; 1487 case bcmFieldActionDstMacNew: 1488 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1489 pa->old_index = pa->hw_index; 1490 } 1491 da_pa = pa; 1492 break; 1493 case bcmFieldActionOuterVlanNew: 1494 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1495 pa->old_index = pa->hw_index; 1496 } 1497 vid_pa = pa; 1498 break; 1499 case bcmFieldActionVnTagNew: 1500 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1501 pa->old_index = pa->hw_index; 1502 } 1503 vn_new_pa = pa; 1504 break; 1505 case bcmFieldActionVnTagDelete: 1506 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1507 pa->old_index = pa->hw_index; 1508 } 1509 vn_del_pa = pa; 1510 break; 1511 default: 1512 continue; 1513 } 1514 } 1515 1516 /* Create nh entry. */ 1517 if ((NULL != vid_pa) || (NULL != da_pa) || (NULL != sa_pa) || 1518 (NULL != vn_new_pa) || (NULL != vn_del_pa)) { 1519 BCM_IF_ERROR_RETURN(_regex_policy_l2_actions_nh_create(unit, da_pa, sa_pa, 1520 vid_pa, vn_new_pa, vn_del_pa)); 1521 } 1522 return (BCM_E_NONE); 1523 } 1524 1525 /* 1526 * Function: 1527 * _regex_policy_l2_actions_hw_free 1528 * 1529 * Purpose: 1530 * Free l3 next hop and egress interface for 1531 * l2 fields update action. 1532 * Parameters: 1533 * unit - (IN) BCM device number. 1534 * p_ent - (IN) Regex policy descriptor. 1535 * flags - (IN) Free flags (old/new/both). 1536 * Returns: 1537 * BCM_E_XXX 1538 */ 1539 STATIC int _regex_policy_l2_actions_hw_free(int unit, _regex_policy_t *p_ent, 1540 uint32 flags) 1541 { 1542 _regex_policy_action_t *pa; /* Field action descriptor. */ 1543 int nh_index; /* Next hop index. */ 1544 int old_nh_index; /* Old next hop index. */ 1545 int egr_intf_set = 0; /* Egress interface allocated */ 1546 int rv = BCM_E_NONE; /* Operation return status. */ 1547 1548 /* Applicable to stage ingress on TRX and FB family of devices only. */ 1549 1550 /* Initialization. */ 1551 nh_index = old_nh_index = _REGEX_INVALID_INDEX; 1552 1553 /* Extract the policy info from the entry structure. */ 1554 for (pa = p_ent->actions; pa != NULL; pa = pa->next) { 1555 switch (pa->action) { 1556 case bcmFieldActionSrcMacNew: 1557 egr_intf_set = TRUE; 1558 /* passthru */ 1559 /* coverity[MISSING_BREAK: FALSE] */ 1560 case bcmFieldActionOuterVlanNew: 1561 case bcmFieldActionDstMacNew: 1562 case bcmFieldActionVnTagNew: 1563 case bcmFieldActionVnTagDelete: 1564 if ((flags & _REGEX_ACTION_RESOURCE_FREE) && 1565 (_REGEX_INVALID_INDEX != pa->hw_index)) { 1566 nh_index = pa->hw_index; 1567 pa->hw_index = _REGEX_INVALID_INDEX; 1568 } 1569 if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) && 1570 (_REGEX_INVALID_INDEX != pa->old_index)) { 1571 old_nh_index = pa->old_index; 1572 pa->old_index = _REGEX_INVALID_INDEX; 1573 } 1574 break; 1575 default: 1576 break; 1577 } 1578 } 1579 1580 /* Destroy old next hop if any. */ 1581 if (_REGEX_INVALID_INDEX != old_nh_index) { 1582 rv = _regex_policy_l2_actions_nh_destroy(unit, old_nh_index, egr_intf_set); 1583 BCM_IF_ERROR_RETURN(rv); 1584 } 1585 if (_REGEX_INVALID_INDEX != nh_index) { 1586 rv = _regex_policy_l2_actions_nh_destroy(unit, nh_index, egr_intf_set); 1587 BCM_IF_ERROR_RETURN(rv); 1588 } 1589 return (BCM_E_NONE); 1590 } 1591 #endif /* INCLUDE_L3 */ 1592 1593 /* 1594 * Function: 1595 * _regex_policy_action_hw_resources_free 1596 * Purpose: 1597 * Free hw resources allocated for regex policy action installation. 1598 * Parameters: 1599 * unit - (IN) BCM device number 1600 * p_ent - (IN) Regex policy structure. 1601 * pa - (IN) Policy action structure. 1602 * Returns: 1603 * BCM_E_XXX 1604 * Notes: 1605 */ 1606 int _regex_policy_action_hw_resources_free(int unit, _regex_policy_t *p_ent, 1607 _regex_policy_action_t *pa, uint32 flags) 1608 { 1609 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 1610 int rv; 1611 1612 /* Input parameters check. */ 1613 if ((NULL == p_ent) || (NULL == pa)) { 1614 return (BCM_E_PARAM); 1615 } 1616 1617 /* Get the device info structure. */ 1618 device = ESW_REGEX_INFO(unit); 1619 if (NULL == device) { 1620 return BCM_E_INIT; 1621 } 1622 1623 switch (pa->action) { 1624 case bcmFieldActionMirrorIngress: 1625 case bcmFieldActionMirrorEgress: 1626 return _regex_policy_mirror_dest_delete(unit, p_ent, pa, flags); 1627 break; 1628 case bcmFieldActionRedirectMcast: 1629 #if defined(INCLUDE_L3) 1630 case bcmFieldActionRedirectIpmc: 1631 #endif /* INCLUDE_L3 */ 1632 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)) { 1633 break; 1634 } 1635 case bcmFieldActionRedirectPbmp: 1636 case bcmFieldActionEgressMask: 1637 case bcmFieldActionEgressPortsAdd: 1638 /* Applicable to stage ingress on TRX devices only. */ 1639 rv = device->functions->redirect_profile_delete(unit, pa->hw_index); 1640 BCM_IF_ERROR_RETURN(rv); 1641 break; 1642 1643 #if defined(INCLUDE_L3) 1644 case bcmFieldActionSrcMacNew: 1645 case bcmFieldActionDstMacNew: 1646 case bcmFieldActionOuterVlanNew: 1647 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 1648 rv = _regex_policy_l2_actions_hw_free(unit, p_ent, 1649 _REGEX_ACTION_HW_FREE); 1650 BCM_IF_ERROR_RETURN(rv); 1651 } 1652 break; 1653 #endif /* INCLUDE_L3 */ 1654 1655 default: 1656 break; 1657 } 1658 pa->hw_index = _REGEX_INVALID_INDEX; 1659 return (BCM_E_NONE); 1660 } 1661 1662 /* 1663 * Function: 1664 * _regex_policy_invalid_actions_remove 1665 * Purpose: 1666 * Remove deleted actions from policy actions 1667 * linked list. 1668 * Parameters: 1669 * unit - (IN) BCM device number 1670 * p_ent - (IN) Regex policy structure. 1671 * Returns: 1672 * BCM_E_XXX 1673 * Notes: 1674 */ 1675 int _regex_policy_invalid_actions_remove(int unit, _regex_policy_t *p_ent) 1676 { 1677 _regex_policy_action_t *pa; 1678 _regex_policy_action_t *pa_prev = NULL; 1679 _regex_policy_action_t *pa_next = NULL; 1680 _regex_policy_action_t *pa_iter; /* Field entry actions iterator.*/ 1681 int rv; 1682 1683 /* Input parameters check. */ 1684 if (NULL == p_ent) { 1685 return (BCM_E_PARAM); 1686 } 1687 1688 /* Find the action in the policy */ 1689 pa = p_ent->actions; /* start at head */ 1690 while (pa != NULL) { 1691 pa_next = pa->next; 1692 if (pa->flags & _REGEX_ACTION_VALID) { 1693 pa_prev = pa; 1694 pa = pa_next; 1695 continue; 1696 } 1697 1698 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1699 /* 1700 * Check if a valid instance of this action exists in 1701 * the entry actions linked list. 1702 * If TRUE, hardware index must be freed only 1703 * after updating policy table with new information. 1704 */ 1705 if ((bcmFieldActionEgressMask == pa->action) || 1706 (bcmFieldActionRedirectBcastPbmp == pa->action) || 1707 (bcmFieldActionRedirectPbmp == pa->action) || 1708 (bcmFieldActionEgressPortsAdd == pa->action) || 1709 (bcmFieldActionRedirectMcast == pa->action) || 1710 (bcmFieldActionRedirectIpmc == pa->action) || 1711 (bcmFieldActionMirrorIngress == pa->action) || 1712 (bcmFieldActionMirrorEgress == pa->action)) { 1713 1714 if (_REGEX_ACTION_MODIFY & pa->flags) { 1715 1716 pa->flags &= ~_REGEX_ACTION_MODIFY; 1717 1718 pa_iter = p_ent->actions; 1719 1720 while (pa_iter != NULL) { 1721 if ((_REGEX_ACTION_VALID == (pa_iter->flags & _REGEX_ACTION_VALID)) && 1722 (pa_iter->action == pa->action) && 1723 (_REGEX_INVALID_INDEX == pa_iter->hw_index)) { 1724 /* Do not free here. Release the hardware 1725 * index after policy install operation. 1726 */ 1727 pa_iter->hw_index = pa->hw_index; 1728 pa_iter->flags |= _REGEX_ACTION_MODIFY; 1729 pa->hw_index = _REGEX_INVALID_INDEX; 1730 break; 1731 } 1732 pa_iter = pa_iter->next; 1733 } 1734 1735 /* Here _REGEX_ACTION_MODIFY flag cleared means, no duplicate 1736 actions are found i.e an action is removed from the entry. 1737 Those invalid but not modified entries will be removed in 1738 the second pass to this function,so just return BCM_E_NONE 1739 on first pass */ 1740 if (!(_REGEX_ACTION_MODIFY & pa->flags)) { 1741 return (BCM_E_NONE); 1742 } 1743 } 1744 } 1745 1746 /* 1747 * Action not set for this entry, free the hardware index. 1748 */ 1749 if (_REGEX_INVALID_INDEX != pa->hw_index) { 1750 rv = _regex_policy_action_hw_resources_free(unit, p_ent, pa, _REGEX_ACTION_RESOURCE_FREE); 1751 BCM_IF_ERROR_RETURN(rv); 1752 } 1753 } 1754 1755 if (pa_prev != NULL) { 1756 pa_prev->next = pa->next; 1757 } else { /* matched head of list */ 1758 p_ent->actions = pa_next; 1759 } 1760 1761 /* okay to free action */ 1762 sal_free(pa); 1763 pa = pa_next; 1764 } 1765 return (BCM_E_NONE); 1766 } 1767 1768 /* 1769 * Function: 1770 * _regex_policy_mtp_hw_free 1771 * 1772 * Purpose: 1773 * Free mtp indexes used in regex policy 1774 * 1775 * Parameters: 1776 * unit - (IN) BCM device number. 1777 * p_ent - (IN) Regex policy structure. 1778 * Returns: 1779 * BCM_E_XXX 1780 * Notes: 1781 */ 1782 STATIC int _regex_policy_mtp_hw_free(int unit, _regex_policy_t *p_ent, uint32 flags) 1783 { 1784 _regex_policy_action_t *pa; 1785 int rv; /* Operation return status. */ 1786 1787 /* Extract action info from the entry structure. */ 1788 for (pa = p_ent->actions; pa != NULL; pa = pa->next) { 1789 /* Allocate mtp destination only for mirroring actions */ 1790 if ((bcmFieldActionMirrorIngress != pa->action) && 1791 (bcmFieldActionMirrorEgress != pa->action)) { 1792 continue; 1793 } 1794 1795 if ((_REGEX_INVALID_INDEX == pa->hw_index) && (_REGEX_INVALID_INDEX == pa->old_index) ) { 1796 continue; 1797 } 1798 1799 rv = _regex_policy_action_hw_resources_free(unit, p_ent, pa, flags); 1800 BCM_IF_ERROR_RETURN(rv); 1801 } 1802 1803 return (BCM_E_NONE); 1804 } 1805 1806 /* 1807 * Function: 1808 * _regex_policy_mtp_hw_alloc 1809 * 1810 * Purpose: 1811 * Allocate mtp indexes required for policy installation. 1812 * 1813 * Parameters: 1814 * unit - (IN) BCM device number. 1815 * p_ent - (IN) Regex policy structure. 1816 * Returns: 1817 * BCM_E_XXX 1818 * Notes: 1819 */ 1820 STATIC int _regex_policy_mtp_hw_alloc(int unit, _regex_policy_t *p_ent) 1821 { 1822 _regex_policy_action_t *pa; 1823 int rv; /* Operation return status. */ 1824 1825 /* Extract action info from the entry structure. */ 1826 for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) { 1827 /* Allocate mtp destination only for mirroring actions */ 1828 if ((bcmFieldActionMirrorIngress != pa->action) && 1829 (bcmFieldActionMirrorEgress != pa->action)) { 1830 continue; 1831 } 1832 if (_REGEX_ACTION_MODIFY & pa->flags) { 1833 pa->old_index = pa->hw_index; 1834 pa->hw_index = _REGEX_INVALID_INDEX; 1835 } 1836 if (_REGEX_INVALID_INDEX == pa->hw_index) { 1837 /* Allocate mirror destination. */ 1838 rv = _regex_policy_mirror_dest_add(unit, p_ent, pa); 1839 if (BCM_E_RESOURCE == rv) { 1840 if (_REGEX_ACTION_MODIFY & pa->flags) { 1841 pa->hw_index = pa->old_index; 1842 pa->old_index = _REGEX_INVALID_INDEX; 1843 } 1844 } 1845 BCM_IF_ERROR_RETURN(rv); 1846 } 1847 } 1848 return (BCM_E_NONE); 1849 } 1850 1851 /* 1852 * Function: 1853 * _regex_policy_redirect_profile_hw_free 1854 * 1855 * Purpose: 1856 * Free redirect profile indexes required for entry installation. 1857 * 1858 * Parameters: 1859 * unit - (IN) BCM device number. 1860 * f_ent - (IN) Field entry descriptor. 1861 * flags - (IN) Free flags (old/new/both). 1862 * Returns: 1863 * BCM_E_XXX 1864 * Notes: 1865 */ 1866 STATIC int _regex_policy_redirect_profile_hw_free(int unit, _regex_policy_t *p_ent, uint32 flags) 1867 { 1868 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 1869 _regex_policy_action_t *pa; 1870 int rv = BCM_E_NONE; /* Operation return status. */ 1871 1872 /* Get the device info structure. */ 1873 device = ESW_REGEX_INFO(unit); 1874 if (NULL == device) { 1875 return BCM_E_INIT; 1876 } 1877 1878 /* Applicable to stage ingress on TRX devices only. */ 1879 1880 /* Extract the policy info from the entry structure. */ 1881 for (pa = p_ent->actions; pa != NULL; pa = pa->next) { 1882 switch (pa->action) { 1883 case bcmFieldActionRedirectMcast: 1884 #if defined(INCLUDE_L3) 1885 case bcmFieldActionRedirectIpmc: 1886 #endif /* INCLUDE_L3 */ 1887 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){ 1888 break; 1889 } 1890 case bcmFieldActionRedirectPbmp: 1891 case bcmFieldActionRedirectBcastPbmp: 1892 case bcmFieldActionEgressMask: 1893 case bcmFieldActionEgressPortsAdd: 1894 if ((flags & _REGEX_ACTION_RESOURCE_FREE) && 1895 (_REGEX_INVALID_INDEX != pa->hw_index)) { 1896 rv = device->functions->redirect_profile_delete(unit, 1897 pa->hw_index); 1898 BCM_IF_ERROR_RETURN(rv); 1899 pa->hw_index = _REGEX_INVALID_INDEX; 1900 } 1901 1902 if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) && 1903 (_REGEX_INVALID_INDEX != pa->old_index)) { 1904 rv = device->functions->redirect_profile_delete(unit, 1905 pa->old_index); 1906 BCM_IF_ERROR_RETURN(rv); 1907 pa->old_index = _REGEX_INVALID_INDEX; 1908 } 1909 break; 1910 default: 1911 break; 1912 } 1913 } 1914 return (rv); 1915 } 1916 1917 1918 /* 1919 * Function: 1920 * _regex_policy_redirect_profile_hw_alloc 1921 * 1922 * Purpose: 1923 * Allocate redirect profile index required for profile installation. 1924 * 1925 * Parameters: 1926 * unit - (IN) BCM device number. 1927 * p_ent - (IN) Regex profile structure. 1928 * Returns: 1929 * BCM_E_XXX 1930 * Notes: 1931 */ 1932 STATIC int _regex_policy_redirect_profile_hw_alloc(int unit, _regex_policy_t *p_ent) 1933 { 1934 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 1935 int rv = BCM_E_NONE; /* Operation return status. */ 1936 _regex_policy_action_t *pa; 1937 int ref_count; /* Profile use reference count. */ 1938 1939 /* Get the device info structure. */ 1940 device = ESW_REGEX_INFO(unit); 1941 if (NULL == device) { 1942 return BCM_E_INIT; 1943 } 1944 1945 /* Applicable to stage ingress on TRX devices only. */ 1946 1947 /* Extract the policy info from the entry structure. */ 1948 for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) { 1949 switch (pa->action) { 1950 case bcmFieldActionRedirectMcast: 1951 #if defined(INCLUDE_L3) 1952 case bcmFieldActionRedirectIpmc: 1953 #endif /* INCLUDE_L3 */ 1954 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){ 1955 break; 1956 } 1957 case bcmFieldActionRedirectPbmp: 1958 case bcmFieldActionRedirectBcastPbmp: 1959 case bcmFieldActionEgressMask: 1960 case bcmFieldActionEgressPortsAdd: 1961 /* 1962 * Store previous hardware index value in old_index. 1963 */ 1964 pa->old_index = pa->hw_index; 1965 1966 rv = device->functions->redirect_profile_alloc(unit, p_ent, pa); 1967 if ((BCM_E_RESOURCE == rv) && 1968 (_REGEX_INVALID_INDEX != pa->old_index)) { 1969 /* Destroy old profile ONLY 1970 * if it is not used by other entries. 1971 */ 1972 rv = device->functions->redirect_profile_ref_count_get(unit, 1973 pa->old_index, 1974 &ref_count); 1975 BCM_IF_ERROR_RETURN(rv); 1976 if (ref_count > 1) { 1977 return (BCM_E_RESOURCE); 1978 } 1979 rv = device->functions->redirect_profile_delete(unit, pa->old_index); 1980 BCM_IF_ERROR_RETURN(rv); 1981 1982 /* Destroy old profile is no longer required. */ 1983 pa->old_index = _REGEX_INVALID_INDEX; 1984 1985 /* Reallocate profile for new action. */ 1986 rv = device->functions->redirect_profile_alloc(unit, p_ent, pa); 1987 } 1988 break; 1989 default: 1990 break; 1991 } 1992 if (BCM_FAILURE(rv)) { 1993 _regex_policy_redirect_profile_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE); 1994 break; 1995 } 1996 } 1997 1998 return (rv); 1999 } 2000 2001 STATIC int _regex_policers_compat(int unit, 2002 _regex_policy_t *p_ent, 2003 unsigned lvl, 2004 _field_policer_t *f_pl) 2005 { 2006 #if defined(ESW_REGEX_HIERARCHICAL_METERS) 2007 const unsigned olvl = 1 - lvl; 2008 _field_policer_t *_f_pl[2] = { 0, 0 }; 2009 2010 _f_pl[lvl] = f_pl; 2011 2012 if (!(p_ent->policer[olvl].flags & _FP_POLICER_VALID)) { 2013 return (BCM_E_NONE); 2014 } 2015 2016 BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit, 2017 p_ent->policer[olvl].pid, 2018 &_f_pl[olvl])); 2019 2020 switch (_f_pl[1]->cfg.flags & BCM_POLICER_COLOR_MERGE_MASK) { 2021 case BCM_POLICER_COLOR_MERGE_AND: 2022 case BCM_POLICER_COLOR_MERGE_OR: 2023 /* Level 1 sharing mode is SINGLE_AND or SINGLE_OR 2024 => level 0 and level 1 must both be in flow or modified 2025 trTCM mode 2026 */ 2027 2028 if ((IS_FLOW_MODE(_f_pl[0]) && IS_FLOW_MODE(_f_pl[1])) || 2029 (IS_MOD_TRTCM_MODE(_f_pl[0]) && IS_MOD_TRTCM_MODE(_f_pl[1]))) { 2030 break; 2031 } 2032 return (BCM_E_PARAM); 2033 2034 case BCM_POLICER_COLOR_MERGE_DUAL: 2035 /* Level 1 sharing mode is DUAL 2036 => level 0 must be modified trTCM 2037 */ 2038 2039 if (IS_MOD_TRTCM_MODE(_f_pl[0])) { 2040 break; 2041 } 2042 return (BCM_E_PARAM); 2043 2044 default: 2045 return (BCM_E_PARAM); 2046 } 2047 #endif 2048 return (BCM_E_NONE); 2049 } 2050 2051 /* 2052 * Function: 2053 * _regex_policer_mode_support 2054 * Purpose: 2055 * Validate policer mode support. 2056 * Parameters: 2057 * unit - (IN) BCM device number. 2058 * p_ent - (IN) Policy to which policer is attached. 2059 * level - (IN) Level policer attached. 2060 * f_pl - (IN) Policer descriptor. 2061 * Returns: 2062 * BCM_E_XXX 2063 */ 2064 STATIC int _regex_policer_mode_support(int unit, 2065 _regex_policy_t *p_ent, 2066 int lvl, 2067 _field_policer_t *f_pl) 2068 { 2069 switch (f_pl->cfg.mode) { 2070 case bcmPolicerModeGreen: 2071 case bcmPolicerModePassThrough: 2072 case bcmPolicerModeCommitted: 2073 case bcmPolicerModeTrTcmDs: 2074 case bcmPolicerModeCoupledTrTcmDs: 2075 break; 2076 case bcmPolicerModeSrTcm: 2077 case bcmPolicerModeSrTcmModified: 2078 case bcmPolicerModeTrTcm: 2079 if (lvl == 1) { 2080 return (BCM_E_PARAM); 2081 } 2082 break; 2083 default: 2084 return (BCM_E_PARAM); 2085 } 2086 2087 return _regex_policers_compat(unit, p_ent, lvl, f_pl); 2088 } 2089 2090 /* 2091 * Function: 2092 * _regex_policer_hw_flags_set 2093 * Purpose: 2094 * Update policer installation is required flag. 2095 * Parameters: 2096 * unit - (IN) Unit number. 2097 * f_pl - (IN/OUT) Internal policer descriptor. 2098 * flags - (IN) Internal flags. 2099 * Returns: 2100 * BCM_E_XXX 2101 * Notes: 2102 */ 2103 STATIC int _regex_policer_hw_flags_set(int unit, _field_policer_t *f_pl, uint32 flags) 2104 { 2105 /* Input parameters check. */ 2106 if (NULL == f_pl) { 2107 return (BCM_E_PARAM); 2108 } 2109 2110 f_pl->hw_flags |= flags; 2111 2112 switch (f_pl->cfg.mode) { 2113 case bcmPolicerModeSrTcm: 2114 case bcmPolicerModeTrTcm: 2115 case bcmPolicerModeTrTcmDs: 2116 case bcmPolicerModeCoupledTrTcmDs: 2117 case bcmPolicerModeSrTcmModified: 2118 case bcmPolicerModeCommitted: 2119 f_pl->hw_flags |= _FP_POLICER_DIRTY; 2120 break; 2121 default: 2122 return (BCM_E_UNAVAIL); 2123 } 2124 return (BCM_E_NONE); 2125 } 2126 2127 /* 2128 * Function: 2129 * _regex_policer_hw_free 2130 * 2131 * Purpose: 2132 * Deallocate hw policer from a policy. 2133 * 2134 * Parameters: 2135 * unit - (IN) BCM device number. 2136 * level - (IN) Policer level. 2137 * p_ent - (IN) Policy that policer belongs to. 2138 * Returns: 2139 * BCM_E_XXX 2140 */ 2141 STATIC int _regex_policer_hw_free(int unit, uint8 level, _regex_policy_t *p_ent) 2142 { 2143 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure. */ 2144 _field_policer_t *f_pl; /* Policer descriptor. */ 2145 2146 /* Input parameters check. */ 2147 if ((NULL == p_ent) || (level >= _REGEX_POLICER_LEVEL_COUNT)) { 2148 return (BCM_E_PARAM); 2149 } 2150 2151 f_ent_pl = p_ent->policer + level; 2152 /* Skip uninstalled policers. */ 2153 if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 2154 return (BCM_E_NONE); 2155 } 2156 2157 /* Read policer configuration.*/ 2158 BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl)); 2159 2160 /* Decrement hw reference count. */ 2161 if (f_pl->hw_ref_count > 0) { 2162 f_pl->hw_ref_count--; 2163 } 2164 2165 /* Policer not used by any other entry. */ 2166 if (f_pl->hw_ref_count == 0) { 2167 /* Mark policer for reinstallation. */ 2168 BCM_IF_ERROR_RETURN(_regex_policer_hw_flags_set(unit, f_pl, 0)); 2169 } 2170 f_ent_pl->flags &= ~_FP_POLICER_INSTALLED; 2171 return (BCM_E_NONE); 2172 } 2173 2174 /* 2175 * Function: 2176 * _regex_policers_hw_alloc 2177 * 2178 * Purpose: 2179 * Allocate policers required for policy installation. 2180 * 2181 * Parameters: 2182 * unit - (IN) BCM device number. 2183 * f_ent - (IN) Field entry array. 2184 * Returns: 2185 * BCM_E_XXX 2186 * Notes: 2187 * This API should be STATIC but is called by the legacy 2188 * bregex code in tr3. 2189 */ 2190 int _regex_policers_hw_alloc(int unit, _regex_policy_t *p_ent) 2191 { 2192 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2193 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 2194 _field_policer_t *f_pl; /* Field policer descriptor. */ 2195 int idx; /* Policer levels iterator. */ 2196 int rv; /* Operation return status. */ 2197 2198 /* Input parameters check. */ 2199 if (NULL == p_ent) { 2200 return (BCM_E_PARAM); 2201 } 2202 2203 /* Get the device info structure. */ 2204 device = ESW_REGEX_INFO(unit); 2205 if (NULL == device) { 2206 return BCM_E_INIT; 2207 } 2208 2209 /* Allocate policers if necessary. */ 2210 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 2211 f_ent_pl = p_ent->policer + idx; 2212 /* Skip invalid policers. */ 2213 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 2214 continue; 2215 } 2216 2217 /* Read policer configuration.*/ 2218 rv = _bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl); 2219 BCM_IF_ERROR_RETURN(rv); 2220 2221 /* 2222 * Check policer mode support - double check in case 2223 * attached policer was modified by bcm_policer_set API. 2224 */ 2225 rv = _regex_policer_mode_support(unit, p_ent, idx, f_pl); 2226 BCM_IF_ERROR_RETURN(rv); 2227 2228 /* Calculate HW index */ 2229 f_pl->hw_index = _REGEX_POLICER_ID_TO_INDEX(f_pl->pid); 2230 f_pl->pool_index = device->meter_pool; 2231 2232 /* Increment hw reference count. */ 2233 if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 2234 f_ent_pl->flags |= _FP_POLICER_INSTALLED; 2235 f_pl->hw_ref_count++; 2236 } 2237 2238 if (f_pl->hw_flags & _FP_POLICER_DIRTY) { 2239 BCM_IF_ERROR_RETURN(device->functions->policer_install(unit, f_pl)); 2240 } 2241 } 2242 2243 return (BCM_E_NONE); 2244 } 2245 2246 /* 2247 * Function: 2248 * _regex_policers_hw_free 2249 * 2250 * Purpose: 2251 * Free entry policers. 2252 * 2253 * Parameters: 2254 * unit - (IN) BCM device number. 2255 * p_ent - (IN) Regex policy structure. 2256 * Returns: 2257 * BCM_E_XXX 2258 * Notes: 2259 */ 2260 STATIC int _regex_policers_hw_free(int unit, _regex_policy_t *p_ent) 2261 { 2262 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 2263 int idx; /* Policer levels iterator. */ 2264 2265 /* Input parameters check. */ 2266 if (NULL == p_ent) { 2267 return (BCM_E_PARAM); 2268 } 2269 2270 /* Free policers if necessary. */ 2271 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 2272 f_ent_pl = p_ent->policer + idx; 2273 /* Skip invalid policers. */ 2274 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 2275 continue; 2276 } 2277 /* Skip installed policers. */ 2278 if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) { 2279 continue; 2280 } 2281 2282 BCM_IF_ERROR_RETURN(_regex_policer_hw_free(unit, idx, p_ent)); 2283 } 2284 return (BCM_E_NONE); 2285 } 2286 2287 /* 2288 * Function: 2289 * _regex_policy_hw_resources_free 2290 * 2291 * Purpose: 2292 * Free hw resources used in FP entry. 2293 * 2294 * Parameters: 2295 * unit - (IN) BCM device number. 2296 * p_ent - (IN) Regex policy structure. 2297 * flags - (IN) Old/installed resource to free. 2298 * Returns: 2299 * BCM_E_XXX 2300 */ 2301 STATIC int _regex_policy_hw_resources_free(int unit, _regex_policy_t *p_ent, uint32 flags) 2302 { 2303 int rv; /* Operation return status. */ 2304 2305 /* Input parameters check. */ 2306 if (NULL == p_ent) { 2307 return (BCM_E_PARAM); 2308 } 2309 2310 /* Free redirection profiles. */ 2311 rv = _regex_policy_redirect_profile_hw_free(unit, p_ent, flags); 2312 BCM_IF_ERROR_RETURN(rv); 2313 2314 /* Free mirror destination indexes. */ 2315 rv = _regex_policy_mtp_hw_free(unit, p_ent, flags); 2316 BCM_IF_ERROR_RETURN(rv); 2317 2318 #ifdef ESW_REGEX_STAT_SUPPORT 2319 /* Free counters. */ 2320 if (flags & _REGEX_ACTION_RESOURCE_FREE) { 2321 rv = _field_stat_hw_free(unit, p_ent); 2322 BCM_IF_ERROR_RETURN(rv); 2323 } 2324 #endif 2325 2326 /* Free policers. */ 2327 if (flags & _REGEX_ACTION_RESOURCE_FREE) { 2328 rv = _regex_policers_hw_free(unit, p_ent); 2329 BCM_IF_ERROR_RETURN(rv); 2330 } 2331 2332 #if defined(INCLUDE_L3) 2333 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 2334 rv = _regex_policy_l2_actions_hw_free(unit, p_ent, flags); 2335 BCM_IF_ERROR_RETURN(rv); 2336 } 2337 #endif /* INCLUDE_L3 */ 2338 2339 return (BCM_E_NONE); 2340 } 2341 2342 /* 2343 * Function: 2344 * _regex_policy_hw_resources_alloc 2345 * 2346 * Purpose: 2347 * Allocate hw resources required for entry installation. 2348 * 2349 * Parameters: 2350 * unit - (IN) BCM device number. 2351 * f_ent - (IN) Entry array 2352 * Returns: 2353 * BCM_E_XXX 2354 */ 2355 STATIC int _regex_policy_hw_resources_alloc(int unit, _regex_policy_t *p_ent) 2356 { 2357 int rv; /* Operation return status. */ 2358 2359 /* Input parameters check. */ 2360 if (NULL == p_ent) { 2361 return (BCM_E_PARAM); 2362 } 2363 2364 /* Allocate policers. */ 2365 BCM_IF_ERROR_RETURN(_regex_policers_hw_alloc(unit, p_ent)); 2366 2367 #ifdef ESW_REGEX_STAT_SUPPORT 2368 /* Allocate statistics. */ 2369 rv = _field_stat_hw_alloc(unit, p_ent); 2370 if (BCM_FAILURE(rv)) { 2371 _regex_policers_hw_free(unit, p_ent); 2372 return (rv); 2373 } 2374 #endif 2375 2376 /* Allocate mirror destination indexes. */ 2377 /* COVERITY 2378 * Internally calls bcm_esw_mirror_enable() 2379 * routine, which has most stack use: 7844 bytes 2380 */ 2381 /* coverity[stack_use_overflow : FALSE] */ 2382 rv = _regex_policy_mtp_hw_alloc(unit, p_ent); 2383 if (BCM_FAILURE(rv)) { 2384 #ifdef ESW_REGEX_STAT_SUPPORT 2385 _field_stat_hw_free(unit, p_ent); 2386 #endif 2387 _regex_policers_hw_free(unit, p_ent); 2388 return (rv); 2389 } 2390 2391 /* Allocate redirection profiles. */ 2392 rv = _regex_policy_redirect_profile_hw_alloc(unit, p_ent); 2393 if (BCM_FAILURE(rv)) { 2394 _regex_policy_mtp_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE); 2395 #ifdef ESW_REGEX_STAT_SUPPORT 2396 _field_stat_hw_free(unit, p_ent); 2397 #endif 2398 _regex_policers_hw_free(unit, p_ent); 2399 return (rv); 2400 } 2401 2402 #if defined (INCLUDE_L3) 2403 if (soc_feature(unit, soc_feature_field_action_l2_change)) { 2404 rv = _regex_policy_l2_actions_hw_alloc(unit, p_ent); 2405 if (BCM_FAILURE(rv)) { 2406 _regex_policy_mtp_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE); 2407 #ifdef ESW_REGEX_STAT_SUPPORT 2408 _field_stat_hw_free(unit, p_ent); 2409 #endif 2410 _regex_policers_hw_free(unit, p_ent); 2411 _regex_policy_redirect_profile_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE); 2412 return (rv); 2413 } 2414 } 2415 #endif /* INCLUDE_L3 */ 2416 2417 return (BCM_E_NONE); 2418 } 2419 2420 /* 2421 * Function: 2422 * _regex_policy_install 2423 * 2424 * Purpose: 2425 * Install a regex FT_POLICY entry. This writes the 2426 * actions to the hardware. 2427 * 2428 * Parameters: 2429 * unit - (IN) BCM device number. 2430 * policy - (IN) Policy ID to be installed. 2431 * Returns: 2432 * BCM_E_XXX 2433 */ 2434 STATIC int _regex_policy_install(int unit, bcm_regex_policy_t policy) 2435 { 2436 _regex_policy_t *p_ent; /* Policy entry pointer. */ 2437 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2438 int rv; /* Operation return status. */ 2439 2440 LOG_DEBUG(BSL_LS_BCM_REGEX, 2441 (BSL_META_U(unit, 2442 "FT(unit %d) vverb: %s(%d)\n"), 2443 unit, FUNCTION_NAME(), policy)); 2444 2445 /* Get the device info structure. */ 2446 device = ESW_REGEX_INFO(unit); 2447 if (NULL == device) { 2448 return BCM_E_INIT; 2449 } 2450 2451 /* Installing the entry. */ 2452 rv = _regex_policy_get(unit, policy, &p_ent); 2453 BCM_IF_ERROR_RETURN(rv); 2454 2455 /* If entry was previously installed, we better disable it temporarily, 2456 * to avoid intermittent actions. 2457 */ 2458 if (p_ent->flags & _REGEX_POLICY_INSTALLED) { 2459 /* Disable installed entry. */ 2460 rv = device->functions->policy_remove(unit, p_ent); 2461 BCM_IF_ERROR_RETURN(rv); 2462 } 2463 2464 /* Remove deleted actions. */ 2465 rv = _regex_policy_invalid_actions_remove(unit, p_ent); 2466 BCM_IF_ERROR_RETURN(rv); 2467 2468 /* Allocate hw resources required for policy installation. */ 2469 rv = _regex_policy_hw_resources_alloc(unit, p_ent); 2470 BCM_IF_ERROR_RETURN(rv); 2471 2472 /* Install physical policy */ 2473 rv = device->functions->policy_install(unit, p_ent); 2474 if (BCM_FAILURE(rv)) { 2475 (void)_regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_HW_FREE); 2476 return (rv); 2477 } 2478 p_ent->flags &= ~_REGEX_POLICY_DIRTY; 2479 p_ent->flags |= _REGEX_POLICY_INSTALLED; 2480 2481 /* In case of policy reinstall free previous installation hw resources. */ 2482 rv = _regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_OLD_RESOURCE_FREE); 2483 if (BCM_FAILURE(rv)) { 2484 BCM_IF_ERROR_RETURN(_regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_HW_FREE)); 2485 return (rv); 2486 } 2487 return (BCM_E_NONE); 2488 } 2489 2490 /* 2491 * Function: _regex_policy_remove 2492 * 2493 * Purpose: 2494 * Remove a policy from the hardware tables. 2495 * 2496 * Parameters: 2497 * unit - (IN) BCM device number 2498 * policy - (IN) policy to remove. 2499 * 2500 * Returns: 2501 * BCM_E_XXX 2502 */ 2503 int _regex_policy_remove(int unit, bcm_regex_policy_t policy) 2504 { 2505 _regex_policy_t *p_ent; /* Policy entry pointer. */ 2506 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2507 int rv; /* Operation return status. */ 2508 2509 LOG_DEBUG(BSL_LS_BCM_REGEX, 2510 (BSL_META_U(unit, 2511 "FT(unit %d) vverb: %s(%d)\n"), 2512 unit, FUNCTION_NAME(), policy)); 2513 2514 /* Get the device info structure. */ 2515 device = ESW_REGEX_INFO(unit); 2516 if (NULL == device) { 2517 return BCM_E_INIT; 2518 } 2519 2520 rv = _regex_policy_get(unit, policy, &p_ent); 2521 if (BCM_FAILURE(rv)) { 2522 return (rv); 2523 } 2524 2525 if (!(p_ent->flags & _REGEX_POLICY_INSTALLED)) { 2526 /* Entry not installed in hardware to perform remove operation. */ 2527 return (BCM_E_NONE); 2528 } 2529 2530 /* Free hw resources allocated during entry installation. */ 2531 rv = _regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_RESOURCE_FREE); 2532 BCM_IF_ERROR_RETURN(rv); 2533 2534 rv = device->functions->policy_remove(unit, p_ent); 2535 BCM_IF_ERROR_RETURN(rv); 2536 2537 p_ent->flags |= _REGEX_POLICY_DIRTY; 2538 p_ent->flags &= ~_REGEX_POLICY_INSTALLED; 2539 2540 2541 /* Remove deleted actions. */ 2542 rv = _regex_policy_invalid_actions_remove(unit, p_ent); 2543 BCM_IF_ERROR_RETURN(rv); 2544 return (BCM_E_NONE); 2545 } 2546 2547 /* 2548 * Function: _regex_policy_create_id 2549 * 2550 * Purpose: 2551 * Create a blank entry group based on a group; 2552 * allows selection of a specific slot in a slice 2553 * 2554 * Parameters: 2555 * unit - (IN) BCM device number. 2556 * policy - (IN) Policy id. 2557 * Returns: 2558 * BCM_E_INIT - unit not initialized 2559 * BCM_E_EXISTS - Policy ID already in use 2560 * BCM_E_MEMORY - allocation failure 2561 * BCM_E_NONE - Success 2562 */ 2563 STATIC int _regex_policy_create_id(int unit, bcm_regex_policy_t policy) 2564 { 2565 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 2566 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2567 int rv; /* Operation return status. */ 2568 2569 LOG_DEBUG(BSL_LS_BCM_REGEX, 2570 (BSL_META_U(unit, 2571 "FT(unit %d) vverb: %s(policy=%d)\n"), 2572 unit, FUNCTION_NAME(), policy)); 2573 2574 /* Confirm that 'policy' is not already used on unit */ 2575 if (BCM_SUCCESS(_regex_policy_get(unit, policy, &p_ent))) { 2576 LOG_ERROR(BSL_LS_BCM_REGEX, 2577 (BSL_META_U(unit, 2578 "FT(unit %d) Error: policy=(%d) already exists.\n"), 2579 unit, policy)); 2580 return (BCM_E_EXISTS); 2581 } 2582 2583 device = ESW_REGEX_INFO(unit); 2584 if (NULL == device) { 2585 return BCM_E_INIT; 2586 } 2587 2588 if (device->num_policies >= ESW_REGEX_POLICIES_MAX(unit)) { 2589 LOG_ERROR(BSL_LS_BCM_REGEX, 2590 (BSL_META_U(unit, 2591 "FT(unit %d) Error: No room.\n"), 2592 unit)); 2593 return (BCM_E_RESOURCE); 2594 } 2595 2596 /* Create entry structure. */ 2597 rv = _regex_policy_phys_create(unit, policy, &p_ent); 2598 if (BCM_FAILURE(rv)) { 2599 return (rv); 2600 } 2601 2602 return (BCM_E_NONE); 2603 } 2604 2605 /* 2606 * Function: 2607 * _regex_policy_action_alloc 2608 * Purpose: 2609 * Allocate and initialize an action structure. 2610 * Parameters: 2611 * unit - BCM device number. 2612 * action - Action to perform (bcmFieldActionXXX) 2613 * param0 - Action parameter (use 0 if not required) 2614 * param1 - Action parameter (use 0 if not required) 2615 * param2 - Action parameter (use 0 if not required) 2616 * param3 - Action parameter (use 0 if not required) 2617 * fa (OUT) - pointer to field action structure 2618 * Returns: 2619 * BCM_E_MEMORY - allocation failure 2620 * BCM_E_NONE - Success 2621 */ 2622 int _regex_policy_action_alloc(int unit, bcm_field_action_t action, 2623 uint32 param0, uint32 param1, uint32 param2, 2624 uint32 param3, _regex_policy_action_t **pa) 2625 { 2626 *pa = sal_alloc(sizeof(**pa), "regex_policy_action"); 2627 if (NULL == *pa) { 2628 LOG_ERROR(BSL_LS_BCM_REGEX, 2629 (BSL_META_U(unit, 2630 "FT(unit %d) Error: allocation failure for regex_policy_action\n"), 2631 unit)); 2632 return (BCM_E_MEMORY); 2633 } 2634 sal_memset(*pa, 0, sizeof(**pa)); 2635 2636 (*pa)->action = action; 2637 (*pa)->param[0] = param0; 2638 (*pa)->param[1] = param1; 2639 (*pa)->param[2] = param2; 2640 (*pa)->param[3] = param3; 2641 (*pa)->hw_index = _REGEX_INVALID_INDEX; 2642 (*pa)->old_index = _REGEX_INVALID_INDEX; 2643 /* mark new action as not yet installed */ 2644 (*pa)->flags |= (_REGEX_ACTION_VALID | _REGEX_ACTION_DIRTY); 2645 2646 return (BCM_E_NONE); 2647 } 2648 2649 /* 2650 * Function: _regex_policy_action_add 2651 * 2652 * Purpose: 2653 * Add action performed when policy is applied to a session. 2654 * 2655 * Parameters: 2656 * unit - (IN) BCM device number. 2657 * policy - (IN) Policy entry id. 2658 * pa - (IN) Policy action structure. 2659 * Returns: 2660 * BCM_E_XXX 2661 */ 2662 int _regex_policy_action_add(int unit, bcm_regex_policy_t policy, _regex_policy_action_t *pa) 2663 { 2664 _regex_policy_t *p_ent; /* Field entry structure. */ 2665 _regex_policy_action_t *pa_iter; /* Field entry actions iterator.*/ 2666 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2667 int rv; /* Operation return status. */ 2668 2669 /* Get policy structure pointer. */ 2670 rv = _regex_policy_get(unit, policy, &p_ent); 2671 BCM_IF_ERROR_RETURN(rv); 2672 2673 device = ESW_REGEX_INFO(unit); 2674 if (NULL == device) { 2675 return BCM_E_INIT; 2676 } 2677 2678 /* Ensure action is supported. */ 2679 rv = device->functions->policy_action_support_check(unit, 2680 pa->action); 2681 if (BCM_FAILURE(rv)) { 2682 LOG_ERROR(BSL_LS_BCM_REGEX, 2683 (BSL_META_U(unit, 2684 "FT(unit %d) Error: action=%s is not supported.\n"), 2685 unit, 2686 _regex_policy_action_name(pa->action))); 2687 return (rv); 2688 } 2689 2690 /* Check for existing actions that conflict with the new action. */ 2691 pa_iter = p_ent->actions; 2692 while (pa_iter != NULL) { 2693 if (0 == (pa_iter->flags & _REGEX_ACTION_VALID)) { 2694 pa_iter = pa_iter->next; 2695 continue; 2696 } 2697 rv = device->functions->policy_action_conflict_check(unit, 2698 pa_iter->action, 2699 pa->action); 2700 if (BCM_FAILURE(rv)) { 2701 LOG_ERROR(BSL_LS_BCM_REGEX, 2702 (BSL_META_U(unit, 2703 "FT(unit %d) Error: action=%s conflicts with existing action in policy=%d\n"), 2704 unit, 2705 _regex_policy_action_name(pa->action), 2706 policy)); 2707 return (rv); 2708 } 2709 pa_iter = pa_iter->next; 2710 } 2711 2712 /* Check action parameters. */ 2713 rv = device->functions->policy_action_params_check(unit, p_ent, pa); 2714 if (BCM_FAILURE(rv)) { 2715 LOG_ERROR(BSL_LS_BCM_REGEX, 2716 (BSL_META_U(unit, 2717 "FT(unit %d) Error: action=%s parameters check failed (%d)\n"), 2718 unit, _regex_policy_action_name(pa->action), rv)); 2719 return (rv); 2720 } 2721 2722 if (pa->action == bcmFieldActionColorIndependent) { 2723 if (0 != pa->param[0]) { 2724 p_ent->flags |= _REGEX_POLICY_COLOR_INDEPENDENT; 2725 } else { 2726 p_ent->flags &= ~_REGEX_POLICY_COLOR_INDEPENDENT; 2727 } 2728 p_ent->flags |= _REGEX_POLICY_DIRTY; 2729 sal_free(pa); 2730 return (BCM_E_NONE); 2731 } 2732 2733 /* Add action to front of entry's linked-list. */ 2734 ESW_REGEX_LOCK(unit); 2735 pa->next = p_ent->actions; 2736 p_ent->actions = pa; 2737 p_ent->flags |= _REGEX_POLICY_DIRTY; 2738 ESW_REGEX_UNLOCK(unit); 2739 return (BCM_E_NONE); 2740 } 2741 2742 /* 2743 * Function: _regex_policy_action_ports_add 2744 * 2745 * Purpose: 2746 * Add action performed when policy is applied to a session. 2747 * 2748 * Parameters: 2749 * unit - (IN) BCM device number 2750 * policy - (IN) Policy entry id. 2751 * action - (IN) Action to perform (bcmFieldActionXXX) 2752 * param0 - (IN) Action parameter (use 0 if not required) 2753 * param1 - (IN) Action parameter (use 0 if not required) 2754 * param2 - (IN) Action parameter (use 0 if not required) 2755 * param3 - (IN) Action parameter (use 0 if not required) 2756 * 2757 * Returns: 2758 * BCM_E_XXX 2759 */ 2760 STATIC int _regex_policy_action_ports_add(int unit, 2761 bcm_regex_policy_t policy, 2762 bcm_field_action_t action, 2763 uint32 param0, 2764 uint32 param1, 2765 uint32 param2, 2766 uint32 param3) 2767 { 2768 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2769 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 2770 int rv; /* Operation return status. */ 2771 2772 LOG_DEBUG(BSL_LS_BCM_REGEX, 2773 (BSL_META_U(unit, 2774 "FT(unit %d) vverb: %s(policy=%d, action=%s, p0=%d, p1=%d, p2=%d)\n"), 2775 unit, FUNCTION_NAME(), policy, 2776 _regex_policy_action_name(action), 2777 param0, param1, param2)); 2778 2779 device = ESW_REGEX_INFO(unit); 2780 if (NULL == device) { 2781 return BCM_E_INIT; 2782 } 2783 ESW_REGEX_LOCK(unit); 2784 2785 /* 2786 * Allocate the action descriptor. 2787 */ 2788 rv = _regex_policy_action_alloc(unit, action, param0, param1, param2, param3, &pa); 2789 if (BCM_FAILURE(rv)) { 2790 LOG_ERROR(BSL_LS_BCM_REGEX, 2791 (BSL_META_U(unit, 2792 "FT Error: _regex_policy_action_alloc failed\n"))); 2793 ESW_REGEX_UNLOCK(unit); 2794 return rv; 2795 } 2796 2797 /* 2798 * Add action to entry actions list. 2799 */ 2800 rv = _regex_policy_action_add(unit, policy, pa); 2801 ESW_REGEX_UNLOCK(unit); 2802 if (BCM_FAILURE(rv)) { 2803 sal_free(pa); 2804 return rv; 2805 } 2806 return (BCM_E_NONE); 2807 } 2808 2809 /* 2810 * Function: _regex_policy_action_ports_get 2811 * 2812 * Purpose: 2813 * Get parameters associated with a policy action 2814 * 2815 * Parameters: 2816 * unit - (IN) BCM device number 2817 * policy - (IN) Policy entry id. 2818 * action - (IN) Action to perform (bcmFieldActionXXX) 2819 * param0 - (OUT) Action parameter 2820 * param1 - (OUT) Action parameter 2821 * param2 - (OUT) Action parameter 2822 * param3 - (OUT) Action parameter 2823 * 2824 * Returns: 2825 * BCM_E_INIT - BCM Unit not initialized 2826 * BCM_E_NOT_FOUND - Entry ID not found 2827 * BCM_E_NOT_FOUND - No matching Action for entry 2828 * BCM_E_PARAM - paramX is NULL 2829 * BCM_E_NONE - Success 2830 */ 2831 2832 STATIC int _regex_policy_action_ports_get(int unit, 2833 bcm_regex_policy_t policy, 2834 bcm_field_action_t action, 2835 uint32 *param0, 2836 uint32 *param1, 2837 uint32 *param2, 2838 uint32 *param3) 2839 { 2840 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2841 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 2842 _regex_policy_t *p_ent; /* Field entry structure. */ 2843 int rv; 2844 2845 /* Input parameters check. */ 2846 if ((NULL == param0) || (NULL == param1) || (NULL == param2)) { 2847 return (BCM_E_PARAM); 2848 } 2849 2850 /* Lock the module. */ 2851 device = ESW_REGEX_INFO(unit); 2852 if (NULL == device) { 2853 return BCM_E_INIT; 2854 } 2855 ESW_REGEX_LOCK(unit); 2856 2857 rv = _regex_policy_get(unit, policy, &p_ent); 2858 if (BCM_FAILURE(rv)) { 2859 ESW_REGEX_UNLOCK(unit); 2860 return (rv); 2861 } 2862 2863 /* Find matching action in the entry */ 2864 for (pa = p_ent->actions; pa != NULL; pa = pa->next) { 2865 if (pa->action == action) { 2866 break; 2867 } 2868 } 2869 2870 if (pa == NULL) { 2871 ESW_REGEX_UNLOCK(unit); 2872 LOG_VERBOSE(BSL_LS_BCM_REGEX, 2873 (BSL_META_U(unit, 2874 "FT(unit %d) Error: action not in policy=%d\n"), 2875 unit, policy)); 2876 return (BCM_E_NOT_FOUND); 2877 } 2878 2879 *param0 = pa->param[0]; 2880 *param1 = pa->param[1]; 2881 *param2 = pa->param[2]; 2882 *param3 = pa->param[3]; 2883 2884 /* Unlock the module. */ 2885 ESW_REGEX_UNLOCK(unit); 2886 2887 return (rv); 2888 } 2889 2890 /* 2891 * Function: 2892 * _regex_policy_action_delete 2893 * Purpose: 2894 * Delete action from a policy. 2895 * Parameters: 2896 * unit - (IN) BCM device number 2897 * policy - (IN) Policy entry id. 2898 * action - (IN) Action to remove (bcmFieldActionXXX) 2899 * param0 - (IN) Action parameter (use 0 if not required) 2900 * param1 - (IN) Action parameter (use 0 if not required) 2901 * Returns: 2902 * BCM_E_XXX 2903 * Notes: 2904 */ 2905 int _regex_policy_action_delete(int unit, bcm_regex_policy_t policy, 2906 bcm_field_action_t action, 2907 uint32 param0, uint32 param1) 2908 { 2909 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 2910 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 2911 _regex_policy_action_t *pa_prev = NULL; 2912 _regex_policy_t *p_ent; /* Field entry structure. */ 2913 int rv; /* Operation return status. */ 2914 2915 device = ESW_REGEX_INFO(unit); 2916 if (NULL == device) { 2917 return BCM_E_INIT; 2918 } 2919 2920 /* Get field entry descriptor. */ 2921 rv = _regex_policy_get(unit, policy, &p_ent); 2922 if (BCM_FAILURE(rv)) { 2923 return (rv); 2924 } 2925 2926 /* Special treatment for pre-historic actions. */ 2927 switch (action) { 2928 case bcmFieldActionColorIndependent: 2929 p_ent->flags |= _REGEX_POLICY_DIRTY; 2930 p_ent->flags &= ~_REGEX_POLICY_COLOR_INDEPENDENT; 2931 return (BCM_E_NONE); 2932 default: 2933 break; 2934 } 2935 2936 ESW_REGEX_LOCK(unit); 2937 2938 /* Find the action in the entry */ 2939 pa = p_ent->actions; /* start at head */ 2940 2941 while (pa != NULL) { 2942 if (pa->action != action) { 2943 pa_prev = pa; 2944 pa = pa->next; 2945 continue; 2946 } 2947 2948 /* Some actions might be applied multiple times.*/ 2949 if (((action == bcmFieldActionMirrorIngress) || 2950 (action == bcmFieldActionMirrorEgress)) && 2951 (((uint32)_REGEX_INVALID_INDEX != param0) && 2952 ((uint32)_REGEX_INVALID_INDEX != param1))) { 2953 if ((pa->param[0] != param0) || (pa->param[1] != param1)) { 2954 pa_prev = pa; 2955 pa = pa->next; 2956 continue; 2957 } 2958 } 2959 break; 2960 } 2961 2962 if (NULL == pa) { 2963 ESW_REGEX_UNLOCK(unit); 2964 return (BCM_E_NOT_FOUND); 2965 } 2966 2967 /* If entry is installed mark action as invalid. 2968 * Invalid actions will be removed during entry remove/reinstall. 2969 */ 2970 if (p_ent->flags & _REGEX_POLICY_INSTALLED) { 2971 pa->flags &= ~_REGEX_ACTION_VALID; 2972 pa->flags |= _REGEX_ACTION_MODIFY; 2973 p_ent->flags |= _REGEX_POLICY_DIRTY; 2974 ESW_REGEX_UNLOCK(unit); 2975 return (BCM_E_NONE); 2976 } 2977 2978 if (pa_prev != NULL) { 2979 pa_prev->next = pa->next; 2980 } else { /* matched head of list */ 2981 p_ent->actions = pa->next; 2982 } 2983 2984 /* okay to free action */ 2985 sal_free(pa); 2986 pa = NULL; 2987 2988 p_ent->flags |= _REGEX_POLICY_DIRTY; 2989 ESW_REGEX_UNLOCK(unit); 2990 return (BCM_E_NONE); 2991 } 2992 2993 /* 2994 * Function: 2995 * bcm_esw_regex_policy_create 2996 * Purpose: 2997 * Create a blank regex policy. 2998 * Parameters: 2999 * unit - (IN) Unit number. 3000 * flags - (IN) REGEX_FLOW_xxx flags 3001 * policy - (OUT) ID of policy to be created. 3002 * Returns: 3003 * BCM_E_xxx 3004 * Notes: 3005 */ 3006 int bcm_esw_regex_policy_create(int unit, int flags, bcm_regex_policy_t *policy) 3007 { 3008 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3009 3010 if (!soc_feature(unit, soc_feature_regex)) { 3011 return BCM_E_UNAVAIL; 3012 } 3013 3014 /* Get the device info structure. */ 3015 device = ESW_REGEX_INFO(unit); 3016 if (NULL == device) { 3017 return BCM_E_INIT; 3018 } 3019 3020 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3021 return BCM_E_PARAM; 3022 } 3023 3024 if (0 == (flags & BCM_REGEX_POLICY_WITH_ID)) 3025 { 3026 /* Generate a policy ID. */ 3027 do { 3028 last_allocated_policy++; 3029 if (ESW_REGEX_POLICIES_LAST(unit) < last_allocated_policy) { 3030 last_allocated_policy = ESW_REGEX_POLICIES_LAST(unit); 3031 } 3032 } while (BCM_SUCCESS(_regex_policy_get(unit, last_allocated_policy, NULL))); 3033 3034 *policy = last_allocated_policy; 3035 } 3036 3037 return _regex_policy_create_id(unit, *policy); 3038 } 3039 3040 /* 3041 * Function: 3042 * bcm_esw_regex_policy_destroy 3043 * Purpose: 3044 * Destroy a regex policy. This deallocates memory only. 3045 * Parameters: 3046 * unit - (IN) Unit number. 3047 * policy - (IN) ID of policy to be destroyed. 3048 * Returns: 3049 * BCM_E_xxx 3050 * Notes: 3051 */ 3052 int bcm_esw_regex_policy_destroy(int unit, bcm_regex_policy_t policy) 3053 { 3054 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3055 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 3056 int rv; 3057 3058 if (!soc_feature(unit, soc_feature_regex)) { 3059 return BCM_E_UNAVAIL; 3060 } 3061 3062 /* Get the device info structure. */ 3063 device = ESW_REGEX_INFO(unit); 3064 if (NULL == device) { 3065 return BCM_E_INIT; 3066 } 3067 3068 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3069 return BCM_E_PARAM; 3070 } 3071 3072 /* Cannot delete policy 0 since it is used by the flow tracker for new and unmatched 3073 * sessions. */ 3074 if (_REGEX_DEFAULT_POLICY_ID == policy) { 3075 return BCM_E_BUSY; 3076 } 3077 3078 rv = _regex_policy_get(unit, policy, &p_ent); 3079 if (BCM_FAILURE(rv)) { 3080 return (rv); 3081 } 3082 3083 ESW_REGEX_LOCK(unit); 3084 3085 /* Remove policy from hw before destroying sw image. */ 3086 if (p_ent->flags & _REGEX_POLICY_INSTALLED) { 3087 rv = bcm_esw_regex_policy_remove(unit, policy); 3088 if (BCM_FAILURE(rv)) { 3089 ESW_REGEX_UNLOCK(unit); 3090 return(rv); 3091 } 3092 } 3093 3094 /* Destroy policy policers */ 3095 rv = bcm_esw_regex_policy_policer_detach_all(unit, policy); 3096 if (BCM_FAILURE(rv)) { 3097 ESW_REGEX_UNLOCK(unit); 3098 return(rv); 3099 } 3100 3101 #ifdef ESW_REGEX_STAT_SUPPORT 3102 /* Destroy policy stats */ 3103 if (p_ent->statistic.flags & _REGEX_POLICY_STAT_VALID) { 3104 rv = bcm_esw_regex_policy_stat_detach(unit, policy, p_ent->statistic.sid); 3105 if (BCM_FAILURE(rv)) { 3106 ESW_REGEX_UNLOCK(unit); 3107 return(rv); 3108 } 3109 } 3110 #endif 3111 3112 /* Destroy entry sw images. */ 3113 rv = _regex_policy_phys_destroy(unit, p_ent); 3114 if (BCM_FAILURE(rv)) { 3115 ESW_REGEX_UNLOCK(unit); 3116 return(rv); 3117 } 3118 3119 #ifdef BCM_WARM_BOOT_SUPPORT 3120 SOC_CONTROL_LOCK(unit); 3121 SOC_CONTROL(unit)->scache_dirty = 1; 3122 SOC_CONTROL_UNLOCK(unit); 3123 #endif 3124 3125 ESW_REGEX_UNLOCK(unit); 3126 3127 return (BCM_E_NONE); 3128 } 3129 3130 /* 3131 * Function: 3132 * bcm_esw_regex_policy_destroy_all 3133 * Purpose: 3134 * Destroy all regex policy entries. 3135 * Parameters: 3136 * unit - (IN) Unit number. 3137 * Returns: 3138 * BCM_E_xxx 3139 * Notes: 3140 */ 3141 int bcm_esw_regex_policy_destroy_all(int unit) 3142 { 3143 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3144 int idx; 3145 int rv; 3146 3147 if (!soc_feature(unit, soc_feature_regex)) { 3148 return BCM_E_UNAVAIL; 3149 } 3150 3151 /* Get the device info structure. */ 3152 device = ESW_REGEX_INFO(unit); 3153 if (NULL == device) { 3154 return BCM_E_INIT; 3155 } 3156 3157 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3158 return BCM_E_PARAM; 3159 } 3160 3161 LOG_DEBUG(BSL_LS_BCM_REGEX, 3162 (BSL_META_U(unit, 3163 "FT(unit %d) vverb: %s()\n"), 3164 unit, FUNCTION_NAME())); 3165 3166 ESW_REGEX_LOCK(unit); 3167 3168 /* Scan unit's groups freeing each entry list. */ 3169 for (idx = device->num_policies - 1; idx >= 0; idx--) { 3170 /* Destroy all policies except the default policy. */ 3171 if (_REGEX_DEFAULT_POLICY_ID == device->policies[idx]->eid) { 3172 continue; 3173 } 3174 rv = bcm_esw_regex_policy_destroy(unit, (device->policies[idx])->eid); 3175 if (BCM_FAILURE(rv)) { 3176 ESW_REGEX_UNLOCK(unit); 3177 return (rv); 3178 } 3179 } 3180 3181 ESW_REGEX_UNLOCK(unit); 3182 3183 return (BCM_E_NONE); 3184 } 3185 3186 /* 3187 * Function: 3188 * bcm_esw_regex_policy_install 3189 * Purpose: 3190 * Install a regex policy into the hardware tables. 3191 * Parameters: 3192 * unit - (IN) Unit number. 3193 * policy - (IN) ID of policy to be installed. 3194 * Returns: 3195 * BCM_E_xxx 3196 * Notes: 3197 */ 3198 int bcm_esw_regex_policy_install(int unit, bcm_regex_policy_t policy) 3199 { 3200 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3201 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 3202 int rv; 3203 int dirty; /* Field entry dirty flag. */ 3204 3205 if (!soc_feature(unit, soc_feature_regex)) { 3206 return BCM_E_UNAVAIL; 3207 } 3208 3209 /* Get the device info structure. */ 3210 device = ESW_REGEX_INFO(unit); 3211 if (NULL == device) { 3212 return BCM_E_INIT; 3213 } 3214 3215 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3216 return BCM_E_PARAM; 3217 } 3218 3219 LOG_DEBUG(BSL_LS_BCM_REGEX, 3220 (BSL_META_U(unit, 3221 "FT(unit %d) vverb: %s()\n"), 3222 unit, FUNCTION_NAME())); 3223 3224 ESW_REGEX_LOCK(unit); 3225 3226 rv = _regex_policy_get(unit, policy, &p_ent); 3227 if (BCM_FAILURE(rv)) { 3228 ESW_REGEX_UNLOCK(unit); 3229 return rv; 3230 } 3231 3232 rv = _regex_policy_dirty(unit, p_ent, &dirty); 3233 if (BCM_FAILURE(rv)) { 3234 ESW_REGEX_UNLOCK(unit); 3235 return (rv); 3236 } 3237 3238 /* Write the Policy entry */ 3239 if (dirty) { 3240 rv = _regex_policy_install(unit, policy); 3241 } else { 3242 rv = BCM_E_NONE; 3243 } 3244 3245 #ifdef BCM_WARM_BOOT_SUPPORT 3246 SOC_CONTROL_LOCK(unit); 3247 SOC_CONTROL(unit)->scache_dirty = 1; 3248 SOC_CONTROL_UNLOCK(unit); 3249 #endif 3250 3251 ESW_REGEX_UNLOCK(unit); 3252 return rv; 3253 } 3254 3255 /* 3256 * Function: 3257 * bcm_esw_regex_policy_remove 3258 * Purpose: 3259 * Remove a regex policy from the hardware tables. 3260 * Parameters: 3261 * unit - (IN) Unit number. 3262 * policy - (IN) ID of policy to be removed. 3263 * Returns: 3264 * BCM_E_xxx 3265 * Notes: 3266 */ 3267 int bcm_esw_regex_policy_remove(int unit, bcm_regex_policy_t policy) 3268 { 3269 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3270 int rv; /* Operation return status. */ 3271 3272 if (!soc_feature(unit, soc_feature_regex)) { 3273 return BCM_E_UNAVAIL; 3274 } 3275 3276 /* Get the device info structure. */ 3277 device = ESW_REGEX_INFO(unit); 3278 if (NULL == device) { 3279 return BCM_E_INIT; 3280 } 3281 3282 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3283 return BCM_E_PARAM; 3284 } 3285 3286 LOG_DEBUG(BSL_LS_BCM_REGEX, 3287 (BSL_META_U(unit, 3288 "FT(unit %d) vverb: %s()\n"), 3289 unit, FUNCTION_NAME())); 3290 3291 ESW_REGEX_LOCK(unit); 3292 3293 rv = _regex_policy_remove(unit, policy); 3294 3295 #ifdef BCM_WARM_BOOT_SUPPORT 3296 SOC_CONTROL_LOCK(unit); 3297 SOC_CONTROL(unit)->scache_dirty = 1; 3298 SOC_CONTROL_UNLOCK(unit); 3299 #endif 3300 3301 ESW_REGEX_UNLOCK(unit); 3302 return (rv); 3303 } 3304 3305 /* 3306 * Function: 3307 * bcm_esw_regex_policy_action_add 3308 * Purpose: 3309 * Add an action to a regex policy. 3310 * Parameters: 3311 * unit - (IN) Unit number. 3312 * policy - (IN) ID of policy to be modified. 3313 * action - (IN) Field processor action value 3314 * param0 - (IN) Action-dependent value; 0 if not used 3315 * param1 - (IN) Action-dependent value; 0 if not used 3316 * Returns: 3317 * BCM_E_xxx 3318 * Notes: 3319 */ 3320 int bcm_esw_regex_policy_action_add(int unit, bcm_regex_policy_t policy, 3321 bcm_field_action_t action, uint32 param0, uint32 param1) 3322 { 3323 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3324 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 3325 int rv; 3326 3327 if (!soc_feature(unit, soc_feature_regex)) { 3328 return BCM_E_UNAVAIL; 3329 } 3330 3331 /* Get the device info structure. */ 3332 device = ESW_REGEX_INFO(unit); 3333 if (NULL == device) { 3334 return BCM_E_INIT; 3335 } 3336 3337 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3338 return BCM_E_PARAM; 3339 } 3340 3341 LOG_DEBUG(BSL_LS_BCM_REGEX, 3342 (BSL_META_U(unit, 3343 "FT(unit %d) vverb: %s(policy=%d, action=%s, p0=%d, p1=%d)\n"), 3344 unit, FUNCTION_NAME(), policy, 3345 _regex_policy_action_name(action), param0, param1)); 3346 3347 if ((SOC_PORT_ADDR_MAX(unit) > 31) && 3348 ((action == bcmFieldActionRedirectPbmp) || 3349 (action == bcmFieldActionEgressMask) || 3350 (action == bcmFieldActionEgressPortsAdd) || 3351 (action == bcmFieldActionRedirectBcastPbmp))) { 3352 LOG_ERROR(BSL_LS_BCM_REGEX, 3353 (BSL_META_U(unit, 3354 "FT(unit %d) Error: Use bcm_regex_policy_action_ports_add api.\n"), 3355 unit)); 3356 return (BCM_E_PARAM); 3357 } 3358 3359 /* Adapt action parameters */ 3360 rv = _regex_policy_params_api_to_hw_adapt(unit, action, ¶m0, ¶m1); 3361 BCM_IF_ERROR_RETURN(rv); 3362 3363 ESW_REGEX_LOCK(unit); 3364 3365 /* 3366 * Allocate the action descriptor, param2 and param3 are not valid here. 3367 */ 3368 rv = _regex_policy_action_alloc(unit, action, param0, param1, 0, 0, &pa); 3369 if (BCM_FAILURE(rv)) { 3370 LOG_ERROR(BSL_LS_BCM_REGEX, 3371 (BSL_META_U(unit, 3372 "FT(unit %d) Error: failure in _regex_policy_action_alloc()\n"), 3373 unit)); 3374 ESW_REGEX_UNLOCK(unit); 3375 return rv; 3376 } 3377 3378 /* 3379 * Add action to entry actions list. 3380 */ 3381 rv = _regex_policy_action_add(unit, policy, pa); 3382 ESW_REGEX_UNLOCK(unit); 3383 if (BCM_FAILURE(rv)) { 3384 sal_free(pa); 3385 return rv; 3386 } 3387 return (BCM_E_NONE); 3388 } 3389 3390 /* 3391 * Function: 3392 * bcm_esw_regex_policy_action_mac_add 3393 * Purpose: 3394 * Add an action to a policy. 3395 * Parameters: 3396 * unit - (IN) Unit number. 3397 * policy - (IN) Regex policy Id. 3398 * action - (IN) Field action value 3399 * mac - (IN) MAC address for actions involving src/dst MAC. 3400 * Returns: 3401 * BCM_E_xxx 3402 * Notes: 3403 */ 3404 int bcm_esw_regex_policy_action_mac_add(int unit, 3405 bcm_regex_policy_t policy, 3406 bcm_field_action_t action, 3407 bcm_mac_t mac) 3408 { 3409 uint32 param[_FT_ACTION_PARAM_SZ]; 3410 3411 if (!soc_feature(unit, soc_feature_regex)) { 3412 return BCM_E_UNAVAIL; 3413 } 3414 3415 if ((action != bcmFieldActionSrcMacNew) && 3416 (action != bcmFieldActionDstMacNew)) { 3417 return (BCM_E_PARAM); 3418 } 3419 3420 SAL_MAC_ADDR_TO_UINT32(mac, param); 3421 3422 return bcm_esw_regex_policy_action_add(unit, policy, action, 3423 param[0],param[1]); 3424 } 3425 3426 /* 3427 * Function: 3428 * bcm_esw_regex_policy_action_ports_add 3429 * Purpose: 3430 * Add an action to a regex policy. 3431 * Parameters: 3432 * unit - (IN) Unit number. 3433 * policy - (IN) regex policy ID 3434 * action - (IN) Field action value 3435 * pbmp - (IN) pbmp for actions involving port bitmap 3436 * Returns: 3437 * BCM_E_xxx 3438 * Notes: 3439 */ 3440 int bcm_esw_regex_policy_action_ports_add(int unit, 3441 bcm_regex_policy_t policy, 3442 bcm_field_action_t action, 3443 bcm_pbmp_t pbmp) 3444 { 3445 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3446 uint32 param[_FT_ACTION_PARAM_SZ]; 3447 3448 if (!soc_feature(unit, soc_feature_regex)) { 3449 return BCM_E_UNAVAIL; 3450 } 3451 3452 /* Get the device info structure. */ 3453 device = ESW_REGEX_INFO(unit); 3454 if (NULL == device) { 3455 return BCM_E_INIT; 3456 } 3457 3458 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3459 return BCM_E_PARAM; 3460 } 3461 3462 if ((action != bcmFieldActionRedirectPbmp) && 3463 (action != bcmFieldActionEgressMask) && 3464 (action != bcmFieldActionEgressPortsAdd) && 3465 (action != bcmFieldActionRedirectBcastPbmp)) { 3466 LOG_ERROR(BSL_LS_BCM_REGEX, 3467 (BSL_META_U(unit, 3468 "FT(unit %d) Error: Incorrect action parameter\n"), 3469 unit)); 3470 return (BCM_E_PARAM); 3471 } 3472 3473 sal_memset(¶m, 0, sizeof(param)); 3474 3475 param[0] = SOC_PBMP_WORD_GET(pbmp, 0); 3476 if (soc_feature(unit, soc_feature_table_hi)) { 3477 param[1] = SOC_PBMP_WORD_GET(pbmp, 1); 3478 /* Trident device can support more than 64-ports */ 3479 if (SOC_IS_TD_TT(unit)) { 3480 param[2] = SOC_PBMP_WORD_GET(pbmp, 2); 3481 } 3482 /* Trident2 device can support more than 96-ports */ 3483 if (SOC_IS_TD2_TT2(unit)) { 3484 param[3] = SOC_PBMP_WORD_GET(pbmp, 3); 3485 param[3] &= 0x3ff; /* TD2 has 106 ports */ 3486 } 3487 } 3488 3489 return _regex_policy_action_ports_add(unit, policy, action, 3490 param[0], param[1], 3491 param[2], param[3]); 3492 } 3493 3494 /* 3495 * Function: 3496 * bcm_esw_regex_policy_action_delete 3497 * Purpose: 3498 * Delete an action from a regex policy. 3499 * Parameters: 3500 * unit - (IN) Unit number. 3501 * policy - (IN) ID of policy to be modified. 3502 * action - (IN) Field processor action value 3503 * param0 - (IN) Action-dependent value; 0 if not used 3504 * param1 - (IN) Action-dependent value; 0 if not used 3505 * Returns: 3506 * BCM_E_xxx 3507 * Notes: 3508 */ 3509 int bcm_esw_regex_policy_action_delete(int unit, 3510 bcm_regex_policy_t policy, 3511 bcm_field_action_t action, 3512 uint32 param0, 3513 uint32 param1) 3514 { 3515 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3516 int rv; /* Operation return status. */ 3517 3518 if (!soc_feature(unit, soc_feature_regex)) { 3519 return BCM_E_UNAVAIL; 3520 } 3521 3522 if (action < 0 || bcmFieldActionCount <= action) { 3523 LOG_ERROR(BSL_LS_BCM_REGEX, 3524 (BSL_META_U(unit, 3525 "FT(unit %d) Error: unknown action=%d\n"), 3526 unit, action)); 3527 return (BCM_E_PARAM); 3528 } 3529 3530 /* Get the device info structure. */ 3531 device = ESW_REGEX_INFO(unit); 3532 if (NULL == device) { 3533 return BCM_E_INIT; 3534 } 3535 3536 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3537 return BCM_E_PARAM; 3538 } 3539 3540 /* Adapt action parameters */ 3541 rv = _regex_policy_params_api_to_hw_adapt(unit, action, ¶m0, ¶m1); 3542 BCM_IF_ERROR_RETURN(rv); 3543 3544 ESW_REGEX_LOCK(unit); 3545 3546 rv = _regex_policy_action_delete(unit, policy, action, param0, param1); 3547 3548 ESW_REGEX_UNLOCK(unit); 3549 return rv; 3550 } 3551 3552 /* 3553 * Function: 3554 * bcm_esw_regex_policy_action_get 3555 * Purpose: 3556 * Retrieve the parameters for an action previously added to a 3557 * regex policy. 3558 * Parameters: 3559 * unit - (IN) Unit number. 3560 * policy - (IN) regex policy ID. 3561 * action - (IN) Field processor action value 3562 * param0 - (OUT) Action-dependent value 3563 * param1 - (OUT) Action-dependent value 3564 * Returns: 3565 * BCM_E_xxx 3566 * Notes: 3567 */ 3568 int bcm_esw_regex_policy_action_get(int unit, 3569 bcm_regex_policy_t policy, 3570 bcm_field_action_t action, 3571 uint32 *param0, 3572 uint32 *param1) 3573 { 3574 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3575 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 3576 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 3577 int rv; 3578 3579 if (!soc_feature(unit, soc_feature_regex)) { 3580 return BCM_E_UNAVAIL; 3581 } 3582 3583 /* Input parameters check. */ 3584 if ((NULL == param0) || (NULL == param1)) { 3585 return (BCM_E_PARAM); 3586 } 3587 3588 /* Get the device info structure. */ 3589 device = ESW_REGEX_INFO(unit); 3590 if (NULL == device) { 3591 return BCM_E_INIT; 3592 } 3593 3594 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3595 return BCM_E_PARAM; 3596 } 3597 3598 /* Lock the module. */ 3599 ESW_REGEX_LOCK(unit); 3600 3601 rv = _regex_policy_get(unit, policy, &p_ent); 3602 if (BCM_FAILURE(rv)) { 3603 ESW_REGEX_UNLOCK(unit); 3604 return (rv); 3605 } 3606 3607 if (bcmFieldActionColorIndependent == action) { 3608 *param0 = (p_ent->flags & _REGEX_POLICY_COLOR_INDEPENDENT) ? 1 : 0; 3609 *param1 = 0; 3610 /* Unlock the module. */ 3611 ESW_REGEX_UNLOCK(unit); 3612 return (BCM_E_NONE); 3613 } 3614 3615 /* Find matching action in the entry */ 3616 for (pa = p_ent->actions; pa != NULL; pa = pa->next) { 3617 if (pa->action == action) { 3618 break; 3619 } 3620 } 3621 3622 if (pa == NULL) { 3623 ESW_REGEX_UNLOCK(unit); 3624 LOG_DEBUG(BSL_LS_BCM_REGEX, 3625 (BSL_META_U(unit, 3626 "FT(unit %d) Error: action not in policy=%d\n"), 3627 unit, policy)); 3628 return (BCM_E_NOT_FOUND); 3629 } 3630 3631 *param0 = pa->param[0]; 3632 *param1 = pa->param[1]; 3633 3634 /* Unlock the module. */ 3635 ESW_REGEX_UNLOCK(unit); 3636 3637 /* Adapt action parameters */ 3638 rv = _regex_policy_params_hw_to_api_adapt(unit, action, param0, param1); 3639 return (rv); 3640 } 3641 3642 /* 3643 * Function: 3644 * bcm_esw_regex_policy_action_mac_get 3645 * Purpose: 3646 * Retrieve the parameters for an action previously added to a 3647 * regex policy. 3648 * Parameters: 3649 * unit - (IN) Unit number. 3650 * policy - (IN) Regex policy ID. 3651 * action - (IN) Field action value. 3652 * mac - (OUT) MAC address for actions involving src/dst MAC. 3653 * Returns: 3654 * BCM_E_xxx 3655 * Notes: 3656 */ 3657 int bcm_esw_regex_policy_action_mac_get(int unit, 3658 bcm_regex_policy_t policy, 3659 bcm_field_action_t action, 3660 bcm_mac_t *mac) 3661 { 3662 uint32 param[_FT_ACTION_PARAM_SZ]; 3663 int rv; 3664 3665 if (!soc_feature(unit, soc_feature_regex)) { 3666 return BCM_E_UNAVAIL; 3667 } 3668 3669 /* Input parameter check. */ 3670 if (NULL == mac) { 3671 return (BCM_E_PARAM); 3672 } 3673 3674 if ((action != bcmFieldActionSrcMacNew) && 3675 (action != bcmFieldActionDstMacNew)) { 3676 return (BCM_E_PARAM); 3677 } 3678 3679 /* Extract action information from field entry. */ 3680 rv = bcm_esw_regex_policy_action_get(unit, policy, action, 3681 param, param + 1); 3682 BCM_IF_ERROR_RETURN(rv); 3683 3684 SAL_MAC_ADDR_FROM_UINT32((*mac), param); 3685 return (BCM_E_NONE); 3686 } 3687 3688 /* 3689 * Function: 3690 * bcm_esw_regex_policy_action_ports_get 3691 * Purpose: 3692 * Retrieve the parameters for an action previously added to a 3693 * regex policy. 3694 * Parameters: 3695 * unit - (IN) Unit number. 3696 * policy - (IN) Regex policy ID 3697 * action - (IN) Field action value 3698 * pbmp - (OUT) pbmp for actions involving port bitmap 3699 * Returns: 3700 * BCM_E_xxx 3701 * Notes: 3702 */ 3703 int bcm_esw_regex_policy_action_ports_get(int unit, 3704 bcm_regex_policy_t policy, 3705 bcm_field_action_t action, 3706 bcm_pbmp_t *pbmp) 3707 { 3708 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3709 uint32 param[_FT_ACTION_PARAM_SZ]; 3710 int rv; 3711 3712 if (!soc_feature(unit, soc_feature_regex)) { 3713 return BCM_E_UNAVAIL; 3714 } 3715 3716 /* Get the device info structure. */ 3717 device = ESW_REGEX_INFO(unit); 3718 if (NULL == device) { 3719 return BCM_E_INIT; 3720 } 3721 3722 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3723 return BCM_E_PARAM; 3724 } 3725 3726 /* Input parameter check. */ 3727 if (NULL == pbmp) { 3728 return (BCM_E_PARAM); 3729 } 3730 3731 if ((action != bcmFieldActionRedirectPbmp) && 3732 (action != bcmFieldActionEgressMask) && 3733 (action != bcmFieldActionRedirectBcastPbmp) && 3734 (action != bcmFieldActionEgressPortsAdd)) { 3735 return (BCM_E_PARAM); 3736 } 3737 3738 sal_memset(param, 0, sizeof(param)); 3739 3740 /* Extract action information from policy entry. */ 3741 rv = _regex_policy_action_ports_get(unit, policy, action, 3742 param, param + 1, param + 2, param + 3); 3743 BCM_IF_ERROR_RETURN(rv); 3744 3745 BCM_PBMP_CLEAR(*pbmp); 3746 SOC_PBMP_WORD_SET(*pbmp, 0, param[0]); 3747 3748 #if defined(BCM_TRIUMPH_SUPPORT) 3749 if (soc_feature(unit, soc_feature_table_hi)) { 3750 SOC_PBMP_WORD_SET(*pbmp, 1, param[1]); 3751 if (SOC_IS_TD_TT(unit)) { 3752 SOC_PBMP_WORD_SET(*pbmp, 2, param[2]); 3753 } 3754 if (SOC_IS_TD2_TT2(unit)) { 3755 SOC_PBMP_WORD_SET(*pbmp, 3, param[3]); 3756 } 3757 } 3758 #endif /* BCM_TRIUMPH_SUPPORT */ 3759 return (BCM_E_NONE); 3760 } 3761 3762 /* 3763 * Function: 3764 * bcm_esw_regex_policy_action_remove 3765 * Purpose: 3766 * Remove an action from a regex_policy. Same as 3767 * bcm_esw_regex_policy_action_delete for actions without parameters. 3768 * Parameters: 3769 * unit - (IN) Unit number. 3770 * policy - (IN) ID of policy to be modified. 3771 * action - (IN) Field processor action value 3772 * Returns: 3773 * BCM_E_xxx 3774 * Notes: 3775 */ 3776 int bcm_esw_regex_policy_action_remove(int unit, 3777 bcm_regex_policy_t policy, 3778 bcm_field_action_t action) 3779 { 3780 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3781 int rv; /* Operation return status. */ 3782 3783 if (!soc_feature(unit, soc_feature_regex)) { 3784 return BCM_E_UNAVAIL; 3785 } 3786 3787 /* Get the device info structure. */ 3788 device = ESW_REGEX_INFO(unit); 3789 if (NULL == device) { 3790 return BCM_E_INIT; 3791 } 3792 3793 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3794 return BCM_E_PARAM; 3795 } 3796 3797 /* Lock the module. */ 3798 ESW_REGEX_LOCK(unit); 3799 3800 rv = bcm_esw_regex_policy_action_delete(unit, policy, action, 3801 (uint32)_REGEX_INVALID_INDEX, 3802 (uint32)_REGEX_INVALID_INDEX); 3803 ESW_REGEX_UNLOCK(unit); 3804 return (rv); 3805 } 3806 3807 /* 3808 * Function: 3809 * bcm_esw_regex_policy_action_remove_all 3810 * Purpose: 3811 * Remove all actions from a regex_policy. 3812 * Parameters: 3813 * unit - (IN) Unit number. 3814 * policy - (IN) ID of policy to be modified. 3815 * Returns: 3816 * BCM_E_xxx 3817 * Notes: 3818 */ 3819 int bcm_esw_regex_policy_action_remove_all(int unit, 3820 bcm_regex_policy_t policy) 3821 { 3822 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3823 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 3824 _regex_policy_action_t *pa = NULL; /* Policy action descriptor. */ 3825 int rv; /* Operation return status. */ 3826 3827 if (!soc_feature(unit, soc_feature_regex)) { 3828 return BCM_E_UNAVAIL; 3829 } 3830 3831 /* Get the device info structure. */ 3832 device = ESW_REGEX_INFO(unit); 3833 if (NULL == device) { 3834 return BCM_E_INIT; 3835 } 3836 3837 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 3838 return BCM_E_PARAM; 3839 } 3840 3841 /* Lock the module. */ 3842 ESW_REGEX_LOCK(unit); 3843 3844 rv = _regex_policy_get(unit, policy, &p_ent); 3845 if (BCM_FAILURE(rv)) { 3846 ESW_REGEX_UNLOCK(unit); 3847 return (rv); 3848 } 3849 3850 /* start at the head of the actions list and burn them up */ 3851 pa = p_ent->actions; 3852 3853 while (pa != NULL) { 3854 rv = _regex_policy_action_delete(unit, policy, pa->action, 3855 pa->param[0], pa->param[1]); 3856 if (BCM_FAILURE(rv)) { 3857 ESW_REGEX_UNLOCK(unit); 3858 return (rv); 3859 } 3860 3861 /* 3862 * Action might be removed from the entry actions 3863 * list only if entry was not installed. 3864 * Otherwise clean up will happen during reinstall. 3865 */ 3866 pa = (p_ent->flags & _REGEX_POLICY_INSTALLED) ? pa->next : p_ent->actions; 3867 } 3868 3869 p_ent->flags |= _REGEX_POLICY_DIRTY; 3870 3871 ESW_REGEX_UNLOCK(unit); 3872 return (rv); 3873 } 3874 3875 /* 3876 * Function: 3877 * _bcm_regex_policer_get 3878 * Purpose: 3879 * Lookup a Policer description structure by policer id. 3880 * Parmeters: 3881 * unit - (IN)BCM device number. 3882 * pid - (IN)Policer id. 3883 * policer_p - (OUT) Policer lookup result. 3884 * Returns: 3885 * BCM_E_XXX 3886 */ 3887 int _bcm_regex_policer_get(int unit, bcm_policer_t pid, 3888 _field_policer_t **policer_p) 3889 { 3890 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3891 _field_policer_t *f_pl; /* Policer lookup pointer. */ 3892 3893 /* Input parameters check. */ 3894 if (NULL == policer_p) { 3895 return (BCM_E_PARAM); 3896 } 3897 3898 /* Get the device info structure. */ 3899 device = ESW_REGEX_INFO(unit); 3900 if (NULL == device) { 3901 return BCM_E_INIT; 3902 } 3903 3904 f_pl = device->policers[_REGEX_POLICER_ID_TO_INDEX(pid)]; 3905 if (NULL != f_pl) { 3906 *policer_p = f_pl; 3907 return (BCM_E_NONE); 3908 } 3909 3910 /* Policer with pid == pid was not found. */ 3911 return (BCM_E_NOT_FOUND); 3912 } 3913 3914 /* 3915 * Function: 3916 * _bcm_esw_regex_policer_destroy 3917 * Purpose: 3918 * Destroy a policer entry. 3919 * Parameters: 3920 * unit - (IN) Unit number. 3921 * policer_id - (IN) Policer ID. 3922 * Returns: 3923 * BCM_E_XXX 3924 * Notes: 3925 */ 3926 int _regex_policer_destroy(int unit, bcm_policer_t pid) 3927 { 3928 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3929 _field_policer_t *f_pl; /* Internal policer descriptor. */ 3930 int rv; /* Operation return status. */ 3931 3932 /* Get the device info structure. */ 3933 device = ESW_REGEX_INFO(unit); 3934 if (NULL == device) { 3935 return BCM_E_INIT; 3936 } 3937 3938 /* Find policer info. */ 3939 rv = _bcm_regex_policer_get(unit, pid, &f_pl); 3940 if (BCM_FAILURE(rv)) { 3941 return (rv); 3942 } 3943 3944 /* Reject destroy if policer is in use. */ 3945 if (f_pl->sw_ref_count > 1) { 3946 return (BCM_E_BUSY); 3947 } 3948 3949 /* Remove policer from policers table. */ 3950 device->policers[_REGEX_POLICER_ID_TO_INDEX(pid)] = NULL; 3951 3952 /* De-allocate policer descriptor. */ 3953 sal_free(f_pl); 3954 3955 return (BCM_E_NONE); 3956 } 3957 3958 /* 3959 * Function: 3960 * _regex_policer_id_alloc 3961 * Purpose: 3962 * Allocate a policer id. 3963 * Parameters: 3964 * unit - (IN) BCM device number. 3965 * pid - (OUT) Policer id. 3966 * Returns: 3967 * BCM_E_XXX 3968 * Notes: 3969 */ 3970 int _regex_policer_id_alloc(int unit, bcm_policer_t *pid) 3971 { 3972 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 3973 int i; 3974 3975 /* Get the device info structure. */ 3976 device = ESW_REGEX_INFO(unit); 3977 if (NULL == device) { 3978 return BCM_E_INIT; 3979 } 3980 /* Input parameters check. */ 3981 if (NULL == pid) { 3982 return (BCM_E_PARAM); 3983 } 3984 3985 for (i = 0; i < _REGEX_POLICER_MAX_NUM; i++) { 3986 if (NULL == device->policers[i]) { 3987 *pid = _REGEX_POLICER_ID_ENCODE(unit, i); 3988 return BCM_E_NONE; 3989 } 3990 } 3991 return (BCM_E_RESOURCE); 3992 } 3993 3994 /* 3995 * Function: 3996 * _bcm_esw_regex_policer_create 3997 * Purpose: 3998 * Initialize a policer entry. 3999 * Parameters: 4000 * unit - (IN) BCM device number. 4001 * pol_cfg - (IN) Policer configuration. 4002 * pid - (OUT) Policer id. 4003 * Returns: 4004 * BCM_E_XXX 4005 * Notes: 4006 */ 4007 int _bcm_esw_regex_policer_create(int unit, bcm_policer_config_t *pol_cfg, 4008 bcm_policer_t *pid) 4009 { 4010 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4011 _field_policer_t *f_pl = NULL; /* Internal policer descriptor. */ 4012 int rv; /* Operation return status. */ 4013 4014 if (!soc_feature(unit, soc_feature_regex)) { 4015 return BCM_E_UNAVAIL; 4016 } 4017 4018 /* Get the device info structure. */ 4019 device = ESW_REGEX_INFO(unit); 4020 if (NULL == device) { 4021 return BCM_E_INIT; 4022 } 4023 4024 /* Input parameters check. */ 4025 if (NULL == pol_cfg) { 4026 return (BCM_E_PARAM); 4027 } 4028 4029 /* Lock the module. */ 4030 ESW_REGEX_LOCK(unit); 4031 4032 /* Generate policer id. */ 4033 if (0 == (pol_cfg->flags & BCM_POLICER_WITH_ID)) { 4034 rv = _regex_policer_id_alloc(unit, pid); 4035 if (BCM_FAILURE(rv)) { 4036 ESW_REGEX_UNLOCK(unit); 4037 return rv; 4038 } 4039 } else { 4040 /* Check if policer id is already in use. */ 4041 rv = _bcm_regex_policer_get(unit, *pid, &f_pl); 4042 if (BCM_SUCCESS(rv)) { 4043 4044 /* Verify that replace flag is set. */ 4045 if (0 == (pol_cfg->flags & BCM_POLICER_REPLACE)) { 4046 ESW_REGEX_UNLOCK(unit); 4047 return (BCM_E_EXISTS); 4048 } 4049 4050 /* Make sure policer is not attached to any entry. */ 4051 if (1 != f_pl->sw_ref_count) { 4052 ESW_REGEX_UNLOCK(unit); 4053 return (BCM_E_BUSY); 4054 } 4055 /* Copy new configuration. */ 4056 sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(f_pl->cfg)); 4057 4058 /* Set policer "dirty" flag and return. */ 4059 rv = _regex_policer_hw_flags_set(unit, f_pl, 0); 4060 ESW_REGEX_UNLOCK(unit); 4061 return (rv); 4062 } 4063 } 4064 4065 /* Allocate policer descriptor. */ 4066 f_pl = sal_alloc(sizeof(*f_pl), "Regex policer"); 4067 if (NULL == f_pl) { 4068 ESW_REGEX_UNLOCK(unit); 4069 return (BCM_E_MEMORY); 4070 } 4071 4072 /* Copy policer configuration. */ 4073 sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(f_pl->cfg)); 4074 4075 /* Set policer "dirty" flags. */ 4076 rv = _regex_policer_hw_flags_set(unit, f_pl, 0); 4077 if (BCM_FAILURE(rv)) { 4078 sal_free(f_pl); 4079 ESW_REGEX_UNLOCK(unit); 4080 return (rv); 4081 } 4082 4083 /* Initialize reference count to 1. */ 4084 f_pl->sw_ref_count = 1; 4085 4086 /* Set hw index to - no hw resources allocated. */ 4087 f_pl->hw_index = _FP_INVALID_INDEX; 4088 4089 /* Initialize policer id. */ 4090 f_pl->pid = *pid; 4091 4092 /* Insert policer into policers table. */ 4093 device->policers[_REGEX_POLICER_ID_TO_INDEX(*pid)] = f_pl; 4094 4095 ESW_REGEX_UNLOCK(unit); 4096 return (BCM_E_NONE); 4097 } 4098 4099 /* 4100 * Function: 4101 * _bcm_esw_regex_policer_destroy 4102 * Purpose: 4103 * Destroy a policer entry. 4104 * Parameters: 4105 * unit - (IN) Unit number. 4106 * policer_id - (IN) Policer ID. 4107 * Returns: 4108 * BCM_E_XXX 4109 * Notes: 4110 */ 4111 int _bcm_esw_regex_policer_destroy(int unit, bcm_policer_t pid) 4112 { 4113 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4114 int rv = BCM_E_NONE; /* Operation return status. */ 4115 4116 if (!soc_feature(unit, soc_feature_regex)) { 4117 return BCM_E_UNAVAIL; 4118 } 4119 4120 /* Get the device info structure. */ 4121 device = ESW_REGEX_INFO(unit); 4122 if (NULL == device) { 4123 return BCM_E_INIT; 4124 } 4125 4126 /* Lock the module. */ 4127 ESW_REGEX_LOCK(unit); 4128 4129 /* Destroy policer. */ 4130 rv = _regex_policer_destroy(unit, pid); 4131 4132 ESW_REGEX_UNLOCK(unit); 4133 4134 return rv; 4135 } 4136 4137 /* 4138 * Function: 4139 * bcm_policer_destroy_all 4140 * Purpose: 4141 * Destroy all policer entries. 4142 * Parameters: 4143 * unit - (IN) Unit number. 4144 * Returns: 4145 * BCM_E_XXX 4146 * Notes: 4147 */ 4148 int _bcm_esw_regex_policer_destroy_all(int unit) 4149 { 4150 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4151 int rv = BCM_E_NONE; /* Operation return status. */ 4152 int idx; 4153 4154 if (!soc_feature(unit, soc_feature_regex)) { 4155 return BCM_E_UNAVAIL; 4156 } 4157 4158 /* Get the device info structure. */ 4159 device = ESW_REGEX_INFO(unit); 4160 if (NULL == device) { 4161 return BCM_E_INIT; 4162 } 4163 4164 /* Lock the module. */ 4165 ESW_REGEX_LOCK(unit); 4166 4167 /* Iterate over all entries. */ 4168 for (idx = 0; idx < sizeof(device->policers)/sizeof(device->policers[0]); idx++) { 4169 if (NULL != device->policers[idx]) { 4170 rv = _regex_policer_destroy(unit, device->policers[idx]->pid); 4171 if (BCM_FAILURE(rv)) { 4172 break; 4173 } 4174 } 4175 } 4176 4177 ESW_REGEX_UNLOCK(unit); 4178 4179 return (rv); 4180 } 4181 4182 /* 4183 * Function: 4184 * bcm_policer_traverse 4185 * Purpose: 4186 * Traverse all existing policer entries and call supplied 4187 * callback function. 4188 * Parameters: 4189 * unit - (IN) Unit number. 4190 * cb - (IN) Callback function. 4191 * user_data - (IN) User data. 4192 * Returns: 4193 * BCM_E_XXX 4194 * Notes: 4195 * To speed up traverse operation - no hw read is perfomed. 4196 */ 4197 int _bcm_esw_regex_policer_traverse(int unit, bcm_policer_traverse_cb cb, 4198 void *user_data) 4199 { 4200 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4201 bcm_policer_config_t cfg; /* Policer configuration. */ 4202 int rv = BCM_E_NONE; /* Operation return status. */ 4203 int idx; 4204 4205 if (!soc_feature(unit, soc_feature_regex)) { 4206 return BCM_E_UNAVAIL; 4207 } 4208 4209 /* Get the device info structure. */ 4210 device = ESW_REGEX_INFO(unit); 4211 if (NULL == device) { 4212 return BCM_E_INIT; 4213 } 4214 4215 /* Lock the module. */ 4216 ESW_REGEX_LOCK(unit); 4217 4218 /* Iterate over all entries. */ 4219 for (idx = 0; idx < sizeof(device->policers)/sizeof(device->policers[0]); idx++) { 4220 if (NULL != device->policers[idx]) { 4221 sal_memcpy(&cfg, &device->policers[idx]->cfg, sizeof(cfg)); 4222 rv = (*cb)(unit, device->policers[idx]->pid, &cfg, user_data); 4223 if (BCM_FAILURE(rv)) { 4224 break; 4225 } 4226 } 4227 } 4228 4229 ESW_REGEX_UNLOCK(unit); 4230 4231 return (rv); 4232 } 4233 4234 /* 4235 * Function: 4236 * _regex_policy_policer_detach 4237 * Purpose: 4238 * Detach a policer from a regex policy 4239 * Parameters: 4240 * unit - (IN) Unit number. 4241 * p_ent - (IN) Regex policy structure. 4242 * level - (IN) Policer level. 4243 * Returns: 4244 * BCM_E_XXX 4245 * Notes: 4246 */ 4247 STATIC int _regex_policy_policer_detach(int unit, _regex_policy_t *p_ent, int level) 4248 { 4249 _field_policer_t *f_pl; /* Internal policer descriptor. */ 4250 _field_entry_policer_t *f_ent_pl;/* Field entry policer structure.*/ 4251 4252 /* Make sure policer attached to the entry. */ 4253 f_ent_pl = p_ent->policer + level; 4254 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 4255 return (BCM_E_EMPTY); 4256 } 4257 4258 /* Get policer description structure. */ 4259 BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl)); 4260 4261 /* If entry was installed decrement hw reference counter. */ 4262 BCM_IF_ERROR_RETURN(_regex_policer_hw_free(unit, level, p_ent)); 4263 4264 /* Decrement policer reference counter. */ 4265 f_pl->sw_ref_count--; 4266 4267 /* If no one else is using the policer and 4268 * policer is internal destroy it. 4269 */ 4270 if ((1 == f_pl->sw_ref_count) && (f_pl->hw_flags & _FP_POLICER_INTERNAL)) { 4271 BCM_IF_ERROR_RETURN(_bcm_esw_regex_policer_destroy(unit, f_ent_pl->pid)); 4272 } 4273 4274 /* Detach policer from an entry. */ 4275 f_ent_pl->pid = _FP_INVALID_INDEX; 4276 f_ent_pl->flags = 0; 4277 4278 /* Mark entry for reinstall. */ 4279 p_ent->flags |= _FP_ENTRY_DIRTY; 4280 4281 return (BCM_E_NONE); 4282 } 4283 4284 /* 4285 * Function: 4286 * bcm_esw_regex_policy_policer_attach 4287 * Purpose: 4288 * Attach a policer to a regex policy. 4289 * Parameters: 4290 * unit - (IN) Unit number. 4291 * policy - (IN) Regex policy ID. 4292 * level - (IN) Policer level. 4293 * policer_id - (IN) Policer ID. 4294 * Returns: 4295 * BCM_E_xxx 4296 * Notes: 4297 */ 4298 int bcm_esw_regex_policy_policer_attach(int unit, 4299 bcm_regex_policy_t policy, 4300 int level, 4301 bcm_policer_t policer_id) 4302 { 4303 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4304 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 4305 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 4306 _field_policer_t *f_pl; /* Internal policer descriptor. */ 4307 int idx; /* Entry policers iterator. */ 4308 int rv; /* Operation return status. */ 4309 4310 if (!soc_feature(unit, soc_feature_regex)) { 4311 return BCM_E_UNAVAIL; 4312 } 4313 4314 /* Input parameters check. */ 4315 if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) { 4316 return (BCM_E_PARAM); 4317 } 4318 4319 if (!BCM_POLICER_IS_REGEX_METER(policer_id)) { 4320 return (BCM_E_PARAM); 4321 } 4322 4323 /* Get the device info structure. */ 4324 device = ESW_REGEX_INFO(unit); 4325 if (NULL == device) { 4326 return BCM_E_INIT; 4327 } 4328 4329 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 4330 return BCM_E_PARAM; 4331 } 4332 4333 /* Lock the module. */ 4334 ESW_REGEX_LOCK(unit); 4335 4336 /* Get policy description structure. */ 4337 rv = _regex_policy_get(unit, policy, &p_ent); 4338 if (BCM_FAILURE(rv)) { 4339 ESW_REGEX_UNLOCK(unit); 4340 return (rv); 4341 } 4342 4343 /* Check if another policer already attached at this level. */ 4344 f_ent_pl = p_ent->policer + level; 4345 if (f_ent_pl->flags & _FP_POLICER_VALID) { 4346 ESW_REGEX_UNLOCK(unit); 4347 return (BCM_E_EXISTS); 4348 } 4349 4350 /* Check if policer already attached to the entry. */ 4351 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 4352 f_ent_pl = p_ent->policer + idx; 4353 if (f_ent_pl->pid == policer_id) { 4354 ESW_REGEX_UNLOCK(unit); 4355 return (idx == level) ? (BCM_E_NONE) : (BCM_E_PARAM); 4356 } 4357 } 4358 4359 /* Get policer description structure. */ 4360 rv = _bcm_regex_policer_get(unit, policer_id, &f_pl); 4361 if (BCM_FAILURE(rv)) { 4362 ESW_REGEX_UNLOCK(unit); 4363 return (rv); 4364 } 4365 4366 /* Check that policer can be shared. */ 4367 if (f_pl->sw_ref_count > 1) { 4368 /* Policer sharing is restricted to a single level. */ 4369 if (level != f_pl->level) { 4370 ESW_REGEX_UNLOCK(unit); 4371 return (BCM_E_PARAM); 4372 } 4373 } 4374 4375 /* Increment policer reference counter. */ 4376 f_pl->sw_ref_count++; 4377 4378 /* Set policer attachment level. */ 4379 f_pl->level = level; 4380 4381 /* Attach policer to an entry. */ 4382 f_ent_pl = p_ent->policer + level; 4383 f_ent_pl->flags |= _FP_POLICER_VALID; 4384 f_ent_pl->pid = policer_id; 4385 4386 /* Entry must be reinstalled for policer to take effect. */ 4387 p_ent->flags |= _REGEX_POLICY_DIRTY; 4388 4389 ESW_REGEX_UNLOCK(unit); 4390 return (BCM_E_NONE); 4391 } 4392 4393 /* 4394 * Function: 4395 * bcm_esw_regex_policy_policer_detach 4396 * Purpose: 4397 * Detach a policer from a regex policy. 4398 * Parameters: 4399 * unit - (IN) Unit number. 4400 * policy - (IN) Regex policy ID. 4401 * level - (IN) Policer level. 4402 * Returns: 4403 * BCM_E_xxx 4404 * Notes: 4405 */ 4406 int bcm_esw_regex_policy_policer_detach(int unit, 4407 bcm_regex_policy_t policy, 4408 int level) 4409 { 4410 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4411 _regex_policy_t *p_ent; /* Allocated entry buffer. */ 4412 int rv; /* Operation return status. */ 4413 4414 if (!soc_feature(unit, soc_feature_regex)) { 4415 return BCM_E_UNAVAIL; 4416 } 4417 4418 /* Input parameters check. */ 4419 if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) { 4420 return (BCM_E_PARAM); 4421 } 4422 4423 /* Get the device info structure. */ 4424 device = ESW_REGEX_INFO(unit); 4425 if (NULL == device) { 4426 return BCM_E_INIT; 4427 } 4428 4429 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 4430 return BCM_E_PARAM; 4431 } 4432 4433 /* Lock the module. */ 4434 ESW_REGEX_LOCK(unit); 4435 4436 /* Get entry description structure. */ 4437 rv = _regex_policy_get(unit, policy, &p_ent); 4438 if (BCM_FAILURE(rv)) { 4439 ESW_REGEX_UNLOCK(unit); 4440 return (rv); 4441 } 4442 4443 rv = _regex_policy_policer_detach(unit, p_ent, level); 4444 4445 ESW_REGEX_UNLOCK(unit); 4446 return (rv); 4447 } 4448 4449 /* 4450 * Function: 4451 * bcm_esw_regex_policy_policer_detach_all 4452 * Purpose: 4453 * Detach all policers from a regex policy. 4454 * Parameters: 4455 * unit - (IN) Unit number. 4456 * policy - (IN) Regex policy ID. 4457 * Returns: 4458 * BCM_E_xxx 4459 * Notes: 4460 */ 4461 int bcm_esw_regex_policy_policer_detach_all(int unit, 4462 bcm_regex_policy_t policy) 4463 { 4464 int idx; /* Entry policers iterator. */ 4465 int rv = BCM_E_NONE; /* Operation return status. */ 4466 4467 if (!soc_feature(unit, soc_feature_regex)) { 4468 return BCM_E_UNAVAIL; 4469 } 4470 4471 /* Detach all the policers attached to an entry. */ 4472 for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) { 4473 rv = bcm_esw_regex_policy_policer_detach(unit, policy, idx); 4474 if (BCM_E_EMPTY == rv) { 4475 /* No policer at this level. */ 4476 rv = BCM_E_NONE; 4477 } else if (BCM_FAILURE(rv)) { 4478 break; 4479 } 4480 } 4481 return (rv); 4482 } 4483 4484 /* 4485 * Function: 4486 * bcm_esw_regex_policy_policer_get 4487 * Purpose: 4488 * Get the policer(s) attached to a regex policy. 4489 * Parameters: 4490 * unit - (IN) Unit number. 4491 * policy - (IN) Regex policy ID. 4492 * level - (IN) Policer level. 4493 * policer_id - (OUT) Policer ID. 4494 * Returns: 4495 * BCM_E_xxx 4496 * Notes: 4497 */ 4498 int bcm_esw_regex_policy_policer_get(int unit, 4499 bcm_regex_policy_t policy, 4500 int level, 4501 bcm_policer_t *policer_id) 4502 { 4503 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4504 _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/ 4505 _regex_policy_t *p_ent; /* Regex policy structure. */ 4506 int rv; /* Operation return status. */ 4507 4508 if (!soc_feature(unit, soc_feature_regex)) { 4509 return BCM_E_UNAVAIL; 4510 } 4511 4512 /* Input parameters check. */ 4513 if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) { 4514 return (BCM_E_PARAM); 4515 } 4516 4517 if (NULL == policer_id) { 4518 return (BCM_E_PARAM); 4519 } 4520 4521 /* Get the device info structure. */ 4522 device = ESW_REGEX_INFO(unit); 4523 if (NULL == device) { 4524 return BCM_E_INIT; 4525 } 4526 4527 if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) { 4528 return BCM_E_PARAM; 4529 } 4530 4531 /* Lock the module. */ 4532 ESW_REGEX_LOCK(unit); 4533 4534 /* Get entry description structure. */ 4535 rv = _regex_policy_get(unit, policy, &p_ent); 4536 if (BCM_FAILURE(rv)) { 4537 ESW_REGEX_UNLOCK(unit); 4538 return (rv); 4539 } 4540 4541 f_ent_pl = p_ent->policer + level; 4542 /* Make sure policer attached to the entry. */ 4543 if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) { 4544 rv = (BCM_E_NOT_FOUND); 4545 } else { 4546 *policer_id = f_ent_pl->pid; 4547 } 4548 4549 ESW_REGEX_UNLOCK(unit); 4550 return (rv); 4551 } 4552 4553 /* 4554 * Function: 4555 * bcm_esw_regex_stat_create 4556 * Purpose: 4557 * Create stat collection entity. 4558 * Parameters: 4559 * unit - (IN) Unit number. 4560 * flags - (IN) REGEX_STAT_xxx flags 4561 * nstat - (IN) Number of elements in stat_arr - counter types array. 4562 * stat_arr - (IN) Array of counters to be collected in statistics entity. 4563 * stat_id - (OUT) Statistics entity ID. 4564 * Returns: 4565 * BCM_E_xxx 4566 * Notes: 4567 */ 4568 int bcm_esw_regex_stat_create(int unit, 4569 int flags, 4570 int nstat, 4571 bcm_field_stat_t *stat_arr, 4572 int *stat_id) 4573 { 4574 if (!soc_feature(unit, soc_feature_regex)) { 4575 return BCM_E_UNAVAIL; 4576 } 4577 4578 #ifdef UNFINISHED_DRIVER_CHECK 4579 #error DRIVER UNFINISHED 4580 #endif 4581 return BCM_E_UNAVAIL; 4582 } 4583 4584 /* 4585 * Function: 4586 * bcm_esw_regex_stat_destroy 4587 * Purpose: 4588 * Create stat collection entity. 4589 * Parameters: 4590 * unit - (IN) Unit number. 4591 * stat_id - (IN) Statistics entity ID. 4592 * Returns: 4593 * BCM_E_xxx 4594 * Notes: 4595 */ 4596 int bcm_esw_regex_stat_destroy(int unit, 4597 int stat_id) 4598 { 4599 if (!soc_feature(unit, soc_feature_regex)) { 4600 return BCM_E_UNAVAIL; 4601 } 4602 4603 #ifdef UNFINISHED_DRIVER_CHECK 4604 #error DRIVER UNFINISHED 4605 #endif 4606 return BCM_E_UNAVAIL; 4607 } 4608 4609 /* 4610 * Function: 4611 * bcm_esw_regex_policy_stat_attach 4612 * Purpose: 4613 * Attach statistics entity to Regex policy. 4614 * Parameters: 4615 * unit - (IN) Unit number. 4616 * policy - (IN) Regex policy ID. 4617 * stat_id - (IN) Statistics entity ID. 4618 * Returns: 4619 * BCM_E_xxx 4620 * Notes: 4621 */ 4622 int bcm_esw_regex_policy_stat_attach(int unit, 4623 bcm_regex_policy_t policy, 4624 int stat_id) 4625 { 4626 if (!soc_feature(unit, soc_feature_regex)) { 4627 return BCM_E_UNAVAIL; 4628 } 4629 4630 #ifdef UNFINISHED_DRIVER_CHECK 4631 #error DRIVER UNFINISHED 4632 #endif 4633 return BCM_E_UNAVAIL; 4634 } 4635 4636 /* 4637 * Function: 4638 * bcm_esw_regex_policy_stat_detach 4639 * Purpose: 4640 * Detach statistics entity from Regex policy. 4641 * Parameters: 4642 * unit - (IN) Unit number. 4643 * policy - (IN) Regex policy ID. 4644 * stat_id - (IN) Statistics entity ID. 4645 * Returns: 4646 * BCM_E_xxx 4647 * Notes: 4648 */ 4649 int bcm_esw_regex_policy_stat_detach(int unit, 4650 bcm_regex_policy_t policy, 4651 int stat_id) 4652 { 4653 if (!soc_feature(unit, soc_feature_regex)) { 4654 return BCM_E_UNAVAIL; 4655 } 4656 4657 #ifdef UNFINISHED_DRIVER_CHECK 4658 #error DRIVER UNFINISHED 4659 #endif 4660 return BCM_E_UNAVAIL; 4661 } 4662 4663 /* 4664 * Function: 4665 * bcm_esw_regex_policy_stat_get 4666 * Purpose: 4667 * Get 64 bit counter value for specific statistic type. 4668 * Parameters: 4669 * unit - (IN) Unit number. 4670 * policy - (IN) Regex policy ID. 4671 * stat_id - (OUT) Statistics entity ID. 4672 * Returns: 4673 * BCM_E_xxx 4674 * Notes: 4675 */ 4676 int bcm_esw_regex_policy_stat_get(int unit, 4677 bcm_regex_policy_t policy, 4678 int *stat_id) 4679 { 4680 if (!soc_feature(unit, soc_feature_regex)) { 4681 return BCM_E_UNAVAIL; 4682 } 4683 4684 #ifdef UNFINISHED_DRIVER_CHECK 4685 #error DRIVER UNFINISHED 4686 #endif 4687 return BCM_E_UNAVAIL; 4688 } 4689 4690 /* 4691 * Function: 4692 * bcm_esw_regex_session_add 4693 * Purpose: 4694 * Adds or updates a session entry. 4695 * Parameters: 4696 * unit - (IN) Unit number. 4697 * flags - (IN) REGEX_SESSION_xxx flags. 4698 * key - (IN) The session key. 4699 * session - (IN) The session data. 4700 * Returns: 4701 * BCM_E_xxx 4702 * Notes: 4703 */ 4704 int bcm_esw_regex_session_add(int unit, 4705 int flags, 4706 bcm_regex_session_key_t *key, 4707 bcm_regex_session_t *session) 4708 { 4709 if (!soc_feature(unit, soc_feature_regex)) { 4710 return BCM_E_UNAVAIL; 4711 } 4712 4713 #if defined(BCM_TRIUMPH3_SUPPORT) 4714 if (SOC_IS_TRIUMPH3(unit)) { 4715 return _bcm_tr3_regex_session_add(unit, flags, key, session); 4716 } 4717 #endif /* BCM_TRIUMPH3_SUPPORT */ 4718 4719 return BCM_E_UNAVAIL; 4720 } 4721 4722 /* 4723 * Function: 4724 * bcm_esw_regex_session_policy_update 4725 * Purpose: 4726 * Updates the policy_id field in an already existing session entry. 4727 * Parameters: 4728 * unit - (IN) Unit number. 4729 * flags - (IN) REGEX_SESSION_xxx flags. 4730 * flow_index - (IN) The session index. 4731 * policy - (IN) The session policy ID. 4732 * Returns: 4733 * BCM_E_xxx 4734 * Notes: 4735 */ 4736 int bcm_esw_regex_session_policy_update(int unit, int flags, int flow_index, 4737 bcm_regex_policy_t policy) 4738 { 4739 if (!soc_feature(unit, soc_feature_regex)) { 4740 return BCM_E_UNAVAIL; 4741 } 4742 4743 #if defined(BCM_TRIUMPH3_SUPPORT) 4744 if (SOC_IS_TRIUMPH3(unit)) { 4745 return _bcm_tr3_regex_session_policy_update(unit, flags, flow_index, policy); 4746 } 4747 #endif /* BCM_TRIUMPH3_SUPPORT */ 4748 4749 return BCM_E_UNAVAIL; 4750 } 4751 4752 /* 4753 * Function: 4754 * bcm_esw_regex_session_delete_all 4755 * Purpose: 4756 * Deletes all entries from the regex session table. 4757 * Parameters: 4758 * unit - (IN) Unit number. 4759 * Returns: 4760 * BCM_E_xxx 4761 * Notes: 4762 */ 4763 int bcm_esw_regex_session_delete_all(int unit) 4764 { 4765 if (!soc_feature(unit, soc_feature_regex)) { 4766 return BCM_E_UNAVAIL; 4767 } 4768 4769 #if defined(BCM_TRIUMPH3_SUPPORT) 4770 if (SOC_IS_TRIUMPH3(unit)) { 4771 return _bcm_tr3_regex_session_delete_all(unit); 4772 } 4773 #endif /* BCM_TRIUMPH3_SUPPORT */ 4774 4775 return BCM_E_UNAVAIL; 4776 } 4777 4778 /* 4779 * Function: 4780 * bcm_esw_regex_session_delete 4781 * Purpose: 4782 * Deletes an entry from the regex session table. 4783 * Parameters: 4784 * unit - (IN) Unit number. 4785 * key - (IN) The session key. 4786 * Returns: 4787 * BCM_E_xxx 4788 * Notes: 4789 */ 4790 int bcm_esw_regex_session_delete(int unit, 4791 bcm_regex_session_key_t *key) 4792 { 4793 if (!soc_feature(unit, soc_feature_regex)) { 4794 return BCM_E_UNAVAIL; 4795 } 4796 4797 #if defined(BCM_TRIUMPH3_SUPPORT) 4798 if (SOC_IS_TRIUMPH3(unit)) { 4799 return _bcm_tr3_regex_session_delete(unit, key); 4800 } 4801 #endif /* BCM_TRIUMPH3_SUPPORT */ 4802 4803 return BCM_E_UNAVAIL; 4804 } 4805 4806 /* 4807 * Function: 4808 * bcm_esw_regex_session_get 4809 * Purpose: 4810 * Returns the session data (if any). 4811 * Parameters: 4812 * unit - (IN) Unit number. 4813 * flags - (IN) REGEX_SESSION_xxx flags. 4814 * key - (IN) The session key. 4815 * session - (OUT) The session data. 4816 * Returns: 4817 * BCM_E_xxx 4818 * Notes: 4819 */ 4820 int bcm_esw_regex_session_get(int unit, 4821 int flags, 4822 bcm_regex_session_key_t *key, 4823 bcm_regex_session_t *session) 4824 { 4825 if (!soc_feature(unit, soc_feature_regex)) { 4826 return BCM_E_UNAVAIL; 4827 } 4828 4829 #if defined(BCM_TRIUMPH3_SUPPORT) 4830 if (SOC_IS_TRIUMPH3(unit)) { 4831 return _bcm_tr3_regex_session_get(unit, flags, key, session); 4832 } 4833 #endif /* BCM_TRIUMPH3_SUPPORT */ 4834 4835 return BCM_E_UNAVAIL; 4836 } 4837 4838 /* 4839 * Function: 4840 * bcm_esw_regex_session_traverse 4841 * Purpose: 4842 * Traverse regex sessions. 4843 * Parameters: 4844 * unit - (IN) Unit number. 4845 * flags - (IN) REGEX_SESSION_xxx flags. 4846 * cb - (IN) A pointer to the callback function to call for each session 4847 * user_data - (IN) Pointer to user data to supply in the callback 4848 * Returns: 4849 * BCM_E_xxx 4850 * Notes: 4851 */ 4852 int bcm_esw_regex_session_traverse(int unit, 4853 int flags, 4854 bcm_regex_session_traverse_cb cb, 4855 void *user_data) 4856 { 4857 if (!soc_feature(unit, soc_feature_regex)) { 4858 return BCM_E_UNAVAIL; 4859 } 4860 4861 #if defined(BCM_TRIUMPH3_SUPPORT) 4862 if (SOC_IS_TRIUMPH3(unit)) { 4863 return _bcm_tr3_regex_session_traverse(unit, flags, cb, user_data); 4864 } 4865 #endif /* BCM_TRIUMPH3_SUPPORT */ 4866 4867 return BCM_E_UNAVAIL; 4868 } 4869 4870 void _bcm_esw_policy_dump(int unit, bcm_regex_policy_t policy) 4871 { 4872 _regex_policy_t *policy_ent; /* Regex policy structure. */ 4873 _regex_policy_action_t *pa; 4874 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4875 int policer_printed = 0; 4876 int i; 4877 4878 LOG_CLI((BSL_META_U(unit, 4879 "\n"))); 4880 4881 /* Get the device info structure. */ 4882 device = ESW_REGEX_INFO(unit); 4883 if (NULL == device) { 4884 LOG_CLI((BSL_META_U(unit, 4885 "Regex module not initialized.\n"))); 4886 return; 4887 } 4888 4889 /* List the global policy data */ 4890 LOG_CLI((BSL_META_U(unit, 4891 "Number of policies: %d\n"), device->num_policies)); 4892 LOG_CLI((BSL_META_U(unit, 4893 "Minimum index: %d\n"), device->policy_index_min)); 4894 LOG_CLI((BSL_META_U(unit, 4895 "Maximum index: %d\n"), device->policy_index_max)); 4896 4897 if (NULL == device->policies) { 4898 LOG_CLI((BSL_META_U(unit, 4899 "No policies are created.\n"))); 4900 return; 4901 } 4902 4903 ESW_REGEX_LOCK(unit); 4904 4905 if (_REGEX_INVALID_INDEX == policy) { 4906 /* List all the policy IDs */ 4907 for (i = 0; i < device->num_policies; i++) { 4908 LOG_CLI((BSL_META_U(unit, 4909 "Policy %d\n"), device->policies[i]->eid)); 4910 } 4911 } else { 4912 /* List all the policy data */ 4913 if (BCM_SUCCESS(_regex_policy_get(unit, policy, &policy_ent))) { 4914 LOG_CLI((BSL_META_U(unit, 4915 "Policy %d, flags = 0x%x\n"), policy_ent->eid, policy_ent->flags)); 4916 LOG_CLI((BSL_META_U(unit, 4917 "Actions:\n"))); 4918 pa = policy_ent->actions; 4919 if (NULL == pa) { 4920 LOG_CLI((BSL_META_U(unit, 4921 "None.\n"))); 4922 } else { 4923 do { 4924 LOG_CLI((BSL_META_U(unit, 4925 "\t%s: %d, %d\n"), _regex_policy_action_name(pa->action), pa->param[0], pa->param[1])); 4926 pa = pa->next; 4927 } while (NULL != pa); 4928 if (policy_ent->statistic.sid != _REGEX_INVALID_INDEX) { 4929 LOG_CLI((BSL_META_U(unit, 4930 "Statistic:\n"))); 4931 LOG_CLI((BSL_META_U(unit, 4932 "\tID %d (0x%x)\n"), policy_ent->statistic.sid, policy_ent->statistic.sid)); 4933 } 4934 for (i = 0; i < _REGEX_POLICER_LEVEL_COUNT; i++) { 4935 if (policy_ent->policer[i].pid != _FP_INVALID_INDEX) { 4936 if (!policer_printed) { 4937 LOG_CLI((BSL_META_U(unit, 4938 "Policers:\n"))); 4939 policer_printed = 1; 4940 } 4941 LOG_CLI((BSL_META_U(unit, 4942 "\tID %d (0x%x)\n"), policy_ent->policer[i].pid, policy_ent->policer[i].pid)); 4943 } 4944 } 4945 } 4946 } else { 4947 LOG_CLI((BSL_META_U(unit, 4948 "Policy not found.\n"))); 4949 } 4950 } 4951 4952 ESW_REGEX_UNLOCK(unit); 4953 } 4954 4955 void _bcm_esw_policer_dump(int unit, bcm_policer_t policer_id) 4956 { 4957 _bcm_esw_regex_device_info_t *device; /* Regex control structure. */ 4958 _field_policer_t *f_pl; /* Internal policer descriptor. */ 4959 int i; 4960 int count = 0; 4961 4962 if (!soc_feature(unit, soc_feature_regex)) { 4963 return; 4964 } 4965 4966 LOG_CLI((BSL_META_U(unit, 4967 "\n"))); 4968 4969 /* Get the device info structure. */ 4970 device = ESW_REGEX_INFO(unit); 4971 if (NULL == device) { 4972 LOG_CLI((BSL_META_U(unit, 4973 "Regex module not initialized.\n"))); 4974 return; 4975 } 4976 4977 /* List the global policy data */ 4978 LOG_CLI((BSL_META_U(unit, 4979 "Maximum number of policers: %zu\n"), sizeof(device->policers)/sizeof(device->policers[0]))); 4980 4981 /* Lock the module. */ 4982 ESW_REGEX_LOCK(unit); 4983 4984 if (_REGEX_INVALID_INDEX == policer_id) { 4985 /* Iterate over all entries. */ 4986 for (i = 0; i < sizeof(device->policers)/sizeof(device->policers[0]); i++) { 4987 if (NULL != device->policers[i]) { 4988 LOG_CLI((BSL_META_U(unit, 4989 "Policer %d (0x%x)\n"), device->policers[i]->pid, device->policers[i]->pid)); 4990 count++; 4991 } 4992 } 4993 LOG_CLI((BSL_META_U(unit, 4994 "Policers in use: %d\n"), count)); 4995 } else { 4996 i = _REGEX_POLICER_ID_TO_INDEX(policer_id); 4997 if ((NULL != device->policers[i]) && 4998 (device->policers[i]->pid == policer_id) && 4999 (BCM_SUCCESS(_bcm_regex_policer_get(unit, device->policers[i]->pid, &f_pl)))) { 5000 LOG_CLI((BSL_META_U(unit, 5001 "Policer %d (0x%x), flags = 0x%x\n"), f_pl->pid, f_pl->pid, f_pl->hw_flags)); 5002 LOG_CLI((BSL_META_U(unit, 5003 "\tSW Ref Count = %d, HW Ref Count = %d\n"), f_pl->sw_ref_count, f_pl->hw_ref_count)); 5004 LOG_CLI((BSL_META_U(unit, 5005 "\tLevel = %d, Pool Index = %d, HW Index = %d\n"), f_pl->level, f_pl->pool_index, f_pl->hw_index)); 5006 } else { 5007 LOG_CLI((BSL_META_U(unit, 5008 "Policer not found.\n"))); 5009 } 5010 } 5011 5012 ESW_REGEX_UNLOCK(unit); 5013 } 5014 #endif /* INCLUDE_REGEX */