flexflow_tunnel.c (145788B)
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 * File: flexflow_tunnel.c 8 * Purpose: Flex flow Tunnel APIs. 9 */ 10 11 #include <shared/bsl.h> 12 #include <soc/defs.h> 13 14 #ifdef INCLUDE_L3 15 16 #include <assert.h> 17 #include <bcm/error.h> 18 #include <soc/error.h> 19 #include <bcm/types.h> 20 #include <soc/drv.h> 21 #include <soc/format.h> 22 #include <bcm_int/esw/firebolt.h> 23 #include <bcm_int/esw/trx.h> 24 #include <bcm_int/esw/triumph2.h> 25 #include <bcm_int/esw/virtual.h> 26 #include <bcm_int/esw/port.h> 27 #include <bcm_int/esw_dispatch.h> 28 #include <bcm_int/esw/stack.h> 29 #include <bcm_int/esw/vpn.h> 30 #include <bcm_int/esw/flow.h> 31 #include <soc/esw/flow_db.h> 32 #include <bcm/flow.h> 33 #include <bcm_int/esw/vxlan.h> 34 #include <bcm_int/esw/l2gre.h> 35 36 /* XXXX move to common header file */ 37 #define _BCM_FLOW_TUNNEL_TYPE_L2(_type) \ 38 (((_type) == bcmTunnelTypeVxlan) || \ 39 ((_type) == bcmTunnelTypeL2Gre) || \ 40 ((_type) == bcmTunnelTypeL2Flex)) 41 42 #define _BCM_FLOW_TUNNEL_TYPE_L3(_type) \ 43 (((_type) == bcmTunnelTypeL3Flex) || \ 44 ((_type) == bcmTunnelTypeIp4In4) || \ 45 ((_type) == bcmTunnelTypeIp6In4) || \ 46 ((_type) == bcmTunnelTypeIpAnyIn4) || \ 47 ((_type) == bcmTunnelTypeIp4In6) || \ 48 ((_type) == bcmTunnelTypeIp6In6) || \ 49 ((_type) == bcmTunnelTypeIpAnyIn6) || \ 50 ((_type) == bcmTunnelTypeGre4In4) || \ 51 ((_type) == bcmTunnelTypeGre6In4) || \ 52 ((_type) == bcmTunnelTypeGreAnyIn4) || \ 53 ((_type) == bcmTunnelTypeGre4In6) || \ 54 ((_type) == bcmTunnelTypeGre6In6) || \ 55 ((_type) == bcmTunnelTypeGreAnyIn6)) 56 57 #define _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit) \ 58 (soc_mem_index_count(unit, EGR_IP_TUNNELm)) 59 60 #define _BCM_FLOW_TUNNEL_L2_MAX(unit) \ 61 (soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm)) 62 #define _BCM_FLOW_TUNNEL_L3_MAX(unit) \ 63 (soc_mem_index_count(unit, EGR_L3_INTFm)) 64 #define _BCM_FLOW_TUNNEL_TBL_MAX(unit) (_BCM_FLOW_TUNNEL_L2_MAX(unit) + \ 65 _BCM_FLOW_TUNNEL_L3_MAX(unit)) 66 67 #define _BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(_type) ((_type) & 0x8000) 68 #define _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4 0x1 69 #define _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6 0xa 70 #define _BCM_FLOW_IP_TUNNEL_SINGLE_WIDE_WIDTH 310 71 #define _BCM_FLOW_VXLAN_TUNNEL_TYPE 0x0B 72 #define _BCM_FLOW_L2GRE_TUNNEL_TYPE 0x7 73 #define _QUAD_ENTRY_MAX (4 * SOC_MAX_MEM_WORDS) 74 #define _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE 1 75 #define _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE 3 76 #define _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB 2 77 78 #define _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE \ 79 sizeof(tunnel_entry_t) 80 81 #define _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(_unit, _id) \ 82 do { \ 83 if (((_id) < 0) || ((_id) >= _BCM_FLOW_TUNNEL_TBL_MAX(_unit))) { \ 84 return (BCM_E_BADID); \ 85 } \ 86 } while(0) 87 88 typedef struct _bcm_flow_tunnel_record_s { 89 bcm_flow_tunnel_initiator_t *info; 90 bcm_flow_logical_field_t *field; 91 int num_of_fields; 92 soc_mem_t mem_view; 93 } _bcm_flow_tunnel_record_t; 94 95 STATIC int 96 _bcm_flow_hw_tunnel_entry_get(int unit, int idx, 97 bcm_flow_tunnel_initiator_t *info, 98 bcm_flow_logical_field_t *field, 99 uint32 num_of_fields, 100 uint32 *field_cnt); 101 102 /* 103 * Function: 104 * _bcm_flow_bud_loopback_termination_set 105 * Purpose: 106 * Enable/Disable termination control for loopback port 107 * for classic flow VXLAN/L2GRE BUD node multicast 108 * Parameters: 109 * IN : unit 110 * IN : flow_handle 111 * IN : enable 112 * Returns: 113 * BCM_E_XXX 114 */ 115 116 STATIC int 117 _bcm_flow_bud_loopback_termination_set(int unit, uint32 flow_handle, int enable) 118 { 119 int i; 120 int field_num = 1; 121 122 soc_field_t lport_fields[] = { 123 VXLAN_TERMINATION_ALLOWEDf, 124 }; 125 uint32 lport_values[] = { 126 0x1, /* VXLAN_TERMINATION_ALLOWEDf */ 127 }; 128 129 if (flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 130 lport_fields[0] = VXLAN_TERMINATION_ALLOWEDf; 131 } else if (flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 132 lport_fields[0] = L2GRE_TERMINATION_ALLOWEDf; 133 } else { 134 /* flex vxlan */ 135 lport_fields[0] = VXLAN_TERMINATION_ALLOWEDf; 136 } 137 138 lport_values[0] = enable ? 1: 0; 139 140 /* update the default profile 0 referenced by STM table. 141 * Packet from loopback port will use pp port number as index to STM 142 */ 143 for (i = 0; i < field_num; i++) { 144 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, LPORT_TABm, 0, 145 lport_fields[i], lport_values[i])); 146 } 147 return BCM_E_NONE; 148 } 149 150 int 151 bcmi_flow_ip6_addr_is_valid(bcm_ip6_t addr) 152 { 153 uint32 idx = 0; 154 for (idx = 0; idx < 16; idx++) { 155 if (addr[idx]) { 156 return TRUE; 157 } 158 } 159 return FALSE; 160 } 161 162 STATIC int 163 _bcm_flow_tunnel_idx_from_oif_get(int unit, int oif_idx, int *tnl_idx) 164 { 165 uint32 oif_entry[SOC_MAX_MEM_WORDS]; 166 soc_mem_t oif_mem_view; 167 soc_mem_t oif_mem; 168 int data_type; 169 int rv; 170 uint32 action_set; 171 172 oif_mem = EGR_L3_INTFm; 173 rv = soc_mem_read(unit, oif_mem, MEM_BLOCK_ANY, 174 oif_idx,oif_entry); 175 if (SOC_FAILURE(rv)) { 176 return rv; 177 } 178 data_type = soc_mem_field32_get(unit, oif_mem, 179 oif_entry, DATA_TYPEf); 180 181 /* find the memory view based on the memory and key type */ 182 rv = soc_flow_db_mem_to_view_id_get (unit, oif_mem, 183 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 184 0, NULL, (uint32 *)&oif_mem_view); 185 if (SOC_FAILURE(rv)) { 186 return rv; 187 } 188 if (SOC_MEM_FIELD_VALID(unit,oif_mem_view, 189 TUNNEL_PTR_ACTION_SETf)) { 190 action_set = 0; 191 action_set = soc_mem_field32_get(unit, oif_mem_view, oif_entry, 192 TUNNEL_PTR_ACTION_SETf); 193 *tnl_idx = soc_format_field32_get(unit,TUNNEL_PTR_ACTION_SETfmt, 194 &action_set,TUNNEL_INDEXf); 195 } 196 return SOC_E_NONE; 197 } 198 199 /* 200 * Function: 201 * _bcm_flow_tunnel_dip_idx_set 202 * Purpose: 203 * set L2 tunnel DIP address. 204 * Parameters: 205 * unit - (IN) SOC unit number. 206 * Returns: 207 * BCM_X_XXX 208 * NOTE: 209 */ 210 211 STATIC int 212 _bcm_flow_tunnel_dip_idx_set(int unit, 213 bcm_flow_tunnel_initiator_t *info, 214 int tnl_idx, 215 int *tnl_in_oif) 216 { 217 int rv = BCM_E_NONE; 218 int data_type; 219 soc_mem_t dvp_mem; 220 uint32 dvp_attr[SOC_MAX_MEM_WORDS]; 221 soc_mem_t dvp_mem_view; 222 int fixed_view = TRUE; 223 uint32 dip6[4]; 224 int dvp; 225 uint32 tnl_index; 226 int l2tnl2oif = FALSE; 227 int l2_tunnel = FALSE; 228 229 if (tnl_in_oif != NULL) { 230 *tnl_in_oif = FALSE; 231 } 232 if (info->flags & BCM_TUNNEL_REPLACE) { 233 if (BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id) < 234 _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 235 l2_tunnel = TRUE; 236 } 237 } else { 238 if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) { 239 l2_tunnel = TRUE; 240 } 241 } 242 243 if (l2_tunnel) { 244 dvp_mem = EGR_DVP_ATTRIBUTEm; 245 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 246 soc_mem_lock(unit,dvp_mem); 247 rv = soc_mem_read(unit, dvp_mem, MEM_BLOCK_ANY, dvp, dvp_attr); 248 data_type = soc_mem_field32_get(unit, dvp_mem, dvp_attr, DATA_TYPEf); 249 250 /* find the memory view based on the memory and key type */ 251 rv = soc_flow_db_mem_to_view_id_get (unit, dvp_mem, 252 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 253 0, NULL, (uint32 *)&dvp_mem_view); 254 LOG_VERBOSE(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 255 "dvp(%d) mem_view_id: 0x%x\n"), dvp, dvp_mem_view)); 256 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 257 soc_mem_unlock(unit,dvp_mem); 258 return rv; 259 } else if (rv == SOC_E_NOT_FOUND) { 260 /* not found, fixed view */ 261 } else { 262 /* found, flex view */ 263 fixed_view = FALSE; 264 } 265 266 if (fixed_view == FALSE) { 267 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 268 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 269 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 270 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 271 DIRECT_ASSIGNMENT_10_ACTION_SETf, info->dip); 272 } 273 } 274 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) { 275 276 /* dip in dvp_attribute table */ 277 SAL_IP6_ADDR_TO_UINT32(info->dip6,dip6); 278 279 /* OUTER_IPV6_DIP_0_31 */ 280 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 281 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 282 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 283 DIRECT_ASSIGNMENT_10_ACTION_SETf, dip6[0]); 284 } 285 286 /* OUTER_IPV6_DIP_32_63 */ 287 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 288 DIRECT_ASSIGNMENT_12_ACTION_SETf)) { 289 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 290 DIRECT_ASSIGNMENT_12_ACTION_SETf, dip6[1]); 291 } 292 293 /* OUTER_IPV6_DIP_64_95 */ 294 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 295 DIRECT_ASSIGNMENT_14_ACTION_SETf)) { 296 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 297 DIRECT_ASSIGNMENT_14_ACTION_SETf, dip6[2]); 298 } 299 300 /* OUTER_IPV6_DIP_96_127 */ 301 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 302 DIRECT_ASSIGNMENT_16_ACTION_SETf)) { 303 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 304 DIRECT_ASSIGNMENT_16_ACTION_SETf, dip6[3]); 305 } 306 } 307 if (SOC_MEM_FIELD_VALID(unit,dvp_mem_view, 308 TUNNEL_PTR_ACTION_SETf)) { 309 tnl_index = 0; 310 soc_format_field32_set(unit,TUNNEL_PTR_ACTION_SETfmt, 311 &tnl_index,TUNNEL_INDEXf, tnl_idx); 312 soc_mem_field32_set(unit, dvp_mem_view, dvp_attr, 313 TUNNEL_PTR_ACTION_SETf, tnl_index); 314 315 } else if (info->l3_intf_id) { 316 if (info->l3_intf_id < _BCM_FLOW_TUNNEL_L3_MAX(unit)) { 317 /* set to EGR_L3_INTF */ 318 l2tnl2oif = TRUE; 319 } 320 } 321 } else { /* fixed view */ 322 /* L2GRE and VXLAN: DIP is in dvp_attr */ 323 324 if (data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) { 325 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 326 soc_mem_field32_set(unit, dvp_mem, dvp_attr, 327 VXLAN__DIPf, info->dip); 328 } 329 soc_mem_field32_set(unit, dvp_mem, dvp_attr, 330 VXLAN__TUNNEL_INDEXf, tnl_idx); 331 332 } else if (data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 333 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 334 soc_mem_field32_set(unit, dvp_mem, dvp_attr, 335 L2GRE__DIPf, info->dip); 336 } 337 soc_mem_field32_set(unit, dvp_mem, dvp_attr, 338 L2GRE__TUNNEL_INDEXf, tnl_idx); 339 } 340 } 341 rv = soc_mem_write(unit, dvp_mem, MEM_BLOCK_ALL, dvp, dvp_attr); 342 soc_mem_unlock(unit,dvp_mem); 343 } 344 345 /* If l3 tunnel or certain l2 tunnel cases, set tunnel idx to oif table */ 346 if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) || l2tnl2oif) { 347 uint32 oif_entry[SOC_MAX_MEM_WORDS]; 348 soc_mem_t oif_mem_view; 349 soc_mem_t oif_mem; 350 351 oif_mem = EGR_L3_INTFm; 352 soc_mem_lock(unit, oif_mem); 353 rv = soc_mem_read(unit, oif_mem, MEM_BLOCK_ANY, 354 info->l3_intf_id,oif_entry); 355 if (SOC_FAILURE(rv)) { 356 soc_mem_unlock(unit,oif_mem); 357 return rv; 358 } 359 data_type = soc_mem_field32_get(unit, oif_mem, 360 oif_entry, DATA_TYPEf); 361 fixed_view = TRUE; 362 /* find the memory view based on the memory and key type */ 363 rv = soc_flow_db_mem_to_view_id_get (unit, oif_mem, 364 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 365 0, NULL, (uint32 *)&oif_mem_view); 366 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 367 return rv; 368 } else if (rv == SOC_E_NOT_FOUND) { 369 /* not found, fixed view */ 370 } else { 371 /* found, flex view */ 372 fixed_view = FALSE; 373 } 374 375 if (fixed_view == TRUE) { 376 if (!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) { 377 soc_mem_field32_set(unit, oif_mem, oif_entry, 378 TUNNEL_INDEXf, tnl_idx); 379 } 380 } else { 381 if (SOC_MEM_FIELD_VALID(unit,oif_mem_view, 382 TUNNEL_PTR_ACTION_SETf)) { 383 tnl_index = 0; 384 soc_format_field32_set(unit,TUNNEL_PTR_ACTION_SETfmt, 385 &tnl_index,TUNNEL_INDEXf, tnl_idx); 386 soc_mem_field32_set(unit, oif_mem_view, oif_entry, 387 TUNNEL_PTR_ACTION_SETf, tnl_index); 388 } else { 389 soc_mem_unlock(unit, oif_mem); 390 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 391 "TUNNEL_PTR_ACTION_SETf not in either dvp or oif"))); 392 return BCM_E_NOT_FOUND; 393 } 394 } 395 if (tnl_in_oif != NULL) { 396 *tnl_in_oif = TRUE; 397 } 398 rv = soc_mem_write(unit, oif_mem, MEM_BLOCK_ALL, info->l3_intf_id, 399 oif_entry); 400 soc_mem_unlock(unit, oif_mem); 401 } 402 SOC_IF_ERROR_RETURN(rv); 403 return rv; 404 } 405 406 /* 407 * Function: 408 * _bcm_flow_tunnel_initiator_hash_calc 409 * Purpose: 410 * Calculate tunnel initiator entry hash(signature). 411 * Parameters: 412 * unit - (IN) SOC unit number. 413 * buf - (IN) Tunnel initiator entry information. 414 * hash - (OUT)Hash(signature) calculated value. 415 * Returns: 416 * BCM_X_XXX 417 * NOTE: 418 * duplication of _bcm_td2_vxlan_tunnel_initiator_hash_calc for 419 * not including legacy vxlan code in the future. 420 * 421 * plugged in _bcm_xgs3_tnl_init_hash_calc 422 */ 423 424 int 425 _bcm_flow_tunnel_initiator_hash_calc(int unit, void *buf, uint16 *hash) 426 { 427 _bcm_flow_tunnel_record_t *tnl_rec; 428 bcm_flow_tunnel_initiator_t tnl_entry; 429 bcm_flow_tunnel_initiator_t *info; 430 431 if ((NULL == buf) || (NULL == hash)) { 432 return (BCM_E_PARAM); 433 } 434 435 tnl_rec = (_bcm_flow_tunnel_record_t *)buf; 436 info = tnl_rec->info; 437 438 bcm_flow_tunnel_initiator_t_init(&tnl_entry); 439 tnl_entry.type = info->type; 440 441 if (_BCM_FLOW_TUNNEL_TYPE_L2(tnl_entry.type)) { 442 /* Set source ip */ 443 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) { 444 sal_memcpy(tnl_entry.sip6, info->sip6, sizeof(bcm_ip6_t)); 445 } 446 447 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) { 448 tnl_entry.sip = info->sip; 449 } 450 451 tnl_entry.udp_dst_port = info->udp_dst_port; 452 tnl_entry.udp_src_port = info->udp_src_port; 453 454 } else { /* L3 tunnel */ 455 /* include all fields, copy buffer to structure. */ 456 sal_memcpy(&tnl_entry, (void *)info, 457 sizeof(bcm_flow_tunnel_initiator_t)); 458 459 /* Ignore flow label for not V6 tunnels. */ 460 if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_entry.type)) { 461 tnl_entry.flow_label = 0; 462 } 463 464 /* Mask fields we don't want to include in hash. */ 465 tnl_entry.flags = 0; 466 tnl_entry.flow_handle = 0; 467 tnl_entry.flow_option = 0; 468 tnl_entry.flow_port = 0; 469 tnl_entry.valid_elements = 0; 470 tnl_entry.tunnel_id = 0; 471 tnl_entry.l3_intf_id = 0; 472 473 switch (tnl_entry.type) { 474 case bcmTunnelTypeIp4In4: 475 case bcmTunnelTypeIp6In4: 476 tnl_entry.type = bcmTunnelTypeIpAnyIn4; 477 break; 478 case bcmTunnelTypeIp4In6: 479 case bcmTunnelTypeIp6In6: 480 tnl_entry.type = bcmTunnelTypeIpAnyIn6; 481 break; 482 case bcmTunnelTypeGre4In4: 483 case bcmTunnelTypeGre6In4: 484 tnl_entry.type = bcmTunnelTypeGreAnyIn4; 485 break; 486 case bcmTunnelTypeGre4In6: 487 case bcmTunnelTypeGre6In6: 488 tnl_entry.type = bcmTunnelTypeGreAnyIn6; 489 break; 490 default: 491 break; 492 } 493 } 494 495 /* Calculate hash */ 496 *hash = _shr_crc16(0, (uint8 *)&tnl_entry, 497 sizeof(bcm_flow_tunnel_initiator_t)); 498 499 return BCM_E_NONE; 500 } 501 502 503 /* 504 * Function: 505 * _bcm_flow_tunnel_initiator_cmp 506 * Purpose: 507 * Routine compares vxlan tunnel initiator entry with entry in the chip 508 * with specified index. 509 * Parameters: 510 * unit - (IN) SOC unit number. 511 * buf - (IN) Tunnel initiator entry to compare. 512 * index - (IN) Entry index in the chip to compare. 513 * cmp_result - (OUT)Compare result. 514 * Returns: 515 * BCM_E_XXX 516 * 517 * NOTE: 518 * duplication of _bcm_td2_vxlan_tunnel_initiator_cmp for 519 * not including legacy vxlan code in the future. 520 * 521 * plugged in _bcm_xgs3_tnl_init_cmp 522 */ 523 524 int 525 _bcm_flow_tunnel_initiator_cmp(int unit, void *buf, 526 int index, int *cmp_result) 527 { 528 bcm_flow_tunnel_initiator_t hw_entry; /* Entry read from hw */ 529 bcm_flow_tunnel_initiator_t *tnl_entry; /* Api passed buffer */ 530 _bcm_flow_tunnel_record_t *tnl_rec; 531 int rv = BCM_E_NONE; 532 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 533 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 534 uint32 mem_entry[SOC_MAX_MEM_WORDS]; 535 int i; 536 uint32 cnt = 0; 537 int data_type; 538 int flow_ctrl_id; 539 int hw_data_type; 540 int hw_flow_ctrl_id; 541 int flex_type_match = FALSE; 542 soc_mem_t mem; 543 544 if ((NULL == buf) || (NULL == cmp_result)) { 545 return BCM_E_PARAM; 546 } 547 tnl_rec = (_bcm_flow_tunnel_record_t *)buf; 548 549 *cmp_result = BCM_L3_CMP_NOT_EQUAL; 550 mem = EGR_IP_TUNNELm; 551 552 /* point to the input entry */ 553 tnl_entry = tnl_rec->info; 554 555 /* Initialize entry to get from hw */ 556 bcm_flow_tunnel_initiator_t_init(&hw_entry); 557 558 if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) { 559 rv = soc_flow_db_mem_view_field_list_get(unit, 560 tnl_rec->mem_view, 561 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 562 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 563 SOC_IF_ERROR_RETURN(rv); 564 for (i = 0; i < cnt; i++) { 565 field[i].id = data_ids[i]; 566 } 567 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, mem_entry); 568 SOC_IF_ERROR_RETURN(rv); 569 hw_data_type = soc_mem_field32_get(unit, mem, mem_entry, DATA_TYPEf); 570 hw_flow_ctrl_id = soc_mem_field32_get(unit, mem, mem_entry, 571 FLEX_FLOW_SELECT_CTRL_IDf); 572 soc_flow_db_mem_view_entry_init(unit,tnl_rec->mem_view, mem_entry); 573 data_type = soc_mem_field32_get(unit, tnl_rec->mem_view, 574 mem_entry, DATA_TYPEf); 575 flow_ctrl_id = soc_mem_field32_get(unit, tnl_rec->mem_view, mem_entry, 576 FLEX_FLOW_SELECT_CTRL_IDf); 577 if (hw_data_type == data_type && hw_flow_ctrl_id == flow_ctrl_id) { 578 flex_type_match = TRUE; 579 } else { 580 return (BCM_E_NONE); 581 } 582 } 583 584 /* Get tunnel initiator entry from hw */ 585 BCM_XGS3_L3_MODULE_LOCK(unit); 586 rv = _bcm_flow_hw_tunnel_entry_get(unit, index, &hw_entry,field, 587 cnt,NULL); 588 BCM_XGS3_L3_MODULE_UNLOCK(unit); 589 BCM_IF_ERROR_RETURN(rv); 590 591 /* compare the type first */ 592 if ((tnl_entry->type != hw_entry.type) && (flex_type_match == FALSE)) { 593 switch (tnl_entry->type) { 594 case bcmTunnelTypeIp4In4: 595 case bcmTunnelTypeIp6In4: 596 if (bcmTunnelTypeIpAnyIn4 != hw_entry.type) { 597 return (BCM_E_NONE); 598 } 599 break; 600 case bcmTunnelTypeIp4In6: 601 case bcmTunnelTypeIp6In6: 602 if (bcmTunnelTypeIpAnyIn6 != hw_entry.type) { 603 return (BCM_E_NONE); 604 } 605 break; 606 case bcmTunnelTypeGre4In4: 607 case bcmTunnelTypeGre6In4: 608 if (bcmTunnelTypeGreAnyIn4 != hw_entry.type) { 609 return (BCM_E_NONE); 610 } 611 break; 612 case bcmTunnelTypeGre4In6: 613 case bcmTunnelTypeGre6In6: 614 if (bcmTunnelTypeGreAnyIn6 != hw_entry.type) { 615 return (BCM_E_NONE); 616 } 617 break; 618 default: 619 return (BCM_E_NONE); 620 } 621 } 622 623 /* Compare source ip */ 624 if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) { 625 if (tnl_entry->sip != hw_entry.sip) { 626 return BCM_E_NONE; 627 } 628 } 629 if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) { 630 if (sal_memcmp(tnl_entry->sip6, hw_entry.sip6, sizeof(bcm_ip6_t))) { 631 return BCM_E_NONE; 632 } 633 } 634 635 if (!_BCM_FLOW_TUNNEL_TYPE_L2(tnl_entry->type)) { 636 if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 637 if (tnl_entry->dip != hw_entry.dip) { 638 return BCM_E_NONE; 639 } 640 } 641 if (tnl_entry->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) { 642 if (sal_memcmp(tnl_entry->dip6, hw_entry.dip6, sizeof(bcm_ip6_t))) { 643 return BCM_E_NONE; 644 } 645 } 646 } 647 648 /* Compare udp dst port */ 649 if ((tnl_entry->udp_dst_port != hw_entry.udp_dst_port) || 650 (tnl_entry->udp_src_port != hw_entry.udp_src_port)) { 651 return BCM_E_NONE; 652 } 653 654 /* Compare hw entry with passed one. */ 655 if ((tnl_entry->dscp_sel != hw_entry.dscp_sel) || 656 (tnl_entry->dscp != hw_entry.dscp)) { 657 return (BCM_E_NONE); 658 } 659 660 if (tnl_entry->ttl != hw_entry.ttl) { 661 return (BCM_E_NONE); 662 } 663 /* Compare destination mac. */ 664 if (sal_memcmp(tnl_entry->dmac, hw_entry.dmac, sizeof(bcm_mac_t))) { 665 return (BCM_E_NONE); 666 } 667 668 /* compare the logical fields if it is flex view */ 669 if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) { 670 for (i = 0; i < cnt && i < tnl_rec->num_of_fields; i++) { 671 if (field[i].id == tnl_rec->field[i].id) { 672 if (field[i].value != tnl_rec->field[i].value) { 673 return (BCM_E_NONE); 674 } 675 } 676 } 677 } 678 *cmp_result = BCM_L3_CMP_EQUAL; 679 return BCM_E_NONE; 680 } 681 682 /* 683 * Function: 684 * _bcm_flow_tnl_init_add 685 * Purpose: 686 * Allocate tunnel initiator table index & Write tunnel initiator entry. 687 * Routine trying to match new entry to an existing one, 688 * if match found reference cound is incremented, otherwise 689 * new index allocated & entry added to hw. 690 * Parameters: 691 * unit - (IN)StrataSwitch unit number. 692 * flags - (IN)Table shared flags. 693 * tnl_entry - (IN)Tunnel initiator entry. 694 * index - (OUT)next hop index. 695 * Returns: 696 * BCM_E_XXX 697 */ 698 int 699 _bcm_flow_tnl_init_add(int unit, uint32 flags, 700 bcm_flow_tunnel_initiator_t *tnl_entry, 701 bcm_flow_logical_field_t *field, 702 uint32 num_of_fields, 703 int *index) 704 { 705 _bcm_l3_tbl_op_t data; /* Operation data. */ 706 soc_flow_db_mem_view_info_t vinfo; 707 int rv = BCM_E_NONE; 708 soc_mem_t mem_view_id; 709 int double_wide; 710 _bcm_flow_tunnel_record_t tnl_rec; 711 712 if (!(flags & _BCM_L3_SHR_WRITE_DISABLE)) { 713 /* Make sure hw call is defined. */ 714 if (!BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_add)) { 715 return (BCM_E_UNAVAIL); 716 } 717 } 718 719 tnl_rec.info = tnl_entry; 720 tnl_rec.field = field; 721 tnl_rec.num_of_fields = num_of_fields; 722 723 /* get the physical memory view */ 724 if (_BCM_FLOW_IS_FLEX_VIEW(tnl_entry)) { 725 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,tnl_entry->flow_handle, 726 tnl_entry->flow_option, 727 SOC_FLOW_DB_FUNC_TUNNEL_INITIATOR_ID, 728 (uint32 *)&mem_view_id); 729 BCM_IF_ERROR_RETURN(rv); 730 rv = soc_flow_db_mem_view_info_get(unit,mem_view_id,&vinfo); 731 BCM_IF_ERROR_RETURN(rv); 732 double_wide = vinfo.width > _BCM_FLOW_IP_TUNNEL_SINGLE_WIDE_WIDTH? 733 TRUE: FALSE; 734 tnl_rec.mem_view = mem_view_id; 735 } else { 736 double_wide = _BCM_EGR_IP_TUNNEL_DOUBLE_WIDE_ENTRY(unit, 737 tnl_entry->type) ? TRUE: FALSE; 738 } 739 740 /* this flag must be set, so tnl_init_add never called */ 741 flags |= _BCM_L3_SHR_WRITE_DISABLE; 742 743 /* Initialization */ 744 sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t)); 745 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, tnl_init); 746 data.width = double_wide? _BCM_DOUBLE_WIDE: _BCM_SINGLE_WIDE; 747 data.oper_flags = flags; 748 data.entry_buffer = (void *)&tnl_rec; 749 data.hash_func = _bcm_flow_tunnel_initiator_hash_calc; 750 data.cmp_func = _bcm_flow_tunnel_initiator_cmp; 751 752 /* init add_func to pass the error check */ 753 data.add_func = BCM_XGS3_L3_HWCALL(unit, tnl_init_add); 754 if (flags & _BCM_L3_SHR_WITH_ID) { 755 data.entry_index = *index; 756 } 757 758 /* Add tunnel initiator entry. */ 759 BCM_IF_ERROR_RETURN (_bcm_xgs3_tbl_add(unit, &data)); 760 *index = data.entry_index; 761 762 return (BCM_E_NONE); 763 } 764 765 /* 766 * Function: 767 * _bcm_flow_tunnel_init_delete 768 * Purpose: 769 * Clear the tunnel initiator hardware entry. 770 * Parameters: 771 * unit - (IN)SOC unit number. 772 * idx - (IN)Index to tunnel initiator hardware entry table. 773 * Returns: 774 * BCM_E_XXX 775 */ 776 STATIC int 777 _bcm_flow_tunnel_init_delete(int unit, int idx, int width) 778 { 779 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */ 780 soc_mem_t mem; /* Tunnel initiator table memory */ 781 782 /* Get table memory. */ 783 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 784 if (width == _BCM_DOUBLE_WIDE) { 785 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 786 idx >>= 1; /* Each record takes two slots. */ 787 } 788 /* Zero write buffer. */ 789 sal_memset(&tnl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32)); 790 791 /* Write buffer to hw. */ 792 return BCM_XGS3_MEM_WRITE(unit, mem, idx, &tnl_entry); 793 } 794 795 /* 796 * Function: 797 * _bcm_flow_tunnel_init_get 798 * Purpose: 799 * Add tunnel initiator entry to hw. 800 * Parameters: 801 * unit - (IN)SOC unit number. 802 * idx - (IN)Index to insert tunnel initiator. 803 * info - (IN)Tunnel initiator entry info. 804 * Returns: 805 * BCM_E_XXX 806 */ 807 STATIC int 808 _bcm_flow_tunnel_init_get(int unit, 809 int soft_tnl_idx, 810 bcm_flow_tunnel_initiator_t *info, 811 bcm_flow_logical_field_t *field, 812 uint32 num_of_fields, 813 uint32 *field_cnt) 814 { 815 uint32 dvp_attr[SOC_MAX_MEM_WORDS]; 816 soc_mem_t dvp_mem; 817 soc_mem_t dvp_mem_view; 818 int rv = BCM_E_NONE; /* Return value */ 819 uint32 dip6[4]; 820 uint32 dvp_data_type; 821 _bcm_flow_bookkeeping_t *flow_info; 822 int oif_idx; 823 int tnl_idx; 824 825 flow_info = FLOW_INFO(unit); 826 827 dvp_mem = EGR_DVP_ATTRIBUTEm; 828 829 tnl_idx = flow_info->init_tunnel[soft_tnl_idx].idx; 830 if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 831 /* L2 tunnel */ 832 rv = soc_mem_read(unit, dvp_mem, MEM_BLOCK_ANY, soft_tnl_idx,dvp_attr); 833 dvp_data_type = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 834 DATA_TYPEf); 835 836 /* find the memory view based on the memory and key type */ 837 rv = soc_flow_db_mem_to_view_id_get (unit, dvp_mem, 838 SOC_FLOW_DB_KEY_TYPE_INVALID, dvp_data_type, 839 0, NULL, (uint32 *)&dvp_mem_view); 840 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 841 return rv; 842 } else if (rv == SOC_E_NOT_FOUND) { 843 /* not found, fixed view */ 844 } else { 845 /* found, flex view */ 846 info->type = bcmTunnelTypeL2Flex; 847 dvp_mem = dvp_mem_view; 848 } 849 850 if (info->type == bcmTunnelTypeL2Flex) { 851 /* dip in dvp_attribute table */ 852 853 dip6[0] = 0; 854 dip6[1] = 0; 855 dip6[2] = 0; 856 dip6[3] = 0; 857 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6); 858 info->dip = 0; 859 860 /* OUTER_IPV6_DIP_0_31 */ 861 if (SOC_MEM_FIELD_VALID(unit,dvp_mem, 862 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 863 dip6[0] = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 864 DIRECT_ASSIGNMENT_10_ACTION_SETf); 865 } 866 867 /* OUTER_IPV6_DIP_32_63 */ 868 if (SOC_MEM_FIELD_VALID(unit,dvp_mem, 869 DIRECT_ASSIGNMENT_12_ACTION_SETf)) { 870 dip6[1] = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 871 DIRECT_ASSIGNMENT_12_ACTION_SETf); 872 } 873 874 /* OUTER_IPV6_DIP_64_95 */ 875 if (SOC_MEM_FIELD_VALID(unit,dvp_mem, 876 DIRECT_ASSIGNMENT_14_ACTION_SETf)) { 877 dip6[2] = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 878 DIRECT_ASSIGNMENT_14_ACTION_SETf); 879 } 880 881 /* OUTER_IPV6_DIP_96_127 */ 882 if (SOC_MEM_FIELD_VALID(unit,dvp_mem, 883 DIRECT_ASSIGNMENT_16_ACTION_SETf)) { 884 dip6[3] = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 885 DIRECT_ASSIGNMENT_16_ACTION_SETf); 886 } 887 if ((dip6[1] == 0) && (dip6[2] == 0) && (dip6[3] == 0)) { 888 info->dip = dip6[0]; 889 } else { 890 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6); 891 } 892 } else { /* fixed view */ 893 894 /* L2GRE and VXLAN: DIP is in dvp_attr */ 895 896 if (dvp_data_type == _BCM_FLOW_VXLAN_EGRESS_DEST_VP_TYPE) { 897 info->type = bcmTunnelTypeVxlan; 898 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 899 info->dip = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 900 VXLAN__DIPf); 901 } else if (dvp_data_type == _BCM_FLOW_L2GRE_EGRESS_DEST_VP_TYPE) { 902 info->type = bcmTunnelTypeL2Gre; 903 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 904 info->dip = soc_mem_field32_get(unit, dvp_mem, dvp_attr, 905 L2GRE__DIPf); 906 } else { 907 return BCM_E_INTERNAL; 908 } 909 } 910 if (tnl_idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) { 911 /* l3_oif index */ 912 oif_idx = tnl_idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit); 913 info->l3_intf_id = oif_idx; 914 BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit, 915 oif_idx, &tnl_idx)); 916 } 917 } 918 919 rv = _bcm_flow_hw_tunnel_entry_get(unit, tnl_idx, info, field, 920 num_of_fields,field_cnt); 921 BCM_IF_ERROR_RETURN(rv); 922 return rv; 923 } 924 925 /* 926 * Function: 927 * _bcm_flow_hw_tunnel_entry_get 928 * Purpose: 929 * Get a IP_TUNNEL entry and convert to bcm_flow_tunnel_initiator_t info. 930 * Parameters: 931 * unit - (IN)SOC unit number. 932 * idx - (IN)Index to IP_TUNNEL hw table. 933 * info - (IN)Tunnel initiator entry info. 934 * Returns: 935 * BCM_E_XXX 936 */ 937 STATIC int 938 _bcm_flow_hw_tunnel_entry_get(int unit, 939 int idx, 940 bcm_flow_tunnel_initiator_t *info, 941 bcm_flow_logical_field_t *field, 942 uint32 num_of_fields, 943 uint32 *field_cnt) 944 { 945 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */ 946 soc_mem_t mem; /* Tunnel initiator table memory */ 947 soc_mem_t mem_view_id; 948 int rv; /* Return value */ 949 int df_val=0; /* Don't fragment encoding */ 950 uint32 sip6[4]; 951 uint32 dip6[4]; 952 uint32 tnl_data_type; 953 int tnl_type = 0; 954 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 955 uint32 cnt; 956 int i; 957 int j; 958 uint32 ttl; 959 int fixed_view = TRUE; 960 soc_field_t qos_f; 961 egr_sequence_number_table_entry_t entry; 962 _bcm_flow_bookkeeping_t *flow_info; 963 int dscp_sel; 964 965 flow_info = FLOW_INFO(unit); 966 967 mem = EGR_IP_TUNNELm; 968 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry); 969 SOC_IF_ERROR_RETURN(rv); 970 tnl_data_type = soc_mem_field32_get(unit, mem, tnl_entry, DATA_TYPEf); 971 if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6) { 972 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 973 idx >>= 1; /* Each record takes two slots. */ 974 975 rv = BCM_XGS3_MEM_READ(unit, mem, idx, tnl_entry); 976 BCM_IF_ERROR_RETURN(rv); 977 } 978 979 /* find the memory view based on the memory and key type */ 980 rv = soc_flow_db_mem_to_view_id_get (unit, mem, 981 SOC_FLOW_DB_KEY_TYPE_INVALID, tnl_data_type, 982 0, NULL, (uint32 *)&mem_view_id); 983 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 984 return rv; 985 } else if (rv == SOC_E_NOT_FOUND) { 986 /* not found, fixed view */ 987 fixed_view = TRUE; 988 } else { 989 /* found, flex view */ 990 if (info->type != bcmTunnelTypeL2Flex) { 991 info->type = bcmTunnelTypeL3Flex; /* set as default */ 992 } 993 fixed_view = FALSE; 994 } 995 996 if (fixed_view == TRUE) { /* fixed view */ 997 tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf); 998 if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4) { 999 if ((tnl_type != _BCM_FLOW_VXLAN_TUNNEL_TYPE) && 1000 (tnl_type != _BCM_FLOW_L2GRE_TUNNEL_TYPE)) { 1001 info->dip = soc_mem_field32_get(unit, mem, tnl_entry, DIPf); 1002 } 1003 info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf); 1004 } else if (tnl_data_type == _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6) { 1005 1006 /* Get destination ip. */ 1007 soc_mem_ip6_addr_get(unit, mem, tnl_entry, DIPf, info->dip6, 1008 SOC_MEM_IP6_FULL_ADDR); 1009 1010 /* Get source ip. */ 1011 soc_mem_ip6_addr_get(unit, mem, tnl_entry, SIPf, info->sip6, 1012 SOC_MEM_IP6_FULL_ADDR); 1013 } 1014 1015 /* Tunnel header DSCP select. */ 1016 info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf); 1017 1018 if (info->dscp_sel == bcmTunnelDscpMap) { 1019 /* Set DSCP_MAP value. */ 1020 int hw_map_idx = 0; 1021 hw_map_idx = soc_mem_field32_get(unit, mem, tnl_entry, 1022 DSCP_MAPPING_PTRf); 1023 BCM_IF_ERROR_RETURN( 1024 _bcm_tr2_qos_idx2id(unit, hw_map_idx, 1025 _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE, &info->dscp_map)); 1026 } else { 1027 /* Set DSCP value. */ 1028 info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf); 1029 } 1030 /* Set TTL. */ 1031 info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf); 1032 1033 /* Set UDP Dest Port */ 1034 info->udp_dst_port = soc_mem_field32_get(unit, mem, tnl_entry, 1035 L4_DEST_PORTf); 1036 1037 /* Set UDP Src Port */ 1038 info->udp_src_port = soc_mem_field32_get(unit, mem, tnl_entry, 1039 L4_SRC_PORTf); 1040 1041 if (SOC_MEM_FIELD_VALID(unit, mem, IPV4_DF_SELf)) { 1042 /* IP tunnel hdr DF bit for IPv4 */ 1043 df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf); 1044 if (0x2 <= df_val) { 1045 info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF; 1046 } else if (0x1 == df_val) { 1047 info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF; 1048 } 1049 } 1050 1051 if (SOC_MEM_FIELD_VALID(unit, mem, IPV6_DF_SELf)) { 1052 /* IP tunnel hdr DF bit for IPv6 */ 1053 if (soc_mem_field32_get(unit, mem, tnl_entry, IPV6_DF_SELf)) { 1054 info->flags |= BCM_TUNNEL_INIT_IPV6_SET_DF; 1055 } 1056 } 1057 1058 /* FRAGMENT ID */ 1059 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1060 MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry)); 1061 info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1062 &entry, SEQUENCE_NUMBERf); 1063 1064 } else { /* flex view */ 1065 uint32 qos = 0; 1066 if (info->type == bcmTunnelTypeL3Flex) { 1067 dip6[0] = 0; 1068 dip6[1] = 0; 1069 dip6[2] = 0; 1070 dip6[3] = 0; 1071 info->dip = 0; 1072 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6); 1073 1074 /* OUTER_IPV6_DIP_0_31 */ 1075 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1076 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 1077 dip6[0] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1078 DIRECT_ASSIGNMENT_10_ACTION_SETf); 1079 } 1080 1081 /* OUTER_IPV6_DIP_32_63 */ 1082 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1083 DIRECT_ASSIGNMENT_12_ACTION_SETf)) { 1084 dip6[1] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1085 DIRECT_ASSIGNMENT_12_ACTION_SETf); 1086 } 1087 1088 /* OUTER_IPV6_DIP_64_95 */ 1089 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1090 DIRECT_ASSIGNMENT_14_ACTION_SETf)) { 1091 dip6[2] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1092 DIRECT_ASSIGNMENT_14_ACTION_SETf); 1093 } 1094 1095 /* OUTER_IPV6_DIP_96_127 */ 1096 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1097 DIRECT_ASSIGNMENT_16_ACTION_SETf)) { 1098 dip6[3] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1099 DIRECT_ASSIGNMENT_16_ACTION_SETf); 1100 } 1101 if ((dip6[1] == 0) && (dip6[2] == 0) && (dip6[3] == 0)) { 1102 info->dip = dip6[0]; 1103 } else { 1104 SAL_IP6_ADDR_FROM_UINT32(info->dip6,dip6); 1105 } 1106 } 1107 1108 sip6[0] = 0; 1109 sip6[1] = 0; 1110 sip6[2] = 0; 1111 sip6[3] = 0; 1112 info->sip = 0; 1113 SAL_IP6_ADDR_FROM_UINT32(info->sip6,sip6); 1114 1115 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1116 DIRECT_ASSIGNMENT_11_ACTION_SETf)) { 1117 sip6[0] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1118 DIRECT_ASSIGNMENT_11_ACTION_SETf); 1119 } 1120 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1121 DIRECT_ASSIGNMENT_13_ACTION_SETf)) { 1122 sip6[1] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1123 DIRECT_ASSIGNMENT_13_ACTION_SETf); 1124 } 1125 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1126 DIRECT_ASSIGNMENT_15_ACTION_SETf)) { 1127 sip6[2] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1128 DIRECT_ASSIGNMENT_15_ACTION_SETf); 1129 } 1130 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1131 DIRECT_ASSIGNMENT_17_ACTION_SETf)) { 1132 sip6[3] = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1133 DIRECT_ASSIGNMENT_17_ACTION_SETf); 1134 } 1135 if ((sip6[1] == 0) && (sip6[2] == 0) && (sip6[3] == 0)) { 1136 info->sip = sip6[0]; 1137 } else { 1138 SAL_IP6_ADDR_FROM_UINT32(info->sip6,sip6); 1139 } 1140 1141 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1142 QOS_A_ACTION_SETf)) { 1143 qos_f = QOS_A_ACTION_SETf; 1144 } else if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1145 QOS_B_ACTION_SETf)) { 1146 qos_f = QOS_B_ACTION_SETf; 1147 } else { 1148 qos_f = 0; 1149 } 1150 if (qos_f) { 1151 qos = soc_mem_field32_get(unit, mem_view_id, tnl_entry, qos_f); 1152 dscp_sel = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt, 1153 &qos,QOS_ACTION_SELf); 1154 if (dscp_sel == _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE) { 1155 info->dscp_sel = bcmTunnelDscpAssign; 1156 } else if (dscp_sel == _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE) { 1157 info->dscp_sel = bcmTunnelDscpPacket; 1158 } else if (dscp_sel == _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB) { 1159 info->dscp_sel = bcmTunnelDscpMap; 1160 } else { 1161 info->dscp_sel = bcmTunnelDscpCount; 1162 } 1163 1164 if (info->dscp_sel == bcmTunnelDscpMap) { 1165 /* Set DSCP_MAP value. */ 1166 int hw_map_idx = 0; 1167 hw_map_idx = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt, 1168 &qos,QOS_MAPPING_PTRf); 1169 BCM_IF_ERROR_RETURN( 1170 _bcm_tr2_qos_idx2id(unit, hw_map_idx, 1171 _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE,&info->dscp_map)); 1172 } else { 1173 /* Set DSCP value. */ 1174 info->dscp = soc_format_field32_get(unit,QOS_A_ACTION_SETfmt, 1175 &qos,QOS_VALUEf); 1176 } 1177 } 1178 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, TTL_B_ACTION_SETf)) { 1179 ttl = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1180 TTL_B_ACTION_SETf); 1181 info->ttl = soc_format_field32_get(unit,TTL_B_ACTION_SETfmt, 1182 &ttl,TTL_VALUEf); 1183 } 1184 1185 /* Set UDP Dest Port */ 1186 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1187 DIRECT_ASSIGNMENT_18_ACTION_SETf)) { 1188 info->udp_dst_port = soc_mem_field32_get(unit, mem_view_id, 1189 tnl_entry, DIRECT_ASSIGNMENT_18_ACTION_SETf); 1190 } 1191 1192 /* Set UDP Src Port */ 1193 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1194 DIRECT_ASSIGNMENT_19_ACTION_SETf)) { 1195 info->udp_src_port = soc_mem_field32_get(unit, mem_view_id, 1196 tnl_entry, DIRECT_ASSIGNMENT_19_ACTION_SETf); 1197 } 1198 1199 /* FRAGMENT ID */ 1200 if (SOC_MEM_FIELD_VALID(unit,mem_view_id, 1201 SEQUENCE_NUMBER_ACTION_SETf)) { 1202 uint32 seq_num; 1203 uint32 inx; 1204 1205 seq_num = soc_mem_field32_get(unit, mem_view_id, tnl_entry, 1206 SEQUENCE_NUMBER_ACTION_SETf); 1207 inx = soc_format_field32_get(unit,SEQUENCE_NUMBER_ACTION_SETfmt, 1208 &seq_num, SEQ_NUM_COUNTER_INDEXf); 1209 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1210 MEM_BLOCK_ANY, inx, &entry)); 1211 info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1212 &entry, SEQUENCE_NUMBERf); 1213 } 1214 1215 } 1216 1217 if ((fixed_view == FALSE) && (field != NULL) && (num_of_fields)) { 1218 rv = soc_flow_db_mem_view_field_list_get(unit, 1219 mem_view_id, 1220 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1221 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 1222 SOC_IF_ERROR_RETURN(rv); 1223 1224 if (field_cnt == NULL) { 1225 for (i = 0; i < num_of_fields; i++) { 1226 for (j = 0; j < cnt; j++) { 1227 if (field[i].id == data_ids[j]) { 1228 field[i].value = soc_mem_field32_get(unit,mem_view_id, 1229 tnl_entry, field[i].id); 1230 break; 1231 } 1232 } 1233 } 1234 } else { 1235 *field_cnt = cnt < num_of_fields? cnt: num_of_fields; 1236 if (cnt > num_of_fields) { 1237 cnt = num_of_fields; 1238 } 1239 for (i = 0; i < cnt; i++) { 1240 field[i].id = data_ids[i]; 1241 field[i].value = soc_mem_field32_get(unit,mem_view_id, tnl_entry, 1242 field[i].id); 1243 } 1244 } 1245 } 1246 return BCM_E_NONE; 1247 } 1248 1249 /* 1250 * Function: 1251 * _bcm_flow_tunnel_init_set 1252 * Purpose: 1253 * Add tunnel initiator entry to hw. 1254 * Parameters: 1255 * unit - (IN)SOC unit number. 1256 * idx - (IN)Index to insert tunnel initiator. 1257 * info - (IN)Tunnel initiator entry info. 1258 * Returns: 1259 * BCM_E_XXX 1260 */ 1261 STATIC int 1262 _bcm_flow_tunnel_init_set(int unit, 1263 int idx, 1264 bcm_flow_tunnel_initiator_t *info, 1265 bcm_flow_logical_field_t *field, 1266 int num_of_fields, 1267 int *tnl_in_oif) 1268 { 1269 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */ 1270 soc_mem_t mem; /* Tunnel initiator table memory */ 1271 soc_mem_t mem_view; 1272 int rv = BCM_E_NONE; /* Return value */ 1273 int df_val=0; /* Don't fragment encoding */ 1274 uint32 sip6[4]; 1275 uint32 dip6[4]; 1276 uint32 data_ids[_BCM_FLOW_LOGICAL_FIELD_MAX]; 1277 uint32 cnt; 1278 int i; 1279 int j; 1280 int ipv6; 1281 int entry_type = BCM_XGS3_TUNNEL_INIT_V4; 1282 uint16 random; 1283 egr_sequence_number_table_entry_t entry; 1284 _bcm_flow_bookkeeping_t *flow_info; 1285 1286 flow_info = FLOW_INFO(unit); 1287 1288 ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(info->type); 1289 if (_BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(info->type)) { 1290 idx >>= 1; 1291 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6); 1292 } else { 1293 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 1294 } 1295 if (!SOC_MEM_IS_VALID(unit, mem)) { 1296 return (BCM_E_UNAVAIL); 1297 } 1298 1299 rv = _bcm_flow_tunnel_dip_idx_set(unit, info, idx, tnl_in_oif); 1300 BCM_IF_ERROR_RETURN(rv); 1301 1302 /* get the physical memory view */ 1303 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1304 rv = soc_flow_db_ffo_to_mem_view_id_get(unit,info->flow_handle, 1305 info->flow_option, 1306 SOC_FLOW_DB_FUNC_TUNNEL_INITIATOR_ID, 1307 (uint32 *)&mem_view); 1308 BCM_IF_ERROR_RETURN(rv); 1309 } 1310 1311 soc_mem_lock(unit,mem); 1312 if (info->flags & BCM_TUNNEL_REPLACE) { 1313 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry); 1314 if (SOC_FAILURE(rv)) { 1315 soc_mem_unlock(unit,mem); 1316 return rv; 1317 } 1318 } else { 1319 /* Zero write buffer. */ 1320 sal_memset(tnl_entry, 0, sizeof(tnl_entry)); 1321 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 1322 soc_flow_db_mem_view_entry_init(unit,mem_view,tnl_entry); 1323 } 1324 } 1325 1326 /* flex view doesn't seem to have these functions */ 1327 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 1328 1329 if ((!ipv6) && SOC_MEM_FIELD_VALID(unit, mem, IPV4_DF_SELf)) { 1330 /* Outer IPv4 tunnel hdr DF bit for Inner IPv4 hdr. */ 1331 df_val = 0; 1332 if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) { 1333 df_val |= 0x2; 1334 } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) { 1335 df_val |= 0x1; 1336 } 1337 soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val); 1338 } 1339 1340 if ((!ipv6) && SOC_MEM_FIELD_VALID(unit, mem, IPV6_DF_SELf)) { 1341 /* Outer IPv4 tunnel hdr DF bit for Inner IPv6 hdr. */ 1342 df_val = (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) ? 0x1 : 0; 1343 soc_mem_field32_set(unit, mem, tnl_entry, IPV6_DF_SELf, df_val); 1344 } 1345 1346 } 1347 1348 if (!_BCM_FLOW_IS_FLEX_VIEW(info)) { 1349 1350 if (ipv6) { 1351 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) { 1352 /* Set destination ipv6 address. */ 1353 soc_mem_ip6_addr_set(unit, mem, tnl_entry, DIPf, info->dip6, 1354 SOC_MEM_IP6_FULL_ADDR); 1355 } 1356 1357 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) { 1358 /* Set source ipv6 address. */ 1359 soc_mem_ip6_addr_set(unit, mem, tnl_entry, SIPf, info->sip6, 1360 SOC_MEM_IP6_FULL_ADDR); 1361 } 1362 } else { 1363 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 1364 /* Set destination address. */ 1365 soc_mem_field_set(unit, mem, tnl_entry, DIPf, 1366 (uint32 *)&info->dip); 1367 } 1368 1369 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) { 1370 /* Set source address. */ 1371 soc_mem_field_set(unit, mem, tnl_entry, SIPf, 1372 (uint32 *)&info->sip); 1373 } 1374 } 1375 1376 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) { 1377 /* Tunnel header DSCP select. */ 1378 soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf,info->dscp_sel); 1379 1380 if (info->dscp_sel == bcmTunnelDscpMap) { 1381 /* Set DSCP_MAP value. */ 1382 int hw_map_idx = 0; 1383 rv = _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx); 1384 if (SOC_FAILURE(rv)) { 1385 soc_mem_unlock(unit,mem); 1386 return rv; 1387 } 1388 1389 soc_mem_field32_set(unit, mem, tnl_entry, 1390 DSCP_MAPPING_PTRf, hw_map_idx); 1391 } else { 1392 /* Set DSCP value. */ 1393 soc_mem_field32_set(unit, mem, tnl_entry, DSCPf, info->dscp); 1394 } 1395 } 1396 1397 /* Set TTL. */ 1398 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) { 1399 soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl); 1400 } 1401 1402 /* Set UDP Dest Port */ 1403 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_DPORT_VALID) { 1404 soc_mem_field32_set(unit, mem, tnl_entry, L4_DEST_PORTf, 1405 info->udp_dst_port); 1406 } 1407 1408 /* Set UDP Src Port */ 1409 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_SPORT_VALID) { 1410 soc_mem_field32_set(unit, mem, tnl_entry, L4_SRC_PORTf, 1411 info->udp_src_port); 1412 } 1413 1414 /* Set destination mac address. */ 1415 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DMAC_VALID) { 1416 if (SOC_MEM_FIELD_VALID(unit, mem, DEST_ADDRf)) { 1417 soc_mem_mac_addr_set(unit, mem, &tnl_entry, DEST_ADDRf, 1418 info->dmac); 1419 } 1420 } 1421 1422 /* IPv4 Fragment ID */ 1423 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_IP4_ID_VALID) { 1424 sal_memset(&entry,0,sizeof(egr_sequence_number_table_entry_t)); 1425 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) { 1426 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 1427 SEQUENCE_NUMBERf, info->ip4_id); 1428 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) { 1429 random = (uint16) (sal_time_usecs() & 0xFFFF); 1430 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 1431 SEQUENCE_NUMBERf, random); 1432 } 1433 rv = soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1434 MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry); 1435 if (SOC_FAILURE(rv)) { 1436 soc_mem_unlock(unit,mem); 1437 return rv; 1438 } 1439 } 1440 1441 if (info->type == bcmTunnelTypeVxlan) { 1442 /* Set Tunnel type = VXLAN */ 1443 soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 1444 _BCM_FLOW_VXLAN_TUNNEL_TYPE); 1445 } else if (info->type == bcmTunnelTypeL2Gre) { 1446 /* Set Tunnel type = L2GRE */ 1447 soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 1448 _BCM_FLOW_L2GRE_TUNNEL_TYPE); 1449 } else { 1450 int hw_code; 1451 1452 rv = _bcm_trx_tnl_type_to_hw_code(unit, info->type, 1453 &hw_code, &entry_type); 1454 if (SOC_FAILURE(rv)) { 1455 soc_mem_unlock(unit,mem); 1456 return rv; 1457 } 1458 soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, 1459 hw_code); 1460 1461 } 1462 1463 /* Set entry type = IPv4 */ 1464 if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) { 1465 soc_mem_field32_set(unit, mem, tnl_entry, DATA_TYPEf, 1466 _BCM_FLOW_TUNNEL_DATA_TYPE_IPV6); 1467 } else { /* ipv4 */ 1468 soc_mem_field32_set(unit, mem, tnl_entry, DATA_TYPEf, 1469 _BCM_FLOW_TUNNEL_DATA_TYPE_IPV4); 1470 } 1471 1472 } else { /* flex view */ 1473 uint32 qos = 0; 1474 uint32 ttl = 0; 1475 1476 if (info->type == bcmTunnelTypeL3Flex) { 1477 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP_VALID) { 1478 if (SOC_MEM_FIELD_VALID(unit,mem_view, 1479 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 1480 soc_mem_field32_set(unit, mem_view, tnl_entry, 1481 DIRECT_ASSIGNMENT_10_ACTION_SETf, info->dip); 1482 } 1483 } 1484 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DIP6_VALID) { 1485 1486 SAL_IP6_ADDR_TO_UINT32(info->dip6,dip6); 1487 1488 /* OUTER_IPV6_DIP_0_31 */ 1489 if (SOC_MEM_FIELD_VALID(unit,mem_view, 1490 DIRECT_ASSIGNMENT_10_ACTION_SETf)) { 1491 soc_mem_field32_set(unit, mem_view, tnl_entry, 1492 DIRECT_ASSIGNMENT_10_ACTION_SETf, dip6[0]); 1493 } 1494 1495 /* OUTER_IPV6_DIP_32_63 */ 1496 if (SOC_MEM_FIELD_VALID(unit,mem_view, 1497 DIRECT_ASSIGNMENT_12_ACTION_SETf)) { 1498 soc_mem_field32_set(unit, mem_view, tnl_entry, 1499 DIRECT_ASSIGNMENT_12_ACTION_SETf, dip6[1]); 1500 } 1501 1502 /* OUTER_IPV6_DIP_64_95 */ 1503 if (SOC_MEM_FIELD_VALID(unit,mem_view, 1504 DIRECT_ASSIGNMENT_14_ACTION_SETf)) { 1505 soc_mem_field32_set(unit, mem_view, tnl_entry, 1506 DIRECT_ASSIGNMENT_14_ACTION_SETf, dip6[2]); 1507 } 1508 1509 /* OUTER_IPV6_DIP_96_127 */ 1510 if (SOC_MEM_FIELD_VALID(unit,mem_view, 1511 DIRECT_ASSIGNMENT_16_ACTION_SETf)) { 1512 soc_mem_field32_set(unit, mem_view, tnl_entry, 1513 DIRECT_ASSIGNMENT_16_ACTION_SETf, dip6[3]); 1514 } 1515 } 1516 } 1517 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP_VALID) { 1518 soc_mem_field32_set(unit, mem_view, tnl_entry, 1519 DIRECT_ASSIGNMENT_11_ACTION_SETf, info->sip); 1520 } 1521 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_SIP6_VALID) { 1522 SAL_IP6_ADDR_TO_UINT32(info->sip6,sip6); 1523 soc_mem_field32_set(unit, mem_view, tnl_entry, 1524 DIRECT_ASSIGNMENT_11_ACTION_SETf, sip6[0]); 1525 soc_mem_field32_set(unit, mem_view, tnl_entry, 1526 DIRECT_ASSIGNMENT_13_ACTION_SETf, sip6[1]); 1527 soc_mem_field32_set(unit, mem_view, tnl_entry, 1528 DIRECT_ASSIGNMENT_15_ACTION_SETf, sip6[2]); 1529 soc_mem_field32_set(unit, mem_view, tnl_entry, 1530 DIRECT_ASSIGNMENT_17_ACTION_SETf, sip6[3]); 1531 } 1532 1533 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) { 1534 int sel_value; 1535 1536 if (info->dscp_sel == bcmTunnelDscpAssign) { 1537 sel_value = _BCM_FLOW_DSCP_SEL_ASSIGN_FROM_TABLE; 1538 } else if (info->dscp_sel == bcmTunnelDscpPacket) { 1539 sel_value = _BCM_FLOW_DSCP_SEL_COPY_FROM_ZONE; 1540 } else if (info->dscp_sel == bcmTunnelDscpMap) { 1541 sel_value = _BCM_FLOW_DSCP_SEL_MAP_FROM_PHB; 1542 } else { 1543 sel_value = 0; /* do not modify */ 1544 } 1545 soc_format_field32_set(unit,QOS_A_ACTION_SETfmt, 1546 &qos,QOS_ACTION_SELf, sel_value); 1547 if (info->dscp_sel == bcmTunnelDscpMap) { 1548 /* Set DSCP_MAP value. */ 1549 int hw_map_idx = 0; 1550 rv = _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx); 1551 if (SOC_FAILURE(rv)) { 1552 soc_mem_unlock(unit,mem); 1553 return rv; 1554 } 1555 soc_format_field32_set(unit,QOS_A_ACTION_SETfmt, 1556 &qos,QOS_MAPPING_PTRf, hw_map_idx); 1557 } else { 1558 /* Set DSCP value. */ 1559 soc_format_field32_set(unit,QOS_A_ACTION_SETfmt, 1560 &qos,QOS_VALUEf, info->dscp); 1561 } 1562 soc_mem_field32_set(unit, mem_view, tnl_entry, QOS_A_ACTION_SETf, qos); 1563 } 1564 1565 /* Set TTL. */ 1566 soc_format_field32_set(unit,TTL_B_ACTION_SETfmt, 1567 &ttl,TTL_ACTION_TYPEf, 1); 1568 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) { 1569 soc_format_field32_set(unit,TTL_B_ACTION_SETfmt, 1570 &ttl,TTL_VALUEf, info->ttl); 1571 } else { 1572 soc_format_field32_set(unit,TTL_B_ACTION_SETfmt, 1573 &ttl,TTL_VALUEf, 0xff); 1574 } 1575 soc_mem_field32_set(unit, mem_view, tnl_entry, TTL_B_ACTION_SETf, ttl); 1576 1577 /* Set UDP Dest Port */ 1578 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_DPORT_VALID) { 1579 soc_mem_field32_set(unit, mem_view, tnl_entry, 1580 DIRECT_ASSIGNMENT_18_ACTION_SETf, info->udp_dst_port); 1581 } 1582 1583 /* Set UDP Src Port */ 1584 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_UDP_SPORT_VALID) { 1585 soc_mem_field32_set(unit, mem_view, tnl_entry, 1586 DIRECT_ASSIGNMENT_19_ACTION_SETf, info->udp_src_port); 1587 } 1588 1589 if (SOC_MEM_FIELD_VALID(unit,mem_view, ECN_ACTION_SETf)) { 1590 uint32 ecn = 0; 1591 soc_format_field32_set(unit,ECN_ACTION_SETfmt,&ecn, ECN_VALUEf, 0); 1592 soc_format_field32_set(unit,ECN_ACTION_SETfmt,&ecn, CHANGE_ECNf, 1); 1593 soc_mem_field32_set(unit, mem_view, tnl_entry, ECN_ACTION_SETf, ecn); 1594 } 1595 1596 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_IP4_ID_VALID) { 1597 uint32 seq_num = 0; 1598 1599 /* Use the same tunnel base as for the fixed view */ 1600 soc_format_field32_set(unit,SEQUENCE_NUMBER_ACTION_SETfmt, 1601 &seq_num, SEQ_NUM_PROFILE_INDEXf, 1); 1602 soc_format_field32_set(unit,SEQUENCE_NUMBER_ACTION_SETfmt, 1603 &seq_num, SEQ_NUM_COUNTER_INDEXf, 1604 idx + flow_info->frag_base_inx); 1605 soc_mem_field32_set(unit, mem_view, tnl_entry, 1606 SEQUENCE_NUMBER_ACTION_SETf, seq_num); 1607 sal_memset(&entry,0,sizeof(egr_sequence_number_table_entry_t)); 1608 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) { 1609 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 1610 SEQUENCE_NUMBERf, info->ip4_id); 1611 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) { 1612 random = (uint16) (sal_time_usecs() & 0xFFFF); 1613 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry, 1614 SEQUENCE_NUMBERf, random); 1615 } 1616 rv = soc_mem_write(unit, EGR_SEQUENCE_NUMBER_TABLEm, 1617 MEM_BLOCK_ANY, idx + flow_info->frag_base_inx, &entry); 1618 if (SOC_FAILURE(rv)) { 1619 soc_mem_unlock(unit,mem); 1620 return rv; 1621 } 1622 } 1623 1624 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_FLEX_VALID) { 1625 rv = soc_flow_db_mem_view_field_list_get(unit, 1626 mem_view, 1627 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 1628 _BCM_FLOW_LOGICAL_FIELD_MAX, data_ids, &cnt); 1629 if (SOC_FAILURE(rv)) { 1630 soc_mem_unlock(unit,mem); 1631 return rv; 1632 } 1633 for (i = 0; i < num_of_fields; i++) { 1634 for (j = 0; j < cnt; j++) { 1635 if (field[i].id == data_ids[j]) { 1636 soc_mem_field32_set(unit,mem_view, tnl_entry, 1637 field[i].id, field[i].value); 1638 break; 1639 } 1640 } 1641 } 1642 } 1643 } 1644 1645 /* Write buffer to hw. */ 1646 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry); 1647 soc_mem_unlock(unit,mem); 1648 return rv; 1649 } 1650 1651 /* 1652 * Function: 1653 * _bcm_flow_tunnel_initiator_entry_add 1654 * Purpose: 1655 * Configure VXLAN Tunnel initiator hardware Entry 1656 * Returns: 1657 * BCM_E_XXX 1658 */ 1659 STATIC int 1660 _bcm_flow_tunnel_initiator_entry_add(int unit, 1661 uint32 flags, 1662 bcm_flow_tunnel_initiator_t *info, 1663 bcm_flow_logical_field_t *field, 1664 uint32 num_of_fields) 1665 { 1666 int tnl_idx; 1667 int rv = BCM_E_NONE; 1668 _bcm_flow_bookkeeping_t *flow_info; 1669 int dvp; 1670 int soft_tnl_idx = 0; 1671 int tnl_in_oif; 1672 int oif_idx; 1673 1674 flow_info = FLOW_INFO(unit); 1675 1676 if (info->flags & BCM_TUNNEL_REPLACE) { 1677 soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 1678 tnl_idx = flow_info->init_tunnel[soft_tnl_idx].idx; 1679 if (tnl_idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) { 1680 /* l3_oif index */ 1681 oif_idx = tnl_idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit); 1682 BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit, 1683 oif_idx, &tnl_idx)); 1684 info->l3_intf_id = oif_idx; 1685 } 1686 1687 /* cannot modify if this tunnel is used more than once */ 1688 if (BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, tnl_init),tnl_idx) 1689 > 1) { 1690 return BCM_E_PARAM; 1691 } 1692 } 1693 1694 rv = _bcm_flow_tnl_init_add(unit, flags, info, field, 1695 num_of_fields,&tnl_idx); 1696 if (BCM_FAILURE(rv)) { 1697 return rv; 1698 } 1699 /* Write the entry to HW */ 1700 rv = _bcm_flow_tunnel_init_set(unit, tnl_idx, info,field,num_of_fields, 1701 &tnl_in_oif); 1702 if (BCM_FAILURE(rv)) { 1703 flags = _BCM_L3_SHR_WRITE_DISABLE; 1704 (void) bcm_xgs3_tnl_init_del(unit, flags, tnl_idx); 1705 BCM_IF_ERROR_RETURN(rv); 1706 } 1707 if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) { 1708 if (!(info->flags & BCM_TUNNEL_REPLACE)) { 1709 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 1710 soft_tnl_idx = dvp; 1711 } 1712 if (tnl_in_oif == TRUE) { 1713 /* tunnel index in oif, save oif instead */ 1714 flow_info->init_tunnel[soft_tnl_idx].idx = 1715 _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit) + info->l3_intf_id; 1716 } else { 1717 flow_info->init_tunnel[soft_tnl_idx].idx = tnl_idx; 1718 } 1719 } else { /* L3 tunnel */ 1720 if (!(info->flags & BCM_TUNNEL_REPLACE)) { 1721 soft_tnl_idx = _BCM_FLOW_TUNNEL_L2_MAX(unit) + info->l3_intf_id; 1722 } 1723 flow_info->init_tunnel[soft_tnl_idx].idx = tnl_idx; 1724 } 1725 BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id,soft_tnl_idx); 1726 return rv; 1727 } 1728 1729 /* 1730 * Function: 1731 * _bcm_esw_flow_tnl_initiator_validate 1732 * Purpose: 1733 * Validate the tunnel initiator attributes 1734 * 1735 * Parameters: 1736 * unit - (IN) Device Number 1737 * info - (IN) Flow tunnel initiator descriptor 1738 * Returns: 1739 * TRUE/FALSE 1740 */ 1741 STATIC 1742 int _bcm_esw_flow_tnl_initiator_validate( 1743 int unit, 1744 bcm_flow_tunnel_initiator_t *info) 1745 { 1746 if (NULL == info) { 1747 return (BCM_E_PARAM); 1748 } 1749 if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) && 1750 (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) { 1751 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1752 "Flow Tunnel Initiation: Invalid tunnel type.\n"))); 1753 return BCM_E_PARAM; 1754 } 1755 1756 if (((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 1757 (info->type != bcmTunnelTypeVxlan)) || 1758 ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) && 1759 (info->type != bcmTunnelTypeL2Gre)) || 1760 ((info->flow_handle >= SOC_FLOW_DB_FLOW_ID_START) && 1761 ((info->type == bcmTunnelTypeL2Gre) || 1762 (info->type == bcmTunnelTypeVxlan)))) { 1763 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1764 "Flow Tunnel Initiation: tunnel type and flow handle mismatch.\n"))); 1765 return BCM_E_PARAM; 1766 } 1767 1768 return BCM_E_NONE; 1769 } 1770 1771 /* 1772 * Function: 1773 * bcmi_esw_flow_tunnel_initiator_create 1774 * Purpose: 1775 * Create a flow tunnel initiator object on the given flow port for L2 1776 * tunnel or on the given L3 interface for L3 tunnel. 1777 * 1778 * Parameters: 1779 * unit - (IN) Device Number 1780 * info - (IN/OUT) Flow tunnel initiator descriptor 1781 * num_of_fields - (IN) number of logical fields 1782 * field - (IN) logical field array 1783 * Returns: 1784 * BCM_E_XXX 1785 */ 1786 int bcmi_esw_flow_tunnel_initiator_create( 1787 int unit, 1788 bcm_flow_tunnel_initiator_t *info, 1789 uint32 num_of_fields, 1790 bcm_flow_logical_field_t *field) 1791 { 1792 int rv = BCM_E_NONE; 1793 uint32 flags=0; 1794 int soft_tnl_idx; 1795 _bcm_flow_bookkeeping_t *flow_info; 1796 int dvp; 1797 int l2_tunnel; 1798 1799 flow_info = FLOW_INFO(unit); 1800 1801 BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_initiator_validate(unit, info)); 1802 1803 l2_tunnel = FALSE; 1804 1805 if (info->flags & BCM_TUNNEL_REPLACE) { 1806 1807 /* validate the tunnel index */ 1808 soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 1809 _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(unit, soft_tnl_idx); 1810 1811 /* check if tunnel exist */ 1812 if (!flow_info->init_tunnel[soft_tnl_idx].idx) { 1813 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1814 "Invalid replace action, tunnel not created\n"))); 1815 return BCM_E_PARAM; 1816 } 1817 if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 1818 l2_tunnel = TRUE; 1819 } 1820 1821 if (l2_tunnel) { 1822 /* flow_port and l3_intf_id cannot be replaced */ 1823 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port,soft_tnl_idx); 1824 } else { 1825 /* L3 tunnel */ 1826 info->l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit); 1827 } 1828 } else { 1829 if (_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) { 1830 l2_tunnel = TRUE; 1831 } 1832 } 1833 1834 /* Input parameters check. */ 1835 if (l2_tunnel) { 1836 1837 /* check the dvp is in range and already created and dvp_encap is set 1838 * The dvp entry should be already initialized. flow_port_encap_set 1839 * should be called first 1840 */ 1841 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 1842 _BCM_FLOW_TUNNEL_ID_IF_INVALID_RETURN(unit, dvp); 1843 1844 if (!_BCM_FLOW_EGR_DVP_USED_GET(unit,dvp)) { 1845 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1846 "dvp(%d) type not set, call bcm_flow_port_encap_set first\n"), 1847 dvp)); 1848 return BCM_E_PARAM; 1849 } 1850 1851 if (!(info->flags & BCM_TUNNEL_REPLACE)) { 1852 soft_tnl_idx = dvp; 1853 if (flow_info->init_tunnel[soft_tnl_idx].idx) { 1854 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1855 "tunnel already created, use replace action to change\n"))); 1856 return BCM_E_PARAM; 1857 } 1858 } 1859 } else { /* l3 tunnel */ 1860 /* make sure intf_id is valid */ 1861 if (info->l3_intf_id >= _BCM_FLOW_TUNNEL_L3_MAX(unit)) { 1862 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1863 "Invalid l3 interface ID\n"))); 1864 return BCM_E_PARAM; 1865 } 1866 if (!(info->flags & BCM_TUNNEL_REPLACE)) { 1867 soft_tnl_idx = _BCM_FLOW_TUNNEL_L2_MAX(unit) + info->l3_intf_id; 1868 /* tunnel already exists */ 1869 if (flow_info->init_tunnel[soft_tnl_idx].idx) { 1870 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 1871 "L3 tunnel exists, use replace action to change\n"))); 1872 return BCM_E_PARAM; 1873 } 1874 } 1875 } 1876 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_TTL_VALID) { 1877 if (!BCM_TTL_VALID(info->ttl)) { 1878 return BCM_E_PARAM; 1879 } 1880 } 1881 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_DSCP_VALID) { 1882 if (info->dscp_sel > 2 || info->dscp_sel < 0) { 1883 return BCM_E_PARAM; 1884 } 1885 1886 if (info->dscp > 63 || info->dscp < 0) { 1887 return BCM_E_PARAM; 1888 } 1889 } 1890 if (info->valid_elements & BCM_FLOW_TUNNEL_INIT_FLEX_VALID) { 1891 if ((field == NULL) || (!num_of_fields)) { 1892 return BCM_E_PARAM; 1893 } 1894 } 1895 flags = _BCM_L3_SHR_WRITE_DISABLE | _BCM_L3_SHR_SKIP_INDEX_ZERO; 1896 1897 /* XXXX use this flag _BCM_L3_SHR_MATCH_DISABLE? */ 1898 /* flags |= _BCM_L3_SHR_MATCH_DISABLE; */ 1899 1900 if (info->flags & BCM_TUNNEL_REPLACE) { 1901 flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID; 1902 } 1903 1904 /* Allocate either existing or new tunnel initiator entry */ 1905 BCM_XGS3_L3_MODULE_LOCK(unit); 1906 rv = _bcm_flow_tunnel_initiator_entry_add(unit, flags, info, 1907 field,num_of_fields); 1908 BCM_XGS3_L3_MODULE_UNLOCK(unit); 1909 return rv; 1910 } 1911 1912 /* 1913 * Function: 1914 * bcmi_esw_flow_tunnel_initiator_destroy 1915 * Purpose: 1916 * Delete the flow tunnel initiator object 1917 * 1918 * Parameters: 1919 * unit - (IN) Device Number 1920 * flow_tunnel_id - (IN/OUT) Flow tunnel initiator object ID 1921 * Returns: 1922 * BCM_E_XXX 1923 */ 1924 int bcmi_esw_flow_tunnel_initiator_destroy( 1925 int unit, 1926 bcm_gport_t flow_tunnel_id) 1927 { 1928 int soft_tnl_idx; 1929 _bcm_flow_bookkeeping_t *flow_info; 1930 bcm_flow_tunnel_initiator_t info; 1931 uint32 flags = 0; 1932 int idx; 1933 int rv; 1934 int oif_idx; 1935 _bcm_l3_tbl_op_t data; /* Delete operation info. */ 1936 uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */ 1937 soc_mem_t mem; 1938 int data_type; 1939 1940 mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4); 1941 bcm_flow_tunnel_initiator_t_init(&info); 1942 soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(flow_tunnel_id); 1943 flow_info = FLOW_INFO(unit); 1944 1945 if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 1946 /* L2 tunnel */ 1947 _SHR_GPORT_FLOW_PORT_ID_SET(info.flow_port,soft_tnl_idx); 1948 info.valid_elements = BCM_FLOW_TUNNEL_INIT_DIP_VALID | 1949 BCM_FLOW_TUNNEL_INIT_DIP6_VALID; 1950 info.type = bcmTunnelTypeL2Flex; 1951 1952 } else if (soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit)) { 1953 /* L3 tunnel */ 1954 info.l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit); 1955 } else { 1956 return BCM_E_NOT_FOUND; 1957 } 1958 idx = flow_info->init_tunnel[soft_tnl_idx].idx; 1959 1960 if (idx >= _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit)) { 1961 /* l3_oif index */ 1962 oif_idx = idx - _BCM_FLOW_TUNNEL_IP_TUNNEL_MAX(unit); 1963 info.l3_intf_id = oif_idx; 1964 BCM_IF_ERROR_RETURN(_bcm_flow_tunnel_idx_from_oif_get(unit, 1965 oif_idx, &idx)); 1966 } 1967 1968 if (!idx) { 1969 return BCM_E_NOT_FOUND; 1970 } 1971 1972 BCM_XGS3_L3_MODULE_LOCK(unit); 1973 rv = _bcm_flow_tunnel_dip_idx_set(unit, &info, 0, NULL); 1974 if (BCM_SUCCESS(rv)) { 1975 flags = _BCM_L3_SHR_WRITE_DISABLE; 1976 1977 /* Initialization */ 1978 sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t)); 1979 1980 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx,tnl_entry); 1981 if (SOC_FAILURE(rv)) { 1982 BCM_XGS3_L3_MODULE_UNLOCK(unit); 1983 return rv; 1984 } 1985 data_type = soc_mem_field32_get(unit, mem, tnl_entry, DATA_TYPEf); 1986 1987 if (_BCM_FLOW_TUNNEL_ENTRY_DOUBLE_WIDE(data_type)) { 1988 data.width = _BCM_DOUBLE_WIDE; 1989 } else { 1990 /* Default is single table entry operation.*/ 1991 data.width = _BCM_SINGLE_WIDE; 1992 } 1993 1994 data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, tnl_init); 1995 data.entry_index = idx; 1996 data.oper_flags = flags; 1997 data.delete_func = BCM_XGS3_L3_HWCALL(unit, tnl_init_del); 1998 1999 /* Delete tunnel initiator table entry. */ 2000 rv = _bcm_xgs3_tbl_del(unit, &data); 2001 if (SOC_FAILURE(rv)) { 2002 BCM_XGS3_L3_MODULE_UNLOCK(unit); 2003 return rv; 2004 } 2005 /* don't clear if the entry is still been referenced by other objs */ 2006 if (!BCM_XGS3_L3_ENT_REF_CNT(data.tbl_ptr, idx)) { 2007 (void) _bcm_flow_tunnel_init_delete(unit, idx, data.width); 2008 } 2009 flow_info->init_tunnel[soft_tnl_idx].idx = 0; 2010 } 2011 BCM_XGS3_L3_MODULE_UNLOCK(unit); 2012 2013 return rv; 2014 } 2015 2016 /* 2017 * Function: 2018 * bcmi_esw_flow_tunnel_initiator_destroy_all 2019 * Purpose: 2020 * Delete all flow tunnel initiator object 2021 * 2022 * Parameters: 2023 * unit - (IN) Device Number 2024 * Returns: 2025 * BCM_E_XXX 2026 */ 2027 int bcmi_esw_flow_tunnel_initiator_destroy_all( 2028 int unit) 2029 { 2030 int soft_tnl_idx; 2031 _bcm_flow_bookkeeping_t *flow_info; 2032 int num_tnl = 0; 2033 bcm_gport_t flow_tunnel_id; 2034 int rv = 0; 2035 2036 num_tnl = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm) + 2037 soc_mem_index_count(unit, EGR_L3_INTFm); 2038 2039 flow_info = FLOW_INFO(unit); 2040 for (soft_tnl_idx = 0; soft_tnl_idx < num_tnl; soft_tnl_idx++) { 2041 if (flow_info->init_tunnel[soft_tnl_idx].idx) { 2042 BCM_GPORT_TUNNEL_ID_SET(flow_tunnel_id, soft_tnl_idx); 2043 rv = bcmi_esw_flow_tunnel_initiator_destroy(unit, flow_tunnel_id); 2044 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 2045 return rv; 2046 } 2047 } 2048 } 2049 2050 return BCM_E_NONE; 2051 } 2052 2053 /* 2054 * Function: 2055 * bcmi_esw_flow_tunnel_initiator_get 2056 * Purpose: 2057 * Retrieve the flow tunnel initiator object on the given flow port for L2 2058 * tunnel or on the given L3 interface for L3 tunnel. 2059 * 2060 * Parameters: 2061 * unit - (IN) Device Number 2062 * info - (IN/OUT) Flow tunnel initiator descriptor 2063 * num_of_fields - (IN) number of logical fields 2064 * field - (IN) logical field array 2065 * Returns: 2066 * BCM_E_XXX 2067 */ 2068 int bcmi_esw_flow_tunnel_initiator_get( 2069 int unit, 2070 bcm_flow_tunnel_initiator_t *info, 2071 uint32 num_of_fields, 2072 bcm_flow_logical_field_t *field) 2073 { 2074 uint32 soft_tnl_idx; 2075 _bcm_flow_bookkeeping_t *flow_info; 2076 int dvp; 2077 int rv = BCM_E_NONE; 2078 2079 flow_info = FLOW_INFO(unit); 2080 2081 if (NULL == info) { 2082 return (BCM_E_PARAM); 2083 } 2084 2085 /* Input parameters check. */ 2086 soft_tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id); 2087 if (soft_tnl_idx >= (_BCM_FLOW_TUNNEL_L2_MAX(unit) + 2088 _BCM_FLOW_TUNNEL_L3_MAX(unit))) { 2089 return (BCM_E_PARAM); 2090 } 2091 2092 if (!flow_info->init_tunnel[soft_tnl_idx].idx) { 2093 return (BCM_E_PARAM); 2094 } 2095 2096 if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 2097 /* L2 tunnel */ 2098 dvp = _SHR_GPORT_FLOW_PORT_ID_GET(info->flow_port); 2099 if (!dvp) { 2100 _SHR_GPORT_FLOW_PORT_ID_SET(info->flow_port, soft_tnl_idx); 2101 } else if (dvp != soft_tnl_idx) { 2102 return BCM_E_PARAM; 2103 } 2104 } else if (soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit)) { 2105 /* L3 tunnel */ 2106 if (!info->l3_intf_id) { 2107 info->l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit); 2108 } else if (info->l3_intf_id != 2109 (soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit))) { 2110 return BCM_E_PARAM; 2111 } 2112 } else { 2113 return BCM_E_NOT_FOUND; 2114 } 2115 2116 rv = _bcm_flow_tunnel_init_get(unit, soft_tnl_idx, info,field, 2117 num_of_fields,NULL); 2118 return rv; 2119 } 2120 2121 /* 2122 * Function: 2123 * bcmi_esw_flow_tunnel_initiator_traverse 2124 * Purpose: 2125 * Traverse all flow tunnel initiator objects and call the user specified 2126 * callback function on each object. 2127 * 2128 * Parameters: 2129 * unit - (IN) Device Number 2130 * bcm_flow_tunnel_initiator_traverse_cb - (IN) user callback function 2131 * user_data - (IN) user context data for the callback 2132 * Returns: 2133 * BCM_E_XXX 2134 */ 2135 int bcmi_esw_flow_tunnel_initiator_traverse( 2136 int unit, 2137 bcm_flow_tunnel_initiator_traverse_cb cb, 2138 void *user_data) 2139 { 2140 bcm_flow_tunnel_initiator_t info; 2141 uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX; 2142 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 2143 int rv = BCM_E_NONE; 2144 uint32 soft_tnl_idx; 2145 _bcm_flow_bookkeeping_t *flow_info; 2146 uint32 cnt = 0; 2147 2148 if (NULL == cb) { 2149 return (BCM_E_PARAM); 2150 } 2151 flow_info = FLOW_INFO(unit); 2152 2153 for (soft_tnl_idx = 0; soft_tnl_idx < _BCM_FLOW_TUNNEL_TBL_MAX(unit); 2154 soft_tnl_idx++) { 2155 if (!flow_info->init_tunnel[soft_tnl_idx].idx) { 2156 continue; 2157 } 2158 bcm_flow_tunnel_initiator_t_init(&info); 2159 BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id,soft_tnl_idx); 2160 rv = _bcm_flow_tunnel_init_get(unit, soft_tnl_idx, &info, field, 2161 num_of_fields,&cnt); 2162 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 2163 continue; 2164 } else if (BCM_FAILURE(rv)) { 2165 break; 2166 } 2167 if (soft_tnl_idx < _BCM_FLOW_TUNNEL_L2_MAX(unit)) { 2168 /* L2 tunnel */ 2169 _SHR_GPORT_FLOW_PORT_ID_SET(info.flow_port, soft_tnl_idx); 2170 2171 } else { 2172 /* L3 tunnel */ 2173 info.l3_intf_id = soft_tnl_idx - _BCM_FLOW_TUNNEL_L2_MAX(unit); 2174 } 2175 2176 rv = cb(unit,&info,cnt,field,user_data); 2177 if (BCM_FAILURE(rv)) { 2178 break; 2179 } 2180 } 2181 return rv; 2182 } 2183 2184 STATIC 2185 int _bcm_esw_flow_tnl_term_num_hw_entries_get(int unit, 2186 soc_mem_t mem, 2187 uint32 *entry, 2188 uint32 *num_hw_entries) 2189 { 2190 int mode; 2191 2192 if ((entry == NULL) || 2193 (num_hw_entries == NULL)) { 2194 return BCM_E_PARAM; 2195 } 2196 *num_hw_entries = 0; 2197 if (mem == L3_TUNNELm) { 2198 mode = soc_mem_field32_get(unit, mem, entry, MODEf); 2199 if (mode == _BCM_FLOW_TD3_L3_TUNNEL_QUAD_WIDE) { 2200 *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_QUAD; 2201 } else if (mode == _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE_WIDE) { 2202 *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_DOUBLE; 2203 } else { 2204 *num_hw_entries = _BCM_FLOW_TD3_L3_TUNNEL_WIDTH_SINGLE; 2205 } 2206 return BCM_E_NONE; 2207 } 2208 return BCM_E_PARAM; 2209 } 2210 2211 int bcmi_esw_flow_entry_to_tnl_term(int unit, 2212 uint32 *entry, 2213 soc_tunnel_term_t *tnl_term) 2214 { 2215 uint32 num_hw_entries = 0; 2216 uint32 i = 0; 2217 uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE; 2218 2219 BCM_IF_ERROR_RETURN( 2220 _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, L3_TUNNELm, 2221 entry, &num_hw_entries)); 2222 for (i = 0; i < num_hw_entries; i++) { 2223 sal_memcpy((uint8 *) &tnl_term->entry_arr[i], 2224 entry + entry_width * i, entry_width); 2225 } 2226 return BCM_E_NONE; 2227 } 2228 2229 int bcmi_esw_flow_tnl_term_to_entry(int unit, 2230 soc_tunnel_term_t *tnl_term, 2231 uint32 *entry) 2232 { 2233 uint32 num_hw_entries = 0; 2234 uint32 i = 0; 2235 uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE; 2236 2237 BCM_IF_ERROR_RETURN( 2238 _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, L3_TUNNELm, 2239 entry, &num_hw_entries)); 2240 for (i = 0; i < num_hw_entries; i++) { 2241 sal_memcpy(entry + (entry_width * i), 2242 (uint8 *) &tnl_term->entry_arr[i], 2243 entry_width); 2244 } 2245 return BCM_E_NONE; 2246 } 2247 2248 /* 2249 * Function: 2250 * _bcm_esw_flow_tnl_term_validate 2251 * Purpose: 2252 * Validate the tunnel terrmination attributes 2253 * 2254 * Parameters: 2255 * unit - (IN) Device Number 2256 * info - (IN) Flow tunnel terminator descriptor 2257 * Returns: 2258 * TRUE/FALSE 2259 */ 2260 STATIC 2261 int _bcm_esw_flow_tnl_term_validate( 2262 int unit, 2263 bcm_flow_tunnel_terminator_t *info) 2264 { 2265 2266 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_VALID) { 2267 if (0 == info->dip) { 2268 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2269 "Flow Tunnel Termination : \ 2270 mismatch valid_elements flag and dip field\n"))); 2271 return FALSE; 2272 } 2273 } 2274 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_VALID) { 2275 if (0 == info->sip) { 2276 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2277 "Flow Tunnel Termination : \ 2278 mismatch valid_elements flag and sip field\n"))); 2279 return FALSE; 2280 } 2281 } 2282 2283 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID) { 2284 if (0 == info->sip_mask) { 2285 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2286 "Flow Tunnel Termination : \ 2287 mismatch valid_elements flag and sip_mask field\n"))); 2288 return FALSE; 2289 } 2290 } 2291 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID) { 2292 if (0 == info->dip_mask) { 2293 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2294 "Flow Tunnel Termination : \ 2295 mismatch valid_elements flag and dip_mask field\n"))); 2296 return FALSE; 2297 } 2298 } 2299 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_VALID) { 2300 if (!bcmi_flow_ip6_addr_is_valid(info->dip6)) { 2301 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2302 "Flow Tunnel Termination : \ 2303 mismatch valid_elements flag and dip6 field\n"))); 2304 return FALSE; 2305 } 2306 } 2307 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_VALID) { 2308 if (!bcmi_flow_ip6_addr_is_valid(info->sip6)) { 2309 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2310 "Flow Tunnel Termination : \ 2311 mismatch valid_elements flag and sip6 field\n"))); 2312 return FALSE; 2313 } 2314 } 2315 2316 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID) { 2317 if (!bcmi_flow_ip6_addr_is_valid(info->sip6_mask)) { 2318 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2319 "Flow Tunnel Termination : \ 2320 mismatch valid_elements flag and sip6_mask field\n"))); 2321 return FALSE; 2322 } 2323 } 2324 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID) { 2325 if (!bcmi_flow_ip6_addr_is_valid(info->dip6_mask)) { 2326 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2327 "Flow Tunnel Termination : \ 2328 mismatch valid_elements flag and dip6_mask field\n"))); 2329 return FALSE; 2330 } 2331 } 2332 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID) { 2333 if (0 == info->udp_src_port) { 2334 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2335 "Flow Tunnel Termination : \ 2336 mismatch valid_elements flag and udp_src_port field\n"))); 2337 return FALSE; 2338 } 2339 } 2340 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID) { 2341 if (0 == info->udp_dst_port) { 2342 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2343 "Flow Tunnel Termination : \ 2344 mismatch valid_elements flag and udp_dst_port field\n"))); 2345 return FALSE; 2346 } 2347 } 2348 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID) { 2349 if (0 == info->protocol) { 2350 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2351 "Flow Tunnel Termination : \ 2352 mismatch valid_elements flag and protocol field\n"))); 2353 return FALSE; 2354 } 2355 } 2356 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_VLAN_VALID) { 2357 VLAN_CHK_ID(unit, info->vlan); 2358 } 2359 return TRUE; 2360 } 2361 2362 /* 2363 * Function: 2364 * _bcm_flow_tnl_term_entry_data_set 2365 * Purpose: 2366 * Set the data information for flow tunnel terminator entry. 2367 * Parameters: 2368 * unit - (IN) Device Number. 2369 * info - (IN) Flow tunnel terminator descriptor. 2370 * field - (IN) logical field array. 2371 * num_of_fields - (IN) number of logical fields. 2372 * entry - (IN) memory entry. 2373 * vinfo - (IN) view information. 2374 * Returns: 2375 * BCM_E_XXX 2376 */ 2377 STATIC int 2378 _bcm_flow_tnl_term_entry_data_set(int unit, 2379 bcm_flow_tunnel_terminator_t *info, 2380 bcm_flow_logical_field_t *field, 2381 uint32 num_of_fields, 2382 uint32 *entry, 2383 soc_flow_db_mem_view_info_t vinfo) 2384 { 2385 int rv = BCM_E_NONE; 2386 int i; 2387 int j; 2388 int index = -1; 2389 uint32 return_entry[SOC_MAX_MEM_WORDS]; 2390 int new_entry_add = FALSE; 2391 uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 2392 uint32 field_count = 0; 2393 soc_mem_t mem; 2394 uint32 mem_view_id; 2395 soc_tunnel_term_t tnl_term; 2396 soc_tunnel_term_t ret_tnl_term; 2397 uint32 vxlan_handle; 2398 2399 mem = _BCM_FLOW_IS_FLEX_VIEW(info)? 2400 vinfo.mem_view_id: vinfo.mem; 2401 mem_view_id = vinfo.mem_view_id; 2402 2403 if (vinfo.mem == L3_TUNNELm) { 2404 BCM_IF_ERROR_RETURN( 2405 bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_term)); 2406 rv = soc_tunnel_term_match(unit, &tnl_term, 2407 &ret_tnl_term, &index); 2408 } else { 2409 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry, 2410 return_entry, 0); 2411 } 2412 2413 if (BCM_E_NONE == rv) { 2414 /* found memory entry */ 2415 if (!(info->flags & BCM_TUNNEL_REPLACE)) { 2416 LOG_ERROR(BSL_LS_BCM_FLOW, 2417 (BSL_META_U(unit, 2418 "Flow Tunnel Termination: \ 2419 Entry with same key already exists\n"))); 2420 return BCM_E_EXISTS; 2421 } 2422 } else if (BCM_E_NOT_FOUND == rv) { 2423 new_entry_add = TRUE; 2424 } else { 2425 return rv; 2426 } 2427 2428 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2429 /* Policy data fields*/ 2430 if (soc_flow_db_mem_view_field_is_valid 2431 (unit, mem_view_id, TERM_TUNNELf)) { 2432 soc_mem_field32_set(unit, mem, entry, 2433 TERM_TUNNELf, 1); 2434 soc_mem_field32_set(unit, mem, entry, 2435 IGNORE_UDP_CHECKSUMf, 2436 (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1); 2437 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) { 2438 soc_mem_field32_set(unit, mem, entry, 2439 USE_OUTER_HEADER_PHBf, 0x1); 2440 } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) { 2441 soc_mem_field32_set(unit, mem, entry, 2442 USE_OUTER_HEADER_PHBf, 0x2); 2443 } 2444 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_TTL) { 2445 soc_mem_field32_set(unit, mem, entry, 2446 USE_OUTER_HDR_TTLf, 1); 2447 } 2448 if (info->flags & BCM_TUNNEL_TERM_KEEP_INNER_DSCP) { 2449 soc_mem_field32_set(unit, mem, entry, 2450 DONOT_CHANGE_INNER_HDR_DSCPf, 1); 2451 } 2452 SOC_IF_ERROR_RETURN(soc_flow_db_flow_handle_get(unit, "VXLAN", 2453 &vxlan_handle)); 2454 2455 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) { 2456 soc_mem_field32_set(unit, mem, entry, 2457 NETWORK_RECEIVERS_PRESENTf, 0x01); 2458 if (info->flow_handle == vxlan_handle) { 2459 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set( 2460 unit, info->flow_handle,TRUE)); 2461 } 2462 } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) { 2463 soc_mem_field32_set(unit, mem, entry, NETWORK_RECEIVERS_PRESENTf, 0x00); 2464 if (info->flow_handle == vxlan_handle) { 2465 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set( 2466 unit, info->flow_handle,FALSE)); 2467 } 2468 } 2469 } 2470 if (SOC_MEM_FIELD_VALID(unit, mem, TUNNEL_TERM_SUBLAYER_ACTION_SETf)) { 2471 soc_mem_field32_set(unit, mem, entry, 2472 TUNNEL_TERM_SUBLAYER_ACTION_SETf, 1); 2473 } 2474 2475 /* Logical policy data fields */ 2476 if (info->valid_elements == BCM_FLOW_MATCH_FLEX_DATA_VALID) { 2477 BCM_IF_ERROR_RETURN( 2478 soc_flow_db_mem_view_field_list_get(unit, 2479 mem_view_id, 2480 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 2481 SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &field_count)); 2482 for (i = 0; (i < num_of_fields); i++) { 2483 for (j = 0; j < field_count; j++) { 2484 if (field[i].id == field_list[j]) { 2485 soc_mem_field32_set(unit,mem, entry, 2486 field[i].id, field[i].value); 2487 } 2488 } 2489 } 2490 2491 } 2492 2493 } else { 2494 /* fixed views */ 2495 if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 2496 (info->type == bcmTunnelTypeVxlan)) { 2497 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2498 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) { 2499 soc_mem_field32_set(unit, mem, entry, 2500 VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01); 2501 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2502 info->flow_handle,TRUE)); 2503 } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) { 2504 soc_mem_field32_set(unit, mem, entry, 2505 VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00); 2506 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2507 info->flow_handle,FALSE)); 2508 } 2509 } else { 2510 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) { 2511 soc_mem_field32_set(unit, mem, entry, 2512 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01); 2513 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2514 info->flow_handle,TRUE)); 2515 } else if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) { 2516 soc_mem_field32_set(unit, mem, entry, 2517 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00); 2518 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2519 info->flow_handle,FALSE)); 2520 } 2521 } 2522 } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) && 2523 (info->type == bcmTunnelTypeL2Gre)) { 2524 if (info->multicast_flag == BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE) { 2525 soc_mem_field32_set(unit, mem, entry, 2526 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x01); 2527 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2528 info->flow_handle,TRUE)); 2529 } else if (info->multicast_flag == 2530 BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE) { 2531 soc_mem_field32_set(unit, mem, entry, 2532 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf, 0x00); 2533 BCM_IF_ERROR_RETURN(_bcm_flow_bud_loopback_termination_set(unit, 2534 info->flow_handle,FALSE)); 2535 } 2536 2537 } 2538 } 2539 2540 2541 if (vinfo.mem == L3_TUNNELm) { 2542 BCM_IF_ERROR_RETURN( 2543 bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_term)); 2544 rv = soc_tunnel_term_insert(unit, &tnl_term, (uint32 *) &index); 2545 } else { 2546 if (new_entry_add) { 2547 rv = soc_mem_insert(unit, mem, 2548 MEM_BLOCK_ALL, entry); 2549 } else { 2550 rv = soc_mem_write(unit, mem, 2551 MEM_BLOCK_ALL, index, entry); 2552 } 2553 } 2554 return rv; 2555 } 2556 2557 /* 2558 * Function: 2559 * _bcm_flow_tnl_term_entry_data_get 2560 * Purpose: 2561 * Get the data information from flow tunnel terminator entry. 2562 * Parameters: 2563 * unit - (IN) Device Number. 2564 * info - (IN) Flow tunnel terminator descriptor. 2565 * field - (IN) logical field array. 2566 * num_of_fields - (IN) number of logical fields. 2567 * entry - (IN) memory entry. 2568 * vinfo - (IN) view information. 2569 * Returns: 2570 * BCM_E_XXX 2571 */ 2572 2573 STATIC int 2574 _bcm_flow_tnl_term_entry_data_get(int unit, 2575 bcm_flow_tunnel_terminator_t *info, 2576 bcm_flow_logical_field_t *field, 2577 uint32 num_of_fields, 2578 uint32 *entry, 2579 soc_flow_db_mem_view_info_t vinfo) 2580 { 2581 int i; 2582 int j; 2583 int index = -1; 2584 uint32 rentry[SOC_MAX_MEM_WORDS]; 2585 uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 2586 uint32 field_count = 0; 2587 soc_tunnel_term_t tnl_entry; 2588 soc_tunnel_term_t ret_tnl_entry; 2589 soc_mem_t mem; 2590 uint32 mem_view_id; 2591 2592 mem = _BCM_FLOW_IS_FLEX_VIEW(info)? 2593 vinfo.mem_view_id: vinfo.mem; 2594 mem_view_id = vinfo.mem_view_id; 2595 2596 if (vinfo.mem == L3_TUNNELm) { 2597 BCM_IF_ERROR_RETURN( 2598 bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_entry)); 2599 BCM_IF_ERROR_RETURN( 2600 soc_tunnel_term_match(unit, &tnl_entry, 2601 &ret_tnl_entry, &index)); 2602 bcmi_esw_flow_tnl_term_to_entry(unit, &ret_tnl_entry, rentry); 2603 } else { 2604 BCM_IF_ERROR_RETURN( 2605 soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, entry, 2606 rentry, 0)); 2607 } 2608 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2609 if (soc_flow_db_mem_view_field_is_valid 2610 (unit, mem_view_id, TERM_TUNNELf)) { 2611 /* Policy data fields*/ 2612 if (soc_mem_field32_get(unit, mem, rentry, 2613 IGNORE_UDP_CHECKSUMf) == 0x0) 2614 { 2615 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 2616 } 2617 if (soc_mem_field32_get(unit, mem, rentry, 2618 USE_OUTER_HEADER_PHBf) == 0x1) { 2619 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 2620 } else if (soc_mem_field32_get(unit, mem, rentry, 2621 USE_OUTER_HEADER_PHBf) == 0x2) { 2622 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP; 2623 } 2624 if (soc_mem_field32_get(unit, mem, rentry, 2625 USE_OUTER_HDR_TTLf) == 1) { 2626 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL; 2627 } 2628 if (soc_mem_field32_get(unit, mem, rentry, 2629 DONOT_CHANGE_INNER_HDR_DSCPf) == 1) { 2630 info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP; 2631 } 2632 if(soc_mem_field32_get(unit, mem, rentry, 2633 NETWORK_RECEIVERS_PRESENTf) == 0x01) { 2634 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 2635 } else if (soc_mem_field32_get(unit, mem, rentry, 2636 NETWORK_RECEIVERS_PRESENTf) == 0x00) { 2637 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 2638 } 2639 } 2640 /* Logical policy data fields */ 2641 if (_BCM_FLOW_IS_FLEX_VIEW(info) && (field != NULL)) { 2642 BCM_IF_ERROR_RETURN( 2643 soc_flow_db_mem_view_field_list_get(unit, 2644 mem_view_id, 2645 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 2646 SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &field_count)); 2647 for (i = 0; (i < num_of_fields); i++) { 2648 for (j = 0; j < field_count; j++) { 2649 if (field[i].id == field_list[j]) { 2650 field[i].value = 2651 soc_mem_field32_get(unit, mem, rentry, field[i].id);; 2652 } 2653 } 2654 } 2655 2656 } 2657 2658 } else { 2659 /* fixed views */ 2660 if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 2661 (info->type == bcmTunnelTypeVxlan)) { 2662 if (soc_mem_field32_get(unit, mem, rentry, 2663 VXLAN_DIP__IGNORE_UDP_CHECKSUMf) == 0x0) 2664 { 2665 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 2666 } 2667 if (soc_mem_field32_get(unit, mem, rentry, 2668 VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x1) { 2669 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 2670 } else if (soc_mem_field32_get(unit, mem, rentry, 2671 VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x2) { 2672 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP; 2673 } 2674 /*Multicast flag information */ 2675 if(soc_mem_field32_get(unit, mem, rentry, 2676 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) { 2677 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 2678 } else if (soc_mem_field32_get(unit, mem, rentry, 2679 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) { 2680 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 2681 } 2682 2683 } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) && 2684 (info->type == bcmTunnelTypeL2Gre)) { 2685 /*Multicast flag information */ 2686 if(soc_mem_field32_get(unit, mem, rentry, 2687 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) { 2688 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 2689 } else if (soc_mem_field32_get(unit, mem, rentry, 2690 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) { 2691 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 2692 } 2693 2694 } 2695 2696 } 2697 return BCM_E_NONE; 2698 } 2699 2700 /* 2701 * Function: 2702 * _bcm_flow_tnl_term_entry_key_set 2703 * Purpose: 2704 * Set the key information for flow tunnel terminator object. 2705 * Parameters: 2706 * unit - (IN) Device Number. 2707 * info - (IN/OUT) Flow tunnel terminator descriptor. 2708 * field - (IN) logical field array. 2709 * num_of_fields - (IN) number of logical fields. 2710 * entry - (IN) memory entry. 2711 * vinfo - (IN) view information. 2712 * Returns: 2713 * BCM_E_XXX 2714 */ 2715 STATIC int 2716 _bcm_flow_tnl_term_entry_key_set(int unit, 2717 bcm_flow_tunnel_terminator_t *info, 2718 bcm_flow_logical_field_t *field, 2719 uint32 num_of_fields, 2720 uint32 *entry, 2721 soc_flow_db_mem_view_info_t *vinfo) 2722 { 2723 int rv = BCM_E_NONE; 2724 uint32 key_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 2725 uint32 key_count = 0; 2726 uint32 mem_view_id = 0; 2727 soc_mem_t mem = 0; 2728 int i = 0; 2729 int j = 0; 2730 2731 /* Get the view info */ 2732 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2733 mem_view_id = vinfo->mem_view_id; 2734 mem = vinfo->mem_view_id; 2735 2736 /* intitalize the entry with 2737 * key_type , data_type , control fields 2738 */ 2739 soc_flow_db_mem_view_entry_init(unit, mem_view_id, entry); 2740 /* set the key fields */ 2741 /* get the list of key fields 2742 * based VALID FIELDS , set the matching fields. 2743 */ 2744 BCM_IF_ERROR_RETURN( 2745 soc_flow_db_mem_view_field_list_get(unit, 2746 mem_view_id, 2747 SOC_FLOW_DB_FIELD_TYPE_KEY, 2748 SOC_FLOW_DB_MAX_VIEW_FIELDS, 2749 key_list, 2750 &key_count)); 2751 for (i = 0; i < key_count; i++) { 2752 if (key_list[i] == IPV4__DIPf) { 2753 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_VALID) { 2754 rv = (info->dip) ? BCM_E_NONE : BCM_E_PARAM; 2755 BCM_IF_ERROR_RETURN(rv); 2756 soc_mem_field32_set(unit, mem, entry, 2757 IPV4__DIPf, info->dip); 2758 } 2759 } else if (key_list[i] == IPV4__SIPf) { 2760 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_VALID) { 2761 rv = (info->sip) ? BCM_E_NONE : BCM_E_PARAM; 2762 BCM_IF_ERROR_RETURN(rv); 2763 soc_mem_field32_set(unit, mem, entry, 2764 IPV4__SIPf, info->sip); 2765 } 2766 } else if (key_list[i] == IPV4__DIP_MASKf) { 2767 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID) { 2768 rv = (info->dip_mask) ? BCM_E_NONE : BCM_E_PARAM; 2769 BCM_IF_ERROR_RETURN(rv); 2770 soc_mem_field32_set(unit, mem, entry, 2771 IPV4__DIP_MASKf, info->dip); 2772 } 2773 } else if (key_list[i] == IPV4__SIP_MASKf) { 2774 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID) { 2775 rv = (info->sip_mask) ? BCM_E_NONE : BCM_E_PARAM; 2776 BCM_IF_ERROR_RETURN(rv); 2777 soc_mem_field32_set(unit, mem, entry, 2778 IPV4__SIP_MASKf, info->sip_mask); 2779 } 2780 } else if (key_list[i] == L4_DEST_PORTf) { 2781 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID) { 2782 rv = (info->udp_dst_port) ? BCM_E_NONE : BCM_E_PARAM; 2783 BCM_IF_ERROR_RETURN(rv); 2784 soc_mem_field32_set(unit, mem, entry, 2785 L4_DEST_PORTf, info->udp_dst_port); 2786 } 2787 } else if (key_list[i] == L4_SRC_PORTf) { 2788 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID) { 2789 rv = (info->udp_src_port) ? BCM_E_NONE : BCM_E_PARAM; 2790 BCM_IF_ERROR_RETURN(rv); 2791 soc_mem_field32_set(unit, mem, entry, 2792 L4_SRC_PORTf, info->udp_src_port); 2793 } 2794 } else if (key_list[i] == PROTOCOLf) { 2795 if(info->valid_elements & BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID) { 2796 rv = (info->protocol) ? BCM_E_NONE : BCM_E_PARAM; 2797 BCM_IF_ERROR_RETURN(rv); 2798 soc_mem_field32_set(unit, mem, entry, 2799 PROTOCOLf, info->protocol); 2800 } 2801 } else if (key_list[i] == IPV6__SIPf) { 2802 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_VALID) { 2803 rv = (bcmi_flow_ip6_addr_is_valid(info->sip6)) ? 2804 BCM_E_NONE : BCM_E_PARAM; 2805 BCM_IF_ERROR_RETURN(rv); 2806 soc_mem_ip6_addr_set(unit, mem, entry, 2807 IPV6__SIPf, info->sip6, 0); 2808 } 2809 } else if (key_list[i] == IPV6__DIPf) { 2810 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_VALID) { 2811 rv = (bcmi_flow_ip6_addr_is_valid(info->dip6)) ? 2812 BCM_E_NONE : BCM_E_PARAM; 2813 BCM_IF_ERROR_RETURN(rv); 2814 soc_mem_ip6_addr_set(unit, mem, entry, 2815 IPV6__DIPf, info->dip6, 0); 2816 } 2817 } else if (key_list[i] == IPV6__SIP_MASKf) { 2818 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID) { 2819 rv = (bcmi_flow_ip6_addr_is_valid(info->sip6_mask)) ? 2820 BCM_E_NONE : BCM_E_PARAM; 2821 BCM_IF_ERROR_RETURN(rv); 2822 soc_mem_ip6_addr_set(unit, mem, entry, 2823 IPV6__SIP_MASKf, info->sip6_mask, 0); 2824 } 2825 } else if (key_list[i] == IPV6__DIP_MASKf) { 2826 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID) { 2827 rv = (bcmi_flow_ip6_addr_is_valid(info->dip6_mask)) ? 2828 BCM_E_NONE : BCM_E_PARAM; 2829 BCM_IF_ERROR_RETURN(rv); 2830 soc_mem_ip6_addr_set(unit, mem, entry, 2831 IPV6__DIP_MASKf, info->dip6_mask, 0); 2832 } 2833 } 2834 } 2835 2836 if (info->valid_elements & BCM_FLOW_TUNNEL_TERM_FLEX_KEY_VALID) { 2837 /* Logical key fields */ 2838 BCM_IF_ERROR_RETURN( 2839 soc_flow_db_mem_view_field_list_get(unit, 2840 mem_view_id, 2841 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 2842 SOC_FLOW_DB_MAX_VIEW_FIELDS, 2843 key_list, 2844 &key_count)); 2845 2846 for (i = 0;(i < num_of_fields); i++) { 2847 for (j = 0; j < key_count; j++) { 2848 if (field[i].id == key_list[j]) { 2849 soc_mem_field32_set(unit, mem, entry, 2850 field[i].id, field[i].value); 2851 } 2852 } 2853 } 2854 } 2855 2856 } else { 2857 /* legacy VXLAN and L2GRE */ 2858 if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) && 2859 (info->type == bcmTunnelTypeVxlan)) { 2860 /* initialize the view info*/ 2861 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 2862 mem = vinfo->mem = MPLS_ENTRY_SINGLEm; 2863 2864 soc_mem_field32_set(unit, mem, entry, BASE_VALIDf, 1); 2865 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 2866 _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP); 2867 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP); 2868 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__DIPf, info->dip); 2869 soc_mem_field32_set(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__TERM_TUNNELf, 0x1); 2870 soc_mem_field32_set(unit, mem, entry, 2871 VXLAN_FLEX_IPV4_DIP__IGNORE_UDP_CHECKSUMf, 2872 (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1); 2873 2874 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) { 2875 soc_mem_field32_set(unit, mem, entry, 2876 VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf, 0x1); 2877 } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) { 2878 soc_mem_field32_set(unit, mem, entry, 2879 VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf, 0x2); 2880 } 2881 } else { 2882 mem = vinfo->mem = VLAN_XLATE_1_DOUBLEm; 2883 2884 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 2885 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 2886 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 2887 _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP); 2888 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP); 2889 soc_mem_field32_set(unit, mem, entry, VXLAN_DIP__DIPf, info->dip); 2890 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) { 2891 soc_mem_field32_set(unit, mem, entry, 2892 VXLAN_DIP__OVIDf, info->vlan); 2893 } 2894 soc_mem_field32_set(unit, mem, entry, 2895 VXLAN_DIP__IGNORE_UDP_CHECKSUMf, 2896 (info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1); 2897 2898 if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) { 2899 soc_mem_field32_set(unit, mem, entry, 2900 VXLAN_DIP__USE_OUTER_HEADER_PHBf, 0x1); 2901 } else if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) { 2902 soc_mem_field32_set(unit, mem, entry, 2903 VXLAN_DIP__USE_OUTER_HEADER_PHBf, 0x2); 2904 } 2905 } 2906 } else if ((info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) && 2907 (info->type == bcmTunnelTypeL2Gre)) { 2908 mem = vinfo->mem = VLAN_XLATE_1_DOUBLEm; 2909 2910 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 2911 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 2912 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, 2913 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2914 soc_mem_field32_set(unit, mem, entry, DATA_TYPEf, 2915 _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP); 2916 soc_mem_field32_set(unit, mem, entry, 2917 L2GRE_DIP__DIPf, info->dip); 2918 } else { 2919 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2920 "Invalid Legacy flow handle or flow type\n"))); 2921 return BCM_E_PARAM; 2922 } 2923 } 2924 2925 return rv; 2926 } 2927 2928 /* 2929 * Function: 2930 * bcmi_esw_flow_tunnel_terminator_create 2931 * Purpose: 2932 * Create a flow tunnel terminator object. 2933 * 2934 * Parameters: 2935 * unit - (IN) Device Number 2936 * info - (IN/OUT) Flow tunnel terminator descriptor 2937 * num_of_fields - (IN) number of logical fields 2938 * field - (IN) logical field array 2939 * Returns: 2940 * BCM_E_XXX 2941 */ 2942 int bcmi_esw_flow_tunnel_terminator_create( 2943 int unit, 2944 bcm_flow_tunnel_terminator_t *info, 2945 uint32 num_of_fields, 2946 bcm_flow_logical_field_t *field) 2947 { 2948 int rv = BCM_E_NONE; 2949 _bcm_flow_bookkeeping_t *flow_info; 2950 soc_mem_t mem_view_id; 2951 uint32 entry[SOC_MAX_MEM_WORDS]; 2952 soc_flow_db_mem_view_info_t vinfo; 2953 2954 flow_info = FLOW_INFO(unit); 2955 2956 if (NULL == info) { 2957 return (BCM_E_PARAM); 2958 } 2959 2960 if (flow_info == NULL) { 2961 return (BCM_E_INTERNAL); 2962 } 2963 2964 if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) && 2965 (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) { 2966 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 2967 "Flow Tunnel Termination: Invalid tunnel type.\n"))); 2968 return BCM_E_PARAM; 2969 } 2970 2971 BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info)); 2972 2973 /* Zero write buffer. */ 2974 sal_memset(entry, 0, sizeof(entry)); 2975 2976 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 2977 BCM_IF_ERROR_RETURN( 2978 soc_flow_db_ffo_to_mem_view_id_get( 2979 unit, 2980 info->flow_handle, 2981 info->flow_option, 2982 SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID, 2983 (uint32 *)&mem_view_id)); 2984 BCM_IF_ERROR_RETURN( 2985 soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo)); 2986 } 2987 2988 2989 BCM_IF_ERROR_RETURN(_bcm_flow_tnl_term_entry_key_set(unit, info, 2990 field, num_of_fields, 2991 entry, &vinfo)); 2992 /* Allocate tunnel terminator entry */ 2993 bcmi_esw_flow_lock(unit); 2994 rv = _bcm_flow_tnl_term_entry_data_set(unit, info, 2995 field, num_of_fields, 2996 entry, vinfo); 2997 bcmi_esw_flow_unlock(unit); 2998 return rv; 2999 } 3000 3001 /* 3002 * Function: 3003 * bcmi_esw_flow_tunnel_terminator_destroy 3004 * Purpose: 3005 * Destroy a flow tunnel terminator entry 3006 * 3007 * Parameters: 3008 * unit - (IN) Device Number 3009 * info - (IN/OUT) Flow tunnel terminator descriptor 3010 * num_of_fields - (IN) number of logical fields 3011 * field - (IN) logical field array 3012 * Returns: 3013 * BCM_E_XXX 3014 */ 3015 int bcmi_esw_flow_tunnel_terminator_destroy( 3016 int unit, 3017 bcm_flow_tunnel_terminator_t *info, 3018 uint32 num_of_fields, 3019 bcm_flow_logical_field_t *field) 3020 { 3021 int rv = BCM_E_NONE; 3022 _bcm_flow_bookkeeping_t *flow_info; 3023 soc_mem_t mem_view_id; 3024 soc_tunnel_term_t tnl_entry; 3025 soc_tunnel_term_t ret_tnl_entry; 3026 uint32 entry[SOC_MAX_MEM_WORDS]; 3027 uint32 ret_entry[SOC_MAX_MEM_WORDS]; 3028 int index = 0; 3029 soc_flow_db_mem_view_info_t vinfo; 3030 3031 flow_info = FLOW_INFO(unit); 3032 3033 if (NULL == info) { 3034 return (BCM_E_PARAM); 3035 } 3036 3037 if (flow_info == NULL) { 3038 return (BCM_E_INTERNAL); 3039 } 3040 3041 if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) && 3042 (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) { 3043 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3044 "Flow Tunnel Termination : Update fail,\ 3045 Invalid tunnel type for flow tunnels\n"))); 3046 return BCM_E_PARAM; 3047 } 3048 3049 BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info)); 3050 /* Zero write buffer. */ 3051 sal_memset(entry, 0, sizeof(entry)); 3052 3053 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3054 BCM_IF_ERROR_RETURN( 3055 soc_flow_db_ffo_to_mem_view_id_get(unit, 3056 info->flow_handle, 3057 info->flow_option, 3058 SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID, 3059 (uint32 *)&mem_view_id)); 3060 BCM_IF_ERROR_RETURN( 3061 soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo)); 3062 } 3063 3064 BCM_IF_ERROR_RETURN(_bcm_flow_tnl_term_entry_key_set(unit, info, 3065 field, num_of_fields, 3066 entry, &vinfo)); 3067 if (vinfo.mem == L3_TUNNELm) { 3068 BCM_IF_ERROR_RETURN( 3069 bcmi_esw_flow_entry_to_tnl_term(unit, entry, &tnl_entry)); 3070 rv = soc_tunnel_term_match(unit, &tnl_entry, &ret_tnl_entry, &index); 3071 if (rv == BCM_E_NONE) { 3072 BCM_IF_ERROR_RETURN( 3073 soc_tunnel_term_delete(unit, &ret_tnl_entry)); 3074 } else if (rv != BCM_E_NOT_FOUND) { 3075 return rv; 3076 } 3077 3078 } else { 3079 rv = soc_mem_search(unit, vinfo.mem, MEM_BLOCK_ANY, &index, 3080 entry, ret_entry, 0); 3081 if (rv == BCM_E_NONE) { 3082 rv = soc_mem_delete(unit, vinfo.mem, MEM_BLOCK_ALL, &ret_entry); 3083 if (BCM_FAILURE(rv)) { 3084 return rv; 3085 } 3086 } else if (rv != BCM_E_NOT_FOUND) { 3087 return rv; 3088 } 3089 } 3090 return BCM_E_NONE; 3091 } 3092 3093 /* 3094 * Function: 3095 * bcmi_esw_flow_tunnel_terminator_get 3096 * Purpose: 3097 * Get a flow tunnel terminator entry 3098 * 3099 * Parameters: 3100 * unit - (IN) Device Number 3101 * info - (IN/OUT) Flow tunnel terminator descriptor 3102 * num_of_fields - (IN) number of logical fields 3103 * field - (IN) logical field array 3104 * Returns: 3105 * BCM_E_XXX 3106 */ 3107 int bcmi_esw_flow_tunnel_terminator_get( 3108 int unit, 3109 bcm_flow_tunnel_terminator_t *info, 3110 uint32 num_of_fields, 3111 bcm_flow_logical_field_t *field) 3112 { 3113 _bcm_flow_bookkeeping_t *flow_info; 3114 soc_mem_t mem_view_id; 3115 uint32 entry[SOC_MAX_MEM_WORDS]; 3116 soc_flow_db_mem_view_info_t vinfo; 3117 3118 flow_info = FLOW_INFO(unit); 3119 3120 if (NULL == info) { 3121 return (BCM_E_PARAM); 3122 } 3123 3124 if (flow_info == NULL) { 3125 return (BCM_E_INTERNAL); 3126 } 3127 3128 if ((!_BCM_FLOW_TUNNEL_TYPE_L2(info->type)) && 3129 (!_BCM_FLOW_TUNNEL_TYPE_L3(info->type))) { 3130 LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit, 3131 "Flow Tunnel Termination : Update fail,\ 3132 Invalid tunnel type for flow tunnels\n"))); 3133 return BCM_E_PARAM; 3134 } 3135 3136 BCM_IF_ERROR_RETURN(_bcm_esw_flow_tnl_term_validate(unit, info)); 3137 /* Zero write buffer. */ 3138 sal_memset(entry, 0, sizeof(entry)); 3139 3140 if (_BCM_FLOW_IS_FLEX_VIEW(info)) { 3141 BCM_IF_ERROR_RETURN( 3142 soc_flow_db_ffo_to_mem_view_id_get(unit, 3143 info->flow_handle, 3144 info->flow_option, 3145 SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID, 3146 (uint32 *)&mem_view_id)); 3147 BCM_IF_ERROR_RETURN( 3148 soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo)); 3149 } 3150 3151 BCM_IF_ERROR_RETURN( 3152 _bcm_flow_tnl_term_entry_key_set(unit, info, 3153 field, num_of_fields, entry, &vinfo)); 3154 BCM_IF_ERROR_RETURN( 3155 _bcm_flow_tnl_term_entry_data_get(unit, info, 3156 field, num_of_fields, 3157 entry, vinfo)); 3158 return BCM_E_NONE; 3159 } 3160 3161 STATIC int 3162 _bcm_flow_tunnel_terminator_entry_valid(int unit, 3163 soc_mem_t mem, 3164 uint32 *entry, 3165 int *valid) 3166 { 3167 if (INVALIDm == mem) { 3168 return BCM_E_MEMORY; 3169 } 3170 3171 if ((NULL == entry) || (NULL == valid)) { 3172 return BCM_E_PARAM; 3173 } 3174 3175 *valid = TRUE; 3176 if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_0f)) { 3177 if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) { 3178 *valid = FALSE; 3179 } 3180 } 3181 if (SOC_MEM_FIELD_VALID(unit,mem,BASE_VALID_1f)) { 3182 if (!soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) { 3183 *valid = FALSE; 3184 } 3185 } 3186 if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 3187 if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) { 3188 *valid = FALSE; 3189 } 3190 } 3191 /* validation for single view like MPLS_ENTRY_SINGLE */ 3192 if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) { 3193 if (0x1 != soc_mem_field32_get(unit, mem, entry, BASE_VALIDf)) { 3194 *valid = FALSE; 3195 } 3196 } 3197 3198 return BCM_E_NONE; 3199 3200 } 3201 3202 /* 3203 * Function : 3204 * _bcm_flow_tunnel_terminator_entry_parse 3205 * Description : 3206 * Convert the memory entry field data to the tunnel terminator 3207 * parameters. 3208 * Parameters : 3209 * unit - (IN) Device Number 3210 * mem - (IN) memory id. 3211 * mem_view_id - (IN) memory view id. 3212 * entry - (IN) HW entry. 3213 * info - (OUT) Flow tunnel termination descriptor 3214 * num_of_fields - (OUT) number of logical fields 3215 * field - (OUT) logical field array 3216 */ 3217 STATIC int 3218 _bcm_flow_tunnel_terminator_entry_parse(int unit, 3219 soc_mem_t mem, 3220 uint32 *entry, 3221 bcm_flow_tunnel_terminator_t *info, 3222 uint32 *num_of_fields, 3223 bcm_flow_logical_field_t *field) 3224 { 3225 int key_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 3226 int data_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 3227 uint32 data_count; 3228 int i; 3229 soc_flow_db_mem_view_info_t vinfo; 3230 uint32 key_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 3231 uint32 key_count = 0; 3232 uint32 field_list[SOC_FLOW_DB_MAX_VIEW_FIELDS]; 3233 uint32 cnt = 0; 3234 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 3235 uint32 num_ffo = 0; 3236 uint32 key_typef[] = {KEY_TYPEf, 3237 KEY_TYPE0f, 3238 KEY_TYPE1f}; 3239 uint32 data_typef[] = {DATA_TYPEf, 3240 DATA_TYPE0f, 3241 DATA_TYPE1f}; 3242 int rv = BCM_E_NONE; 3243 uint32 mem_view_id = 0; 3244 3245 for (i = 0; i < SOC_FLOW_DB_MAX_KEY_TYPE; i++) { 3246 if (SOC_MEM_FIELD_VALID(unit,mem,key_typef[i])) { 3247 key_type = soc_mem_field32_get(unit, mem, entry, key_typef[i]); 3248 break; 3249 } 3250 } 3251 for (i = 0; i < SOC_FLOW_DB_MAX_DATA_TYPE; i++) { 3252 if (SOC_MEM_FIELD_VALID(unit,mem,data_typef[i])) { 3253 data_type = soc_mem_field32_get(unit, mem, entry, data_typef[i]); 3254 } 3255 } 3256 3257 /* find the memory view based on the memory and key type */ 3258 rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 3259 0, NULL, (uint32 *) &mem_view_id); 3260 3261 if (rv != BCM_E_NONE && rv != BCM_E_NOT_FOUND) { 3262 return rv; 3263 } 3264 3265 if (rv == BCM_E_NOT_FOUND) { 3266 /* Fixed view */ 3267 switch (key_type) { 3268 case _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP: 3269 case _BCM_VXLAN_FLEX_KEY_TYPE_LOOKUP_DIP: 3270 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN; 3271 info->type = bcmTunnelTypeVxlan; 3272 break; 3273 case _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP: 3274 info->flow_handle = SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE; 3275 info->type = bcmTunnelTypeL2Gre; 3276 break; 3277 default: 3278 return BCM_E_NONE; 3279 } 3280 3281 if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_VXLAN) { 3282 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) { 3283 info->dip = soc_mem_field32_get(unit, mem, entry, VXLAN_FLEX_IPV4_DIP__DIPf); 3284 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID; 3285 if (soc_mem_field32_get(unit, mem, entry, 3286 VXLAN_FLEX_IPV4_DIP__IGNORE_UDP_CHECKSUMf) == 0x0) { 3287 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 3288 } 3289 3290 if (soc_mem_field32_get(unit, mem, entry, 3291 VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf) == 0x01) { 3292 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 3293 } 3294 if (soc_mem_field32_get(unit, mem, entry, 3295 VXLAN_FLEX_IPV4_DIP__USE_OUTER_HEADER_PHBf) == 0x02) { 3296 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP; 3297 } 3298 /* Multicast Flags */ 3299 if(soc_mem_field32_get(unit, mem, entry, 3300 VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) { 3301 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 3302 } else if (soc_mem_field32_get(unit, mem, entry, 3303 VXLAN_FLEX_IPV4_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) { 3304 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 3305 } 3306 } else { 3307 info->dip = soc_mem_field32_get(unit, mem, 3308 entry, VXLAN_DIP__DIPf); 3309 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID; 3310 3311 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) { 3312 info->vlan = soc_mem_field32_get(unit, mem, entry, 3313 VXLAN_DIP__OVIDf); 3314 } 3315 3316 if (soc_mem_field32_get(unit, mem, entry, 3317 VXLAN_DIP__IGNORE_UDP_CHECKSUMf) == 0x0) { 3318 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 3319 } 3320 3321 if (soc_mem_field32_get(unit, mem, entry, 3322 VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x01) { 3323 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 3324 } 3325 if (soc_mem_field32_get(unit, mem, entry, 3326 VXLAN_DIP__USE_OUTER_HEADER_PHBf) == 0x02) { 3327 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP; 3328 } 3329 /* Multicast Flags */ 3330 if(soc_mem_field32_get(unit, mem, entry, 3331 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) { 3332 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 3333 } else if (soc_mem_field32_get(unit, mem, entry, 3334 VXLAN_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) { 3335 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 3336 } 3337 } 3338 } else if (info->flow_handle == SOC_FLOW_DB_FLOW_ID_LEGACY_L2GRE) { 3339 info->dip = soc_mem_field32_get(unit, mem, 3340 entry, L2GRE_DIP__DIPf); 3341 info->flags |= BCM_FLOW_TUNNEL_TERM_DIP_VALID; 3342 /* Multicast flags */ 3343 if(soc_mem_field32_get(unit, mem, entry, 3344 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x01) { 3345 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 3346 } else if (soc_mem_field32_get(unit, mem, entry, 3347 L2GRE_DIP__NETWORK_RECEIVERS_PRESENTf) == 0x00) { 3348 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 3349 } 3350 3351 } 3352 3353 } else { 3354 /* Flex view */ 3355 /* find the memory view info */ 3356 BCM_IF_ERROR_RETURN( 3357 soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo)); 3358 3359 /* get the flow handle, function id, option id */ 3360 BCM_IF_ERROR_RETURN( 3361 soc_flow_db_mem_view_to_ffo_get(unit, 3362 mem_view_id, 3363 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 3364 ffo, 3365 &num_ffo)); 3366 info->flow_handle = ffo[0].flow_handle; 3367 info->flow_option = ffo[0].option_id; 3368 info->type = bcmTunnelTypeL2Flex; 3369 3370 /* key - Flex view */ 3371 BCM_IF_ERROR_RETURN( 3372 soc_flow_db_mem_view_field_list_get(unit, 3373 mem_view_id, 3374 SOC_FLOW_DB_FIELD_TYPE_KEY, 3375 SOC_FLOW_DB_MAX_VIEW_FIELDS, 3376 key_list, 3377 &key_count)); 3378 3379 for (i = 0; i < key_count; i++) { 3380 if (key_list[i] == IPV4__DIPf) { 3381 info->dip = soc_mem_field32_get(unit, mem_view_id, 3382 entry, IPV4__DIPf); 3383 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_VALID; 3384 } else if (key_list[i] == IPV4__SIPf) { 3385 info->sip = soc_mem_field32_get(unit, mem_view_id, 3386 entry, IPV4__SIPf); 3387 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP_VALID; 3388 } else if (key_list[i] == IPV4__DIP_MASKf) { 3389 info->dip_mask = soc_mem_field32_get(unit, mem_view_id, 3390 entry, IPV4__DIP_MASKf); 3391 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP_MASK_VALID; 3392 } else if (key_list[i] == IPV4__SIP_MASKf) { 3393 info->sip_mask = soc_mem_field32_get(unit, mem_view_id, 3394 entry, IPV4__SIP_MASKf); 3395 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP_MASK_VALID; 3396 } else if (key_list[i] == IPV6__SIPf) { 3397 soc_mem_ip6_addr_get(unit, mem_view_id, 3398 entry, IPV6__SIPf, info->sip6, 0); 3399 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP6_VALID; 3400 } else if (key_list[i] == IPV6__DIPf) { 3401 soc_mem_ip6_addr_get(unit, mem_view_id, 3402 entry, IPV6__DIPf, info->dip6, 0); 3403 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP6_VALID; 3404 } else if (key_list[i] == IPV6__SIP_MASKf) { 3405 soc_mem_ip6_addr_get(unit, mem_view_id, 3406 entry, IPV6__SIP_MASKf, info->sip6_mask, 0); 3407 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_SIP6_MASK_VALID; 3408 } else if (key_list[i] == IPV6__DIP_MASKf) { 3409 soc_mem_ip6_addr_get(unit, mem_view_id, 3410 entry, IPV6__DIP_MASKf, info->dip6_mask, 0); 3411 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_DIP6_MASK_VALID; 3412 } else if (key_list[i] == L4_DEST_PORTf) { 3413 info->udp_dst_port = soc_mem_field32_get(unit, mem_view_id, 3414 entry, L4_DEST_PORTf); 3415 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_UDP_DST_PORT_VALID; 3416 } else if (key_list[i] == L4_SRC_PORTf) { 3417 info->udp_src_port = soc_mem_field32_get(unit, mem_view_id, 3418 entry, L4_SRC_PORTf); 3419 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_UDP_SRC_PORT_VALID; 3420 } else if (key_list[i] == PROTOCOLf) { 3421 info->protocol = soc_mem_field32_get(unit, mem_view_id, 3422 entry, PROTOCOLf); 3423 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_PROTOCOL_VALID; 3424 } 3425 } 3426 3427 BCM_IF_ERROR_RETURN(soc_flow_db_mem_view_field_list_get(unit, 3428 mem_view_id, 3429 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY, 3430 SOC_FLOW_DB_MAX_VIEW_FIELDS, key_list, &key_count)); 3431 3432 if(key_count) { 3433 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_FLEX_KEY_VALID; 3434 } 3435 for (i = 0; i < key_count; i++) { 3436 field[cnt].id = key_list[i]; 3437 field[cnt++].value = soc_mem_field32_get(unit,mem_view_id, entry, 3438 key_list[i]); 3439 } 3440 3441 /* DATA - Flex VIew */ 3442 if (soc_flow_db_mem_view_field_is_valid 3443 (unit, mem_view_id, TERM_TUNNELf)) { 3444 3445 if (soc_mem_field32_get(unit, mem_view_id, entry, 3446 IGNORE_UDP_CHECKSUMf) == 0x0) 3447 { 3448 info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE; 3449 } 3450 if (soc_mem_field32_get(unit, mem_view_id, entry, 3451 USE_OUTER_HEADER_PHBf) == 0x1) { 3452 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP; 3453 } 3454 if (soc_mem_field32_get(unit, mem_view_id, entry, 3455 USE_OUTER_HEADER_PHBf) == 0x2) { 3456 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP; 3457 } 3458 if (soc_mem_field32_get(unit, mem_view_id, entry, 3459 USE_OUTER_HDR_TTLf) == 1) { 3460 info->flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL; 3461 } 3462 if (soc_mem_field32_get(unit, mem_view_id, entry, 3463 DONOT_CHANGE_INNER_HDR_DSCPf) == 1) { 3464 info->flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP; 3465 } 3466 if(soc_mem_field32_get(unit, mem_view_id, entry, 3467 NETWORK_RECEIVERS_PRESENTf) == 0x01) { 3468 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_ENABLE; 3469 } else if (soc_mem_field32_get(unit, mem_view_id, entry, 3470 NETWORK_RECEIVERS_PRESENTf) == 0x00) { 3471 info->multicast_flag |= BCM_FLOW_MULTICAST_TUNNEL_STATE_BUD_DISABLE; 3472 } 3473 } 3474 BCM_IF_ERROR_RETURN( 3475 soc_flow_db_mem_view_field_list_get(unit, 3476 mem_view_id, 3477 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA, 3478 SOC_FLOW_DB_MAX_VIEW_FIELDS, field_list, &data_count)); 3479 3480 if (data_count) { 3481 info->valid_elements |= BCM_FLOW_TUNNEL_TERM_FLEX_DATA_VALID; 3482 } 3483 for (i = 0; i < data_count; i++) { 3484 field[cnt].id = field_list[i]; 3485 field[cnt++].value = 3486 soc_mem_field32_get(unit, mem_view_id, entry, field_list[i]); 3487 } 3488 *num_of_fields = cnt; 3489 3490 } 3491 3492 return BCM_E_NONE; 3493 3494 } 3495 3496 /* 3497 * Function: 3498 * _bcm_flow_tunnel_terminator_traverse_mem 3499 * Purpose: 3500 * Read the given memory table and call the user callback function on 3501 * each entry. 3502 * Parameters: 3503 * unit - (IN) Device Number 3504 * mem - (IN) the memory id 3505 * cb - (IN) user callback function 3506 * user_data - (IN) user context data 3507 * Returns: 3508 * BCM_E_XXX 3509 */ 3510 3511 STATIC int 3512 _bcm_flow_tunnel_terminator_mem_traverse(int unit, soc_mem_t mem, 3513 bcm_flow_tunnel_terminator_traverse_cb cb, 3514 void *user_data) 3515 { 3516 3517 3518 bcm_flow_tunnel_terminator_t info; 3519 uint32 num_of_fields = _BCM_FLOW_LOGICAL_FIELD_MAX; 3520 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 3521 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 3522 int buf_size, chunksize, chnk_end; 3523 /* Buffer to store chunk of table we currently work on */ 3524 uint32 *vt_tbl_chnk; 3525 uint32 *entry; 3526 uint32 trav_entry[_QUAD_ENTRY_MAX]; 3527 int valid = FALSE; 3528 int rv = BCM_E_NONE; 3529 uint32 entry_width = _BCM_FLOW_TD3_L3_TUNNEL_SINGLE_ENTRY_SIZE; 3530 uint32 num_hw_entries = 0; 3531 int i = 0; 3532 3533 if (INVALIDm == mem) { 3534 return BCM_E_MEMORY; 3535 } 3536 3537 if (!soc_mem_index_count(unit, mem)) { 3538 return BCM_E_NONE; 3539 } 3540 3541 chunksize = soc_property_get(unit, spn_VLANDELETE_CHUNKS, 3542 VLAN_MEM_CHUNKS_DEFAULT); 3543 3544 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 3545 vt_tbl_chnk = soc_cm_salloc(unit, buf_size, "flow tunnel terminator traverse"); 3546 if (NULL == vt_tbl_chnk) { 3547 return BCM_E_MEMORY; 3548 } 3549 3550 mem_idx_max = soc_mem_index_max(unit, mem); 3551 for (chnk_idx = soc_mem_index_min(unit, mem); 3552 chnk_idx <= mem_idx_max; 3553 chnk_idx += chunksize) { 3554 sal_memset((void *)vt_tbl_chnk, 0, buf_size); 3555 3556 chnk_idx_max = 3557 ((chnk_idx + chunksize) <= mem_idx_max) ? 3558 chnk_idx + chunksize - 1: mem_idx_max; 3559 3560 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 3561 chnk_idx, chnk_idx_max, vt_tbl_chnk); 3562 if (SOC_FAILURE(rv)) { 3563 break; 3564 } 3565 chnk_end = (chnk_idx_max - chnk_idx); 3566 for (ent_idx = 0 ; ent_idx <= chnk_end; ) { 3567 entry = 3568 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 3569 vt_tbl_chnk, ent_idx); 3570 rv = _bcm_flow_tunnel_terminator_entry_valid(unit, 3571 mem, entry, &valid); 3572 if (BCM_FAILURE(rv)) { 3573 break; 3574 } 3575 if (!valid) { 3576 ent_idx++; 3577 continue; 3578 } 3579 if (mem == L3_TUNNELm) { 3580 rv = _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, mem, 3581 entry, &num_hw_entries); 3582 if (BCM_FAILURE(rv)) { 3583 break; 3584 } 3585 for (i= 0; i < num_hw_entries; i++) { 3586 sal_memcpy((uint8 *)trav_entry + entry_width * i, 3587 entry, entry_width); 3588 ent_idx++; 3589 entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 3590 vt_tbl_chnk, ent_idx); 3591 } 3592 } else { 3593 sal_memcpy(trav_entry, entry, 3594 WORDS2BYTES(soc_mem_entry_words(unit, mem))); 3595 ent_idx++; 3596 } 3597 bcm_flow_tunnel_terminator_t_init(&info); 3598 3599 rv = _bcm_flow_tunnel_terminator_entry_parse(unit, mem, trav_entry, &info, 3600 &num_of_fields,field); 3601 if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */ 3602 continue; 3603 } else if (BCM_FAILURE(rv)) { 3604 break; 3605 } 3606 rv = cb(unit, &info, num_of_fields,field,user_data); 3607 if (BCM_FAILURE(rv)) { 3608 break; 3609 } 3610 } 3611 } 3612 soc_cm_sfree(unit, vt_tbl_chnk); 3613 return rv; 3614 } 3615 3616 /* 3617 * Function: 3618 * bcmi_esw_flow_tunnel_terminator_traverse 3619 * Purpose: 3620 * Traverse all flow tunnel initiator objects and call the user specified 3621 * callback function on each object. 3622 * 3623 * Parameters: 3624 * unit - (IN) Device Number 3625 * bcm_flow_tunnel_initiator_traverse_cb - (IN) user callback function 3626 * user_data - (IN) user context data for the callback 3627 * Returns: 3628 * BCM_E_XXX 3629 */ 3630 int bcmi_esw_flow_tunnel_terminator_traverse( 3631 int unit, 3632 bcm_flow_tunnel_terminator_traverse_cb cb, 3633 void *user_data) 3634 { 3635 soc_mem_t mem; 3636 3637 if (NULL == cb) { 3638 return (BCM_E_PARAM); 3639 } 3640 mem = VLAN_XLATE_1_DOUBLEm; 3641 BCM_IF_ERROR_RETURN( 3642 _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data)); 3643 3644 mem = MPLS_ENTRYm; /* MPLS_ENTRY_DOUBLE */ 3645 BCM_IF_ERROR_RETURN( 3646 _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data)); 3647 3648 mem = L3_TUNNELm; 3649 BCM_IF_ERROR_RETURN( 3650 _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data)); 3651 3652 mem = MPLS_ENTRY_SINGLEm; 3653 BCM_IF_ERROR_RETURN( 3654 _bcm_flow_tunnel_terminator_mem_traverse(unit, mem, cb, user_data)); 3655 return BCM_E_NONE; 3656 } 3657 3658 /* 3659 * Function : 3660 * _bcm_flow_tunnel_terminator_entry_term 3661 * Description : 3662 * Determine whether this is a tunnel terminator entry. 3663 * Parameters : 3664 * unit - (IN) Device Number 3665 * mem - (IN) memory id. 3666 * entry - (IN) HW entry. 3667 * term - (OUT) Tunnel terminator entry. 3668 */ 3669 STATIC int 3670 _bcm_flow_tunnel_terminator_entry_term(int unit, 3671 soc_mem_t mem, 3672 uint32 *entry, 3673 int *term) 3674 { 3675 int key_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 3676 int data_type = SOC_FLOW_DB_KEY_TYPE_INVALID; 3677 int i; 3678 soc_flow_db_mem_view_info_t vinfo; 3679 soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL]; 3680 uint32 num_ffo = 0; 3681 uint32 key_typef[] = {KEY_TYPEf, KEY_TYPE0f, KEY_TYPE1f}; 3682 uint32 data_typef[] = {DATA_TYPEf, DATA_TYPE0f, DATA_TYPE1f}; 3683 3684 uint32 mem_view_id = 0; 3685 int rv = BCM_E_NONE; 3686 3687 for (i = 0; i < SOC_FLOW_DB_MAX_KEY_TYPE; i++) { 3688 if (SOC_MEM_FIELD_VALID(unit,mem,key_typef[i])) { 3689 key_type = soc_mem_field32_get(unit, mem, entry, key_typef[i]); 3690 break; 3691 } 3692 } 3693 for (i = 0; i < SOC_FLOW_DB_MAX_DATA_TYPE; i++) { 3694 if (SOC_MEM_FIELD_VALID(unit,mem,data_typef[i])) { 3695 data_type = soc_mem_field32_get(unit, mem, entry, data_typef[i]); 3696 } 3697 } 3698 3699 /* find the memory view based on the memory and key type */ 3700 rv = soc_flow_db_mem_to_view_id_get (unit, mem, key_type, data_type, 3701 0, NULL, (uint32 *) &mem_view_id); 3702 3703 if (rv != BCM_E_NONE && rv != BCM_E_NOT_FOUND) { 3704 return rv; 3705 } 3706 3707 *term = 0; 3708 if (rv == BCM_E_NOT_FOUND) { 3709 /* Fixed view */ 3710 if ((key_type == _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP) || 3711 (key_type == _BCM_TD2_L2GRE_KEY_TYPE_LOOKUP_DIP)) { 3712 *term = 1; 3713 } else { 3714 *term = 0; 3715 } 3716 } else { 3717 /* Flex view */ 3718 /* find the memory view info */ 3719 BCM_IF_ERROR_RETURN( 3720 soc_flow_db_mem_view_info_get(unit, mem_view_id, &vinfo)); 3721 3722 /* get the flow handle, function id, option id */ 3723 BCM_IF_ERROR_RETURN( 3724 soc_flow_db_mem_view_to_ffo_get(unit, 3725 mem_view_id, 3726 SOC_FLOW_DB_MAX_VIEW_FFO_TPL, 3727 ffo, 3728 &num_ffo)); 3729 3730 3731 if(ffo[0].function_id == SOC_FLOW_DB_FUNC_TUNNEL_TERMINATOR_ID) { 3732 *term = 1; 3733 } else { 3734 *term = 0; 3735 } 3736 } 3737 3738 return BCM_E_NONE; 3739 } 3740 3741 /* 3742 * Function: 3743 * bcmi_esw_flow_tunnel_terminator_destroy_all 3744 * Purpose: 3745 * Destroy all flow tunnel terminator entry 3746 * 3747 * Parameters: 3748 * unit - (IN) Device Number 3749 * Returns: 3750 * BCM_E_XXX 3751 */ 3752 int bcmi_esw_flow_tunnel_terminator_destroy_all( 3753 int unit) 3754 { 3755 soc_mem_t tunnel_mems[4] = {VLAN_XLATE_1_DOUBLEm, MPLS_ENTRYm, 3756 L3_TUNNELm, INVALIDm}; 3757 int mem_index = 0; 3758 soc_tunnel_term_t tnl_entry; 3759 soc_tunnel_term_t ret_tnl_entry; 3760 uint32 ret_entry[SOC_MAX_MEM_WORDS]; 3761 int index = 0; 3762 int chnk_idx, ent_idx, chnk_idx_max, mem_idx_max; 3763 int buf_size, chunksize, chnk_end; 3764 uint32 *tbl_chnk; 3765 uint32 *entry; 3766 int valid = FALSE; 3767 uint32 num_hw_entries = 0; 3768 int i = 0; 3769 soc_mem_t mem; 3770 int term = 0; 3771 int rv = BCM_E_NONE; 3772 3773 if ((SOC_HW_RESET(unit) || 3774 (SOC_SWITCH_BYPASS_MODE(unit) != SOC_SWITCH_BYPASS_MODE_NONE))) { 3775 return BCM_E_NONE; 3776 } 3777 3778 while (INVALIDm != tunnel_mems[mem_index]){ 3779 mem = tunnel_mems[mem_index++]; 3780 if (!soc_mem_index_count(unit, mem)) { 3781 continue; 3782 } 3783 3784 chunksize = 1024; 3785 buf_size = soc_mem_entry_words(unit, mem) * sizeof(uint32) * chunksize; 3786 tbl_chnk = soc_cm_salloc(unit, buf_size, "flow tunnel term destroy"); 3787 if (NULL == tbl_chnk) { 3788 return BCM_E_MEMORY; 3789 } 3790 3791 mem_idx_max = soc_mem_index_max(unit, mem); 3792 3793 for (chnk_idx = soc_mem_index_min(unit, mem); 3794 chnk_idx <= mem_idx_max; 3795 chnk_idx += chunksize) { 3796 sal_memset((void *)tbl_chnk, 0, buf_size); 3797 3798 chnk_idx_max = 3799 ((chnk_idx + chunksize) <= mem_idx_max) ? 3800 chnk_idx + chunksize - 1: mem_idx_max; 3801 3802 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 3803 chnk_idx, chnk_idx_max, tbl_chnk); 3804 if (SOC_FAILURE(rv)) { 3805 break; 3806 } 3807 3808 chnk_end = (chnk_idx_max - chnk_idx); 3809 for (ent_idx = 0 ; ent_idx <= chnk_end; ) { 3810 entry = 3811 soc_mem_table_idx_to_pointer(unit, mem, uint32 *, 3812 tbl_chnk, ent_idx); 3813 rv = _bcm_flow_tunnel_terminator_entry_valid(unit, 3814 mem, entry, &valid); 3815 if (BCM_FAILURE(rv)) { 3816 break; 3817 } 3818 if (!valid) { 3819 ent_idx++; 3820 continue; 3821 } 3822 if (mem == L3_TUNNELm) { 3823 rv = _bcm_esw_flow_tnl_term_num_hw_entries_get(unit, mem, 3824 entry, &num_hw_entries); 3825 if (BCM_FAILURE(rv)) { 3826 break; 3827 } 3828 for (i= 0; i < num_hw_entries; i++) { 3829 ent_idx++; 3830 entry = soc_mem_table_idx_to_pointer(unit, mem, 3831 uint32 *,tbl_chnk, ent_idx); 3832 } 3833 } else { 3834 ent_idx++; 3835 } 3836 3837 term = 0; 3838 rv = _bcm_flow_tunnel_terminator_entry_term(unit, mem, 3839 entry, &term); 3840 if (BCM_FAILURE(rv)) { 3841 break; 3842 } else if (term){ 3843 if (mem == L3_TUNNELm) { 3844 rv = bcmi_esw_flow_entry_to_tnl_term(unit, entry, 3845 &tnl_entry); 3846 if (rv == BCM_E_NONE) { 3847 rv = soc_tunnel_term_match(unit, &tnl_entry, 3848 &ret_tnl_entry, &index); 3849 } 3850 if (rv == BCM_E_NONE) { 3851 rv = soc_tunnel_term_delete(unit, &ret_tnl_entry); 3852 } 3853 } else { 3854 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, 3855 entry, ret_entry, 0); 3856 if (rv == BCM_E_NONE) { 3857 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, 3858 &ret_entry); 3859 } 3860 } 3861 3862 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) { 3863 break; 3864 } 3865 } else { 3866 continue; 3867 } 3868 } 3869 /* error detect, ignore this table */ 3870 if (ent_idx <= chnk_end ) { 3871 break; 3872 } 3873 } 3874 soc_cm_sfree(unit, tbl_chnk); 3875 } 3876 3877 return BCM_E_NONE; 3878 } 3879 3880 #ifdef BCM_WARM_BOOT_SUPPORT 3881 3882 /* 3883 * Function: 3884 * _bcm_flow_tunnel_initiator_reinit 3885 * Purpose: 3886 * Tunnel initiator hash and ref-count recovery. 3887 * Parameters: 3888 * unit - (IN) BCM device number. 3889 * Returns: 3890 * BCM_E_XXX 3891 */ 3892 int 3893 _bcm_flow_tunnel_initiator_reinit(int unit) 3894 { 3895 bcm_flow_tunnel_initiator_t tnl_init_info; 3896 int rv = BCM_E_NONE; 3897 int i = 0; 3898 int idx_min = 0; 3899 int idx_max = 0; 3900 bcm_flow_logical_field_t field[_BCM_FLOW_LOGICAL_FIELD_MAX]; 3901 uint32 cnt; 3902 soc_mem_t mem; 3903 _bcm_flow_tunnel_record_t tnl_rec; 3904 3905 mem = EGR_IP_TUNNELm; 3906 idx_min = soc_mem_index_min(unit, mem); 3907 idx_max = soc_mem_index_max(unit, mem); 3908 3909 for (i = idx_min; i <= idx_max; i++) { 3910 3911 bcm_flow_tunnel_initiator_t_init(&tnl_init_info); 3912 rv = _bcm_flow_hw_tunnel_entry_get(unit, i, &tnl_init_info,field, 3913 _BCM_FLOW_LOGICAL_FIELD_MAX,&cnt); 3914 BCM_IF_ERROR_RETURN(rv); 3915 3916 tnl_rec.info = &tnl_init_info; 3917 tnl_rec.field = field; 3918 tnl_rec.num_of_fields = cnt; 3919 3920 rv = _bcm_flow_tunnel_initiator_hash_calc(unit, &tnl_rec, 3921 &BCM_XGS3_L3_ENT_HASH(BCM_XGS3_L3_TBL_PTR( 3922 unit, tnl_init), i)); 3923 BCM_IF_ERROR_RETURN(rv); 3924 BCM_XGS3_L3_ENT_REF_CNT_INC 3925 (BCM_XGS3_L3_TBL_PTR(unit, tnl_init), i, 3926 ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ? 3927 _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE)); 3928 } 3929 return rv; 3930 } 3931 #endif 3932 3933 #endif /* INCLUDE_L3 */ 3934