tunnel.c (15197B)
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: bcmx/l3.c 8 * Purpose: BCMX APIs 9 */ 10 11 #include <sal/core/libc.h> 12 #include <shared/alloc.h> 13 14 #include <bcm/types.h> 15 16 #include <bcmx/l3.h> 17 #include <bcmx/tunnel.h> 18 #include <bcmx/lport.h> 19 #include <bcmx/bcmx.h> 20 #include <bcmx/lplist.h> 21 22 #include "bcmx_int.h" 23 24 #ifdef INCLUDE_L3 25 26 #define BCMX_TUNNEL_INIT_CHECK BCMX_READY_CHECK 27 28 #define BCMX_TUNNEL_SET_ERROR_CHECK(_unit, _check, _rv) \ 29 BCMX_SET_ERROR_CHECK(_unit, _check, _rv) 30 31 #define BCMX_TUNNEL_DELETE_ERROR_CHECK(_unit, _check, _rv) \ 32 BCMX_DELETE_ERROR_CHECK(_unit, _check, _rv) 33 34 #define BCMX_TUNNEL_GET_IS_VALID(_unit, _rv) \ 35 BCMX_ERROR_IS_VALID(_unit, _rv) 36 37 38 STATIC INLINE void 39 _bcmx_tunnel_to_bcm(bcmx_tunnel_terminator_t *l3xtun, 40 bcm_tunnel_terminator_t *l3tun) 41 { 42 bcm_tunnel_terminator_t_init(l3tun); 43 l3tun->flags = l3xtun->flags; 44 l3tun->vrf = l3xtun->vrf; 45 l3tun->sip = l3xtun->sip; 46 l3tun->dip = l3xtun->dip; 47 l3tun->sip_mask = l3xtun->sip_mask; 48 l3tun->dip_mask = l3xtun->dip_mask; 49 sal_memcpy(l3tun->sip6, l3xtun->sip6, sizeof(bcm_ip6_t)); 50 sal_memcpy(l3tun->dip6, l3xtun->dip6, sizeof(bcm_ip6_t)); 51 sal_memcpy(l3tun->sip6_mask, l3xtun->sip6_mask, sizeof(bcm_ip6_t)); 52 sal_memcpy(l3tun->dip6_mask, l3xtun->dip6_mask, sizeof(bcm_ip6_t)); 53 l3tun->udp_dst_port = l3xtun->udp_dst_port; 54 l3tun->udp_src_port = l3xtun->udp_src_port; 55 l3tun->type = l3xtun->type; 56 l3tun->vlan = l3xtun->vlan; 57 l3tun->remote_port = l3xtun->remote_port; 58 l3tun->tunnel_id = l3xtun->tunnel_id; 59 l3tun->if_class = l3xtun->if_class; 60 } 61 62 STATIC INLINE void 63 _bcmx_tunnel_from_bcm(bcm_tunnel_terminator_t *l3tun, 64 bcmx_tunnel_terminator_t *l3xtun) 65 { 66 bcmx_tunnel_terminator_t_init(l3xtun); 67 l3xtun->flags = l3tun->flags; 68 l3xtun->vrf = l3tun->vrf; 69 l3xtun->sip = l3tun->sip; 70 l3xtun->dip = l3tun->dip; 71 l3xtun->sip_mask = l3tun->sip_mask; 72 l3xtun->dip_mask = l3tun->dip_mask; 73 sal_memcpy(l3xtun->sip6, l3tun->sip6, sizeof(bcm_ip6_t)); 74 sal_memcpy(l3xtun->dip6, l3tun->dip6, sizeof(bcm_ip6_t)); 75 sal_memcpy(l3xtun->sip6_mask, l3tun->sip6_mask, sizeof(bcm_ip6_t)); 76 sal_memcpy(l3xtun->dip6_mask, l3tun->dip6_mask, sizeof(bcm_ip6_t)); 77 l3xtun->udp_dst_port = l3tun->udp_dst_port; 78 l3xtun->udp_src_port = l3tun->udp_src_port; 79 l3xtun->type = l3tun->type; 80 l3xtun->vlan = l3tun->vlan; 81 l3xtun->remote_port = l3tun->remote_port; 82 l3xtun->tunnel_id = l3tun->tunnel_id; 83 l3xtun->if_class = l3tun->if_class; 84 } 85 86 /* 87 * Initialize a tunneling terminator structure 88 * 89 * Notes: 90 * Memory is allocated for the port list member in this 91 * call. The corresponding 'free' API needs to be called 92 * when structure is no longer needed. 93 */ 94 void 95 bcmx_tunnel_terminator_t_init(bcmx_tunnel_terminator_t *info) 96 { 97 if (info != NULL) { 98 sal_memset(info, 0, sizeof(bcmx_tunnel_terminator_t)); 99 info->vrf = BCM_L3_VRF_DEFAULT; 100 bcmx_lplist_t_init(&info->ports); 101 } 102 } 103 104 /* 105 * Free memory allocated by the tunneling terminator initialization routine 106 */ 107 void 108 bcmx_tunnel_terminator_t_free(bcmx_tunnel_terminator_t *info) 109 { 110 if (info != NULL) { 111 bcmx_lplist_free(&info->ports); 112 } 113 } 114 115 /* 116 * Initialize a tunneling header (initiator) structure 117 */ 118 void 119 bcmx_tunnel_initiator_t_init(bcmx_tunnel_initiator_t *tunnel) 120 { 121 if (tunnel != NULL) { 122 sal_memset(tunnel, 0, sizeof(bcmx_tunnel_initiator_t)); 123 } 124 } 125 126 /* 127 * Initialize a tunnel configuration structure 128 */ 129 void 130 bcmx_tunnel_config_t_init(bcmx_tunnel_config_t *tconfig) 131 { 132 if (tconfig != NULL) { 133 sal_memset(tconfig, 0, sizeof(bcmx_tunnel_config_t)); 134 } 135 } 136 137 /************************************************************** 138 * bcmx_tunnel_xxx 139 */ 140 141 /* 142 * Function: 143 * bcmx_tunnel_terminator_add 144 */ 145 146 int 147 bcmx_tunnel_terminator_add(bcmx_tunnel_terminator_t *info) 148 { 149 int rv = BCM_E_UNAVAIL, tmp_rv; 150 int i, bcm_unit; 151 bcm_tunnel_terminator_t bcm_tunnel; 152 153 BCMX_TUNNEL_INIT_CHECK; 154 155 BCMX_PARAM_NULL_CHECK(info); 156 157 _bcmx_tunnel_to_bcm(info, &bcm_tunnel); 158 BCMX_UNIT_ITER(bcm_unit, i) { 159 BCMX_LPLIST_TO_PBMP(info->ports, bcm_unit, bcm_tunnel.pbmp); 160 if(BCM_PBMP_NOT_NULL(bcm_tunnel.pbmp)) { 161 tmp_rv = bcm_tunnel_terminator_add(bcm_unit, &bcm_tunnel); 162 BCM_IF_ERROR_RETURN 163 (BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 164 } 165 } 166 return rv; 167 } 168 169 /* 170 * Function: 171 * bcmx_tunnel_terminator_delete 172 */ 173 174 int 175 bcmx_tunnel_terminator_delete(bcmx_tunnel_terminator_t *info) 176 { 177 int rv = BCM_E_UNAVAIL, tmp_rv; 178 int i, bcm_unit; 179 bcm_tunnel_terminator_t bcm_tunnel; 180 181 BCMX_TUNNEL_INIT_CHECK; 182 183 BCMX_PARAM_NULL_CHECK(info); 184 185 _bcmx_tunnel_to_bcm(info, &bcm_tunnel); 186 BCMX_UNIT_ITER(bcm_unit, i) { 187 BCMX_LPLIST_TO_PBMP(info->ports, bcm_unit, bcm_tunnel.pbmp); 188 if(BCM_PBMP_NOT_NULL(bcm_tunnel.pbmp)) { 189 tmp_rv = bcm_tunnel_terminator_delete(bcm_unit, &bcm_tunnel); 190 BCM_IF_ERROR_RETURN 191 (BCMX_TUNNEL_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 192 } 193 } 194 195 return rv; 196 } 197 198 /* 199 * Function: 200 * bcmx_tunnel_terminator_update 201 */ 202 203 int 204 bcmx_tunnel_terminator_update(bcmx_tunnel_terminator_t *info) 205 { 206 int rv = BCM_E_UNAVAIL, tmp_rv; 207 int i, bcm_unit; 208 bcm_tunnel_terminator_t bcm_tunnel; 209 210 BCMX_TUNNEL_INIT_CHECK; 211 212 BCMX_PARAM_NULL_CHECK(info); 213 214 _bcmx_tunnel_to_bcm(info, &bcm_tunnel); 215 BCMX_UNIT_ITER(bcm_unit, i) { 216 BCMX_LPLIST_TO_PBMP(info->ports, bcm_unit, bcm_tunnel.pbmp); 217 if(BCM_PBMP_NOT_NULL(bcm_tunnel.pbmp)) { 218 tmp_rv = bcm_tunnel_terminator_update(bcm_unit, &bcm_tunnel); 219 BCM_IF_ERROR_RETURN 220 (BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 221 } 222 } 223 224 return rv; 225 } 226 227 /* 228 * Function: 229 * bcmx_tunnel_terminator_get 230 */ 231 232 int 233 bcmx_tunnel_terminator_get(bcmx_tunnel_terminator_t *info) 234 { 235 int rv = BCM_E_UNAVAIL, tmp_rv; 236 int i, bcm_unit; 237 bcm_tunnel_terminator_t bcm_tunnel; 238 239 BCMX_TUNNEL_INIT_CHECK; 240 241 BCMX_PARAM_NULL_CHECK(info); 242 243 _bcmx_tunnel_to_bcm(info, &bcm_tunnel); 244 BCMX_UNIT_ITER(bcm_unit, i) { 245 tmp_rv = bcm_tunnel_terminator_get(bcm_unit, &bcm_tunnel); 246 247 /* Ignore those units that don't have tunnel terminator ports */ 248 if (tmp_rv == BCM_E_NOT_FOUND) { 249 if (rv == BCM_E_UNAVAIL) { 250 rv = tmp_rv; 251 } 252 continue; 253 } 254 255 if (BCMX_TUNNEL_GET_IS_VALID(bcm_unit, tmp_rv)) { 256 rv = tmp_rv; 257 if (BCM_SUCCESS(tmp_rv)) { 258 rv = BCMX_LPLIST_PBMP_ADD(&info->ports, bcm_unit, 259 bcm_tunnel.pbmp); 260 } else { 261 break; 262 } 263 } 264 } 265 if (BCM_SUCCESS(rv)) { 266 _bcmx_tunnel_from_bcm(&bcm_tunnel, info); 267 } 268 269 return rv; 270 } 271 272 273 /* 274 * Function: 275 * bcmx_tunnel_initiator_set 276 */ 277 278 int 279 bcmx_tunnel_initiator_set(bcmx_l3_intf_t *intf, 280 bcmx_tunnel_initiator_t *tunnel) 281 { 282 int rv = BCM_E_UNAVAIL, tmp_rv; 283 int i, bcm_unit; 284 285 BCMX_TUNNEL_INIT_CHECK; 286 287 BCMX_PARAM_NULL_CHECK(intf); 288 BCMX_PARAM_NULL_CHECK(tunnel); 289 290 BCMX_UNIT_ITER(bcm_unit, i) { 291 tmp_rv = bcm_tunnel_initiator_set(bcm_unit, intf, tunnel); 292 BCM_IF_ERROR_RETURN(BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 293 } 294 295 return rv; 296 } 297 298 /* 299 * Function: 300 * bcmx_tunnel_initiator_clear 301 */ 302 303 int 304 bcmx_tunnel_initiator_clear(bcmx_l3_intf_t *intf) 305 { 306 int rv = BCM_E_UNAVAIL, tmp_rv; 307 int i, bcm_unit; 308 309 BCMX_TUNNEL_INIT_CHECK; 310 311 BCMX_PARAM_NULL_CHECK(intf); 312 313 BCMX_UNIT_ITER(bcm_unit, i) { 314 tmp_rv = bcm_tunnel_initiator_clear(bcm_unit, intf); 315 BCM_IF_ERROR_RETURN 316 (BCMX_TUNNEL_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 317 } 318 319 return rv; 320 } 321 322 /* 323 * Function: 324 * bcmx_tunnel_initiator_get 325 */ 326 327 int 328 bcmx_tunnel_initiator_get(bcmx_l3_intf_t *intf, 329 bcmx_tunnel_initiator_t *tunnel) 330 { 331 int rv; 332 int i, bcm_unit; 333 334 BCMX_TUNNEL_INIT_CHECK; 335 336 BCMX_PARAM_NULL_CHECK(intf); 337 BCMX_PARAM_NULL_CHECK(tunnel); 338 339 BCMX_UNIT_ITER(bcm_unit, i) { 340 rv = bcm_tunnel_initiator_get(bcm_unit, intf, tunnel); 341 if (BCMX_TUNNEL_GET_IS_VALID(bcm_unit, rv)) { 342 return rv; 343 } 344 } 345 346 return BCM_E_UNAVAIL; 347 } 348 349 350 /* 351 * Function: 352 * bcmx_tunnel_dscp_map_create 353 * Purpose: 354 * Create a tunnel DSCP map instance. 355 * Parameters: 356 * flags - (IN) BCM_L3_XXX 357 * dscp_map_id - (OUT) Allocated DSCP map ID 358 * Returns: 359 * BCM_E_XXX 360 */ 361 int 362 bcmx_tunnel_dscp_map_create(uint32 flags, int *dscp_map_id) 363 { 364 int rv = BCM_E_UNAVAIL, tmp_rv; 365 int i, bcm_unit; 366 367 BCMX_TUNNEL_INIT_CHECK; 368 369 BCMX_PARAM_NULL_CHECK(dscp_map_id); 370 371 BCMX_UNIT_ITER(bcm_unit, i) { 372 tmp_rv = bcm_tunnel_dscp_map_create(bcm_unit, flags, dscp_map_id); 373 BCM_IF_ERROR_RETURN(BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 374 } 375 376 return rv; 377 } 378 379 380 /* 381 * Function: 382 * bcmx_tunnel_dscp_map_destroy 383 * Purpose: 384 * Destroy an existing tunnel DSCP map instance. 385 * Parameters: 386 * dscp_map_id - (IN) DSCP map ID 387 * Returns: 388 * BCM_E_XXX 389 */ 390 int 391 bcmx_tunnel_dscp_map_destroy(int dscp_map_id) 392 { 393 int rv = BCM_E_UNAVAIL, tmp_rv; 394 int i, bcm_unit; 395 396 BCMX_TUNNEL_INIT_CHECK; 397 398 BCMX_UNIT_ITER(bcm_unit, i) { 399 tmp_rv = bcm_tunnel_dscp_map_destroy(bcm_unit, dscp_map_id); 400 BCM_IF_ERROR_RETURN 401 (BCMX_TUNNEL_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 402 } 403 404 return rv; 405 } 406 407 408 /* 409 * Function: 410 * bcmx_tunnel_dscp_map_set 411 * Purpose: 412 * Set the mapping of { internal priority, color } 413 * to a DSCP value for outer tunnel headers 414 * in the specified DSCP map instance. 415 * Parameters: 416 * dscp_map_id - (IN) DSCP map ID 417 * dscp_map - (IN) tunnel DSCP info 418 * Returns: 419 * BCM_E_XXX 420 */ 421 int 422 bcmx_tunnel_dscp_map_set(int dscp_map_id, 423 bcm_tunnel_dscp_map_t *dscp_map) 424 { 425 int rv = BCM_E_UNAVAIL, tmp_rv; 426 int i, bcm_unit; 427 428 BCMX_TUNNEL_INIT_CHECK; 429 430 BCMX_PARAM_NULL_CHECK(dscp_map); 431 432 BCMX_UNIT_ITER(bcm_unit, i) { 433 tmp_rv = bcm_tunnel_dscp_map_set(bcm_unit, dscp_map_id, dscp_map); 434 BCM_IF_ERROR_RETURN(BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 435 } 436 437 return rv; 438 } 439 440 441 /* 442 * Function: 443 * bcmx_tunnel_dscp_map_get 444 * Purpose: 445 * Get the tunnel DSCP map information for the specified 446 * DSCP map instance. 447 * Parameters: 448 * dscp_map_id - (IN) DSCP map ID 449 * dscp_map - (OUT) Returning DSCP map info 450 * Returns: 451 * BCM_E_XXX 452 */ 453 int 454 bcmx_tunnel_dscp_map_get(int dscp_map_id, 455 bcm_tunnel_dscp_map_t *dscp_map) 456 { 457 int rv; 458 int i, bcm_unit; 459 460 BCMX_TUNNEL_INIT_CHECK; 461 462 BCMX_PARAM_NULL_CHECK(dscp_map); 463 464 BCMX_UNIT_ITER(bcm_unit, i) { 465 rv = bcm_tunnel_dscp_map_get(bcm_unit, dscp_map_id, dscp_map); 466 if (BCMX_TUNNEL_GET_IS_VALID(bcm_unit, rv)) { 467 return rv; 468 } 469 } 470 471 return BCM_E_UNAVAIL; 472 } 473 474 475 /* 476 * Function: 477 * bcmx_tunnel_dscp_map_port_set 478 * Purpose: 479 * Set the mapping of { internal priority, color } 480 * to a DSCP value for outer tunnel headers 481 * for a specific egress port. 482 * Parameters: 483 * port - (IN) Egress port number. 484 * dscp_map - (IN) tunnel DSCP info 485 * Returns: 486 * BCM_E_XXX 487 */ 488 int 489 bcmx_tunnel_dscp_map_port_set(bcmx_lport_t port, 490 bcm_tunnel_dscp_map_t *dscp_map) 491 { 492 int bcm_unit; 493 bcm_port_t bcm_port; 494 495 BCMX_TUNNEL_INIT_CHECK; 496 497 BCMX_PARAM_NULL_CHECK(dscp_map); 498 499 BCM_IF_ERROR_RETURN 500 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 501 BCMX_DEST_CONVERT_DEFAULT)); 502 503 return bcm_tunnel_dscp_map_set(bcm_unit, bcm_port, 504 dscp_map); 505 } 506 507 508 /* 509 * Function: 510 * bcmx_tunnel_dscp_map_port_get 511 * Purpose: 512 * Get the tunnel DSCP map information for the specified 513 * egress port 514 * Parameters: 515 * port - (IN) Egress port number 516 * dscp_map - (OUT) Returning DSCP map info 517 * Returns: 518 * BCM_E_XXX 519 */ 520 int 521 bcmx_tunnel_dscp_map_port_get(bcmx_lport_t port, 522 bcm_tunnel_dscp_map_t *dscp_map) 523 { 524 int bcm_unit; 525 bcm_port_t bcm_port; 526 527 BCMX_TUNNEL_INIT_CHECK; 528 529 BCMX_PARAM_NULL_CHECK(dscp_map); 530 531 BCM_IF_ERROR_RETURN 532 (_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port, 533 BCMX_DEST_CONVERT_DEFAULT)); 534 535 return bcm_tunnel_dscp_map_get(bcm_unit, bcm_port, 536 dscp_map); 537 } 538 539 540 /* 541 * Function: 542 * bcmx_tunnel_config_set 543 */ 544 545 int 546 bcmx_tunnel_config_set(bcmx_tunnel_config_t *tconfig) 547 { 548 int rv = BCM_E_UNAVAIL, tmp_rv; 549 int i, bcm_unit; 550 551 BCMX_TUNNEL_INIT_CHECK; 552 553 BCMX_PARAM_NULL_CHECK(tconfig); 554 555 BCMX_UNIT_ITER(bcm_unit, i) { 556 tmp_rv = bcm_tunnel_config_set(bcm_unit, tconfig); 557 BCM_IF_ERROR_RETURN(BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 558 } 559 560 return rv; 561 } 562 563 /* 564 * Function: 565 * bcmx_tunnel_config_get 566 */ 567 568 int 569 bcmx_tunnel_config_get(bcmx_tunnel_config_t *tconfig) 570 { 571 int rv; 572 int i, bcm_unit; 573 574 BCMX_TUNNEL_INIT_CHECK; 575 576 BCMX_UNIT_ITER(bcm_unit, i) { 577 rv = bcm_tunnel_config_get(bcm_unit, tconfig); 578 if (BCMX_TUNNEL_GET_IS_VALID(bcm_unit, rv)) { 579 return rv; 580 } 581 } 582 583 return BCM_E_UNAVAIL; 584 } 585 586 587 /* 588 * Function: 589 * bcmx_tunnel_terminator_vlan_set 590 * Purpose: 591 * Set the allowed VLANs for a WLAN tunnel. 592 * Parameters: 593 * tunnel - Tunnel ID 594 * vlan_vec - VLAN vector 595 * Returns: 596 * BCM_E_XXX 597 */ 598 int 599 bcmx_tunnel_terminator_vlan_set(bcm_gport_t tunnel, 600 bcm_vlan_vector_t vlan_vec) 601 { 602 int rv = BCM_E_UNAVAIL, tmp_rv; 603 int i, bcm_unit; 604 605 BCMX_TUNNEL_INIT_CHECK; 606 607 BCMX_UNIT_ITER(bcm_unit, i) { 608 tmp_rv = bcm_tunnel_terminator_vlan_set(bcm_unit, tunnel, vlan_vec); 609 BCM_IF_ERROR_RETURN(BCMX_TUNNEL_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv)); 610 } 611 612 return rv; 613 } 614 615 /* 616 * Function: 617 * bcmx_tunnel_terminator_vlan_get 618 * Purpose: 619 * Get the allowed VLANs for a WLAN tunnel. 620 * Parameters: 621 * tunnel - Tunnel ID 622 * vlan_vec - (OUT) VLAN vector 623 * Returns: 624 * BCM_E_XXX 625 */ 626 int 627 bcmx_tunnel_terminator_vlan_get(bcm_gport_t tunnel, 628 bcm_vlan_vector_t *vlan_vec) 629 { 630 int rv; 631 int i, bcm_unit; 632 633 BCMX_TUNNEL_INIT_CHECK; 634 635 BCMX_PARAM_NULL_CHECK(vlan_vec); 636 637 BCMX_UNIT_ITER(bcm_unit, i) { 638 rv = bcm_tunnel_terminator_vlan_get(bcm_unit, tunnel, vlan_vec); 639 if (BCMX_TUNNEL_GET_IS_VALID(bcm_unit, rv)) { 640 return rv; 641 } 642 } 643 644 return BCM_E_UNAVAIL; 645 } 646 647 #endif /* INCLUDE_L3 */