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

stats.c (30902B)


      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:    stats.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      bcm_common_ptp_packet_counters_clear
     13  *      bcm_common_ptp_packet_counters_get
     14  *      bcm_common_ptp_peer_dataset_get
     15  *
     16  *      _bcm_ptp_packet_counters_msg_get
     17  *      _bcm_ptp_packet_counters_pci_get
     18  *      _bcm_ptp_update_peer_counts
     19  *      _bcm_ptp_update_peer_dataset
     20  *      _bcm_ptp_peer_dataset_get
     21  *      _bcm_ptp_clock_description_get
     22  *      _bcm_ptp_show_system_info
     23  */
     24 
     25 #if defined(INCLUDE_PTP)
     26 
     27 #include <bcm/ptp.h>
     28 #include <bcm_int/common/ptp.h>
     29 #include <bcm_int/ptp_common.h>
     30 #include <bcm/error.h>
     31 
     32 /* Constants and variables. */
     33 static const bcm_ptp_packet_counters_t counters_zero;
     34 static const bcm_ptp_clock_port_packet_drop_counters_t drop_counters_zero = {0};
     35 
     36 
     37 static const bcm_ptp_port_identity_t portid_all = 
     38     {{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}, PTP_IEEE1588_ALL_PORTS};
     39 
     40 /* Static functions. */
     41 static int _bcm_ptp_packet_counters_msg_get(int unit, bcm_ptp_stack_id_t ptp_id,
     42     int clock_num, bcm_ptp_packet_counters_t *counters);
     43     
     44 /*
     45  * Function:
     46  *      bcm_common_ptp_packet_counters_clear
     47  * Purpose:
     48  *      Reset packet counters.
     49  * Parameters:
     50  *      unit           - (IN)  Unit number.
     51  *      ptp_id         - (IN)  PTP stack ID.
     52  *      clock_num      - (IN)  PTP clock number.
     53  *      port_num       - (IN)  PTP clock port number (for port-specific stats reset).
     54  *      counter_bitmap - (IN)  counter bitmap
     55  * Returns:
     56  *      BCM_E_XXX - Function status.
     57  * Notes:
     58  */
     59 int
     60 bcm_common_ptp_packet_counters_clear(
     61     int unit,
     62     bcm_ptp_stack_id_t ptp_id,
     63     int clock_num,
     64     int port_num,
     65     uint32 counter_bitmap)
     66 {
     67     int rv = BCM_E_UNAVAIL;
     68 
     69     uint8 payload[PTP_MGMTMSG_PAYLOAD_PACKET_STATS_CLEAR_SIZE_OCTETS] = {0};
     70     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
     71     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
     72 
     73     bcm_ptp_port_identity_t portid;
     74 
     75     /* Mask unused bits */
     76     counter_bitmap &= BCM_PTP_PKT_COUNTER_ALL;
     77 
     78     if (counter_bitmap == BCM_PTP_PKT_COUNTER_ALL ||
     79         counter_bitmap <= BCM_PTP_PKT_COUNTER_COMMON) {
     80         /* To clear any/all common counters or all counters, port_num shall be 0xFFFF */
     81         port_num = PTP_IEEE1588_ALL_PORTS;
     82     }
     83 
     84     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, port_num))) {
     85             return rv;
     86     }
     87 
     88     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
     89             clock_num, port_num, &portid))) {
     90         return rv;
     91     }
     92 
     93     /*
     94      * Make payload.
     95      *    Octet 0-3 : counter_bitmap.
     96      *    Octet 4-7 : Reserved.
     97      */
     98      _bcm_ptp_uint32_write(payload, counter_bitmap);
     99 
    100     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    101             clock_num, &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_PACKET_STATS,
    102 			payload, PTP_MGMTMSG_PAYLOAD_PACKET_STATS_CLEAR_SIZE_OCTETS, resp, &resp_len))) {
    103         return rv;
    104     }
    105 
    106     return rv;
    107 }
    108 
    109 /*
    110  * Function:
    111  *      bcm_common_ptp_packet_counters_get
    112  * Purpose:
    113  *      Get packet counters.
    114  * Parameters:
    115  *      unit      - (IN)  Unit number.
    116  *      ptp_id    - (IN)  PTP stack ID.
    117  *      clock_num - (IN)  PTP clock number.
    118  *      counters  - (OUT) Packet counts/statistics.
    119  * Returns:
    120  *      BCM_E_XXX - Function status.
    121  * Notes:
    122  */
    123 int 
    124 bcm_common_ptp_packet_counters_get(
    125     int unit, 
    126     bcm_ptp_stack_id_t ptp_id,
    127     int clock_num, 
    128     bcm_ptp_packet_counters_t *counters)
    129 {   
    130     return _bcm_ptp_packet_counters_msg_get(unit, ptp_id, clock_num, counters);
    131 }
    132 
    133 /*
    134  * Function:
    135  *      _bcm_ptp_packet_counters_msg_get
    136  * Purpose:
    137  *      Get packet counters via custom PTP managment message.
    138  * Parameters:
    139  *      unit      - (IN)  Unit number.
    140  *      ptp_id    - (IN)  PTP stack ID.
    141  *      clock_num - (IN)  PTP clock number.
    142  *      counters  - (OUT) Packet counters.
    143  * Returns:
    144  *      BCM_E_XXX - Function status.
    145  * Notes:
    146  */
    147 static int 
    148 _bcm_ptp_packet_counters_msg_get(
    149     int unit, 
    150     bcm_ptp_stack_id_t ptp_id,
    151     int clock_num, 
    152     bcm_ptp_packet_counters_t *counters)
    153 {   
    154     int rv = BCM_E_UNAVAIL;
    155     
    156     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    157     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 
    158     int i = 0;
    159 
    160     bcm_ptp_port_identity_t portid;  
    161     
    162     int port;
    163     uint16 num_ports;
    164     
    165     *counters = counters_zero;
    166     
    167     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    168             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    169         return rv;   
    170     }
    171         
    172     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 
    173             clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) {
    174         return rv;
    175     }
    176     
    177     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id, 
    178             clock_num, &portid, 
    179             PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PACKET_STATS, 
    180             0, 0, resp, &resp_len))) {
    181         return rv;
    182     }
    183     
    184     if (resp_len < PTP_MGMTMSG_PAYLOAD_PACKET_STATS_MIN_SIZE_OCTETS) {
    185         /* Internal error : message too short to contain correct data. */
    186         return BCM_E_INTERNAL;
    187     }
    188     
    189     /*
    190      * Parse response.
    191      *    Octet 0...5      : Custom management message key/identifier. 
    192      *                       BCM<null><null><null>.
    193      *    Octet 6...7      : Number of ports.    
    194      *    Octet 8...11     : Packets transmitted.
    195      *    Octet 12...15    : Packets received.
    196      *    Octet 16...19    : Packets discarded.
    197      *    Octet 20...23    : RCPU encapsulated packets received.
    198      *    Octet 24...27    : IPv4 packets received.
    199      *    Octet 28...31    : IPv6 packets received.
    200      *    Octet 32...35    : L2 PTP packets received.
    201      *    Octet 36...39    : UDP PTP packets received.
    202      *    Octet 40...43    : Enduro sync packets transmitted.
    203      *    Octet 44...47    : Enduro sync packets received.
    204      *    Octet 48...51    : Rx queue overflows.
    205      *    Per Port: # = Port Number, I = 52 + 12(#-1) 
    206      *    Octet I...I+3    : PTP port # packets transmitted.
    207      *    Octet I+4...I+7  : PTP port # packets received.
    208      *    Octet I+8...I+11 : PTP port # packets discarded.
    209      */
    210     i = 6;    
    211     num_ports = _bcm_ptp_uint16_read(resp+i);
    212     i += sizeof(uint16); 
    213     counters->packets_transmitted = _bcm_ptp_uint32_read(resp+i);
    214     i += sizeof(uint32);
    215     counters->packets_received = _bcm_ptp_uint32_read(resp+i);
    216     i += sizeof(uint32);
    217     counters->packets_discarded = _bcm_ptp_uint32_read(resp+i);
    218     i += sizeof(uint32);
    219     counters->rcpu_encap_packets_received = _bcm_ptp_uint32_read(resp+i);
    220     i += sizeof(uint32);
    221     counters->ipv4_packets_received = _bcm_ptp_uint32_read(resp+i);
    222     i += sizeof(uint32);
    223     counters->ipv6_packets_received = _bcm_ptp_uint32_read(resp+i);
    224     i += sizeof(uint32);
    225     counters->l2_ptp_packets_received = _bcm_ptp_uint32_read(resp+i);
    226     i += sizeof(uint32);
    227     counters->udp_ptp_packets_received = _bcm_ptp_uint32_read(resp+i);
    228     i += sizeof(uint32);
    229     counters->enduro_sync_packets_transmitted = _bcm_ptp_uint32_read(resp+i);
    230     i += sizeof(uint32);
    231     counters->enduro_sync_packets_received = _bcm_ptp_uint32_read(resp+i);
    232     i += sizeof(uint32);
    233     counters->rx_queue_overflows = _bcm_ptp_uint32_read(resp+i);
    234     i += sizeof(uint32);
    235     
    236     for (port = 0; port < num_ports; ++port) {
    237         counters->port_packets_transmitted[port] = _bcm_ptp_uint32_read(resp+i);
    238         i += sizeof(uint32);
    239         counters->port_packets_received[port] = _bcm_ptp_uint32_read(resp+i);
    240         i += sizeof(uint32);
    241         counters->port_packets_discarded[port] = _bcm_ptp_uint32_read(resp+i);
    242         i += sizeof(uint32);
    243     }
    244         
    245     return rv;
    246 }
    247 
    248 
    249 /*
    250  * Function:
    251  *      _bcm_ptp_update_peer_counts
    252  * Purpose:
    253  *      Update peer message counts.
    254  * Parameters: 
    255  *      unit         - (IN) Unit number.
    256  *      ptp_id       - (IN) PTP stack id
    257  *      clock_num    - (IN) PTP clock index
    258  *      localPortNum - (IN) Local PTP clock port number.
    259  *      clockID      - (IN) Peer PTP clock identity.
    260  *      port_addr    - (IN) Peer PTP port address.
    261  *      isMaster     - (IN) Peer-is-master Boolean.
    262  *      announces    - (IN) Number of addt'l announce messages.
    263  *      syncs        - (IN) Number of addt'l sync messages.
    264  *      delayreqs    - (IN) Number of addt'l delay request messages.
    265  *      delayresps   - (IN) Number of addt'l dealy response messages.
    266  *      mgmts        - (IN) Number of addt'l management messages.
    267  *      signals      - (IN) Number of addt'l signaling messages.
    268  *      rejected     - (IN) Number of addt'l rejected messages.
    269  * Returns:
    270  *      BCM_E_XXX - Function status.
    271  * Notes:
    272  */
    273 int
    274 _bcm_ptp_update_peer_counts(
    275     int unit,
    276     int ptp_id,
    277     int clock_num,
    278     uint16 localPortNum,
    279     bcm_ptp_clock_identity_t *clockID,
    280     bcm_ptp_clock_port_address_t *port_addr,
    281     int isMaster,
    282     unsigned announces,
    283     unsigned syncs,
    284     unsigned followups,
    285     unsigned delayreqs,
    286     unsigned delayresps,
    287     unsigned mgmts,
    288     unsigned signals,
    289     unsigned rejected,
    290     bcm_gport_t *phy_port)
    291 {
    292     int         rv = BCM_E_NONE;
    293     unsigned    index;
    294     _bcm_ptp_info_t *ptp_info_p;
    295     int max_peer_dataset_entries;
    296     bcm_ptp_peer_dataset_t *peerTable;
    297 
    298     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    299         return rv;
    300     }
    301 
    302     peerTable = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num].peerTable;
    303 
    304     sal_mutex_take(peerTable->lock, sal_mutex_FOREVER);
    305 
    306     /* Look in the table for a match */
    307     for (index = 0; index < peerTable->num_peers; index++) {
    308         if ((localPortNum == 0xffff) ||
    309             (peerTable->peer[index].local_port_number == 0xffff) ||
    310             (localPortNum == peerTable->peer[index].local_port_number)) {
    311             if (!_bcm_ptp_port_address_cmp(port_addr, &peerTable->peer[index].port_address)) {
    312                 /* We have a match, so inc the counts as listed a return */
    313                 if (isMaster) {
    314                     COMPILER_64_ADD_32(peerTable->peer[index].rx_announces, announces);
    315                     COMPILER_64_ADD_32(peerTable->peer[index].rx_syncs, syncs);
    316                     COMPILER_64_ADD_32(peerTable->peer[index].rx_followups, followups);
    317                     COMPILER_64_ADD_32(peerTable->peer[index].tx_delayreqs, delayreqs);
    318                     COMPILER_64_ADD_32(peerTable->peer[index].rx_delayresps, delayresps);
    319                     COMPILER_64_ADD_32(peerTable->peer[index].tx_mgmts, mgmts);
    320                     COMPILER_64_ADD_32(peerTable->peer[index].tx_signals, signals);
    321                 } else {
    322                     COMPILER_64_ADD_32(peerTable->peer[index].tx_announces, announces);
    323                     COMPILER_64_ADD_32(peerTable->peer[index].tx_syncs, syncs);
    324                     COMPILER_64_ADD_32(peerTable->peer[index].tx_followups, followups);
    325                     COMPILER_64_ADD_32(peerTable->peer[index].rx_delayreqs, delayreqs);
    326                     COMPILER_64_ADD_32(peerTable->peer[index].tx_delayresps, delayresps);
    327                     COMPILER_64_ADD_32(peerTable->peer[index].rx_mgmts, mgmts);
    328                     COMPILER_64_ADD_32(peerTable->peer[index].rx_signals, signals);
    329                 }
    330 
    331                 if (peerTable->peer[index].local_port_number == 0xffff) {
    332                     peerTable->peer[index].local_port_number = localPortNum;
    333                 }
    334 
    335                 COMPILER_64_ADD_32(peerTable->peer[index].rejected, rejected);
    336                 if (clockID) {
    337                     memcpy(peerTable->peer[index].clock_identity, clockID, BCM_PTP_CLOCK_EUID_IEEE1588_SIZE);
    338                 }
    339                 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    340                     if (phy_port) {
    341                         peerTable->peer[index].phy_port = *phy_port;
    342                     }
    343                 }
    344                 sal_mutex_give(peerTable->lock);
    345                 return rv;
    346             }
    347         }
    348     }
    349 
    350     SET_PTP_INFO;
    351 
    352     max_peer_dataset_entries = ptp_info_p->stack_info->unicast_slave_table_size +  
    353                                PTP_MAX_CLOCK_INSTANCE_PORTS + _PTP_MAX_FOREIGN_MASTER_DATASET_ENTRIES;
    354 
    355     /* Make sure we have room */
    356     if (peerTable->num_peers >= max_peer_dataset_entries) {
    357         sal_mutex_give(peerTable->lock);
    358         LOG_VERBOSE(BSL_LS_BCM_PTP,
    359                     (BSL_META_U(unit,
    360                                 "PTP Peer Statistics full, dropping count\n")));
    361         return BCM_E_NONE;
    362     }
    363 
    364     /* Add an entry */
    365     index = peerTable->num_peers;
    366 
    367     peerTable->peer[index].local_port_number = localPortNum;
    368     if (clockID) {
    369         memcpy(peerTable->peer[index].clock_identity, clockID, BCM_PTP_CLOCK_EUID_IEEE1588_SIZE);
    370     } else {
    371         memset(peerTable->peer[index].clock_identity, 0, BCM_PTP_CLOCK_EUID_IEEE1588_SIZE);
    372     }
    373     peerTable->peer[index].port_address = *port_addr;
    374 
    375     if (isMaster) {
    376         COMPILER_64_SET(peerTable->peer[index].rx_announces, 0, announces);
    377         COMPILER_64_SET(peerTable->peer[index].rx_syncs, 0, syncs);
    378         COMPILER_64_SET(peerTable->peer[index].rx_followups, 0, followups);
    379         COMPILER_64_SET(peerTable->peer[index].tx_delayreqs, 0, delayreqs);
    380         COMPILER_64_SET(peerTable->peer[index].rx_delayresps, 0, delayresps);
    381         COMPILER_64_SET(peerTable->peer[index].tx_mgmts, 0, mgmts);
    382         COMPILER_64_SET(peerTable->peer[index].tx_signals, 0, signals);
    383         COMPILER_64_SET(peerTable->peer[index].tx_announces, 0, 0);
    384         COMPILER_64_SET(peerTable->peer[index].tx_syncs, 0, 0);
    385         COMPILER_64_SET(peerTable->peer[index].tx_followups, 0, 0);
    386         COMPILER_64_SET(peerTable->peer[index].rx_delayreqs, 0, 0);
    387         COMPILER_64_SET(peerTable->peer[index].tx_delayresps, 0, 0);
    388         COMPILER_64_SET(peerTable->peer[index].rx_mgmts, 0, 0);
    389         COMPILER_64_SET(peerTable->peer[index].rx_signals, 0, 0);
    390     } else {
    391         COMPILER_64_SET(peerTable->peer[index].tx_announces, 0, announces);
    392         COMPILER_64_SET(peerTable->peer[index].tx_syncs, 0, syncs);
    393         COMPILER_64_SET(peerTable->peer[index].tx_followups, 0, followups);
    394         COMPILER_64_SET(peerTable->peer[index].rx_delayreqs, 0, delayreqs);
    395         COMPILER_64_SET(peerTable->peer[index].tx_delayresps, 0, delayresps);
    396         COMPILER_64_SET(peerTable->peer[index].rx_mgmts, 0, mgmts);
    397         COMPILER_64_SET(peerTable->peer[index].rx_signals, 0, signals);
    398         COMPILER_64_SET(peerTable->peer[index].rx_announces, 0, 0);
    399         COMPILER_64_SET(peerTable->peer[index].rx_syncs, 0, 0);
    400         COMPILER_64_SET(peerTable->peer[index].rx_followups, 0, 0);
    401         COMPILER_64_SET(peerTable->peer[index].tx_delayreqs, 0, 0);
    402         COMPILER_64_SET(peerTable->peer[index].rx_delayresps, 0, 0);
    403         COMPILER_64_SET(peerTable->peer[index].tx_mgmts, 0, 0);
    404         COMPILER_64_SET(peerTable->peer[index].tx_signals, 0, 0);
    405     }
    406     COMPILER_64_SET(peerTable->peer[index].rejected, 0, rejected);
    407     if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    408         if (phy_port) {
    409             peerTable->peer[index].phy_port = *phy_port;
    410         }
    411     }
    412 
    413     peerTable->num_peers++;
    414 
    415     sal_mutex_give(peerTable->lock);
    416 
    417     return rv;
    418 }
    419 
    420 /*
    421  * Function:
    422  *      _bcm_ptp_update_peer_dataset
    423  * Purpose:
    424  *      Update peer dataset.
    425  * Parameters:
    426  *      unit      - (IN) Unit number.
    427  *      ptp_id    - (IN) PTP stack ID.
    428  *      clock_num - (IN) PTP clock number.
    429  *      port_num  - (IN) PTP clock port number.
    430  * Returns:
    431  *      BCM_E_XXX - Function status.
    432  * Notes:
    433  */
    434 int
    435 _bcm_ptp_update_peer_dataset(
    436     int unit,
    437     bcm_ptp_stack_id_t ptp_id,
    438     int clock_num,
    439     int port_num)
    440 {
    441     int rv = BCM_E_NONE;
    442     unsigned firstTime = 1;
    443     unsigned index;
    444     unsigned module_num = 0;
    445     unsigned phy_port_num = 0;
    446     bcm_gport_t phy_port;
    447 
    448     bcm_ptp_port_identity_t portid = portid_all;
    449     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    450     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    451     int expected_per_peerdata_resp_len = 0;
    452     _bcm_ptp_clock_cache_t *clock_cache;
    453 
    454     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, port_num))) {
    455         return rv;
    456     }
    457 
    458     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    459             clock_num, port_num, &portid))) {
    460         return rv;
    461     }
    462     
    463     clock_cache = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num];
    464     if (!clock_cache->in_use)
    465         return BCM_E_UNAVAIL;
    466 
    467     while (1) {
    468         if (firstTime) {
    469             /* Send "first" management message. */
    470             if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    471                     clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PEER_DATASET_FIRST,
    472                     0, 0, resp, &resp_len))) {
    473                 return rv;
    474             }
    475             firstTime = 0;
    476         } else {
    477             if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    478                     clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_PEER_DATASET_NEXT,
    479                     0, 0, resp, &resp_len))) {
    480                 return rv;
    481             }
    482         }
    483 
    484         /*
    485          * Parse response.
    486          *    Octet  0     number of peers in dump set (0 - _PTP_MAX_PEER_DATASET_CHUNK_SIZE)
    487          *    Octet  1     reserved
    488          *    Octet  2..3  PEER#0  Local port num
    489          *    Octet  4..11 PEER#0  Peer clock ID
    490          *    Octet 12     PEER#0  Peer is master
    491          *    Octet 13     PEER#0  Peer address type
    492          *    Octet 14..29 PEER#0  Peer network address
    493          *    Octet 30..31 PEER#0  Announces
    494          *    Octet 32..33 PEER#0  Syncs
    495          *    Octet 34..35 PEER#0  Followups
    496          *    Octet 36..37 PEER#0  delayreqs
    497          *    Octet 38..39 PEER#0  delayresps
    498          *    Octet 40..41 PEER#0  rejected count
    499          *    Octet 41..42 PEER#0  module number
    500          *    Octet 43..44 PEER#0  physical port number
    501          *    Octet 42..81 PEER#1 (as PEER#0)
    502          *    Octet 82....
    503          */
    504 
    505         if (resp_len < 1) {
    506             return BCM_E_INTERNAL;
    507         }
    508 
    509         if (resp[0] > _PTP_MAX_PEER_DATASET_CHUNK_SIZE) {
    510             return BCM_E_INTERNAL;
    511         }
    512 
    513         if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    514             expected_per_peerdata_resp_len = 44;
    515         } else {
    516             expected_per_peerdata_resp_len = 40;
    517         }
    518 
    519         if (resp_len != 2 + resp[0] * expected_per_peerdata_resp_len ) {
    520             return BCM_E_INTERNAL;
    521         }
    522 
    523         /* return when the ToP doesn't have any more elements to send us */
    524         if (resp[0] == 0) {
    525             return (rv);
    526         }
    527 
    528         /* Since we have elements update the tables */
    529         for (index = 0; index < resp[0]; index++) {
    530             bcm_ptp_clock_identity_t clockIDStorage, *clockID;
    531             bcm_ptp_clock_port_address_t port_addr;
    532             int addr_len;
    533             unsigned localPortNum, announces, syncs, followups, delayreqs, delayresps, mgmts, signals, rejected;
    534             int isMaster;
    535 
    536             unsigned offset = 2 + index * expected_per_peerdata_resp_len;
    537 
    538             localPortNum = _bcm_ptp_uint16_read(resp + offset);
    539             offset += 2;
    540 
    541             memcpy(clockIDStorage, resp + offset, BCM_PTP_CLOCK_EUID_IEEE1588_SIZE);
    542             offset += BCM_PTP_CLOCK_EUID_IEEE1588_SIZE;
    543 
    544             isMaster = resp[offset++];
    545 
    546             port_addr.addr_type = resp[offset++];
    547             addr_len = _bcm_ptp_addr_len(port_addr.addr_type);
    548             if (addr_len) {
    549                 memcpy(port_addr.address, resp + offset, addr_len);
    550             } else {
    551                 return BCM_E_INTERNAL;
    552             }
    553             offset += 16;
    554 
    555             announces = _bcm_ptp_uint16_read(resp + offset);
    556             offset += 2;
    557 
    558             syncs = _bcm_ptp_uint16_read(resp + offset);
    559             offset += 2;
    560 
    561             followups = _bcm_ptp_uint16_read(resp + offset);
    562             offset += 2;
    563 
    564             delayreqs = _bcm_ptp_uint16_read(resp + offset);
    565             offset += 2;
    566 
    567             delayresps = _bcm_ptp_uint16_read(resp + offset);
    568             offset += 2;
    569 
    570             mgmts = 0;
    571             signals = 0;
    572 
    573             rejected = _bcm_ptp_uint16_read(resp + offset);
    574             offset += 2;
    575 
    576             if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    577                 module_num = _bcm_ptp_uint16_read(resp + offset);
    578                 offset += 2;
    579                 phy_port_num = _bcm_ptp_uint16_read(resp + offset);
    580                 BCM_GPORT_MODPORT_SET(phy_port, module_num, phy_port_num);
    581             }
    582 
    583             if (_bcm_ptp_is_clockid_null(clockIDStorage)) {
    584                 clockID = 0;
    585             } else {
    586                 clockID = &clockIDStorage;
    587             }
    588 
    589             if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num, localPortNum, clockID,
    590                     &port_addr, isMaster, announces, syncs, followups, delayreqs,
    591                     delayresps, mgmts, signals, rejected, &phy_port))) {
    592                 return rv;
    593             }
    594         }
    595 
    596         /*
    597          * Reset response message length.
    598          * _bcm_ptp_management_message_send() uses argument as maximum allowable 
    599          * message length and actual message lengths on function entry and exit,
    600          * respectively.
    601          */
    602         resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    603     }
    604 
    605     return (rv);
    606 }
    607 
    608 /*
    609  * Function:
    610  *      _bcm_ptp_peer_dataset_get
    611  * Purpose:
    612  *      Get peer dataset(s).
    613  * Parameters:
    614  *      unit          - (IN)  Unit number.
    615  *      ptp_id        - (IN)  PTP stack ID.
    616  *      clock_num     - (IN)  PTP clock number.
    617  *      port_num      - (IN)  PTP clock port number.
    618  *      max_num_peers - (IN)  Maximum number of peer dataset entries.
    619  *      peers         - (OUT) Peers.
    620  *      num_peers     - (OUT) Number of peer dataset entries.
    621  * Returns:
    622  *      BCM_E_XXX - Function status.
    623  * Notes:
    624  *      All-ports identifier (i.e. all-ones port_num) returns all peers.
    625  */
    626 int
    627 _bcm_ptp_peer_dataset_get(
    628     int unit,
    629     bcm_ptp_stack_id_t ptp_id,
    630     int clock_num,
    631     int port_num,
    632     int max_num_peers,
    633     bcm_ptp_peer_entry_t *peers,
    634     int *num_peers)
    635 {
    636     int rv;
    637     static const bcm_ptp_peer_entry_t zero_peer = {0};
    638     bcm_ptp_peer_dataset_t *peerTable;
    639     unsigned peer_index;
    640     unsigned temp_index;
    641 
    642     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, port_num))) {
    643         return rv;
    644     }
    645 
    646     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_dataset(unit, ptp_id, clock_num, port_num))) {
    647         return rv;
    648     }
    649 
    650     peerTable = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num].peerTable;
    651 
    652     sal_mutex_take(peerTable->lock, sal_mutex_FOREVER);
    653 
    654     *num_peers = 0;
    655     for (peer_index = 0; peer_index < peerTable->num_peers; ) {
    656         /* Stop if caller-provided table is full. */
    657         if (*num_peers >= max_num_peers) {
    658             break;
    659         }
    660 
    661         /* Find peers associated with matching local port number. */
    662         if (port_num == peerTable->peer[peer_index].local_port_number ||
    663             port_num == PTP_IEEE1588_ALL_PORTS) {
    664             /* Get matching peer. */
    665             peers[(*num_peers)++] = peerTable->peer[peer_index];
    666 
    667             /* Move remaining peers up in list. */
    668             for (temp_index = peer_index + 1; temp_index < peerTable->num_peers; temp_index++) {
    669                 peerTable->peer[temp_index - 1] = peerTable->peer[temp_index];
    670             }
    671             peerTable->peer[--(peerTable->num_peers)] = zero_peer;
    672         } else {
    673             peer_index++;
    674         }
    675     }
    676 
    677     sal_mutex_give(peerTable->lock);
    678 
    679     return BCM_E_NONE;
    680 }
    681 
    682 /*
    683  * Function:
    684  *      _bcm_ptp_clock_description_get
    685  * Purpose:
    686  *      Get PTP clock description.
    687  * Parameters:
    688  *      unit        - (IN)  Unit number.
    689  *      ptp_id      - (IN)  PTP stack ID.
    690  *      clock_num   - (IN)  PTP clock number.
    691  *      port_num    - (IN)  PTP clock port number.
    692  *      description - (OUT) PTP clock description.
    693  * Returns:
    694  *      BCM_E_XXX - Function status.
    695  * Notes:
    696  */
    697 int
    698 _bcm_ptp_clock_description_get(
    699     int unit,
    700     bcm_ptp_stack_id_t ptp_id,
    701     int clock_num,
    702     int port_num,
    703     _bcm_ptp_clock_description_t *description)
    704 {
    705     int rv = BCM_E_UNAVAIL;
    706 
    707     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    708     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    709 
    710     bcm_ptp_port_identity_t portid;
    711 
    712     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, port_num))) {
    713         return rv;
    714     }
    715 
    716     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    717             clock_num, port_num, &portid))) {
    718         return rv;
    719     }
    720 
    721     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    722             clock_num, &portid, PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CLOCK_DESCRIPTION,
    723             0, 0, resp, &resp_len))) {
    724         return rv;
    725     }
    726 
    727     description->size = resp_len;
    728     description->data = sal_alloc(resp_len,"_bcm_ptp_clock_description_get");
    729     memcpy(description->data,resp,resp_len);
    730     return BCM_E_NONE;
    731 }
    732 
    733 /*
    734  * Function:
    735  *      _bcm_ptp_show_system_info
    736  * Purpose:
    737  *      Report ToP CPU and memory use information to debug stream.
    738  * Parameters:
    739  *      unit      - (IN) Unit number.
    740  *      ptp_id    - (IN) PTP stack ID.
    741  *      clock_num - (IN) PTP clock number.
    742  * Returns:
    743  *      BCM_E_XXX - Function status.
    744  * Notes:
    745  */
    746 int
    747 _bcm_ptp_show_system_info(
    748     int unit,
    749     bcm_ptp_stack_id_t ptp_id,
    750     int clock_num)
    751 {
    752     int rv = BCM_E_UNAVAIL;
    753 
    754     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    755     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    756 
    757     bcm_ptp_port_identity_t portid;
    758 
    759     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    760             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    761         return rv;
    762     }
    763 
    764     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    765             clock_num, PTP_IEEE1588_ALL_PORTS, &portid))) {
    766         return rv;
    767     }
    768 
    769     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    770             clock_num, &portid, PTP_MGMTMSG_CMD, PTP_MGMTMSG_ID_SHOW_SYSTEM_INFO,
    771             0, 0, resp, &resp_len))) {
    772         return rv;
    773     }
    774 
    775     return BCM_E_NONE;
    776 }
    777 
    778 /*
    779  * Function:
    780  *      bcm_common_ptp_peer_dataset_get
    781  * Purpose:
    782  *      Get Peer Dataset
    783  * Parameters:
    784  *      unit          - (IN) Unit number
    785  *      ptp_id        - (IN) PTP stack ID
    786  *      clock_num     - (IN) PTP clock number
    787  *      port_num      - (IN) PTP port number
    788  *      max_num_peers - (IN) max # of peer entries
    789  *      peers         - (OUT) list of peer entries
    790  *      *num_peers    - (OUT) actual # of peer entries returned in peers
    791  * Returns:
    792  *      int
    793  * Notes:
    794  */
    795 int
    796 bcm_common_ptp_peer_dataset_get(
    797     int unit,
    798     bcm_ptp_stack_id_t ptp_id,
    799     int clock_num,
    800     int port_num,
    801     int max_num_peers,
    802     bcm_ptp_peer_entry_t *peers,
    803     int *num_peers)
    804 {
    805     int rc;
    806 
    807     rc = _bcm_ptp_peer_dataset_get(unit, ptp_id, clock_num, port_num, max_num_peers, peers, num_peers);
    808 
    809     return (rc);
    810 }
    811 
    812 int
    813 bcm_common_ptp_clock_port_drop_counters_enable_set(
    814     int unit,
    815     bcm_ptp_stack_id_t ptp_id,
    816     int clock_num,
    817     uint32 clock_port,
    818     int enable)
    819 {
    820     int rv = BCM_E_UNAVAIL;
    821 
    822     uint8 payload[PTP_MGMTMSG_PAYLOAD_PACKET_DROP_STATS_ENABLE_SIZE_OCTETS] = {0};
    823     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    824     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    825 
    826     bcm_ptp_port_identity_t portid;
    827 
    828     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, clock_port))) {
    829             return rv;
    830     }
    831 
    832     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    833             clock_num, clock_port, &portid))) {
    834         return rv;
    835     }
    836 
    837     payload[0] = enable ? 1:0;
    838     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    839             clock_num, &portid, PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_CLOCK_PORTS_DROP_COUNT,
    840             payload, PTP_MGMTMSG_PAYLOAD_PACKET_DROP_STATS_ENABLE_SIZE_OCTETS, resp, &resp_len))) {
    841         return rv;
    842     }
    843 
    844     return rv;
    845 }
    846 
    847 int
    848 bcm_common_ptp_clock_port_drop_counters_get(
    849     int unit,
    850     bcm_ptp_stack_id_t ptp_id,
    851     int clock_num,
    852     uint32 clock_port,
    853     bcm_ptp_clock_port_packet_drop_counters_t *counters)
    854 {
    855     int rv = BCM_E_UNAVAIL;
    856 
    857     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    858     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS;
    859     int i = 0;
    860     bcm_ptp_port_identity_t portid;
    861 
    862     *counters = drop_counters_zero;
    863 
    864     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    865             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    866         return rv;
    867     }
    868 
    869     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
    870             clock_num, clock_port, &portid))) {
    871         return rv;
    872     }
    873 
    874     if (BCM_FAILURE(rv = _bcm_ptp_management_message_send(unit, ptp_id,
    875             clock_num, &portid,
    876             PTP_MGMTMSG_GET, PTP_MGMTMSG_ID_CLOCK_PORTS_DROP_COUNT,
    877             0, 0, resp, &resp_len))) {
    878         return rv;
    879     }
    880 
    881     if (resp_len < PTP_MGMTMSG_PAYLOAD_PACKET_STATS_MIN_SIZE_OCTETS) {
    882         /* Internal error : message too short to contain correct data. */
    883         return BCM_E_INTERNAL;
    884     }
    885     i = 6;
    886     counters->domain_mismatch = _bcm_ptp_uint32_read(resp+i);
    887     i += sizeof(uint32);
    888     counters->memory_alloc_failure = _bcm_ptp_uint32_read(resp+i);
    889     i += sizeof(uint32);
    890     counters->pkt_len_too_short = _bcm_ptp_uint32_read(resp+i);
    891     i += sizeof(uint32);
    892     counters->pkt_rcvd_on_bad_port_state = _bcm_ptp_uint32_read(resp+i);
    893     i += sizeof(uint32);
    894     counters->ptp_profile_mismatch = _bcm_ptp_uint32_read(resp+i);
    895     i += sizeof(uint32);
    896     counters->clock_port_mismatch = _bcm_ptp_uint32_read(resp+i);
    897     i += sizeof(uint32);
    898     counters->ptp_packet_parsing_failure = _bcm_ptp_uint32_read(resp+i);
    899     i += sizeof(uint32);
    900     counters->unicast_delreq_from_unknown_slave = _bcm_ptp_uint32_read(resp+i);
    901     i += sizeof(uint32);
    902 
    903     counters->announce_rcvd_on_master_only_port = _bcm_ptp_uint32_read(resp+i);
    904     i += sizeof(uint32);
    905     counters->announce_rcvd_with_invalid_steps_removed_field = _bcm_ptp_uint32_read(resp+i);
    906     i += sizeof(uint32);
    907     counters->announce_from_unknown_unicast_master = _bcm_ptp_uint32_read(resp+i);
    908     i += sizeof(uint32);
    909     counters->announce_rcvd_on_gps_timesource_ptp_port = _bcm_ptp_uint32_read(resp+i);
    910     i += sizeof(uint32);
    911 
    912     counters->sync_rcvd_invalid = _bcm_ptp_uint32_read(resp+i);
    913     i += sizeof(uint32);
    914     counters->sync_rcvd_on_ptp_port_without_master = _bcm_ptp_uint32_read(resp+i);
    915     i += sizeof(uint32);
    916 
    917     return rv;
    918 }
    919 #endif /* defined(INCLUDE_PTP)*/