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

master_config.c (19396B)


      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:    master_config.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      bcm_common_ptp_static_unicast_master_add
     13  *      bcm_common_ptp_static_unicast_master_list
     14  *      bcm_common_ptp_static_unicast_master_remove
     15  *      bcm_common_ptp_static_unicast_master_table_clear
     16  *      bcm_common_ptp_static_unicast_master_table_size_get
     17  */
     18 
     19 #if defined(INCLUDE_PTP)
     20 
     21 #include <soc/defs.h>
     22 #include <soc/drv.h>
     23 
     24 #include <bcm/ptp.h>
     25 #include <bcm_int/common/ptp.h>
     26 #include <bcm/error.h>
     27 #include <bcm_int/ptp_common.h>
     28 
     29 /* PTP clock unicast master table. */
     30 typedef struct _bcm_ptp_unicast_master_table_s {
     31     uint16 num_entries;
     32     bcm_ptp_clock_unicast_master_t entry[PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES];
     33 } _bcm_ptp_unicast_master_table_t;
     34 
     35 /* PTP stack unicast master table array. */
     36 typedef struct _bcm_ptp_stack_ucm_array_s {
     37     _bcm_ptp_memstate_t memstate;
     38     _bcm_ptp_unicast_master_table_t *table;
     39 } _bcm_ptp_stack_ucm_array_t;
     40 
     41 /* Unit unicast master table array(s). */
     42 typedef struct _bcm_ptp_unit_ucm_array_s {
     43     _bcm_ptp_memstate_t memstate;
     44     _bcm_ptp_stack_ucm_array_t *stack_array;
     45 } _bcm_ptp_unit_ucm_array_t;
     46 
     47 static const bcm_ptp_clock_unicast_master_t ucm_entry_default;
     48 static const _bcm_ptp_unicast_master_table_t ucm_default;
     49 static _bcm_ptp_unit_ucm_array_t unit_ucm_array[BCM_MAX_NUM_UNITS];
     50 
     51 static int _bcm_ptp_unicast_master_table_set(int unit, bcm_ptp_stack_id_t ptp_id, int clock_num);
     52 
     53 /*
     54  * Function:
     55  *      _bcm_ptp_unicast_master_table_init
     56  * Purpose:
     57  *      Initialize the unicast master table arrays of a unit.
     58  * Parameters:
     59  *      unit - (IN) Unit number.
     60  * Returns:
     61  *      BCM_E_XXX
     62  * Notes:
     63  */
     64 int
     65 _bcm_ptp_unicast_master_table_init(
     66     int unit)
     67 {
     68     int rv = BCM_E_UNAVAIL;
     69     int i;
     70 
     71     _bcm_ptp_stack_ucm_array_t *stack_p;
     72 
     73     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
     74             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
     75         return rv;
     76     }
     77     if (NULL == unit_ucm_array[unit].stack_array) {
     78         stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT*
     79                             sizeof(_bcm_ptp_stack_ucm_array_t),"Unit UCM arrays");
     80     } else {
     81         stack_p = unit_ucm_array[unit].stack_array;
     82     }
     83     
     84     if (!stack_p) {
     85         unit_ucm_array[unit].memstate = PTP_MEMSTATE_FAILURE;
     86         return BCM_E_MEMORY;
     87     }
     88 
     89     unit_ucm_array[unit].stack_array = stack_p;
     90     unit_ucm_array[unit].memstate = PTP_MEMSTATE_INITIALIZED;
     91 
     92     for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) {
     93         unit_ucm_array[unit].stack_array[i].memstate = PTP_MEMSTATE_STARTUP;
     94     }
     95 
     96     return rv;
     97 }
     98 
     99 /*
    100  * Function:
    101  *      _bcm_ptp_unicast_master_table_init_detach
    102  * Purpose:
    103  *      Shut down the unicast master table arrays of a unit.
    104  * Parameters:
    105  *      unit - (IN) Unit number.
    106  * Returns:
    107  *      BCM_E_XXX
    108  * Notes:
    109  */
    110 int
    111 _bcm_ptp_unicast_master_table_detach(
    112     int unit)
    113 {
    114     int i;
    115 
    116     if(unit_ucm_array[unit].stack_array) {
    117         for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) {
    118             _bcm_ptp_unicast_master_table_stack_destroy(unit, i);
    119         }
    120 
    121         unit_ucm_array[unit].memstate = PTP_MEMSTATE_STARTUP;
    122         sal_free(unit_ucm_array[unit].stack_array);
    123         unit_ucm_array[unit].stack_array = NULL;
    124     }
    125     return BCM_E_NONE;
    126 }
    127 
    128 /*
    129  * Function:
    130  *      _bcm_ptp_unicast_master_table_stack_create
    131  * Purpose:
    132  *      Create the unicast master table array of a PTP stack.
    133  * Parameters:
    134  *      unit    - (IN) Unit number.
    135  *      ptp_id  - (IN) PTP stack ID.
    136  * Returns:
    137  *      BCM_E_XXX
    138  * Notes:
    139  */
    140 int
    141 _bcm_ptp_unicast_master_table_stack_create(
    142     int unit,
    143     bcm_ptp_stack_id_t ptp_id)
    144 {
    145     int rv = BCM_E_UNAVAIL;
    146 
    147     _bcm_ptp_unicast_master_table_t *table_p;
    148     int i = 0;
    149 
    150     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    151             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    152         return rv;
    153     }
    154 
    155     if (unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    156         return BCM_E_UNAVAIL;
    157     }
    158 
    159     if (unit_ucm_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_INITIALIZED) {
    160         return BCM_E_EXISTS;
    161     }
    162 
    163     table_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES*
    164                         sizeof(_bcm_ptp_unicast_master_table_t),
    165                         "PTP stack UCM array");
    166 
    167     if (!table_p) {
    168             unit_ucm_array[unit].stack_array[ptp_id].memstate =
    169             PTP_MEMSTATE_FAILURE;
    170         return BCM_E_MEMORY;
    171     }
    172 
    173     unit_ucm_array[unit].stack_array[ptp_id].table = table_p;
    174     unit_ucm_array[unit].stack_array[ptp_id].memstate =
    175         PTP_MEMSTATE_INITIALIZED;
    176 
    177     /* Set number of entries. */
    178     for (i = 0; i < PTP_MAX_CLOCK_INSTANCES; ++i) {
    179         unit_ucm_array[unit].stack_array[ptp_id].table[i].num_entries = 0;
    180     }
    181 
    182     return rv;
    183 }
    184 
    185 /*
    186  * Function:
    187  *      _bcm_ptp_unicast_master_table_stack_destroy
    188  * Purpose:
    189  *      Destroy the unicast master table array of a PTP stack.
    190  * Parameters:
    191  *      unit    - (IN) Unit number.
    192  *      ptp_id  - (IN) PTP stack ID.
    193  * Returns:
    194  *      BCM_E_XXX
    195  * Notes:
    196  */
    197 int
    198 _bcm_ptp_unicast_master_table_stack_destroy(
    199     int unit,
    200     bcm_ptp_stack_id_t ptp_id)
    201 {
    202     int rv = BCM_E_NONE;
    203 
    204     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    205             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    206         return rv;
    207     }
    208 
    209     if (unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    210         return BCM_E_UNAVAIL;
    211     }
    212 
    213     if (unit_ucm_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_INITIALIZED) {
    214         unit_ucm_array[unit].stack_array[ptp_id].memstate =
    215             PTP_MEMSTATE_STARTUP;
    216         sal_free(unit_ucm_array[unit].stack_array[ptp_id].table);
    217         unit_ucm_array[unit].stack_array[ptp_id].table = 0;
    218     }
    219 
    220     return rv;
    221 }
    222 
    223 /*
    224  * Function:
    225  *      _bcm_ptp_unicast_master_table_clock_create
    226  * Purpose:
    227  *      Create the unicast master table array of a PTP clock.
    228  * Parameters:
    229  *      unit      - (IN) Unit number.
    230  *      ptp_id    - (IN) PTP stack ID.
    231  *      clock_num - (IN) PTP clock number.
    232  * Returns:
    233  *      BCM_E_XXX
    234  * Notes:
    235  */
    236 int 
    237 _bcm_ptp_unicast_master_table_clock_create(
    238     int unit, 
    239     bcm_ptp_stack_id_t ptp_id,
    240     int clock_num)
    241 {
    242     int rv = BCM_E_UNAVAIL;
    243          
    244     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    245             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    246         return rv;   
    247     }
    248         
    249     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    250             (unit_ucm_array[unit].stack_array[ptp_id].memstate != 
    251             PTP_MEMSTATE_INITIALIZED)) {
    252         return BCM_E_UNAVAIL;
    253     }
    254 
    255     unit_ucm_array[unit].stack_array[ptp_id].table[clock_num] = ucm_default;
    256     
    257     return rv;
    258 }
    259 
    260 /*
    261  * Function:
    262  *      bcm_common_ptp_static_unicast_master_table_size_get
    263  * Purpose:
    264  *      Get maximum number of unicast master table entries of a PTP clock.
    265  * Parameters:
    266  *      unit              - (IN)  Unit number.
    267  *      ptp_id            - (IN)  PTP stack ID.
    268  *      clock_num         - (IN)  PTP clock number.
    269  *      port_num          - (IN)  PTP clock port number.
    270  *      max_table_entries - (OUT) Maximum number of unicast master table entries.
    271  * Returns:
    272  *      BCM_E_XXX
    273  * Notes:
    274  *      Ref. IEEE Std. 1588-2008, Chapter 17.5.4.
    275  */
    276 int 
    277 bcm_common_ptp_static_unicast_master_table_size_get(
    278     int unit, 
    279     bcm_ptp_stack_id_t ptp_id, 
    280     int clock_num, 
    281     int port_num, 
    282     int *max_table_entries)
    283 {
    284     int rv = BCM_E_UNAVAIL;
    285     
    286     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    287             (uint32)port_num))) {
    288         return rv;   
    289     }
    290         
    291     *max_table_entries = PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES;
    292     
    293     return rv;
    294 }
    295 
    296 /*
    297  * Function:
    298  *      bcm_common_ptp_static_unicast_master_add
    299  * Purpose:
    300  *      Add an entry to the unicast master table of a PTP clock.
    301  * Parameters:
    302  *      unit        - (IN) Unit number.
    303  *      ptp_id      - (IN) PTP stack ID.
    304  *      clock_num   - (IN) PTP clock number.
    305  *      port_num    - (IN) PTP clock port number.
    306  *      master_info - (IN) Unicast master address and granted message intervals.                  
    307  * Returns:
    308  *      BCM_E_XXX
    309  * Notes:
    310  */
    311 int 
    312 bcm_common_ptp_static_unicast_master_add(
    313     int unit, 
    314     bcm_ptp_stack_id_t ptp_id, 
    315     int clock_num, 
    316     int port_num, 
    317     bcm_ptp_clock_unicast_master_t *master_info)
    318 {
    319     int rv = BCM_E_UNAVAIL;
    320     
    321     _bcm_ptp_unicast_master_table_t *unicast_master_table;
    322     int i = 0;
    323     
    324     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    325             (uint32)port_num))) {
    326         return rv;   
    327     }
    328         
    329     if (master_info == NULL) {
    330         return BCM_E_PARAM;
    331     }
    332     
    333     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    334             (unit_ucm_array[unit].stack_array[ptp_id].memstate != 
    335             PTP_MEMSTATE_INITIALIZED)) {
    336         return BCM_E_UNAVAIL;
    337     }
    338 
    339     unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id]
    340                                                 .table[clock_num];
    341 
    342     i = 0;
    343     while (i < unicast_master_table->num_entries) {
    344         if (_bcm_ptp_peer_address_compare(&master_info->address,
    345                 &unicast_master_table->entry[i].address)) {
    346             break;
    347         }
    348         ++i;
    349     }
    350 
    351     if (i >= PTP_MAX_UNICAST_MASTER_TABLE_ENTRIES) {
    352         return BCM_E_FULL; 
    353     }
    354 
    355     if (i == unicast_master_table->num_entries) {
    356         /* New entry. */
    357         ++unicast_master_table->num_entries;
    358     }
    359 
    360     unicast_master_table->entry[i].address = 
    361         master_info->address;
    362     unicast_master_table->entry[i].log_sync_interval = 
    363         master_info->log_sync_interval;
    364     unicast_master_table->entry[i].log_min_delay_request_interval =
    365         master_info->log_min_delay_request_interval;
    366 
    367     /* Update PTP stack firmware unicast master table. */
    368     rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num);
    369     
    370     return rv;
    371 }
    372 
    373 /*
    374  * Function:
    375  *      bcm_common_ptp_static_unicast_master_list
    376  * Purpose:
    377  *      List the unicast master table of a PTP clock.
    378  * Parameters:
    379  *      unit        - (IN) Unit number.
    380  *      ptp_id      - (IN) PTP stack ID.
    381  *      clock_num   - (IN) PTP clock number.
    382  *      port_num    - (IN) PTP clock port number.
    383  *      num_masters - (OUT) Number of unicast master table entries.
    384  *      master_info - (OUT) Unicast master table.
    385  * Returns:
    386  *      BCM_E_XXX
    387  * Notes:
    388  */
    389 int 
    390 bcm_common_ptp_static_unicast_master_list(
    391     int unit,
    392     bcm_ptp_stack_id_t ptp_id, 
    393     int clock_num, 
    394     int port_num, 
    395     int max_num_masters, 
    396     int *num_masters, 
    397     bcm_ptp_clock_peer_address_t *master_info)
    398 {
    399     int rv = BCM_E_NONE;
    400     
    401     _bcm_ptp_unicast_master_table_t *unicast_master_table;
    402     int i = 0;
    403     
    404     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    405             (uint32)port_num))) {
    406         return rv;   
    407     }
    408         
    409     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    410             (unit_ucm_array[unit].stack_array[ptp_id].memstate != 
    411             PTP_MEMSTATE_INITIALIZED)) {
    412         return BCM_E_UNAVAIL;
    413     }
    414 
    415     unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id]
    416                                                 .table[clock_num];
    417 
    418     if (unicast_master_table->num_entries == 0) {
    419         *num_masters = 0;
    420         return rv;
    421     }
    422 
    423     
    424     if (unicast_master_table->num_entries > max_num_masters) {
    425         *num_masters = 0;
    426         return BCM_E_RESOURCE;
    427     }
    428 
    429     /* 
    430      * Get PTP clock unicast master table.
    431      * NOTICE: Returns a local, SDK copy of unicast master table 
    432      *         rather than query PTP stack firmware.
    433      */
    434     *num_masters = unicast_master_table->num_entries;
    435 
    436     for (i = 0; i < (*num_masters); ++i) {
    437         master_info[i] = unicast_master_table->entry[i].address;
    438     }
    439 
    440     return rv;
    441 }
    442 
    443 /*
    444  * Function:
    445  *      bcm_common_ptp_static_unicast_master_remove
    446  * Purpose:
    447  *      Remove an entry from the unicast master table of a PTP clock.
    448  * Parameters:
    449  *      unit        - (IN) Unit number.
    450  *      ptp_id      - (IN) PTP stack ID.
    451  *      clock_num   - (IN) PTP clock number.
    452  *      port_num    - (IN) PTP clock port number.
    453  *      master_info - (IN) Unicast master address.
    454  * Returns:
    455  *      BCM_E_XXX
    456  * Notes:
    457  */
    458 int 
    459 bcm_common_ptp_static_unicast_master_remove(
    460     int unit, 
    461     bcm_ptp_stack_id_t ptp_id, 
    462     int clock_num, 
    463     int port_num, 
    464     bcm_ptp_clock_peer_address_t *master_info)
    465 {
    466     int rv = BCM_E_UNAVAIL;
    467     
    468     _bcm_ptp_unicast_master_table_t *unicast_master_table;
    469     int i = 0;
    470     int k = 0;
    471     
    472     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    473             (uint32)port_num))) {
    474         return rv;   
    475     }
    476         
    477     if (master_info == NULL) {
    478         return BCM_E_PARAM;
    479     }
    480     
    481     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    482             (unit_ucm_array[unit].stack_array[ptp_id].memstate != 
    483             PTP_MEMSTATE_INITIALIZED)) {
    484         return BCM_E_UNAVAIL;
    485     }
    486 
    487     unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id]
    488                                                 .table[clock_num];
    489 
    490     if (unicast_master_table->num_entries == 0) {
    491         return BCM_E_EMPTY;
    492     }
    493 
    494     i = 0; 
    495     k = 0;
    496     while (i < unicast_master_table->num_entries) {
    497         if (_bcm_ptp_peer_address_compare(master_info,
    498                 &unicast_master_table->entry[i].address)) {
    499             /* 
    500              * Remove this entry by moving last entry into this slot, and 
    501              * decrementing number of entries. 
    502              */
    503             unicast_master_table->entry[i] = 
    504                 unicast_master_table->entry[--unicast_master_table->num_entries];
    505 
    506             /* Reset unused entry. */
    507             unicast_master_table->entry[unicast_master_table->num_entries] =
    508                 ucm_entry_default;
    509 
    510             ++k;
    511         } 
    512         else 
    513         {
    514             ++i;
    515         }
    516     }
    517 
    518     if (k <= 0) {
    519         /* No matching peer address(es) in unicast master table. */
    520         return BCM_E_NOT_FOUND; 
    521     }
    522 
    523     /* Update PTP stack firmware unicast master table. */
    524     rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num);
    525     
    526     return rv;
    527 }
    528 
    529 /*
    530  * Function:
    531  *      bcm_common_ptp_static_unicast_master_table_clear
    532  * Purpose:
    533  *      Clear (i.e. remove all entries from) the unicast master table 
    534  *      of a PTP clock.
    535  * Parameters:
    536  *      unit      - (IN) Unit number.
    537  *      ptp_id    - (IN) PTP stack ID.
    538  *      clock_num - (IN) PTP clock number.
    539  *      port_num  - (IN) PTP clock port number.
    540  * Returns:
    541  *      BCM_E_XXX
    542  * Notes:
    543  */
    544 int 
    545 bcm_common_ptp_static_unicast_master_table_clear(
    546     int unit, 
    547     bcm_ptp_stack_id_t ptp_id, 
    548     int clock_num, 
    549     int port_num)
    550 {
    551     int rv;
    552 
    553     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
    554             (uint32)port_num))) {
    555         return rv;
    556     }
    557 
    558     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    559             (unit_ucm_array[unit].stack_array[ptp_id].memstate !=
    560             PTP_MEMSTATE_INITIALIZED)) {
    561         return BCM_E_UNAVAIL;
    562     }
    563 
    564     unit_ucm_array[unit].stack_array[ptp_id].table[clock_num] = ucm_default;
    565 
    566     /* Update PTP stack firmware unicast master table. */
    567     rv = _bcm_ptp_unicast_master_table_set(unit, ptp_id, clock_num);
    568 
    569     return rv;
    570 }
    571 
    572 /*
    573  * Function:
    574  *      _bcm_ptp_unicast_master_table_set
    575  * Purpose:
    576  *      Set unicast master table of a PTP clock.
    577  * Parameters:
    578  *      unit       - (IN)  Unit number.
    579  *      ptp_id     - (IN)  PTP stack ID.
    580  *      clock_num  - (IN)  PTP clock number.
    581  * Returns:
    582  *      BCM_E_XXX
    583  * Notes:
    584  */
    585 static int 
    586 _bcm_ptp_unicast_master_table_set(
    587     int unit, 
    588     bcm_ptp_stack_id_t ptp_id, 
    589     int clock_num)
    590 {
    591     int rv = BCM_E_UNAVAIL;
    592     
    593     uint8 payload[PTP_MGMTMSG_PAYLOAD_MAX_UNICAST_MASTER_TABLE_SIZE_OCTETS] = {0};
    594     uint8 resp[PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS];
    595     int resp_len = PTP_MGMTMSG_RESP_MAX_SIZE_OCTETS; 
    596     
    597     _bcm_ptp_unicast_master_table_t *unicast_master_table;
    598     bcm_ptp_port_identity_t portid;     
    599     int i = 0;
    600     int k = 0;
    601     int el = 0;
    602     int raw_l2_length = 0;
    603     
    604     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 
    605             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    606         return rv;   
    607     }
    608   
    609     if ((unit_ucm_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    610             (unit_ucm_array[unit].stack_array[ptp_id].memstate != 
    611             PTP_MEMSTATE_INITIALIZED)) {
    612         return BCM_E_UNAVAIL;
    613     }
    614 
    615     if (BCM_FAILURE(rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, 
    616             clock_num, 1, &portid))) {
    617         return rv;
    618     }
    619 
    620     unicast_master_table = &unit_ucm_array[unit].stack_array[ptp_id]
    621                                                 .table[clock_num];
    622 
    623     /* 
    624      * Make payload.
    625      *    Octet 0...1 : Number of unicast master table entries.
    626      *    Octet 3...* : Unicast master table entries.
    627      */
    628     i = 0;
    629     _bcm_ptp_uint16_write(payload, unicast_master_table->num_entries);  
    630     i += sizeof(uint16);
    631 
    632     for (el = 0; el < unicast_master_table->num_entries; ++el) {
    633         _bcm_ptp_uint16_write(&payload[i], 
    634             unicast_master_table->entry[el].address.addr_type);  
    635         i += sizeof(uint16);
    636 
    637         switch (unicast_master_table->entry[el].address.addr_type) {
    638         case bcmPTPUDPIPv4:
    639             /* Ethernet/UDP/IPv4 address type. */
    640             _bcm_ptp_uint16_write(&payload[i], PTP_IPV4_ADDR_SIZE_BYTES);  
    641             i += sizeof(uint16);
    642             _bcm_ptp_uint32_write(&payload[i], 
    643                 unicast_master_table->entry[el].address.ipv4_addr);  
    644             i += sizeof(uint32);
    645 
    646             break;
    647 
    648         case bcmPTPUDPIPv6:
    649             /* Ethernet/UDP/IPv6 address type. */
    650             _bcm_ptp_uint16_write(&payload[i], PTP_IPV6_ADDR_SIZE_BYTES);  
    651             i += sizeof(uint16);
    652 
    653             for (k = 0; k < PTP_IPV6_ADDR_SIZE_BYTES; ++k) {
    654                 payload[i++] = unicast_master_table->entry[el]
    655                                .address.ipv6_addr[k];
    656             }
    657 
    658             break;
    659 
    660         default:
    661             _bcm_ptp_uint16_write(&payload[i], 0);  
    662             i += sizeof(uint16);
    663         }
    664 
    665         payload[i++] = (uint8)unicast_master_table->entry[el]
    666                               .log_sync_interval;
    667         payload[i++] = (uint8)unicast_master_table->entry[el]
    668                               .log_min_delay_request_interval;
    669 
    670         raw_l2_length = unicast_master_table->entry[el]
    671                         .address.raw_l2_header_length;
    672         _bcm_ptp_uint16_write(&payload[i], raw_l2_length);  
    673         i += sizeof(uint16);
    674 
    675         for (k = 0; k < raw_l2_length; ++k) {
    676             payload[i++] = unicast_master_table->entry[el]
    677                            .address.raw_l2_header[k];
    678         }
    679     }    
    680 
    681     rv = _bcm_ptp_management_message_send(unit, ptp_id, clock_num, &portid,
    682             PTP_MGMTMSG_SET, PTP_MGMTMSG_ID_UNICAST_MASTER_TABLE, 
    683             payload, i, resp, &resp_len);
    684     
    685     return rv;
    686 }
    687 #endif /* defined(INCLUDE_PTP)*/