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

signaling.c (129128B)


      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:    signaling.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      bcm_common_ptp_signaled_unicast_master_add
     13  *      bcm_common_ptp_signaled_unicast_master_remove
     14  *      bcm_common_ptp_signaled_unicast_slave_list
     15  *      bcm_common_ptp_signaled_unicast_slave_table_clear
     16  *      bcm_common_ptp_unicast_request_duration_get
     17  *      bcm_common_ptp_unicast_request_duration_set
     18  *      bcm_common_ptp_unicast_request_duration_min_get
     19  *      bcm_common_ptp_unicast_request_duration_min_set
     20  *      bcm_common_ptp_unicast_request_duration_max_get
     21  *      bcm_common_ptp_unicast_request_duration_max_set
     22  *
     23  *      _bcm_ptp_register_signaling_arbiter
     24  *      _bcm_ptp_unregister_signaling_arbiter
     25  *      _bcm_ptp_signaling_init
     26  *      _bcm_ptp_signaling_manager
     27  *      _bcm_ptp_signaled_unicast_master_table_init
     28  *      _bcm_ptp_signaled_unicast_master_table_reset
     29  *      _bcm_ptp_signaled_unicast_slave_table_init
     30  *      _bcm_ptp_signaled_unicast_slave_table_reset
     31  *      _bcm_ptp_signaled_unicast_slave_exists
     32  *      _bcm_ptp_signaled_unicast_slave_add
     33  *      _bcm_ptp_signaled_unicast_slave_remove
     34  *      _bcm_ptp_signaled_unicast_slave_expire
     35  *      _bcm_ptp_signaled_unicast_slave_table_update
     36  *      send_unicast_request
     37  *      _bcm_ptp_master_active_service_cancel
     38  *      _bcm_ptp_master_active_service_ack_cancel
     39  *      _bcm_ptp_slave_signaling_send
     40  *      send_pending_signaling_to_masters
     41  *      _bcm_ptp_slave_signaling_request_deny
     42  *      _bcm_ptp_slave_signaling_gateway
     43  *      _bcm_ptp_parse_signaling_message
     44  *      _bcm_ptp_make_peer_from_signaling_msg
     45  *      _bcm_ptp_process_incoming_signaling_msg
     46  *      delayed_master_table_update
     47  */
     48 
     49 #if defined(INCLUDE_PTP)
     50 
     51 #ifdef BCM_HIDE_DISPATCHABLE
     52 #undef BCM_HIDE_DISPATCHABLE
     53 #endif
     54 
     55 #include <shared/bsl.h>
     56 #include <shared/util.h>
     57 
     58 #include <soc/defs.h>
     59 #include <soc/drv.h>
     60 
     61 #include <sal/appl/io.h>
     62 #include <sal/core/libc.h>
     63 #include <sal/core/alloc.h>
     64 #include <sal/core/time.h>
     65 #include <shared/bitop.h>
     66 #include <bcm/ptp.h>
     67 #include <bcm_int/common/ptp.h>
     68 #include <bcm_int/ptp_common.h>
     69 
     70 /* Parameters and constants. */
     71 #define BCM_PTP_SIGNAL_LOGINTERMSG_PERIOD_NONGRANT   (0x7f)
     72 #define BCM_PTP_SIGNAL_REQUEST_DENY_DURATION_SEC     (0)
     73 
     74 #define BCM_PTP_SIGNAL_GRANT_UNICAST_RENEWAL_INVITED (1)
     75 #define BCM_PTP_SIGNAL_TELECOM_GRANT_UNICAST_RENEWAL_INVITED (0)
     76 
     77 #define BCM_PTP_SIGNAL_MIN_SLAVE_DPC_TIME_USEC       (50)
     78 #define BCM_PTP_SIGNAL_DEFAULT_SLAVE_DPC_TIME_USEC   (1000000)
     79 #define BCM_PTP_SIGNAL_SLAVE_MUTEX_TIMEOUT_USEC      (50000)
     80 
     81 #define BCM_PTP_SIGNAL_REQUEST_UC_MINIMUM_DURATION_SEC (10)
     82 #define BCM_PTP_SIGNAL_REQUEST_UC_DEFAULT_DURATION_SEC (300)
     83 #define BCM_PTP_SIGNAL_REQUEST_UC_MAXIMUM_DURATION_SEC (1000)
     84 
     85 #define BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_MINIMUM_DURATION_SEC (60)
     86 #define BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_DEFAULT_DURATION_SEC (300)
     87 #define BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_MAXIMUM_DURATION_SEC (1000)
     88 
     89 #define BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_MAX                (3)
     90 #define BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_QUERY_INTERVAL_SEC (60)
     91 
     92 #define BCM_PTP_SIGNAL_MIN_MASTER_DPC_TIME_USEC      (50)
     93 #define BCM_PTP_SIGNAL_DEFAULT_MASTER_DPC_TIME_USEC  (1000000)
     94 
     95 #define BCM_PTP_UDP_HEADER_LENGTH_BYTES              (8)
     96 #define BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS             (44)
     97 #define BCM_PTP_SIGNAL_MIN_TLV_SIZE_OCTETS           (6)
     98 #define BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS           (12)
     99 
    100 #define BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE           (3)
    101 #define BCM_PTP_SIGNAL_MAX_MULTI_TLV_SIZE_OCTETS     (BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS * \
    102                                                       BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE)
    103 
    104 #define BCM_PTP_SIGNAL_MIN_UDP_PAYLOAD_SIZE_OCTETS   (BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS + \
    105                                                       BCM_PTP_SIGNAL_MIN_TLV_SIZE_OCTETS)
    106 #define BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS   (BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS + \
    107                                                       BCM_PTP_SIGNAL_MAX_MULTI_TLV_SIZE_OCTETS)
    108 #define BCM_PTP_SIGNAL_MAX_PKT_SIZE_OCTETS           (PTP_MSG_L2_HEADER_LENGTH + 40 + \
    109                                                       PTP_UDPHDR_SIZE_OCTETS + \
    110                                                       BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS)
    111 
    112 /* Macros. */
    113 #define BCM_PTP_SLAVETABLE_MUTEX_TAKE() \
    114     PTP_MUTEX_TAKE(slaveTable_mutex, BCM_PTP_SIGNAL_SLAVE_MUTEX_TIMEOUT_USEC)
    115 
    116 #define BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(__rv__) \
    117     PTP_MUTEX_RELEASE_RETURN(slaveTable_mutex, __rv__)
    118 
    119 /* Types. */
    120 typedef struct _bcm_ptp_msg_services_s {
    121     uint8 announce;
    122     uint8 sync;
    123     uint8 delayresp;
    124 } _bcm_ptp_msg_services_t;
    125 
    126 typedef struct signaled_master_s {
    127     sal_time_t announce_refresh_time, sync_refresh_time, delay_refresh_time;
    128     int8 log_announce_interval, log_sync_interval, log_delay_interval;
    129     int8 granted_log_sync_interval, granted_log_delay_interval;
    130     uint32 query_interval_sec;
    131     uint32 durationField;
    132     uint16 sequenceId;
    133 
    134     _bcm_ptp_msg_services_t service_enable;
    135     _bcm_ptp_msg_services_t service_grants;
    136     _bcm_ptp_msg_services_t to_ack_cancel;
    137     _bcm_ptp_msg_services_t unmet_requests;
    138 
    139     bcm_ptp_clock_peer_t master;
    140 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    141 	int8 update_servo;
    142 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    143 } signaled_master_t;
    144 
    145 typedef struct _bcm_ptp_signaled_slave_s {
    146     sal_time_t announce_request_time;
    147     sal_time_t sync_request_time;
    148     sal_time_t delay_request_time;
    149 
    150     sal_time_t announce_grant_time;
    151     sal_time_t sync_grant_time;
    152     sal_time_t delay_grant_time;
    153 
    154     sal_time_t announce_cancel_time;
    155     sal_time_t sync_cancel_time;
    156     sal_time_t delay_cancel_time;
    157 
    158 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
    159     sal_time_t announce_ack_time;
    160     sal_time_t sync_ack_time;
    161     sal_time_t delay_ack_time;
    162 
    163     sal_time_t announce_expire_time;
    164     sal_time_t sync_expire_time;
    165     sal_time_t delay_expire_time;
    166 #endif
    167 
    168     uint8 announce_service_active;
    169     uint8 sync_service_active;
    170     uint8 delay_service_active;
    171 
    172     uint8 queue_announce_grant;
    173     uint8 queue_sync_grant;
    174     uint8 queue_delay_grant;
    175 
    176     uint8 announce_service_changed;
    177     uint8 sync_service_changed;
    178     uint8 delay_service_changed;
    179 
    180     uint8 queue_announce_cancel;
    181     uint8 queue_sync_cancel;
    182     uint8 queue_delay_cancel;
    183 
    184     uint8 queue_announce_expire;
    185     uint8 queue_sync_expire;
    186     uint8 queue_delay_expire;
    187 
    188     uint32 announce_duration;
    189     uint32 sync_duration;
    190     uint32 delay_duration;
    191 
    192     uint16 sequenceId;
    193 
    194     _bcm_ptp_clock_peer_ext_t slave;
    195 } _bcm_ptp_signaled_slave_t;
    196 
    197 typedef struct _bcm_ptp_signaled_slave_table_s {
    198     uint16 num_entries;
    199     _bcm_ptp_signaled_slave_t entry[PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES];
    200 } _bcm_ptp_signaled_slave_table_t;
    201 
    202 typedef struct unit_sig_info_s {
    203     bcm_ptp_signaling_arbiter_t arbiter;
    204     void * arbiter_user_data;
    205     
    206     shr_rdpc_t send_pending_signaling_to_masters_rdpc;
    207     shr_rdpc_t send_pending_signaling_to_slaves_rdpc;
    208 } unit_sig_info_t;
    209 
    210 /* Variables. */
    211 static int signaling_initialized = 0;        
    212 static int signaling_initialized_slave = 0;  
    213 static unit_sig_info_t unit_sig_array[BCM_MAX_NUM_UNITS] = {{0}};
    214 
    215 static signaled_master_t signaled_master[PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES] = {{0}};   
    216 static volatile int num_signaled_masters = 0;  
    217 
    218 static _bcm_ptp_signaled_slave_t signaled_slave_entry_default = {0};
    219 static _bcm_ptp_signaled_slave_table_t signaled_slave_table;    
    220 static _bcm_ptp_mutex_t slaveTable_mutex = 0x0;     
    221 
    222 static bcm_ptp_clock_identity_t BCM_PTP_ALL_CLOCKS = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
    223 static uint16 BCM_PTP_ANY_PORT = 0xFFFF;  /* From the standard: port 65535 => any/every port */
    224 
    225 static uint32 request_uc_durationField = BCM_PTP_SIGNAL_REQUEST_UC_DEFAULT_DURATION_SEC;
    226 static uint32 request_uc_durationField_min = BCM_PTP_SIGNAL_REQUEST_UC_MINIMUM_DURATION_SEC;
    227 static uint32 request_uc_durationField_max = BCM_PTP_SIGNAL_REQUEST_UC_MAXIMUM_DURATION_SEC;
    228 
    229 static int renewal_invited = BCM_PTP_SIGNAL_GRANT_UNICAST_RENEWAL_INVITED;
    230 
    231 /* Static functions. */
    232 static int send_unicast_request(int unit, bcm_ptp_stack_id_t ptp_id, int clock_num,
    233     int num_tlvs, int *type, int8 *log_inter_message_period, uint32 durationField,
    234     uint16 sequenceId, bcm_ptp_clock_peer_t *master);
    235 static int _bcm_ptp_master_active_service_cancel(int unit, bcm_ptp_stack_id_t ptp_id,
    236     int clock_num, signaled_master_t *entry, bcm_ptp_message_type_t messageType);
    237 static int _bcm_ptp_master_active_service_ack_cancel(int unit, bcm_ptp_stack_id_t ptp_id,
    238     int clock_num, signaled_master_t *entry, bcm_ptp_message_type_t messageType);
    239 static sal_usecs_t send_pending_signaling_to_masters(void **arg_unit, void **arg_ptp_id,
    240                                               void **arg_clock_num, void **unused);
    241 static void delayed_master_table_update(void *owner, void *arg_unit, void *arg_ptp_id,
    242                                         void *arg_clock_num, void *unused);
    243 
    244 static int _bcm_ptp_slave_signaling_send(int unit, bcm_ptp_stack_id_t ptp_id,
    245     int clock_num, bcm_ptp_tlv_type_t tlv_type, bcm_ptp_message_type_t msg_type,
    246     int8 log_intermessage_period, uint32 duration, uint16 sequenceId, _bcm_ptp_clock_peer_ext_t *slave, int async);
    247 static int _bcm_ptp_slave_signaling_request_deny(int unit, bcm_ptp_stack_id_t ptp_id,
    248     int clock_num, bcm_ptp_message_type_t msg_type, int8 log_intermessage_period,
    249     _bcm_ptp_clock_peer_ext_t *slave);
    250 static sal_usecs_t send_pending_signaling_to_slaves(void **arg_unit, void **arg_ptp_id,
    251                                              void **arg_clock_num, void **unused);
    252 
    253 static int _bcm_ptp_signaled_unicast_master_table_init(int unit, bcm_ptp_stack_id_t ptp_id);
    254 static int _bcm_ptp_signaled_unicast_master_table_cleanup(int unit, bcm_ptp_stack_id_t ptp_id);
    255 static int _bcm_ptp_signaled_unicast_slave_table_init(int unit, bcm_ptp_stack_id_t ptp_id);
    256 static int _bcm_ptp_signaled_unicast_slave_table_cleanup(int unit, bcm_ptp_stack_id_t ptp_id);
    257 
    258 /*
    259  * Function:
    260  *      _bcm_ptp_register_signaling_arbiter
    261  * Purpose:
    262  *      Register a callback function to accept or reject PTP signaling messages.
    263  * Parameters:
    264  *      unit      - (IN) Unit number.
    265  *      arb       - (IN) PTP signaling message arbiter function pointer.
    266  *      user_data - (IN) User data.
    267  * Returns:
    268  *      BCM_E_XXX - Function status.
    269  */
    270 int
    271 _bcm_ptp_register_signaling_arbiter(
    272     int unit,
    273     bcm_ptp_signaling_arbiter_t arb,
    274     void *user_data)
    275 {
    276     int rv = BCM_E_NONE;
    277     unit_sig_array[unit].arbiter = arb;
    278     unit_sig_array[unit].arbiter_user_data = user_data;
    279 
    280     return rv;
    281 }
    282 
    283 /*
    284  * Function:
    285  *      _bcm_ptp_unregister_signaling_arbiter
    286  * Purpose:
    287  *      Unregister a PTP signaling message arbiter.
    288  * Parameters:
    289  *      unit - (IN) Unit number.
    290  * Returns:
    291  *      BCM_E_XXX - Function status.
    292  */
    293 int
    294 _bcm_ptp_unregister_signaling_arbiter(
    295     int unit)
    296 {
    297     int rv = BCM_E_NONE;
    298     unit_sig_array[unit].arbiter = NULL;
    299     unit_sig_array[unit].arbiter_user_data = NULL;
    300 
    301     return rv;
    302 }
    303 
    304 
    305 /*
    306  * Function:
    307  *      _bcm_ptp_signaling_init
    308  * Purpose:
    309  *      Initialize the BCM PTP signaling message framework.
    310  * Parameters:
    311  *      unit   - (IN) Unit number.
    312  *      ptp_id - (IN) PTP stack ID.
    313  * Returns:
    314  *      BCM_E_XXX - Function status.
    315  * Notes:
    316  */
    317 int
    318 _bcm_ptp_signaling_init(
    319     int unit,
    320     bcm_ptp_stack_id_t ptp_id)
    321 {
    322     int rv;
    323     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    324             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    325         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    326         return rv;
    327     }
    328 
    329     if (shr_rdpc_callback_created(&unit_sig_array[unit].send_pending_signaling_to_masters_rdpc) == BCM_E_INIT) {
    330         /* RDPC (and associated lock) is left in place on cleanup, so only create it once */
    331         shr_rdpc_callback_create(&unit_sig_array[unit].send_pending_signaling_to_masters_rdpc, &send_pending_signaling_to_masters);
    332     }
    333 
    334     if (shr_rdpc_callback_created(&unit_sig_array[unit].send_pending_signaling_to_slaves_rdpc) == BCM_E_INIT) {
    335         /* RDPC (and associated lock) is left in place on cleanup, so only create it once */
    336         shr_rdpc_callback_create(&unit_sig_array[unit].send_pending_signaling_to_slaves_rdpc, &send_pending_signaling_to_slaves);
    337     }
    338 
    339     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_master_table_init(unit, ptp_id))) {
    340         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_master_table_init()");
    341         return rv;
    342     }
    343 
    344     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_master_table_reset(unit, ptp_id))) {
    345         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_master_table_reset()");
    346         return rv;
    347     }
    348 
    349     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_init(unit, ptp_id))) {
    350         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_table_init()");
    351         return rv;
    352     }
    353 
    354     return BCM_E_NONE;
    355 }
    356 
    357 /*
    358  * Function:
    359  *      _bcm_ptp_signaling_cleanup
    360  * Purpose:
    361  *      Uninitializes signaling framework
    362  * Parameters:
    363  *      unit       - (IN) Unit number.
    364  *      ptp_id     - (IN) PTP stack ID.
    365  */
    366 int _bcm_ptp_signaling_cleanup(int unit, bcm_ptp_stack_id_t ptp_id)
    367 {
    368     int rv = BCM_E_NONE;
    369 
    370     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_master_table_cleanup(unit, ptp_id))) {
    371         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_master_table_cleanup()");
    372         return rv;
    373     }
    374 
    375     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_cleanup(unit, ptp_id))) {
    376         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_master_table_cleanup()");
    377         return rv;
    378     }
    379 
    380     return BCM_E_NONE;
    381 }
    382 
    383 /*
    384  * Function:
    385  *      _bcm_ptp_signaling_manager
    386  * Purpose:
    387  *      Manage configurable attributes based on active PTP profile.
    388  * Parameters:
    389  *      unit       - (IN) Unit number.
    390  *      ptp_id     - (IN) PTP stack ID.
    391  *      clock_num  - (IN) PTP clock number.
    392  *      en_telecom - (IN) Telecom profile enabled Boolean.
    393  * Returns:
    394  *      BCM_E_XXX - Function status.
    395  */
    396 int
    397 _bcm_ptp_signaling_manager(
    398     int unit,
    399     bcm_ptp_stack_id_t ptp_id,
    400     int clock_num,
    401     int en_telecom)
    402 {
    403     int rv;
    404     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    405             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    406         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    407         return rv;
    408     }
    409 
    410     
    411     if (0 == en_telecom) {
    412         /* Standard profile. */
    413         request_uc_durationField = BCM_PTP_SIGNAL_REQUEST_UC_DEFAULT_DURATION_SEC;
    414         request_uc_durationField_min = BCM_PTP_SIGNAL_REQUEST_UC_MINIMUM_DURATION_SEC;
    415         request_uc_durationField_max = BCM_PTP_SIGNAL_REQUEST_UC_MAXIMUM_DURATION_SEC;
    416 
    417         renewal_invited = BCM_PTP_SIGNAL_GRANT_UNICAST_RENEWAL_INVITED;
    418     } else {
    419         /* Telecom profile. */
    420         request_uc_durationField = BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_DEFAULT_DURATION_SEC;
    421         request_uc_durationField_min = BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_MINIMUM_DURATION_SEC;
    422         request_uc_durationField_max = BCM_PTP_SIGNAL_TELECOM_REQUEST_UC_MAXIMUM_DURATION_SEC;
    423 
    424         renewal_invited = BCM_PTP_SIGNAL_TELECOM_GRANT_UNICAST_RENEWAL_INVITED;
    425     }
    426 
    427     return BCM_E_NONE;
    428 }
    429 
    430 /*
    431  * Function:
    432  *      _bcm_ptp_signaled_unicast_master_table_init
    433  * Purpose:
    434  *      Initialize the periodic check to see if signaling messages need to be sent to masters
    435  * Parameters:
    436  *      unit   - (IN) Unit number.
    437  *      ptp_id - (IN) PTP stack ID.
    438  * Returns:
    439  *      BCM_E_XXX - Function status.
    440  * Notes:
    441  */
    442 int
    443 _bcm_ptp_signaled_unicast_master_table_init(
    444     int unit,
    445     bcm_ptp_stack_id_t ptp_id)
    446 {
    447     int rv;
    448 
    449     request_uc_durationField = BCM_PTP_SIGNAL_REQUEST_UC_DEFAULT_DURATION_SEC;
    450     request_uc_durationField_min = BCM_PTP_SIGNAL_REQUEST_UC_MINIMUM_DURATION_SEC;
    451     request_uc_durationField_max = BCM_PTP_SIGNAL_REQUEST_UC_MAXIMUM_DURATION_SEC;
    452 
    453     renewal_invited = BCM_PTP_SIGNAL_GRANT_UNICAST_RENEWAL_INVITED;
    454 
    455     signaling_initialized = 1;
    456 
    457     rv = shr_rdpc_callback_start(&unit_sig_array[unit].send_pending_signaling_to_masters_rdpc,
    458                                  BCM_PTP_SIGNAL_DEFAULT_MASTER_DPC_TIME_USEC,
    459                                  INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(PTP_CLOCK_NUMBER_DEFAULT), INT_TO_PTR(0));
    460     return rv;
    461 }
    462 
    463 /*
    464  * Function:
    465  *      _bcm_ptp_signaled_unicast_master_table_reset
    466  * Purpose:
    467  *      Reset signaled unicast master table.
    468  * Parameters:
    469  *      unit   - (IN) Unit number.
    470  *      ptp_id - (IN) PTP stack ID.
    471  * Returns:
    472  *      BCM_E_XXX - Function status.
    473  * Notes:
    474  */
    475 int
    476 _bcm_ptp_signaled_unicast_master_table_reset(
    477     int unit,
    478     bcm_ptp_stack_id_t ptp_id)
    479 {
    480     num_signaled_masters = 0;
    481     return BCM_E_NONE;
    482 }
    483 
    484 /*
    485  * Function:
    486  *      _bcm_ptp_signaled_unicast_master_table_cleanup
    487  * Purpose:
    488  *      Uninitialize signaled master table in preparation for stack deletion
    489  * Parameters:
    490  *      unit   - (IN) Unit number.
    491  *      ptp_id - (IN) PTP stack ID.
    492  */
    493 
    494 int _bcm_ptp_signaled_unicast_master_table_cleanup(
    495     int unit,
    496     bcm_ptp_stack_id_t ptp_id)
    497 {
    498     return shr_rdpc_callback_stop(&unit_sig_array[unit].send_pending_signaling_to_masters_rdpc);
    499 }
    500 
    501 
    502 /*
    503  * Function:
    504  *      _bcm_ptp_signaled_unicast_slave_table_init
    505  * Purpose:
    506  *      Initialize the signaled unicast slave table and framework to manage
    507  *      signaling messages sent to slaves.
    508  * Parameters:
    509  *      unit   - (IN) Unit number.
    510  *      ptp_id - (IN) PTP stack ID.
    511  * Returns:
    512  *      BCM_E_XXX - Function status.
    513  * Notes:
    514  */
    515 int
    516 _bcm_ptp_signaled_unicast_slave_table_init(
    517     int unit,
    518     bcm_ptp_stack_id_t ptp_id)
    519 {
    520     int rv;
    521 
    522     if (!slaveTable_mutex) {
    523         slaveTable_mutex = _bcm_ptp_mutex_create("signaled_slave_table");
    524         if (!slaveTable_mutex) {
    525             return BCM_E_MEMORY;
    526         }
    527     }
    528 
    529     if (signaling_initialized_slave) {
    530         /* Reset signaled unicast slave table. */
    531         if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_reset(unit, ptp_id))) {
    532             PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_table_reset()");
    533             return rv;
    534         }
    535     }
    536 
    537     signaling_initialized_slave = 1;
    538 
    539     rv = shr_rdpc_callback_start(&unit_sig_array[unit].send_pending_signaling_to_slaves_rdpc,
    540                                  BCM_PTP_SIGNAL_DEFAULT_SLAVE_DPC_TIME_USEC,
    541                                  INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(PTP_CLOCK_NUMBER_DEFAULT), INT_TO_PTR(0));
    542 
    543     return rv;
    544 }
    545 
    546 /*
    547  * Function:
    548  *      _bcm_ptp_signaled_unicast_slave_table_reset
    549  * Purpose:
    550  *      Reset signaled unicast slave table.
    551  * Parameters:
    552  *      unit   - (IN) Unit number.
    553  *      ptp_id - (IN) PTP stack ID.
    554  * Returns:
    555  *      BCM_E_XXX - Function status.
    556  * Notes:
    557  */
    558 int
    559 _bcm_ptp_signaled_unicast_slave_table_reset(
    560     int unit,
    561     bcm_ptp_stack_id_t ptp_id)
    562 {
    563     int i;
    564 
    565     signaled_slave_table.num_entries = 0;
    566     for (i = 0; i < PTP_MAX_UNICAST_SLAVE_TABLE_ENTRIES; ++i) {
    567         signaled_slave_table.entry[i] = signaled_slave_entry_default;
    568     }
    569 
    570     return BCM_E_NONE;
    571 }
    572 
    573 /*
    574  * Function:
    575  *      _bcm_ptp_signaled_unicast_slave_table_cleanup
    576  * Purpose:
    577  *      Uninitialize signaled slave table in preparation for stack deletion
    578  * Parameters:
    579  *      unit   - (IN) Unit number.
    580  *      ptp_id - (IN) PTP stack ID.
    581  */
    582 int
    583 _bcm_ptp_signaled_unicast_slave_table_cleanup(
    584     int unit,
    585     bcm_ptp_stack_id_t ptp_id)
    586 {
    587     int rv;
    588     rv = shr_rdpc_callback_stop(&unit_sig_array[unit].send_pending_signaling_to_slaves_rdpc);
    589 
    590     if (BCM_FAILURE(rv)) {
    591         PTP_ERROR_FUNC("Failed to stop Slave Signaling DPC");
    592         return rv;
    593     }
    594 
    595     _bcm_ptp_mutex_destroy(slaveTable_mutex);
    596     slaveTable_mutex = 0;
    597     signaling_initialized_slave = 0;
    598 
    599     return BCM_E_NONE;
    600 }
    601 
    602 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    603 int
    604 _bcm_ptp_signaled_unicast_master_index_get(
    605     int unit,
    606     bcm_ptp_stack_id_t ptp_id,
    607     int clock_num,
    608     bcm_ptp_port_identity_t *master_portId,
    609     int *inst_num)
    610 {
    611     int idx;
    612 
    613     for (idx = 0; idx < num_signaled_masters; ++idx) {
    614         if (_bcm_ptp_peer_portid_compare((bcm_ptp_port_identity_t *)&signaled_master[idx].master,
    615                 master_portId)) {
    616             *inst_num = idx;
    617             return BCM_E_NONE;
    618         }
    619     }
    620 
    621     return BCM_E_NOT_FOUND;
    622 }
    623 
    624 #if 0
    625 int _bcm_ptp_signaled_unicast_master_log_sync_int_get(
    626     int unit,
    627     bcm_ptp_stack_id_t ptp_id,
    628     int clock_num,
    629     int idx,
    630     int8 *log_sync_int)
    631 {
    632     if ((idx < PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES) && (idx < num_signaled_masters))
    633         *log_sync_int = signaled_master[idx].granted_log_sync_interval;
    634         return BCM_E_NONE;
    635 
    636     return BCM_E_BADID;
    637 }
    638 
    639 int _bcm_ptp_signaled_unicast_master_log_delay_int_get(
    640     int unit,
    641     bcm_ptp_stack_id_t ptp_id,
    642     int clock_num,
    643     int idx,
    644     int8 *log_delay_int)
    645 {
    646     if ((idx < PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES) && (idx < num_signaled_masters))
    647         *log_delay_int = signaled_master[idx].granted_log_delay_interval;
    648         return BCM_E_NONE;
    649 
    650     return BCM_E_BADID;
    651 }
    652 
    653 int
    654 _bcm_ptp_signaled_unicast_master_log_int_get(
    655     int unit,
    656     bcm_ptp_stack_id_t ptp_id,
    657     int clock_num,
    658     bcm_ptp_port_identity_t *master_portId,
    659     int *inst_num,
    660     int8 *log_sync_int,
    661     int8 *log_delay_int)
    662 {
    663     int idx;
    664 
    665     for (idx = 0; idx < num_signaled_masters; ++idx) {
    666         if (_bcm_ptp_peer_portid_compare((bcm_ptp_port_identity_t *)&signaled_master[idx].master,
    667                 master_portId)) {
    668             *inst_num = idx;
    669             *log_sync_int = signaled_master[idx].granted_log_sync_interval;
    670             *log_delay_int = signaled_master[idx].granted_log_delay_interval;
    671             return BCM_E_NONE;
    672         }
    673     }
    674 
    675     return BCM_E_NOT_FOUND;
    676 }
    677 #endif
    678 
    679 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    680 
    681 /*
    682  * Function:
    683  *      bcm_common_ptp_signaled_unicast_master_add
    684  * Purpose:
    685  *      Add an entry to the signaled unicast master table.
    686  * Parameters:
    687  *      unit               - (IN) Unit number.
    688  *      ptp_id             - (IN) PTP stack ID.
    689  *      clock_num          - (IN) PTP clock number.
    690  *      port_num           - (IN) PTP clock port number.
    691  *      master_info        - (IN) Unicast master.
    692  *      flags              - (IN) Signaled unicast master configuration flags.
    693  * Returns:
    694  *      BCM_E_XXX - Function status.
    695  * Notes:
    696  */
    697 int
    698 bcm_common_ptp_signaled_unicast_master_add(
    699     int unit,
    700     bcm_ptp_stack_id_t ptp_id,
    701     int clock_num,
    702     int port_num,
    703     bcm_ptp_clock_unicast_master_t *master_info,
    704     uint32 flags)
    705 {
    706     int rv;
    707     int idx;
    708     sal_time_t t;
    709 
    710     _bcm_ptp_port_state_t portState;
    711 
    712     SHR_BITDCL reqmask = flags;
    713 
    714     /* Telecom profile support. */
    715     bcm_ptp_clock_port_address_t address;
    716 
    717     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    718             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    719         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    720         return rv;
    721     }
    722 
    723     if (!signaling_initialized) {
    724         _bcm_ptp_signaled_unicast_master_table_init(unit, ptp_id);
    725     }
    726 
    727     /* Do not add unicast master if portState is DISABLED. */
    728     if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_port_state_get(unit,
    729             ptp_id, clock_num, port_num, &portState))) {
    730         return rv;
    731     } else if (portState == _bcm_ptp_state_disabled) {
    732         return BCM_E_DISABLED;
    733     }
    734     
    735     /*
    736      * Scan signaled unicast master table for an entry with matching address.
    737      *    If match found, indexing logic shall replace existing entry.
    738      *    Otherwise, indexing logic shall append a new entry to table.
    739      */
    740     for (idx = 0; idx < num_signaled_masters; ++idx) {
    741         if (_bcm_ptp_peer_address_compare(&signaled_master[idx].master.peer_address,
    742                 &master_info->address)) {
    743             break;
    744         }
    745     }
    746 
    747     if (idx == PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES) {
    748         return BCM_E_FULL;
    749     }
    750 
    751     signaled_master[idx].master.peer_address = master_info->address;
    752     signaled_master[idx].master.local_port_number = port_num;
    753     signaled_master[idx].master.remote_port_number = BCM_PTP_ANY_PORT;
    754     sal_memcpy(signaled_master[idx].master.clock_identity,
    755                BCM_PTP_ALL_CLOCKS, sizeof(bcm_ptp_clock_identity_t));
    756 
    757     signaled_master[idx].log_announce_interval = master_info->log_announce_interval;
    758     signaled_master[idx].log_sync_interval = master_info->log_sync_interval;
    759     signaled_master[idx].log_delay_interval = master_info->log_min_delay_request_interval;
    760 
    761     /* Before telling firmware to add the master, indicate that DelReqs are not yet allowed */
    762     master_info->log_min_delay_request_interval = BCM_PTP_SIGNAL_LOGINTERMSG_PERIOD_NONGRANT;
    763 
    764     if (BCM_FAILURE(rv = bcm_ptp_static_unicast_master_add(unit, ptp_id, clock_num,
    765             port_num, master_info))) {
    766         return rv;
    767     }
    768 
    769     /* Register PTP message services. */
    770     if (SHR_BITGET(&reqmask, PTP_SIGNALING_ANNOUNCE_SERVICE_BIT)) {
    771         signaled_master[idx].service_enable.announce = 1;
    772     } else {
    773         signaled_master[idx].service_enable.announce = 0;
    774     }
    775     if (SHR_BITGET(&reqmask, PTP_SIGNALING_SYNC_SERVICE_BIT)) {
    776         signaled_master[idx].service_enable.sync = 1;
    777     } else {
    778         signaled_master[idx].service_enable.sync = 0;
    779     }
    780     if (SHR_BITGET(&reqmask, PTP_SIGNALING_DELAYRESP_SERVICE_BIT)) {
    781         signaled_master[idx].service_enable.delayresp = 1;
    782     } else {
    783         signaled_master[idx].service_enable.delayresp = 0;
    784     }
    785 
    786     signaled_master[idx].service_grants.announce = 0;
    787     signaled_master[idx].service_grants.sync = 0;
    788     signaled_master[idx].service_grants.delayresp = 0;
    789 
    790     signaled_master[idx].to_ack_cancel.announce = 0;
    791     signaled_master[idx].to_ack_cancel.sync = 0;
    792     signaled_master[idx].to_ack_cancel.delayresp = 0;
    793 
    794     signaled_master[idx].unmet_requests.announce = 0;
    795     signaled_master[idx].unmet_requests.sync = 0;
    796     signaled_master[idx].unmet_requests.delayresp = 0;
    797 
    798     /* 2 seconds: plenty long to get signaling response */
    799     signaled_master[idx].granted_log_sync_interval = 1;
    800     signaled_master[idx].granted_log_delay_interval = BCM_PTP_SIGNAL_LOGINTERMSG_PERIOD_NONGRANT;
    801 
    802     t = _bcm_ptp_monotonic_time();
    803     signaled_master[idx].announce_refresh_time = t;
    804     signaled_master[idx].sync_refresh_time = t;
    805     signaled_master[idx].delay_refresh_time = t;
    806 
    807     if (master_info->log_query_interval < 0) {
    808         signaled_master[idx].query_interval_sec = 1;
    809     } else {
    810         signaled_master[idx].query_interval_sec = (1 << master_info->log_query_interval);
    811     }
    812 
    813     signaled_master[idx].durationField = request_uc_durationField;
    814     signaled_master[idx].sequenceId = 0;
    815 
    816     if (idx == num_signaled_masters) {
    817         num_signaled_masters++;
    818     }
    819 
    820     /*
    821      * Telecom profile support.
    822      * Register signaled unicast master in packet master array.
    823      */
    824     _bcm_ptp_peer_address_convert(&master_info->address, &address);
    825     if (BCM_FAILURE(rv = bcm_ptp_telecom_g8265_packet_master_add(unit, ptp_id,
    826             clock_num, port_num, &address))) {
    827         return rv;
    828     }
    829 
    830 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    831     signaled_master[idx].update_servo = 1;
    832 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    833 
    834     return BCM_E_NONE;
    835 }
    836 
    837 
    838 /*
    839  * Function:
    840  *      bcm_common_ptp_signaled_unicast_master_remove
    841  * Purpose:
    842  *      Remove an entry from the signaled unicast master table.
    843  * Parameters:
    844  *      unit        - (IN) Unit number.
    845  *      ptp_id      - (IN) PTP stack ID.
    846  *      clock_num   - (IN) PTP clock number.
    847  *      port_num    - (IN) PTP clock port number.
    848  *      master_info - (IN) Unicast master.
    849  * Returns:
    850  *      BCM_E_XXX - Function status.
    851  * Notes:
    852  */
    853 int
    854 bcm_common_ptp_signaled_unicast_master_remove(
    855     int unit,
    856     bcm_ptp_stack_id_t ptp_id,
    857     int clock_num,
    858     int port_num,
    859     bcm_ptp_clock_peer_address_t *address)
    860 {
    861     int status;
    862     int idx = 0;
    863     int rv;
    864 
    865     /* Telecom profile support. */
    866     bcm_ptp_clock_port_address_t profile_address;
    867 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    868     bcm_ptp_port_identity_t mstr_portId;
    869     int inst_num;
    870 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    871 
    872     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    873             clock_num, port_num))) {
    874         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    875         return rv;
    876     }
    877 
    878     status = bcm_ptp_static_unicast_master_remove(unit, ptp_id, clock_num, port_num, address);
    879     if (status != BCM_E_NONE) {
    880         return status;
    881     }
    882 
    883     _bcm_ptp_peer_address_convert(address, &profile_address);
    884 
    885     while (idx < num_signaled_masters) {
    886         if (_bcm_ptp_peer_address_compare(&signaled_master[idx].master.peer_address,
    887                 address)) {
    888             /* Cancel active unicast message services. */
    889             _bcm_ptp_master_active_service_cancel(unit, ptp_id, clock_num,
    890                 &signaled_master[idx], bcmPTP_MESSAGE_TYPE_ANNOUNCE);
    891             _bcm_ptp_master_active_service_cancel(unit, ptp_id, clock_num,
    892                 &signaled_master[idx], bcmPTP_MESSAGE_TYPE_SYNC);
    893             _bcm_ptp_master_active_service_cancel(unit, ptp_id, clock_num,
    894                 &signaled_master[idx], bcmPTP_MESSAGE_TYPE_DELAY_RESP);
    895 
    896 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    897             sal_memcpy(mstr_portId.clock_identity, &signaled_master[idx].master.clock_identity, sizeof(bcm_ptp_clock_identity_t));
    898             mstr_portId.port_number= signaled_master[idx].master.remote_port_number;
    899 
    900             if (BCM_FAILURE(rv = _bcm_ptp_ext_servo_master_table_entry_delete(unit, ptp_id, clock_num, &mstr_portId, &profile_address, 1, &inst_num))) {
    901                 PTP_ERROR_FUNC("_bcm_ptp_ext_servo_master_table_entry_delete()");
    902 				inst_num = idx;
    903             }
    904 
    905             if (BCM_FAILURE(rv = _bcm_ptp_servo_master_remove(unit, ptp_id, clock_num, inst_num, 1, &mstr_portId, NULL, &profile_address))) {
    906                 PTP_ERROR_FUNC("_bcm_ptp_servo_master_remove()");
    907             }
    908 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    909 
    910             /* Swap the last entry into this place, then decrement total number.  Could be in place... */
    911             signaled_master[idx] = signaled_master[--num_signaled_masters];
    912         } else {
    913             ++idx;
    914         }
    915     }
    916 
    917     if (BCM_FAILURE(rv = bcm_ptp_telecom_g8265_packet_master_remove(unit, ptp_id,
    918             clock_num, port_num, &profile_address))) {
    919         return rv;
    920     }
    921 
    922     return BCM_E_NONE;
    923 }
    924 
    925 
    926 /*
    927  * Function:
    928  *      bcm_ptp_signaled_unicast_slave_list
    929  * Purpose:
    930  *      List the signaled unicast slaves.
    931  * Parameters:
    932  *      unit           - (IN)  Unit number.
    933  *      ptp_id         - (IN)  PTP stack ID.
    934  *      clock_num      - (IN)  PTP clock number.
    935  *      port_num       - (IN)  PTP clock port number.
    936  *      max_num_slaves - (IN)  Maximum number of signaled unicast slaves.
    937  *      num_slaves     - (OUT) Number of signaled unicast slaves.
    938  *      slave_table    - (OUT) Signaled unicast slave table.
    939  * Returns:
    940  *      BCM_E_XXX - Function status.
    941  * Notes:
    942  */
    943 int
    944 bcm_common_ptp_signaled_unicast_slave_list (
    945     int unit,
    946     bcm_ptp_stack_id_t ptp_id,
    947     int clock_num,
    948     int port_num,
    949     int max_num_slaves,
    950     int *num_slaves,
    951     bcm_ptp_clock_peer_t *slave_table)
    952 {
    953     int i;
    954     int rv;
    955 
    956     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    957             clock_num, port_num))) {
    958         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
    959         return rv;
    960     }
    961 
    962     BCM_PTP_SLAVETABLE_MUTEX_TAKE();
    963 
    964     if (signaled_slave_table.num_entries > max_num_slaves) {
    965         /* Insufficient caller-provided table size for result. */
    966         *num_slaves = 0;
    967 
    968         BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(BCM_E_RESOURCE);
    969     }
    970 
    971     *num_slaves = signaled_slave_table.num_entries;
    972 
    973     for (i = 0; i < (*num_slaves); ++i) {
    974         slave_table[i] = signaled_slave_table.entry[i].slave.peer;
    975     }
    976 
    977     BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(rv);
    978 }
    979 
    980 
    981 /*
    982  * Function:
    983  */
    984 static int
    985 _bcm_ptp_signaled_unicast_slave_exists(
    986     int unit,
    987     bcm_ptp_stack_id_t ptp_id,
    988     _bcm_ptp_clock_peer_ext_t *slave,
    989     int *index)
    990 {
    991     int i;
    992     for (i = 0; i < signaled_slave_table.num_entries; ++i) {
    993         if (_bcm_ptp_peer_address_compare(&signaled_slave_table.entry[i].slave.peer.peer_address,
    994                 &slave->peer.peer_address)) {
    995             /* Entry exists. */
    996             *index = i;
    997             return BCM_E_NONE;
    998         }
    999     }
   1000 
   1001     *index = -1;
   1002     return BCM_E_NOT_FOUND;
   1003 }
   1004 
   1005 /*
   1006  * Function:
   1007  */
   1008 static int
   1009 _bcm_ptp_signaled_unicast_slave_add(
   1010     int unit,
   1011     bcm_ptp_stack_id_t ptp_id,
   1012     _bcm_ptp_clock_peer_ext_t *slave)
   1013 {
   1014     int i;
   1015     int rv;
   1016     _bcm_ptp_info_t *ptp_info_p;
   1017 
   1018     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1019             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1020         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1021         return rv;
   1022     }
   1023 
   1024     SET_PTP_INFO;
   1025 
   1026     if (signaled_slave_table.num_entries >= ptp_info_p->stack_info->unicast_slave_table_size) {
   1027         /* Signaled unicast slave table full. */
   1028         return BCM_E_FULL;
   1029     }
   1030 
   1031     /* Add entry. */
   1032     i = signaled_slave_table.num_entries++;
   1033     signaled_slave_table.entry[i] = signaled_slave_entry_default;
   1034     signaled_slave_table.entry[i].slave = *slave;
   1035 
   1036     return BCM_E_NONE;
   1037 }
   1038 
   1039 /*
   1040  * Function:
   1041  */
   1042 static int
   1043 _bcm_ptp_signaled_unicast_slave_remove(
   1044     int unit,
   1045     bcm_ptp_stack_id_t ptp_id,
   1046     _bcm_ptp_clock_peer_ext_t *slave)
   1047 {
   1048     int i = 0;
   1049     int k = 0;
   1050     int rv;
   1051 
   1052     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1053             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1054         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1055         return rv;
   1056     }
   1057 
   1058     while (i < signaled_slave_table.num_entries) {
   1059         if (_bcm_ptp_peer_address_compare(&slave->peer.peer_address,
   1060                 &signaled_slave_table.entry[i].slave.peer.peer_address)) {
   1061             /*
   1062              * Remove entry.
   1063              * Move last entry into this slot, and decrement number of entries.
   1064              */
   1065             signaled_slave_table.entry[i] =
   1066                 signaled_slave_table.entry[--signaled_slave_table.num_entries];
   1067 
   1068             /* Reset unused entry. */
   1069             signaled_slave_table.entry[signaled_slave_table.num_entries] =
   1070                 signaled_slave_entry_default;
   1071 
   1072             ++k;
   1073         } else {
   1074             ++i;
   1075         }
   1076     }
   1077 
   1078     if (k > 0) {
   1079         return BCM_E_NONE;
   1080     } else {
   1081         /* No matching peer address(es) in signaled unicast slave table. */
   1082         return BCM_E_NOT_FOUND;
   1083     }
   1084 }
   1085 
   1086 /*
   1087  * Function:
   1088  */
   1089 static int
   1090 _bcm_ptp_signaled_unicast_slave_expire(
   1091     int unit,
   1092     bcm_ptp_stack_id_t ptp_id)
   1093 {
   1094     int i;
   1095     int rv;
   1096     sal_time_t t = _bcm_ptp_monotonic_time();
   1097 
   1098     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1099             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1100         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1101         return rv;
   1102     }
   1103 
   1104     /*
   1105      * Tag signaled slave announce, sync, and delay response services that
   1106      * are to expire.
   1107      */
   1108     for (i = 0; i < signaled_slave_table.num_entries; ++i) {
   1109         if ((!signaled_slave_table.entry[i].announce_service_active) ||
   1110             (signaled_slave_table.entry[i].queue_announce_grant) ||
   1111             (signaled_slave_table.entry[i].announce_grant_time +
   1112              signaled_slave_table.entry[i].announce_duration >= t)) {
   1113             signaled_slave_table.entry[i].queue_announce_expire = 0;
   1114         } else {
   1115             signaled_slave_table.entry[i].queue_announce_expire = 1;
   1116         }
   1117 
   1118         if ((!signaled_slave_table.entry[i].sync_service_active) ||
   1119             (signaled_slave_table.entry[i].queue_sync_grant) ||
   1120             (signaled_slave_table.entry[i].sync_grant_time +
   1121              signaled_slave_table.entry[i].sync_duration >= t)) {
   1122             signaled_slave_table.entry[i].queue_sync_expire = 0;
   1123         } else {
   1124             signaled_slave_table.entry[i].queue_sync_expire = 1;
   1125         }
   1126 
   1127         if ((!signaled_slave_table.entry[i].delay_service_active) ||
   1128             (signaled_slave_table.entry[i].queue_delay_grant) ||
   1129             (signaled_slave_table.entry[i].delay_grant_time +
   1130              signaled_slave_table.entry[i].delay_duration >= t)) {
   1131             signaled_slave_table.entry[i].queue_delay_expire = 0;
   1132         } else {
   1133             signaled_slave_table.entry[i].queue_delay_expire = 1;
   1134         }
   1135     }
   1136 
   1137     return BCM_E_NONE;
   1138 }
   1139 
   1140 /*
   1141  * Function:
   1142  */
   1143 static int
   1144 _bcm_ptp_signaled_unicast_slave_table_update(
   1145     int unit,
   1146     bcm_ptp_stack_id_t ptp_id)
   1147 {
   1148     int i;
   1149     int rv;
   1150     int num_entries;
   1151 
   1152     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1153             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1154         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1155         return rv;
   1156     }
   1157     /*
   1158      * Remove inactive/expired slaves from signaled unicast slave table.
   1159      * NOTICE: Process table in reverse given logic in removal function
   1160      *         _bcm_ptp_signaled_unicast_slave_remove() to reorder entries.
   1161      */
   1162     num_entries = signaled_slave_table.num_entries;
   1163     for (i = (num_entries-1); i >= 0; --i) {
   1164         if ((signaled_slave_table.entry[i].queue_announce_grant == 0) &&
   1165             (signaled_slave_table.entry[i].queue_sync_grant == 0) &&
   1166             (signaled_slave_table.entry[i].queue_delay_grant == 0) &&
   1167             (signaled_slave_table.entry[i].queue_announce_cancel == 0) &&
   1168             (signaled_slave_table.entry[i].queue_sync_cancel == 0) &&
   1169             (signaled_slave_table.entry[i].queue_delay_cancel == 0) &&
   1170             (signaled_slave_table.entry[i].queue_announce_expire == 0) &&
   1171             (signaled_slave_table.entry[i].queue_sync_expire == 0) &&
   1172             (signaled_slave_table.entry[i].queue_delay_expire == 0) &&
   1173             (signaled_slave_table.entry[i].announce_service_active == 0) &&
   1174             (signaled_slave_table.entry[i].sync_service_active == 0) &&
   1175             (signaled_slave_table.entry[i].delay_service_active == 0)) {
   1176             /*
   1177              * Remove slave.
   1178              *    No pending unicast grant, cancel, or acknowledge cancel TLVs to send.
   1179              *    All slave announce, sync, and delay services are inactive or expired.
   1180              */
   1181             _bcm_ptp_clock_peer_ext_t slave = signaled_slave_table.entry[i].slave;
   1182             _bcm_ptp_signaled_unicast_slave_remove(unit, ptp_id, &slave);
   1183         }
   1184     }
   1185 
   1186     return BCM_E_NONE;
   1187 }
   1188 
   1189 /*
   1190  * Function:
   1191  */
   1192 static int
   1193 send_unicast_request(
   1194     int unit,
   1195     bcm_ptp_stack_id_t ptp_id,
   1196     int clock_num,
   1197     int num_tlvs,
   1198     int *type,
   1199     int8 *log_inter_message_period,
   1200     uint32 durationField,
   1201     uint16 sequenceId,
   1202     bcm_ptp_clock_peer_t *master)
   1203 {
   1204     int rv = BCM_E_NONE;
   1205     int i;
   1206 
   1207     bcm_ptp_port_identity_t local_port;
   1208     bcm_ptp_clock_port_address_t master_addr;
   1209     bcm_ptp_clock_info_t ci;
   1210     bcm_ptp_clock_port_info_t pi;
   1211 
   1212     int tlvLen;
   1213     int udpLen;
   1214     int packet_len;
   1215     uint8 udp[BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS] = {0};
   1216     uint8 packet[BCM_PTP_SIGNAL_MAX_PKT_SIZE_OCTETS] = {0};
   1217     uint8 tlv[BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS] = {0};
   1218     uint8 multi_tlv_en = 0;
   1219     uint8 domain;
   1220 
   1221     static int failure_count = 0;
   1222     static const int failure_log_threshold = 10;
   1223 
   1224     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1225             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1226         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1227         return rv;
   1228     }
   1229 
   1230     if (BCM_SUCCESS(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   1231         multi_tlv_en = (SHR_BITGET(&ci.flags, PTP_CLOCK_FLAGS_SIGNALING_MULTI_TLV_BIT) ||
   1232                         SHR_BITGET(&ci.flags, PTP_CLOCK_FLAGS_TELECOM_PROFILE_BIT));
   1233     }
   1234 
   1235     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
   1236             clock_num, master->local_port_number, &local_port))) {
   1237         PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()");
   1238         return rv;
   1239     }
   1240 
   1241     if (BCM_FAILURE(rv = bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num,
   1242             local_port.port_number, &pi))) {
   1243         PTP_ERROR_FUNC("bcm_ptp_clock_port_info_get()");
   1244         return rv;
   1245     }
   1246 
   1247     if (BCM_FAILURE(rv = _bcm_ptp_management_domain_get(unit, ptp_id, clock_num,
   1248             &domain))) {
   1249         PTP_ERROR_FUNC("_bcm_ptp_management_domain_get()");
   1250         return rv;
   1251     }
   1252 
   1253     if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_msg(&local_port,
   1254             master->clock_identity, master->remote_port_number,
   1255             domain, sequenceId, 0, 0, udp, &udpLen))) {
   1256         PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_msg()");
   1257         return rv;
   1258     }
   1259 
   1260     if (num_tlvs > 1 && multi_tlv_en == 0) {
   1261         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1262                     (BSL_META_U(unit,
   1263                                 "Multiple TLV support not enabled\n")));
   1264         return BCM_E_CONFIG;
   1265     }
   1266 
   1267     for (i = 0; i < num_tlvs; ++i) {
   1268         if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_request_tlv(type[i],
   1269                 log_inter_message_period[i], durationField, tlv, &tlvLen))) {
   1270             PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_request_tlv()");
   1271             return rv;
   1272         }
   1273 
   1274         if (BCM_FAILURE(rv = _bcm_ptp_signaling_message_append_tlv(udp, &udpLen,
   1275                 tlv, tlvLen))) {
   1276             PTP_ERROR_FUNC("_bcm_ptp_signaling_message_append_tlv()");
   1277             return rv;
   1278         }
   1279     }
   1280 
   1281     if (BCM_FAILURE(rv = _bcm_ptp_construct_udp_packet(master, &pi.port_address,
   1282             udp, udpLen, packet, &packet_len))) {
   1283         PTP_ERROR_FUNC("_bcm_ptp_construct_udp_packet()");
   1284         return rv;
   1285     }
   1286 
   1287     if (BCM_FAILURE(rv = _bcm_ptp_peer_address_convert(&master->peer_address, &master_addr))) {
   1288         PTP_ERROR_FUNC("_bcm_ptp_peer_address_convert()");
   1289         return rv;
   1290     }
   1291     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num,
   1292             master->local_port_number, 0, &master_addr,
   1293             1, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
   1294         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1295         return rv;
   1296     }
   1297     if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, ptp_id, clock_num,
   1298                              packet_len, packet, 0))) {
   1299         if (++failure_count > failure_log_threshold) {
   1300             LOG_ERROR(BSL_LS_BCM_PTP,
   1301                       (BSL_META_U(unit,
   1302                                   "Repeated PTP failures sending signaling message\n")));
   1303         } else {
   1304             LOG_VERBOSE(BSL_LS_BCM_PTP,
   1305                         (BSL_META_U(unit,
   1306                                   "PTP failed sending signaling message\n")));
   1307         }
   1308         return rv;
   1309     } else {
   1310         failure_count = 0;
   1311     }
   1312 
   1313     return BCM_E_NONE;
   1314 }
   1315 
   1316 /*
   1317  * Function:
   1318  *      _bcm_ptp_master_active_service_cancel
   1319  * Purpose:
   1320  *      Cancel unicast message service (|Announce|Sync|Delay_Resp|) of unicast master.
   1321  * Parameters:
   1322  *      unit        - (IN)     Unit number.
   1323  *      ptp_id      - (IN)     PTP stack ID.
   1324  *      clock_num   - (IN)     PTP clock number.
   1325  *      entry       - (IN/OUT) Signaled unicast master table entry.
   1326  *      messageType - (IN)     Unicast message service to cancel.
   1327  * Returns:
   1328  *      BCM_E_XXX - Function status.
   1329  * Notes:
   1330  */
   1331 static int
   1332 _bcm_ptp_master_active_service_cancel(
   1333     int unit,
   1334     bcm_ptp_stack_id_t ptp_id,
   1335     int clock_num,
   1336     signaled_master_t *entry,
   1337     bcm_ptp_message_type_t messageType)
   1338 {
   1339     int rv;
   1340 
   1341     bcm_ptp_port_identity_t local_port;
   1342     bcm_ptp_clock_port_address_t master_addr;
   1343     bcm_ptp_clock_port_info_t pi;
   1344     uint8 domainNumber;
   1345 
   1346     uint8 tlv[BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS] = {0};
   1347     uint8 udp[BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS] = {0};
   1348     uint8 packet[BCM_PTP_SIGNAL_MAX_PKT_SIZE_OCTETS] = {0};
   1349     int tlvLen;
   1350     int udpLen;
   1351     int packet_len;
   1352 
   1353     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1354             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1355         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1356         return rv;
   1357     }
   1358 
   1359     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
   1360             clock_num, entry->master.local_port_number, &local_port))) {
   1361         PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()");
   1362         return rv;
   1363     }
   1364 
   1365     if (BCM_FAILURE(rv = bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num,
   1366             local_port.port_number, &pi))) {
   1367         PTP_ERROR_FUNC("bcm_ptp_clock_port_info_get()");
   1368         return rv;
   1369     }
   1370 
   1371     if (BCM_FAILURE(rv = _bcm_ptp_management_domain_get(unit, ptp_id, clock_num,
   1372             &domainNumber))) {
   1373         PTP_ERROR_FUNC("_bcm_ptp_management_domain_get()");
   1374         return rv;
   1375     }
   1376 
   1377     switch (messageType) {
   1378     case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   1379         if (0 == entry->service_grants.announce) {
   1380             /* Do nothing. Announce service is not active. */
   1381             return BCM_E_NONE;
   1382         }
   1383         entry->service_grants.announce = 0;
   1384         break;
   1385     case bcmPTP_MESSAGE_TYPE_SYNC:
   1386         if (0 == entry->service_grants.sync) {
   1387             /* Do nothing. Sync service is not active. */
   1388             return BCM_E_NONE;
   1389         }
   1390         entry->service_grants.sync = 0;
   1391         break;
   1392     case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   1393         if (0 == entry->service_grants.delayresp) {
   1394             /* Do nothing. Delay_Resp service is not active. */
   1395             return BCM_E_NONE;
   1396         }
   1397         entry->service_grants.delayresp = 0;
   1398         break;
   1399     default:
   1400         return BCM_E_PARAM;
   1401     }
   1402 
   1403     if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_cancel_tlv(messageType,
   1404             tlv, &tlvLen))) {
   1405         PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_cancel_tlv()");
   1406         return rv;
   1407     }
   1408 
   1409     if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_msg(&local_port,
   1410             entry->master.clock_identity, entry->master.remote_port_number,
   1411             domainNumber, ++entry->sequenceId, tlv, tlvLen, udp, &udpLen))) {
   1412         PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_msg()");
   1413         return rv;
   1414     }
   1415 
   1416     if (BCM_FAILURE(rv = _bcm_ptp_construct_udp_packet(&entry->master, &pi.port_address,
   1417             udp, udpLen, packet, &packet_len))) {
   1418         PTP_ERROR_FUNC("_bcm_ptp_construct_udp_packet()");
   1419         return rv;
   1420     }
   1421 
   1422     if (BCM_FAILURE(rv = _bcm_ptp_peer_address_convert(&entry->master.peer_address, &master_addr))) {
   1423         PTP_ERROR_FUNC("_bcm_ptp_peer_address_convert()");
   1424         return rv;
   1425     }
   1426     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num,
   1427             entry->master.local_port_number, 0, &master_addr,
   1428             1, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
   1429         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1430         return rv;
   1431     }
   1432 
   1433     if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, ptp_id, clock_num,
   1434                                packet_len, packet, 0))) {
   1435         PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_world()");
   1436         return rv;
   1437     }
   1438 
   1439     return BCM_E_NONE;
   1440 }
   1441 
   1442 /*
   1443  * Function:
   1444  *      _bcm_ptp_master_active_service_ack_cancel
   1445  * Purpose:
   1446  *      Acknowledge cancellation of (|Announce|Sync|Delay_Resp|) message service by unicast master.
   1447  * Parameters:
   1448  *      unit        - (IN)     Unit number.
   1449  *      ptp_id      - (IN)     PTP stack ID.
   1450  *      clock_num   - (IN)     PTP clock number.
   1451  *      entry       - (IN/OUT) Signaled unicast master table entry.
   1452  *      messageType - (IN)     Unicast message service to acknowledge cancellation.
   1453  * Returns:
   1454  *      BCM_E_XXX - Function status.
   1455  * Notes:
   1456  */
   1457 static int
   1458 _bcm_ptp_master_active_service_ack_cancel(
   1459     int unit,
   1460     bcm_ptp_stack_id_t ptp_id,
   1461     int clock_num,
   1462     signaled_master_t *entry,
   1463     bcm_ptp_message_type_t messageType)
   1464 {
   1465     int rv;
   1466 
   1467     bcm_ptp_port_identity_t local_port;
   1468     bcm_ptp_clock_port_address_t master_addr;
   1469     bcm_ptp_clock_port_info_t pi;
   1470     uint8 domainNumber;
   1471 
   1472     uint8 tlv[BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS] = {0};
   1473     uint8 udp[BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS] = {0};
   1474     uint8 packet[BCM_PTP_SIGNAL_MAX_PKT_SIZE_OCTETS] = {0};
   1475     int tlvLen;
   1476     int udpLen;
   1477     int packet_len;
   1478 
   1479     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1480             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1481         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1482         return rv;
   1483     }
   1484 
   1485     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id,
   1486             clock_num, entry->master.local_port_number, &local_port))) {
   1487         PTP_ERROR_FUNC("bcm_common_ptp_clock_port_identity_get()");
   1488         return rv;
   1489     }
   1490 
   1491     if (BCM_FAILURE(rv = bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num,
   1492             local_port.port_number, &pi))) {
   1493         PTP_ERROR_FUNC("bcm_ptp_clock_port_info_get()");
   1494         return rv;
   1495     }
   1496 
   1497     if (BCM_FAILURE(rv = _bcm_ptp_management_domain_get(unit, ptp_id, clock_num,
   1498             &domainNumber))) {
   1499         PTP_ERROR_FUNC("_bcm_ptp_management_domain_get()");
   1500         return rv;
   1501     }
   1502 
   1503     switch (messageType) {
   1504     case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   1505         if (0 == entry->to_ack_cancel.announce) {
   1506             /* Do nothing. Announce service was not cancelled by master. */
   1507             return BCM_E_NONE;
   1508         }
   1509         entry->to_ack_cancel.announce = 0;
   1510         break;
   1511     case bcmPTP_MESSAGE_TYPE_SYNC:
   1512         if (0 == entry->to_ack_cancel.sync) {
   1513             /* Do nothing. Sync service was not cancelled by master. */
   1514             return BCM_E_NONE;
   1515         }
   1516         entry->to_ack_cancel.sync = 0;
   1517         break;
   1518     case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   1519         if (0 == entry->to_ack_cancel.delayresp) {
   1520             /* Do nothing. Delay_Resp service was not cancelled by master. */
   1521             return BCM_E_NONE;
   1522         }
   1523         entry->to_ack_cancel.delayresp = 0;
   1524         break;
   1525     default:
   1526         return BCM_E_PARAM;
   1527     }
   1528 
   1529     if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_ack_cancel_tlv(messageType,
   1530             tlv, &tlvLen))) {
   1531         PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_ack_cancel_tlv()");
   1532         return rv;
   1533     }
   1534 
   1535     if (BCM_FAILURE(rv = _bcm_ptp_construct_signaling_msg(&local_port,
   1536             entry->master.clock_identity, entry->master.remote_port_number,
   1537             domainNumber, ++entry->sequenceId, tlv, tlvLen, udp, &udpLen))) {
   1538         PTP_ERROR_FUNC("_bcm_ptp_construct_signaling_msg()");
   1539         return rv;
   1540     }
   1541 
   1542     if (BCM_FAILURE(rv = _bcm_ptp_construct_udp_packet(&entry->master, &pi.port_address,
   1543             udp, udpLen, packet, &packet_len))) {
   1544         PTP_ERROR_FUNC("_bcm_ptp_construct_udp_packet()");
   1545         return rv;
   1546     }
   1547 
   1548     if (BCM_FAILURE(rv = _bcm_ptp_peer_address_convert(&entry->master.peer_address, &master_addr))) {
   1549         PTP_ERROR_FUNC("_bcm_ptp_peer_address_convert()");
   1550         return rv;
   1551     }
   1552     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num,
   1553             entry->master.local_port_number, 0, &master_addr,
   1554             1, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
   1555         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1556         return rv;
   1557     }
   1558 
   1559     if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, ptp_id, clock_num,
   1560                                packet_len, packet, 1))) {
   1561         PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_world()");
   1562         return rv;
   1563     }
   1564 
   1565     return BCM_E_NONE;
   1566 }
   1567 
   1568 /*
   1569  * Function:
   1570  */
   1571 static int
   1572 _bcm_ptp_slave_signaling_send(
   1573     int unit,
   1574     bcm_ptp_stack_id_t ptp_id,
   1575     int clock_num,
   1576     bcm_ptp_tlv_type_t tlv_type,
   1577     bcm_ptp_message_type_t msg_type,
   1578     int8 log_intermessage_period,
   1579     uint32 duration,
   1580     uint16 sequenceId,
   1581     _bcm_ptp_clock_peer_ext_t *slave,
   1582     int async)
   1583 {
   1584     bcm_ptp_port_identity_t local_port_id;
   1585     bcm_ptp_clock_port_address_t slave_addr;
   1586     uint8 tlv[BCM_PTP_SIGNAL_MAX_TLV_SIZE_OCTETS];
   1587     uint8 udp[BCM_PTP_SIGNAL_MAX_UDP_PAYLOAD_SIZE_OCTETS];
   1588     uint8 packet[BCM_PTP_SIGNAL_MAX_PKT_SIZE_OCTETS];
   1589     int packet_len;
   1590     int udpLen;
   1591     int tlvLen;
   1592     int rv;
   1593     uint8 domain;
   1594 
   1595     static int failure_count = 0;
   1596     static const int failure_log_threshold = 10;
   1597 
   1598     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1599             clock_num, slave->peer.local_port_number))) {
   1600         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1601         return rv;
   1602     }
   1603 
   1604     if (BCM_FAILURE(bcm_common_ptp_clock_port_identity_get(unit, ptp_id, clock_num,
   1605                                                         slave->peer.local_port_number, &local_port_id))) {
   1606         return BCM_E_PARAM;
   1607     }
   1608 
   1609     switch (tlv_type) {
   1610     case bcmPTPTlvTypeGrantUnicastTransmission:
   1611         _bcm_ptp_construct_signaling_grant_tlv(msg_type, log_intermessage_period,
   1612             duration, renewal_invited, tlv, &tlvLen);
   1613         break;
   1614 
   1615     case bcmPTPTlvTypeCancelUnicastTransmission:
   1616         _bcm_ptp_construct_signaling_cancel_tlv(msg_type, tlv, &tlvLen);
   1617         break;
   1618 
   1619     case bcmPTPTlvTypeAckCancelUnicastTransmission:
   1620         _bcm_ptp_construct_signaling_ack_cancel_tlv(msg_type, tlv, &tlvLen);
   1621         break;
   1622 
   1623     default:
   1624         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1625                     (BSL_META_U(unit,
   1626                                 "Unknown or unsupported TLV type\n")));
   1627         return BCM_E_PARAM;
   1628     }
   1629 
   1630     _bcm_ptp_management_domain_get(unit, ptp_id, clock_num, &domain);
   1631     _bcm_ptp_construct_signaling_msg(&local_port_id, slave->peer.clock_identity,
   1632         slave->peer.remote_port_number, domain, sequenceId, tlv, tlvLen, udp, &udpLen);
   1633 
   1634     _bcm_ptp_construct_udp_packet(&slave->peer, &slave->local_address, udp, udpLen, packet, &packet_len);
   1635 
   1636 #if 0
   1637     bsl_printf(" _bcm_ptp_construct_signaling_msg: UDP payload len[%d]\n", udpLen);
   1638     _bcm_ptp_dump_hex(udp, udpLen, 0);
   1639     bsl_printf(" _bcm_ptp_construct_signaling_msg: packet: len[%d]\n", packet_len);
   1640     _bcm_ptp_dump_hex(packet, packet_len, 0);
   1641 #endif
   1642 
   1643     if (BCM_FAILURE(rv = _bcm_ptp_peer_address_convert(&slave->peer.peer_address, &slave_addr))) {
   1644         PTP_ERROR_FUNC("_bcm_ptp_peer_address_convert()");
   1645         return rv;
   1646     }
   1647     if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num,
   1648             slave->peer.local_port_number, 0, &slave_addr,
   1649             1, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) {
   1650         PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()");
   1651         return rv;
   1652     }
   1653 
   1654     if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message_to_world(unit, ptp_id, clock_num,
   1655                                                           packet_len, packet, async)))
   1656     {
   1657         if (++failure_count > failure_log_threshold) {
   1658             LOG_ERROR(BSL_LS_BCM_COMMON,
   1659                 (BSL_META_U(unit,
   1660                  "Repeated PTP failures sending signaling message to %s slave\n"),
   1661                  (async) ? "async" : ""));
   1662         } else {
   1663             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1664                 (BSL_META_U(unit,
   1665                  "PTP failure sending signaling message to %s slave\n"),
   1666                  (async) ? "async" : ""));
   1667         }
   1668     } else {
   1669         failure_count = 0;
   1670     }
   1671 
   1672     return BCM_E_NONE;
   1673 }
   1674 
   1675 /*
   1676  * Function:
   1677  *      send_pending_signaling_to_masters
   1678  * Purpose:
   1679  *      Send any necessary signaling messages to masters (as DPC).
   1680  * Parameters:
   1681  *      arg_unit      - (IN) Unit number (as void**).
   1682  *      arg_ptp_id    - (IN) PTP stack ID (as void**).
   1683  *      arg_clock_num - (IN) PTP clock number (as void**).
   1684  *      unused        - (IN) Unused.
   1685  * Returns:
   1686  *      time interval before next call
   1687  * Notes:
   1688  */
   1689 static sal_usecs_t
   1690 send_pending_signaling_to_masters(
   1691     void **arg_unit,
   1692     void **arg_ptp_id,
   1693     void **arg_clock_num,
   1694     void **unused)
   1695 {
   1696     int i;
   1697     int rv;
   1698 
   1699     int unit = PTR_TO_INT(*arg_unit);
   1700     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id);
   1701     int clock_num = PTR_TO_INT(*arg_clock_num);
   1702 
   1703     sal_time_t ref_time;
   1704     int messageType[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE] = {0};
   1705     int8 logInterMessagePeriod[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE] = {0};
   1706     int num_tlvs = 0;
   1707     uint8 multi_tlv_en = 0;
   1708     uint8 telecom_en = 0;
   1709 
   1710     bcm_ptp_clock_info_t ci;
   1711     _bcm_ptp_port_state_t portState;
   1712 
   1713     /* Note: to prevent flooding, the DPC sends only one message per call, but will reschedule for a short
   1714        interval later if it does send something */
   1715 
   1716     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   1717                               clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   1718         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   1719         return BCM_PTP_SIGNAL_DEFAULT_MASTER_DPC_TIME_USEC;  /* retry at default interval */
   1720     }
   1721 
   1722     if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   1723         return BCM_PTP_SIGNAL_DEFAULT_MASTER_DPC_TIME_USEC;  /* retry at default interval */
   1724     }
   1725 
   1726     telecom_en = SHR_BITGET(&ci.flags, PTP_CLOCK_FLAGS_TELECOM_PROFILE_BIT);
   1727     multi_tlv_en = (SHR_BITGET(&ci.flags, PTP_CLOCK_FLAGS_SIGNALING_MULTI_TLV_BIT) ||
   1728                     telecom_en);
   1729 
   1730     /* Acknowledge any unanswered cancellations from master(s). */
   1731     for (i = 0; i < num_signaled_masters; ++i) {
   1732         if (signaled_master[i].to_ack_cancel.announce) {
   1733             _bcm_ptp_master_active_service_ack_cancel(unit, ptp_id, clock_num,
   1734                                                       &signaled_master[i], bcmPTP_MESSAGE_TYPE_ANNOUNCE);
   1735             return BCM_PTP_SIGNAL_MIN_MASTER_DPC_TIME_USEC;
   1736         } else if (signaled_master[i].to_ack_cancel.sync) {
   1737             _bcm_ptp_master_active_service_ack_cancel(unit, ptp_id, clock_num,
   1738                                                       &signaled_master[i], bcmPTP_MESSAGE_TYPE_SYNC);
   1739             return BCM_PTP_SIGNAL_MIN_MASTER_DPC_TIME_USEC;
   1740         } else if (signaled_master[i].to_ack_cancel.delayresp) {
   1741             _bcm_ptp_master_active_service_ack_cancel(unit, ptp_id, clock_num,
   1742                                                       &signaled_master[i], bcmPTP_MESSAGE_TYPE_DELAY_RESP);
   1743             return BCM_PTP_SIGNAL_MIN_MASTER_DPC_TIME_USEC;
   1744         }
   1745     }
   1746 
   1747     /* we haven't sent anything yet, so loop through masters to find something to send */
   1748     for (i = 0; i < num_signaled_masters; ++i) {
   1749         ref_time = _bcm_ptp_monotonic_time();
   1750 
   1751         if (signaled_master[i].master.local_port_number == 0) {
   1752             continue;
   1753         }
   1754         /* Check local port state; do not send signaling messages if portState is DISABLED. */
   1755         if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_port_state_get(unit, ptp_id, clock_num,
   1756                                                                  signaled_master[i].master.local_port_number, &portState)) ||
   1757             portState == _bcm_ptp_state_disabled) {
   1758             continue;
   1759         }
   1760 
   1761         if (signaled_master[i].service_enable.announce &&
   1762             signaled_master[i].announce_refresh_time &&
   1763             signaled_master[i].announce_refresh_time < ref_time) {
   1764             messageType[num_tlvs] = bcmPTP_MESSAGE_TYPE_ANNOUNCE;
   1765             logInterMessagePeriod[num_tlvs++] = signaled_master[i].log_announce_interval;
   1766 
   1767             /*
   1768              * Increment counter of unanswered/denied Announce service requests.
   1769              * Do not rollover.
   1770              */
   1771             if (signaled_master[i].unmet_requests.announce < ((uint8)-1)) {
   1772                 ++signaled_master[i].unmet_requests.announce;
   1773             }
   1774 
   1775             /*
   1776              * Set the time to send the next signaling message.
   1777              * Will be overwritten if we get a master response.
   1778              */
   1779             if ((telecom_en == 0) ||
   1780                 (signaled_master[i].unmet_requests.announce <
   1781                  BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_MAX)) {
   1782                 signaled_master[i].announce_refresh_time = ref_time +
   1783                     signaled_master[i].query_interval_sec;
   1784             } else {
   1785                 /*
   1786                  * Telecom profile support.
   1787                  * Retry at 60 sec. intervals if three (3) unanswered or denied requests.
   1788                  * Ref. ITU-T G.8265.1, Clause 6.6.
   1789                  */
   1790                 signaled_master[i].announce_refresh_time = ref_time +
   1791                     BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_QUERY_INTERVAL_SEC;
   1792             }
   1793 
   1794             if (multi_tlv_en == 0) {
   1795                 break;
   1796             }
   1797         }
   1798 
   1799         if (signaled_master[i].service_grants.announce &&
   1800             signaled_master[i].service_enable.sync &&
   1801             signaled_master[i].sync_refresh_time &&
   1802             signaled_master[i].sync_refresh_time < ref_time) {
   1803             messageType[num_tlvs] = bcmPTP_MESSAGE_TYPE_SYNC;
   1804             logInterMessagePeriod[num_tlvs++] = signaled_master[i].log_sync_interval;
   1805 
   1806             /*
   1807              * Increment counter of unanswered/denied Sync service requests.
   1808              * Do not rollover.
   1809              */
   1810             if (signaled_master[i].unmet_requests.sync < ((uint8)-1)) {
   1811                 ++signaled_master[i].unmet_requests.sync;
   1812             }
   1813 
   1814             /*
   1815              * Set the time to send the next signaling message.
   1816              * Will be overwritten if we get a master response.
   1817              */
   1818             if ((telecom_en == 0) ||
   1819                 (signaled_master[i].unmet_requests.sync <
   1820                  BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_MAX)) {
   1821                 signaled_master[i].sync_refresh_time = ref_time +
   1822                     signaled_master[i].query_interval_sec;
   1823             } else {
   1824                 /*
   1825                  * Telecom profile support.
   1826                  * Retry at 60 sec. intervals if three (3) unanswered or denied requests.
   1827                  * Ref. ITU-T G.8265.1, Clause 6.6.
   1828                  */
   1829                 signaled_master[i].sync_refresh_time = ref_time +
   1830                     BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_QUERY_INTERVAL_SEC;
   1831             }
   1832 
   1833             if (multi_tlv_en == 0) {
   1834                 break;
   1835             }
   1836         }
   1837 
   1838         if (signaled_master[i].service_grants.announce &&
   1839             signaled_master[i].service_enable.delayresp &&
   1840             signaled_master[i].delay_refresh_time &&
   1841             signaled_master[i].delay_refresh_time < ref_time) {
   1842             messageType[num_tlvs] = bcmPTP_MESSAGE_TYPE_DELAY_RESP;
   1843             logInterMessagePeriod[num_tlvs++] = signaled_master[i].log_delay_interval;
   1844 
   1845             /*
   1846              * Increment counter of unanswered/denied Delay_Resp service requests.
   1847              * Do not rollover.
   1848              */
   1849             if (signaled_master[i].unmet_requests.delayresp < ((uint8)-1)) {
   1850                 ++signaled_master[i].unmet_requests.delayresp;
   1851             }
   1852 
   1853             /*
   1854              * Set the time to send the next signaling message.
   1855              * Will be overwritten if we get a master response.
   1856              */
   1857             if ((telecom_en == 0) ||
   1858                 (signaled_master[i].unmet_requests.delayresp <
   1859                  BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_MAX)) {
   1860                 signaled_master[i].delay_refresh_time = ref_time +
   1861                     signaled_master[i].query_interval_sec;
   1862             } else {
   1863                 /*
   1864                  * Telecom profile support.
   1865                  * Retry at 60 sec. intervals if three (3) unanswered or denied requests.
   1866                  * Ref. ITU-T G.8265.1, Clause 6.6.
   1867                  */
   1868                 signaled_master[i].delay_refresh_time = ref_time +
   1869                     BCM_PTP_SIGNAL_TELECOM_UNMET_REQUEST_QUERY_INTERVAL_SEC;
   1870             }
   1871         }
   1872         /* We only will send TLVs to a single master, so if we have some, break out of the loop over masters */
   1873         if (num_tlvs) {
   1874             break;
   1875         }
   1876     }
   1877 
   1878     if (num_tlvs) {
   1879         /* Pending signaling message(s) to send to a master. */
   1880         send_unicast_request(unit, ptp_id, clock_num, num_tlvs, messageType,
   1881                              logInterMessagePeriod, signaled_master[i].durationField,
   1882                              ++signaled_master[i].sequenceId, &signaled_master[i].master);
   1883         return BCM_PTP_SIGNAL_MIN_MASTER_DPC_TIME_USEC;
   1884     }
   1885 
   1886     /* nothing to send, so we don't need to be re-called immediately */
   1887     return BCM_PTP_SIGNAL_DEFAULT_MASTER_DPC_TIME_USEC;
   1888 }
   1889 
   1890 /*
   1891  * Function:
   1892  *      _bcm_ptp_slave_signaling_request_deny
   1893  * Purpose:
   1894  *      Encapsulate system behavior to deny slave's request for PTP message
   1895  *      services.
   1896  * Parameters:
   1897  *      unit                    - (IN) Unit number.
   1898  *      ptp_id                  - (IN) PTP stack ID.
   1899  *      clock_num               - (IN) PTP clock number.
   1900  *      msg_type                - (IN) PTP message type (|Announce|Sync|DelayResp|).
   1901  *      log_intermessage_period - (IN) logInterMessagePeriod.
   1902  *      slave                   - (IN) Slave data.
   1903  * Returns:
   1904  *      BCM_E_XXX - Function status.
   1905  */
   1906 static int
   1907 _bcm_ptp_slave_signaling_request_deny(
   1908     int unit,
   1909     bcm_ptp_stack_id_t ptp_id,
   1910     int clock_num,
   1911     bcm_ptp_message_type_t msg_type,
   1912     int8 log_intermessage_period,
   1913     _bcm_ptp_clock_peer_ext_t *slave)
   1914 {
   1915     int rv;
   1916     int i;
   1917 
   1918     BCM_PTP_SLAVETABLE_MUTEX_TAKE();
   1919     /* Signaled unicast slave lookup. */
   1920     if (BCM_FAILURE(_bcm_ptp_signaled_unicast_slave_exists(unit, ptp_id, slave, &i))) {
   1921         /*
   1922          * Unknown slave.
   1923          * Send zero duration GRANT_UNICAST_TRANSMISSION to deny request.
   1924          * Ref. IEEE Std. 1588-2008, Sect. 16.1.4.2.5.
   1925          */
   1926         if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num,
   1927                 bcmPTPTlvTypeGrantUnicastTransmission, msg_type,
   1928                 log_intermessage_period, BCM_PTP_SIGNAL_REQUEST_DENY_DURATION_SEC,
   1929                 1, slave, 1))) {
   1930             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1931                         (BSL_META_U(unit,
   1932                                     "Zero duration GRANT_UNICAST_TRANSMISSION error\n")));
   1933             BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(rv);
   1934         }
   1935 
   1936         /* Return. No matching entry in signaled unicast slave table. */
   1937         BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(BCM_E_NONE);
   1938     }
   1939 
   1940     /*
   1941      * Send zero duration GRANT_UNICAST_TRANSMISSION to deny request.
   1942      * Ref. IEEE Std. 1588-2008, Sect. 16.1.4.2.5.
   1943      */
   1944     if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num,
   1945             bcmPTPTlvTypeGrantUnicastTransmission, msg_type,
   1946             log_intermessage_period, BCM_PTP_SIGNAL_REQUEST_DENY_DURATION_SEC,
   1947             ++signaled_slave_table.entry[i].sequenceId, slave, 1))) {
   1948         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1949                     (BSL_META_U(unit,
   1950                                 "Zero duration GRANT_UNICAST_TRANSMISSION error\n")));
   1951         BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(rv);
   1952     }
   1953 
   1954     /*
   1955      * Signaled unicast slave table management.
   1956      * Configure table to cancel corresponding PTP message service if slave
   1957      * is currently subscribed to the service.
   1958      */
   1959     switch (msg_type) {
   1960     case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   1961         if (signaled_slave_table.entry[i].announce_service_active) {
   1962             signaled_slave_table.entry[i].queue_announce_grant = 0;
   1963             signaled_slave_table.entry[i].queue_announce_expire = 1;
   1964         }
   1965         if (signaled_slave_table.entry[i].sync_service_active) {
   1966             signaled_slave_table.entry[i].queue_sync_grant = 0;
   1967             signaled_slave_table.entry[i].queue_sync_expire = 1;
   1968         }
   1969         if (signaled_slave_table.entry[i].delay_service_active) {
   1970             signaled_slave_table.entry[i].queue_delay_grant = 0;
   1971             signaled_slave_table.entry[i].queue_delay_expire = 1;
   1972         }
   1973         break;
   1974 
   1975     case bcmPTP_MESSAGE_TYPE_SYNC:
   1976         if (signaled_slave_table.entry[i].sync_service_active) {
   1977             signaled_slave_table.entry[i].queue_sync_grant = 0;
   1978             signaled_slave_table.entry[i].queue_sync_expire = 1;
   1979         }
   1980         break;
   1981 
   1982     case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   1983         if (signaled_slave_table.entry[i].delay_service_active) {
   1984             signaled_slave_table.entry[i].queue_delay_grant = 0;
   1985             signaled_slave_table.entry[i].queue_delay_expire = 1;
   1986         }
   1987         break;
   1988 
   1989     default:
   1990         ;
   1991     }
   1992 
   1993     _bcm_ptp_mutex_give(slaveTable_mutex);
   1994 
   1995     /* reschedule the gateway RDPC to run immediately */
   1996     rv = shr_rdpc_callback_start(&unit_sig_array[unit].send_pending_signaling_to_slaves_rdpc,
   1997                                  (sal_usecs_t)0,
   1998                                  INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(PTP_CLOCK_NUMBER_DEFAULT), INT_TO_PTR(0));
   1999     return rv;
   2000 }
   2001 
   2002 /*
   2003  * Function:
   2004  */
   2005 static sal_usecs_t
   2006 send_pending_signaling_to_slaves(
   2007     void **arg_unit,
   2008     void **arg_ptp_id,
   2009     void **arg_clock_num,
   2010     void **unused)
   2011 {
   2012     int rv = BCM_E_NONE;
   2013     int i;
   2014     int isqueued = 0;
   2015     bcm_ptp_tlv_type_t tlvType = 0;
   2016     bcm_ptp_tlv_type_t tlvTypeResp = 0;
   2017     bcm_ptp_message_type_t messageType = 0;
   2018     int8 logInterMessagePeriod = 0;
   2019     uint32 durationField = 0;
   2020     _bcm_ptp_clock_peer_ext_t slave;
   2021     int top_needs_updating = 0;
   2022     int unit = PTR_TO_INT(*arg_unit);
   2023     int clock_num = PTR_TO_INT(*arg_clock_num);
   2024     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id);
   2025 
   2026     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2027                              clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2028         PTP_ERROR_FUNC("_bcm_ptp_function_precheck");
   2029         return BCM_PTP_SIGNAL_DEFAULT_SLAVE_DPC_TIME_USEC;
   2030     }
   2031 
   2032     if ((rv = _bcm_ptp_mutex_take(slaveTable_mutex, BCM_PTP_SIGNAL_SLAVE_MUTEX_TIMEOUT_USEC))) {
   2033         PTP_ERROR_FUNC("_bcm_ptp_mutex_take of slaveTable_mutex");
   2034         return BCM_PTP_SIGNAL_DEFAULT_SLAVE_DPC_TIME_USEC;
   2035     }
   2036 
   2037     for (i = 0; i < signaled_slave_table.num_entries; ++i) {
   2038         /* We service one signaling message per DPC call to avoid flooding */
   2039         if (signaled_slave_table.entry[i].queue_announce_grant) {
   2040             /*
   2041              * Defer processing of announce grant iff pending cancel
   2042              * announce TLV precedes request announce TLV.
   2043              */
   2044             if ((signaled_slave_table.entry[i].announce_request_time <=
   2045                  signaled_slave_table.entry[i].announce_cancel_time) ||
   2046                 (!signaled_slave_table.entry[i].queue_announce_cancel)) {
   2047 
   2048                 top_needs_updating = signaled_slave_table.entry[i].announce_service_changed;
   2049                 signaled_slave_table.entry[i].announce_service_changed = 0;
   2050 
   2051                 signaled_slave_table.entry[i].queue_announce_grant = 0;
   2052                 signaled_slave_table.entry[i].announce_service_active = 1;
   2053                 signaled_slave_table.entry[i].announce_grant_time = _bcm_ptp_monotonic_time();
   2054 
   2055                 /* Select message to service. */
   2056                 tlvType = bcmPTPTlvTypeRequestUnicastTransmission;
   2057                 tlvTypeResp = bcmPTPTlvTypeGrantUnicastTransmission;
   2058                 messageType = bcmPTP_MESSAGE_TYPE_ANNOUNCE;
   2059                 logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_announce_interval;
   2060                 durationField = signaled_slave_table.entry[i].announce_duration;
   2061                 slave = signaled_slave_table.entry[i].slave;
   2062 
   2063                 isqueued = 1;
   2064                 break;
   2065             }
   2066         }
   2067 
   2068         if (signaled_slave_table.entry[i].queue_sync_grant) {
   2069             /* Defer processing of sync grant iff pending cancel sync TLV precedes it */
   2070             if ((signaled_slave_table.entry[i].sync_request_time <=
   2071                  signaled_slave_table.entry[i].sync_cancel_time) ||
   2072                 (!signaled_slave_table.entry[i].queue_sync_cancel)) {
   2073 
   2074                 top_needs_updating = signaled_slave_table.entry[i].sync_service_changed;
   2075                 signaled_slave_table.entry[i].sync_service_changed = 0;
   2076 
   2077                 signaled_slave_table.entry[i].queue_sync_grant = 0;
   2078                 signaled_slave_table.entry[i].sync_service_active = 1;
   2079                 signaled_slave_table.entry[i].sync_grant_time = _bcm_ptp_monotonic_time();
   2080 
   2081                 /* Select message to service. */
   2082                 tlvType = bcmPTPTlvTypeRequestUnicastTransmission;
   2083                 tlvTypeResp = bcmPTPTlvTypeGrantUnicastTransmission;
   2084                 messageType = bcmPTP_MESSAGE_TYPE_SYNC;
   2085                 logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_sync_interval;
   2086                 durationField = signaled_slave_table.entry[i].sync_duration;
   2087                 slave = signaled_slave_table.entry[i].slave;
   2088 
   2089                 isqueued = 1;
   2090                 break;
   2091             }
   2092         }
   2093 
   2094         if (signaled_slave_table.entry[i].queue_delay_grant) {
   2095             /* Defer processing of delay response grant iff pending cancel TLV preceeds it */
   2096             if ((signaled_slave_table.entry[i].delay_request_time <=
   2097                  signaled_slave_table.entry[i].delay_cancel_time) ||
   2098                 (!signaled_slave_table.entry[i].queue_delay_cancel)) {
   2099 
   2100                 top_needs_updating = signaled_slave_table.entry[i].delay_service_changed;
   2101                 signaled_slave_table.entry[i].delay_service_changed = 0;
   2102 
   2103                 signaled_slave_table.entry[i].queue_delay_grant = 0;
   2104                 signaled_slave_table.entry[i].delay_service_active = 1;
   2105                 signaled_slave_table.entry[i].delay_grant_time = _bcm_ptp_monotonic_time();
   2106 
   2107                 /* Select message to service. */
   2108                 tlvType = bcmPTPTlvTypeRequestUnicastTransmission;
   2109                 tlvTypeResp = bcmPTPTlvTypeGrantUnicastTransmission;
   2110                 messageType = bcmPTP_MESSAGE_TYPE_DELAY_RESP;
   2111                 logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_delay_request_interval;
   2112                 durationField = signaled_slave_table.entry[i].delay_duration;
   2113                 slave = signaled_slave_table.entry[i].slave;
   2114 
   2115                 isqueued = 1;
   2116                 break;
   2117             }
   2118         }
   2119 
   2120         if (signaled_slave_table.entry[i].queue_announce_cancel) {
   2121             signaled_slave_table.entry[i].queue_announce_cancel = 0;
   2122             signaled_slave_table.entry[i].announce_service_active = 0;
   2123             signaled_slave_table.entry[i].slave.peer.log_announce_interval = 99;
   2124 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2125             signaled_slave_table.entry[i].announce_ack_time = _bcm_ptp_monotonic_time();
   2126 #endif
   2127             top_needs_updating = 1;
   2128 
   2129             /* Select message to service. */
   2130             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2131             tlvTypeResp = bcmPTPTlvTypeAckCancelUnicastTransmission;
   2132             messageType = bcmPTP_MESSAGE_TYPE_ANNOUNCE;
   2133             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_announce_interval;
   2134             durationField = signaled_slave_table.entry[i].announce_duration;
   2135             slave = signaled_slave_table.entry[i].slave;
   2136 
   2137             isqueued = 1;
   2138             break;
   2139         }
   2140 
   2141         if (signaled_slave_table.entry[i].queue_sync_cancel) {
   2142             signaled_slave_table.entry[i].queue_sync_cancel = 0;
   2143             signaled_slave_table.entry[i].sync_service_active = 0;
   2144             signaled_slave_table.entry[i].slave.peer.log_sync_interval = 99;
   2145 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2146             signaled_slave_table.entry[i].sync_ack_time = _bcm_ptp_monotonic_time();
   2147 #endif
   2148             top_needs_updating = 1;
   2149 
   2150             /* Select message to service. */
   2151             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2152             tlvTypeResp = bcmPTPTlvTypeAckCancelUnicastTransmission;
   2153             messageType = bcmPTP_MESSAGE_TYPE_SYNC;
   2154             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_sync_interval;
   2155             durationField = signaled_slave_table.entry[i].sync_duration;
   2156             slave = signaled_slave_table.entry[i].slave;
   2157 
   2158             isqueued = 1;
   2159             break;
   2160         }
   2161 
   2162         if (signaled_slave_table.entry[i].queue_delay_cancel) {
   2163             signaled_slave_table.entry[i].queue_delay_cancel = 0;
   2164             signaled_slave_table.entry[i].delay_service_active = 0;
   2165             signaled_slave_table.entry[i].slave.peer.log_delay_request_interval = 99;
   2166 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2167             signaled_slave_table.entry[i].delay_ack_time = _bcm_ptp_monotonic_time();
   2168 #endif
   2169             top_needs_updating = 1;
   2170 
   2171             /* Select message to service. */
   2172             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2173             tlvTypeResp = bcmPTPTlvTypeAckCancelUnicastTransmission;
   2174             messageType = bcmPTP_MESSAGE_TYPE_DELAY_RESP;
   2175             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_delay_request_interval;
   2176             durationField = signaled_slave_table.entry[i].delay_duration;
   2177             slave = signaled_slave_table.entry[i].slave;
   2178 
   2179             isqueued = 1;
   2180             break;
   2181         }
   2182 
   2183         if (signaled_slave_table.entry[i].queue_announce_expire) {
   2184             signaled_slave_table.entry[i].queue_announce_expire = 0;
   2185             signaled_slave_table.entry[i].announce_service_active = 0;
   2186             signaled_slave_table.entry[i].slave.peer.log_announce_interval = 99;
   2187 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2188             signaled_slave_table.entry[i].announce_expire_time = _bcm_ptp_monotonic_time();
   2189 #endif
   2190             top_needs_updating = 1;
   2191 
   2192             /* Select message to service. */
   2193             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2194             tlvTypeResp = bcmPTPTlvTypeCancelUnicastTransmission;
   2195             messageType = bcmPTP_MESSAGE_TYPE_ANNOUNCE;
   2196             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_announce_interval;
   2197             durationField = signaled_slave_table.entry[i].announce_duration;
   2198             slave = signaled_slave_table.entry[i].slave;
   2199 
   2200             isqueued = 1;
   2201             break;
   2202         }
   2203 
   2204         if (signaled_slave_table.entry[i].queue_sync_expire) {
   2205             signaled_slave_table.entry[i].queue_sync_expire = 0;
   2206             signaled_slave_table.entry[i].sync_service_active = 0;
   2207             signaled_slave_table.entry[i].slave.peer.log_sync_interval = 99;
   2208 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2209             signaled_slave_table.entry[i].sync_expire_time = _bcm_ptp_monotonic_time();
   2210 #endif
   2211             top_needs_updating = 1;
   2212 
   2213             /* Select message to service. */
   2214             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2215             tlvTypeResp = bcmPTPTlvTypeCancelUnicastTransmission;
   2216             messageType = bcmPTP_MESSAGE_TYPE_SYNC;
   2217             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_sync_interval;
   2218             durationField = signaled_slave_table.entry[i].sync_duration;
   2219             slave = signaled_slave_table.entry[i].slave;
   2220 
   2221             isqueued = 1;
   2222             break;
   2223         }
   2224 
   2225         if (signaled_slave_table.entry[i].queue_delay_expire) {
   2226             signaled_slave_table.entry[i].queue_delay_expire = 0;
   2227             signaled_slave_table.entry[i].delay_service_active = 0;
   2228             signaled_slave_table.entry[i].slave.peer.log_delay_request_interval = 99;
   2229 #if defined(BCM_PTP_SIGNAL_TIMESTAMP)
   2230             signaled_slave_table.entry[i].delay_expire_time = _bcm_ptp_monotonic_time();
   2231 #endif
   2232             top_needs_updating = 1;
   2233 
   2234             /* Select message to service. */
   2235             tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2236             tlvTypeResp = bcmPTPTlvTypeCancelUnicastTransmission;
   2237             messageType = bcmPTP_MESSAGE_TYPE_DELAY_RESP;
   2238             logInterMessagePeriod = signaled_slave_table.entry[i].slave.peer.log_delay_request_interval;
   2239             durationField = signaled_slave_table.entry[i].delay_duration;
   2240             slave = signaled_slave_table.entry[i].slave;
   2241 
   2242             isqueued = 1;
   2243             break;
   2244         }
   2245     }
   2246 
   2247     if (isqueued) {
   2248         /* Queued signaling message(s). */
   2249 
   2250         /* Done with slave table update, release mutex */
   2251         _bcm_ptp_mutex_give(slaveTable_mutex);
   2252 
   2253         /* Respond to (grant, cancel, acknowledge cancel) selected message. */
   2254         if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num, tlvTypeResp,
   2255                                  messageType, logInterMessagePeriod, durationField,
   2256                                  ++signaled_slave_table.entry[i].sequenceId,&slave, 0))) {
   2257             PTP_ERROR_FUNC("_bcm_ptp_slave_signaling_send()");
   2258         }
   2259         if (top_needs_updating) {
   2260             /* Subscribe slave. */
   2261             if (BCM_FAILURE(rv = _bcm_ptp_unicast_slave_subscribe(unit, ptp_id, clock_num,
   2262                                      BCM_PTP_ANY_PORT, &slave, messageType, tlvType, logInterMessagePeriod))) {
   2263                 PTP_ERROR_FUNC("_bcm_ptp_unicast_slave_subscribe()");
   2264             }
   2265         }
   2266 
   2267         return BCM_PTP_SIGNAL_MIN_SLAVE_DPC_TIME_USEC;
   2268     } else {
   2269         /* No queued signaling messages. Update expiration / slave table while we have the lock */
   2270 
   2271         /* Update indicators of expired slave services. */
   2272         if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_expire(unit, ptp_id))) {
   2273             PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_expire()");
   2274         }
   2275 
   2276         /* Update signaled unicast slave table to remove inactive/expired slaves. */
   2277         if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_update(unit, ptp_id))) {
   2278             PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_table_update()");
   2279         }
   2280 
   2281         /* Done with slave table update, release mutex */
   2282         _bcm_ptp_mutex_give(slaveTable_mutex);
   2283 
   2284         return BCM_PTP_SIGNAL_DEFAULT_SLAVE_DPC_TIME_USEC;
   2285     }
   2286 }
   2287 
   2288 
   2289 /*
   2290  * Function:
   2291  *      bcm_common_ptp_signaled_unicast_slave_table_clear()
   2292  * Purpose:
   2293  *      Cancel active unicast services for slaves and clear signaled unicast
   2294  *      slave table entries that correspond to caller-specified master port.
   2295  * Parameters:
   2296  *      unit      - (IN) Unit number.
   2297  *      ptp_id    - (IN) PTP stack ID.
   2298  *      clock_num - (IN) PTP clock number.
   2299  *      port_num  - (IN) Local (master) PTP clock port number.
   2300  *      callstack - (IN) Boolean to unsubscribe/unregister unicast services.
   2301  *                       TRUE : Cancellation message to slave and PTP stack.
   2302  *                       FALSE: Cancellation message tunneled to slave only.
   2303  * Returns:
   2304  *      BCM_E_XXX - Function status.
   2305  */
   2306 int
   2307 bcm_common_ptp_signaled_unicast_slave_table_clear(
   2308     int unit,
   2309     bcm_ptp_stack_id_t ptp_id,
   2310     int clock_num,
   2311     int port_num,
   2312     int callstack)
   2313 {
   2314     int rv = BCM_E_NONE;
   2315     int i;
   2316     bcm_ptp_tlv_type_t tlvType;
   2317     bcm_ptp_message_type_t messageType;
   2318     int8 logInterMessagePeriod;
   2319     uint32 durationField;
   2320     _bcm_ptp_clock_peer_ext_t slave;
   2321 
   2322     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2323             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2324         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   2325         return rv;
   2326     }
   2327 
   2328     BCM_PTP_SLAVETABLE_MUTEX_TAKE();
   2329 
   2330     for (i = 0; i < signaled_slave_table.num_entries; ++i)
   2331     {
   2332        tlvType = bcmPTPTlvTypeCancelUnicastTransmission;
   2333        slave = signaled_slave_table.entry[i].slave;
   2334 
   2335        /* Remove slaves associated with specified master port. */
   2336        if (port_num == slave.peer.local_port_number ||
   2337            port_num == PTP_IEEE1588_ALL_PORTS) {
   2338            if (signaled_slave_table.entry[i].announce_service_active) {
   2339                 /* Select message to service. */
   2340                 messageType = bcmPTP_MESSAGE_TYPE_ANNOUNCE;
   2341                 logInterMessagePeriod =  signaled_slave_table.entry[i].slave.peer.log_announce_interval;
   2342                 durationField =  signaled_slave_table.entry[i].announce_duration;
   2343 
   2344                 /* Cancel message. */
   2345                 if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num, tlvType,
   2346                         messageType, logInterMessagePeriod, durationField,
   2347                         ++signaled_slave_table.entry[i].sequenceId, &slave, 0))) {
   2348                     PTP_ERROR_FUNC("_bcm_ptp_slave_signaling_send()");
   2349                 }
   2350 
   2351                 /* Unsubscribe slave. */
   2352                 if (callstack &&
   2353                     BCM_FAILURE(rv = _bcm_ptp_unicast_slave_subscribe(unit, ptp_id,
   2354                        clock_num, slave.peer.local_port_number, &slave, messageType, tlvType,
   2355                        logInterMessagePeriod))) {
   2356                     PTP_ERROR_FUNC("_bcm_ptp_unicast_slave_subscribe()");
   2357                 }
   2358             }
   2359 
   2360             if (signaled_slave_table.entry[i].sync_service_active) {
   2361                 /* Select message to service. */
   2362                 messageType = bcmPTP_MESSAGE_TYPE_SYNC;
   2363                 logInterMessagePeriod =  signaled_slave_table.entry[i].slave.peer.log_sync_interval;
   2364                 durationField =  signaled_slave_table.entry[i].sync_duration;
   2365 
   2366                 /* Cancel message. */
   2367                 if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num, tlvType,
   2368                         messageType, logInterMessagePeriod, durationField,
   2369                         ++signaled_slave_table.entry[i].sequenceId, &slave, 0))) {
   2370                     PTP_ERROR_FUNC("_bcm_ptp_slave_signaling_send()");
   2371                 }
   2372 
   2373                 /* Unsubscribe slave. */
   2374                 if (callstack &&
   2375                     BCM_FAILURE(rv = _bcm_ptp_unicast_slave_subscribe(unit, ptp_id,
   2376                         clock_num, slave.peer.local_port_number, &slave, messageType, tlvType,
   2377                         logInterMessagePeriod))) {
   2378                     PTP_ERROR_FUNC("_bcm_ptp_unicast_slave_subscribe()");
   2379                 }
   2380             }
   2381 
   2382             if (signaled_slave_table.entry[i].delay_service_active) {
   2383                 /* Select message to service. */
   2384                 messageType = bcmPTP_MESSAGE_TYPE_DELAY_RESP;
   2385                 logInterMessagePeriod =  signaled_slave_table.entry[i].slave.peer.log_delay_request_interval;
   2386                 durationField =  signaled_slave_table.entry[i].delay_duration;
   2387 
   2388                 /* Cancel message. */
   2389                 if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_send(unit, ptp_id, clock_num, tlvType,
   2390                         messageType, logInterMessagePeriod, durationField,
   2391                         ++signaled_slave_table.entry[i].sequenceId, &slave, 0))) {
   2392                     PTP_ERROR_FUNC("_bcm_ptp_slave_signaling_send()");
   2393                 }
   2394 
   2395                 /* Unsubscribe slave. */
   2396                 if (callstack &&
   2397                     BCM_FAILURE(rv = _bcm_ptp_unicast_slave_subscribe(unit, ptp_id,
   2398                         clock_num, slave.peer.local_port_number, &slave, messageType, tlvType,
   2399                         logInterMessagePeriod))) {
   2400                     PTP_ERROR_FUNC("_bcm_ptp_unicast_slave_subscribe()");
   2401                 }
   2402             }
   2403 
   2404             /*
   2405              * Set slave entry.
   2406              *    Reset message attributes to defaults to render inactive/expired.
   2407              *    Preserve slave address.
   2408              */
   2409             signaled_slave_table.entry[i] = signaled_slave_entry_default;
   2410             signaled_slave_table.entry[i].slave = slave;
   2411 
   2412         }
   2413     }
   2414 
   2415     /* Update unicast slave table to remove inactive/expired slaves. */
   2416     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_update(unit, ptp_id))) {
   2417         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_table_update()");
   2418     }
   2419 
   2420     BCM_PTP_SLAVETABLE_MUTEX_RELEASE_RETURN(rv);
   2421 }
   2422 
   2423 /* Basic parsing of a signaling message: checks clock/port numbers and gets TLV info */
   2424 
   2425 int _bcm_ptp_parse_signaling_message(
   2426     int unit,
   2427     bcm_ptp_stack_id_t ptp_id,
   2428     int clock_num,
   2429     int port_num,
   2430     unsigned data_length,
   2431     uint8 * data,
   2432     int ptp_msg_offset,
   2433     bcm_ptp_tlv_type_t *tlvType,
   2434     bcm_ptp_message_type_t *messageType,
   2435     int8 *logInterMessagePeriod,
   2436     uint32 *durationField,
   2437     int *num_tlvs)
   2438 {
   2439     int rv;
   2440     uint8 *targetClock;
   2441     int cursor = 0;
   2442     uint8 *ptp_tlv;
   2443     uint8 *udp;
   2444     int udp_payload_len;
   2445     uint16 lengthField;
   2446     int lengthRemaining;
   2447     bcm_ptp_clock_info_t ci;
   2448 
   2449     /* Initialize number of TLVs processed. */
   2450     *num_tlvs = 0;
   2451 
   2452     /* Retrieve clock instance create-time data and metadata. */
   2453     if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   2454         PTP_ERROR_FUNC("_bcm_ptp_clock_get()");
   2455         /* Reject signaling messages if a PTP clock is not available. */
   2456         return BCM_E_FAIL;
   2457     }
   2458 
   2459     /* Check target clock identity. Either broadcast, or must match that of clock_num  */
   2460     targetClock = data + ptp_msg_offset + PTP_PTPHDR_SIZE_OCTETS;
   2461     if (sal_memcmp(targetClock, BCM_PTP_ALL_CLOCKS, sizeof(bcm_ptp_clock_identity_t)) != 0) {
   2462         if (sal_memcmp(targetClock, ci.clock_identity, sizeof(bcm_ptp_clock_identity_t)) != 0) {
   2463             return BCM_E_FAIL;
   2464         }
   2465     }
   2466 
   2467     /*
   2468      * Dimension consistency check(s).
   2469      * Ensure bogus or malformed messages do not cause range errors.
   2470      */
   2471     if (data_length - ptp_msg_offset <
   2472         BCM_PTP_SIGNAL_MIN_UDP_PAYLOAD_SIZE_OCTETS) {
   2473         return BCM_E_FAIL;
   2474     }
   2475 
   2476 #if 0
   2477     bsl_printf(" Signaling Msg recvd:: \n");
   2478     _bcm_ptp_dump_hex(data, data_length, 0);
   2479 #endif
   2480 
   2481     ptp_tlv = data + ptp_msg_offset + BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS;
   2482     lengthRemaining = data_length - ptp_msg_offset - BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS;
   2483 
   2484     udp = data + ptp_msg_offset - BCM_PTP_UDP_HEADER_LENGTH_BYTES;
   2485     udp_payload_len = _bcm_ptp_uint16_read(udp+4);
   2486     lengthRemaining = udp_payload_len - BCM_PTP_UDP_HEADER_LENGTH_BYTES - BCM_PTP_SIGNAL_TLV_OFFSET_OCTETS;
   2487 
   2488     LOG_DEBUG(BSL_LS_BCM_PTP,
   2489         (BSL_META_U(unit, "UDP payload len[%d] Remaining Length[%d]\n"), udp_payload_len, lengthRemaining));
   2490 
   2491     /* A 4-byte FCS can be present. 
   2492        TlvType(2B) and TlvLength(2B) together constitutes 4Bytes.
   2493        So, continue parsing ONLY if the length remaining is > 4bytes */
   2494 
   2495     while (lengthRemaining > 4) {
   2496 
   2497         tlvType[*num_tlvs] = _bcm_ptp_uint16_read(ptp_tlv);
   2498         cursor += sizeof(uint16);
   2499 
   2500         lengthField = _bcm_ptp_uint16_read(ptp_tlv + cursor);
   2501         cursor += sizeof(uint16);
   2502 
   2503         LOG_DEBUG(BSL_LS_BCM_PTP,
   2504             (BSL_META_U(unit, "tlv type[0x%04x] tlv length[0x%04x]\n"), tlvType[*num_tlvs], lengthField));
   2505 
   2506         /* Get message type from TLV. */
   2507         if (lengthField < 1) {
   2508             return BCM_E_FAIL;
   2509         }
   2510         messageType[*num_tlvs] = (ptp_tlv[cursor++] >> 4);
   2511 
   2512         /* If the message has space for them, parse the interval and duration */
   2513         if (lengthField >= 5) {
   2514             logInterMessagePeriod[*num_tlvs] = ptp_tlv[cursor++];
   2515             durationField[*num_tlvs] = _bcm_ptp_uint32_read(ptp_tlv + cursor);
   2516         } else {
   2517             logInterMessagePeriod[*num_tlvs] = 0;
   2518             durationField[*num_tlvs] = 0;
   2519         }
   2520 
   2521         /* Advance to next TLV, if any. */
   2522         ++(*num_tlvs);
   2523         ptp_tlv += lengthField + 4;
   2524         cursor = 0;
   2525 
   2526         /* Adjust remaining length. */
   2527         lengthRemaining -= (lengthField + 4);
   2528 
   2529         LOG_DEBUG(BSL_LS_BCM_PTP,
   2530             (BSL_META_U(unit, "length remaining[%d] num_tlvs[%d]\n"), lengthRemaining, *num_tlvs));
   2531 
   2532         /* Exit if maximum number of TLVs has been processed. */
   2533         if (*num_tlvs >= BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE) {
   2534             lengthRemaining = 0;
   2535         }
   2536     }
   2537 
   2538     return BCM_E_NONE;
   2539 }
   2540 
   2541 STATIC int
   2542 _bcm_ptp_make_peer_from_signaling_msg(
   2543     int unit,
   2544     bcm_ptp_stack_id_t ptp_id,
   2545     int clock_num,
   2546     unsigned data_length,
   2547     uint8 *data,
   2548     bcm_ptp_protocol_t protocol,
   2549     int src_addr_offset,
   2550     int ptp_msg_offset,
   2551     _bcm_ptp_clock_peer_ext_t *peer_ext)
   2552 {
   2553     int any_port = 0xffff;
   2554     int rv = BCM_E_NONE;
   2555     int cursor;
   2556 
   2557     int port_num;
   2558     bcm_ptp_clock_info_t ci;
   2559     bcm_ptp_clock_port_info_t pi;
   2560 
   2561     bcm_mac_t src_mac;
   2562     bcm_mac_t dest_mac;
   2563     bcm_ptp_clock_peer_t *peer = &peer_ext->peer;
   2564 
   2565     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2566             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2567         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   2568         return rv;
   2569     }
   2570 
   2571     /* Parse signaling message to construct peer data structure. */
   2572     switch ((bcm_ptp_protocol_t)protocol) {
   2573     case bcmPTPUDPIPv4:
   2574         /* Ethernet/UDP/IPv4 address. */
   2575         peer->peer_address.raw_l2_header_length = src_addr_offset -
   2576             PTP_IPV4HDR_SRC_IPADDR_OFFSET_OCTETS;
   2577 
   2578         if (peer->peer_address.raw_l2_header_length > PTP_MAX_L2_HEADER_LENGTH) {
   2579             peer->peer_address.raw_l2_header_length = 0;
   2580             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2581                         (BSL_META_U(unit,
   2582                                     "Incompatible L2 header size\n")));
   2583             return BCM_E_CONFIG;
   2584         }
   2585 
   2586         /*
   2587          * Configure raw L2 header.
   2588          * Reference implementation: Swap source and destination MACs from
   2589          * incoming signaling message.
   2590          */
   2591         sal_memcpy(dest_mac, data, sizeof(bcm_mac_t));
   2592         sal_memcpy(src_mac, data + sizeof(bcm_mac_t), sizeof(bcm_mac_t));
   2593 
   2594         sal_memset(peer->peer_address.raw_l2_header, 0, PTP_MSG_L2_HEADER_LENGTH);
   2595         sal_memcpy(peer->peer_address.raw_l2_header, data,
   2596             peer->peer_address.raw_l2_header_length);
   2597 
   2598         sal_memcpy(peer->peer_address.raw_l2_header, src_mac, sizeof(bcm_mac_t));
   2599         sal_memcpy(peer->peer_address.raw_l2_header + sizeof(bcm_mac_t), dest_mac,
   2600             sizeof(bcm_mac_t));
   2601 
   2602         /* Set address. */
   2603         peer->peer_address.addr_type = bcmPTPUDPIPv4;
   2604         peer->peer_address.ipv4_addr = _bcm_ptp_uint32_read(data + src_addr_offset);
   2605         sal_memset(peer->peer_address.ipv6_addr, 0, PTP_IPV6_ADDR_SIZE_BYTES);
   2606 
   2607         peer_ext->local_address.addr_type = bcmPTPUDPIPv4;
   2608         sal_memcpy(peer_ext->local_address.address, data + src_addr_offset + PTP_IPV4_ADDR_SIZE_BYTES, PTP_IPV4_ADDR_SIZE_BYTES);
   2609 
   2610         /* Extract req'd remote (source) port information. */
   2611         cursor = ptp_msg_offset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS;
   2612         sal_memcpy(peer->clock_identity,
   2613             data + cursor, sizeof(bcm_ptp_clock_identity_t));
   2614 
   2615         cursor += sizeof(bcm_ptp_clock_identity_t);
   2616         peer->remote_port_number = _bcm_ptp_uint16_read(data + cursor);
   2617 
   2618         /* Extract req'd local (target) port information. */
   2619         cursor = ptp_msg_offset + PTP_PTPHDR_SIZE_OCTETS + sizeof(bcm_ptp_clock_identity_t);
   2620         peer->local_port_number = _bcm_ptp_uint16_read(data + cursor);
   2621 
   2622         /*
   2623          * Process target port.
   2624          * Reference implementation: Assign "all ports" target to port with
   2625          *                           matching protocol address.
   2626          * Reference implementation: Reject message if associated port is
   2627          *                           unavailable as determined by the port
   2628          *                           address accessor.
   2629          * Reference implementation: Reject message if destination address
   2630          *                           does not match local port address.
   2631          */
   2632         if (peer->local_port_number == any_port) {
   2633             if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   2634                 PTP_ERROR_FUNC("_bcm_ptp_clock_get()");
   2635                 return BCM_E_FAIL;
   2636             }
   2637 
   2638             for (port_num = 1; port_num <= ci.num_ports; ++port_num) {
   2639                 if (BCM_FAILURE(bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num, port_num, &pi))) {
   2640                     PTP_ERROR_FUNC("_bcm_ptp_clock_port_info_get()");
   2641                     return BCM_E_FAIL;
   2642                 }
   2643 
   2644                 if (protocol == pi.port_address.addr_type) {
   2645                     /* See if the address matches, or if the port will accept any incoming address */
   2646                     if (!sal_memcmp(data + src_addr_offset + PTP_IPV4_ADDR_SIZE_BYTES,
   2647                                     pi.port_address.address, PTP_IPV4_ADDR_SIZE_BYTES) ||
   2648                         (pi.rx_packets_criteria_mask & BCM_PTP_RXMAP_MATCH_ANY_ADDR)) {
   2649                         break;
   2650                     }
   2651                 }
   2652             }
   2653 
   2654             peer->local_port_number = port_num;
   2655             if (peer->local_port_number > ci.num_ports) {
   2656                 peer->local_port_number = 1;
   2657                 PTP_WARN("Destination IP address not found (IPv4).\n");
   2658 
   2659                 return BCM_E_PARAM;
   2660             }
   2661         } else {
   2662             if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   2663                 PTP_ERROR_FUNC("_bcm_ptp_clock_get()");
   2664                 return BCM_E_FAIL;
   2665             }
   2666 
   2667             if (BCM_FAILURE(bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num,
   2668                                                         peer->local_port_number, &pi))) {
   2669                 PTP_ERROR_FUNC("_bcm_ptp_clock_port_info_get()");
   2670                 return BCM_E_FAIL;
   2671             }
   2672 
   2673             if (protocol != pi.port_address.addr_type ||
   2674                 sal_memcmp(data + src_addr_offset + PTP_IPV4_ADDR_SIZE_BYTES,
   2675                            pi.port_address.address, PTP_IPV4_ADDR_SIZE_BYTES)) {
   2676                 PTP_WARN("Destination IP address mismatch (IPv4).\n");
   2677                 return BCM_E_PARAM;
   2678             }
   2679         }
   2680 
   2681         break;
   2682 
   2683     case bcmPTPUDPIPv6:
   2684         /* Ethernet/UDP/IPv6 address. */
   2685         peer->peer_address.raw_l2_header_length = src_addr_offset - 8;
   2686 
   2687         if (peer->peer_address.raw_l2_header_length > PTP_MAX_L2_HEADER_LENGTH) {
   2688             peer->peer_address.raw_l2_header_length = 0;
   2689             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2690                         (BSL_META_U(unit,
   2691                                     "Incompatible L2 header size\n")));
   2692             return BCM_E_CONFIG;
   2693         }
   2694 
   2695         /*
   2696          * Configure raw L2 header.
   2697          * Reference implementation: Swap source and destination MACs from
   2698          * incoming signaling message.
   2699          */
   2700         sal_memcpy(dest_mac, data, sizeof(bcm_mac_t));
   2701         sal_memcpy(src_mac, data + sizeof(bcm_mac_t), sizeof(bcm_mac_t));
   2702 
   2703         sal_memset(peer->peer_address.raw_l2_header, 0, PTP_MSG_L2_HEADER_LENGTH);
   2704         sal_memcpy(peer->peer_address.raw_l2_header, data,
   2705             peer->peer_address.raw_l2_header_length);
   2706 
   2707         sal_memcpy(peer->peer_address.raw_l2_header, src_mac, sizeof(bcm_mac_t));
   2708         sal_memcpy(peer->peer_address.raw_l2_header + sizeof(bcm_mac_t), dest_mac,
   2709             sizeof(bcm_mac_t));
   2710 
   2711         /* Set address. */
   2712         peer->peer_address.addr_type = bcmPTPUDPIPv6;
   2713         peer->peer_address.ipv4_addr = 0;
   2714         sal_memcpy(peer->peer_address.ipv6_addr, data + src_addr_offset,
   2715             PTP_IPV6_ADDR_SIZE_BYTES);
   2716 
   2717         peer_ext->local_address.addr_type = bcmPTPUDPIPv6;
   2718         sal_memcpy(peer_ext->local_address.address, data + src_addr_offset + PTP_IPV6_ADDR_SIZE_BYTES, PTP_IPV6_ADDR_SIZE_BYTES);
   2719 
   2720         /* Extract req'd remote (source) port information. */
   2721         cursor = ptp_msg_offset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS;
   2722         sal_memcpy(peer->clock_identity,
   2723             data + cursor, sizeof(bcm_ptp_clock_identity_t));
   2724 
   2725         cursor += sizeof(bcm_ptp_clock_identity_t);
   2726         peer->remote_port_number = _bcm_ptp_uint16_read(data + cursor);
   2727 
   2728         /* Extract req'd local (target) port information. */
   2729         cursor = ptp_msg_offset + PTP_PTPHDR_SIZE_OCTETS + sizeof(bcm_ptp_clock_identity_t);
   2730         peer->local_port_number = _bcm_ptp_uint16_read(data + cursor);
   2731 
   2732         /*
   2733          * Process target port.
   2734          * Reference implementation: Assign "all ports" target to port with
   2735          *                           matching protocol address.
   2736          * Reference implementation: Reject message if associated port is
   2737          *                           unavailable as determined by the port
   2738          *                           address accessor.
   2739          * Reference implementation: Reject message if destination address
   2740          *                           does not match local port address.
   2741          */
   2742         if (peer->local_port_number == any_port) {
   2743             if (BCM_FAILURE(rv = bcm_ptp_clock_get(unit, ptp_id, clock_num, &ci))) {
   2744                 PTP_ERROR_FUNC("_bcm_ptp_clock_get()");
   2745                 return BCM_E_FAIL;
   2746             }
   2747 
   2748             for (port_num = 1; port_num <= ci.num_ports; ++port_num) {
   2749                 if (BCM_FAILURE(bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num, port_num, &pi))) {
   2750                     PTP_ERROR_FUNC("_bcm_ptp_clock_port_info_get()");
   2751                     return BCM_E_FAIL;
   2752                 }
   2753 
   2754                 if (protocol == pi.port_address.addr_type &&
   2755                     !sal_memcmp(data + src_addr_offset + PTP_IPV6_ADDR_SIZE_BYTES,
   2756                                 pi.port_address.address, PTP_IPV6_ADDR_SIZE_BYTES)) {
   2757                     break;
   2758                 }
   2759             }
   2760 
   2761             peer->local_port_number = port_num;
   2762             if (peer->local_port_number > ci.num_ports) {
   2763                 peer->local_port_number = 1;
   2764                 PTP_WARN("Destination IP address mismatch (IPv6).\n");
   2765                 return BCM_E_PARAM;
   2766             }
   2767         } else {
   2768             if (BCM_FAILURE(bcm_ptp_clock_port_info_get(unit, ptp_id, clock_num,
   2769                                                         peer->local_port_number, &pi))) {
   2770                 PTP_ERROR_FUNC("_bcm_ptp_clock_port_info_get()");
   2771                 return BCM_E_FAIL;
   2772             }
   2773 
   2774             if (protocol != pi.port_address.addr_type ||
   2775                 sal_memcmp(data + src_addr_offset + PTP_IPV6_ADDR_SIZE_BYTES,
   2776                            pi.port_address.address, PTP_IPV6_ADDR_SIZE_BYTES)) {
   2777                 PTP_WARN("Destination IP address mismatch (IPv6).\n");
   2778                 return BCM_E_PARAM;
   2779             }
   2780         }
   2781 
   2782         break;
   2783 
   2784     default:
   2785         /* Unknown or unsupported address type. */
   2786         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   2787                     (BSL_META_U(unit,
   2788                                 "Unknown or unsupported address type\n")));
   2789         return BCM_E_PARAM;
   2790     }
   2791 
   2792     return BCM_E_NONE;
   2793 }
   2794 
   2795 /*
   2796  * Function:
   2797  *      _bcm_ptp_process_incoming_signaling_msg()
   2798  * Purpose:
   2799  *      Reference implementation to process an incoming PTP signaling message.
   2800  * Parameters:
   2801  *      unit            - (IN) Unit number.
   2802  *      ptp_id          - (IN) PTP stack ID.
   2803  *      clock_num       - (IN) PTP clock number.
   2804  *      port_num        - (IN) PTP clock port number.
   2805  *      protocol        - (IN) Network protocol.
   2806  *      src_addr_offset - (IN) Source address offset in message.
   2807  *      ptp_msg_offset  - (IN) PTP offset (PTP common header) in message.
   2808  *      data_length     - (IN) Signaling message size.
   2809  *      data            - (IN) Signaling message data.
   2810  * Returns:
   2811  *      bcmPTPCallbackAccept - Criteria met; accept PTP signaling message.
   2812  *      bcmPTPCallbackReject - Criteria not met; reject PTP signaling message.
   2813  */
   2814 bcm_ptp_callback_t
   2815 _bcm_ptp_process_incoming_signaling_msg(
   2816     int unit,
   2817     bcm_ptp_stack_id_t ptp_id,
   2818     int clock_num,
   2819     int port_num,
   2820     bcm_ptp_protocol_t protocol,
   2821     int src_addr_offset,
   2822     int ptp_msg_offset,
   2823     unsigned data_length,
   2824     uint8 *data)
   2825 {
   2826     int rv;
   2827 
   2828     int num_tlvs;
   2829     int tlv_num;
   2830 
   2831     bcm_ptp_tlv_type_t tlvType;
   2832     bcm_ptp_tlv_type_t tlvTypes[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE];
   2833 
   2834     bcm_ptp_message_type_t messageType;
   2835     bcm_ptp_message_type_t messageTypes[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE];
   2836 
   2837     int logInterMessagePeriodAsInt;
   2838     int8 logInterMessagePeriod;
   2839     int8 logInterMessagePeriods[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE];
   2840 
   2841     uint32 durationField;
   2842     uint32 durationFields[BCM_PTP_SIGNAL_MAX_TLV_PER_MESSAGE];
   2843 
   2844     _bcm_ptp_clock_peer_ext_t peer_ext;
   2845     bcm_ptp_callback_t rvcb;
   2846     bcm_ptp_cb_msg_t msg;
   2847     _bcm_ptp_clock_cache_t *clock;
   2848     _bcm_ptp_port_state_t portState;
   2849 
   2850     bcm_ptp_clock_info_t ci;
   2851     uint8 domainNumber;
   2852 
   2853     bcm_ptp_signaling_arbiter_t arbiter = unit_sig_array[unit].arbiter;
   2854     bcm_ptp_cb_signaling_arbiter_msg_t amsg;
   2855     void *user_data = unit_sig_array[unit].arbiter_user_data;
   2856 
   2857 
   2858     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2859             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2860         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   2861         return bcmPTPCallbackReject;
   2862     }
   2863 
   2864     /*
   2865      * Check domainNumber in message common header against local clock instance.
   2866      * Reference implementation: Reject (ignore) PTP signaling messages that are
   2867      *                           not in local clock's domain.
   2868      */
   2869     domainNumber = *(data + ptp_msg_offset + PTP_PTPHDR_DOMAIN_OFFSET_OCTETS);
   2870 
   2871     if (BCM_FAILURE(_bcm_ptp_clock_cache_info_get(unit, ptp_id, clock_num, &ci)) ||
   2872             domainNumber != ci.domain_number) {
   2873         return bcmPTPCallbackReject;
   2874     }
   2875 
   2876     if (BCM_FAILURE(rv = _bcm_ptp_parse_signaling_message(unit, ptp_id, clock_num,
   2877             port_num, data_length, data, ptp_msg_offset, tlvTypes, messageTypes,
   2878             logInterMessagePeriods, durationFields, &num_tlvs))) {
   2879         PTP_ERROR_FUNC("_bcm_ptp_parse_signaling_message()");
   2880         return bcmPTPCallbackReject;
   2881     }
   2882 
   2883     if (BCM_FAILURE(rv = _bcm_ptp_make_peer_from_signaling_msg(unit, ptp_id, clock_num,
   2884             data_length, data, protocol, src_addr_offset, ptp_msg_offset, &peer_ext))) {
   2885         return bcmPTPCallbackReject;
   2886     }
   2887 
   2888     /*
   2889      * Check portState of target port.
   2890      * Reference implementation: Reject (ignore) PTP signaling messages if
   2891      *                           the portState of target port is DISABLED.
   2892      */
   2893     if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_port_state_get(unit,
   2894             ptp_id, clock_num, peer_ext.peer.local_port_number, &portState)) ||
   2895             portState == _bcm_ptp_state_disabled) {
   2896         return bcmPTPCallbackReject;
   2897     }
   2898 
   2899     for (tlv_num = 0; tlv_num < num_tlvs; ++tlv_num) {
   2900         tlvType = tlvTypes[tlv_num];
   2901         messageType = messageTypes[tlv_num];
   2902         logInterMessagePeriod = logInterMessagePeriods[tlv_num];
   2903         logInterMessagePeriodAsInt = (int)logInterMessagePeriod;
   2904         durationField = durationFields[tlv_num];
   2905 
   2906         if (tlvType == bcmPTPTlvTypeRequestUnicastTransmission) {
   2907             if (!arbiter) {
   2908                 return bcmPTPCallbackReject;
   2909             }
   2910             /*
   2911              * Use caller-provided, application-specific registered interpreter/arbiter
   2912              * callback to determine whether to accept or reject PTP signaling message.
   2913              */
   2914             clock = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[clock_num];
   2915 
   2916             sal_memset(&amsg, 0, sizeof(bcm_ptp_cb_signaling_arbiter_msg_t));
   2917             sal_memset(&msg, 0, sizeof(bcm_ptp_cb_msg_t));
   2918 
   2919             amsg.ptp_id = ptp_id;
   2920             amsg.clock_num = clock_num;
   2921             amsg.port_num = port_num;
   2922             msg.length = data_length;
   2923             msg.data = data;
   2924             msg.protocol = protocol;
   2925             msg.src_addr_offset = src_addr_offset;
   2926             msg.msg_offset = ptp_msg_offset;
   2927             amsg.clock_info = &clock->clock_info;
   2928             amsg.tlv_type = &tlvType;
   2929             amsg.messageType = &messageType;
   2930             amsg.logInterMessagePeriod = &logInterMessagePeriodAsInt;
   2931             amsg.durationField = &durationField;
   2932             amsg.msg = &msg;
   2933             amsg.slave = &peer_ext.peer;
   2934 
   2935             rvcb = arbiter(unit, &amsg, user_data);
   2936 
   2937             if (bcmPTPCallbackReject == rvcb) {
   2938                 /*
   2939                  * Deny request for PTP message service.
   2940                  * NOTE : Use as-provided messageType and logInterMessagePeriod
   2941                  *        in the event a custom arbiter modifies the parameters.
   2942                  */
   2943                 if (BCM_FAILURE(rv = _bcm_ptp_slave_signaling_request_deny(
   2944                         unit, ptp_id, clock_num, messageTypes[tlv_num],
   2945                         logInterMessagePeriods[tlv_num], &peer_ext))) {
   2946                     PTP_ERROR_FUNC("_bcm_ptp_slave_signaling_request_deny()");
   2947                 }
   2948                 continue;
   2949             }
   2950         }
   2951 
   2952         if ((rv = _bcm_ptp_mutex_take(slaveTable_mutex, BCM_PTP_SIGNAL_SLAVE_MUTEX_TIMEOUT_USEC))) {
   2953             PTP_ERROR_FUNC("_bcm_ptp_mutex_take()");
   2954             return bcmPTPCallbackReject;
   2955         }
   2956 
   2957         switch (tlvType) {
   2958         case bcmPTPTlvTypeRequestUnicastTransmission:
   2959             {
   2960                 /*
   2961                  * Signaled unicast slave table management.
   2962                  *    Locate slave in signaled unicast slave table.
   2963                  *    Add an entry if corresponding slave does not exist yet.
   2964                  */
   2965                 int rv;
   2966                 int i;
   2967 
   2968                 if (BCM_SUCCESS(rv = _bcm_ptp_signaled_unicast_slave_exists(unit, ptp_id, &peer_ext, &i))) {
   2969                     if ((sal_memcmp(&signaled_slave_table.entry[i].slave.peer.peer_address.raw_l2_header[0], &peer_ext.peer.peer_address.raw_l2_header[0], peer_ext.peer.peer_address.raw_l2_header_length) == 0) && 
   2970                         (sal_memcmp(&signaled_slave_table.entry[i].slave.peer.clock_identity, &peer_ext.peer.clock_identity, sizeof(bcm_ptp_clock_identity_t)) == 0)) {
   2971                         /* Slave with that address already exists, update clock info if necessary */
   2972                         signaled_slave_table.entry[i].slave.peer.remote_port_number = peer_ext.peer.remote_port_number;
   2973                     } else {
   2974                     /* slave's MAC address has changed, remove the slave entry, add a new entry and notify R5 to update Slave's mac address */
   2975                         signaled_slave_table.entry[i].queue_announce_grant = 0;
   2976                         signaled_slave_table.entry[i].queue_sync_grant = 0;
   2977                         signaled_slave_table.entry[i].queue_delay_grant = 0;
   2978                         signaled_slave_table.entry[i].queue_announce_cancel = 0;
   2979                         signaled_slave_table.entry[i].queue_sync_cancel = 0;
   2980                         signaled_slave_table.entry[i].queue_delay_cancel = 0;
   2981                         signaled_slave_table.entry[i].queue_announce_expire = 0;
   2982                         signaled_slave_table.entry[i].queue_sync_expire = 0;
   2983                         signaled_slave_table.entry[i].queue_delay_expire = 0;
   2984                         signaled_slave_table.entry[i].announce_service_active = 0;
   2985                         signaled_slave_table.entry[i].sync_service_active = 0;
   2986                         signaled_slave_table.entry[i].delay_service_active = 0;
   2987                         /* Update unicast slave table to remove inactive/expired slaves. */
   2988                         if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_table_update(unit, ptp_id))) {
   2989                             PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_table_update()");
   2990                         }
   2991 
   2992                         if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_add(unit, ptp_id, &peer_ext))) {
   2993                             PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_add()");
   2994                             goto release_return;
   2995                         }
   2996                         i = signaled_slave_table.num_entries - 1;
   2997                         signaled_slave_table.entry[i].slave.peer.log_announce_interval = 99;
   2998                         signaled_slave_table.entry[i].slave.peer.log_sync_interval = 99;
   2999                         signaled_slave_table.entry[i].slave.peer.log_delay_request_interval = 99;
   3000 
   3001                         signaled_slave_table.entry[i].slave.peer.announce_receive_timeout =
   3002                             PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT;
   3003                         signaled_slave_table.entry[i].slave.peer.delay_mechanism =
   3004                             bcmPTPDelayMechanismEnd2End;
   3005                         signaled_slave_table.entry[i].slave.peer.tx_timestamp_mech =
   3006                             peer_ext.peer.tx_timestamp_mech;
   3007                     }
   3008                 } else {
   3009                     if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_add(unit, ptp_id, &peer_ext))) {
   3010                         PTP_ERROR_FUNC("_bcm_ptp_signaled_unicast_slave_add()");
   3011                         goto release_return;
   3012                     }
   3013                     i = signaled_slave_table.num_entries - 1;
   3014                     signaled_slave_table.entry[i].slave.peer.log_announce_interval = 99;
   3015                     signaled_slave_table.entry[i].slave.peer.log_sync_interval = 99;
   3016                     signaled_slave_table.entry[i].slave.peer.log_delay_request_interval = 99;
   3017 
   3018                     signaled_slave_table.entry[i].slave.peer.announce_receive_timeout =
   3019                         PTP_CLOCK_PRESETS_ANNOUNCE_RECEIPT_TIMEOUT_DEFAULT;
   3020                     signaled_slave_table.entry[i].slave.peer.delay_mechanism =
   3021                         bcmPTPDelayMechanismEnd2End;
   3022                     signaled_slave_table.entry[i].slave.peer.tx_timestamp_mech =
   3023                         peer_ext.peer.tx_timestamp_mech;
   3024                 }
   3025 
   3026                 switch (messageType) {
   3027                 case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   3028                     if ((signaled_slave_table.entry[i].slave.peer.log_announce_interval != logInterMessagePeriod) ||
   3029                         (signaled_slave_table.entry[i].announce_service_active == 0)) {
   3030                         signaled_slave_table.entry[i].announce_service_changed = 1;
   3031                     }
   3032 
   3033                     signaled_slave_table.entry[i].slave.peer.log_announce_interval = logInterMessagePeriod;
   3034                     signaled_slave_table.entry[i].queue_announce_grant = 1;
   3035                     signaled_slave_table.entry[i].announce_duration = durationField;
   3036                     signaled_slave_table.entry[i].announce_request_time = _bcm_ptp_monotonic_time();
   3037 
   3038                     goto release_return;
   3039 
   3040                 case bcmPTP_MESSAGE_TYPE_SYNC:
   3041                     if ((signaled_slave_table.entry[i].slave.peer.log_sync_interval != logInterMessagePeriod) ||
   3042                         (signaled_slave_table.entry[i].sync_service_active == 0)) {
   3043                         signaled_slave_table.entry[i].sync_service_changed = 1;
   3044                     }
   3045 
   3046                     signaled_slave_table.entry[i].slave.peer.log_sync_interval = logInterMessagePeriod;
   3047                     signaled_slave_table.entry[i].queue_sync_grant = 1;
   3048                     signaled_slave_table.entry[i].sync_duration = durationField;
   3049                     signaled_slave_table.entry[i].sync_request_time = _bcm_ptp_monotonic_time();
   3050 
   3051                     goto release_return;
   3052 
   3053                 case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   3054                     if ((signaled_slave_table.entry[i].slave.peer.log_delay_request_interval != logInterMessagePeriod) ||
   3055                         (signaled_slave_table.entry[i].delay_service_active == 0)) {
   3056                         signaled_slave_table.entry[i].delay_service_changed = 1;
   3057                     }
   3058 
   3059                     signaled_slave_table.entry[i].slave.peer.log_delay_request_interval = logInterMessagePeriod;
   3060                     signaled_slave_table.entry[i].queue_delay_grant = 1;
   3061                     signaled_slave_table.entry[i].delay_duration = durationField;
   3062                     signaled_slave_table.entry[i].delay_request_time = _bcm_ptp_monotonic_time();
   3063 
   3064                     goto release_return;
   3065 
   3066                 default:
   3067                     goto release_return;
   3068                 }
   3069             }
   3070 
   3071             break;
   3072 
   3073         case bcmPTPTlvTypeGrantUnicastTransmission:
   3074             {
   3075                 /* find the index of the master in our list: */
   3076                 int idx;
   3077 
   3078                 for (idx = 0; idx < num_signaled_masters; ++idx) {
   3079                     if (_bcm_ptp_peer_address_raw_compare(&signaled_master[idx].master.peer_address,
   3080                             data + src_addr_offset, protocol)) {
   3081 
   3082 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
   3083                         if (signaled_master[idx].update_servo) {
   3084                             sal_memcpy(&signaled_master[idx].master.clock_identity, peer_ext.peer.clock_identity, sizeof(bcm_ptp_clock_identity_t));
   3085                             signaled_master[idx].master.remote_port_number = peer_ext.peer.remote_port_number;
   3086                             signaled_master[idx].update_servo = 0;
   3087                         }
   3088 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
   3089 
   3090                         switch (messageType) {
   3091                         case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   3092                             if (durationField) {
   3093                                 signaled_master[idx].announce_refresh_time = _bcm_ptp_monotonic_time() + durationField / 2 + 1;
   3094                                 signaled_master[idx].service_grants.announce = 1;
   3095                                 signaled_master[idx].unmet_requests.announce = 0;
   3096                             } else {
   3097                                 /* Zero duration GRANT_UNICAST_TRANSMISSION equals request denial. */
   3098                                 signaled_master[idx].service_grants.announce = 0;
   3099                             }
   3100                             goto release_return;
   3101 
   3102                         case bcmPTP_MESSAGE_TYPE_SYNC:
   3103                             if (durationField) {
   3104                                 signaled_master[idx].sync_refresh_time = _bcm_ptp_monotonic_time() + durationField / 2 + 1;
   3105                                 signaled_master[idx].service_grants.sync = 1;
   3106                                 signaled_master[idx].unmet_requests.sync = 0;
   3107 
   3108                                 if (signaled_master[idx].granted_log_sync_interval != logInterMessagePeriod) {
   3109                                     signaled_master[idx].granted_log_sync_interval = logInterMessagePeriod;
   3110                                     sal_dpc(delayed_master_table_update, INT_TO_PTR(delayed_master_table_update),
   3111                                             INT_TO_PTR(idx), INT_TO_PTR(unit), INT_TO_PTR(ptp_id),0);
   3112                                 }
   3113                             } else {
   3114                                 /* Zero duration GRANT_UNICAST_TRANSMISSION equals request denial. */
   3115                                 signaled_master[idx].service_grants.sync = 0;
   3116                             }
   3117 
   3118                             goto release_return;
   3119 
   3120                         case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   3121                             if (durationField) {
   3122                                 signaled_master[idx].delay_refresh_time = _bcm_ptp_monotonic_time() + durationField / 2 + 1;
   3123                                 signaled_master[idx].service_grants.delayresp = 1;
   3124                                 signaled_master[idx].unmet_requests.delayresp = 0;
   3125 
   3126                                 if (signaled_master[idx].granted_log_delay_interval != logInterMessagePeriod) {
   3127                                     signaled_master[idx].granted_log_delay_interval = logInterMessagePeriod;
   3128                                     sal_dpc(delayed_master_table_update, INT_TO_PTR(delayed_master_table_update),
   3129                                             INT_TO_PTR(idx), INT_TO_PTR(unit), INT_TO_PTR(ptp_id),0);
   3130                                 }
   3131                             } else {
   3132                                 /* Zero duration GRANT_UNICAST_TRANSMISSION equals request denial. */
   3133                                 signaled_master[idx].service_grants.delayresp = 0;
   3134                             }
   3135 
   3136                             goto release_return;
   3137 
   3138                         default:
   3139                             goto release_return;
   3140                         }
   3141                     }
   3142                 }
   3143             }
   3144             break;
   3145 
   3146         case bcmPTPTlvTypeCancelUnicastTransmission:
   3147             {
   3148                 /* This could either be from a slave, indicating that we can stop sending
   3149                  * or from a master, indicating that we no longer have a grant
   3150                  * See if it matches a master from our list: */
   3151                 int idx;
   3152                 int rv;
   3153                 int i;
   3154 
   3155                 for (idx = 0; idx < num_signaled_masters; ++idx) {
   3156                     if (_bcm_ptp_peer_address_raw_compare(&signaled_master[idx].master.peer_address,
   3157                             data + src_addr_offset, protocol)) {
   3158                         switch (messageType) {
   3159                         case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   3160                             signaled_master[idx].announce_refresh_time =
   3161                                 _bcm_ptp_monotonic_time() + signaled_master[idx].query_interval_sec;
   3162                             signaled_master[idx].service_grants.announce = 0;
   3163                             signaled_master[idx].to_ack_cancel.announce = 1;
   3164                             goto release_return;
   3165 
   3166                         case bcmPTP_MESSAGE_TYPE_SYNC:
   3167                             signaled_master[idx].sync_refresh_time =
   3168                                 _bcm_ptp_monotonic_time() + signaled_master[idx].query_interval_sec;
   3169                             signaled_master[idx].service_grants.sync = 0;
   3170                             signaled_master[idx].to_ack_cancel.sync = 1;
   3171                             goto release_return;
   3172 
   3173                         case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   3174                             signaled_master[idx].delay_refresh_time =
   3175                                 _bcm_ptp_monotonic_time() + signaled_master[idx].query_interval_sec;
   3176                             signaled_master[idx].service_grants.delayresp = 0;
   3177                             signaled_master[idx].to_ack_cancel.delayresp = 1;
   3178 
   3179                             signaled_master[idx].granted_log_delay_interval = BCM_PTP_SIGNAL_LOGINTERMSG_PERIOD_NONGRANT;
   3180                             sal_dpc(delayed_master_table_update, INT_TO_PTR(delayed_master_table_update),
   3181                                     INT_TO_PTR(idx), INT_TO_PTR(unit), INT_TO_PTR(ptp_id),0);
   3182                             goto release_return;
   3183 
   3184                         default:
   3185                             goto release_return;
   3186                         }
   3187                     }
   3188                 }
   3189 
   3190                 /* Signaled unicast slave lookup. */
   3191                 if (BCM_FAILURE(rv = _bcm_ptp_signaled_unicast_slave_exists(unit, ptp_id, &peer_ext, &i))) {
   3192                     /* No matching entry in signaled unicast slave table. */
   3193                     goto release_return;
   3194                 }
   3195 
   3196                 switch (messageType) {
   3197                 case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   3198                     signaled_slave_table.entry[i].announce_cancel_time = _bcm_ptp_monotonic_time();
   3199                     signaled_slave_table.entry[i].queue_announce_cancel = 1;
   3200                     goto release_return;
   3201 
   3202                 case bcmPTP_MESSAGE_TYPE_SYNC:
   3203                     signaled_slave_table.entry[i].sync_cancel_time = _bcm_ptp_monotonic_time();
   3204                     signaled_slave_table.entry[i].queue_sync_cancel = 1;
   3205                     goto release_return;
   3206 
   3207                 case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   3208                     signaled_slave_table.entry[i].delay_cancel_time = _bcm_ptp_monotonic_time();
   3209                     signaled_slave_table.entry[i].queue_delay_cancel = 1;
   3210                     goto release_return;
   3211 
   3212                 default:
   3213                     goto release_return;
   3214                 }
   3215             }
   3216             break;
   3217 
   3218         case bcmPTPTlvTypeAckCancelUnicastTransmission:
   3219             /* Do nothing. */
   3220             break;
   3221         default:
   3222             ;
   3223         }
   3224 
   3225 release_return:
   3226         _bcm_ptp_mutex_give(slaveTable_mutex);
   3227     }
   3228 
   3229     return bcmPTPCallbackAccept;
   3230 }
   3231 
   3232 
   3233 /*
   3234  * Function:
   3235  *      bcm_common_ptp_unicast_request_duration_get
   3236  * Purpose:
   3237  *      Get durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3238  * Parameters:
   3239  *      unit        - (IN)  Unit number.
   3240  *      ptp_id      - (IN)  PTP stack ID.
   3241  *      clock_num   - (IN)  PTP clock number.
   3242  *      port_num    - (IN) PTP clock port number.
   3243  *      duration - (OUT) durationField (sec.)
   3244  * Returns:
   3245  *      BCM_E_XXX - Function status.
   3246  */
   3247 int
   3248 bcm_common_ptp_unicast_request_duration_get(
   3249     int unit,
   3250     bcm_ptp_stack_id_t ptp_id,
   3251     int clock_num,
   3252     int port_num,
   3253     uint32 *duration)
   3254 {
   3255     *duration = request_uc_durationField;
   3256 
   3257     return BCM_E_NONE;
   3258 }
   3259 
   3260 /*
   3261  * Function:
   3262  *      bcm_common_ptp_unicast_request_duration_set
   3263  * Purpose:
   3264  *      Set durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3265  * Parameters:
   3266  *      unit        - (IN)  Unit number.
   3267  *      ptp_id      - (IN)  PTP stack ID.
   3268  *      clock_num   - (IN)  PTP clock number.
   3269  *      port_num    - (IN) PTP clock port number.
   3270  *      duration - (IN) durationField (sec.)
   3271  * Returns:
   3272  *      BCM_E_XXX - Function status.
   3273  */
   3274 int
   3275 bcm_common_ptp_unicast_request_duration_set(
   3276     int unit,
   3277     bcm_ptp_stack_id_t ptp_id,
   3278     int clock_num,
   3279     int port_num,
   3280     uint32 duration)
   3281 {
   3282     if (duration < request_uc_durationField_min) {
   3283         request_uc_durationField = request_uc_durationField_min;
   3284     } else if (duration > request_uc_durationField_max) {
   3285         request_uc_durationField = request_uc_durationField_max;
   3286     } else {
   3287         request_uc_durationField = duration;
   3288     }
   3289 
   3290     return BCM_E_NONE;
   3291 }
   3292 
   3293 /*
   3294  * Function:
   3295  *      bcm_common_ptp_unicast_request_duration_min_get
   3296  * Purpose:
   3297  *      Get minimum durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3298  * Parameters:
   3299  *      unit         - (IN)  Unit number.
   3300  *      ptp_id       - (IN)  PTP stack ID.
   3301  *      clock_num    - (IN)  PTP clock number.
   3302  *      port_num     - (IN) PTP clock port number.
   3303  *      duration_min - (OUT) minimum durationField (sec.)
   3304  * Returns:
   3305  *      BCM_E_XXX - Function status.
   3306  */
   3307 int
   3308 bcm_common_ptp_unicast_request_duration_min_get(
   3309     int unit,
   3310     bcm_ptp_stack_id_t ptp_id,
   3311     int clock_num,
   3312     int port_num,
   3313     uint32 *duration_min)
   3314 {
   3315     *duration_min = request_uc_durationField_min;
   3316 
   3317     return BCM_E_NONE;
   3318 }
   3319 
   3320 /*
   3321  * Function:
   3322  *      bcm_common_ptp_unicast_request_duration_min_set
   3323  * Purpose:
   3324  *      Set minimum durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3325  * Parameters:
   3326  *      unit         - (IN)  Unit number.
   3327  *      ptp_id       - (IN)  PTP stack ID.
   3328  *      clock_num    - (IN)  PTP clock number.
   3329  *      port_num     - (IN) PTP clock port number.
   3330  *      duration_min - (IN) minimum durationField (sec.)
   3331  * Returns:
   3332  *      BCM_E_XXX - Function status.
   3333  */
   3334 int
   3335 bcm_common_ptp_unicast_request_duration_min_set(
   3336     int unit,
   3337     bcm_ptp_stack_id_t ptp_id,
   3338     int clock_num,
   3339     int port_num,
   3340     uint32 duration_min)
   3341 {
   3342     if (duration_min > request_uc_durationField_max) {
   3343         return BCM_E_PARAM;
   3344     }
   3345 
   3346     request_uc_durationField_min = duration_min;
   3347 
   3348     /* durationField in-range enforcement. */
   3349     if (request_uc_durationField < duration_min) {
   3350         request_uc_durationField = duration_min;
   3351     }
   3352 
   3353     return BCM_E_NONE;
   3354 }
   3355 
   3356 /*
   3357  * Function:
   3358  *      bcm_common_ptp_unicast_request_duration_max_get
   3359  * Purpose:
   3360  *      Get maximum durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3361  * Parameters:
   3362  *      unit         - (IN)  Unit number.
   3363  *      ptp_id       - (IN)  PTP stack ID.
   3364  *      clock_num    - (IN)  PTP clock number.
   3365  *      port_num     - (IN) PTP clock port number.
   3366  *      duration_max - (OUT) maximum durationField (sec.)
   3367  * Returns:
   3368  *      BCM_E_XXX - Function status.
   3369  */
   3370 int
   3371 bcm_common_ptp_unicast_request_duration_max_get(
   3372     int unit,
   3373     bcm_ptp_stack_id_t ptp_id,
   3374     int clock_num,
   3375     int port_num,
   3376     uint32 *duration_max)
   3377 {
   3378     *duration_max = request_uc_durationField_max;
   3379 
   3380     return BCM_E_NONE;
   3381 }
   3382 
   3383 /*
   3384  * Function:
   3385  *      bcm_common_ptp_unicast_request_duration_max_set
   3386  * Purpose:
   3387  *      Set maximum durationField of REQUEST_UNICAST_TRANSMISSION TLV.
   3388  * Parameters:
   3389  *      unit         - (IN)  Unit number.
   3390  *      ptp_id       - (IN)  PTP stack ID.
   3391  *      clock_num    - (IN)  PTP clock number.
   3392  *      port_num     - (IN) PTP clock port number.
   3393  *      duration_max - (IN) maximum durationField (sec.)
   3394  * Returns:
   3395  *      BCM_E_XXX - Function status.
   3396  */
   3397 int
   3398 bcm_common_ptp_unicast_request_duration_max_set(
   3399     int unit,
   3400     bcm_ptp_stack_id_t ptp_id,
   3401     int clock_num,
   3402     int port_num,
   3403     uint32 duration_max)
   3404 {
   3405     if (duration_max < request_uc_durationField_min) {
   3406         return BCM_E_PARAM;
   3407     }
   3408 
   3409     request_uc_durationField_max = duration_max;
   3410 
   3411     /* durationField in-range enforcement. */
   3412     if (request_uc_durationField > duration_max) {
   3413         request_uc_durationField = duration_max;
   3414     }
   3415 
   3416     return BCM_E_NONE;
   3417 }
   3418 
   3419 /*
   3420  * Function:
   3421  *      delayed_master_table_update
   3422  * Purpose:
   3423  *      DPC-called function to update the ToP's master table
   3424  */
   3425 static void
   3426 delayed_master_table_update(
   3427     void *owner,
   3428     void *arg_idx,
   3429     void *arg_unit,
   3430     void *arg_ptp_id,
   3431     void *arg_clock_num)
   3432 {
   3433     int idx = PTR_TO_INT(arg_idx);
   3434     int unit = PTR_TO_INT(arg_unit);
   3435     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(arg_ptp_id);
   3436     int clock_num = PTR_TO_INT(arg_clock_num);
   3437     bcm_ptp_clock_unicast_master_t master_info;
   3438     int rv;
   3439 
   3440     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3441             clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3442         PTP_ERROR_FUNC("_bcm_ptp_function_precheck()");
   3443         return;
   3444     }
   3445 
   3446     master_info.address = signaled_master[idx].master.peer_address;
   3447     master_info.log_sync_interval = signaled_master[idx].log_sync_interval;
   3448     master_info.log_min_delay_request_interval = signaled_master[idx].log_delay_interval;
   3449 
   3450     bcm_ptp_static_unicast_master_add(unit, ptp_id, clock_num,
   3451         signaled_master[idx].master.local_port_number,
   3452         &master_info);
   3453 }
   3454 
   3455 #endif /* INCLUDE_PTP */