esmc.c (34173B)
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: esmc.c 8 * 9 * Purpose: Ethernet Synchronization Messaging Channel (ESMC) infrastructure. 10 * 11 * Functions: 12 * bcm_esmc_init 13 * bcm_esmc_rx 14 * bcm_common_esmc_tx 15 * bcm_esmc_pdu_tx_dnx 16 * bcm_esmc_rx_callback_register 17 * bcm_esmc_rx_callback_unregister 18 * bcm_esmc_tunnel_get 19 * bcm_esmc_tunnel_set 20 * bcm_esmc_g781_option_get() 21 * bcm_esmc_g781_option_set() 22 * bcm_esmc_QL_SSM_map 23 * bcm_esmc_SSM_QL_map 24 * bcm_esmc_pdu_port_data_get() 25 * 26 * bcm_esmc_pdu_read 27 * bcm_esmc_pdu_write 28 */ 29 30 #if defined(INCLUDE_PTP) 31 32 #include <shared/bsl.h> 33 34 #include <bcm/pkt.h> 35 #include <bcm/tx.h> 36 37 #include <bcm/ptp.h> 38 #include <bcm_int/common/ptp.h> 39 #include <bcm_int/ptp_common.h> 40 #include <bcm/error.h> 41 42 #if defined (BCM_QAX_SUPPORT) || defined (BCM_QUX_SUPPORT) 43 #include <bcm/stack.h> 44 #include <soc/dpp/headers.h> 45 #include <soc/dpp/error.h> 46 #include <soc/dpp/port_sw_db.h> 47 #endif 48 49 /* Definitions. */ 50 #define ESMC_PDU_SIZE_OCTETS (28) 51 #define ESMC_PDU_PAD_SIZE_OCTETS (64) 52 #define ESMC_PDU_SOURCE_MAC_OFFSET (6) 53 #define ESMC_PDU_ETHERTYPE_OFFSET (12) 54 #define ESMC_PDU_SLOW_PROTOCOL_SUBTYPE_OFFSET (14) 55 #define ESMC_PDU_EVENT_FLAG_OFFSET (20) 56 #define ESMC_PDU_SSMQL_OFFSET (27) 57 58 #define ESMC_ETHERTYPE_SLOW_PROTOCOL (0x8809) 59 #define ESMC_SLOW_PROTOCOL_SUBTYPE_OSSP (0x0a) 60 61 #define ESMC_8021Q_TPID (0x8100) 62 #define ESMC_8021Q_SIZE (4) 63 64 #define ESMC_NETWORK_OPTION_DEFAULT (bcm_esmc_network_option_g781_II) 65 #define ESMC_QL_DEFAULT (bcm_esmc_g781_II_ql_dus) 66 #define ESMC_SSM_CODE_DEFAULT (0x0f) 67 68 #define ESMC_RX_ENABLE_DEFAULT (0) 69 70 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 71 /* External TDPLL */ 72 #define ESMC_PORT_TABLE_ENTRIES_MAX _SHR_PBMP_PORT_MAX 73 #else 74 /* Internal TDPLL */ 75 #if defined(BCM_GREYHOUND2_SUPPORT) 76 #define ESMC_PORT_TABLE_ENTRIES_MAX (90) 77 #else 78 #define ESMC_PORT_TABLE_ENTRIES_MAX (40) 79 #endif 80 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 81 82 83 /* G.8264 Amd2 extended QL TLV values */ 84 #define ESMC_PDU_ESSM_CODE_TLV_TYPE (0x02) 85 #define ESMC_PDU_ESSM_CODE_TLV_LEN (0x0014) 86 87 #define ESMC_PDU_ESSM_CODE_TLV_SIZE_OCTETS (20) 88 89 #define ESMC_PDU_ESSM_CODE_TLV_TYPE_OFFSET (28) 90 #define ESMC_PDU_ESSM_CODE_TLV_LEN_OFFSET (29) /* 16 bit */ 91 92 #define ESMC_PDU_ESSM_CODE_TLV_SSMCODE_OFFSET (31) 93 #define ESMC_PDU_ESSM_CODE_TLV_FLAG_OFFSET (40) 94 #define ESMC_PDU_ESSM_CODE_TLV_EEEC_CNT_OFFSET (41) 95 #define ESMC_PDU_ESSM_CODE_TLV_EEC_CNT_OFFSET (42) 96 97 /* Macros. */ 98 99 /* Types. */ 100 typedef struct bcm_esmc_port_s { 101 bcm_esmc_pdu_data_t pdu_data; 102 sal_time_t timestamp; 103 } bcm_esmc_port_t; 104 105 typedef struct bcm_esmc_data_s { 106 int rx_enable; 107 108 bcm_esmc_rx_cb rx_callback; 109 bcm_esmc_port_t rx_port[ESMC_PORT_TABLE_ENTRIES_MAX]; 110 111 bcm_pkt_t *tx_pkt; 112 113 bcm_esmc_network_option_t network_option; 114 } bcm_esmc_data_t; 115 116 /* Constants and variables. */ 117 static const uint8 esmc_pdu_template[ESMC_PDU_SIZE_OCTETS + ESMC_PDU_ESSM_CODE_TLV_SIZE_OCTETS] = { 118 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02, /* Destination MAC. */ 119 0x00, 0x10, 0x18, 0x00, 0x00, 0x00, /* Source MAC. */ 120 0x88, 0x09, /* Slow Protocol Ethertype. */ 121 ESMC_SLOW_PROTOCOL_SUBTYPE_OSSP, /* Slow Protocol subtype. */ 122 0x00, 0x19, 0xa7, /* ITU Organization Unique Identifier (OUI). */ 123 0x00, 0x01, /* ITU Subtype. */ 124 0x10, /* Version, Event Flag. */ 125 0x00, 0x00, 0x00, /* Reserved. */ 126 0x01, /* TLV Type. */ 127 0x00, 0x04, /* TLV Length. */ 128 0x00, /* Reserved, SSM/QL. */ 129 /* G8264Amd2 - ESSM code TLV - synce clock type */ 130 0x02, /* ESSM code TLV - Type - 0x02. */ 131 0x00, 0x14, /* ESSM code TLV - Length. */ 132 bcmEsmcEssmCodeNone, /* ESSM code TLV - ESSMCode */ 133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ESSM code TLV - synce master id */ 134 0x00, /* ESSM code TLV - flag */ 135 0x00, /* ESSM code TLV - cascaded EEEC count */ 136 0x00, /* ESSM code TLV - cascaded EEC count */ 137 0x00, 0x00, 0x00, 0x00, 0x00 /* ESSM code TLV - Reserved */ 138 }; 139 140 static const bcm_mac_t slow_protocol_multicast_mac = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x02}; 141 142 static bcm_esmc_data_t objdata; 143 144 /* Static functions. */ 145 static int bcm_esmc_pdu_read( 146 uint8 *esmc_pdu, int esmc_pdu_len, 147 bcm_esmc_pdu_data_t *esmc_pdu_data); 148 149 static int bcm_esmc_pdu_write( 150 bcm_esmc_pdu_data_t *esmc_pdu_data, int esmc_pdu_len_max, 151 uint8 *esmc_pdu, int *esmc_pdu_len); 152 153 /* 154 * Function: 155 * bcm_esmc_init() 156 * Purpose: 157 * Initialize Ethernet Synchronization Messaging Channel (ESMC). 158 * Parameters: 159 * unit - (IN) Unit number. 160 * stack_id - (IN) Stack identifier index. 161 * Returns: 162 * BCM_E_XXX - Function status. 163 * Notes: 164 */ 165 int 166 bcm_esmc_init( 167 int unit, 168 int stack_id) 169 { 170 int rv; 171 int port_num; 172 173 /* Initialize ESMC module data. */ 174 objdata.rx_enable = ESMC_RX_ENABLE_DEFAULT; 175 objdata.rx_callback = NULL; 176 objdata.network_option = ESMC_NETWORK_OPTION_DEFAULT; 177 178 if (NULL == objdata.tx_pkt) { 179 if (BCM_FAILURE(rv = bcm_pkt_alloc(unit, 128, BCM_TX_CRC_REGEN, &objdata.tx_pkt))) { 180 return rv; 181 } 182 } 183 184 for (port_num = 0; port_num < ESMC_PORT_TABLE_ENTRIES_MAX; ++port_num) { 185 sal_memset(objdata.rx_port[port_num].pdu_data.source_mac, 0, sizeof(bcm_mac_t)); 186 objdata.rx_port[port_num].pdu_data.pdu_type = bcm_esmc_pdu_type_info; 187 objdata.rx_port[port_num].pdu_data.ql = ESMC_QL_DEFAULT; 188 objdata.rx_port[port_num].pdu_data.ssm_code = ESMC_SSM_CODE_DEFAULT; 189 190 objdata.rx_port[port_num].timestamp = 0; 191 } 192 193 return BCM_E_NONE; 194 } 195 196 /* 197 * Function: 198 * bcm_esmc_cleanup() 199 * Purpose: 200 * Uninitialize Ethernet Synchronization Messaging Channel (ESMC). 201 * Parameters: 202 * unit - (IN) Unit number. 203 * stack_id - (IN) Stack identifier index. 204 * Returns: 205 * BCM_E_XXX - Function status. 206 * Notes: 207 */ 208 int 209 bcm_esmc_cleanup( 210 int unit, 211 int stack_id) 212 { 213 /* Leave objdata.tx_pkt allocated, as it won't be re-allocated on re-init */ 214 return BCM_E_NONE; 215 } 216 217 /* 218 * Function: 219 * bcm_esmc_rx() 220 * Purpose: 221 * ESMC PDU receive (Rx). 222 * Parameters: 223 * unit - (IN) Unit number. 224 * stack_id - (IN) Stack identifier index. 225 * ingress_port - (IN) Ingress port. 226 * ethertype - (IN) Ethertype. 227 * esmc_pdu_len - (IN) ESMC PDU length (octets). 228 * esmc_pdu - (IN) ESMC PDU. 229 * Returns: 230 * BCM_E_XXX - Function status. 231 * Notes: 232 */ 233 int 234 bcm_esmc_rx( 235 int unit, 236 int stack_id, 237 int ingress_port, 238 int ethertype, 239 int esmc_pdu_len, 240 uint8 *esmc_pdu) 241 { 242 int rv; 243 bcm_esmc_pdu_data_t esmc_pdu_data; 244 245 /* Argument checking and error handling. */ 246 if (ESMC_PDU_SIZE_OCTETS > esmc_pdu_len) { 247 LOG_VERBOSE(BSL_LS_BCM_COMMON, 248 (BSL_META_U(unit, 249 "bcm_esmc_rx(): Insufficient message length (%d).\n"), esmc_pdu_len)); 250 return BCM_E_PARAM; 251 } 252 253 if (_bcm_ptp_uint16_read(esmc_pdu + ESMC_PDU_ETHERTYPE_OFFSET) == ESMC_8021Q_TPID) { 254 /* 255 * Tagged packet. 256 * Remove 802.1Q header (single tag assumed). 257 * NB: Use memmove() b/c there is no corresponding sal_memmove(). 258 */ 259 memmove(esmc_pdu + ESMC_PDU_ETHERTYPE_OFFSET, 260 esmc_pdu + ESMC_PDU_ETHERTYPE_OFFSET + ESMC_8021Q_SIZE, 261 esmc_pdu_len - ESMC_PDU_ETHERTYPE_OFFSET - ESMC_8021Q_SIZE); 262 sal_memset(esmc_pdu + esmc_pdu_len - ESMC_8021Q_SIZE, 0, ESMC_8021Q_SIZE); 263 esmc_pdu_len -= ESMC_8021Q_SIZE; 264 } 265 266 if (ESMC_ETHERTYPE_SLOW_PROTOCOL != ethertype) { 267 LOG_VERBOSE(BSL_LS_BCM_COMMON, 268 (BSL_META_U(unit, 269 "bcm_esmc_rx(): Incorrect Ethertype (0x%04x).\n"), ethertype)); 270 return BCM_E_PARAM; 271 } else if (ESMC_SLOW_PROTOCOL_SUBTYPE_OSSP != 272 esmc_pdu[ESMC_PDU_SLOW_PROTOCOL_SUBTYPE_OFFSET]) { 273 LOG_VERBOSE(BSL_LS_BCM_COMMON, 274 (BSL_META_U(unit, 275 "bcm_esmc_rx(): Unexpected Slow Protocols subtype (0x%02x).\n"), 276 esmc_pdu[ESMC_PDU_SLOW_PROTOCOL_SUBTYPE_OFFSET])); 277 return BCM_E_PARAM; 278 } else if (sal_memcmp(esmc_pdu, slow_protocol_multicast_mac, sizeof(bcm_mac_t))) { 279 LOG_VERBOSE(BSL_LS_BCM_COMMON, 280 (BSL_META_U(unit, 281 "bcm_esmc_rx(): Incorrect destination MAC (%02x:%02x:%02x:%02x:%02x:%02x).\n"), 282 esmc_pdu[0], esmc_pdu[1], esmc_pdu[2], esmc_pdu[3], esmc_pdu[4], esmc_pdu[5])); 283 return BCM_E_PARAM; 284 } 285 286 if (BCM_FAILURE(rv = bcm_esmc_pdu_read(esmc_pdu, esmc_pdu_len, 287 &esmc_pdu_data))) { 288 PTP_ERROR_FUNC("bcm_esmc_pdu_read()"); 289 return rv; 290 } 291 292 /* Update ESMC port table entry. */ 293 if (ingress_port > 0 && ingress_port <= ESMC_PORT_TABLE_ENTRIES_MAX) { 294 objdata.rx_port[ingress_port-1].pdu_data = esmc_pdu_data; 295 objdata.rx_port[ingress_port-1].timestamp = _bcm_ptp_monotonic_time(); 296 } 297 298 if (objdata.rx_callback) { 299 LOG_VERBOSE(BSL_LS_BCM_PTP, 300 (BSL_META_U(0, " ESMC PDU Rcvd: port[%d] Type[%d] ssm[%d] src_mac[%02x.%02x.%02x.%02x.%02x.%02x]\n"), 301 ingress_port, esmc_pdu_data.pdu_type, esmc_pdu_data.ssm_code, 302 esmc_pdu_data.source_mac[0], esmc_pdu_data.source_mac[1],esmc_pdu_data.source_mac[2], 303 esmc_pdu_data.source_mac[3],esmc_pdu_data.source_mac[4],esmc_pdu_data.source_mac[5])); 304 if (BCM_FAILURE(rv = objdata.rx_callback(unit, stack_id, ingress_port, &esmc_pdu_data))) { 305 PTP_ERROR_FUNC("ESMC Rx Callback f()"); 306 return rv; 307 } 308 } 309 310 return BCM_E_NONE; 311 } 312 313 #if defined (BCM_QAX_SUPPORT) || defined (BCM_QUX_SUPPORT) 314 /* 315 * Function: 316 * bcm_esmc_pdu_tx_dnx() 317 * Purpose: 318 * Add required DNX headers to ESMC PDU and transmit (Tx). 319 * Parameters: 320 * unit - (IN) Unit number. 321 * esmc_pdu - (IN) ESMC PDU. 322 * esmc_pdu_len - (IN) ESMC PDU length. 323 * Returns: 324 * None. 325 * Notes: 326 */ 327 void 328 bcm_esmc_pdu_tx_dnx( 329 int unit, 330 uint8 *esmc_pdu, 331 int esmc_pdu_len) 332 { 333 int rv; 334 int gport; 335 int port_ndx; 336 bcm_gport_t sysport; 337 soc_dpp_itmh_t itmh; /* itmh header contents */ 338 339 bcm_pkt_t *esmc_packet = objdata.tx_pkt; 340 341 if (SOC_IS_JERICHO(unit)) { 342 343 esmc_packet->flags = 0x21; 344 345 BCM_PBMP_ITER(esmc_packet->tx_pbmp, port_ndx){ 346 /* Fetch the system port */ 347 rv = bcm_stk_gport_sysport_get(unit, port_ndx, &sysport); 348 if(BCM_E_NONE != rv) { 349 LOG_VERBOSE(BSL_LS_BCM_COMMON, 350 (BSL_META("bcm_stk_gport_sysport_get failed. TX Unit: %d port: %d Error(%d): %s\n"), \ 351 unit, port_ndx, rv, bcm_errmsg(rv))); 352 } 353 354 /* Get gport for the system port */ 355 gport = BCM_GPORT_SYSTEM_PORT_ID_GET(sysport); 356 357 sal_memset(&itmh, 0, sizeof(soc_dpp_itmh_t)); 358 359 itmh.base.jer_dest_info.dest_info_hi = 0x1; 360 itmh.base.jer_dest_info.dest_info_mi = (gport >> 8) & 0xff; 361 itmh.base.jer_dest_info.dest_info_lo = (gport & 0xff); 362 363 /* Update PTCH header */ 364 esmc_packet->pkt_data[0].data[0] = 0x50; 365 esmc_packet->pkt_data[0].data[1] = 0x00; 366 367 /* Update ITMH header */ 368 sal_memcpy(BCM_PKT_IEEE(esmc_packet) + DPP_HDR_PTCH_TYPE2_LEN, &itmh.base.raw.bytes[0], DPP_HDR_ITMH_BASE_LEN); 369 370 /* Update ESMC packet */ 371 sal_memcpy(BCM_PKT_IEEE(esmc_packet) + DPP_HDR_ITMH_BASE_LEN + DPP_HDR_PTCH_TYPE2_LEN, esmc_pdu, esmc_pdu_len); 372 373 /* Update length */ 374 esmc_packet->pkt_data[0].len = DPP_HDR_PTCH_TYPE2_LEN + DPP_HDR_ITMH_BASE_LEN + esmc_pdu_len; 375 376 LOG_VERBOSE(BSL_LS_BCM_PTP, 377 (BSL_META("port_ndx[%d] sysport[0x%08x] gport[0x%08x] Header[%02x:%02x:%02x:%02x:%02x:%02x] pkt_len[%d] \n"), port_ndx, sysport, gport, 378 esmc_packet->pkt_data[0].data[0], esmc_packet->pkt_data[0].data[1], esmc_packet->pkt_data[0].data[2], 379 esmc_packet->pkt_data[0].data[3], esmc_packet->pkt_data[0].data[4], esmc_packet->pkt_data[0].data[5], 380 esmc_packet->pkt_data[0].len)); 381 382 rv = bcm_tx(unit, esmc_packet, NULL); 383 if (rv != BCM_E_NONE) { 384 LOG_ERROR(BSL_LS_BCM_COMMON, 385 (BSL_META("bcm_tx failed: TX Unit %d: %s\n"), \ 386 unit, bcm_errmsg(rv))); 387 break; 388 } 389 } /* BCM_PBMP_ITER */ 390 391 } /* SOC_IS_JERICHO*/ 392 393 } 394 #endif 395 396 /* 397 * Function: 398 * bcm_common_esmc_tx() 399 * Purpose: 400 * ESMC PDU transmit (Tx). 401 * Parameters: 402 * unit - (IN) Unit number. 403 * stack_id - (IN) Stack identifier index. 404 * pbmp - (IN) Tx port bitmap. 405 * esmc_pdu_data - (IN) ESMC PDU data. 406 * Returns: 407 * BCM_E_XXX - Function status. 408 * Notes: 409 */ 410 int 411 bcm_common_esmc_tx( 412 int unit, 413 int stack_id, 414 bcm_pbmp_t pbmp, 415 bcm_esmc_pdu_data_t *esmc_pdu_data) 416 { 417 int rv; 418 419 int esmc_pdu_len; 420 int esmc_pdu_len_max = ESMC_PDU_PAD_SIZE_OCTETS + ESMC_PDU_ESSM_CODE_TLV_SIZE_OCTETS ; 421 uint8 esmc_pdu[ESMC_PDU_PAD_SIZE_OCTETS + ESMC_PDU_ESSM_CODE_TLV_SIZE_OCTETS] = {0}; 422 423 bcm_pkt_t *esmc_packet = objdata.tx_pkt; 424 425 if (BCM_FAILURE(rv = bcm_esmc_pdu_write(esmc_pdu_data, 426 esmc_pdu_len_max, esmc_pdu, &esmc_pdu_len))) { 427 PTP_ERROR_FUNC("bcm_esmc_pdu_write()"); 428 return rv; 429 } 430 431 BCM_PBMP_ASSIGN(esmc_packet->tx_pbmp, pbmp); 432 433 #if defined (BCM_QAX_SUPPORT) || defined (BCM_QUX_SUPPORT) 434 bcm_esmc_pdu_tx_dnx(unit, esmc_pdu, esmc_pdu_len); 435 #else 436 437 sal_memcpy(BCM_PKT_IEEE(esmc_packet), esmc_pdu, esmc_pdu_len); 438 esmc_packet->pkt_data[0].len = esmc_pdu_len + 4; 439 440 if (BCM_FAILURE(rv = bcm_tx(unit, esmc_packet, NULL))) { 441 PTP_ERROR_FUNC("bcm_tx()"); 442 return rv; 443 } 444 445 #endif 446 447 return BCM_E_NONE; 448 } 449 450 /* 451 * Function: 452 * bcm_esmc_rx_callback_register() 453 * Purpose: 454 * Register ESMC PDU Rx callback. 455 * Parameters: 456 * unit - (IN) Unit number. 457 * stack_id - (IN) Stack identifier index. 458 * rx_cb - (IN) ESMC PDU Rx callback function pointer. 459 * Returns: 460 * BCM_E_XXX - Function status. 461 * Notes: 462 */ 463 int 464 bcm_common_esmc_rx_callback_register( 465 int unit, 466 int stack_id, 467 bcm_esmc_rx_cb rx_cb) 468 { 469 objdata.rx_callback = rx_cb; 470 return BCM_E_NONE; 471 } 472 473 /* 474 * Function: 475 * bcm_esmc_rx_callback_unregister() 476 * Purpose: 477 * Unregister ESMC PDU Rx callback. 478 * Parameters: 479 * unit - (IN) Unit number. 480 * stack_id - (IN) Stack identifier index. 481 * Returns: 482 * BCM_E_XXX - Function status. 483 * Notes: 484 */ 485 int 486 bcm_common_esmc_rx_callback_unregister( 487 int unit, 488 int stack_id) 489 { 490 objdata.rx_callback = NULL; 491 return BCM_E_NONE; 492 } 493 494 /* 495 * Function: 496 * bcm_esmc_tunnel_get() 497 * Purpose: 498 * Get ESMC PDU tunneling-enabled Boolean. 499 * Parameters: 500 * unit - (IN) Unit number. 501 * stack_id - (IN) PTP stack ID. 502 * enable - (OUT) Enable Boolean. 503 * Returns: 504 * BCM_E_XXX - Function status. 505 * Notes: 506 * Boolean controls whether ToP tunnels slow-protocol Ethertype packets 507 * - which include ESMC PDUs - to host for processing. 508 */ 509 int 510 bcm_common_esmc_tunnel_get( 511 int unit, 512 int stack_id, 513 int *enable) 514 { 515 int rv; 516 517 uint8 resp[PTP_MGMTMSG_PAYLOAD_ESMC_TUNNEL_SIZE_OCTETS] = {0}; 518 int resp_len = PTP_MGMTMSG_PAYLOAD_ESMC_TUNNEL_SIZE_OCTETS; 519 520 bcm_ptp_port_identity_t portid; 521 522 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 523 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 524 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 525 return rv; 526 } 527 528 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 529 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 530 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 531 return rv; 532 } 533 534 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 535 &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_ESMC_TUNNEL, 536 0, 0, resp, &resp_len))) { 537 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 538 return rv; 539 } 540 541 /* 542 * Parse response. 543 * Octet 0...5 : Custom management message key/identifier. 544 * BCM<null><null><null>. 545 * Octet 6 : ESMC PDU tunneling-enabled Boolean. 546 * Octet 7 : Reserved. 547 */ 548 *enable = resp[6] ? 1:0; /* Advance cursor past custom management message identifier. */ 549 550 /* Set local ESMC PDU Rx enable Boolean. */ 551 objdata.rx_enable = *enable; 552 553 return BCM_E_NONE; 554 } 555 556 /* 557 * Function: 558 * bcm_esmc_tunnel_set() 559 * Purpose: 560 * Set ESMC PDU tunneling-enabled Boolean. 561 * Parameters: 562 * unit - (IN) Unit number. 563 * stack_id - (IN) PTP stack ID. 564 * enable - (OUT) Enable Boolean. 565 * Returns: 566 * BCM_E_XXX - Function status. 567 * Notes: 568 * Boolean controls whether ToP tunnels slow-protocol Ethertype packets 569 * - which include ESMC PDUs - to host for processing. 570 */ 571 int 572 bcm_common_esmc_tunnel_set( 573 int unit, 574 int stack_id, 575 int enable) 576 { 577 int rv; 578 int i; 579 580 uint8 payload[PTP_MGMTMSG_PAYLOAD_ESMC_TUNNEL_SIZE_OCTETS] = {0}; 581 uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS]; 582 int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 583 584 bcm_ptp_port_identity_t portid; 585 586 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, stack_id, 587 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 588 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 589 return rv; 590 } 591 592 if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, stack_id, 593 PTP_CLOCK_NUMBER_DEFAULT, PTP_IEEE1588_ALL_PORTS, &portid))) { 594 PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()"); 595 return rv; 596 } 597 598 /* 599 * Make payload. 600 * Octet 0...5 : Custom management message key/identifier. 601 * BCM<null><null><null>. 602 * Octet 6 : ESMC tunneling-enabled Boolean. 603 * Octet 7 : Reserved. 604 */ 605 sal_memcpy(payload, "BCM\0\0\0", 6); 606 i = 6; 607 payload[i++] = enable ? 1:0; 608 609 if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, stack_id, PTP_CLOCK_NUMBER_DEFAULT, 610 &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_ESMC_TUNNEL, 611 payload, PTP_MGMTMSG_PAYLOAD_ESMC_TUNNEL_SIZE_OCTETS, 612 resp, &resp_len))) { 613 PTP_ERROR_FUNC("_bcm_ptp_management_message_send()"); 614 return rv; 615 } 616 617 /* Set local ESMC PDU Rx enable Boolean. */ 618 objdata.rx_enable = enable ? 1:0; 619 620 return BCM_E_NONE; 621 } 622 623 /* 624 * Function: 625 * bcm_esmc_g781_option_get() 626 * Purpose: 627 * Get ITU-T G.781 networking option for SyncE. 628 * Parameters: 629 * unit - (IN) Unit number. 630 * stack_id - (IN) Stack identifier index. 631 * g781_option - (OUT) ITU-T G.781 networking option. 632 * Returns: 633 * BCM_E_XXX - Function status. 634 * Notes: 635 */ 636 int 637 bcm_common_esmc_g781_option_get( 638 int unit, 639 int stack_id, 640 bcm_esmc_network_option_t *g781_option) 641 { 642 *g781_option = objdata.network_option; 643 return BCM_E_NONE; 644 } 645 646 /* 647 * Function: 648 * bcm_esmc_g781_option_set() 649 * Purpose: 650 * Set ITU-T G.781 networking option for SyncE. 651 * Parameters: 652 * unit - (IN) Unit number. 653 * stack_id - (IN) Stack identifier index. 654 * g781_option - (IN) ITU-T G.781 networking option. 655 * Returns: 656 * BCM_E_XXX - Function status. 657 * Notes: 658 */ 659 int 660 bcm_common_esmc_g781_option_set( 661 int unit, 662 int stack_id, 663 bcm_esmc_network_option_t g781_option) 664 { 665 switch (g781_option) { 666 case bcm_esmc_network_option_g781_I: 667 case bcm_esmc_network_option_g781_II: 668 case bcm_esmc_network_option_g781_III: 669 objdata.network_option = g781_option; 670 break; 671 default: 672 return BCM_E_PARAM; 673 } 674 675 return BCM_E_NONE; 676 } 677 678 /* 679 * Function: 680 * bcm_esmc_QL_SSM_map() 681 * Purpose: 682 * Get synchronization status message (SSM) code corresponding to 683 * ITU-T G.781 quality level (QL). 684 * Parameters: 685 * unit - (IN) Unit number. 686 * opt - (IN) ITU-T G.781 networking option. 687 * ql - (IN) ITU-T G.781 quality level. 688 * ssm_code - (OUT) SSM code. 689 * Returns: 690 * BCM_E_XXX - Function status. 691 * Notes: 692 */ 693 int 694 bcm_common_esmc_QL_SSM_map( 695 int unit, 696 bcm_esmc_network_option_t opt, 697 bcm_esmc_quality_level_t ql, 698 uint8 *ssm_code) 699 { 700 switch (opt) { 701 case bcm_esmc_network_option_g781_I: 702 switch (ql) { 703 case bcm_esmc_g781_I_ql_prc: 704 *ssm_code = 0x02; 705 break; 706 case bcm_esmc_g781_I_ql_ssua: 707 *ssm_code = 0x04; 708 break; 709 case bcm_esmc_g781_I_ql_ssub: 710 *ssm_code = 0x08; 711 break; 712 case bcm_esmc_g781_I_ql_sec: 713 *ssm_code = 0x0b; 714 break; 715 case bcm_esmc_g781_I_ql_dnu: 716 /* Fall through. */ 717 default: 718 *ssm_code = 0x0f; 719 } 720 break; 721 case bcm_esmc_network_option_g781_II: 722 switch (ql) { 723 case bcm_esmc_g781_II_ql_stu: 724 *ssm_code = 0x00; 725 break; 726 case bcm_esmc_g781_II_ql_prs: 727 *ssm_code = 0x01; 728 break; 729 case bcm_esmc_g781_II_ql_tnc: 730 *ssm_code = 0x04; 731 break; 732 case bcm_esmc_g781_II_ql_st2: 733 *ssm_code = 0x07; 734 break; 735 case bcm_esmc_g781_II_ql_st3: 736 *ssm_code = 0x0a; 737 break; 738 case bcm_esmc_g781_II_ql_smc: 739 *ssm_code = 0x0c; 740 break; 741 case bcm_esmc_g781_II_ql_st3e: 742 *ssm_code = 0x0d; 743 break; 744 case bcm_esmc_g781_II_ql_prov: 745 *ssm_code = 0x0e; 746 break; 747 case bcm_esmc_g781_II_ql_dus: 748 /* Fall through. */ 749 default: 750 *ssm_code = 0x0f; 751 } 752 break; 753 case bcm_esmc_network_option_g781_III: 754 switch (ql) { 755 case bcm_esmc_g781_III_ql_unk: 756 *ssm_code = 0x00; 757 break; 758 case bcm_esmc_g781_III_ql_sec: 759 *ssm_code = 0x0b; 760 break; 761 default: 762 *ssm_code = 0x0f; 763 } 764 break; 765 default: 766 *ssm_code = 0x0f; 767 return BCM_E_CONFIG; 768 } 769 770 return BCM_E_NONE; 771 } 772 773 /* 774 * Function: 775 * bcm_esmc_SSM_QL_map() 776 * Purpose: 777 * Get ITU-T G.781 quality level (QL) corresponding to synchronization 778 * status message (SSM) code. 779 * Parameters: 780 * unit - (IN) Unit number. 781 * opt - (IN) ITU-T G.781 networking option. 782 * ssm_code - (IN) SSM code. 783 * ql - (OUT) ITU-T G.781 quality level. 784 * Returns: 785 * BCM_E_XXX - Function status. 786 * Notes: 787 */ 788 int 789 bcm_common_esmc_SSM_QL_map( 790 int unit, 791 bcm_esmc_network_option_t opt, 792 uint8 ssm_code, 793 bcm_esmc_quality_level_t *ql) 794 { 795 switch (opt) { 796 case bcm_esmc_network_option_g781_I: 797 switch (ssm_code) { 798 case 0x00: 799 *ql = bcm_esmc_g781_I_ql_inv0; 800 break; 801 case 0x01: 802 *ql = bcm_esmc_g781_I_ql_inv1; 803 break; 804 case 0x02: 805 *ql = bcm_esmc_g781_I_ql_prc; 806 break; 807 case 0x03: 808 *ql = bcm_esmc_g781_I_ql_inv3; 809 break; 810 case 0x04: 811 *ql = bcm_esmc_g781_I_ql_ssua; 812 break; 813 case 0x05: 814 *ql = bcm_esmc_g781_I_ql_inv5; 815 break; 816 case 0x06: 817 *ql = bcm_esmc_g781_I_ql_inv6; 818 break; 819 case 0x07: 820 *ql = bcm_esmc_g781_I_ql_inv7; 821 break; 822 case 0x08: 823 *ql = bcm_esmc_g781_I_ql_ssub; 824 break; 825 case 0x09: 826 *ql = bcm_esmc_g781_I_ql_inv9; 827 break; 828 case 0x0a: 829 *ql = bcm_esmc_g781_I_ql_inv10; 830 break; 831 case 0x0b: 832 *ql = bcm_esmc_g781_I_ql_sec; 833 break; 834 case 0x0c: 835 *ql = bcm_esmc_g781_I_ql_inv12; 836 break; 837 case 0x0d: 838 *ql = bcm_esmc_g781_I_ql_inv13; 839 break; 840 case 0x0e: 841 *ql = bcm_esmc_g781_I_ql_inv14; 842 break; 843 case 0x0f: 844 *ql = bcm_esmc_g781_I_ql_dnu; 845 break; 846 default: 847 *ql = bcm_esmc_g781_I_ql_nsupp; 848 return BCM_E_CONFIG; 849 } 850 break; 851 case bcm_esmc_network_option_g781_II: 852 switch (ssm_code) { 853 case 0x00: 854 *ql = bcm_esmc_g781_II_ql_stu; 855 break; 856 case 0x01: 857 *ql = bcm_esmc_g781_II_ql_prs; 858 break; 859 case 0x02: 860 *ql = bcm_esmc_g781_II_ql_inv2; 861 break; 862 case 0x03: 863 *ql = bcm_esmc_g781_II_ql_inv3; 864 break; 865 case 0x04: 866 *ql = bcm_esmc_g781_II_ql_tnc; 867 break; 868 case 0x05: 869 *ql = bcm_esmc_g781_II_ql_inv5; 870 break; 871 case 0x06: 872 *ql = bcm_esmc_g781_II_ql_inv6; 873 break; 874 case 0x07: 875 *ql = bcm_esmc_g781_II_ql_st2; 876 break; 877 case 0x08: 878 *ql = bcm_esmc_g781_II_ql_inv8; 879 break; 880 case 0x09: 881 *ql = bcm_esmc_g781_II_ql_inv9; 882 break; 883 case 0x0a: 884 *ql = bcm_esmc_g781_II_ql_st3; 885 break; 886 case 0x0b: 887 *ql = bcm_esmc_g781_II_ql_inv11; 888 break; 889 case 0x0c: 890 *ql = bcm_esmc_g781_II_ql_smc; 891 break; 892 case 0x0d: 893 *ql = bcm_esmc_g781_II_ql_st3e; 894 break; 895 case 0x0e: 896 *ql = bcm_esmc_g781_II_ql_prov; 897 break; 898 case 0x0f: 899 *ql = bcm_esmc_g781_II_ql_dus; 900 break; 901 default: 902 *ql = bcm_esmc_g781_II_ql_nsupp; 903 return BCM_E_CONFIG; 904 } 905 break; 906 case bcm_esmc_network_option_g781_III: 907 switch (ssm_code) { 908 case 0x00: 909 *ql = bcm_esmc_g781_III_ql_unk; 910 break; 911 case 0x01: 912 *ql = bcm_esmc_g781_III_ql_inv1; 913 break; 914 case 0x02: 915 *ql = bcm_esmc_g781_III_ql_inv2; 916 break; 917 case 0x03: 918 *ql = bcm_esmc_g781_III_ql_inv3; 919 break; 920 case 0x04: 921 *ql = bcm_esmc_g781_III_ql_inv4; 922 break; 923 case 0x05: 924 *ql = bcm_esmc_g781_III_ql_inv5; 925 break; 926 case 0x06: 927 *ql = bcm_esmc_g781_III_ql_inv6; 928 break; 929 case 0x07: 930 *ql = bcm_esmc_g781_III_ql_inv7; 931 break; 932 case 0x08: 933 *ql = bcm_esmc_g781_III_ql_inv8; 934 break; 935 case 0x09: 936 *ql = bcm_esmc_g781_III_ql_inv9; 937 break; 938 case 0x0a: 939 *ql = bcm_esmc_g781_III_ql_inv10; 940 break; 941 case 0x0b: 942 *ql = bcm_esmc_g781_III_ql_sec; 943 break; 944 case 0x0c: 945 *ql = bcm_esmc_g781_III_ql_inv12; 946 break; 947 case 0x0d: 948 *ql = bcm_esmc_g781_III_ql_inv13; 949 break; 950 case 0x0e: 951 *ql = bcm_esmc_g781_III_ql_inv14; 952 break; 953 case 0x0f: 954 *ql = bcm_esmc_g781_III_ql_inv15; 955 break; 956 default: 957 *ql = bcm_esmc_g781_III_ql_nsupp; 958 return BCM_E_CONFIG; 959 } 960 break; 961 default: 962 *ql = bcm_esmc_ql_unresolvable; 963 return BCM_E_CONFIG; 964 } 965 966 return BCM_E_NONE; 967 } 968 969 /* 970 * Function: 971 * bcm_esmc_pdu_port_data_get() 972 * Purpose: 973 * Get data for most recent ESMC PDU of a port. 974 * Parameters: 975 * unit - (IN) Unit number. 976 * stack_id - (IN) Stack identifier index. 977 * port_num - (IN) Physical port number. 978 * pdu_data - (OUT) ESMC PDU data. 979 * timestamp - (OUT) ESMC PDU timestamp. 980 * Returns: 981 * BCM_E_XXX - Function status. 982 * Notes: 983 */ 984 int 985 bcm_esmc_pdu_port_data_get( 986 int unit, 987 int stack_id, 988 int port_num, 989 bcm_esmc_pdu_data_t *pdu_data, 990 sal_time_t *timestamp) 991 { 992 if (port_num < 1 || port_num > ESMC_PORT_TABLE_ENTRIES_MAX) { 993 return BCM_E_PARAM; 994 } 995 996 *pdu_data = objdata.rx_port[port_num-1].pdu_data; 997 *timestamp = objdata.rx_port[port_num-1].timestamp; 998 999 return BCM_E_NONE; 1000 } 1001 1002 /* 1003 * Function: 1004 * bcm_esmc_pdu_essm_code_tlv_read() 1005 * Purpose: 1006 * Read ESMC PDU and extract relevant data. 1007 * Parameters: 1008 * esmc_pdu - (IN) ESMC PDU. 1009 * esmc_pdu_len - (IN) ESMC PDU length (octets). 1010 * esmc_pdu_data - (OUT) ESMC PDU data. 1011 * Returns: 1012 * BCM_E_XXX - Function status. 1013 * Notes: 1014 */ 1015 static int 1016 bcm_esmc_pdu_essm_code_tlv_read( 1017 uint8 *esmc_pdu, 1018 int esmc_pdu_len, 1019 bcm_esmc_pdu_data_t *esmc_pdu_data) 1020 { 1021 esmc_pdu_data->essm_code = bcmEsmcEssmCodeNone; 1022 esmc_pdu_data->essm_flag = 0; 1023 esmc_pdu_data->essm_eec_count = 0; 1024 esmc_pdu_data->essm_eeec_count = 0; 1025 1026 /* Argument checking and error handling. */ 1027 if (esmc_pdu_len < (ESMC_PDU_SIZE_OCTETS + ESMC_PDU_ESSM_CODE_TLV_LEN)) { 1028 return BCM_E_UNAVAIL; 1029 } 1030 1031 /* check synce clokc type ql tlv type */ 1032 if ( ESMC_PDU_ESSM_CODE_TLV_TYPE != esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_TYPE_OFFSET]) { 1033 return BCM_E_UNAVAIL; 1034 } 1035 1036 /* parse synce clock type tlv */ 1037 esmc_pdu_data->essm_code = (bcm_esmc_essm_code_t)esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_SSMCODE_OFFSET]; 1038 esmc_pdu_data->essm_flag = esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_FLAG_OFFSET]; 1039 esmc_pdu_data->essm_eeec_count = esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_EEEC_CNT_OFFSET]; 1040 esmc_pdu_data->essm_eec_count = esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_EEC_CNT_OFFSET]; 1041 1042 return BCM_E_NONE; 1043 } 1044 1045 /* 1046 * Function: 1047 * bcm_esmc_pdu_read() 1048 * Purpose: 1049 * Read ESMC PDU and extract relevant data. 1050 * Parameters: 1051 * esmc_pdu - (IN) ESMC PDU. 1052 * esmc_pdu_len - (IN) ESMC PDU length (octets). 1053 * esmc_pdu_data - (OUT) ESMC PDU data. 1054 * Returns: 1055 * BCM_E_XXX - Function status. 1056 * Notes: 1057 */ 1058 static int 1059 bcm_esmc_pdu_read( 1060 uint8 *esmc_pdu, 1061 int esmc_pdu_len, 1062 bcm_esmc_pdu_data_t *esmc_pdu_data) 1063 { 1064 int rv; 1065 1066 /* Argument checking and error handling. */ 1067 if (esmc_pdu_len < ESMC_PDU_SIZE_OCTETS) { 1068 return BCM_E_PARAM; 1069 } 1070 1071 /* Get source MAC address. */ 1072 sal_memcpy(esmc_pdu_data->source_mac, esmc_pdu + ESMC_PDU_SOURCE_MAC_OFFSET, sizeof(bcm_mac_t)); 1073 1074 /* Get ESMC PDU type. */ 1075 esmc_pdu_data->pdu_type = ((esmc_pdu[ESMC_PDU_EVENT_FLAG_OFFSET] & 0x08) >> 3); 1076 1077 /* Get ESMC SSM/QL. */ 1078 esmc_pdu_data->ssm_code = (esmc_pdu[ESMC_PDU_SSMQL_OFFSET]); 1079 if (BCM_FAILURE(rv = bcm_esmc_SSM_QL_map(0, objdata.network_option, 1080 esmc_pdu_data->ssm_code, &esmc_pdu_data->ql))) { 1081 PTP_ERROR_FUNC("bcm_esmc_SSM_QL_map"); 1082 return rv; 1083 } 1084 1085 /* parse G.8264 amd2 ql tlv if present */ 1086 bcm_esmc_pdu_essm_code_tlv_read(esmc_pdu, esmc_pdu_len, esmc_pdu_data); 1087 1088 return BCM_E_NONE; 1089 } 1090 1091 /* 1092 * Function: 1093 * bcm_esmc_pdu_write() 1094 * Purpose: 1095 * Write ESMC PDU. 1096 * Parameters: 1097 * esmc_pdu_data - (IN) ESMC PDU data. 1098 * esmc_pdu_len_max - (IN) ESMC PDU maximum length (octets). 1099 * esmc_pdu - (OUT) ESMC PDU. 1100 * esmc_pdu_len - (OUT) ESMC PDU length (octets). 1101 * Returns: 1102 * BCM_E_XXX - Function status. 1103 * Notes: 1104 */ 1105 static int 1106 bcm_esmc_pdu_write( 1107 bcm_esmc_pdu_data_t *esmc_pdu_data, 1108 int esmc_pdu_len_max, 1109 uint8 *esmc_pdu, 1110 int *esmc_pdu_len) 1111 { 1112 /* Argument checking and error handling. */ 1113 if (esmc_pdu_len_max < ESMC_PDU_PAD_SIZE_OCTETS) { 1114 return BCM_E_PARAM; 1115 } 1116 *esmc_pdu_len = ESMC_PDU_PAD_SIZE_OCTETS; 1117 1118 /* Initialize PDU with ESMC PDU template. */ 1119 sal_memset(esmc_pdu, 0, esmc_pdu_len_max); 1120 sal_memcpy(esmc_pdu, esmc_pdu_template, ESMC_PDU_SIZE_OCTETS); 1121 1122 /* Set source MAC address. */ 1123 sal_memcpy(esmc_pdu + ESMC_PDU_SOURCE_MAC_OFFSET, esmc_pdu_data->source_mac, 1124 sizeof(bcm_mac_t)); 1125 1126 /* Set ESMC PDU type. */ 1127 esmc_pdu[ESMC_PDU_EVENT_FLAG_OFFSET] |= (esmc_pdu_data->pdu_type << 3); 1128 1129 /* Set ESMC SSM/QL. */ 1130 esmc_pdu[ESMC_PDU_SSMQL_OFFSET] = (esmc_pdu_data->ssm_code & 0x0f); 1131 1132 /* if required , write g.8264 amd2 synce clock type tlv */ 1133 if (esmc_pdu_data->essm_code != bcmEsmcEssmCodeNone) { 1134 sal_memcpy(esmc_pdu + ESMC_PDU_SIZE_OCTETS, esmc_pdu_template + ESMC_PDU_SIZE_OCTETS, ESMC_PDU_ESSM_CODE_TLV_LEN); 1135 /* TBD different sync clokc type handling */ 1136 esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_SSMCODE_OFFSET] = esmc_pdu_data->essm_code; 1137 esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_FLAG_OFFSET] = esmc_pdu_data->essm_flag; 1138 esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_EEEC_CNT_OFFSET] = esmc_pdu_data->essm_eeec_count; 1139 esmc_pdu[ESMC_PDU_ESSM_CODE_TLV_EEC_CNT_OFFSET] = esmc_pdu_data->essm_eec_count; 1140 *esmc_pdu_len += ESMC_PDU_ESSM_CODE_TLV_SIZE_OCTETS; 1141 } 1142 1143 return BCM_E_NONE; 1144 } 1145 1146 #endif /* defined(INCLUDE_PTP) */