master_config.c (19396B)
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: master_config.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * bcm_common_ptp_static_unicast_master_add 13 * bcm_common_ptp_static_unicast_master_list 14 * bcm_common_ptp_static_unicast_master_remove 15 * bcm_common_ptp_static_unicast_master_table_clear 16 * bcm_common_ptp_static_unicast_master_table_size_get 17 */ 18 19 #if defined(INCLUDE_PTP) 20 21 #include <soc/defs.h> 22 #include <soc/drv.h> 23 24 #include <bcm/ptp.h> 25 #include <bcm_int/common/ptp.h> 26 #include <bcm/error.h> 27 #include <bcm_int/ptp_common.h> 28 29 /* PTP clock unicast master table. */ 30 typedef struct _bcm_ptp_unicast_master_table_s { 31 uint16 num_entries; 32 bcm_ptp_clock_unicast_master_t entry[PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES]; 33 } _bcm_ptp_unicast_master_table_t; 34 35 /* PTP stack unicast master table array. */ 36 typedef struct _bcm_ptp_stack_ucm_array_s { 37 _bcm_ptp_memstate_t memstate; 38 _bcm_ptp_unicast_master_table_t *table; 39 } _bcm_ptp_stack_ucm_array_t; 40 41 /* Unit unicast master table array(s). */ 42 typedef struct _bcm_ptp_unit_ucm_array_s { 43 _bcm_ptp_memstate_t memstate; 44 _bcm_ptp_stack_ucm_array_t *stack_array; 45 } _bcm_ptp_unit_ucm_array_t; 46 47 static const bcm_ptp_clock_unicast_master_t ucm_entry_default; 48 static const _bcm_ptp_unicast_master_table_t ucm_default; 49 static _bcm_ptp_unit_ucm_array_t unit_ucm_array[BCM_MAX_NUM_UNITS]; 50 51 static int _bcm_ptp_unicast_master_table_set(int unit, bcm_ptp_stack_id_t ptp_id, int clock_num); 52 53 /* 54 * Function: 55 * _bcm_ptp_unicast_master_table_init 56 * Purpose: 57 * Initialize the unicast master table arrays of a unit. 58 * Parameters: 59 * unit - (IN) Unit number. 60 * Returns: 61 * BCM_E_XXX 62 * Notes: 63 */ 64 int 65 _bcm_ptp_unicast_master_table_init( 66 int unit) 67 { 68 int rv = BCM_E_UNAVAIL; 69 int i; 70 71 _bcm_ptp_stack_ucm_array_t *stack_p; 72 73 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 74 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 75 return rv; 76 } 77 if (NULL == unit_ucm_array[unit].stack_array) { 78 stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT* 79 sizeof(_bcm_ptp_stack_ucm_array_t),"Unit UCM arrays"); 80 } else { 81 stack_p = unit_ucm_array[unit].stack_array; 82 } 83 84 if (!stack_p) { 85 unit_ucm_array[unit].memstate = PTP_MEMSTATE_FAILURE; 86 return BCM_E_MEMORY; 87 } 88 89 unit_ucm_array[unit].stack_array = stack_p; 90 unit_ucm_array[unit].memstate = PTP_MEMSTATE_INITIALIZED; 91 92 for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) { 93 unit_ucm_array[unit].stack_array[i].memstate = PTP_MEMSTATE_STARTUP; 94 } 95 96 return rv; 97 } 98 99 /* 100 * Function: 101 * _bcm_ptp_unicast_master_table_init_detach 102 * Purpose: 103 * Shut down the unicast master table arrays of a unit. 104 * Parameters: 105 * unit - (IN) Unit number. 106 * Returns: 107 * BCM_E_XXX 108 * Notes: 109 */ 110 int 111 _bcm_ptp_unicast_master_table_detach( 112 int unit) 113 { 114 int i; 115 116 if(unit_ucm_array[unit].stack_array) { 117 for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) { 118 _bcm_ptp_unicast_master_table_stack_destroy(unit, i); 119 } 120 121 unit_ucm_array[unit].memstate = PTP_MEMSTATE_STARTUP; 122 sal_free(unit_ucm_array[unit].stack_array); 123 unit_ucm_array[unit].stack_array = NULL; 124 } 125 return BCM_E_NONE; 126 } 127 128 /* 129 * Function: 130 * _bcm_ptp_unicast_master_table_stack_create 131 * Purpose: 132 * Create the unicast master table array of a PTP stack. 133 * Parameters: 134 * unit - (IN) Unit number. 135 * ptp_id - (IN) PTP stack ID. 136 * Returns: 137 * BCM_E_XXX 138 * Notes: 139 */ 140 int 141 _bcm_ptp_unicast_master_table_stack_create( 142 int unit, 143 bcm_ptp_stack_id_t ptp_id) 144 { 145 int rv = BCM_E_UNAVAIL; 146 147 _bcm_ptp_unicast_master_table_t *table_p; 148 int i = 0; 149 150 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 151 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 152 return rv; 153 } 154 155 if (unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 156 return BCM_E_UNAVAIL; 157 } 158 159 if (unit_ucm_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_INITIALIZED) { 160 return BCM_E_EXISTS; 161 } 162 163 table_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES* 164 sizeof(_bcm_ptp_unicast_master_table_t), 165 "PTP stack UCM array"); 166 167 if (!table_p) { 168 unit_ucm_array[unit].stack_array[ptp_id].memstate = 169 PTP_MEMSTATE_FAILURE; 170 return BCM_E_MEMORY; 171 } 172 173 unit_ucm_array[unit].stack_array[ptp_id].table = table_p; 174 unit_ucm_array[unit].stack_array[ptp_id].memstate = 175 PTP_MEMSTATE_INITIALIZED; 176 177 /* Set number of entries. */ 178 for (i = 0; i < PTP_MAX_CLOCK_INSTANCES; ++i) { 179 unit_ucm_array[unit].stack_array[ptp_id].table[i].num_entries = 0; 180 } 181 182 return rv; 183 } 184 185 /* 186 * Function: 187 * _bcm_ptp_unicast_master_table_stack_destroy 188 * Purpose: 189 * Destroy the unicast master table array of a PTP stack. 190 * Parameters: 191 * unit - (IN) Unit number. 192 * ptp_id - (IN) PTP stack ID. 193 * Returns: 194 * BCM_E_XXX 195 * Notes: 196 */ 197 int 198 _bcm_ptp_unicast_master_table_stack_destroy( 199 int unit, 200 bcm_ptp_stack_id_t ptp_id) 201 { 202 int rv = BCM_E_NONE; 203 204 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 205 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 206 return rv; 207 } 208 209 if (unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 210 return BCM_E_UNAVAIL; 211 } 212 213 if (unit_ucm_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_INITIALIZED) { 214 unit_ucm_array[unit].stack_array[ptp_id].memstate = 215 PTP_MEMSTATE_STARTUP; 216 sal_free(unit_ucm_array[unit].stack_array[ptp_id].table); 217 unit_ucm_array[unit].stack_array[ptp_id].table = 0; 218 } 219 220 return rv; 221 } 222 223 /* 224 * Function: 225 * _bcm_ptp_unicast_master_table_clock_create 226 * Purpose: 227 * Create the unicast master table array of a PTP clock. 228 * Parameters: 229 * unit - (IN) Unit number. 230 * ptp_id - (IN) PTP stack ID. 231 * clock_num - (IN) PTP clock number. 232 * Returns: 233 * BCM_E_XXX 234 * Notes: 235 */ 236 int 237 _bcm_ptp_unicast_master_table_clock_create( 238 int unit, 239 bcm_ptp_stack_id_t ptp_id, 240 int clock_num) 241 { 242 int rv = BCM_E_UNAVAIL; 243 244 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 245 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 246 return rv; 247 } 248 249 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 250 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 251 PTP_MEMSTATE_INITIALIZED)) { 252 return BCM_E_UNAVAIL; 253 } 254 255 unit_ucm_array[unit].stack_array[ptp_id].table[clock_num] = ucm_default; 256 257 return rv; 258 } 259 260 /* 261 * Function: 262 * bcm_common_ptp_static_unicast_master_table_size_get 263 * Purpose: 264 * Get maximum number of unicast master table entries of a PTP clock. 265 * Parameters: 266 * unit - (IN) Unit number. 267 * ptp_id - (IN) PTP stack ID. 268 * clock_num - (IN) PTP clock number. 269 * port_num - (IN) PTP clock port number. 270 * max_table_entries - (OUT) Maximum number of unicast master table entries. 271 * Returns: 272 * BCM_E_XXX 273 * Notes: 274 * Ref. IEEE Std. 1588-2008, Chapter 17.5.4. 275 */ 276 int 277 bcm_common_ptp_static_unicast_master_table_size_get( 278 int unit, 279 bcm_ptp_stack_id_t ptp_id, 280 int clock_num, 281 int port_num, 282 int *max_table_entries) 283 { 284 int rv = BCM_E_UNAVAIL; 285 286 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 287 (uint32)port_num))) { 288 return rv; 289 } 290 291 *max_table_entries = PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES; 292 293 return rv; 294 } 295 296 /* 297 * Function: 298 * bcm_common_ptp_static_unicast_master_add 299 * Purpose: 300 * Add an entry to the unicast master table of a PTP clock. 301 * Parameters: 302 * unit - (IN) Unit number. 303 * ptp_id - (IN) PTP stack ID. 304 * clock_num - (IN) PTP clock number. 305 * port_num - (IN) PTP clock port number. 306 * master_info - (IN) Unicast master address and granted message intervals. 307 * Returns: 308 * BCM_E_XXX 309 * Notes: 310 */ 311 int 312 bcm_common_ptp_static_unicast_master_add( 313 int unit, 314 bcm_ptp_stack_id_t ptp_id, 315 int clock_num, 316 int port_num, 317 bcm_ptp_clock_unicast_master_t *master_info) 318 { 319 int rv = BCM_E_UNAVAIL; 320 321 _bcm_ptp_unicast_master_table_t *unicast_master_table; 322 int i = 0; 323 324 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 325 (uint32)port_num))) { 326 return rv; 327 } 328 329 if (master_info == NULL) { 330 return BCM_E_PARAM; 331 } 332 333 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 334 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 335 PTP_MEMSTATE_INITIALIZED)) { 336 return BCM_E_UNAVAIL; 337 } 338 339 unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id] 340 .table[clock_num]; 341 342 i = 0; 343 while (i < unicast_master_table->num_entries) { 344 if (_bcm_ptp_peer_address_compare(&master_info->address, 345 &unicast_master_table->entry[i].address)) { 346 break; 347 } 348 ++i; 349 } 350 351 if (i >= PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES) { 352 return BCM_E_FULL; 353 } 354 355 if (i == unicast_master_table->num_entries) { 356 /* New entry. */ 357 ++unicast_master_table->num_entries; 358 } 359 360 unicast_master_table->entry[i].address = 361 master_info->address; 362 unicast_master_table->entry[i].log_sync_interval = 363 master_info->log_sync_interval; 364 unicast_master_table->entry[i].log_min_delay_request_interval = 365 master_info->log_min_delay_request_interval; 366 367 /* Update PTP stack firmware unicast master table. */ 368 rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num); 369 370 return rv; 371 } 372 373 /* 374 * Function: 375 * bcm_common_ptp_static_unicast_master_list 376 * Purpose: 377 * List the unicast master table of a PTP clock. 378 * Parameters: 379 * unit - (IN) Unit number. 380 * ptp_id - (IN) PTP stack ID. 381 * clock_num - (IN) PTP clock number. 382 * port_num - (IN) PTP clock port number. 383 * num_masters - (OUT) Number of unicast master table entries. 384 * master_info - (OUT) Unicast master table. 385 * Returns: 386 * BCM_E_XXX 387 * Notes: 388 */ 389 int 390 bcm_common_ptp_static_unicast_master_list( 391 int unit, 392 bcm_ptp_stack_id_t ptp_id, 393 int clock_num, 394 int port_num, 395 int max_num_masters, 396 int *num_masters, 397 bcm_ptp_clock_peer_address_t *master_info) 398 { 399 int rv = BCM_E_NONE; 400 401 _bcm_ptp_unicast_master_table_t *unicast_master_table; 402 int i = 0; 403 404 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 405 (uint32)port_num))) { 406 return rv; 407 } 408 409 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 410 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 411 PTP_MEMSTATE_INITIALIZED)) { 412 return BCM_E_UNAVAIL; 413 } 414 415 unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id] 416 .table[clock_num]; 417 418 if (unicast_master_table->num_entries == 0) { 419 *num_masters = 0; 420 return rv; 421 } 422 423 424 if (unicast_master_table->num_entries > max_num_masters) { 425 *num_masters = 0; 426 return BCM_E_RESOURCE; 427 } 428 429 /* 430 * Get PTP clock unicast master table. 431 * NOTICE: Returns a local, SDK copy of unicast master table 432 * rather than query PTP stack firmware. 433 */ 434 *num_masters = unicast_master_table->num_entries; 435 436 for (i = 0; i < (*num_masters); ++i) { 437 master_info[i] = unicast_master_table->entry[i].address; 438 } 439 440 return rv; 441 } 442 443 /* 444 * Function: 445 * bcm_common_ptp_static_unicast_master_remove 446 * Purpose: 447 * Remove an entry from the unicast master table of a PTP clock. 448 * Parameters: 449 * unit - (IN) Unit number. 450 * ptp_id - (IN) PTP stack ID. 451 * clock_num - (IN) PTP clock number. 452 * port_num - (IN) PTP clock port number. 453 * master_info - (IN) Unicast master address. 454 * Returns: 455 * BCM_E_XXX 456 * Notes: 457 */ 458 int 459 bcm_common_ptp_static_unicast_master_remove( 460 int unit, 461 bcm_ptp_stack_id_t ptp_id, 462 int clock_num, 463 int port_num, 464 bcm_ptp_clock_peer_address_t *master_info) 465 { 466 int rv = BCM_E_UNAVAIL; 467 468 _bcm_ptp_unicast_master_table_t *unicast_master_table; 469 int i = 0; 470 int k = 0; 471 472 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 473 (uint32)port_num))) { 474 return rv; 475 } 476 477 if (master_info == NULL) { 478 return BCM_E_PARAM; 479 } 480 481 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 482 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 483 PTP_MEMSTATE_INITIALIZED)) { 484 return BCM_E_UNAVAIL; 485 } 486 487 unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id] 488 .table[clock_num]; 489 490 if (unicast_master_table->num_entries == 0) { 491 return BCM_E_EMPTY; 492 } 493 494 i = 0; 495 k = 0; 496 while (i < unicast_master_table->num_entries) { 497 if (_bcm_ptp_peer_address_compare(master_info, 498 &unicast_master_table->entry[i].address)) { 499 /* 500 * Remove this entry by moving last entry into this slot, and 501 * decrementing number of entries. 502 */ 503 unicast_master_table->entry[i] = 504 unicast_master_table->entry[--unicast_master_table->num_entries]; 505 506 /* Reset unused entry. */ 507 unicast_master_table->entry[unicast_master_table->num_entries] = 508 ucm_entry_default; 509 510 ++k; 511 } 512 else 513 { 514 ++i; 515 } 516 } 517 518 if (k <= 0) { 519 /* No matching peer address(es) in unicast master table. */ 520 return BCM_E_NOT_FOUND; 521 } 522 523 /* Update PTP stack firmware unicast master table. */ 524 rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num); 525 526 return rv; 527 } 528 529 /* 530 * Function: 531 * bcm_common_ptp_static_unicast_master_table_clear 532 * Purpose: 533 * Clear (i.e. remove all entries from) the unicast master table 534 * of a PTP clock. 535 * Parameters: 536 * unit - (IN) Unit number. 537 * ptp_id - (IN) PTP stack ID. 538 * clock_num - (IN) PTP clock number. 539 * port_num - (IN) PTP clock port number. 540 * Returns: 541 * BCM_E_XXX 542 * Notes: 543 */ 544 int 545 bcm_common_ptp_static_unicast_master_table_clear( 546 int unit, 547 bcm_ptp_stack_id_t ptp_id, 548 int clock_num, 549 int port_num) 550 { 551 int rv; 552 553 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 554 (uint32)port_num))) { 555 return rv; 556 } 557 558 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 559 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 560 PTP_MEMSTATE_INITIALIZED)) { 561 return BCM_E_UNAVAIL; 562 } 563 564 unit_ucm_array[unit].stack_array[ptp_id].table[clock_num] = ucm_default; 565 566 /* Update PTP stack firmware unicast master table. */ 567 rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num); 568 569 return rv; 570 } 571 572 /* 573 * Function: 574 * _bcm_ptp_unicast_master_table_set 575 * Purpose: 576 * Set unicast master table of a PTP clock. 577 * Parameters: 578 * unit - (IN) Unit number. 579 * ptp_id - (IN) PTP stack ID. 580 * clock_num - (IN) PTP clock number. 581 * Returns: 582 * BCM_E_XXX 583 * Notes: 584 */ 585 static int 586 _bcm_ptp_unicast_master_table_set( 587 int unit, 588 bcm_ptp_stack_id_t ptp_id, 589 int clock_num) 590 { 591 int rv = BCM_E_UNAVAIL; 592 593 uint8 payload[PTP_MGMTMSG_PAYLOAD_MAX_UNICAST_MASTER_TABLE_SIZE_OCTETS] = {0}; 594 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 595 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 596 597 _bcm_ptp_unicast_master_table_t *unicast_master_table; 598 bcm_ptp_port_identity_t portid; 599 int i = 0; 600 int k = 0; 601 int el = 0; 602 int raw_l2_length = 0; 603 604 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 605 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 606 return rv; 607 } 608 609 if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 610 (unit_ucm_array[unit].stack_array[ptp_id].memstate != 611 PTP_MEMSTATE_INITIALIZED)) { 612 return BCM_E_UNAVAIL; 613 } 614 615 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 616 clock_num, 1, &portid))) { 617 return rv; 618 } 619 620 unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id] 621 .table[clock_num]; 622 623 /* 624 * Make payload. 625 * Octet 0...1 : Number of unicast master table entries. 626 * Octet 3...* : Unicast master table entries. 627 */ 628 i = 0; 629 _bcm_ptp_uint16_write(payload, unicast_master_table->num_entries); 630 i += sizeof(uint16); 631 632 for (el = 0; el < unicast_master_table->num_entries; ++el) { 633 _bcm_ptp_uint16_write(&payload[i], 634 unicast_master_table->entry[el].address.addr_type); 635 i += sizeof(uint16); 636 637 switch (unicast_master_table->entry[el].address.addr_type) { 638 case bcmPTPUDPIPv4: 639 /* Ethernet/UDP/IPv4 address type. */ 640 _bcm_ptp_uint16_write(&payload[i], PTP_IPV4_ADDR_SIZE_BYTES); 641 i += sizeof(uint16); 642 _bcm_ptp_uint32_write(&payload[i], 643 unicast_master_table->entry[el].address.ipv4_addr); 644 i += sizeof(uint32); 645 646 break; 647 648 case bcmPTPUDPIPv6: 649 /* Ethernet/UDP/IPv6 address type. */ 650 _bcm_ptp_uint16_write(&payload[i], PTP_IPV6_ADDR_SIZE_BYTES); 651 i += sizeof(uint16); 652 653 for (k = 0; k < PTP_IPV6_ADDR_SIZE_BYTES; ++k) { 654 payload[i++] = unicast_master_table->entry[el] 655 .address.ipv6_addr[k]; 656 } 657 658 break; 659 660 default: 661 _bcm_ptp_uint16_write(&payload[i], 0); 662 i += sizeof(uint16); 663 } 664 665 payload[i++] = (uint8)unicast_master_table->entry[el] 666 .log_sync_interval; 667 payload[i++] = (uint8)unicast_master_table->entry[el] 668 .log_min_delay_request_interval; 669 670 raw_l2_length = unicast_master_table->entry[el] 671 .address.raw_l2_header_length; 672 _bcm_ptp_uint16_write(&payload[i], raw_l2_length); 673 i += sizeof(uint16); 674 675 for (k = 0; k < raw_l2_length; ++k) { 676 payload[i++] = unicast_master_table->entry[el] 677 .address.raw_l2_header[k]; 678 } 679 } 680 681 rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid, 682 PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_UNICAST_MASTER_TABLE, 683 payload, i, resp, &resp_len); 684 685 return rv; 686 } 687 #endif /* defined(INCLUDE_PTP)*/