openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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) */