management.c (118921B)
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: management.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * _bcm_ptp_management_init 13 * _bcm_ptp_management_detach 14 * _bcm_ptp_management_stack_create 15 * _bcm_ptp_external_transport_init 16 * _bcm_ptp_external_transport_terminate 17 * _bcm_ptp_internal_transport_init 18 * _bcm_ptp_internal_transport_terminate 19 * _bcm_ptp_management_clock_create 20 * _bcm_ptp_management_message_send 21 * _bcm_ptp_tunnel_message_to_top 22 * _bcm_ptp_tunnel_message_to_world 23 * _bcm_ptp_external_tx 24 * _bcm_ptp_external_tx_completion 25 * _bcm_ptp_internal_tx 26 * _bcm_ptp_internal_tx_completion 27 * _bcm_ptp_unicast_slave_subscribe 28 * _bcm_ptp_management_domain_get 29 * _bcm_ptp_management_domain_set 30 * _bcm_ptp_management_message_create 31 * _bcm_ptp_management_message_macaddr_set 32 * _bcm_ptp_management_message_vlantag_set 33 * _bcm_ptp_management_message_ipaddr_set 34 * _bcm_ptp_management_message_ipv4hdr_checksum_set 35 * _bcm_ptp_management_message_port_set 36 * _bcm_ptp_management_message_domain_set 37 * _bcm_ptp_management_rfc791_checksum 38 * _bcm_ptp_rfc791_checksum_add_word 39 * _bcm_ptp_construct_udp_packet 40 * _bcm_ptp_construct_signaling_msg 41 * _bcm_ptp_construct_signaling_request_tlv 42 * _bcm_ptp_construct_signaling_cancel_tlv 43 * _bcm_ptp_construct_signaling_grant_tlv 44 * _bcm_ptp_construct_signaling_ack_cancel_tlv 45 * _bcm_ptp_signaling_message_append_tlv 46 */ 47 48 #if defined(INCLUDE_PTP) 49 50 #ifdef BCM_HIDE_DISPATCHABLE 51 #undef BCM_HIDE_DISPATCHABLE 52 #endif 53 54 #include <shared/bsl.h> 55 56 #include <soc/defs.h> 57 #include <soc/drv.h> 58 #include <shared/bsl.h> 59 #include <bcm/pkt.h> 60 #include <bcm/tx.h> 61 #include <bcm/rx.h> 62 63 #include <bcm/ptp.h> 64 #include <bcm_int/common/ptp.h> 65 #include <bcm_int/ptp_common.h> 66 #include <bcm/error.h> 67 68 #include <bcm_int/common/rx.h> 69 #include <bcm_int/common/tx.h> 70 71 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 72 #include <soc/uc_msg.h> 73 #endif 74 75 /* Parameters and constants. */ 76 #define PTP_MGMT_RESPONSE_TIMEOUT_US (10000000) /* 1 sec */ 77 #define PTP_TUNNEL_MESSAGE_TIMEOUT_US (100000) /* 100 msec */ 78 #define PTP_TIMESTAMP_MESSAGE_TIMEOUT_US (100000) /* 100 msec */ 79 80 #define PTP_MGMT_RESP_ACTION_OFFSET (46) 81 #define PTP_MGMT_RESP_TLV_TYPE_OFFSET (48) 82 #define PTP_MGMT_RESP_TLV_LEN_OFFSET (50) 83 #define PTP_MGMT_RESP_TLV_VAL_OFFSET (52) 84 #define PTP_MGMT_RESP_PAYLOAD_OFFSET (54) 85 86 #define CLOCK_DATA(unit, ptp_id, clock_num) (unit_mgmt_array[unit].stack_array[ptp_id].clock_data[clock_num]) 87 #define STACK_DATA(unit, ptp_id) (unit_mgmt_array[unit].stack_array[ptp_id]) 88 #define UNIT_DATA(unit) (unit_mgmt_array[unit]) 89 90 static const uint8 l2hdr_default[] = 91 { 92 /* Destination MAC address (zeros placeholder). */ 93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 /* Source MAC address (zeros placeholder). */ 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 }; 97 98 static const uint8 vlanhdr_default[] = 99 { 100 /* Tag protocol identifier (TPID). */ 101 0x81, 0x00, 102 /* 103 * Priority code point (PCP), 104 * canonical form indicator (CFI), 105 * VLAN identifier (VID) . 106 */ 107 0xe0, 0x00, 108 }; 109 110 static const uint8 ethhdr_default[] = 111 { 112 /* Ethertype (0x0800 = IPv4, 0x86dd = IPv6). */ 113 0x08, 0x00, 114 }; 115 116 static const uint8 ipv4hdr_default[] = 117 { 118 /* Version (IPv4), header length. */ 119 0x45, 120 /* 121 * Differential service code point (DSCP), 122 * Explicit congestion notification (ECN). 123 */ 124 0x00, 125 /* 126 * Total length (octets). 127 * NOTICE: Placeholder value. 128 */ 129 0x00, 0x52, 130 /* Identification. */ 131 0x00, 0x00, 132 /* Flags (Do not fragment), Fragment offset. */ 133 0x40, 0x00, 134 /* Time to live (TTL). */ 135 0x01, 136 /* Protocol (UDP). */ 137 0x11, 138 /* Header checksum (zeros placeholder). */ 139 0x00, 0x00, 140 /* Source IPv4 address (zeros placeholder). */ 141 0x00, 0x00, 0x00, 0x00, 142 /* Destination IPv4 address (zeros placeholder). */ 143 0x00, 0x00, 0x00, 0x00, 144 }; 145 146 static const uint8 udphdr_default[] = 147 { 148 /* Source port. */ 149 0x01, 0x40, 150 /* Destination port. */ 151 0x01, 0x40, 152 /* 153 * Length (octets). 154 * NOTICE: Placeholder value. 155 */ 156 0x00, 0x00, 157 /* 158 * Checksum (optional). 159 * NOTICE: 0x0000 indicates checksum skipped. 160 */ 161 0x00, 0x00, 162 }; 163 164 static const uint8 udphdr_tunnel[] = 165 { 166 /* Source port. */ 167 0x01, 0x41, 168 /* Destination port. */ 169 0x01, 0x41, 170 /* Length (zeros placeholder). */ 171 0x00, 0x00, 172 /* Checksum (optional). */ 173 0x00, 0x00, 174 }; 175 176 177 static const uint8 ptphdr_mgmt[] = 178 { 179 /* Message ID (management message) */ 180 bcmPTP_MESSAGE_TYPE_MANAGEMENT, 181 /* PTP version. */ 182 0x02, 183 /* PTP message length, TLV "V" part only */ 184 0x00, 0x00, 185 /* PTP domain (zero default) */ 186 0x00, 187 /* Reserved */ 188 0x00, 189 /* PTP flags (Unicast = true) */ 190 0x04, 0x00, 191 /* Correction field */ 192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 193 /* Reserved */ 194 0x00, 0x00, 0x00, 0x00, 195 /* Source Clock ID */ 196 0x00, 0x10, 0x94, 0xff, 0xfe, 0x00, 0x00, 0x04, 197 /* Source Port Number */ 198 0x00, 0x01, 199 /* Sequence ID */ 200 0x00, 0x01, 201 /* Control field (management) */ 202 0x04, 203 /* Log inter-message interval */ 204 0x7f, 205 }; 206 207 208 static const uint8 mgmthdr_mgmt[]= 209 { 210 /* Target clock ID. */ 211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 212 /* Target port ID. */ 213 0xff, 0xff, 214 /* Starting boundary hops. */ 215 0x01, 216 /* Boundary hops. */ 217 0x01, 218 /* Action field. */ 219 0x00, 220 /* Reserved. */ 221 0x00, 222 }; 223 224 225 static const uint8 tlvhdr_mgmt[]= 226 { 227 /* TLV type (0x0001 = Management message). */ 228 0x00, 0x01, 229 /* TLV length (octets) (0x0002 = TLV prefix, no payload placeholder) */ 230 0x00, 0x02, 231 /* TLV value prefix (management ID, i.e. command definition) */ 232 0x00, 0x00, 233 }; 234 235 static const uint8 ptphdr_ucsig[] = 236 { 237 /* 238 * Message ID (signaling message). 239 * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.2. 240 */ 241 bcmPTP_MESSAGE_TYPE_SIGNALING, 242 /* PTP version. */ 243 0x02, 244 /* 245 * PTP message length, TLV "V" part only. 246 * NOTICE: Placeholder based on REQUEST_UNICAST_TRANSMISSION TLV. 247 */ 248 0x00, (PTP_UCSIG_REQUEST_TOTAL_SIZE_OCTETS - PTP_SIGHDR_START_IDX), 249 /* PTP domain (zero default). */ 250 0x00, 0x00, 251 /* PTP flags (Unicast= true). */ 252 0x04, 0x00, 253 /* 254 * Correction field. 255 * Ref. IEEE Std. 1588-2008, Chapter 13.3.2.7. 256 */ 257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 258 /* Reserved. */ 259 0x00, 0x00, 0x00, 0x00, 260 /* Source port ID. */ 261 0x00, 0x10, 0x94, 0xff, 0xfe, 0x00, 0x00, 0x0d, 262 0x00, 0x01, 263 /* Sequence ID. */ 264 0x00, 0x02, 265 /* 266 * Control field (all others). 267 * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.10. 268 */ 269 0x05, 270 /* 271 * Log inter-message interval. 272 * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.11. 273 */ 274 0x7f, 275 }; 276 277 static const uint8 tgtport_ucsig[] = 278 { 279 /* Signaling message target clock identity. */ 280 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 281 /* Signaling message target port. */ 282 0xff, 0xff, 283 }; 284 285 static const uint8 unicast_request_tlv_ucsig[] = 286 { 287 /* 288 * TLV type. (0x0004 = REQUEST_UNICAST_TRANSMISSION placeholder). 289 * Ref. IEEE Std. 1588-2008, Sect. 14.1.1. 290 */ 291 0x00, 0x04, 292 /* 293 * TLV length (octets). 294 * NOTICE: Placeholder based on REQUEST_UNICAST_TRANSMISSION TLV. 295 */ 296 0x00, (PTP_UCSIG_REQUEST_TLV_SIZE_OCTETS - 4), 297 /* 298 * TLV value (data). Message type (0x0b = Announce message, placeholder). 299 * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.2. 300 */ 301 bcmPTP_MESSAGE_TYPE_ANNOUNCE, 302 /* Interval. */ 303 0x00, 304 /* Duration. */ 305 0x00, 0x00, 0x00, 0x14, 306 /* Address type. */ 307 bcmPTPUDPIPv4, 308 /* Peer address. */ 309 0x01, 0x02, 0x03, 0x04, 310 0x00, 0x00, 0x00, 0x00, 311 0x00, 0x00, 0x00, 0x00, 312 0x00, 0x00, 0x00, 0x00, 313 /* L2 header length (zeros placeholder). */ 314 0x00, 315 /* L2 header (zeros placeholder). */ 316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 }; 321 322 #define BCM_GPS_NUM_TIMESTAMPS_PER_BUFFER 110 /* Although only 100 timestamps are expected, 323 * max is set to 110 in order to account for 324 * extremely large frequency offsets*/ 325 326 uint64 gps_diff_ts[BCM_GPS_NUM_TIMESTAMPS_PER_BUFFER] = {0}; 327 bcm_ptp_port_identity_t g_gps_port_id = {{1,2,3,4,5,6,7,8},9}; 328 bcm_ptp_clock_port_address_t g_gps_port_address = {bcmPTPIEEE8023,{0xFE}}; 329 bcm_ptp_port_identity_t g_ptp_best_master_portId = {{0,0,0,0,0,0,0,0},0}; 330 331 /* Clock PTP management data. */ 332 typedef struct _bcm_ptp_clock_mgmt_data_s { 333 uint8 domain; /* PTP domain. */ 334 } _bcm_ptp_clock_mgmt_data_t; 335 336 /* Stack PTP management data array. */ 337 typedef struct _bcm_ptp_stack_mgmt_array_s { 338 _bcm_ptp_memstate_t memstate; 339 340 bcm_mac_t src_mac; 341 bcm_mac_t dest_mac; 342 343 bcm_ip_t src_ip; 344 bcm_ip_t dest_ip; 345 346 uint16 vlan; 347 uint8 prio; 348 349 _bcm_ptp_sem_t outgoing_available; /* any outgoing message (management, signaling, tunneled) to TOP */ 350 351 bcm_pkt_t *mgmt_packet; 352 bcm_pkt_t *tunnel_packet; 353 bcm_pkt_t *ucsig_packet; 354 355 _bcm_ptp_clock_mgmt_data_t *clock_data; 356 } _bcm_ptp_stack_mgmt_array_t; 357 358 /* Unit PTP management data array(s). */ 359 typedef struct _bcm_ptp_unit_mgmt_array_s { 360 _bcm_ptp_memstate_t memstate; 361 _bcm_ptp_stack_mgmt_array_t *stack_array; 362 } _bcm_ptp_unit_mgmt_array_t; 363 364 static const _bcm_ptp_clock_mgmt_data_t mgmt_default = { 0 }; 365 366 static _bcm_ptp_unit_mgmt_array_t unit_mgmt_array[BCM_MAX_NUM_UNITS]; 367 368 static int _bcm_ptp_management_message_create( 369 uint8 *message); 370 371 /* static int _bcm_ptp_management_message_make( */ 372 /* uint8 *message, */ 373 /* uint8 action, */ 374 /* uint16 cmd, */ 375 /* uint8 *payload, */ 376 /* int payload_len); */ 377 378 /* static int _bcm_ptp_management_message_header_metadata_set( */ 379 /* uint8 *message); */ 380 381 static int _bcm_ptp_management_message_macaddr_set( 382 uint8 *message, 383 bcm_mac_t *src_mac, 384 bcm_mac_t *dest_mac); 385 386 static int _bcm_ptp_management_message_vlantag_set( 387 uint8 *message, 388 uint16 vlan_tag, 389 uint8 prio); 390 391 static int _bcm_ptp_management_message_ipaddr_set( 392 uint8 *message, 393 bcm_ip_t src_ip, 394 bcm_ip_t dest_ip); 395 396 static int _bcm_ptp_management_message_ipv4hdr_checksum_set( 397 uint8 *message); 398 399 static int _bcm_ptp_management_message_port_set( 400 uint8 *message, 401 uint16 src_port, 402 uint16 dest_port); 403 404 /* static int _bcm_ptp_management_message_target_set( */ 405 /* uint8 *message, */ 406 /* const bcm_ptp_clock_identity_t clock_identity, */ 407 /* uint16 port_num); */ 408 409 /* static int _bcm_ptp_management_message_length_get( */ 410 /* uint8 *message); */ 411 412 #if 0 /* Unused. */ 413 static int _bcm_ptp_management_message_domain_get( 414 uint8 *message, 415 uint8 *domain); 416 #endif /* Unused. */ 417 418 static uint16 _bcm_ptp_management_rfc791_checksum( 419 uint8* packet, 420 int packet_len); 421 422 static uint16 _bcm_ptp_rfc791_checksum_add_word( 423 uint16 prev_checksum, 424 uint16 add_word); 425 426 static sal_usecs_t send_pending_tunneled( 427 void **arg_unit, 428 void **arg_ptp_id, 429 void **unused1, 430 void **unused2); 431 432 static int _bcm_ptp_tunnel_queue_add( 433 int unit, 434 bcm_ptp_stack_id_t ptp_id, 435 int clock_idx, 436 int tunnel_type, 437 unsigned hdr_len, 438 uint8 *hdr, 439 unsigned data_len, 440 uint8 *data); 441 442 static int _bcm_ptp_tunnel_message( 443 int unit, 444 bcm_ptp_stack_id_t ptp_id, 445 int clock_index, 446 int tunnel_type, 447 unsigned hdr_len, 448 uint8 *hdr, 449 unsigned payload_len, 450 uint8 *payload); 451 452 static sal_usecs_t send_pending_timestamp( 453 void **arg_unit, 454 void **arg_ptp_id, 455 void **unused1, 456 void **unused2); 457 458 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 459 bcm_ptp_mbox_tsevent_stats_t mbox_tsevent_stats; 460 461 void _bcm_ptp_dump_mbox_tsevent_stats() { 462 bsl_printf("\n\t Events Queued : %u", mbox_tsevent_stats.event_queued); 463 bsl_printf("\n\t Events DeQueued : %u", mbox_tsevent_stats.event_dequeued); 464 bsl_printf("\n\t Event DLTS dequeued : %u", mbox_tsevent_stats.event_dl_ts); 465 bsl_printf("\n\t Event DLTS handled : %u", mbox_tsevent_stats.event_dl_ts_handled); 466 bsl_printf("\n\t Event DLTS above threshold : %u", mbox_tsevent_stats.event_dl_ts_above_thres); 467 bsl_printf("\n\t Event ULTS dequeued : %u", mbox_tsevent_stats.event_ul_ts); 468 bsl_printf("\n\t Event ULTS handled : %u", mbox_tsevent_stats.event_ul_ts_handled); 469 bsl_printf("\n\t Event ULTS above threshold : %u", mbox_tsevent_stats.event_ul_ts_above_thres); 470 bsl_printf("\n\t Event Master Add : %u", mbox_tsevent_stats.event_master_add); 471 bsl_printf("\n\t Event Master Remove : %u", mbox_tsevent_stats.event_master_remove); 472 bsl_printf("\n\t Event Master Change : %u", mbox_tsevent_stats.event_master_change); 473 bsl_printf("\n\t Event Unknown : %u", mbox_tsevent_stats.event_unknown); 474 bsl_printf("\n\t Error QueueAdd : %u", mbox_tsevent_stats.error_queue_add); 475 bsl_printf("\n\t TS RPC livecount : %u\n", mbox_tsevent_stats.ts_rpc_livecount); 476 } 477 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 478 479 /* 480 * Function: 481 * _bcm_ptp_management_init 482 * Purpose: 483 * Initialize the PTP management framework of a unit. 484 * Parameters: 485 * unit - (IN) Unit number. 486 * Returns: 487 * BCM_E_XXX 488 * Notes: 489 */ 490 int 491 _bcm_ptp_management_init( 492 int unit) 493 { 494 int rv = BCM_E_UNAVAIL; 495 496 _bcm_ptp_stack_mgmt_array_t *stack_p; 497 498 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 499 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 500 return rv; 501 } 502 503 504 if (NULL == unit_mgmt_array[unit].stack_array) { 505 stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT* 506 sizeof(_bcm_ptp_stack_mgmt_array_t),"Unit MGMT arrays"); 507 } else { 508 stack_p = unit_mgmt_array[unit].stack_array; 509 } 510 511 if (!stack_p) { 512 unit_mgmt_array[unit].memstate = PTP_MEMSTATE_FAILURE; 513 return BCM_E_MEMORY; 514 } 515 516 unit_mgmt_array[unit].stack_array = stack_p; 517 unit_mgmt_array[unit].memstate = PTP_MEMSTATE_INITIALIZED; 518 519 return rv; 520 } 521 522 /* 523 * Function: 524 * _bcm_ptp_management_detach 525 * Purpose: 526 * Shut down the PTP management framework of a unit. 527 * Parameters: 528 * unit - (IN) Unit number. 529 * Returns: 530 * BCM_E_XXX 531 * Notes: 532 */ 533 int 534 _bcm_ptp_management_detach( 535 int unit) 536 { 537 if(unit_mgmt_array[unit].stack_array) { 538 unit_mgmt_array[unit].memstate = PTP_MEMSTATE_STARTUP; 539 sal_free(unit_mgmt_array[unit].stack_array); 540 unit_mgmt_array[unit].stack_array = NULL; 541 } 542 return BCM_E_NONE; 543 } 544 545 /* 546 * Function: 547 * _bcm_ptp_management_stack_create 548 * Purpose: 549 * Create the PTP management data array of a PTP stack 550 * Parameters: 551 * unit - (IN) Unit number. 552 * ptp_id - (IN) PTP stack ID. 553 * src_mac - (IN) Source MAC address. 554 * dest_mac - (IN) Destination (PTP stack) MAC address. 555 * src_ip - (IN) Source IPv4 address. 556 * dest_ip - (IN) Destination (PTP stack) IPv4 address. 557 * vlan - (IN) VLAN. 558 * prio - (IN) VLAN priority. 559 * top_bitmap - (IN) ToP bitmap. 560 * Returns: 561 * BCM_E_XXX 562 * Notes: 563 */ 564 int 565 _bcm_ptp_management_stack_create( 566 int unit, 567 bcm_ptp_stack_id_t ptp_id, 568 bcm_mac_t *src_mac, 569 bcm_mac_t *dest_mac, 570 bcm_ip_t src_ip, 571 bcm_ip_t dest_ip, 572 uint16 vlan, 573 uint8 prio, 574 bcm_pbmp_t top_bitmap) 575 { 576 int rv = BCM_E_UNAVAIL; 577 _bcm_ptp_info_t *ptp_info_p; 578 _bcm_ptp_stack_info_t *stack_p; 579 580 _bcm_ptp_clock_mgmt_data_t *data_p; 581 582 SET_PTP_INFO; 583 584 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 585 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 586 return rv; 587 } 588 589 if (unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 590 return BCM_E_UNAVAIL; 591 } 592 593 stack_p = &ptp_info_p->stack_info[ptp_id]; 594 595 596 data_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES * sizeof(_bcm_ptp_clock_mgmt_data_t), "PTP stack MGMT array"); 597 598 if (!data_p) { 599 STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_FAILURE; 600 return BCM_E_MEMORY; 601 } 602 603 STACK_DATA(unit, ptp_id).clock_data = data_p; 604 STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_INITIALIZED; 605 606 STACK_DATA(unit, ptp_id).outgoing_available = _bcm_ptp_sem_create("BCM PTP out", sal_sem_BINARY, 0); 607 rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available); 608 if (BCM_FAILURE(rv)) { 609 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 610 return rv; 611 } 612 613 rv = stack_p->transport_init(unit, ptp_id, src_mac, dest_mac, src_ip, dest_ip, vlan, prio, top_bitmap); 614 615 return rv; 616 } 617 618 /* 619 * Function: 620 * _bcm_ptp_management_stack_destroy 621 * Purpose: 622 * Destroy the PTP management data array of a PTP stack 623 * Parameters: 624 * unit - (IN) Unit number. 625 * ptp_id - (IN) PTP stack ID. 626 * src_mac - (IN) Source MAC address. 627 * dest_mac - (IN) Destination (PTP stack) MAC address. 628 * src_ip - (IN) Source IPv4 address. 629 * dest_ip - (IN) Destination (PTP stack) IPv4 address. 630 * vlan - (IN) VLAN. 631 * prio - (IN) VLAN priority. 632 * top_bitmap - (IN) ToP bitmap. 633 * Returns: 634 * BCM_E_XXX 635 * Notes: 636 */ 637 int 638 _bcm_ptp_management_stack_destroy( 639 int unit, 640 bcm_ptp_stack_id_t ptp_id) 641 { 642 int rv = BCM_E_UNAVAIL; 643 int retry_cnt = 0; 644 _bcm_ptp_info_t *ptp_info_p; 645 _bcm_ptp_stack_info_t *stack_p; 646 647 SET_PTP_INFO; 648 649 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 650 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 651 return rv; 652 } 653 654 if (unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 655 return BCM_E_UNAVAIL; 656 } 657 658 stack_p = &ptp_info_p->stack_info[ptp_id]; 659 660 if (STACK_DATA(unit, ptp_id).memstate == PTP_MEMSTATE_INITIALIZED) { 661 STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_STARTUP; 662 663 while (retry_cnt++ < 5) { 664 if (BCM_FAILURE(rv = _bcm_ptp_sem_take( 665 STACK_DATA(unit, ptp_id).outgoing_available, 666 PTP_MGMT_RESPONSE_TIMEOUT_US))) { 667 PTP_ERROR_FUNC("_bcm_ptp_sem_take() in stack destroy"); 668 } else { 669 break; 670 } 671 } 672 673 rv = stack_p->transport_terminate(unit, ptp_id); 674 675 _bcm_ptp_sem_destroy(STACK_DATA(unit, ptp_id).outgoing_available); 676 STACK_DATA(unit, ptp_id).outgoing_available = 0; 677 678 sal_free(STACK_DATA(unit, ptp_id).clock_data); 679 STACK_DATA(unit, ptp_id).clock_data = 0; 680 } 681 682 return rv; 683 } 684 685 /* 686 * Function: 687 * _bcm_ptp_external_transport_init 688 * Purpose: 689 * Initialize message transport to an external ToP 690 * Parameters: 691 * unit - (IN) Unit number. 692 * ptp_id - (IN) PTP stack ID. 693 * src_mac - (IN) Source MAC address. 694 * dest_mac - (IN) Destination (PTP stack) MAC address. 695 * src_ip - (IN) Source IPv4 address. 696 * dest_ip - (IN) Destination (PTP stack) IPv4 address. 697 * vlan - (IN) VLAN. 698 * prio - (IN) VLAN priority. 699 * top_bitmap - (IN) ToP bitmap. 700 * Returns: 701 * BCM_E_XXX 702 * Notes: 703 */ 704 int _bcm_ptp_external_transport_init( 705 int unit, 706 bcm_ptp_stack_id_t ptp_id, 707 bcm_mac_t *src_mac, 708 bcm_mac_t *dest_mac, 709 bcm_ip_t src_ip, 710 bcm_ip_t dest_ip, 711 uint16 vlan, 712 uint8 prio, 713 bcm_pbmp_t top_bitmap) 714 { 715 bcm_pkt_t *mgmt_packet; 716 bcm_pkt_t *tunnel_packet; 717 bcm_pkt_t *ucsig_packet; 718 int i = 0; 719 int rv = BCM_E_UNAVAIL; 720 721 sal_memcpy(STACK_DATA(unit, ptp_id).src_mac, src_mac, sizeof(bcm_mac_t)); 722 723 sal_memcpy(STACK_DATA(unit, ptp_id).dest_mac, dest_mac, sizeof(bcm_mac_t)); 724 725 STACK_DATA(unit, ptp_id).src_ip = src_ip; 726 STACK_DATA(unit, ptp_id).dest_ip = dest_ip; 727 728 STACK_DATA(unit, ptp_id).vlan = vlan; 729 STACK_DATA(unit, ptp_id).prio = prio; 730 731 rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).mgmt_packet); 732 if (BCM_FAILURE(rv)) { 733 return rv; 734 } 735 736 rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).tunnel_packet); 737 if (BCM_FAILURE(rv)) { 738 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet); 739 return rv; 740 } 741 742 rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).ucsig_packet); 743 if (BCM_FAILURE(rv)) { 744 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet); 745 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).tunnel_packet); 746 return rv; 747 } 748 749 mgmt_packet = STACK_DATA(unit, ptp_id).mgmt_packet; 750 tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet; 751 ucsig_packet = STACK_DATA(unit, ptp_id).ucsig_packet; 752 753 BCM_PBMP_ASSIGN(mgmt_packet->tx_pbmp, top_bitmap); 754 BCM_PBMP_ASSIGN(tunnel_packet->tx_pbmp, top_bitmap); 755 BCM_PBMP_ASSIGN(ucsig_packet->tx_pbmp, top_bitmap); 756 757 _bcm_ptp_management_message_create(BCM_PKT_IEEE(mgmt_packet)); 758 _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(mgmt_packet), 759 src_mac, dest_mac); 760 _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(mgmt_packet), 761 src_ip, dest_ip); 762 _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(mgmt_packet), 763 vlan, prio); 764 765 /* Make template (default) tunnel message packet. */ 766 i = 0; 767 sal_memcpy(BCM_PKT_IEEE(tunnel_packet), l2hdr_default, 768 sizeof(l2hdr_default)); 769 i += sizeof(l2hdr_default); 770 771 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, vlanhdr_default, 772 sizeof(vlanhdr_default)); 773 i += sizeof(vlanhdr_default); 774 775 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, ethhdr_default, 776 sizeof(ethhdr_default)); 777 i += sizeof(ethhdr_default); 778 779 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, ipv4hdr_default, 780 sizeof(ipv4hdr_default)); 781 i += sizeof(ipv4hdr_default); 782 783 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, udphdr_tunnel, 784 sizeof(udphdr_tunnel)); 785 786 _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(tunnel_packet), 787 src_mac, dest_mac); 788 _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(tunnel_packet), 789 src_ip, dest_ip); 790 _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(tunnel_packet), 791 vlan, prio); 792 793 /* Make template (default) unicast transmission signaling packet. */ 794 i = 0; 795 sal_memcpy(BCM_PKT_IEEE(ucsig_packet), l2hdr_default, 796 sizeof(l2hdr_default)); 797 i += sizeof(l2hdr_default); 798 799 sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, vlanhdr_default, 800 sizeof(vlanhdr_default)); 801 i += PTP_VLANHDR_SIZE_OCTETS; 802 803 sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, ethhdr_default, 804 sizeof(ethhdr_default)); 805 i += sizeof(ethhdr_default); 806 807 sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, ipv4hdr_default, 808 sizeof(ipv4hdr_default)); 809 i += sizeof(ipv4hdr_default); 810 811 sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, udphdr_default, 812 sizeof(udphdr_default)); 813 i += sizeof(udphdr_default); 814 815 _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(ucsig_packet), 816 src_mac, dest_mac); 817 _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(ucsig_packet), 818 src_ip, dest_ip); 819 _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(ucsig_packet), 820 vlan, prio); 821 822 return rv; 823 } 824 825 /* 826 * Function: 827 * _bcm_ptp_external_transport_terminate 828 * Purpose: 829 * Terminate message transport to an external ToP 830 * Parameters: 831 * unit - (IN) Unit number. 832 * ptp_id - (IN) PTP stack ID. 833 * Returns: 834 * BCM_E_XXX 835 * Notes: 836 */ 837 int _bcm_ptp_external_transport_terminate( 838 int unit, 839 bcm_ptp_stack_id_t ptp_id) 840 { 841 842 843 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).ucsig_packet); 844 STACK_DATA(unit, ptp_id).ucsig_packet = 0; 845 846 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).tunnel_packet); 847 STACK_DATA(unit, ptp_id).tunnel_packet = 0; 848 849 bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet); 850 STACK_DATA(unit, ptp_id).mgmt_packet = 0; 851 852 return BCM_E_NONE; 853 } 854 855 /* 856 * Function: 857 * _bcm_ptp_internal_transport_init 858 * Purpose: 859 * Initialize message transport to an internal ToP core 860 * Parameters: 861 * unit - (IN) Unit number. 862 * ptp_id - (IN) PTP stack ID. 863 * src_mac - (IN) Source MAC address. 864 * dest_mac - (IN) Destination (PTP stack) MAC address. 865 * src_ip - (IN) Source IPv4 address. 866 * dest_ip - (IN) Destination (PTP stack) IPv4 address. 867 * vlan - (IN) VLAN. 868 * prio - (IN) VLAN priority. 869 * top_bitmap - (IN) ToP bitmap. 870 * Returns: 871 * BCM_E_XXX 872 * Notes: 873 */ 874 int _bcm_ptp_internal_transport_init( 875 int unit, 876 bcm_ptp_stack_id_t ptp_id, 877 bcm_mac_t *src_mac, 878 bcm_mac_t *dest_mac, 879 bcm_ip_t src_ip, 880 bcm_ip_t dest_ip, 881 uint16 vlan, 882 uint8 prio, 883 bcm_pbmp_t top_bitmap) 884 { 885 return BCM_E_NONE; 886 } 887 888 /* 889 * Function: 890 * _bcm_ptp_internal_transport_terminate 891 * Purpose: 892 * Terminate message transport to an internal ToP core 893 * Parameters: 894 * unit - (IN) Unit number. 895 * ptp_id - (IN) PTP stack ID. 896 * Returns: 897 * BCM_E_XXX 898 * Notes: 899 */ 900 int _bcm_ptp_internal_transport_terminate( 901 int unit, 902 bcm_ptp_stack_id_t ptp_id) 903 { 904 return BCM_E_NONE; 905 } 906 907 /* 908 * Function: 909 * _bcm_ptp_management_clock_create 910 * Purpose: 911 * Create the PTP management data of a PTP clock. 912 * Parameters: 913 * unit - (IN) Unit number. 914 * ptp_id - (IN) PTP stack ID. 915 * clock_num - (IN) PTP clock number. 916 * Returns: 917 * BCM_E_XXX 918 * Notes: 919 */ 920 int 921 _bcm_ptp_management_clock_create( 922 int unit, 923 bcm_ptp_stack_id_t ptp_id, 924 int clock_num) 925 { 926 int rv = BCM_E_NONE; 927 928 rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT); 929 if (BCM_FAILURE(rv)) { 930 return rv; 931 } 932 933 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 934 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 935 return BCM_E_UNAVAIL; 936 } 937 938 CLOCK_DATA(unit, ptp_id, clock_num) = mgmt_default; 939 940 return rv; 941 } 942 943 944 /* 945 * Function: 946 * _bcm_ptp_management_message_send 947 * Purpose: 948 * Send a PTP management message. 949 * Parameters: 950 * unit - (IN) Unit number. 951 * ptp_id - (IN) PTP stack ID. 952 * clock_num - (IN) PTP clock number. 953 * dest_clock_port - (IN) Destination PTP clock port. 954 * action - (IN) PTP management action (actionField). 955 * cmd - (IN) PTP command (managementId). 956 * payload - (IN) PTP management message payload. 957 * payload_len - (IN) PTP management message payload size (octets). 958 * resp - (IN/OUT) PTP management message response. 959 * resp_len - (OUT) PTP management message response size (octets). 960 * Returns: 961 * BCM_E_XXX 962 * Notes: 963 */ 964 int 965 _bcm_ptp_management_message_send( 966 int unit, 967 bcm_ptp_stack_id_t ptp_id, 968 int clock_num, 969 const bcm_ptp_port_identity_t* dest_clock_port, 970 uint8 action, 971 uint16 cmd, 972 uint8* payload, 973 int payload_len, 974 uint8* resp, 975 int* resp_len) 976 { 977 int rv = BCM_E_UNAVAIL; 978 int rvbody = BCM_E_FAIL; 979 980 uint8 *response_data; 981 int response_len; 982 int response_payload_len; 983 984 uint8 resp_action; 985 986 uint16 tlvtype; 987 uint16 tlvlen; 988 989 int tlv_len = 2 + payload_len; 990 int message_len = 48 + 4 + tlv_len; 991 992 uint8 message[1500]; 993 994 uint16 mgmt_id; 995 996 int max_resp_len = (resp_len) ? *resp_len : 0; 997 998 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 999 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id]; 1000 1001 /* ptp_printf("_bcm_ptp_management_message_send(): ENTER | %s | @ t = %u |\n", */ 1002 /* bcm_errmsg(BCM_E_NONE), (unsigned)sal_time_usecs()); */ 1003 1004 if (resp_len) { 1005 *resp_len = 0; 1006 } 1007 1008 /* Sanity check running system */ 1009 rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT); 1010 if (BCM_FAILURE(rv)) { 1011 return rv; 1012 } 1013 1014 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1015 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 1016 /* Verify initialization */ 1017 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1018 (BSL_META_U(unit, 1019 "PTP send failed: Memory state\n"))); 1020 return BCM_E_UNAVAIL; 1021 } 1022 1023 rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_MGMT_RESPONSE_TIMEOUT_US); 1024 if (BCM_FAILURE(rv)) { 1025 PTP_ERROR_FUNC("_bcm_ptp_sem_take()"); 1026 return rv; 1027 } 1028 1029 /* LOG_CLI((BSL_META_U(unit, 1030 "mgmt_send(len:%d)\n"), payload_len)); */ 1031 /* _bcm_ptp_dump_hex(payload, payload_len, 0); */ 1032 1033 /* Init the mgmt message with presets */ 1034 sal_memset(message, 0, sizeof (message)); 1035 1036 sal_memcpy(message, 1037 ptphdr_mgmt, sizeof(ptphdr_mgmt)); 1038 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS, 1039 mgmthdr_mgmt, sizeof(mgmthdr_mgmt)); 1040 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS, 1041 tlvhdr_mgmt, sizeof(tlvhdr_mgmt)); 1042 1043 /* Make the PTP Packet header */ 1044 _bcm_ptp_uint16_write(message + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, message_len); 1045 1046 message[PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = CLOCK_DATA(unit, ptp_id, clock_num).domain; 1047 1048 /* Make the Management header */ 1049 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS, 1050 (uint8*)dest_clock_port->clock_identity, sizeof(bcm_ptp_clock_identity_t)); 1051 1052 _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + BCM_PTP_CLOCK_EUID_IEEE1588_SIZE, 1053 dest_clock_port->port_number); 1054 1055 message[PTP_PTPHDR_SIZE_OCTETS + sizeof(bcm_ptp_port_identity_t) + 2] = action; 1056 1057 /* Make the TLV header */ 1058 _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + 2, tlv_len); 1059 1060 _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + 2 + 2, cmd); 1061 1062 /* Make the payload */ 1063 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + PTP_TLVHDR_SIZE_OCTETS, 1064 payload, payload_len); 1065 1066 /* LOG_CLI((BSL_META_U(unit, 1067 "mgmt_send_tx(len:%d)\n"), message_len)); */ 1068 /* _bcm_ptp_dump_hex(message, message_len, 0); */ 1069 1070 rv = stack_p->tx(unit, ptp_id, clock_num, PTP_MESSAGE_TO_TOP, 0, 0, message, message_len); 1071 1072 if (rv != BCM_E_NONE) { 1073 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1074 (BSL_META_U(unit, 1075 "PTP send failed: Tx error\n"))); 1076 goto release_mgmt_lock; 1077 } 1078 1079 /* 1080 * Get rx buffer, either from rx callback or from cmicm wait task 1081 * NOTICE: This call will return an rx response buffer that we will need to 1082 * release by notifying the Rx section 1083 */ 1084 rv = _bcm_ptp_rx_response_get(unit, ptp_id, clock_num, PTP_MGMT_RESPONSE_TIMEOUT_US, 1085 &response_data, &response_len); 1086 if (BCM_FAILURE(rv)) { 1087 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1088 (BSL_META_U(unit, 1089 "PTP send failed: No response\n"))); 1090 goto release_mgmt_lock; 1091 } 1092 1093 if (!response_data) { 1094 LOG_ERROR(BSL_LS_BCM_COMMON, 1095 (BSL_META_U(unit, 1096 "Unexpected NULL response\n"))); 1097 goto release_mgmt_lock; 1098 } 1099 1100 rv = BCM_E_FAIL; 1101 resp_action = (response_data[PTP_MGMT_RESP_ACTION_OFFSET] & 0x0f); 1102 1103 if (((action == PTP_MGMTMSG_SET) || (action == PTP_MGMTMSG_GET)) && (resp_action != PTP_MGMTMSG_RESP)) { 1104 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1105 (BSL_META_U(unit, 1106 "PTP send failed: Bad response action\n"))); 1107 goto dispose_of_resp; 1108 } 1109 1110 if ((action == PTP_MGMTMSG_CMD) && (resp_action != PTP_MGMTMSG_ACK) ) { 1111 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1112 (BSL_META_U(unit, 1113 "PTP send failed: Bad cmd response action\n"))); 1114 goto dispose_of_resp; 1115 } 1116 1117 tlvtype = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_TYPE_OFFSET); 1118 1119 if (tlvtype == bcmPTPTlvTypeManagementErrorStatus) { 1120 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1121 (BSL_META_U(unit, 1122 "Error response: 0x%04x\n"), 1123 _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_VAL_OFFSET))); 1124 goto dispose_of_resp; 1125 } 1126 1127 tlvlen = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_LEN_OFFSET); 1128 1129 if (tlvlen + PTP_MGMT_RESP_TLV_VAL_OFFSET > response_len) { 1130 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1131 (BSL_META_U(unit, 1132 "PTP send failed: Bad TLV len\n"))); 1133 goto dispose_of_resp; 1134 } 1135 1136 mgmt_id = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_VAL_OFFSET); 1137 1138 if (mgmt_id != cmd) { 1139 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1140 (BSL_META_U(unit, 1141 "Bad mgmt ID: %04x vs %04x\n"), mgmt_id, cmd)); 1142 goto dispose_of_resp; 1143 } 1144 1145 if (resp && resp_len) { 1146 response_payload_len = tlvlen - 2; 1147 if (response_payload_len > max_resp_len) { 1148 response_payload_len = max_resp_len; 1149 } 1150 1151 *resp_len = response_payload_len; 1152 sal_memcpy(resp, response_data + PTP_MGMT_RESP_PAYLOAD_OFFSET, response_payload_len); 1153 } 1154 1155 rv = BCM_E_NONE; 1156 1157 dispose_of_resp: 1158 stack_p->rx_free(unit, ptp_id, response_data); 1159 1160 release_mgmt_lock: 1161 rvbody = rv; 1162 if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) { 1163 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 1164 } 1165 1166 /* ptp_printf("_bcm_ptp_management_message_send(): EXIT | %s | @ t = %u |\n", */ 1167 /* bcm_errmsg(rvbody), (unsigned)sal_time_usecs()); */ 1168 1169 return rvbody ? rvbody : rv; 1170 } 1171 1172 1173 /* 1174 * Function: 1175 * _bcm_ptp_tunnel_message_to_top 1176 * Purpose: 1177 * Tunnel a message to ToP processor. 1178 * Parameters: 1179 * unit - (IN) Unit number. 1180 * ptp_id - (IN) PTP stack ID. 1181 * clock_index - (IN) PTP clock index 1182 * port_index - (IN) PTP port index 1183 * payload_len - (IN) Tunnel message payload size (octets). 1184 * payload - (IN) Tunnel message payload. 1185 * async - (IN) Message should be queued and sent asynchronously 1186 * Returns: 1187 * BCM_E_XXX 1188 * Notes: 1189 */ 1190 int 1191 _bcm_ptp_tunnel_message_to_top( 1192 int unit, 1193 bcm_ptp_stack_id_t ptp_id, 1194 int clock_index, 1195 int port_index, 1196 unsigned payload_len, 1197 uint8 *payload, 1198 int async) 1199 { 1200 uint8 hdr[2] = {0}; 1201 _bcm_ptp_uint16_write(hdr, port_index); 1202 1203 if (async) { 1204 return _bcm_ptp_tunnel_queue_add(unit, ptp_id, clock_index, PTP_TUNNEL_TO_TOP, sizeof(hdr), hdr, payload_len, payload); 1205 } else { 1206 return _bcm_ptp_tunnel_message(unit, ptp_id, clock_index, PTP_TUNNEL_TO_TOP, sizeof(hdr), hdr, payload_len, payload); 1207 } 1208 } 1209 1210 1211 /* 1212 * Function: 1213 * _bcm_ptp_tunnel_message_to_world 1214 * Purpose: 1215 * Tunnel a message to "world". 1216 * Parameters: 1217 * unit - (IN) Unit number. 1218 * ptp_id - (IN) PTP stack ID. 1219 * clock_index - (IN) PTP clock index. 1220 * payload_len - (IN) Tunnel message payload size (octets). 1221 * payload - (IN) Tunnel message payload. 1222 * async - (IN) Message should be queued and sent asynchronously 1223 * Returns: 1224 * BCM_E_XXX 1225 * Notes: 1226 */ 1227 int 1228 _bcm_ptp_tunnel_message_to_world( 1229 int unit, 1230 bcm_ptp_stack_id_t ptp_id, 1231 int clock_index, 1232 unsigned payload_len, 1233 uint8 *payload, 1234 int async) 1235 { 1236 if (async) { 1237 return _bcm_ptp_tunnel_queue_add(unit, ptp_id, clock_index, PTP_TUNNEL_FROM_TOP, 0, 0, payload_len, payload); 1238 } else { 1239 return _bcm_ptp_tunnel_message(unit, ptp_id, clock_index, PTP_TUNNEL_FROM_TOP, 0, 0, payload_len, payload); 1240 } 1241 } 1242 1243 1244 /* 1245 * Function: 1246 * _bcm_ptp_tunnel_message 1247 * Purpose: 1248 * Tunnel a message out 1249 * Parameters: 1250 * unit - (IN) Unit number. 1251 * ptp_id - (IN) PTP stack ID. 1252 * clock_index - (IN) PTP clock index. 1253 * clock_port - (IN) PTP clock port if type is PTP_TUNNEL_TO_TOP 1254 * tunnel_type - (IN) PTP_TUNNEL_FROM_TOP, PTP_TUNNEL_TO_TOP, PTP_TUNNEL_SINGLE_TO_TOP 1255 * payload_len - (IN) Tunnel message payload size (octets). 1256 * payload - (IN) Tunnel message payload. 1257 * Returns: 1258 * BCM_E_XXX 1259 * Notes: 1260 */ 1261 static int 1262 _bcm_ptp_tunnel_message( 1263 int unit, 1264 bcm_ptp_stack_id_t ptp_id, 1265 int clock_index, 1266 int tunnel_type, 1267 unsigned hdr_len, 1268 uint8 *hdr, 1269 unsigned payload_len, 1270 uint8 *payload) 1271 { 1272 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 1273 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id]; 1274 1275 int rv = BCM_E_NONE; 1276 int rvbody = BCM_E_FAIL; 1277 static int failure_count = 0; 1278 static const int failure_log_threshold = 10; 1279 1280 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1281 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 1282 /* Verify initialization */ 1283 LOG_VERBOSE(BSL_LS_BCM_PTP, 1284 (BSL_META_U(unit, 1285 "PTP tunnel failed: Memory state\n"))); 1286 return BCM_E_UNAVAIL; 1287 } 1288 1289 rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_TUNNEL_MESSAGE_TIMEOUT_US); 1290 if (BCM_FAILURE(rv)) { 1291 if (++failure_count > failure_log_threshold) { 1292 LOG_ERROR(BSL_LS_BCM_PTP, 1293 (BSL_META_U(unit, 1294 "Repeated PTP tunnel failures due to busy state\n"))); 1295 } else { 1296 LOG_VERBOSE(BSL_LS_BCM_PTP, 1297 (BSL_META_U(unit, 1298 "PTP tunnel failure due to busy state\n"))); 1299 } 1300 return rv; 1301 } 1302 1303 rv = stack_p->tx(unit, ptp_id, clock_index, tunnel_type, hdr, hdr_len, payload, payload_len); 1304 1305 if (rv != BCM_E_NONE) { 1306 LOG_VERBOSE(BSL_LS_BCM_PTP, 1307 (BSL_META_U(unit, 1308 "PTP tunnel failed: Tx error\n"))); 1309 goto release_tunnel_lock; 1310 } 1311 1312 rv = stack_p->tx_completion(unit, ptp_id); 1313 1314 release_tunnel_lock: 1315 rvbody = rv; 1316 if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) { 1317 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 1318 } 1319 1320 if (rvbody == BCM_E_NONE) { 1321 failure_count = 0; 1322 } 1323 1324 return rvbody ? rvbody : rv; 1325 } 1326 1327 1328 1329 int 1330 _bcm_ptp_external_tx( 1331 int unit, 1332 bcm_ptp_stack_id_t ptp_id, 1333 int clock_num, 1334 _bcm_ptp_transport_type_t transport, 1335 uint8 *hdr, 1336 int hdr_len, 1337 uint8 *message, 1338 int message_len) 1339 { 1340 int rv = BCM_E_NONE; 1341 1342 /* LOG_CLI((BSL_META_U(unit, 1343 "external_tx(type:%d len:%d)\n"), (int)transport, message_len)); */ 1344 /* _bcm_ptp_dump_hex(message, message_len, 0); */ 1345 1346 /* Send the right kind of message */ 1347 switch (transport) { 1348 case PTP_MESSAGE_TO_TOP: 1349 { 1350 /* WFT: probably should just allocate packet here rather than having pre-allocated... */ 1351 _bcm_ptp_stack_mgmt_array_t *mgmt = &STACK_DATA(unit, ptp_id); 1352 bcm_pkt_t *mgmt_packet = mgmt->mgmt_packet; 1353 uint8 *cursor = BCM_PKT_IEEE(mgmt_packet); 1354 int prio = 0; 1355 1356 /* L2 Header MACs*/ 1357 sal_memcpy(cursor, mgmt->dest_mac, sizeof(bcm_mac_t)); cursor += sizeof(bcm_mac_t); 1358 sal_memcpy(cursor, mgmt->src_mac, sizeof(bcm_mac_t)); cursor += sizeof(bcm_mac_t); 1359 1360 /* VLAN */ 1361 *cursor++ = 0x81; *cursor++ = 0x00; 1362 *cursor++ = (prio << 5) | (0x0f & (mgmt->vlan >> 8)); 1363 *cursor++ = (mgmt->vlan); 1364 1365 /* Ethertype: IPv4 */ 1366 *cursor++ = 0x08; 1367 *cursor++ = 0x00; 1368 1369 /* IPv4 Header */ 1370 *cursor++ = 0x45; /*type & header length */ 1371 *cursor++ = 0x00; 1372 1373 /* IPv4 total length */ 1374 _bcm_ptp_uint16_write(cursor, 20 + 8 + hdr_len + message_len); cursor += 2; 1375 1376 *cursor++ = 0; 1377 *cursor++ = 0; 1378 1379 *cursor++ = 0x40; /* flags */ 1380 *cursor++ = 0; 1381 1382 *cursor++ = 1; /* TTL */ 1383 *cursor++ = 0x11; /* protocol = UDP */ 1384 1385 *cursor++ = 0; /* header checksum (zeros for computation) */ 1386 *cursor++ = 0; 1387 1388 _bcm_ptp_uint32_write(cursor, mgmt->src_ip); cursor += 4; 1389 _bcm_ptp_uint32_write(cursor, mgmt->dest_ip); cursor += 4; 1390 1391 /* UDP Header */ 1392 _bcm_ptp_uint16_write(cursor, 0x140); cursor += 2; /* source port */ 1393 _bcm_ptp_uint16_write(cursor, 0x140); cursor += 2; /* dest port */ 1394 1395 _bcm_ptp_uint16_write(cursor, 8 + hdr_len + message_len); cursor += 2; /* UDP length */ 1396 1397 _bcm_ptp_uint16_write(cursor, 0); cursor += 2; /* UDP Checksum (optional) */ 1398 1399 /* Update IPv4 header checksum. */ 1400 rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(BCM_PKT_IEEE(mgmt_packet)); 1401 1402 1403 sal_memcpy(cursor, hdr, hdr_len); cursor += hdr_len; 1404 sal_memcpy(cursor, message, message_len); cursor += message_len; 1405 1406 /* 1407 * Set packet length. 1408 * NOTICE: Includes 4 for the CRC appended to the packet 1409 */ 1410 mgmt_packet->pkt_data[0].len = (cursor - BCM_PKT_IEEE(mgmt_packet)) + 4; 1411 1412 /* LOG_CLI((BSL_META_U(unit, 1413 "packet(len:%d)\n"), mgmt_packet->pkt_data[0].len)); */ 1414 /* _bcm_ptp_dump_hex(BCM_PKT_IEEE(mgmt_packet), mgmt_packet->pkt_data[0].len, 0); */ 1415 1416 rv = bcm_tx(unit, mgmt_packet, NULL); 1417 1418 break; 1419 } 1420 1421 case PTP_TUNNEL_TO_TOP: 1422 { 1423 int rv = BCM_E_UNAVAIL; 1424 1425 bcm_pkt_t *tunnel_packet; 1426 1427 uint16 udp_length = hdr_len + message_len + PTP_UDPHDR_SIZE_OCTETS; 1428 uint16 ip_length = udp_length + PTP_IPV4HDR_SIZE_OCTETS; 1429 uint16 packet_length = ip_length + PTP_IPV4HDR_START_IDX; 1430 int i = 0; 1431 1432 tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet; 1433 1434 i = PTP_PTPHDR_START_IDX; 1435 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, hdr, hdr_len); 1436 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i + hdr_len, message, message_len); 1437 1438 i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS; 1439 _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, udp_length); 1440 1441 i = PTP_IPV4HDR_START_IDX + PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS; 1442 _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, ip_length); 1443 1444 _bcm_ptp_management_message_port_set(BCM_PKT_IEEE(tunnel_packet), 0x0141, 0x0141); 1445 1446 /* Set IPv4 header checksum. */ 1447 if (BCM_FAILURE(rv = _bcm_ptp_management_message_ipv4hdr_checksum_set( 1448 BCM_PKT_IEEE(tunnel_packet)))) { 1449 return rv; 1450 } 1451 1452 /* Set packet size. */ 1453 tunnel_packet->pkt_data[0].len = packet_length + 4; 1454 1455 rv = bcm_tx(unit, tunnel_packet, NULL); 1456 1457 break; 1458 } 1459 1460 case PTP_TUNNEL_FROM_TOP: 1461 { 1462 int rv = BCM_E_UNAVAIL; 1463 1464 bcm_pkt_t *tunnel_packet; 1465 1466 uint16 udp_length = hdr_len + message_len + PTP_UDPHDR_SIZE_OCTETS; 1467 uint16 ip_length = udp_length + PTP_IPV4HDR_SIZE_OCTETS; 1468 uint16 packet_length = ip_length + PTP_IPV4HDR_START_IDX; 1469 int i = 0; 1470 1471 tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet; 1472 1473 i = PTP_PTPHDR_START_IDX; 1474 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, hdr, hdr_len); 1475 sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i + hdr_len, message, message_len); 1476 1477 i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS; 1478 _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, udp_length); 1479 1480 i = PTP_IPV4HDR_START_IDX + PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS; 1481 _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, ip_length); 1482 1483 _bcm_ptp_management_message_port_set(BCM_PKT_IEEE(tunnel_packet), 0x0143, 0x0143); 1484 1485 /* Set IPv4 header checksum. */ 1486 rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(BCM_PKT_IEEE(tunnel_packet)); 1487 if (BCM_FAILURE(rv)) { 1488 PTP_ERROR_FUNC("_bcm_ptp_management_message_ipv4hdr_checksum_set()"); 1489 return rv; 1490 } 1491 1492 /* Set packet size. */ 1493 tunnel_packet->pkt_data[0].len = packet_length + 4; 1494 1495 rv = bcm_tx(unit, tunnel_packet, NULL); 1496 1497 break; 1498 } 1499 1500 default: 1501 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1502 (BSL_META_U(unit, 1503 "PTP external send failed: Unkmown transport type\n"))); 1504 } 1505 1506 return rv; 1507 } 1508 1509 1510 int 1511 _bcm_ptp_external_tx_completion( 1512 int unit, 1513 bcm_ptp_stack_id_t ptp_id) 1514 { 1515 /* message was already sent as a packet via switch, so it is already gone */ 1516 return BCM_E_NONE; 1517 } 1518 1519 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 1520 int 1521 _bcm_ptp_internal_tx( 1522 int unit, 1523 bcm_ptp_stack_id_t ptp_id, 1524 int clock_num, 1525 _bcm_ptp_transport_type_t transport, 1526 uint8 *hdr, 1527 int hdr_len, 1528 uint8 *message, 1529 int message_len) 1530 1531 { 1532 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 1533 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id]; 1534 1535 int rv = BCM_E_NONE; 1536 1537 mos_msg_data_t uc_msg; 1538 uint8 *msg_data; 1539 1540 int wait_iter = 0; 1541 1542 sal_memset(&uc_msg, 0, sizeof(uc_msg)); 1543 uc_msg.s.mclass = MOS_MSG_CLASS_1588; 1544 uc_msg.s.subclass = MOS_MSG_SUBCLASS_MBOX_CMDRESP; 1545 1546 /* mbox 0 reserved for cmd/resp */ 1547 msg_data = (uint8 *)stack_p->int_state.mboxes->mbox[0].data; 1548 1549 if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) { 1550 /* wait for to-TOP buffer to be free */ 1551 while (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY && wait_iter < 1000000) { 1552 ++wait_iter; 1553 sal_usleep(1); 1554 } 1555 1556 if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) { 1557 int old_status = GET_MBOX_STATUS(stack_p, 0); 1558 /* Waiting failed. Flush whatever is in the mbox to reset things. 1559 * Note: If this is happening, a previous message send/receive has 1560 * likely failed. Possible causes can be a block on the host side 1561 * Rx task, or a failure of the FW that we are trying to talk to 1562 */ 1563 _bcm_ptp_rx_response_flush(unit, ptp_id, clock_num); 1564 if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) { 1565 LOG_ERROR(BSL_LS_BCM_PTP, (BSL_META_U(unit, 1566 "PTP mbox full and unflushable (status %d)\n"), 1567 old_status)); 1568 return BCM_E_FAIL; 1569 } else { 1570 LOG_ERROR(BSL_LS_BCM_PTP, (BSL_META_U(unit, 1571 "PTP mbox force-flushed (status %d)\n"), 1572 old_status)); 1573 } 1574 } else if (wait_iter > 0) { 1575 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, 1576 "PTP mbox contention, wait: %d\n"), wait_iter)); 1577 } 1578 } 1579 1580 sal_memcpy(msg_data, hdr, hdr_len); 1581 sal_memcpy(msg_data + hdr_len, message, message_len); 1582 1583 stack_p->int_state.mboxes->mbox[0].data_len = soc_htonl(hdr_len + message_len); 1584 stack_p->int_state.mboxes->mbox[0].clock_num = soc_htonl(clock_num); 1585 1586 /* Flush entire mbox structure so firmware can DMA it (before setting status, to avoid race) */ 1587 soc_cm_sflush(unit, (void*)&stack_p->int_state.mboxes->mbox[0], 1588 sizeof(stack_p->int_state.mboxes->mbox[0])); 1589 1590 /* Send the right kind of message */ 1591 switch (transport) { 1592 case PTP_MESSAGE_TO_TOP: 1593 SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_CMD); 1594 break; 1595 case PTP_TUNNEL_TO_TOP: 1596 SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_TUNNEL_TO_TOP); 1597 break; 1598 case PTP_TUNNEL_FROM_TOP: 1599 SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_TUNNEL_EXTERNAL); 1600 break; 1601 default: 1602 LOG_ERROR(BSL_LS_BCM_COMMON, 1603 (BSL_META_U(unit, 1604 "PTP internal send failed: Unkmown transport type\n"))); 1605 } 1606 1607 rv = soc_cmic_uc_msg_send(unit, stack_p->int_state.core_num, &uc_msg, 1000000); 1608 1609 return rv; 1610 } 1611 1612 int 1613 _bcm_ptp_internal_tx_completion( 1614 int unit, 1615 bcm_ptp_stack_id_t ptp_id) 1616 { 1617 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 1618 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id]; 1619 int iter; 1620 1621 for (iter = 0; iter < 10000; ++iter) { 1622 if (GET_MBOX_STATUS(stack_p, 0) == MBOX_STATUS_EMPTY) { 1623 return BCM_E_NONE; 1624 } 1625 sal_usleep(1); 1626 } 1627 1628 LOG_ERROR(BSL_LS_BCM_COMMON, 1629 (BSL_META_U(unit, 1630 "Failed async Tx to ToP. No clear\n"))); 1631 return BCM_E_TIMEOUT; 1632 } 1633 1634 1635 #endif 1636 1637 1638 /* 1639 * Function: 1640 * _bcm_ptp_unicast_slave_subscribe 1641 * Purpose: 1642 * Manage external slave subscriptions of a PTP clock port. 1643 * Parameters: 1644 * unit - (IN) Unit number. 1645 * ptp_id - (IN) PTP stack ID. 1646 * clock_num - (IN) PTP clock number. 1647 * clock_port - (IN) PTP clock port number. 1648 * slave_info - (IN) Unicast slave information. 1649 * msg_type - (IN) PTP message type to request/cancel. 1650 * tlv_type - (IN) TLV type (request/cancel unicast transmission). 1651 * interval - (IN) Log inter-message interval (logInterMessagePeriod). 1652 * Returns: 1653 * BCM_E_XXX 1654 * Notes: 1655 * PTP unicast negotiation is used to manage external slave services 1656 * through REQUEST_UNICAST_TRANSMISSION and CANCEL_UNICAST_TRANSMISSION 1657 * TLVs. 1658 * Ref. IEEE Std. 1588-2008, Chapters 14.1 and 16.1. 1659 */ 1660 int 1661 _bcm_ptp_unicast_slave_subscribe( 1662 int unit, 1663 bcm_ptp_stack_id_t ptp_id, 1664 int clock_num, 1665 uint32 clock_port, 1666 _bcm_ptp_clock_peer_ext_t *slave_info, 1667 bcm_ptp_message_type_t msg_type, 1668 bcm_ptp_tlv_type_t tlv_type, 1669 int interval) 1670 { 1671 int rv = BCM_E_UNAVAIL; 1672 int rvbody = BCM_E_FAIL; 1673 1674 bcm_ptp_port_identity_t portid; 1675 uint8 message[1500]; 1676 uint16 message_len; 1677 1678 uint16 tlv_octets = 0; 1679 uint16 sequence_id = 0x0002; 1680 1681 uint8 *response_data; 1682 uint16 response_tlv_type; 1683 int response_len; 1684 int i = 0; 1685 1686 _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit]; 1687 _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id]; 1688 1689 rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT); 1690 if (BCM_FAILURE(rv)) { 1691 return rv; 1692 } 1693 1694 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1695 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 1696 return BCM_E_UNAVAIL; 1697 } 1698 1699 rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_MGMT_RESPONSE_TIMEOUT_US); 1700 if (BCM_FAILURE(rv)) { 1701 PTP_ERROR_FUNC("_bcm_ptp_sem_take()"); 1702 return rv; 1703 } 1704 1705 /* 1706 * TLV-type dependent message constructor parameters. 1707 * Set unicast signaling message size information based on TLV type. 1708 * Set sequence ID numbering scheme offset. 1709 */ 1710 switch (tlv_type) { 1711 case bcmPTPTlvTypeRequestUnicastTransmission: 1712 tlv_octets = PTP_UCSIG_REQUEST_TLV_SIZE_OCTETS; 1713 message_len = PTP_UCSIG_REQUEST_TOTAL_SIZE_OCTETS - PTP_PTPHDR_START_IDX; 1714 sequence_id += 0; 1715 break; 1716 1717 case bcmPTPTlvTypeCancelUnicastTransmission: 1718 tlv_octets = PTP_UCSIG_CANCEL_TLV_SIZE_OCTETS; 1719 message_len = PTP_UCSIG_CANCEL_TOTAL_SIZE_OCTETS - PTP_PTPHDR_START_IDX; 1720 sequence_id += 4; 1721 break; 1722 1723 default: 1724 rv = BCM_E_PARAM; 1725 goto release_return; 1726 } 1727 1728 /* Make unicast transmission message. */ 1729 sal_memset(message, 0, sizeof (message)); 1730 1731 sal_memcpy(message, 1732 ptphdr_ucsig, sizeof(ptphdr_ucsig)); 1733 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS, 1734 tgtport_ucsig, sizeof(tgtport_ucsig)); 1735 sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS, 1736 unicast_request_tlv_ucsig, sizeof(unicast_request_tlv_ucsig)); 1737 1738 /* Insert PTP header length. */ 1739 _bcm_ptp_uint16_write(message + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, message_len); 1740 1741 message[PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = CLOCK_DATA(unit, ptp_id, clock_num).domain; 1742 1743 /* 1744 * Insert source port identity. 1745 * NOTICE: In this context, the source port is the remote port, i.e., 1746 * requester/grantee of signaling messages. 1747 */ 1748 sal_memcpy(message + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS, 1749 slave_info->peer.clock_identity, sizeof(bcm_ptp_clock_identity_t)); 1750 1751 _bcm_ptp_uint16_write(message + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS + BCM_PTP_CLOCK_EUID_IEEE1588_SIZE, 1752 slave_info->peer.remote_port_number); 1753 1754 /* 1755 * Insert sequence ID. 1756 * NOTICE: Logic uses a unique sequence IDs for distinct classes only of 1757 * REQUEST_UNICAST_TRANSMISSION and CANCEL_UNICAST_TRANSMISSION 1758 * signaling messages. 1759 */ 1760 switch (msg_type) { 1761 case bcmPTP_MESSAGE_TYPE_ANNOUNCE: 1762 break; 1763 1764 case bcmPTP_MESSAGE_TYPE_SYNC: 1765 sequence_id += 1; 1766 break; 1767 1768 case bcmPTP_MESSAGE_TYPE_DELAY_RESP: 1769 sequence_id += 2; 1770 break; 1771 1772 case bcmPTP_MESSAGE_TYPE_PDELAY_RESP: 1773 sequence_id += 3; 1774 break; 1775 1776 default: 1777 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1778 (BSL_META_U(unit, 1779 "PTP unicast subscribe failed: Unknown message type\n"))); 1780 rv = BCM_E_PARAM; 1781 goto release_return; 1782 } 1783 1784 _bcm_ptp_uint16_write(message + PTP_PTPHDR_SEQID_OFFSET_OCTETS, sequence_id); 1785 1786 /* Insert target port identity. */ 1787 rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, clock_num, slave_info->peer.local_port_number, &portid); 1788 if (BCM_FAILURE(rv)) { 1789 goto release_return; 1790 } 1791 1792 sal_memcpy(message + PTP_SIGHDR_TGTCLOCK_OFFSET_OCTETS, 1793 portid.clock_identity, sizeof(bcm_ptp_clock_identity_t)); 1794 1795 _bcm_ptp_uint16_write(message + PTP_SIGHDR_TGTPORT_OFFSET_OCTETS, slave_info->peer.local_port_number); 1796 1797 /* Insert TLV type. */ 1798 _bcm_ptp_uint16_write(message + PTP_SIGHDR_SIZE_OCTETS, tlv_type); 1799 1800 /* Insert TLV length. NOTICE: PTP message length, TLV "V" part only. */ 1801 _bcm_ptp_uint16_write(message + PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_TLVLEN_OFFSET_OCTETS, (tlv_octets-4)); 1802 1803 /* 1804 * Insert message type. 1805 * NOTICE: IEEE Std. 1588-2008, Tables 73-75 specify following format for 1806 * 4-bit message type (messageType). 1807 * |B7|B6|B5|B4|B3|B2|B1|B0| = 1808 * |messageType|X |X |X |X |. X = Reserved. 1809 */ 1810 message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_MSGTYPE_OFFSET_OCTETS] = ((msg_type << 4) & 0xf0); 1811 1812 if (tlv_type == bcmPTPTlvTypeRequestUnicastTransmission) { 1813 /* REQUEST_UNICAST_TRANSMISSION TLV. */ 1814 1815 /* Set log message interval. */ 1816 message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_INTERVAL_OFFSET_OCTETS] = (uint8)interval; 1817 1818 /* Set message duration. */ 1819 _bcm_ptp_uint32_write(message + PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_INTERVAL_OFFSET_OCTETS + 1, 1820 PTP_UNICAST_NEVER_EXPIRE); 1821 1822 /* Insert signaling message TLV data. Peer address */ 1823 i = PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_ADDRTYPE_OFFSET_OCTETS; 1824 switch (slave_info->peer.peer_address.addr_type) { 1825 case bcmPTPUDPIPv4: 1826 /* Ethernet/UDP/IPv4 address type. */ 1827 message[i++] = bcmPTPUDPIPv4; 1828 sal_memset(message + i, 0, PTP_MAX_NETW_ADDR_SIZE); 1829 _bcm_ptp_uint32_write(message + i, slave_info->peer.peer_address.ipv4_addr); 1830 1831 break; 1832 1833 case bcmPTPUDPIPv6: 1834 /* Ethernet/UDP/IPv6 address type. */ 1835 message[i++] = bcmPTPUDPIPv6; 1836 sal_memcpy(message + i, slave_info->peer.peer_address.ipv6_addr, sizeof(bcm_ip6_t)); 1837 1838 break; 1839 1840 default: 1841 /* Unknown or unsupported address type. */ 1842 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1843 (BSL_META_U(unit, 1844 "PTP unicast subscribe failed: Unknown or unsupported address type\n"))); 1845 rv = BCM_E_PARAM; 1846 goto release_return; 1847 } 1848 1849 /* Signaling message L2 header length and L2 header. */ 1850 i += PTP_MAX_NETW_ADDR_SIZE; 1851 1852 message[i++] = 1853 (slave_info->peer.peer_address.raw_l2_header_length > PTP_MAX_L2_HEADER_LENGTH) ? 1854 (PTP_MAX_L2_HEADER_LENGTH) : (slave_info->peer.peer_address.raw_l2_header_length); 1855 1856 sal_memcpy(message + i, 1857 slave_info->peer.peer_address.raw_l2_header, 1858 slave_info->peer.peer_address.raw_l2_header_length); 1859 1860 i += slave_info->peer.peer_address.raw_l2_header_length; 1861 1862 /* Add Local address */ 1863 sal_memcpy(message + i, slave_info->local_address.address, PTP_MAX_NETW_ADDR_SIZE); 1864 i += PTP_MAX_NETW_ADDR_SIZE; 1865 } else if (tlv_type == bcmPTPTlvTypeCancelUnicastTransmission) { 1866 /* CANCEL_UNICAST_TRANSMISSION TLV. */ 1867 1868 /* Reserved TLV element. */ 1869 message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_CANCEL_RESERVED_OFFSET_OCTETS] = 0x00; 1870 1871 /* 1872 * Insert signaling message TLV data. 1873 * Peer address. 1874 */ 1875 i = PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_CANCEL_ADDRTYPE_OFFSET_OCTETS; 1876 switch (slave_info->peer.peer_address.addr_type) { 1877 case bcmPTPUDPIPv4: 1878 /* Ethernet/UDP/IPv4 address type. */ 1879 message[i++] = bcmPTPUDPIPv4; 1880 _bcm_ptp_uint32_write(message + i, slave_info->peer.peer_address.ipv4_addr); 1881 1882 break; 1883 1884 case bcmPTPUDPIPv6: 1885 /* Ethernet/UDP/IPv6 address type. */ 1886 message[i++] = bcmPTPUDPIPv6; 1887 sal_memcpy(message + i, slave_info->peer.peer_address.ipv6_addr, sizeof(bcm_ip6_t)); 1888 1889 break; 1890 1891 default: 1892 /* Unknown or unsupported address type. */ 1893 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1894 (BSL_META_U(unit, 1895 "PTP unicast subscribe failed: Unknown or unsupported address type\n"))); 1896 rv = BCM_E_PARAM; 1897 goto release_return; 1898 } 1899 } 1900 1901 /* LOG_CLI((BSL_META_U(unit, 1902 "sig_send_tx(len:%d)\n"), message_len)); */ 1903 /* _bcm_ptp_dump_hex(message, message_len, 0); */ 1904 1905 /* Transmit message. */ 1906 rv = stack_p->tx(unit, ptp_id, clock_num, PTP_MESSAGE_TO_TOP, 0, 0, message, message_len); 1907 if (BCM_FAILURE(rv)) { 1908 PTP_ERROR_FUNC("tx()"); 1909 goto release_return; 1910 } 1911 1912 /* 1913 * NOTICE: This call will return an rx response buffer that we 1914 * will own and need to free. 1915 */ 1916 if (BCM_FAILURE(rv = _bcm_ptp_rx_response_get(unit, ptp_id, clock_num, 1917 PTP_MGMT_RESPONSE_TIMEOUT_US, &response_data, &response_len))) { 1918 PTP_ERROR_FUNC("bcmptp_rx_get_response()"); 1919 goto release_return; 1920 } 1921 1922 rv = BCM_E_FAIL; 1923 1924 /* Parse response. */ 1925 response_tlv_type = _bcm_ptp_uint16_read(response_data + 1926 PTP_SIGHDR_SIZE_OCTETS); 1927 if (tlv_type == bcmPTPTlvTypeRequestUnicastTransmission && 1928 response_tlv_type != bcmPTPTlvTypeGrantUnicastTransmission) { 1929 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1930 (BSL_META_U(unit, 1931 "PTP unicast subscribe failed: Unicast request failed\n"))); 1932 goto dispose_of_resp; 1933 } 1934 1935 if (tlv_type == bcmPTPTlvTypeCancelUnicastTransmission && 1936 response_tlv_type != bcmPTPTlvTypeAckCancelUnicastTransmission) { 1937 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1938 (BSL_META_U(unit, 1939 "PTP unicast subscribe failed: Unicast cancel failed\n"))); 1940 goto dispose_of_resp; 1941 } 1942 1943 rv = BCM_E_NONE; 1944 1945 dispose_of_resp: 1946 stack_p->rx_free(unit, ptp_id, response_data); 1947 1948 release_return: 1949 rvbody = rv; 1950 if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) { 1951 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 1952 } 1953 1954 return rvbody ? rvbody : rv; 1955 } 1956 1957 /* 1958 * Function: 1959 * _bcm_ptp_management_domain_get 1960 * Purpose: 1961 * Get the current domain used for PTP management messages for a PTP clock. 1962 * Parameters: 1963 * unit - (IN) Unit number. 1964 * ptp_id - (IN) PTP stack ID. 1965 * clock_num - (IN) PTP clock number. 1966 * domain - (OUT) PTP domain. 1967 * Returns: 1968 * BCM_E_XXX 1969 * Notes: 1970 */ 1971 int 1972 _bcm_ptp_management_domain_get( 1973 int unit, 1974 bcm_ptp_stack_id_t ptp_id, 1975 int clock_num, 1976 uint8 *domain) 1977 { 1978 int rv = BCM_E_UNAVAIL; 1979 1980 rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT); 1981 if (BCM_FAILURE(rv)) { 1982 return rv; 1983 } 1984 1985 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1986 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 1987 return BCM_E_UNAVAIL; 1988 } 1989 1990 *domain = CLOCK_DATA(unit, ptp_id, clock_num).domain; 1991 1992 return rv; 1993 } 1994 1995 /* 1996 * Function: 1997 * _bcm_ptp_management_domain_set 1998 * Purpose: 1999 * Set the domain to use in PTP management messages for a PTP clock. 2000 * Parameters: 2001 * unit - (IN) Unit number. 2002 * ptp_id - (IN) PTP stack ID. 2003 * clock_num - (IN) PTP clock number. 2004 * domain - (IN) PTP domain. 2005 * Returns: 2006 * BCM_E_XXX 2007 * Notes: 2008 */ 2009 int 2010 _bcm_ptp_management_domain_set( 2011 int unit, 2012 bcm_ptp_stack_id_t ptp_id, 2013 int clock_num, 2014 uint8 domain) 2015 { 2016 int rv = BCM_E_UNAVAIL; 2017 2018 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 2019 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 2020 return rv; 2021 } 2022 2023 if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 2024 (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) { 2025 return BCM_E_UNAVAIL; 2026 } 2027 2028 CLOCK_DATA(unit, ptp_id, clock_num).domain = domain; 2029 2030 return rv; 2031 } 2032 2033 /* 2034 * Function: 2035 * _bcm_ptp_management_message_create 2036 * Purpose: 2037 * Create a PTP management message from template. 2038 * Parameters: 2039 * message - (IN/OUT) PTP management message. 2040 * Returns: 2041 * BCM_E_XXX 2042 * Notes: 2043 */ 2044 static int 2045 _bcm_ptp_management_message_create( 2046 uint8 *message) 2047 { 2048 int rv = BCM_E_UNAVAIL; 2049 int i = 0; 2050 2051 /* 2052 * Management message header 2053 * NOTICE: Includes L2, VLAN, IPv4, UDP, PTP, and management headers. 2054 */ 2055 sal_memcpy(message, l2hdr_default, sizeof(l2hdr_default)); 2056 i += sizeof(l2hdr_default); 2057 2058 sal_memcpy(message + i, vlanhdr_default, sizeof(vlanhdr_default)); 2059 i += sizeof(vlanhdr_default); 2060 2061 sal_memcpy(message + i, ethhdr_default, sizeof(ethhdr_default)); 2062 i += sizeof(ethhdr_default); 2063 2064 sal_memcpy(message + i, ipv4hdr_default, sizeof(ipv4hdr_default)); 2065 i += sizeof(ipv4hdr_default); 2066 2067 sal_memcpy(message + i, udphdr_default, sizeof(udphdr_default)); 2068 i += sizeof(udphdr_default); 2069 2070 sal_memcpy(message + i, ptphdr_mgmt, sizeof(ptphdr_mgmt)); 2071 i += sizeof(ptphdr_mgmt); 2072 2073 sal_memcpy(message + i, mgmthdr_mgmt, sizeof(mgmthdr_mgmt)); 2074 i += sizeof(mgmthdr_mgmt); 2075 2076 sal_memcpy(message + i, tlvhdr_mgmt, sizeof(tlvhdr_mgmt)); 2077 2078 /* Set L2 header (Ethertype= IPv4). */ 2079 i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_SIZE_OCTETS; 2080 message[i++] = 0x08; 2081 message[i] = 0x00; 2082 2083 /* Update IPv4 header checksum. */ 2084 rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(message); 2085 2086 return rv; 2087 } 2088 2089 /* /\* */ 2090 /* * Function: */ 2091 /* * _bcm_ptp_management_message_make */ 2092 /* * Purpose: */ 2093 /* * Make a PTP management message. */ 2094 /* * Parameters: */ 2095 /* * message - (IN/OUT) PTP management message. */ 2096 /* * action - (IN) PTP management action (actionField). */ 2097 /* * cmd - (IN) PTP command (managementId). */ 2098 /* * payload - (IN) PTP management message payload. */ 2099 /* * payload_len - (IN) PTP management message payload size (octets). */ 2100 /* * Returns: */ 2101 /* * BCM_E_XXX */ 2102 /* * Notes: */ 2103 /* *\/ */ 2104 /* static int */ 2105 /* _bcm_ptp_management_message_make( */ 2106 /* uint8 *message, */ 2107 /* uint8 action, */ 2108 /* uint16 cmd, */ 2109 /* uint8 *payload, */ 2110 /* int payload_len) */ 2111 /* { */ 2112 /* int rv = BCM_E_UNAVAIL; */ 2113 /* int i = 0; */ 2114 2115 /* /\* Set management message action. *\/ */ 2116 /* i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_ACTION_OFFSET_OCTETS; */ 2117 /* message[i] = action; */ 2118 2119 /* /\* */ 2120 /* * Set TLV data. */ 2121 /* * TLV length. */ 2122 /* *\/ */ 2123 /* i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS + */ 2124 /* PTP_TLVHDR_LEN_OFFSET_OCTETS; */ 2125 2126 /* message[i++] = (uint8)((payload_len + PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS) >> 8); */ 2127 /* message[i] = (uint8)((payload_len + PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS) & 0x00ff); */ 2128 2129 /* /\* */ 2130 /* * Set TLV data. */ 2131 /* * TLV value prefix (management ID/command definition). */ 2132 /* *\/ */ 2133 /* i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS + */ 2134 /* PTP_TLVHDR_VAL_PREFIX_OFFSET_OCTETS; */ 2135 2136 /* message[i++]= (uint8)((cmd) >> 8); */ 2137 /* message[i]= (uint8)((cmd) & 0x00ff); */ 2138 2139 /* /\* */ 2140 /* * Insert payload. */ 2141 /* * TLV value body. */ 2142 /* *\/ */ 2143 /* sal_memcpy(message + PTP_MGMTMSG_TOTAL_HEADER_SIZE, payload, payload_len); */ 2144 2145 /* /\* Update management message header metadata. *\/ */ 2146 /* rv = _bcm_ptp_management_message_header_metadata_set(message); */ 2147 2148 /* return rv; */ 2149 /* } */ 2150 2151 /* 2152 * Function: 2153 * _bcm_ptp_management_message_header_metadata_set 2154 * Purpose: 2155 * Set header lengths and IPv4 checksum based on PTP message payload. 2156 * Parameters: 2157 * message - (IN/OUT) PTP management message. 2158 * Returns: 2159 * BCM_E_XXX 2160 * Notes: 2161 */ 2162 /* static int */ 2163 /* _bcm_ptp_management_message_header_metadata_set( */ 2164 /* uint8 *message) */ 2165 /* { */ 2166 /* int rv = BCM_E_UNAVAIL; */ 2167 2168 /* int tlv_length_pos; */ 2169 /* uint16 tlv_length; */ 2170 /* uint16 ptp_length; */ 2171 /* uint16 udp_length; */ 2172 /* uint16 ip_length; */ 2173 2174 /* tlv_length_pos = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS + */ 2175 /* PTP_TLVHDR_LEN_OFFSET_OCTETS; */ 2176 2177 /* tlv_length = _bcm_ptp_uint16_read(message + tlv_length_pos); */ 2178 /* ptp_length = tlv_length + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + */ 2179 /* PTP_TLVHDR_VAL_PREFIX_OFFSET_OCTETS; */ 2180 /* udp_length = ptp_length + PTP_UDPHDR_SIZE_OCTETS; */ 2181 /* ip_length = udp_length + PTP_IPV4HDR_SIZE_OCTETS; */ 2182 2183 /* _bcm_ptp_uint16_write(message + PTP_PTPHDR_START_IDX + */ 2184 /* PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, ptp_length); */ 2185 /* _bcm_ptp_uint16_write(message + PTP_UDPHDR_START_IDX + */ 2186 /* PTP_UDPHDR_MSGLEN_OFFSET_OCTETS, udp_length); */ 2187 /* _bcm_ptp_uint16_write(message + PTP_IPV4HDR_START_IDX + */ 2188 /* PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS, ip_length); */ 2189 2190 /* /\* Update IPv4 header checksum. *\/ */ 2191 /* rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(message); */ 2192 2193 /* return rv; */ 2194 /* } */ 2195 2196 /* 2197 * Function: 2198 * _bcm_ptp_management_macaddr_set 2199 * Purpose: 2200 * Set MAC addresses in PTP management message. 2201 * Parameters: 2202 * message - (IN/OUT) PTP management message. 2203 * src_mac - (IN) Source MAC address. 2204 * dest_mac - (IN) Destination MAC address. 2205 * Returns: 2206 * BCM_E_XXX 2207 * Notes: 2208 */ 2209 static int 2210 _bcm_ptp_management_message_macaddr_set( 2211 uint8 *message, 2212 bcm_mac_t *src_mac, 2213 bcm_mac_t *dest_mac) 2214 { 2215 int i = sizeof(bcm_mac_t); 2216 2217 sal_memcpy(message, dest_mac, i); 2218 sal_memcpy(message + i, src_mac, i); 2219 2220 return BCM_E_NONE; 2221 } 2222 2223 /* 2224 * Function: 2225 * _bcm_ptp_management_message_vlantag_set 2226 * Purpose: 2227 * Set VLAN tag in PTP management message. 2228 * Parameters: 2229 * message - (IN/OUT) PTP management message. 2230 * vlan_tag - (IN) VLAN identifier (VID). 2231 * prio - (IN) Priority code point (PCP). 2232 * Returns: 2233 * BCM_E_XXX 2234 * Notes: 2235 */ 2236 static int 2237 _bcm_ptp_management_message_vlantag_set( 2238 uint8 *message, 2239 uint16 vlan_tag, 2240 uint8 prio) 2241 { 2242 int i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_VID_OFFSET_OCTETS; 2243 2244 /* 2245 * Set VLAN tag. 2246 * Logically combine VLAN identifier (VID) with priority code point (PCP). 2247 * 2248 * IEEE 802.1Q VLAN tagging 32-bit frame. 2249 * |16 Bits| 16 Bits | 2250 * | |3 Bits|1 Bit|12 Bits| 2251 * |TPID |PCP |CFI |VID | 2252 */ 2253 message[i++] = (prio << 5) | (0x0f & (vlan_tag >> 8)); 2254 message[i] = (vlan_tag & 0x00ff); 2255 2256 return BCM_E_NONE; 2257 } 2258 2259 /* 2260 * Function: 2261 * _bcm_ptp_management_message_ipaddr_set 2262 * Purpose: 2263 * Set IP addresses in PTP management message. 2264 * Parameters: 2265 * message - (IN/OUT) PTP management message. 2266 * src_ip - (IN) Source IPv4 address. 2267 * dest_ip - (IN) Destination IPv4 address. 2268 * Returns: 2269 * BCM_E_XXX 2270 * Notes: 2271 */ 2272 static int 2273 _bcm_ptp_management_message_ipaddr_set( 2274 uint8 *message, 2275 bcm_ip_t src_ip, 2276 bcm_ip_t dest_ip) 2277 { 2278 int rv = BCM_E_UNAVAIL; 2279 int i = PTP_L2HDR_SIZE_OCTETS + PTP_ETHHDR_SIZE_OCTETS + 2280 PTP_VLANHDR_SIZE_OCTETS + PTP_IPV4HDR_SRC_IPADDR_OFFSET_OCTETS; 2281 2282 /* Update IPv4 header checksum. */ 2283 if (BCM_FAILURE(rv = 2284 _bcm_ptp_management_message_ipv4hdr_checksum_set(message))) { 2285 return rv; 2286 } 2287 2288 /* Set management message header IP addresses. */ 2289 _bcm_ptp_uint32_write(message + i, src_ip); 2290 i += sizeof(bcm_ip_t); 2291 _bcm_ptp_uint32_write(message + i, dest_ip); 2292 2293 return BCM_E_NONE; 2294 } 2295 2296 /* 2297 * Function: 2298 * _bcm_ptp_management_message_ipv4hdr_checksum_set 2299 * Purpose: 2300 * Set IPv4 header checksum. 2301 * Parameters: 2302 * message - (IN/OUT) PTP management message. 2303 * Returns: 2304 * BCM_E_XXX 2305 * Notes: 2306 */ 2307 static int 2308 _bcm_ptp_management_message_ipv4hdr_checksum_set( 2309 uint8 *message) 2310 { 2311 uint16 chksum; 2312 int i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_SIZE_OCTETS + 2313 PTP_ETHHDR_SIZE_OCTETS; 2314 2315 /* 2316 * Zero header checksum fields in IPv4 header. 2317 * Ref. RFC 791, pp. 14. 2318 */ 2319 message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS] = 0x00; 2320 message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS+1] = 0x00; 2321 2322 /* Calculate checksum. */ 2323 chksum = _bcm_ptp_management_rfc791_checksum(message + i, 2324 PTP_IPV4HDR_SIZE_OCTETS); 2325 2326 /* Insert checksum answer in IPv4 header. */ 2327 message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS] = (uint8)((chksum) >> 8); 2328 message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS+1] = (uint8)((chksum) & 0x00ff); 2329 2330 return BCM_E_NONE; 2331 } 2332 2333 /* 2334 * Function: 2335 * _bcm_ptp_management_message_port_set 2336 * Purpose: 2337 * Set source and destination port numbers in UDP header. 2338 * Parameters: 2339 * message - (IN/OUT) PTP management message. 2340 * src_port - (IN) Source port number. 2341 * dest_port - (IN) Destination port number. 2342 * Returns: 2343 * BCM_E_XXX 2344 * Notes: 2345 */ 2346 static int 2347 _bcm_ptp_management_message_port_set( 2348 uint8 *message, 2349 uint16 src_port, 2350 uint16 dest_port) 2351 { 2352 int i = PTP_UDPHDR_START_IDX; 2353 2354 _bcm_ptp_uint16_write(message + i, src_port); 2355 i += sizeof(uint16); 2356 _bcm_ptp_uint16_write(message + i, dest_port); 2357 2358 return BCM_E_NONE; 2359 } 2360 2361 /* 2362 * Function: 2363 * _bcm_ptp_management_message_target_set 2364 * Purpose: 2365 * Set target PTP clock port identity in PTP management message. 2366 * Parameters: 2367 * message - (IN/OUT) PTP management message. 2368 * clock_identity - (IN) Target PTP clock identity. 2369 * port_num - (IN) Target PTP clock port number. 2370 * Returns: 2371 * BCM_E_XXX 2372 * Notes: 2373 */ 2374 /* static int */ 2375 /* _bcm_ptp_management_message_target_set( */ 2376 /* uint8 *message, */ 2377 /* const bcm_ptp_clock_identity_t clock_identity, */ 2378 /* uint16 port_num) */ 2379 /* { */ 2380 /* int i = PTP_MGMTHDR_START_IDX; */ 2381 2382 /* sal_memcpy(message + i, clock_identity, sizeof(bcm_ptp_clock_identity_t)); */ 2383 /* i += sizeof(bcm_ptp_clock_identity_t); */ 2384 /* _bcm_ptp_uint16_write(message + i, port_num); */ 2385 2386 /* return BCM_E_NONE; */ 2387 /* } */ 2388 2389 /* 2390 * Function: 2391 * _bcm_ptp_management_message_length_get 2392 * Purpose: 2393 * Get the length of PTP management message. 2394 * Parameters: 2395 * message - (IN) PTP management message. 2396 * Returns: 2397 * Length. 2398 * Notes: 2399 */ 2400 /* static int */ 2401 /* _bcm_ptp_management_message_length_get( */ 2402 /* uint8 *message) */ 2403 /* { */ 2404 /* int len = PTP_MGMTMSG_TOTAL_HEADER_SIZE - PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS; */ 2405 2406 /* len += _bcm_ptp_uint16_read(message + PTP_MGMTHDR_START_IDX + */ 2407 /* PTP_MGMTHDR_SIZE_OCTETS + */ 2408 /* PTP_TLVHDR_LEN_OFFSET_OCTETS); */ 2409 2410 /* return len; */ 2411 /* } */ 2412 2413 #if 0 /* Unused. */ 2414 /* 2415 * Function: 2416 * _bcm_ptp_management_message_domain_get 2417 * Purpose: 2418 * Get the PTP domain in PTP management message. 2419 * Parameters: 2420 * message - (IN) PTP management message. 2421 * domain - (OUT) PTP domain. 2422 * Returns: 2423 * BCM_E_XXX 2424 * Notes: 2425 */ 2426 static int 2427 _bcm_ptp_management_message_domain_get( 2428 uint8 *message, 2429 uint8 *domain) 2430 { 2431 *domain = message[PTP_PTPHDR_START_IDX + PTP_PTPHDR_DOMAIN_OFFSET_OCTETS]; 2432 return BCM_E_NONE; 2433 } 2434 #endif /* Unused. */ 2435 2436 /* 2437 * Function: 2438 * _bcm_ptp_management_message_domain_set 2439 * Purpose: 2440 * Set the PTP domain in PTP management message. 2441 * Parameters: 2442 * message - (IN/OUT) PTP management message. 2443 * domain - (IN) PTP domain. 2444 * Returns: 2445 * BCM_E_XXX 2446 * Notes: 2447 */ 2448 int 2449 _bcm_ptp_management_message_domain_set( 2450 uint8 *message, 2451 uint8 domain) 2452 { 2453 message[PTP_PTPHDR_START_IDX + PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = domain; 2454 return BCM_E_NONE; 2455 } 2456 2457 /* 2458 * Function: 2459 * _bcm_ptp_management_rfc791_checksum 2460 * Purpose: 2461 * Calculate checksum of a packet per RFC 791. 2462 * Parameters: 2463 * packet - (IN) Packet. 2464 * packet_len - (IN) Packet size (octets). 2465 * Returns: 2466 * Checksum. 2467 * Notes: 2468 * Caller is responsible for zeroing header checksum fields if IPv4 2469 * packets are passed to the algorithm. 2470 */ 2471 static uint16 2472 _bcm_ptp_management_rfc791_checksum( 2473 uint8 *packet, 2474 int packet_len) 2475 { 2476 uint32 chksum = 0x00000000; 2477 2478 /* 2479 * CHECKSUM ALGORITHM: RFC 791, pp 14. 2480 * 2481 * "The checksum algorithm is: 2482 * The checksum field is the 16 bit one's complement of the one's 2483 * complement sum of all 16 bit words in the header. For purposes of 2484 * computing the checksum, the value of the checksum field is zero." 2485 * 2486 * NOTICE: An equivalent, efficient implementation algorithm enlists 2487 * 32-bit addition and handles 16-bit overflows (carries) as 2488 * a penultimate step. 2489 */ 2490 2491 while (packet_len > 1) 2492 { 2493 /* Assemble words from consecutive octets and add to sum. */ 2494 chksum += (uint32)((((uint16)packet[0]) << 8) | (packet[1])); 2495 2496 /* 2497 * Increment pointer in packet. 2498 * Decrement remaining size. 2499 */ 2500 packet += 2; 2501 packet_len -= 2; 2502 } 2503 2504 /* Process odd octet. */ 2505 if (packet_len == 1) { 2506 chksum += (uint32)(((uint16)packet[0]) << 8); 2507 } 2508 2509 /* Carry(ies). */ 2510 chksum = (chksum >> 16) + (chksum & 0x0000ffff); 2511 2512 /* 2513 * Result. 2514 * NOTICE: 16-bit ones complement. 2515 */ 2516 return (~((uint16)chksum)); 2517 } 2518 2519 2520 /* 2521 * Function: 2522 * _bcm_ptp_rfc791_checksum_add_word 2523 * Purpose: 2524 * Calculate incremental checksum 2525 * Parameters: 2526 * prev_checksum - (IN) Previous checksum 2527 * add_word - (IN) word added 2528 * Returns: 2529 * BCM_E_XXX 2530 * Notes: 2531 */ 2532 static uint16 2533 _bcm_ptp_rfc791_checksum_add_word( 2534 uint16 prev_checksum, 2535 uint16 add_word) 2536 { 2537 uint32 intermediate = 0xffff & ~prev_checksum; 2538 intermediate += add_word; 2539 intermediate = (intermediate >> 16) + (intermediate & 0xffff); 2540 2541 return (uint16)~intermediate; 2542 } 2543 2544 2545 /* 2546 * Function: 2547 * _bcm_ptp_construct_udp_packet 2548 * Purpose: 2549 * Construct UDP packet for signaling messages 2550 * Parameters: 2551 * Returns: 2552 * BCM_E_XXX 2553 * Notes: 2554 */ 2555 int 2556 _bcm_ptp_construct_udp_packet( 2557 bcm_ptp_clock_peer_t *peer, 2558 bcm_ptp_clock_port_address_t *local_port, 2559 uint8* udp_payload, 2560 int udp_payload_len, 2561 uint8* packet, 2562 int *packet_len) 2563 { 2564 int ret = BCM_E_NONE; 2565 int cursor = 0; 2566 int ip_header_start, ip_checksum_pos; 2567 int udp_header_start, udp_checksum_pos; 2568 uint32 checksum; /* 16 bit checksum, with overhead space for carry bits during computation */ 2569 2570 /* L2 Header */ 2571 sal_memcpy(packet, &peer->peer_address.raw_l2_header[0], peer->peer_address.raw_l2_header_length); 2572 cursor += peer->peer_address.raw_l2_header_length; 2573 2574 ip_header_start = cursor; 2575 2576 switch (peer->peer_address.addr_type) { 2577 case bcmPTPUDPIPv4: 2578 packet[cursor++] = 0x45; /* version */ 2579 packet[cursor++] = 0; /* TOS */ 2580 _bcm_ptp_uint16_write(&packet[cursor], 20 + 8 + udp_payload_len); /* Length: IP Hdr, UDP Hdr, payload */ 2581 cursor += 2; 2582 _bcm_ptp_uint16_write(&packet[cursor], 0); /* ident */ 2583 cursor += 2; 2584 packet[cursor++] = 0x40; /* flags: don't fragment */ 2585 packet[cursor++] = 0; /* fragment offset 0 */ 2586 packet[cursor++] = 64; /* TTL = 64 */ 2587 packet[cursor++] = 17; /* Proto = UDP */ 2588 ip_checksum_pos = cursor; 2589 _bcm_ptp_uint16_write(&packet[cursor], 0); /* checksum (write as 0, then compute) */ 2590 cursor += 2; 2591 2592 packet[cursor++] = local_port->address[0]; 2593 packet[cursor++] = local_port->address[1]; 2594 packet[cursor++] = local_port->address[2]; 2595 packet[cursor++] = local_port->address[3]; 2596 2597 _bcm_ptp_uint32_write(&packet[cursor], peer->peer_address.ipv4_addr); 2598 cursor += 4; 2599 2600 /* calculate and write the IP checksum */ 2601 checksum = _bcm_ptp_management_rfc791_checksum(&packet[ip_header_start], 20); 2602 _bcm_ptp_uint16_write(&packet[ip_checksum_pos], checksum); 2603 2604 /* UDP header */ 2605 udp_header_start = cursor; 2606 _bcm_ptp_uint16_write(&packet[cursor], 320); /* Source Port */ 2607 cursor += 2; 2608 _bcm_ptp_uint16_write(&packet[cursor], 320); /* Dest Port */ 2609 cursor += 2; 2610 2611 _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len); /* Length: UDP Hdr, payload */ 2612 cursor += 2; 2613 _bcm_ptp_uint16_write(&packet[cursor], 0); /* Checksum: 0 -> no checksum */ 2614 cursor += 2; 2615 2616 sal_memcpy(&packet[cursor], udp_payload, udp_payload_len); /* Payload */ 2617 cursor += udp_payload_len; 2618 break; 2619 2620 case bcmPTPUDPIPv6: 2621 packet[cursor++] = 0x6e; /* version 6, class 0xe0 (high nybble) */ 2622 packet[cursor++] = 0; /* class 0xe0 (low nybble), flow label 0 */ 2623 packet[cursor++] = 0; /* flow label 0 */ 2624 packet[cursor++] = 0; /* flow label 0 */ 2625 _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len); /* Length: UDP Hdr, payload (sic, no header len like ipv4) */ 2626 cursor += 2; 2627 packet[cursor++] = 17; /* Protocol: UDP */ 2628 packet[cursor++] = 64; /* Hop Limit (TTL) */ 2629 sal_memcpy(&packet[cursor], &local_port->address[0], 16); 2630 cursor += 16; 2631 sal_memcpy(&packet[cursor], &peer->peer_address.ipv6_addr[0], 16); 2632 cursor += 16; 2633 2634 /* UDP header */ 2635 udp_header_start = cursor; 2636 _bcm_ptp_uint16_write(&packet[cursor], 320); /* Source Port */ 2637 cursor += 2; 2638 _bcm_ptp_uint16_write(&packet[cursor], 320); /* Dest Port */ 2639 cursor += 2; 2640 2641 _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len); /* Length: UDP Hdr, payload */ 2642 cursor += 2; 2643 udp_checksum_pos = cursor; 2644 _bcm_ptp_uint16_write(&packet[cursor], 0); /* Checksum: 0 during calculation */ 2645 cursor += 2; 2646 2647 sal_memcpy(&packet[cursor], udp_payload, udp_payload_len); /* Payload */ 2648 cursor += udp_payload_len; 2649 2650 /* checksum over addrs, UDP, & payload */ 2651 checksum = _bcm_ptp_management_rfc791_checksum(&packet[udp_header_start - 32], 32 + 8 + udp_payload_len); 2652 checksum = _bcm_ptp_rfc791_checksum_add_word(checksum, udp_payload_len + 8); /* UDP header len + len */ 2653 checksum = _bcm_ptp_rfc791_checksum_add_word(checksum, 17); /* UDP protocol field */ 2654 _bcm_ptp_uint16_write(&packet[udp_checksum_pos], checksum); 2655 2656 break; 2657 2658 default: 2659 return BCM_E_PARAM; 2660 } 2661 2662 *packet_len = cursor; 2663 2664 return ret; 2665 } 2666 2667 /* 2668 * Function: 2669 * _bcm_ptp_construct_signaling_msg 2670 * Purpose: 2671 * Construct the UDP payload for a signaling message, 2672 * given the TLV payload for the message 2673 * Parameters: 2674 * Returns: 2675 * BCM_E_XXX 2676 * Notes: 2677 */ 2678 int 2679 _bcm_ptp_construct_signaling_msg( 2680 bcm_ptp_port_identity_t *from_port, 2681 bcm_ptp_clock_identity_t to_clock, 2682 uint16 to_port, 2683 int domain, 2684 uint16 sequenceId, 2685 uint8* tlv_payload, 2686 int tlv_payload_len, 2687 uint8* udp_payload, 2688 int *udp_payload_len) 2689 { 2690 memset(udp_payload, 0, 34); /* blank PTP header */ 2691 udp_payload[0] = bcmPTP_MESSAGE_TYPE_SIGNALING; 2692 udp_payload[1] = 2; 2693 _bcm_ptp_uint16_write(&udp_payload[2], 44 + tlv_payload_len); 2694 udp_payload[4] = domain; 2695 udp_payload[6] = 0x04; /* flags: unicast */ 2696 sal_memcpy(&udp_payload[20], &from_port->clock_identity[0], 8); 2697 _bcm_ptp_uint16_write(&udp_payload[28], from_port->port_number); 2698 _bcm_ptp_uint16_write(&udp_payload[30], sequenceId); 2699 udp_payload[32] = 0x05; /* control field: all others */ 2700 udp_payload[33] = 0x7f; /* logMessageInterval: 0x7f */ 2701 2702 sal_memcpy(&udp_payload[34], &to_clock[0], 8); 2703 _bcm_ptp_uint16_write(&udp_payload[42], to_port); 2704 2705 if (NULL != tlv_payload) { 2706 sal_memcpy(&udp_payload[44], tlv_payload, tlv_payload_len); 2707 } else { 2708 tlv_payload_len = 0; 2709 } 2710 2711 *udp_payload_len = tlv_payload_len + 44; 2712 2713 return BCM_E_NONE; 2714 } 2715 2716 2717 /* 2718 * Function: 2719 * _bcm_ptp_construct_signaling_request_tlv 2720 * Purpose: 2721 * Construct the TLV for a signaling msg request unicast transmission 2722 * Parameters: 2723 * Returns: 2724 * BCM_E_XXX 2725 * Notes: 2726 */ 2727 int 2728 _bcm_ptp_construct_signaling_request_tlv( 2729 int type, 2730 int interval, 2731 unsigned duration, 2732 uint8* tlv_payload, 2733 int *tlv_payload_len) 2734 { 2735 tlv_payload[0] = 0; /* TLV type: */ 2736 tlv_payload[1] = bcmPTPTlvTypeRequestUnicastTransmission; 2737 tlv_payload[2] = 0; /* Length: */ 2738 tlv_payload[3] = 6; 2739 tlv_payload[4] = (type << 4); 2740 tlv_payload[5] = interval; 2741 _bcm_ptp_uint32_write(&tlv_payload[6], duration); 2742 2743 *tlv_payload_len = 10; 2744 2745 return BCM_E_NONE; 2746 } 2747 2748 2749 /* 2750 * Function: 2751 * _bcm_ptp_construct_signaling_cancel_tlv 2752 * Purpose: 2753 * Construct the TLV for a signaling msg cancel unicast transmission 2754 * Parameters: 2755 * Returns: 2756 * BCM_E_XXX 2757 * Notes: 2758 */ 2759 int 2760 _bcm_ptp_construct_signaling_cancel_tlv( 2761 int type, 2762 uint8* tlv_payload, 2763 int *tlv_payload_len) 2764 { 2765 tlv_payload[0] = 0; /* TLV type: */ 2766 tlv_payload[1] = bcmPTPTlvTypeCancelUnicastTransmission; 2767 tlv_payload[2] = 0; /* Length: */ 2768 tlv_payload[3] = 2; 2769 tlv_payload[4] = (type << 4); 2770 tlv_payload[5] = 0; 2771 2772 *tlv_payload_len = 6; 2773 2774 return BCM_E_NONE; 2775 } 2776 2777 2778 /* 2779 * Function: 2780 * _bcm_ptp_construct_signaling_grant_tlv 2781 * Purpose: 2782 * Construct the TLV for a signaling msg grant unicast transmission 2783 * Parameters: 2784 * Returns: 2785 * BCM_E_XXX 2786 * Notes: 2787 */ 2788 int 2789 _bcm_ptp_construct_signaling_grant_tlv( 2790 int type, 2791 int interval, 2792 unsigned duration, 2793 int invite_renewal, 2794 uint8* tlv_payload, 2795 int *tlv_payload_len) 2796 { 2797 tlv_payload[0] = 0; /* TLV type: */ 2798 tlv_payload[1] = bcmPTPTlvTypeGrantUnicastTransmission; 2799 tlv_payload[2] = 0; /* Length: */ 2800 tlv_payload[3] = 8; 2801 tlv_payload[4] = (type << 4); 2802 tlv_payload[5] = interval; 2803 _bcm_ptp_uint32_write(&tlv_payload[6], duration); 2804 tlv_payload[10] = 0; 2805 tlv_payload[11] = invite_renewal; 2806 2807 *tlv_payload_len = 12; 2808 return BCM_E_NONE; 2809 } 2810 2811 2812 /* 2813 * Function: 2814 * _bcm_ptp_construct_signaling_ack_cancel_tlv 2815 * Purpose: 2816 * Construct the TLV for a signaling msg acknowledge cancel unicast transmission 2817 * Parameters: 2818 * Returns: 2819 * BCM_E_XXX 2820 * Notes: 2821 */ 2822 int 2823 _bcm_ptp_construct_signaling_ack_cancel_tlv( 2824 int type, 2825 uint8* tlv_payload, 2826 int *tlv_payload_len) 2827 { 2828 tlv_payload[0] = 0; /* TLV type: */ 2829 tlv_payload[1] = bcmPTPTlvTypeAckCancelUnicastTransmission; 2830 tlv_payload[2] = 0; /* Length: */ 2831 tlv_payload[3] = 2; 2832 tlv_payload[4] = (type << 4); 2833 tlv_payload[5] = 0; 2834 2835 *tlv_payload_len = 6; 2836 2837 return BCM_E_NONE; 2838 } 2839 2840 2841 /* 2842 * Function: 2843 * _bcm_ptp_signaling_message_append_tlv 2844 * Purpose: 2845 * Append a TLV to a PTP signaling message. 2846 * Parameters: 2847 * msg (IN/OUT) - PTP signaling message. 2848 * msgLength (IN/OUT) - PTP signaling message length. 2849 * tlv (IN) - Signaling message TLV. 2850 * tlvLength (IN) - Signaling message TLV length. 2851 * Returns: 2852 * BCM_E_XXX - Function status. 2853 * Notes: 2854 */ 2855 int 2856 _bcm_ptp_signaling_message_append_tlv( 2857 uint8 *msg, 2858 int *msgLength, 2859 uint8 *tlv, 2860 int tlvLength) 2861 { 2862 /* Argument checking and error handling. */ 2863 if (NULL == tlv) { 2864 return BCM_E_FAIL; 2865 } 2866 2867 if ((*msgLength != (int)_bcm_ptp_uint16_read(msg + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS)) || 2868 (tlvLength != (int)_bcm_ptp_uint16_read(tlv + PTP_TLVHDR_LEN_OFFSET_OCTETS) + 4)) { 2869 return BCM_E_PARAM; 2870 } 2871 2872 /* Append TLV. */ 2873 sal_memcpy(msg + *msgLength, tlv, tlvLength); 2874 2875 /* Update message length. */ 2876 *msgLength += tlvLength; 2877 _bcm_ptp_uint16_write(msg + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, (uint16)*msgLength); 2878 2879 return BCM_E_NONE; 2880 } 2881 2882 2883 /* 2884 * Function: 2885 * _bcm_ptp_tunnel_queue_init 2886 * Purpose: 2887 * Initializes the outgoing tunneled message queue 2888 * Parameters: 2889 * unit - (IN) Unit number. 2890 * ptp_id - (IN) PTP stack ID. 2891 * Returns: 2892 * BCM_E_XXX - Function status. 2893 * Notes: 2894 */ 2895 int 2896 _bcm_ptp_tunnel_queue_init( 2897 int unit, 2898 bcm_ptp_stack_id_t ptp_id) 2899 { 2900 _bcm_ptp_tunnel_queue_t *queue; 2901 int rv; 2902 2903 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 2904 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 2905 return rv; 2906 } 2907 2908 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue; 2909 2910 if (!queue->lock) { 2911 queue->lock = _bcm_ptp_mutex_create("ptp.tunnel"); 2912 } 2913 2914 if (shr_rdpc_callback_created(&queue->rdpc) == BCM_E_INIT) { 2915 /* RDPC (and associated lock) is left in place on cleanup, so only create it once */ 2916 shr_rdpc_callback_create(&queue->rdpc, &send_pending_tunneled); 2917 } 2918 2919 queue->head = 0; 2920 queue->tail = 0; 2921 2922 return BCM_E_NONE; 2923 } 2924 2925 2926 /* 2927 * Function: 2928 * _bcm_ptp_tunnel_queue_cleanup 2929 * Purpose: 2930 * Cleans up the outgoing tunneled message queue for shutdown 2931 * Parameters: 2932 * unit - (IN) Unit number. 2933 * ptp_id - (IN) PTP stack ID. 2934 * Returns: 2935 * BCM_E_XXX - Function status. 2936 * Notes: 2937 */ 2938 int 2939 _bcm_ptp_tunnel_queue_cleanup( 2940 int unit, 2941 bcm_ptp_stack_id_t ptp_id) 2942 { 2943 _bcm_ptp_tunnel_queue_t *queue; 2944 int rv; 2945 2946 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 2947 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 2948 return rv; 2949 } 2950 2951 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue; 2952 2953 shr_rdpc_callback_stop(&queue->rdpc); 2954 2955 PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US); 2956 queue->head = 0; 2957 queue->tail = 0; 2958 PTP_MUTEX_GIVE(queue->lock); 2959 2960 return BCM_E_NONE; 2961 } 2962 2963 /* 2964 * Function: 2965 * _bcm_ptp_tunnel_queue_add 2966 * Purpose: 2967 * Adds a packet to the outgoing tunnel queue 2968 * Parameters: 2969 * unit - (IN) Unit number. 2970 * ptp_id - (IN) PTP stack ID. 2971 * clock_idx - (IN) PTP clock index 2972 * tunnel_type - (IN) Type of tunneling 2973 * hdr_len - (IN) Length of header 2974 * hdr - (IN) Header data 2975 * data_len - (IN) Length of packet 2976 * data - (IN) packet data 2977 * Returns: 2978 * BCM_E_XXX - Function status. 2979 * Notes: 2980 */ 2981 int 2982 _bcm_ptp_tunnel_queue_add( 2983 int unit, 2984 bcm_ptp_stack_id_t ptp_id, 2985 int clock_idx, 2986 int tunnel_type, 2987 unsigned hdr_len, 2988 uint8 *hdr, 2989 unsigned data_len, 2990 uint8 *data) 2991 { 2992 const int pkt_overhead = 4; /* each entry has 1 byte type, 1 byte clock index, 16 bit length */ 2993 int len = hdr_len + data_len; 2994 int padded_len = (len + 3) & 0xfffc; 2995 int rv; 2996 _bcm_ptp_tunnel_queue_t *queue; 2997 2998 2999 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3000 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3001 return rv; 3002 } 3003 3004 /* If packet is too large for buffer, just exit */ 3005 if (len > padded_len || 3006 padded_len + 2 * pkt_overhead > BCM_PTP_TUNNEL_QUEUE_SIZE) { 3007 return BCM_E_MEMORY; 3008 } 3009 3010 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue; 3011 PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US); 3012 3013 /* If this packet won't fit in the remaining space before the end of the buffer, reset the head 3014 we need space for overhead & packet, plus enough space for an 3015 extra overhead to indicate that the buffer has wrapped */ 3016 if (queue->head + pkt_overhead + padded_len + pkt_overhead > BCM_PTP_TUNNEL_QUEUE_SIZE) { 3017 queue->buf[queue->head] = 0; 3018 queue->head = 0; 3019 } 3020 3021 if (queue->head < queue->tail && 3022 queue->head + pkt_overhead + padded_len + pkt_overhead > queue->tail) { 3023 /* packet won't fit */ 3024 PTP_MUTEX_RELEASE_RETURN(queue->lock, BCM_E_MEMORY); 3025 } 3026 queue->buf[queue->head] = tunnel_type; 3027 queue->buf[queue->head + 1] = clock_idx; 3028 _bcm_ptp_uint16_write(queue->buf + queue->head + 2, (uint16)len); 3029 sal_memcpy(queue->buf + queue->head + pkt_overhead, hdr, hdr_len); 3030 sal_memcpy(queue->buf + queue->head + pkt_overhead + hdr_len, data, data_len); 3031 queue->head += pkt_overhead + padded_len; 3032 3033 PTP_MUTEX_GIVE(queue->lock); 3034 3035 rv = shr_rdpc_callback_start(&queue->rdpc, 0, INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(0), INT_TO_PTR(0)); 3036 3037 return rv; 3038 } 3039 3040 3041 /* 3042 * Function: 3043 * send_pending_tunneled 3044 * Purpose: 3045 * Send any queued messages to be tunneled 3046 * Parameters: 3047 * arg_unit - (IN) Unit number (as void**). 3048 * arg_ptp_id - (IN) PTP stack ID (as void**). 3049 * unused1 - (IN) Unused. 3050 * unused2 - (IN) Unused. 3051 * Returns: 3052 * time interval before next call 3053 * Notes: 3054 */ 3055 static sal_usecs_t send_pending_tunneled(void **arg_unit, void **arg_ptp_id, void **unused1, void **unused2) 3056 { 3057 int unit = PTR_TO_INT(*arg_unit); 3058 bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id); 3059 int clock_idx, tunnel_type; 3060 int len, padded_len; 3061 3062 int rv; 3063 _bcm_ptp_tunnel_queue_t *queue; 3064 static uint8 buf[PTP_MGMTMSG_TOTAL_SIZE_OCTETS]; /* 1500 bytes */ 3065 3066 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3067 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3068 return 0; 3069 } 3070 3071 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue; 3072 3073 PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US); 3074 3075 if (queue->buf[queue->tail] == 0) { 3076 /* zero 'type' signals that it is time to wrap */ 3077 queue->tail = 0; 3078 } 3079 3080 if (queue->tail == queue->head) { 3081 /* nothing in queue */ 3082 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, "PTP tunnel queue unexpectedly empty\n"))); 3083 PTP_MUTEX_RELEASE_RETURN(queue->lock, 0); 3084 } 3085 tunnel_type = queue->buf[queue->tail]; 3086 clock_idx = queue->buf[queue->tail + 1]; 3087 len = _bcm_ptp_uint16_read(queue->buf + queue->tail + 2); 3088 sal_memcpy(buf, queue->buf + queue->tail + 4, len); 3089 padded_len = (len + 3) & 0xfffc; 3090 queue->tail += 4 + padded_len; 3091 PTP_MUTEX_GIVE(queue->lock); 3092 3093 if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message(unit, ptp_id, clock_idx, tunnel_type, 0, 0, len, buf))) { 3094 LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, "PTP delayed tunnel send failed\n"))); 3095 } 3096 return 0; 3097 } 3098 /* 3099 * Function: 3100 * _bcm_ptp_timestamp_queue_init 3101 * Purpose: 3102 * Initializes the timestamp message queue 3103 * Parameters: 3104 * unit - (IN) Unit number. 3105 * ptp_id - (IN) PTP stack ID. 3106 * Returns: 3107 * BCM_E_XXX - Function status. 3108 * Notes: 3109 */ 3110 int 3111 _bcm_ptp_timestamp_queue_init( 3112 int unit, 3113 bcm_ptp_stack_id_t ptp_id) 3114 { 3115 _bcm_ptp_timestamp_queue_t *queue; 3116 int rv; 3117 3118 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3119 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3120 return rv; 3121 } 3122 3123 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue; 3124 3125 if (!queue->lock) { 3126 queue->lock = _bcm_ptp_mutex_create("ptp.tsqueue"); 3127 if (queue->lock == NULL) { 3128 bsl_printf("_bcm_ptp_timestamp_queue_init error\n"); 3129 return BCM_E_MEMORY; 3130 } 3131 } 3132 3133 queue->ts_list = (_bcm_ptp_timestamp_list_t *)sal_alloc(BCM_PTP_TIMESTAMP_QUEUE_SIZE * sizeof(_bcm_ptp_timestamp_list_t), 3134 "PTP Timestamp List"); 3135 sal_memset(queue->ts_list, 0, sizeof(_bcm_ptp_timestamp_list_t) * BCM_PTP_TIMESTAMP_QUEUE_SIZE); 3136 3137 bsl_printf("_bcm_ptp_timestamp_queue_t initiatilzed...................... \n"); 3138 3139 if (shr_rdpc_callback_created(&queue->rdpc) == BCM_E_INIT) { 3140 /* RDPC (and associated lock) is left in place on cleanup, so only create it once */ 3141 shr_rdpc_callback_create(&queue->rdpc, &send_pending_timestamp); 3142 } 3143 3144 queue->head = -1; 3145 queue->tail = -1; 3146 3147 return BCM_E_NONE; 3148 } 3149 3150 3151 /* 3152 * Function: 3153 * _bcm_ptp_timestamp_queue_cleanup 3154 * Purpose: 3155 * Cleans up the outgoing timestamp queue for shutdown 3156 * Parameters: 3157 * unit - (IN) Unit number. 3158 * ptp_id - (IN) PTP stack ID. 3159 * Returns: 3160 * BCM_E_XXX - Function status. 3161 * Notes: 3162 */ 3163 int 3164 _bcm_ptp_timestamp_queue_cleanup( 3165 int unit, 3166 bcm_ptp_stack_id_t ptp_id) 3167 { 3168 _bcm_ptp_timestamp_queue_t *queue; 3169 _bcm_ptp_timestamp_list_t *tsList; 3170 int idx = 0; 3171 int rv; 3172 3173 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3174 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3175 return rv; 3176 } 3177 3178 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue; 3179 3180 shr_rdpc_callback_stop(&queue->rdpc); 3181 3182 PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US); 3183 3184 tsList = queue->ts_list; 3185 3186 bsl_printf("_bcm_ptp_timestamp_queue_t cleanup...................... \n"); 3187 3188 while(idx < BCM_PTP_TIMESTAMP_QUEUE_SIZE) { 3189 if((tsList +idx)->data != NULL) { 3190 sal_free((void *)((tsList + idx)->data)); 3191 (tsList + idx)->data = NULL; 3192 } 3193 idx++; 3194 } 3195 queue->head = -1; 3196 queue->tail = -1; 3197 sal_free((void *)tsList); 3198 queue->ts_list = NULL; 3199 3200 PTP_MUTEX_GIVE(queue->lock); 3201 3202 return BCM_E_NONE; 3203 } 3204 3205 /* 3206 * Function: 3207 * _bcm_ptp_timestamp_queue_add 3208 * Purpose: 3209 * Adds a packet to the outgoing timestamp queue 3210 * Parameters: 3211 * unit - (IN) Unit number. 3212 * ptp_id - (IN) PTP stack ID. 3213 * clock_idx - (IN) PTP clock index 3214 * tunnel_type - (IN) Type of tunneling 3215 * hdr_len - (IN) Length of header 3216 * hdr - (IN) Header data 3217 * data_len - (IN) Length of packet 3218 * data - (IN) packet data 3219 * Returns: 3220 * BCM_E_XXX - Function status. 3221 * Notes: 3222 */ 3223 int 3224 _bcm_ptp_timestamp_queue_add( 3225 int unit, 3226 bcm_ptp_stack_id_t ptp_id, 3227 int clock_idx, 3228 unsigned data_len, 3229 uint8 *data) 3230 { 3231 int rv; 3232 _bcm_ptp_timestamp_queue_t *queue; 3233 _bcm_ptp_timestamp_node_t *node; 3234 _bcm_ptp_timestamp_list_t *tsList; 3235 3236 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3237 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3238 return rv; 3239 } 3240 3241 /* If packet is too large for buffer, just exit */ 3242 if (data_len > sizeof(_bcm_ptp_timestamp_node_t)) { 3243 return BCM_E_MEMORY; 3244 } 3245 3246 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue; 3247 3248 if (queue->lock == NULL) { 3249 bsl_printf("_bcm_ptp_timestamp_queue_add error\n"); 3250 return BCM_E_MEMORY; 3251 } 3252 3253 PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US); 3254 3255 tsList = queue->ts_list; 3256 3257 /* If this is last node set it to null and Wrap the list */ 3258 if ((queue->head == 0 && queue->tail == (BCM_PTP_TIMESTAMP_QUEUE_SIZE -1)) || 3259 queue->tail == (queue->head - 1) % (BCM_PTP_TIMESTAMP_QUEUE_SIZE -1)) { 3260 #ifdef PTP_EXT_SERVO_DEBUG 3261 bsl_printf("Queue FULL %s,%d\n",__FUNCTION__,__LINE__); 3262 #endif 3263 } else { 3264 /* Copy the Data in Node */ 3265 node = (_bcm_ptp_timestamp_node_t *)sal_alloc(sizeof(_bcm_ptp_timestamp_node_t), "PTP Timestamp node"); 3266 if (node == NULL) { 3267 PTP_MUTEX_GIVE(queue->lock); 3268 bsl_printf("%s,%d\n",__FUNCTION__,__LINE__); 3269 return BCM_E_MEMORY; 3270 } 3271 sal_memcpy(node, data, data_len); 3272 3273 if (queue->head == -1) { 3274 queue->head = 0; 3275 queue->tail = 0; 3276 } else if (queue->tail == BCM_PTP_TIMESTAMP_QUEUE_SIZE - 1 && queue->head != 0) { 3277 queue->tail = 0; 3278 } else { 3279 queue->tail++; 3280 } 3281 (tsList + queue->tail)->data = node; 3282 } 3283 3284 PTP_MUTEX_GIVE(queue->lock); 3285 3286 rv = shr_rdpc_callback_start(&queue->rdpc, 0, INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(0), INT_TO_PTR(0)); 3287 3288 return rv; 3289 } 3290 3291 /* 3292 * Function: 3293 * send_pending_timestamp 3294 * Purpose: 3295 * Send any queued timestamps to servo 3296 * Parameters: 3297 * arg_unit - (IN) Unit number (as void**). 3298 * t 3299 * q 3300 * arg_ptp_id - (IN) PTP stack ID (as void**). 3301 * unused1 - (IN) Unused. 3302 * unused2 - (IN) Unused. 3303 * Returns: 3304 * time interval before next call 3305 * Notes: 3306 */ 3307 static sal_usecs_t send_pending_timestamp(void **arg_unit, void **arg_ptp_id, void **unused1, void **unused2) 3308 { 3309 int unit = PTR_TO_INT(*arg_unit); 3310 bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id); 3311 _bcm_ptp_timestamp_list_t *tsList; 3312 3313 int rv; 3314 _bcm_ptp_timestamp_queue_t *queue; 3315 3316 3317 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 3318 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 3319 return 0; 3320 } 3321 3322 queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue; 3323 3324 PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US); 3325 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3326 mbox_tsevent_stats.ts_rpc_livecount++; 3327 #endif 3328 3329 tsList = queue->ts_list; 3330 while(queue->head != -1 && (tsList + queue->head)->data != NULL) 3331 { 3332 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3333 _bcm_ptp_ext_servo_event_t event_type; 3334 int num_TS; 3335 uint8 *ptr = NULL; 3336 bcm_ptp_port_identity_t master_portId, best_master_portId; 3337 bcm_ptp_clock_port_address_t master_portaddr; 3338 bcm_ptp_timestamp_t first_TS = { 0, 0 }; 3339 uint32 int_usec=0; 3340 int8 log_interval=10; 3341 int is_unicast=0; 3342 int i = 0; 3343 uint64 temp_ts = 0; 3344 bcm_ptp_clock_info_t *clock_info; 3345 bcm_ptp_port_identity_t clk_portid; 3346 3347 3348 mbox_tsevent_stats.event_dequeued++; 3349 3350 event_type = _bcm_ptp_uint16_read((uint8 *)(tsList + queue->head)->data); 3351 3352 switch ((_bcm_ptp_ext_servo_event_t)event_type) { 3353 case _bcm_ptp_ext_servo_downlink_ts_event: 3354 case _bcm_ptp_ext_servo_uplink_ts_event: 3355 #if 0 3356 node = (_bcm_ptp_timestamp_node_t *) ((int8 *)(tsList + queue->head)->data + sizeof(uint16)); 3357 bsl_printf("clockIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",node->portId.clock_identity[0], 3358 node->portId.clock_identity[1], 3359 node->portId.clock_identity[2], 3360 node->portId.clock_identity[3], 3361 node->portId.clock_identity[4], 3362 node->portId.clock_identity[5], 3363 node->portId.clock_identity[6], 3364 node->portId.clock_identity[7]); 3365 bsl_printf("portNumber : %u\n",node->portId.port_number); 3366 bsl_printf("msgSeqId : %d\n",node->msgSeqId); 3367 bsl_printf("flags : %d\n",node->flags); 3368 bsl_printf("numTs : %d\n",node->numTs); 3369 bsl_printf("tsType : %d\n",node->tsType); 3370 bsl_printf("DL TS: \n"); 3371 for(idx =0; idx < node->numTs; idx++) 3372 bsl_printf("%lld ", (long long int)node->tsDiff[idx]); 3373 bsl_printf("\n"); 3374 #endif 3375 ptr = ((uint8 *)(tsList + queue->head)->data + sizeof(uint16)); 3376 3377 #ifdef PTP_EXT_SERVO_DEBUG 3378 bsl_printf(" _bcm_ptp_ext_servo_up/downlink_ts_event:: \n"); 3379 _bcm_ptp_dump_hex(ptr, 320, 0); 3380 #endif 3381 sal_memcpy(&master_portId.clock_identity, ptr, sizeof(bcm_ptp_clock_identity_t)); 3382 master_portId.port_number = _bcm_ptp_uint16_read(ptr+8); 3383 num_TS = _bcm_ptp_uint16_read(ptr+14); 3384 3385 log_interval= ptr[16]; 3386 int_usec = _bcm_ptp_servo_usecintv_get(log_interval); 3387 3388 first_TS.seconds = _bcm_ptp_uint64_read(ptr+20); 3389 first_TS.nanoseconds = _bcm_ptp_uint32_read(ptr+28); 3390 3391 LOG_DEBUG(BSL_LS_BCM_PTP, 3392 (BSL_META_U(unit, "[UL:%d] master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] numTs[%d] log_int[%d] first_TS[0x%016llx / %llds.%uns]\n"), 3393 event_type, 3394 master_portId.clock_identity[0], master_portId.clock_identity[1], master_portId.clock_identity[2], master_portId.clock_identity[3], 3395 master_portId.clock_identity[4], master_portId.clock_identity[5], master_portId.clock_identity[6], master_portId.clock_identity[7], 3396 master_portId.port_number, num_TS, log_interval, 3397 (long long signed int)first_TS.seconds, 3398 (long long signed int)first_TS.seconds, first_TS.nanoseconds)); 3399 3400 #ifdef BCM_PTP_EXT_SERVO_ABS_TS_SUPPORT 3401 /* absolute timestamps */ 3402 if (event_type == _bcm_ptp_ext_servo_downlink_ts_event) 3403 _bcm_ptp_servo_AddFullTimestamps(unit, ptp_id, 0, &master_portId, num_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_downlink, int_usec); 3404 else 3405 _bcm_ptp_servo_AddFullTimestamps(unit, ptp_id, 0, &master_portId, num_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_uplink, int_usec); 3406 #else 3407 /* timestamp differences */ 3408 if (event_type == _bcm_ptp_ext_servo_downlink_ts_event) { 3409 rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &master_portId, num_TS, first_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_downlink, int_usec); 3410 } else { 3411 rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &master_portId, num_TS, first_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_uplink, int_usec); 3412 } 3413 3414 #endif /* BCM_PTP_EXT_SERVO_ABS_TS_SUPPORT */ 3415 break; 3416 3417 case _bcm_ptp_ext_servo_master_change_event: 3418 3419 clock_info = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[0].clock_info; 3420 3421 sal_memcpy(&clk_portid.clock_identity, &clock_info->clock_identity, sizeof(bcm_ptp_clock_identity_t)); 3422 clk_portid.port_number = 0; 3423 3424 ptr = ((uint8 *)(tsList + queue->head)->data + sizeof(uint16)); 3425 #ifdef PTP_EXT_SERVO_DEBUG 3426 bsl_printf(" _bcm_ptp_ext_servo_master_change_event: \n"); 3427 _bcm_ptp_dump_hex(ptr, 64, 0); 3428 #endif 3429 LOG_INFO(BSL_LS_BCM_PTP, 3430 (BSL_META_U(unit, " _bcm_ptp_ext_servo_master_change_event: \n"))); 3431 mbox_tsevent_stats.event_master_change++; 3432 3433 /* Retrieve best master port Id */ 3434 sal_memcpy(&best_master_portId.clock_identity, ptr+13, sizeof(bcm_ptp_clock_identity_t)); 3435 best_master_portId.port_number = _bcm_ptp_uint16_read(ptr+21); 3436 3437 LOG_INFO(BSL_LS_BCM_PTP, 3438 (BSL_META_U(unit, "best_master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] \n"), 3439 best_master_portId.clock_identity[0], best_master_portId.clock_identity[1], 3440 best_master_portId.clock_identity[2], best_master_portId.clock_identity[3], 3441 best_master_portId.clock_identity[4], best_master_portId.clock_identity[5], 3442 best_master_portId.clock_identity[6], best_master_portId.clock_identity[7], 3443 best_master_portId.port_number)); 3444 3445 if (g_apts_enabled) 3446 { 3447 bcm_ptp_clock_apts_mode_t old_op_mode = g_apts_current_op_mode; 3448 3449 if (_bcm_ptp_peer_portid_compare(&best_master_portId, &clk_portid)) { 3450 /* Set PTP source as unavailable */ 3451 g_apts_current_source_state &= _bcm_ptp_apts_avail_gps_synce; 3452 _bcm_ptp_apts_update_current_mode(); 3453 3454 if (((old_op_mode == bcmPtpClockAptsModePtpPtp) || (old_op_mode == bcmPtpClockAptsModeSyncEPtp)) && 3455 ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps))) 3456 { 3457 /* Switched from PTP to GPS - update servo with GPS as best master */ 3458 if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_gps_port_id))) 3459 { 3460 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS"); 3461 } 3462 } 3463 } else { 3464 /* Set PTP source as available */ 3465 g_apts_current_source_state |= _bcm_ptp_apts_avail_ptp; 3466 _bcm_ptp_apts_update_current_mode(); 3467 3468 if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps)) 3469 { 3470 /* GPS is best master currently. Do not update IDT servo */ 3471 LOG_INFO(BSL_LS_BCM_PTP, 3472 (BSL_META_U(unit, "[APTS]: PTP best master changed but current mode requires servo to track GPS"))); 3473 } else if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &best_master_portId))) { 3474 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update()"); 3475 } 3476 } 3477 g_ptp_best_master_portId = best_master_portId; 3478 } 3479 else if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &best_master_portId))) { 3480 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update()"); 3481 } 3482 break; 3483 3484 case _bcm_ptp_ext_servo_master_avail_event: 3485 case _bcm_ptp_ext_servo_master_unavail_event: 3486 3487 ptr = ((uint8 *)(tsList + queue->head)->data + sizeof(uint16)); 3488 #ifdef PTP_EXT_SERVO_DEBUG 3489 bsl_printf(" _bcm_ptp_ext_servo_master_avail/unavail_event \n"); 3490 _bcm_ptp_dump_hex(ptr, 64, 0); 3491 #endif 3492 3493 /* Retrieve master port Id */ 3494 sal_memcpy(&master_portId.clock_identity, ptr+13, sizeof(bcm_ptp_clock_identity_t)); 3495 master_portId.port_number = _bcm_ptp_uint16_read(ptr+21); 3496 3497 is_unicast = ptr[24]; 3498 3499 master_portaddr.addr_type = ptr[25]; 3500 memset(master_portaddr.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE); 3501 memcpy(master_portaddr.address, ptr+28, BCM_PTP_MAX_NETW_ADDR_SIZE); 3502 3503 /* Retrieve best master port Id */ 3504 sal_memcpy(&best_master_portId.clock_identity, ptr+48, sizeof(bcm_ptp_clock_identity_t)); 3505 best_master_portId.port_number = _bcm_ptp_uint16_read(ptr+56); 3506 3507 LOG_INFO(BSL_LS_BCM_PTP, 3508 (BSL_META_U(unit, " %s \n"), 3509 (event_type == _bcm_ptp_ext_servo_master_avail_event)? "_bcm_ptp_ext_servo_master_avail_event:":"_bcm_ptp_ext_servo_master_unavail_event:")); 3510 LOG_INFO(BSL_LS_BCM_PTP, 3511 (BSL_META_U(unit, "master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] unicast[%d]\n"), 3512 master_portId.clock_identity[0], master_portId.clock_identity[1], 3513 master_portId.clock_identity[2], master_portId.clock_identity[3], 3514 master_portId.clock_identity[4], master_portId.clock_identity[5], 3515 master_portId.clock_identity[6], master_portId.clock_identity[7], 3516 master_portId.port_number, is_unicast)); 3517 LOG_INFO(BSL_LS_BCM_PTP, 3518 (BSL_META_U(unit, "master_portAddr: [%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x : AddrType:%d]\n"), 3519 master_portaddr.address[0], master_portaddr.address[1],master_portaddr.address[2], master_portaddr.address[3], 3520 master_portaddr.address[4], master_portaddr.address[5],master_portaddr.address[6], master_portaddr.address[7], 3521 master_portaddr.address[8], master_portaddr.address[9],master_portaddr.address[10], master_portaddr.address[11], 3522 master_portaddr.address[12], master_portaddr.address[13],master_portaddr.address[14], master_portaddr.address[5], 3523 master_portaddr.addr_type)); 3524 LOG_INFO(BSL_LS_BCM_PTP, 3525 (BSL_META_U(unit, "best_master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] \n"), 3526 best_master_portId.clock_identity[0], best_master_portId.clock_identity[1], 3527 best_master_portId.clock_identity[2], best_master_portId.clock_identity[3], 3528 best_master_portId.clock_identity[4], best_master_portId.clock_identity[5], 3529 best_master_portId.clock_identity[6], best_master_portId.clock_identity[7], 3530 best_master_portId.port_number)); 3531 3532 if (event_type == _bcm_ptp_ext_servo_master_avail_event) { 3533 mbox_tsevent_stats.event_master_add++; 3534 if (BCM_FAILURE(rv = _bcm_ptp_servo_master_add(unit, ptp_id, 0, PTP_EXT_SERVO_MSTR_INST_UNKNOWN, 3535 &master_portId, 3536 &master_portaddr, is_unicast, 127))) { 3537 PTP_ERROR_FUNC("_bcm_ptp_servo_master_add()"); 3538 } 3539 } else if(event_type == _bcm_ptp_ext_servo_master_unavail_event) { 3540 mbox_tsevent_stats.event_master_remove++; 3541 if (BCM_FAILURE(rv = _bcm_ptp_servo_master_remove(unit, ptp_id, 0,PTP_EXT_SERVO_MSTR_INST_UNKNOWN, 3542 is_unicast, 3543 &master_portId, 3544 &best_master_portId, &master_portaddr))) { 3545 PTP_ERROR_FUNC("_bcm_ptp_servo_master_remove()"); 3546 } 3547 } 3548 break; 3549 case _bcm_ptp_ext_servo_gps_avail_event: 3550 case _bcm_ptp_ext_servo_gps_unavail_event: 3551 is_unicast = 1; 3552 3553 LOG_INFO(BSL_LS_BCM_PTP, 3554 (BSL_META_U(unit, " %s \n"), 3555 (event_type == _bcm_ptp_ext_servo_gps_avail_event)? "_bcm_ptp_ext_servo_gps_avail_event:":"_bcm_ptp_ext_servo_gps_unavail_event:")); 3556 3557 LOG_INFO(BSL_LS_BCM_PTP, 3558 (BSL_META_U(unit, "gps master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] unicast[%d]\n"), 3559 g_gps_port_id.clock_identity[0], g_gps_port_id.clock_identity[1], 3560 g_gps_port_id.clock_identity[2], g_gps_port_id.clock_identity[3], 3561 g_gps_port_id.clock_identity[4], g_gps_port_id.clock_identity[5], 3562 g_gps_port_id.clock_identity[6], g_gps_port_id.clock_identity[7], 3563 g_gps_port_id.port_number, is_unicast)); 3564 LOG_INFO(BSL_LS_BCM_PTP, 3565 (BSL_META_U(unit, "gps master_portAddr: [%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x : AddrType:%d]\n"), 3566 g_gps_port_address.address[0], g_gps_port_address.address[1],g_gps_port_address.address[2], g_gps_port_address.address[3], 3567 g_gps_port_address.address[4], g_gps_port_address.address[5],g_gps_port_address.address[6], g_gps_port_address.address[7], 3568 g_gps_port_address.address[8], g_gps_port_address.address[9],g_gps_port_address.address[10], g_gps_port_address.address[11], 3569 g_gps_port_address.address[12], g_gps_port_address.address[13],g_gps_port_address.address[14], g_gps_port_address.address[5], 3570 g_gps_port_address.addr_type)); 3571 3572 if (event_type == _bcm_ptp_ext_servo_gps_avail_event) 3573 { 3574 if (BCM_FAILURE(rv = _bcm_ptp_servo_master_add(unit, ptp_id, 0, PTP_EXT_SERVO_MSTR_INST_UNKNOWN, 3575 &g_gps_port_id, 3576 &g_gps_port_address, is_unicast, 127))) { 3577 PTP_ERROR_FUNC("_bcm_ptp_servo_master_add() - GPS"); 3578 } 3579 3580 g_apts_current_source_state |= _bcm_ptp_apts_avail_gps; 3581 _bcm_ptp_apts_update_current_mode(); 3582 3583 if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps)) 3584 { 3585 if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_gps_port_id))){ 3586 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS"); 3587 } 3588 } 3589 } else if(event_type == _bcm_ptp_ext_servo_gps_unavail_event) 3590 { 3591 if (BCM_FAILURE(rv = _bcm_ptp_servo_master_remove(unit, ptp_id, 0,PTP_EXT_SERVO_MSTR_INST_UNKNOWN, 3592 is_unicast, 3593 &g_gps_port_id, 3594 &g_gps_port_id, &g_gps_port_address))) { 3595 PTP_ERROR_FUNC("_bcm_ptp_servo_master_remove() - GPS"); 3596 } 3597 3598 g_apts_current_source_state &= _bcm_ptp_apts_avail_ptp_synce; 3599 _bcm_ptp_apts_update_current_mode(); 3600 3601 if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEPtp) || (g_apts_current_op_mode == bcmPtpClockAptsModePtpPtp)) 3602 { 3603 if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_ptp_best_master_portId))){ 3604 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS is down. Switching to PTP"); 3605 } 3606 } 3607 } 3608 break; 3609 case _bcm_ptp_ext_servo_gps_ts_event: 3610 if (g_apts_current_source_state & _bcm_ptp_apts_avail_gps) 3611 { 3612 /* reference tracker should be configured for GPS by now. Start sending ts diffs */ 3613 ptr = ((uint8 *)(tsList + queue->head)->data + sizeof(uint16)); 3614 3615 temp_ts = _bcm_ptp_uint64_read(ptr); 3616 ptr += 8; 3617 3618 first_TS.seconds = (temp_ts/1000000000); 3619 first_TS.nanoseconds = 0; 3620 3621 num_TS =_bcm_ptp_uint16_read(ptr); 3622 ptr+= 2; 3623 3624 for (i = 0; i < num_TS; i++) 3625 { 3626 gps_diff_ts[i] = _bcm_ptp_uint64_read(ptr) - temp_ts; 3627 ptr += 8; 3628 temp_ts = (temp_ts + 10000000) % ((uint64)1 << 48); 3629 } 3630 3631 int_usec = 1000000; 3632 LOG_DEBUG(BSL_LS_BCM_PTP, 3633 (BSL_META_U(unit, "GPS: numTs[%d] log_int[%d] first_TS[0x%016llx / %llds.%uns]\n"), 3634 num_TS, log_interval, 3635 (long long signed int)first_TS.seconds, 3636 (long long signed int)first_TS.seconds, first_TS.nanoseconds)); 3637 3638 /* timestamp differences */ 3639 rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &g_gps_port_id, num_TS, first_TS, (uint8 *)gps_diff_ts, _bcm_ptp_ts_type_downlink, int_usec); 3640 rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &g_gps_port_id, num_TS, first_TS, (uint8 *)gps_diff_ts, _bcm_ptp_ts_type_uplink, int_usec); 3641 } 3642 break; 3643 default: 3644 mbox_tsevent_stats.event_unknown++; 3645 break; 3646 } 3647 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 3648 sal_free((void *)((tsList + queue->head)->data)); 3649 (tsList + queue->head)->data = NULL; 3650 if (queue->head == queue->tail) { 3651 queue->head = queue->tail = -1; 3652 } else if (queue->head == BCM_PTP_TIMESTAMP_QUEUE_SIZE -1) { 3653 queue->head = 0; 3654 } else 3655 queue->head++; 3656 } 3657 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 3658 mbox_tsevent_stats.ts_rpc_livecount--; 3659 #endif 3660 3661 PTP_MUTEX_GIVE(queue->lock); 3662 3663 return 0; 3664 } 3665 3666 3667 #endif /* defined(INCLUDE_PTP)*/