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

traffic.c (111796B)


      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  * XGS/StrataSwitch Traffic Generator aka. "Traffic, Traf-Test, Snake, etc."
      8  *
      9  * Switching API Stress Test using A/B Ethernet port pairs as
     10  * load generators. Different from Snake test in that packet flow
     11  * is between a source and sink port pair (A/B).
     12  *
     13  * When stress-testing XGS/StrataSwitch devices, usually, one will require
     14  * a SmartBits (TM) or IXIA (TM) network testing device to spray
     15  * frames to all of the ports and make them switch at line rate.
     16  *
     17  * The purpose of this test is to configure a pair of ports as
     18  * transmitters and receivers while the switch ASIC is configured to only
     19  * forward a frame between these two port pairs.
     20  *
     21  * The CPU then injects a frame into the port pairs going one
     22  * direction or the other (or bidirectional), and the packet loops
     23  * forever between the port pairs until the H/W fails, or the user
     24  * stops the test. Typically, this happens at layer 2, using unicast,
     25  * broadcast, multicast, or VLAN traffic, however extensions for layer3
     26  * and higher (via the FFP) are possible.
     27  *
     28  * When testing, a "golden" switch (one known to be free of H/W bugs)
     29  * is stress tested and the result is that the port-pairs should
     30  * forward the frame forever. Failure for the ASIC to do so indicates
     31  * faulty hardware and the problem should be investigated and
     32  * debugged.  An interesting feature of the XGS/StrataSwitch family of
     33  * devices is that they should forward traffic at line rate for all
     34  * layers of the test (e.g. MAC, PHY, Wire at 10Mbps, 100Mbps, 1Gbps, etc).
     35  *
     36  * In addition, this test allows the switch hardware to be used to
     37  * test itself, without the cost of a SmartBits or IXIA testing device
     38  * per switch; moreover, this speeds up testing as any switch which
     39  * passes this traffic test is known to pass a forwarding test between
     40  * two theoretical hosts.
     41  *
     42  *
     43  * MAC/PHY (Broadcast Test)
     44  *
     45  *     In the MAC or PHY tests, a VLAN is created with each port pair
     46  *     (A/B) as a member. The PVLAN table reflects the same VLAN ID
     47  *     and an untagged packet is sent out the port (with the ports in
     48  *     loopback) with the matching VLAN. As the packet ingresses into
     49  *     the switch, a DLF occurs, and the resulting unknown unicast or
     50  *     broadcast frame floods the VLAN, and packets swirl between
     51  *     ports A/B at line rate.
     52  *
     53  *     For example, assuming two ports A(ge0), and B (ge1):
     54  *
     55  *     vlan create 10 PBM=portA,portB UBM=portA,portB
     56  *     pvlan set portA VIDA
     57  *     pvlan set portB VIDA
     58  *
     59  *     tx 1 PBM=portA UBM=portA L=68 VL=10 P=0x12345678 PI=1 \
     60  *     SM=00:00:00:00:00:02 SMI=0 DM=ff:ff:ff:ff:ff:ff DMI=0 \
     61  *     COS=0 CRC=Recompute
     62  *
     63  *     tx 1 PBM=portB UBM=portB L=68 VL=10 P=0x12345678 PI=1 \
     64  *     SM=00:00:00:00:00:02 SMI=0 DM=ff:ff:ff:ff:ff:ff DMI=0 \
     65  *     COS=0 CRC=Recompute
     66  *
     67  *
     68  * External (Unicast Test)
     69  *
     70  *     In external test mode, a VLAN is created for each port (A/B)
     71  *     and both ports are in the tagged and untagged bitmaps. Next,
     72  *     the PVLAN table is setup with a unique vlan for both A and B.
     73  *     Finally, an L2 address is setup for each port in the ARL with a
     74  *     MAC address (of the port), however, the VLAN entry points to
     75  *     the opposite port, so that when a packet comes back in the link
     76  *     partner's port, it gets retagged with a VLAN which will flood
     77  *     it to the originator.
     78  *
     79  *     For example, assuming two ports A(ge0), and B (ge1):
     80  *
     81  *     vlan create A PBM=portA,portB UBM=portA,portB
     82  *     vlan create B PBM=portA,portB UBM=portA,portB
     83  *     pvlan set portA A
     84  *     pvlan set portB B
     85  *
     86  *     l2 add PBM=portA MAC=00:00:00:00:00:portA V=B ST=T
     87  *     l2 add PBM=portB MAC=00:00:00:00:00:portB V=A ST=T
     88  *
     89  *     tx 1 PBM=portB UBM=portB L=68 VL=A P=0x12345678 PI=1 \
     90  *     SM=00:00:00:00:00:portA SMI=0 DM=00:00:00:00:00:portB \
     91  *     DMI=0 COS=0 CRC=Recompute
     92  *
     93  *     tx 1 PBM=portA UBM=portA L=68 VL=B P=0x12345678 PI=1 \
     94  *     SM=00:00:00:00:00:portB SMI=0 DM=00:00:00:00:00:portA \
     95  *     DMI=0 COS=0 CRC=Recompute
     96  *
     97  *  General
     98  *
     99  *    Both ports are setup to transmit and receive a packet (full-duplex)
    100  *    by default.
    101  *
    102  *    The test runs forever, looping and reporting statistics until it
    103  *    detects that a packet is lost, at which point an error is
    104  *    reported and relevant statistics from the MAC or PHY are reported.
    105  *
    106  *    In general, when bringing up new switch hardware, one should start by
    107  *    testing at the MAC layer, then moving to the PHY layer, and
    108  *    finally, externally, by connected each port pair to it's
    109  *    neighbor (1-2, 3-4, etc).
    110  */
    111 #include <sal/types.h>
    112 #include <sal/core/boot.h>
    113 #include <sal/appl/sal.h>
    114 #include <shared/bsl.h>
    115 #include <appl/diag/system.h>
    116 #include <appl/diag/parse.h>
    117 #include <appl/diag/test.h>
    118 #include <appl/test/loopback2.h>
    119 
    120 #include <soc/mem.h>
    121 #ifdef BCM_ESW_SUPPORT
    122 #include <soc/firebolt.h>
    123 #include <bcm_int/esw/mbcm.h>
    124 #ifdef BCM_ENDURO_SUPPORT
    125 #include <soc/error.h>
    126 #endif
    127 #endif
    128 
    129 #include <bcm/error.h>
    130 #include <bcm/l2.h>
    131 #include <bcm/pkt.h>
    132 #include <bcm/tx.h>
    133 #include <bcm/port.h>
    134 #include <bcm/vlan.h>
    135 #include <bcm/link.h>
    136 #include <bcm/stg.h>
    137 #include <bcm/link.h>
    138 #include <bcm/stat.h>
    139 #include <bcm/stack.h>
    140 
    141 #if defined(INCLUDE_MACSEC)
    142 #include <bcm/macsec.h>
    143 
    144 static int macsec_stop_poll_task = 1;
    145 #endif /* INCLUDE_MACSEC */
    146 
    147 #if defined(BCM_GREYHOUND2_SUPPORT)
    148 #include <soc/port_ability.h>
    149 #endif /* BCM_GREYHOUND2_SUPPORT */
    150 #include "traffic.h"
    151 
    152 /* Unicast test */
    153 static sal_mac_addr_t traf_unicast_mac_base = {0,0,0,0,0xfe,0};
    154 
    155 /* Unicast test */
    156 static sal_mac_addr_t traf_broadcast_mac_base = {0xff,0xff,0xff,0xff,0xff,0xff};
    157 
    158 
    159 /*
    160  * Module local variables.
    161  */
    162 
    163 /* Test Structure for the CLI */
    164 STATIC traffic_test_t     *traf_test[SOC_MAX_NUM_DEVICES];
    165 
    166 
    167 /*
    168  * The order in this table should mirror traffic_mode_t
    169  */
    170 STATIC char *
    171 traffic_mode_str[] = {
    172     "MAC",
    173     "PHY",
    174     "External",
    175     /*    "ExternalUp",
    176           "ExternalDown", */
    177     NULL
    178 };
    179 
    180 /*
    181  * The order in this table should mirror traffic_speed_t
    182  */
    183 STATIC char *
    184 traffic_speed_str[] = {
    185     LB2_SPEED_INIT_STR,
    186     NULL
    187 };
    188 
    189 
    190 /* Test parameter default options */
    191 static int      dfl_speed = 0,          /* MAX */
    192                 dfl_autoneg = 1,
    193                 dfl_size = 1518,
    194                 dfl_count = 1,
    195                 dfl_poll_interval = 5,  /* seconds between polls */
    196                 dfl_runtime = 60,       /* 60/5 = 12 polls */
    197                 dfl_cleanup = 1,
    198                 dfl_showstats = 0,
    199                 dfl_run2end = 0;
    200 static pbmp_t   dfl_portbitmap;
    201 static uint32   dfl_pattern = 0xa5a4a3a2,
    202                 dfl_pattern_inc = 0;
    203 static traffic_mode_t dfl_runmode = TRAFFIC_INTERNAL_PHY;
    204 
    205 #if defined(INCLUDE_MACSEC)
    206 static int dfl_macsec = 0;
    207 #endif /* INCLUDE_MACSEC */
    208 
    209 /*
    210  * Function:
    211  *      _traffic_xgs3_test_modid_get
    212  * Purpose:
    213  *      Get a set of modids that do not conflict with my_modid
    214  * Parameters:
    215  *      unit  - SOC unit#
    216  *      port  - test port
    217  * Returns:
    218  *      module id
    219  */
    220 STATIC int
    221 _traffic_xgs3_test_modid_get(int unit, int port)
    222 {
    223     int modid;
    224 
    225     if (bcm_stk_my_modid_get(unit, &modid) < 0) {
    226         return -1;
    227     }    
    228 
    229     if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) {
    230         return (modid >= 8) ? port : port + 8;
    231     } else {
    232         return (modid >= 32) ? port : port + 32;
    233     }
    234 }
    235 
    236 #ifdef BCM_ESW_SUPPORT
    237 /*
    238  * Function:
    239  *      _traffic_xgs3_modport_set
    240  * Purpose:
    241  *      Set the port in MODPORT entry for ingress port/modid
    242  * Parameters:
    243  *      unit  - SOC unit#
    244  *      modid - module id
    245  *      portA - egress Higig port
    246  *      portB - ingress Higig port
    247  * Returns:
    248  *      BCM_E_XXX
    249  */
    250 STATIC int
    251 _traffic_xgs3_modport_set(int unit, int modid, int portA, int portB)
    252 {
    253     modport_map_entry_t uc;
    254     modport_map_sw_entry_t sw_entry;
    255     bcm_pbmp_t hg;
    256     int idx, rv;
    257     uint32 hg_reg;
    258 
    259     if (SOC_MEM_FIELD_VALID(unit, MODPORT_MAP_SWm, DEST0f)) {
    260         idx = modid;
    261         soc_mem_lock(unit, MODPORT_MAP_SWm);
    262         rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, idx,
    263                           &sw_entry);
    264         if (SOC_SUCCESS(rv)) {
    265             soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, DEST0f,
    266                                 portA);
    267             soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ENABLE0f, 1);
    268             soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, DEST1f,
    269                                 portB);
    270             soc_mem_field32_set(unit, MODPORT_MAP_SWm, &sw_entry, ENABLE1f, 1);
    271             rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, idx,
    272                                &sw_entry);
    273         }
    274         soc_mem_unlock(unit, MODPORT_MAP_SWm);
    275         return rv;
    276     }
    277 
    278     BCM_PBMP_CLEAR(hg);
    279 
    280 #ifdef BCM_RAPTOR1_SUPPORT
    281     if (SOC_IS_RAPTOR(unit)) {
    282         BCM_PBMP_PORT_SET(hg, portA-1);
    283         BCM_PBMP_PORT_ADD(hg, portB-1);
    284         LOG_ERROR(BSL_LS_APPL_TESTS,
    285                   (BSL_META_U(unit,
    286                               "portA %d portB %d\n"), portA, portB));
    287         idx = modid;
    288     } else
    289 #endif
    290     if (SOC_IS_RAVEN(unit) || SOC_IS_TRIUMPH2(unit) || 
    291                SOC_IS_APOLLO(unit) || SOC_IS_VALKYRIE2(unit)) {
    292         BCM_PBMP_PORT_SET(hg, portA);
    293         BCM_PBMP_PORT_ADD(hg, portB);
    294         LOG_ERROR(BSL_LS_APPL_TESTS,
    295                   (BSL_META_U(unit,
    296                               "portA %d portB %d\n"), portA, portB));
    297         idx = modid;
    298     } else if (SOC_IS_FB_FX_HX(unit)) {
    299         BCM_PBMP_PORT_SET(hg, portA-24);
    300         BCM_PBMP_PORT_ADD(hg, portB-24);
    301         idx = modid;
    302     } else if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit)) {
    303         BCM_PBMP_PORT_SET(hg, portA-26);
    304         BCM_PBMP_PORT_ADD(hg, portB-26);
    305         idx = modid;
    306     } else if (SOC_IS_HBX(unit)) {
    307         BCM_PBMP_PORT_SET(hg, portB);
    308         idx = (portA * (SOC_MODID_MAX(unit) + 1)) + modid;
    309     } else if (SOC_IS_TR_VL(unit)) {
    310         uint32 hg_regA, hg_regB;
    311         SOC_IF_ERROR_RETURN
    312             (soc_xgs3_port_to_higig_bitmap(unit, portA, &hg_regA));
    313         SOC_IF_ERROR_RETURN
    314             (soc_xgs3_port_to_higig_bitmap(unit, portB, &hg_regB));
    315         SOC_PBMP_WORD_SET(hg, 0, hg_regA | hg_regB);
    316         idx = modid;
    317     } else {
    318         return BCM_E_INTERNAL;
    319     }
    320 
    321     soc_mem_lock(unit, MODPORT_MAPm);
    322 
    323     rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc);
    324     if (SOC_SUCCESS(rv)) {
    325         hg_reg =  SOC_PBMP_WORD_GET(hg, 0);
    326         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
    327             SOC_IS_VALKYRIE2(unit)) {
    328             soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAP_LOf, 
    329                                          hg_reg);
    330             hg_reg = SOC_PBMP_WORD_GET(hg, 1);
    331             soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAP_HIf, 
    332                                          hg_reg);
    333         } else {
    334             soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, hg_reg);
    335         }
    336         rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, idx, &uc);
    337     }
    338 
    339     soc_mem_unlock(unit, MODPORT_MAPm);
    340 
    341     return rv;
    342 }
    343 #endif /* BCM_ESW_SUPPORT */
    344 
    345 /*
    346  * Save H/W state and setup test structure for a given unit with the
    347  * specified mode. If the test_structure is not allocated, a new one
    348  * is created and returned with the mode settings specified.
    349  */
    350 
    351 STATIC traffic_test_t *
    352 traffic_test_alloc(int unit)
    353 {
    354     int port, rv = -1;
    355     traffic_test_t *test;
    356 
    357     test = sal_alloc(sizeof(traffic_test_t), "Traffic Test config");
    358     test->port_stats = sal_alloc(SOC_MAX_NUM_PORTS *
    359                                  sizeof(traffic_port_stat_t),
    360                                  "Stats");
    361     test->port_pair = sal_alloc(SOC_MAX_NUM_PORTS *
    362                                 sizeof(traffic_port_config_t),
    363                                 "Port Config");
    364     test->port_info = sal_alloc(SOC_MAX_NUM_PORTS *
    365                                 sizeof(bcm_port_info_t),
    366                                 "Port Test Configuration");
    367     test->saved_port_info = sal_alloc(SOC_MAX_NUM_PORTS *
    368                                       sizeof(bcm_port_info_t),
    369                                       "Original Port Configuration");
    370 #ifdef BCM_ESW_SUPPORT
    371     if (SOC_MEM_FIELD_VALID(unit, MODPORT_MAP_SWm, DEST0f)) {
    372         test->saved_modport_map_sw = sal_alloc(SOC_MAX_NUM_PORTS *
    373                                                sizeof(modport_map_sw_entry_t),
    374                                                "Original Modport Map");
    375     } else {
    376         test->saved_modport_map = sal_alloc(SOC_MAX_NUM_PORTS *
    377                                             sizeof(modport_map_entry_t),
    378                                             "Original Modport Map");
    379     }
    380 #endif /* BCM_ESW_SUPPORT */
    381 
    382     test->unit = unit;
    383     test->npkts = dfl_count;
    384     test->pattern = dfl_pattern;
    385     test->pattern_inc = dfl_pattern_inc;
    386     test->ports = dfl_portbitmap;
    387     test->pkt_size = dfl_size;
    388     test->mode = dfl_runmode;
    389     test->req_speed = dfl_speed;
    390     test->stop_on_fail = TRUE;
    391     test->cleanup = dfl_cleanup;
    392     test->showstats = dfl_showstats;
    393     test->poll_interval = dfl_poll_interval;
    394     test->runtime = dfl_runtime;
    395     test->run2end = dfl_run2end;
    396 #if defined(INCLUDE_MACSEC)
    397     test->macsec_enabled = dfl_macsec;
    398     test->macsec_info = sal_alloc(sizeof(traffic_macsec_info_t),
    399                                             "macsec traffic info");
    400     test->macsec_info->num_assoc = 1;
    401 #endif /* INCLUDE_MACSEC */
    402 
    403     /* Save age timer if it's set */
    404     bcm_l2_age_timer_get(test->unit, &test->l2agetime);
    405 
    406     /* Cache original port config */
    407     PBMP_ITER(test->ports, port) {
    408         if ((rv = bcm_port_info_save(unit, port,
    409                         &test->saved_port_info[port])) < 0) {
    410             cli_out("traffic_init: port %s: could not get port info: %s\n",
    411                     SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
    412         }
    413         /* Remove L2 addresses on Switch ASIC's which support them */
    414         /* this is a no-op on fabrics */
    415         rv = bcm_l2_addr_delete_by_port(unit, -1, port, BCM_L2_DELETE_STATIC);
    416         if (rv < 0) {
    417             cli_out("traffic_test_free: ARL delete by port unsuccessful on port %s: could not set port info: %s\n",
    418                     SOC_PORT_NAME(unit, port),
    419                     bcm_errmsg(rv));
    420         }
    421 #ifdef BCM_ESW_SUPPORT
    422         /* Save modport maps used for Higig port pairs */
    423         if (IS_ST_PORT(unit, port) && SOC_IS_FBX(unit)) {
    424             int modid, idx;
    425             modid = _traffic_xgs3_test_modid_get(unit, port);
    426             if (modid < 0) {
    427                 cli_out("traffic_init: port %s: could not get modid\n",
    428                         SOC_PORT_NAME(unit, port));
    429             }
    430             if (SOC_IS_HBX(unit)) {
    431                 idx = (port * (SOC_MODID_MAX(unit) + 1)) + modid;
    432             } else {
    433                 idx = modid;
    434             }
    435             if (SOC_MEM_FIELD_VALID(unit, MODPORT_MAP_SWm, DEST0f)) {
    436                 rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, idx,
    437                                   &test->saved_modport_map_sw[port]);
    438             } else {
    439                 rv = soc_mem_read(unit, MODPORT_MAPm, MEM_BLOCK_ANY, idx,
    440                                   &test->saved_modport_map[port]);
    441             }
    442             if (rv < 0) {                                            
    443                 cli_out("traffic_init: "
    444                         "port %s: could not get modport map: %s\n",
    445                         SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
    446             }
    447         }
    448 #endif /* BCM_ESW_SUPPORT */
    449     }
    450 
    451     return test;
    452 }
    453 
    454 /*
    455  * Free Test structure, restore H/W state.
    456  */
    457 STATIC int
    458 traffic_test_free(traffic_test_t* test)
    459 {
    460     int         unit, port, rv = -1;
    461     int         ms;
    462 #if defined (BCM_ESW_SUPPORT)  
    463     uint64      tmp64;
    464 #endif
    465 
    466     if (!test) {
    467         return rv;
    468     }
    469 
    470     /*
    471      * Cleanup means shutdown switching test, we have this
    472      * option so that on a failure, you can exit the test
    473      * and use the CLI to debug.
    474      */
    475     unit = test->unit;
    476     if (test->cleanup) {
    477 
    478         if (!SAL_BOOT_QUICKTURN) {
    479 #if defined (BCM_ESW_SUPPORT)  
    480             COMPILER_64_ZERO(tmp64);
    481 #endif                    
    482             if (SOC_IS_ESW(unit)) {
    483 #ifdef BCM_ESW_SUPPORT                    
    484                 counter_val_set_by_port(unit, test->ports, tmp64);
    485 #endif
    486             } else {
    487             }
    488         }
    489 
    490         if (!SOC_IS_XGS12_FABRIC(unit)) {
    491             PBMP_ITER(test->ports, port) {
    492                 if (port != test->port_pair[port].portA) {
    493                     continue;
    494                 }
    495                 cli_out("TRAFFIC: restoring ports: %s, %s\n",
    496                         SOC_PORT_NAME(unit, test->port_pair[port].portA),
    497                         SOC_PORT_NAME(unit, test->port_pair[port].portB));
    498 
    499                 bcm_vlan_destroy(unit, test->port_pair[port].vidA);
    500                 bcm_vlan_destroy(unit, test->port_pair[port].vidB);
    501 
    502                 /* Very Important: clear EPCLINKr to halt traffic */
    503                 bcm_port_stp_set(unit, test->port_pair[port].portA,
    504                                  BCM_STG_STP_DISABLE);
    505                 bcm_port_stp_set(unit, test->port_pair[port].portB,
    506                                  BCM_STG_STP_DISABLE);
    507             }
    508             bcm_vlan_port_add(unit, VLAN_ID_DEFAULT, test->ports, test->ports);
    509         }
    510 
    511         PBMP_ITER(test->ports, port) {
    512             /* If port is FE port, remove phy_master attributes controlled by it */
    513             if(IS_FE_PORT(unit, port)) {
    514               test->saved_port_info[port].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
    515             }
    516             /* If the Master mode is not changed, remove phy_master attributes from action_mask */
    517             ms = 0;
    518             if ((rv = bcm_port_master_get(unit, port, &ms)) != BCM_E_NONE) {
    519                 cli_out("traffic_test_free: port %s: could not get port Master mode: %s\n",
    520                         SOC_PORT_NAME(unit, port),
    521                         bcm_errmsg(rv));
    522                 goto done;
    523             }
    524             if (ms == test->saved_port_info[port].phy_master) {
    525                test->saved_port_info[port].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
    526             }
    527 
    528             if ((rv = bcm_port_info_restore(unit, port,
    529                                         &test->saved_port_info[port])) < 0) {
    530                 cli_out("traffic_test_free: port %s: could not set port info: %s\n",
    531                         SOC_PORT_NAME(unit, port),
    532                         bcm_errmsg(rv));
    533                 goto done;
    534             }
    535             rv = bcm_l2_addr_delete_by_port(unit, -1, port,
    536                                             BCM_L2_DELETE_STATIC);
    537             if (rv < 0) {
    538                 cli_out("traffic_test_free: ARL delete by port unsuccessful on port %s: could not set port info: %s\n",
    539                         SOC_PORT_NAME(unit, port),
    540                         bcm_errmsg(rv));
    541                 goto done;
    542             }
    543 
    544 #ifdef BCM_ESW_SUPPORT
    545             /* Restore modport maps used for Higig port pairs */
    546             if (IS_ST_PORT(unit, port) && SOC_IS_FBX(unit)) {
    547                 int modid, idx;
    548                 modid = _traffic_xgs3_test_modid_get(unit, port);
    549                 if (modid < 0) {
    550                     cli_out("traffic_test_free: port %s: could not get modid\n",
    551                             SOC_PORT_NAME(unit, port));
    552                     goto done;
    553                 }
    554                 if (SOC_IS_HBX(unit) || SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) {
    555                     idx = (port * (SOC_MODID_MAX(unit) + 1)) + modid;
    556                 } else {
    557                     idx = modid;
    558                 }
    559                 if (SOC_MEM_FIELD_VALID(unit, MODPORT_MAP_SWm, DEST0f)) {
    560                     rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY,
    561                                        idx, &test->saved_modport_map_sw[port]);
    562                 } else {
    563                     rv = soc_mem_write(unit, MODPORT_MAPm, MEM_BLOCK_ANY, idx, 
    564                                        &test->saved_modport_map[port]);
    565                 }
    566                 if (rv  < 0) {
    567                     cli_out("traffic_test_free: "
    568                             "port %s: could not set modport map: %s\n",
    569                             SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
    570                 }
    571             }
    572 #endif /* BCM_ESW_SUPPORT */
    573         }
    574 
    575         /* Restore l2 age time */
    576         bcm_l2_age_timer_set(unit, test->l2agetime);
    577     }
    578  done:
    579     sal_free(test->port_stats);
    580     sal_free(test->port_pair);
    581     sal_free(test->port_info);
    582     sal_free(test->saved_port_info);
    583 #ifdef BCM_ESW_SUPPORT
    584     if (SOC_MEM_FIELD_VALID(unit, MODPORT_MAP_SWm, DEST0f)) {
    585         sal_free(test->saved_modport_map_sw);
    586     } else {
    587         sal_free(test->saved_modport_map);
    588     }
    589 #endif /* BCM_ESW_SUPPORT */
    590     return 0;
    591 }
    592 
    593 /*
    594  * Send frames to destination port pair index. Each port is a
    595  * transmitter and receiver. Packets are sent in external mode
    596  * such that  DA=00:00:00:00:fe:x where x=portA, and
    597  * SA=00:00:00:00:00:portB; in internal test mode, packets
    598  * are sent with SA=00:00:00:00:00:01,  and DA=broadcast address
    599  */
    600 int
    601 traffic_test_send_frames(traffic_test_t* test, int port_pair_index)
    602 {
    603     int rv = BCM_E_NONE;
    604     int unit = test->unit;
    605     traffic_port_config_t *config = &test->port_pair[port_pair_index];
    606     int portA = config->portA;
    607     int portB = config->portB;
    608     int mode = test->mode;
    609     int pad;
    610     int i;
    611 
    612     bcm_pkt_t *pktA;
    613     void *bufA;
    614     enet_hdr_t *ehdrA;
    615     int sizeA;
    616 
    617     bcm_pkt_t *pktB;
    618     void *bufB;
    619     enet_hdr_t *ehdrB;
    620     int sizeB;
    621 
    622     pad = sizeof(uint32); /* Add size of CRC .. */
    623 
    624     bcm_pkt_alloc(unit, test->pkt_size + pad, 0, &pktA);
    625     bcm_pkt_alloc(unit, test->pkt_size + pad, 0, &pktB);
    626 
    627     if (pktA == NULL || pktB == NULL) {
    628         cli_out("Error initializing packet buffers\n");
    629         goto error;
    630     }
    631 
    632     bufA = pktA->_pkt_data.data;
    633     bufB = pktB->_pkt_data.data;
    634 
    635     /* Set packet buffer */
    636     ehdrA = (enet_hdr_t*)bufA;
    637     ehdrB = (enet_hdr_t*)bufB;
    638 
    639     pktA->flags = BCM_TX_CRC_APPEND;
    640     pktB->flags = BCM_TX_CRC_APPEND;
    641 #ifdef BCM_XGS12_FABRIC_SUPPORT
    642     if (SOC_IS_XGS12_FABRIC(unit)) {
    643         pktA->dest_port = portB;
    644         pktA->opcode = BCM_HG_OPCODE_UC;
    645         pktB->dest_port = portA;
    646         pktB->opcode = BCM_HG_OPCODE_UC;
    647     }
    648 #endif
    649     if (SOC_IS_XGS3_SWITCH(unit)) {
    650 
    651         if (IS_ST_PORT(unit, portA) || IS_ST_PORT(unit, portB)) {
    652             int modid = _traffic_xgs3_test_modid_get(unit, portA);
    653             if (modid < 0) {
    654                 cli_out("ERROR: port %s: could not get modid\n",
    655                         SOC_PORT_NAME(unit, portA));
    656                 goto error;
    657             }
    658             pktA->dest_port = portB;
    659             pktA->opcode = BCM_HG_OPCODE_UC;
    660             pktA->src_mod = modid + 1;
    661             pktA->flags |= BCM_TX_SRC_MOD;
    662             pktA->dest_mod = modid;
    663             pktB->dest_port = portA;
    664             pktB->opcode = BCM_HG_OPCODE_UC;
    665             pktB->src_mod = modid + 1;
    666             pktB->flags |= BCM_TX_SRC_MOD;
    667             pktB->dest_mod = modid;
    668         }
    669     }
    670     test->pattern = packet_store((uint8*)ehdrA, test->pkt_size,
    671                                  test->pattern, test->pattern_inc);
    672 
    673     /* Strata Internal MAC, PHY, or XGS/Fabric packets */
    674     if (SOC_IS_XGS12_FABRIC(unit) ||
    675         (mode == TRAFFIC_INTERNAL) ||
    676         (mode == TRAFFIC_INTERNAL_PHY)) {
    677 
    678         /* PortA packet */
    679         ENET_COPY_MACADDR(traf_broadcast_mac_base, &ehdrA->en_dhost);
    680         ENET_COPY_MACADDR(traf_unicast_mac_base,   &ehdrA->en_shost);
    681         if (!SOC_IS_XGS12_FABRIC(unit)) {
    682             ehdrA->en_tag_ctrl = soc_htons(VLAN_CTRL(0, 0, config->vidA));
    683             ehdrA->en_tag_tpid = soc_htons(ENET_DEFAULT_TPID );
    684         }
    685         ehdrA->en_tag_len  = soc_htons(test->pkt_size) - 18;
    686 
    687         sizeA = test->pkt_size;
    688         BCM_PKT_PORT_SET(pktA, portA, TRUE, FALSE);
    689         BCM_PKT_TX_LEN_SET(pktA, sizeA);
    690 
    691         /* Port B packet */
    692         ENET_COPY_MACADDR(traf_broadcast_mac_base, &ehdrB->en_dhost);
    693         ENET_COPY_MACADDR(traf_unicast_mac_base,   &ehdrB->en_shost);
    694         if (!SOC_IS_XGS12_FABRIC(unit)) {
    695             ehdrB->en_tag_ctrl = soc_htons(VLAN_CTRL(0, 0, config->vidB));
    696             ehdrB->en_tag_tpid = soc_htons(ENET_DEFAULT_TPID );
    697         }
    698         ehdrB->en_tag_len  = soc_htons(test->pkt_size) - 18;
    699 
    700         sizeB = test->pkt_size;
    701         BCM_PKT_PORT_SET(pktB, portB, TRUE, FALSE);
    702         BCM_PKT_TX_LEN_SET(pktB, sizeB);
    703     } else { /* External && !Fabric */
    704         /* PortA packet */
    705         ENET_COPY_MACADDR(&config->l2B.mac, &ehdrA->en_dhost);
    706         ENET_COPY_MACADDR(&config->l2A.mac, &ehdrA->en_shost);
    707         ehdrA->en_tag_ctrl = soc_htons(VLAN_CTRL(0, 0, config->vidA));
    708         ehdrA->en_tag_tpid = soc_htons(ENET_DEFAULT_TPID );
    709         ehdrA->en_tag_len  = soc_htons(test->pkt_size) - 18;
    710 
    711         sizeA = test->pkt_size;
    712         BCM_PKT_PORT_SET(pktA, portB, TRUE, FALSE);
    713         BCM_PKT_TX_LEN_SET(pktA, sizeA);
    714 
    715         /* Port B packet */
    716         ENET_COPY_MACADDR(&config->l2A.mac, &ehdrB->en_dhost);
    717         ENET_COPY_MACADDR(&config->l2B.mac, &ehdrB->en_shost);
    718         ehdrB->en_tag_ctrl = soc_htons(VLAN_CTRL(0, 0, config->vidB));
    719         ehdrB->en_tag_tpid = soc_htons(ENET_DEFAULT_TPID );
    720         ehdrB->en_tag_len  = soc_htons(test->pkt_size) - 18;
    721 
    722         sizeB = test->pkt_size;
    723         BCM_PKT_PORT_SET(pktB, portA, TRUE, FALSE);
    724         BCM_PKT_TX_LEN_SET(pktB, sizeB);
    725     }
    726 
    727     for (i=0; i < test->npkts; i++) {
    728         rv = bcm_tx(unit, pktA, NULL);
    729         if (rv < 0) {
    730             cli_out("ERROR: port %s: bcm_tx A #%d failed: %s\n",
    731                     SOC_PORT_NAME(unit, portB), i, bcm_errmsg(rv));
    732             goto error;
    733         }
    734 
    735         rv = bcm_tx(unit, pktB, NULL);
    736         if (rv < 0) {
    737             cli_out("ERROR: port %s: bcm_tx B #%d failed: %s\n",
    738                     SOC_PORT_NAME(unit, portA), i, bcm_errmsg(rv));
    739             goto error;
    740         }
    741     }
    742 
    743  error:
    744     if (pktA != NULL) {
    745         bcm_pkt_free(unit, pktA);
    746     }
    747     if (pktB != NULL) {
    748         bcm_pkt_free(unit, pktB);
    749     }
    750 
    751     return BCM_E_NONE;
    752 }
    753 
    754 #if defined(INCLUDE_MACSEC)
    755 typedef struct traffic_macsec_user_data_s {
    756     int                 unit;
    757     bcm_port_t          match_port;
    758     bcm_macsec_core_t   dev_core;
    759     int                 dev_port;
    760     int                 found;
    761     pbmp_t              pbm;
    762     traffic_test_t     *test;
    763 } traffic_macsec_user_data_t;
    764 
    765 static int _traffic_macsec_port_iter_cb(int unit, 
    766                                         bcm_port_t port, 
    767                                         bcm_macsec_core_t dev_core, 
    768                                         bcm_macsec_dev_addr_t dev_addr, 
    769                                         int dev_port, 
    770                                         bcm_macsec_dev_io_t devio_f, 
    771                                         void *user_data)
    772 {
    773     traffic_macsec_user_data_t *mdata = (traffic_macsec_user_data_t*) user_data;
    774 
    775     if ((mdata->unit == unit) && (mdata->match_port == port)) {
    776          mdata->found = 1;
    777          mdata->dev_port = dev_port;
    778          mdata->dev_core = dev_core;
    779     }
    780     return 0;
    781 }
    782 
    783 static int _traffic_port_is_macsec_capable(int unit, bcm_port_t port)
    784 {
    785     traffic_macsec_user_data_t mdata;
    786 
    787     mdata.found = 0;
    788     mdata.unit = unit;
    789     mdata.match_port = port;
    790     
    791     bcm_macsec_port_traverse(unit, _traffic_macsec_port_iter_cb, (void*) &mdata);
    792     return (mdata.found) ? 1 : 0;
    793 }
    794 
    795 static int
    796 _traffic_alloc_crypto_key(int unit, int port, int ofst, unsigned char *key)
    797 {
    798     int ii;
    799 
    800     key[0] = unit;
    801     key[1] = port;
    802     key[2] = (ofst >> 8) & 0xff;
    803     key[3] = ofst & 0xff;
    804     for (ii = 4; ii < 16; ii++) {
    805         key[ii] = ii;
    806     }
    807     return 0;
    808 }
    809 
    810 static int _traffic_setup_new_key(int unit, bcm_port_t port, 
    811                               bcm_port_t portB, traffic_test_t *test)
    812 {
    813     int symmetric, an, peer_port, rxchanId, txchanId;
    814     int old_rx_assocId = -1, old_tx_assocId = -1, new_an, rv = BCM_E_NONE;
    815     bcm_macsec_secure_assoc_t assoc;
    816 
    817     symmetric = ((test->mode == TRAFFIC_INTERNAL_PHY) ||
    818                  (test->mode == TRAFFIC_INTERNAL)) ? 1 : 0;
    819 
    820     if (symmetric) {
    821         peer_port = port;
    822     } else {
    823         peer_port = portB;
    824     }
    825     if (peer_port >= SOC_MAX_NUM_PORTS) {
    826         cli_out("peer_port num %d too large \n", peer_port );
    827         return BCM_E_PORT;
    828     }
    829     if (port >= SOC_MAX_NUM_PORTS) {
    830         cli_out("port num %d too large \n", port );
    831         return BCM_E_PORT;
    832     }
    833 
    834     an = test->macsec_info->ports[port].cur_an;
    835     if (an >= 0) {
    836         old_tx_assocId = 
    837                 test->macsec_info->ports[port].tx_keys[an].assocId;
    838         old_rx_assocId = 
    839                 test->macsec_info->ports[peer_port].rx_keys[an].assocId;
    840     }
    841 
    842     new_an = (an + 1) & 3;
    843 
    844     test->macsec_info->ports[port].cur_an = new_an;
    845 
    846     /* Update RX */
    847     sal_memset(&assoc, 0, sizeof(bcm_macsec_secure_assoc_t));
    848     assoc.an = new_an;
    849     assoc.crypto = BCM_MACSEC_CRYPTO_AES_128_GCM;
    850     assoc.flags = BCM_MACSEC_ASSOC_ACTIVE;
    851 
    852     /* setup TX crypto key */
    853     _traffic_alloc_crypto_key(unit, port, 
    854                               test->macsec_info->ports[port].num_alloc++,
    855                               assoc.aes128_gcm.key);
    856 
    857     /* store the key */
    858     sal_memcpy(test->macsec_info->ports[port].tx_keys[new_an].crypto_key,
    859                assoc.aes128_gcm.key, 16);
    860 
    861     rxchanId = test->macsec_info->ports[peer_port].rx_chanId;
    862 
    863     /* create RX assoc */
    864     rv = bcm_macsec_secure_assoc_create(unit, peer_port, 0, rxchanId, &assoc, 
    865                  &test->macsec_info->ports[peer_port].rx_keys[new_an].assocId);
    866     if (rv < 0) {
    867         cli_out("Failed to create RX secure association \n");
    868         return BCM_E_PORT;
    869     }
    870 
    871     sal_memset(&assoc, 0, sizeof(bcm_macsec_secure_assoc_t));
    872     assoc.an = new_an;
    873     assoc.flags = BCM_MACSEC_ASSOC_ACTIVE;
    874     assoc.crypto = BCM_MACSEC_CRYPTO_AES_128_GCM;
    875     sal_memcpy(assoc.aes128_gcm.key,
    876                test->macsec_info->ports[port].tx_keys[new_an].crypto_key, 16);
    877 
    878     /* switch over now */
    879     txchanId = test->macsec_info->ports[port].tx_chanId;
    880     rv = bcm_macsec_secure_assoc_create(unit, port, 0, txchanId, &assoc, 
    881                             &test->macsec_info->ports[port].tx_keys[new_an].assocId);
    882     if (rv < 0) {
    883         cli_out("Failed to create TX secure association \n");
    884         return BCM_E_PORT;
    885     }
    886     test->macsec_info->ports[port].cur_an = new_an;
    887 
    888     if (old_tx_assocId >= 0) {
    889         bcm_macsec_secure_assoc_destroy(unit, port, old_tx_assocId);
    890     }
    891 
    892     if (old_rx_assocId >= 0) {
    893         bcm_macsec_secure_assoc_destroy(unit, port, old_rx_assocId);
    894     }
    895 
    896     cli_out("Key updated (p=%s) \n", SOC_PORT_NAME(unit, port));
    897     return BCM_E_NONE;
    898 }
    899 
    900 static int _macsec_calc_assoc_life(int speedM, uint32 availPkt, int before)
    901 {
    902     uint32 time_ms;
    903 
    904     /* calculate worst cast life of assoc */
    905     /*
    906     time_ms = (availPkt ) / (speedM * 1000);
    907     time_ms *=  64 * 8;
    908     */
    909 
    910     switch (speedM) {
    911         case 10:
    912             time_ms = availPkt / 20;
    913             break;
    914         case 100:
    915             time_ms = availPkt / 195;
    916             break;
    917         case 1000:
    918             time_ms = availPkt / 1953;
    919             break;
    920         case 10000:
    921         default:
    922             time_ms = availPkt / 19531;
    923             break;
    924     }
    925 
    926     return (time_ms <= before) ? 0 : (time_ms - before);
    927 }
    928 
    929 static void
    930 _macsec_poll_thread(void *data)
    931 {
    932     traffic_macsec_user_data_t  *mdata = (traffic_macsec_user_data_t*) data;
    933     traffic_test_t  *test;
    934     pbmp_t      pbm;
    935     int         unit, cur_an, rv;
    936     bcm_port_t  port, peer_port;
    937     int         poll_interval, total_time = 0;
    938     int         wake_time_ms;
    939     unsigned int    avail_pkt;
    940     int symmetric, rxchanId, txchanId;
    941     bcm_macsec_port_config_t config;
    942     
    943 
    944     /* setup macsec PBMP and */
    945     test = mdata->test;
    946     pbm  = test->macsec_info->macsec_pbm;
    947     unit = mdata->unit;
    948 
    949     if (SOC_PBMP_IS_NULL(pbm)) {
    950         return;
    951     }
    952 
    953     while (macsec_stop_poll_task == 0) {
    954         wake_time_ms = 10000;
    955         PBMP_ITER(pbm, port) {
    956             cur_an = test->macsec_info->ports[port].cur_an;
    957             /* Get the availPkt count for the assoc */
    958             rv = bcm_macsec_stat_get32(unit, port, bcm_txSAavailablePkts, -1,
    959                         test->macsec_info->ports[port].tx_keys[cur_an].assocId,
    960                         &avail_pkt);
    961             if (rv < 0) {
    962                 continue;
    963             }
    964             poll_interval = _macsec_calc_assoc_life(test->port_info[port].speed,
    965                                                     avail_pkt, 10000);
    966             if (poll_interval == 0) {
    967                 peer_port = test->port_pair[port].portB;
    968                 /* Update the keys */
    969                 _traffic_setup_new_key(unit, port, peer_port, test);
    970                 continue;
    971             }
    972             if (wake_time_ms > poll_interval) {
    973                 wake_time_ms = poll_interval;
    974             }
    975         }
    976         sal_usleep(wake_time_ms * 1000);
    977         total_time += wake_time_ms;
    978     }
    979 
    980     symmetric = ((test->mode == TRAFFIC_INTERNAL_PHY) ||
    981                  (test->mode == TRAFFIC_INTERNAL)) ? 1 : 0;
    982 
    983     if (test->cleanup) {
    984         PBMP_ITER(pbm, port) {
    985             if (symmetric) {
    986                 peer_port = port;
    987             } else {
    988                 peer_port = test->port_pair[port].portB;
    989             }
    990             if (peer_port >= SOC_MAX_NUM_PORTS) {
    991                 cli_out("peer_port num %d  >=  %d : MACSEC clean failed\n", 
    992                         peer_port, SOC_MAX_NUM_PORTS);
    993                         
    994                 continue;
    995             }
    996             txchanId = test->macsec_info->ports[port].tx_chanId;
    997             if (txchanId >= 0) {
    998                 bcm_macsec_secure_chan_destroy(unit, port, txchanId);
    999             }
   1000             rxchanId = test->macsec_info->ports[peer_port].rx_chanId;
   1001             if (rxchanId >= 0) {
   1002                 bcm_macsec_secure_chan_destroy(unit, peer_port, rxchanId);
   1003             }
   1004 
   1005             if (bcm_macsec_port_config_get(unit, port, &config) < 0) {
   1006                 cli_out("Port %s MACSEC clean failed\n", 
   1007                         SOC_PORT_NAME(unit, port));
   1008                 continue;
   1009             }
   1010 
   1011             config.flags &= ~BCM_MACSEC_PORT_ENABLE;
   1012             if (bcm_macsec_port_config_set(unit, port, &config) < 0) {
   1013                 cli_out("Port %s MACSEC clean failed\n", 
   1014                         SOC_PORT_NAME(unit, port));
   1015                 continue;
   1016             }
   1017         }
   1018     }
   1019 
   1020     cli_out("MACSEC Poll task exiting ...\n");
   1021     return;
   1022 }
   1023 
   1024 static int 
   1025 _traffic_setup_macsec_poll_task(int unit, traffic_test_t* test)
   1026 {
   1027     traffic_macsec_user_data_t  mdata;
   1028 
   1029     if (!test->macsec_enabled) {
   1030         return 0;
   1031     }
   1032 
   1033     macsec_stop_poll_task = 0;
   1034 
   1035     /* fill up data for poller task */
   1036     mdata.unit = unit;
   1037     mdata.test = test;
   1038 
   1039     /* Start task to renew the key when secure assoc expires */
   1040     if (sal_thread_create("macsec_sa_poller",
   1041                           SAL_THREAD_STKSZ, 100,
   1042                           (void (*)(void*))_macsec_poll_thread,
   1043                               (void*) &mdata) == SAL_THREAD_ERROR) {
   1044         return BCM_E_MEMORY;
   1045     }
   1046     return 0;
   1047 }   
   1048 
   1049 static int 
   1050 _traffic_setup_macsec(int unit, bcm_port_t portA, 
   1051                                  bcm_port_t portB, traffic_test_t* test)
   1052 {
   1053     bcm_port_t  port, alt_port, peer_port;
   1054     bcm_macsec_port_config_t config;
   1055     bcm_macsec_secure_chan_t    chan;
   1056     int         txchanId, rxchanId;
   1057     int         symmetric, ii, flowId, jj;
   1058     bcm_macsec_flow_match_t flow;
   1059     bcm_macsec_flow_action_t action;
   1060 
   1061     symmetric = ((test->mode == TRAFFIC_INTERNAL_PHY) ||
   1062                  (test->mode == TRAFFIC_INTERNAL)) ? 1 : 0;
   1063 
   1064     /* Setup MACSEC flows and keys */
   1065     if ((test->macsec_enabled == 0) ||
   1066         ((symmetric == 0) &&
   1067          (!_traffic_port_is_macsec_capable(unit, portA) ||
   1068           !_traffic_port_is_macsec_capable(unit, portB)))) {
   1069         return 0; /* Not macsec capable, nothing to do. */
   1070     }
   1071 
   1072     for (ii = 0; ii < 2; ii++) {
   1073         port = (ii == 0) ? portA : portB;
   1074         alt_port = (ii == 0) ? portB : portA;
   1075         peer_port = (symmetric) ? port : alt_port;
   1076 
   1077         if (!_traffic_port_is_macsec_capable(unit, port)) {
   1078             continue;
   1079         }
   1080 
   1081         /* Enable controlled port */
   1082         if (bcm_macsec_port_config_get(unit, port, &config) < 0) {
   1083             return BCM_E_PORT;
   1084         }
   1085 
   1086         config.flags = BCM_MACSEC_PORT_ENABLE;
   1087         config.max_frame = 1518 + 32;
   1088         for (jj = 0; jj < BCM_MACSEC_PACKET_FORMAT__COUNT; jj++) {
   1089             config.egress_flow_match_set[jj] = BCM_MACSEC_FLOW_MATCH_MACSA;
   1090         }
   1091         if (bcm_macsec_port_config_set(unit, port, &config) < 0) {
   1092             return BCM_E_PORT;
   1093         }
   1094 
   1095         /* Create TX and RX channels */
   1096         sal_memset(&chan, 0, sizeof(chan));
   1097         chan.flags = BCM_MACSEC_SECURE_CONFIDENTIAL | 
   1098                      BCM_MACSEC_SECURE_SECTAG_TX_SCI;
   1099         sal_memset(chan.sci, 0x33, 8);
   1100         if (bcm_macsec_secure_chan_create(unit, port, 0, &chan, &txchanId) < 0) {
   1101             return BCM_E_PORT;
   1102         }
   1103 
   1104         test->macsec_info->ports[port].tx_chanId = txchanId;
   1105 
   1106         /* setup rx channel */
   1107         sal_memset(&chan, 0, sizeof(chan));
   1108         chan.flags = BCM_MACSEC_SECURE_CONFIDENTIAL | 
   1109                                             BCM_MACSEC_SECURE_CHAN_INGRESS;
   1110         sal_memset(chan.sci, 0x33, 8);
   1111         if (bcm_macsec_secure_chan_create(unit, peer_port, 
   1112                                                 0, &chan, &rxchanId) < 0) {
   1113             return BCM_E_PORT;
   1114         }
   1115 
   1116         test->macsec_info->ports[peer_port].rx_chanId = rxchanId;
   1117 
   1118         /* setup egress flows */
   1119         sal_memset(&flow, 0, sizeof(flow));
   1120         flow.flags = 0;
   1121         flow.direction = BCM_MACSEC_DIR_EGRESS;
   1122         flow.pkt_format = BCM_MACSEC_PACKET_FORMAT_802_3;
   1123 
   1124         sal_memset(&action, 0, sizeof(action));
   1125         action.flags = BCM_MACSEC_FLOW_ACTION_CONTROLLED_FORWARD;
   1126 
   1127         if (bcm_macsec_flow_create(unit, port, 0, &flow, &action, &flowId) < 0) {
   1128             return BCM_E_PORT;
   1129         }
   1130     
   1131         BCM_PBMP_PORT_ADD(test->macsec_info->macsec_pbm, port);
   1132 
   1133         test->macsec_info->ports[port].cur_an = -1;
   1134 
   1135         _traffic_setup_new_key(unit, port, alt_port, test);
   1136     }
   1137 
   1138     return BCM_E_NONE;
   1139 }
   1140 
   1141 #endif /* INCLUDE_MACSEC */
   1142 
   1143 /*
   1144  * Setup an l2 entry with specified address on
   1145  * the given port.
   1146  */
   1147 int
   1148 traffic_test_setup_l2addr(int unit, bcm_l2_addr_t* l2addr, int vid, int port)
   1149 {
   1150     int rv = BCM_E_NONE;
   1151 #ifdef BCM_TRIUMPH_SUPPORT
   1152     int ext_index_max = -1;
   1153 #endif /* BCM_TRIUMPH_SUPPORT */
   1154 
   1155     traf_unicast_mac_base[5] = port;
   1156     bcm_l2_addr_t_init(l2addr, traf_unicast_mac_base, vid);
   1157 
   1158     l2addr->flags = BCM_L2_STATIC;
   1159     l2addr->port = port;
   1160     if ((rv = bcm_stk_my_modid_get(unit, &l2addr->modid)) < 0) {
   1161         cli_out("ERROR: could not get modid: %s\n", bcm_errmsg(rv));
   1162         return rv;
   1163     }
   1164     if (SOC_PORT_MOD1(unit, port)) {
   1165         l2addr->modid += 1;
   1166     }
   1167 
   1168 #ifdef BCM_TRIUMPH_SUPPORT
   1169     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   1170         ext_index_max = SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
   1171         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
   1172     }
   1173 #endif /* BCM_TRIUMPH_SUPPORT */
   1174 
   1175     if ((rv = bcm_l2_addr_add(unit, l2addr)) < 0) {
   1176         cli_out("ERROR: l2 entry add failed: "
   1177                 "port %s, mac %2x:%2x:%2x:%2x:%2x:%2x vlan %d: %s\n",
   1178                 SOC_PORT_NAME(unit, port),
   1179                 traf_unicast_mac_base[0],
   1180                 traf_unicast_mac_base[1],
   1181                 traf_unicast_mac_base[2],
   1182                 traf_unicast_mac_base[3],
   1183                 traf_unicast_mac_base[4],
   1184                 traf_unicast_mac_base[5],
   1185                 vid,
   1186                 bcm_errmsg(rv));
   1187     }
   1188 #ifdef BCM_TRIUMPH_SUPPORT
   1189     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   1190         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = ext_index_max;
   1191     }
   1192 #endif /* BCM_TRIUMPH_SUPPORT */
   1193     return rv;
   1194 }
   1195 
   1196 int
   1197 traffic_test_setup_maxframe(traffic_test_t *test)
   1198 {
   1199     pbmp_t          pbm;
   1200     int             unit, max_pkt;
   1201     soc_port_t      port;
   1202 
   1203     unit = test->unit;
   1204 
   1205     BCM_PBMP_ASSIGN(pbm, PBMP_E_ALL(unit));
   1206     BCM_PBMP_AND(pbm, test->ports);
   1207     BCM_PBMP_ITER(pbm, port) {
   1208         BCM_IF_ERROR_RETURN
   1209             (bcm_port_frame_max_get(unit, port, &max_pkt));
   1210         if (max_pkt < test->pkt_size) {
   1211             BCM_IF_ERROR_RETURN
   1212                 (bcm_port_frame_max_set(unit, port, test->pkt_size));
   1213         }
   1214     }
   1215 
   1216     return BCM_E_NONE;
   1217 }
   1218 
   1219 /*
   1220  * Setup forwarding to occur between port pairs.
   1221  */
   1222 int
   1223 traffic_test_setup_port_pair(traffic_test_t* test, int port_pair_index,
   1224                              traffic_mode_t mode, traffic_speed_t speed)
   1225 {
   1226     int                 unit = test->unit;
   1227     traffic_port_config_t       *config = &test->port_pair[port_pair_index];
   1228     bcm_port_info_t     *infoA = &test->port_info[config->portA];
   1229     bcm_port_info_t     *infoB = &test->port_info[config->portB];
   1230     int                 portA = config->portA;
   1231     int                 portB = config->portB;
   1232     int                 rv;
   1233     int                 ms;
   1234     pbmp_t              port_pbm;
   1235     bcm_port_resource_t portResrc;
   1236 
   1237     if (SOC_IS_XGS3_SWITCH(unit)) {
   1238         if (IS_ST_PORT(unit, portA) || IS_ST_PORT(unit, portB)) {
   1239             if (!(IS_ST_PORT(unit, portA) && IS_ST_PORT(unit, portB))) {
   1240                 cli_out("ERROR: ports %s, %s: "
   1241                         "Higig port must be paired with Higig port\n",
   1242                         SOC_PORT_NAME(unit, portA),
   1243                         SOC_PORT_NAME(unit, portB));
   1244                 return -1;
   1245             }
   1246         }
   1247     }
   1248 
   1249     /* Setup Ports */
   1250     if (bcm_port_info_save(unit, portA, infoA) < 0) {
   1251         cli_out("ERROR: traffic setup unit %d, ports %s, %s: "
   1252                 "%s info save failed\n",
   1253                 unit,
   1254                 SOC_PORT_NAME(unit, portA),
   1255                 SOC_PORT_NAME(unit, portB),
   1256                 SOC_PORT_NAME(unit, portA));
   1257         return -1;
   1258     }
   1259     if (bcm_port_info_save(unit, portB, infoB) < 0) {
   1260         cli_out("ERROR: traffic setup unit %d, ports %s, %s: "
   1261                 "%s info save failed\n",
   1262                 unit,
   1263                 SOC_PORT_NAME(unit, portA),
   1264                 SOC_PORT_NAME(unit, portB),
   1265                 SOC_PORT_NAME(unit, portB));
   1266         return -1;
   1267     }
   1268 
   1269     /* Get port ability  */
   1270     if (!IS_CD_PORT(unit, portA)) {
   1271         if (bcm_port_ability_local_get(unit, portA, &infoA->port_ability) < 0) {
   1272                     cli_out("ERROR: traffic setup unit %d, ports %s: "
   1273                             "ability get failed\n",
   1274                             unit, SOC_PORT_NAME(unit, portA));
   1275                     return -1;
   1276         }
   1277     }
   1278     if (!IS_CD_PORT(unit, portB)) {
   1279         if (bcm_port_ability_local_get(unit, portB, &infoB->port_ability) < 0) {
   1280                     cli_out("ERROR: traffic setup unit %d, ports %s: "
   1281                             "ability get failed\n",
   1282                             unit, SOC_PORT_NAME(unit, portB));
   1283                     return -1;
   1284         }
   1285     }
   1286     switch (speed) {
   1287     case SPEED_10:
   1288         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_10MB) && 
   1289             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_10MB)) {
   1290             infoA->duplex = TRUE;
   1291             infoB->duplex = TRUE;
   1292             infoA->local_ability.speed_full_duplex =
   1293                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_10MB;
   1294             infoA->local_ability.speed_half_duplex =
   1295                 infoB->local_ability.speed_half_duplex = 0;
   1296         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_10MB) && 
   1297                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_10MB)) {
   1298             infoA->duplex = FALSE;
   1299             infoB->duplex = FALSE;
   1300             infoA->local_ability.speed_full_duplex =
   1301                 infoB->local_ability.speed_full_duplex = 0;
   1302             infoA->local_ability.speed_half_duplex =
   1303                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_10MB;
   1304         } else {
   1305             LOG_ERROR(BSL_LS_APPL_TESTS,
   1306                       (BSL_META_U(unit,
   1307                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1308                        unit, SOC_PORT_NAME(unit, portA),
   1309                        SOC_PORT_NAME(unit, portB)));
   1310             speed = SPEED_MAX;
   1311         }
   1312         infoA->speed = infoB->speed = 10;
   1313         break;
   1314 
   1315     case SPEED_100:
   1316         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_100MB) && 
   1317             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_100MB)) {
   1318             infoA->duplex = TRUE;
   1319             infoB->duplex = TRUE;
   1320             infoA->local_ability.speed_full_duplex =
   1321                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_100MB;
   1322             infoA->local_ability.speed_half_duplex =
   1323                 infoB->local_ability.speed_half_duplex = 0;
   1324         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_100MB) && 
   1325                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_100MB)) {
   1326             infoA->duplex = FALSE;
   1327             infoB->duplex = FALSE;
   1328             infoA->local_ability.speed_full_duplex =
   1329                 infoB->local_ability.speed_full_duplex = 0;
   1330             infoA->local_ability.speed_half_duplex =
   1331                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_100MB;
   1332         } else {
   1333             LOG_ERROR(BSL_LS_APPL_TESTS,
   1334                       (BSL_META_U(unit,
   1335                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1336                        unit, SOC_PORT_NAME(unit, portA),
   1337                        SOC_PORT_NAME(unit, portB)));
   1338             speed = SPEED_MAX;
   1339         } 
   1340         infoA->speed = infoB->speed = 100;
   1341         break;
   1342 
   1343     case SPEED_1GIG:
   1344         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_1000MB) && 
   1345             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_1000MB)) {
   1346             infoA->duplex = TRUE;
   1347             infoB->duplex = TRUE;
   1348             infoA->local_ability.speed_full_duplex =
   1349                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_1000MB;
   1350             infoA->local_ability.speed_half_duplex =
   1351                 infoB->local_ability.speed_half_duplex = 0;
   1352         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_1000MB) && 
   1353                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_1000MB)) {
   1354             infoA->duplex = FALSE;
   1355             infoB->duplex = FALSE;
   1356             infoA->local_ability.speed_full_duplex =
   1357                 infoB->local_ability.speed_full_duplex = 0;
   1358             infoA->local_ability.speed_half_duplex =
   1359                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_1000MB;
   1360         } else {
   1361             LOG_ERROR(BSL_LS_APPL_TESTS,
   1362                       (BSL_META_U(unit,
   1363                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1364                        unit, SOC_PORT_NAME(unit, portA),
   1365                        SOC_PORT_NAME(unit, portB)));
   1366             speed = SPEED_MAX;
   1367         }
   1368         infoA->speed = infoB->speed = 1000;
   1369         break;
   1370 
   1371     case SPEED_2_5GIG:
   1372         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_2500MB) && 
   1373             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_2500MB)) {
   1374             infoA->duplex = TRUE;
   1375             infoB->duplex = TRUE;
   1376             infoA->local_ability.speed_full_duplex =
   1377                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_2500MB;
   1378             infoA->local_ability.speed_half_duplex =
   1379                 infoB->local_ability.speed_half_duplex = 0;
   1380         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_2500MB) && 
   1381                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_2500MB)) {
   1382             infoA->duplex = FALSE;
   1383             infoB->duplex = FALSE;
   1384             infoA->local_ability.speed_full_duplex =
   1385                 infoB->local_ability.speed_full_duplex = 0;
   1386             infoA->local_ability.speed_half_duplex =
   1387                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_2500MB;
   1388         } else {
   1389             LOG_ERROR(BSL_LS_APPL_TESTS,
   1390                       (BSL_META_U(unit,
   1391                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1392                        unit, SOC_PORT_NAME(unit, portA),
   1393                        SOC_PORT_NAME(unit, portB)));
   1394             speed = SPEED_MAX;
   1395         } 
   1396         infoA->speed = infoB->speed = 2500;
   1397         break;
   1398 
   1399     case SPEED_3GIG:
   1400         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_3000MB) && 
   1401             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_3000MB)) {
   1402             infoA->duplex = TRUE;
   1403             infoB->duplex = TRUE;
   1404             infoA->local_ability.speed_full_duplex =
   1405                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_3000MB;
   1406             infoA->local_ability.speed_half_duplex =
   1407                 infoB->local_ability.speed_half_duplex = 0;
   1408         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_3000MB) && 
   1409                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_3000MB)) {
   1410             infoA->duplex = FALSE;
   1411             infoB->duplex = FALSE;
   1412             infoA->local_ability.speed_full_duplex =
   1413                 infoB->local_ability.speed_full_duplex = 0;
   1414             infoA->local_ability.speed_half_duplex =
   1415                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_3000MB;
   1416         } else {
   1417             LOG_ERROR(BSL_LS_APPL_TESTS,
   1418                       (BSL_META_U(unit,
   1419                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1420                        unit, SOC_PORT_NAME(unit, portA),
   1421                        SOC_PORT_NAME(unit, portB)));
   1422             speed = SPEED_MAX;
   1423         } 
   1424         infoA->speed = infoB->speed = 3000;
   1425         break;
   1426 
   1427     case SPEED_10GIG:
   1428         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_10GB) && 
   1429             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_10GB)) {
   1430             infoA->duplex = TRUE;
   1431             infoB->duplex = TRUE;
   1432             infoA->local_ability.speed_full_duplex =
   1433                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_10GB;
   1434             infoA->local_ability.speed_half_duplex =
   1435                 infoB->local_ability.speed_half_duplex = 0;
   1436         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_10GB) && 
   1437                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_10GB)) {
   1438             infoA->duplex = FALSE;
   1439             infoB->duplex = FALSE;
   1440             infoA->local_ability.speed_full_duplex =
   1441                 infoB->local_ability.speed_full_duplex = 0;
   1442             infoA->local_ability.speed_half_duplex =
   1443                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_10GB;
   1444         } else {
   1445             LOG_ERROR(BSL_LS_APPL_TESTS,
   1446                       (BSL_META_U(unit,
   1447                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1448                        unit, SOC_PORT_NAME(unit, portA),
   1449                        SOC_PORT_NAME(unit, portB)));
   1450             speed = SPEED_MAX;
   1451         } 
   1452         infoA->speed = infoB->speed = 10000;
   1453         break;
   1454 
   1455     case SPEED_12GIG:
   1456         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_12GB) && 
   1457             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_12GB)) {
   1458             infoA->duplex = TRUE;
   1459             infoB->duplex = TRUE;
   1460             infoA->local_ability.speed_full_duplex =
   1461                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_12GB;
   1462             infoA->local_ability.speed_half_duplex =
   1463                 infoB->local_ability.speed_half_duplex = 0;
   1464         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_12GB) && 
   1465                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_12GB)) {
   1466             infoA->duplex = FALSE;
   1467             infoB->duplex = FALSE;
   1468             infoA->local_ability.speed_full_duplex =
   1469                 infoB->local_ability.speed_full_duplex = 0;
   1470             infoA->local_ability.speed_half_duplex =
   1471                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_12GB;
   1472         } else {
   1473             LOG_ERROR(BSL_LS_APPL_TESTS,
   1474                       (BSL_META_U(unit,
   1475                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1476                        unit, SOC_PORT_NAME(unit, portA),
   1477                        SOC_PORT_NAME(unit, portB)));
   1478             speed = SPEED_MAX;
   1479         } 
   1480         infoA->speed = infoB->speed = 12000;
   1481         break;
   1482 
   1483     case SPEED_13GIG:
   1484         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_13GB) && 
   1485             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_13GB)) {
   1486             infoA->duplex = TRUE;
   1487             infoB->duplex = TRUE;
   1488             infoA->local_ability.speed_full_duplex =
   1489                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_13GB;
   1490             infoA->local_ability.speed_half_duplex =
   1491                 infoB->local_ability.speed_half_duplex = 0;
   1492         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_13GB) && 
   1493                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_13GB)) {
   1494             infoA->duplex = FALSE;
   1495             infoB->duplex = FALSE;
   1496             infoA->local_ability.speed_full_duplex =
   1497                 infoB->local_ability.speed_full_duplex = 0;
   1498             infoA->local_ability.speed_half_duplex =
   1499                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_13GB;
   1500         } else {
   1501             LOG_ERROR(BSL_LS_APPL_TESTS,
   1502                       (BSL_META_U(unit,
   1503                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1504                        unit, SOC_PORT_NAME(unit, portA),
   1505                        SOC_PORT_NAME(unit, portB)));
   1506             speed = SPEED_MAX;
   1507         }
   1508         infoA->speed = infoB->speed = 13000;
   1509         break;
   1510         
   1511     case SPEED_16GIG:
   1512         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_16GB) && 
   1513             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_16GB)) {
   1514             infoA->duplex = TRUE;
   1515             infoB->duplex = TRUE;
   1516             infoA->local_ability.speed_full_duplex =
   1517                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_16GB;
   1518             infoA->local_ability.speed_half_duplex =
   1519                 infoB->local_ability.speed_half_duplex = 0;
   1520         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_16GB) && 
   1521                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_16GB)) {
   1522             infoA->duplex = FALSE;
   1523             infoB->duplex = FALSE;
   1524             infoA->local_ability.speed_full_duplex =
   1525                 infoB->local_ability.speed_full_duplex = 0;
   1526             infoA->local_ability.speed_half_duplex =
   1527                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_16GB;
   1528         } else {
   1529             LOG_ERROR(BSL_LS_APPL_TESTS,
   1530                       (BSL_META_U(unit,
   1531                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1532                        unit, SOC_PORT_NAME(unit, portA),
   1533                        SOC_PORT_NAME(unit, portB)));
   1534             speed = SPEED_MAX;
   1535         }
   1536         infoA->speed = infoB->speed = 16000;
   1537         break;
   1538 
   1539     case SPEED_20GIG:
   1540         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_20GB) && 
   1541             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_20GB)) {
   1542             infoA->duplex = TRUE;
   1543             infoB->duplex = TRUE;
   1544             infoA->local_ability.speed_full_duplex =
   1545                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_20GB;
   1546             infoA->local_ability.speed_half_duplex =
   1547                 infoB->local_ability.speed_half_duplex = 0;
   1548         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_20GB) && 
   1549                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_20GB)) {
   1550             infoA->duplex = FALSE;
   1551             infoB->duplex = FALSE;
   1552             infoA->local_ability.speed_full_duplex =
   1553                 infoB->local_ability.speed_full_duplex = 0;
   1554             infoA->local_ability.speed_half_duplex =
   1555                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_20GB;
   1556         } else {
   1557             LOG_ERROR(BSL_LS_APPL_TESTS,
   1558                       (BSL_META_U(unit,
   1559                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1560                        unit, SOC_PORT_NAME(unit, portA),
   1561                        SOC_PORT_NAME(unit, portB)));
   1562             speed = SPEED_MAX;
   1563         } 
   1564         infoA->speed = infoB->speed = 20000;
   1565         break;
   1566 
   1567     case SPEED_21GIG:
   1568         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_21GB) && 
   1569             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_21GB)) {
   1570             infoA->duplex = TRUE;
   1571             infoB->duplex = TRUE;
   1572             infoA->local_ability.speed_full_duplex =
   1573                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_21GB;
   1574             infoA->local_ability.speed_half_duplex =
   1575                 infoB->local_ability.speed_half_duplex = 0;
   1576         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_21GB) && 
   1577                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_21GB)) {
   1578             infoA->duplex = FALSE;
   1579             infoB->duplex = FALSE;
   1580             infoA->local_ability.speed_full_duplex =
   1581                 infoB->local_ability.speed_full_duplex = 0;
   1582             infoA->local_ability.speed_half_duplex =
   1583                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_21GB;
   1584         } else {
   1585             LOG_ERROR(BSL_LS_APPL_TESTS,
   1586                       (BSL_META_U(unit,
   1587                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1588                        unit, SOC_PORT_NAME(unit, portA),
   1589                        SOC_PORT_NAME(unit, portB)));
   1590             speed = SPEED_MAX;
   1591         } 
   1592         infoA->speed = infoB->speed = 21000;
   1593         break;
   1594 
   1595     case SPEED_24GIG:
   1596         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_24GB) && 
   1597             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_24GB)) {
   1598             infoA->duplex = TRUE;
   1599             infoB->duplex = TRUE;
   1600             infoA->local_ability.speed_full_duplex =
   1601                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_24GB;
   1602             infoA->local_ability.speed_half_duplex =
   1603                 infoB->local_ability.speed_half_duplex = 0;
   1604         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_24GB) && 
   1605                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_24GB)) {
   1606             infoA->duplex = FALSE;
   1607             infoB->duplex = FALSE;
   1608             infoA->local_ability.speed_full_duplex =
   1609                 infoB->local_ability.speed_full_duplex = 0;
   1610             infoA->local_ability.speed_half_duplex =
   1611                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_24GB;
   1612         } else {
   1613             LOG_ERROR(BSL_LS_APPL_TESTS,
   1614                       (BSL_META_U(unit,
   1615                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1616                        unit, SOC_PORT_NAME(unit, portA),
   1617                        SOC_PORT_NAME(unit, portB)));
   1618             speed = SPEED_MAX;
   1619         }
   1620         infoA->speed = infoB->speed = 24000;
   1621         break;
   1622 
   1623     case SPEED_25GIG:
   1624         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_25GB) && 
   1625             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_25GB)) {
   1626             infoA->duplex = TRUE;
   1627             infoB->duplex = TRUE;
   1628             infoA->local_ability.speed_full_duplex =
   1629                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_25GB;
   1630             infoA->local_ability.speed_half_duplex =
   1631                 infoB->local_ability.speed_half_duplex = 0;
   1632         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_25GB) && 
   1633                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_25GB)) {
   1634             infoA->duplex = FALSE;
   1635             infoB->duplex = FALSE;
   1636             infoA->local_ability.speed_full_duplex =
   1637                 infoB->local_ability.speed_full_duplex = 0;
   1638             infoA->local_ability.speed_half_duplex =
   1639                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_25GB;
   1640         } else {
   1641             LOG_ERROR(BSL_LS_APPL_TESTS,
   1642                       (BSL_META_U(unit,
   1643                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1644                        unit, SOC_PORT_NAME(unit, portA),
   1645                        SOC_PORT_NAME(unit, portB)));
   1646             speed = SPEED_MAX;
   1647         } 
   1648         infoA->speed = infoB->speed = 25000;
   1649         break;
   1650 
   1651     case SPEED_30GIG:
   1652         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_30GB) && 
   1653             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_30GB)) {
   1654             infoA->duplex = TRUE;
   1655             infoB->duplex = TRUE;
   1656             infoA->local_ability.speed_full_duplex =
   1657                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_30GB;
   1658             infoA->local_ability.speed_half_duplex =
   1659                 infoB->local_ability.speed_half_duplex = 0;
   1660         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_30GB) && 
   1661                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_30GB)) {
   1662             infoA->duplex = FALSE;
   1663             infoB->duplex = FALSE;
   1664             infoA->local_ability.speed_full_duplex =
   1665                 infoB->local_ability.speed_full_duplex = 0;
   1666             infoA->local_ability.speed_half_duplex =
   1667                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_30GB;
   1668         } else {
   1669             LOG_ERROR(BSL_LS_APPL_TESTS,
   1670                       (BSL_META_U(unit,
   1671                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1672                        unit, SOC_PORT_NAME(unit, portA),
   1673                        SOC_PORT_NAME(unit, portB)));
   1674             speed = SPEED_MAX;
   1675         } 
   1676         infoA->speed = infoB->speed = 30000;
   1677         break;
   1678 
   1679     case SPEED_32GIG:
   1680         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_32GB) && 
   1681             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_32GB)) {
   1682             infoA->duplex = TRUE;
   1683             infoB->duplex = TRUE;
   1684             infoA->local_ability.speed_full_duplex =
   1685                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_32GB;
   1686             infoA->local_ability.speed_half_duplex =
   1687                 infoB->local_ability.speed_half_duplex = 0;
   1688         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_32GB) && 
   1689                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_32GB)) {
   1690             infoA->duplex = FALSE;
   1691             infoB->duplex = FALSE;
   1692             infoA->local_ability.speed_full_duplex =
   1693                 infoB->local_ability.speed_full_duplex = 0;
   1694             infoA->local_ability.speed_half_duplex =
   1695                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_32GB;
   1696         } else {
   1697             LOG_ERROR(BSL_LS_APPL_TESTS,
   1698                       (BSL_META_U(unit,
   1699                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1700                        unit, SOC_PORT_NAME(unit, portA),
   1701                        SOC_PORT_NAME(unit, portB)));
   1702             speed = SPEED_MAX;
   1703         } 
   1704         infoA->speed = infoB->speed = 32000;
   1705         break;
   1706 
   1707     case SPEED_40GIG:
   1708         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_40GB) && 
   1709             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_40GB)) {
   1710             infoA->duplex = TRUE;
   1711             infoB->duplex = TRUE;
   1712             infoA->local_ability.speed_full_duplex =
   1713                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_40GB;
   1714             infoA->local_ability.speed_half_duplex =
   1715                 infoB->local_ability.speed_half_duplex = 0;
   1716         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_40GB) && 
   1717                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_40GB)) {
   1718             infoA->duplex = FALSE;
   1719             infoB->duplex = FALSE;
   1720             infoA->local_ability.speed_full_duplex =
   1721                 infoB->local_ability.speed_full_duplex = 0;
   1722             infoA->local_ability.speed_half_duplex =
   1723                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_40GB;
   1724         } else {
   1725             LOG_ERROR(BSL_LS_APPL_TESTS,
   1726                       (BSL_META_U(unit,
   1727                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1728                        unit, SOC_PORT_NAME(unit, portA),
   1729                        SOC_PORT_NAME(unit, portB)));
   1730             speed = SPEED_MAX;
   1731         } 
   1732         infoA->speed = infoB->speed = 40000;
   1733         break;
   1734 
   1735     case SPEED_42GIG:
   1736         if ((infoA->port_ability.speed_full_duplex & SOC_PA_SPEED_42GB) &&
   1737             (infoB->port_ability.speed_full_duplex & SOC_PA_SPEED_42GB)) {
   1738             infoA->duplex = TRUE;
   1739             infoB->duplex = TRUE;
   1740             infoA->local_ability.speed_full_duplex =
   1741                 infoB->local_ability.speed_full_duplex = SOC_PA_SPEED_42GB;
   1742             infoA->local_ability.speed_half_duplex =
   1743                 infoB->local_ability.speed_half_duplex = 0;
   1744         } else if ((infoA->port_ability.speed_half_duplex & SOC_PA_SPEED_42GB) &&
   1745                    (infoB->port_ability.speed_half_duplex & SOC_PA_SPEED_42GB)) {
   1746             infoA->duplex = FALSE;
   1747             infoB->duplex = FALSE;
   1748             infoA->local_ability.speed_full_duplex =
   1749                 infoB->local_ability.speed_full_duplex = 0;
   1750             infoA->local_ability.speed_half_duplex =
   1751                 infoB->local_ability.speed_half_duplex = SOC_PA_SPEED_42GB;
   1752         } else {
   1753             LOG_ERROR(BSL_LS_APPL_TESTS,
   1754                       (BSL_META_U(unit,
   1755                                   "Unit %d Ports %s-%s: Forcing max speed\n"),
   1756                        unit, SOC_PORT_NAME(unit, portA),
   1757                        SOC_PORT_NAME(unit, portB)));             
   1758             speed = SPEED_MAX;
   1759         }
   1760         infoA->speed = infoB->speed = 42000;
   1761         break;
   1762 
   1763     case SPEED_MAX:
   1764     default:
   1765         speed = SPEED_MAX;
   1766         break;
   1767     }
   1768 
   1769     if (speed == SPEED_MAX) {
   1770         /* compare and take lesser of
   1771          * bcm_port_speed_max and SOC_INFO(unit).port_speed_max */
   1772         bcm_port_speed_max(unit, portA, &infoA->speed);
   1773         if (infoA->speed > SOC_INFO(unit).port_speed_max[portA]) {
   1774             infoA->speed = SOC_INFO(unit).port_speed_max[portA];
   1775         }
   1776         bcm_port_speed_max(unit, portB, &infoB->speed);
   1777         if (infoB->speed > SOC_INFO(unit).port_speed_max[portB]) {
   1778             infoB->speed = SOC_INFO(unit).port_speed_max[portB];
   1779         }
   1780 
   1781         /* Pick lesser of two speeds if gigabit attached to fast */
   1782         if (infoA->speed < infoB->speed) {
   1783             cli_out("NOTICE: port %s only capable of speed %d, setting "
   1784                     "link partner to match.\n",
   1785                     SOC_PORT_NAME(unit, portA), infoA->speed);
   1786             infoB->speed = infoA->speed;
   1787         }
   1788         if (infoB->speed < infoA->speed) {
   1789             cli_out("NOTICE: port %s only capable of speed %d, setting "
   1790                     "link partner to match.\n",
   1791                     SOC_PORT_NAME(unit, portB), infoB->speed);
   1792             infoA->speed = infoB->speed;
   1793         }
   1794         infoA->duplex = infoB->duplex = TRUE;
   1795     } 
   1796 
   1797     /* Setup test mode (internal/external) */
   1798     switch ( mode ) {
   1799     default:
   1800     case TRAFFIC_EXTERNAL_BI:   /* A <-> B */
   1801     case TRAFFIC_EXTERNAL_UP:   /* A -> B  */
   1802     case TRAFFIC_EXTERNAL_DOWN: /* A <- B  */
   1803         infoA->autoneg = infoB->autoneg = dfl_autoneg;
   1804         infoA->enable = infoB->enable = TRUE;
   1805         infoA->stp_state = infoB->stp_state = BCM_STG_STP_FORWARD;
   1806         break;
   1807 
   1808     case TRAFFIC_INTERNAL:
   1809         infoA->autoneg = infoB->autoneg = FALSE;
   1810         infoA->enable = infoB->enable = TRUE;
   1811         infoA->stp_state = infoB->stp_state = BCM_STG_STP_FORWARD;
   1812         infoA->loopback = infoB->loopback = BCM_PORT_LOOPBACK_MAC;
   1813         break;
   1814 
   1815     case TRAFFIC_INTERNAL_PHY:
   1816         infoA->autoneg = infoB->autoneg = FALSE;
   1817         infoA->enable = infoB->enable = TRUE;
   1818         infoA->stp_state = infoB->stp_state = BCM_STG_STP_FORWARD;
   1819         infoA->loopback = infoB->loopback = BCM_PORT_LOOPBACK_PHY;
   1820         break;
   1821 
   1822     }
   1823 
   1824     /* When ANA is disabled, on Gigabit port: assign A as master */
   1825     if ((!infoA->autoneg) || (!infoB->autoneg)) {
   1826         bcm_port_medium_t medium;
   1827         rv = bcm_port_medium_get(unit, portA, &medium);
   1828         if (rv >= 0) {
   1829             if (medium == BCM_PORT_MEDIUM_COPPER) {
   1830                 if (IS_GE_PORT(unit, portA)) {
   1831                     infoA->phy_master = TRUE;
   1832                 } else if (IS_GE_PORT(unit, portB)) {
   1833                     infoB->phy_master = TRUE;
   1834                 }
   1835             }
   1836         }
   1837     }
   1838 
   1839     /* If port is FE port, remove phy_master attributes controlled by it */
   1840     if(IS_FE_PORT(unit, portA)) {
   1841        infoA->action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1842     }
   1843     if(IS_FE_PORT(unit, portB)) {
   1844        infoB->action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1845     }
   1846     
   1847     /* If the Master mode is not changed, remove phy_master attributes from action_mask */
   1848     ms = 0;
   1849     if ((rv = bcm_port_master_get(unit, portA, &ms)) != BCM_E_NONE) {
   1850         cli_out("traffic setup: port %s: could not get port Master mode: %s\n",
   1851                 SOC_PORT_NAME(unit, portA),
   1852                 bcm_errmsg(rv));
   1853         return -1;
   1854     }
   1855     if (ms == infoA->phy_master) {
   1856         infoA->action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1857     }
   1858 
   1859     ms = 0;
   1860     if ((rv = bcm_port_master_get(unit, portB, &ms)) != BCM_E_NONE) {
   1861         cli_out("traffic setup: port %s: could not get port Master mode: %s\n",
   1862                 SOC_PORT_NAME(unit, portB),
   1863                 bcm_errmsg(rv));
   1864         return -1;
   1865     }
   1866     if (ms == infoB->phy_master) {
   1867         infoB->action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   1868     }
   1869 
   1870     /* Commit all changes in one call */
   1871     if (IS_CD_PORT(unit, portA)) {
   1872         bcm_port_resource_t_init(&portResrc);
   1873 
   1874         /* Retrieve the port resource details for the given port */
   1875         if ((rv=bcm_port_resource_speed_get(unit, portA, &portResrc)) < 0) {
   1876                 cli_out("ERROR: traffic setup unit %d, ports %s, %s:"
   1877                         "%s resource speed get failed: %s\n",
   1878                         unit,
   1879                         SOC_PORT_NAME(unit, portA),
   1880                         SOC_PORT_NAME(unit, portB),
   1881                         SOC_PORT_NAME(unit, portA),
   1882                         bcm_errmsg(rv));
   1883                 return -1;
   1884         }
   1885 
   1886         /* Save the new speed to be set */
   1887         portResrc.speed = infoA->speed;
   1888 
   1889         /* Call the API to set the new port speed */
   1890         rv = bcm_port_resource_speed_set(unit, portA, &portResrc);
   1891 
   1892     } else {
   1893         /* Call the API to set the new port speed */
   1894         rv = bcm_port_speed_set(unit, portA, infoA->speed);
   1895     }
   1896 
   1897     if (rv < 0) {
   1898         cli_out("ERROR: traffic setup unit %d, "
   1899                 "port %s - speed %d set failed: %s\n",
   1900                 unit,
   1901                 SOC_PORT_NAME(unit, portA),
   1902                 infoA->speed,
   1903                 bcm_errmsg(rv));
   1904         return -1;
   1905     }
   1906 
   1907     if (IS_CD_PORT(unit, portB)) {
   1908         bcm_port_resource_t_init(&portResrc);
   1909 
   1910         /* Retrieve the port resource details for the given port */
   1911         if ((rv=bcm_port_resource_speed_get(unit, portB, &portResrc)) < 0) {
   1912                 cli_out("ERROR: traffic setup unit %d, ports %s, %s:"
   1913                         "%s resource speed get failed: %s\n",
   1914                         unit,
   1915                         SOC_PORT_NAME(unit, portA),
   1916                         SOC_PORT_NAME(unit, portB),
   1917                         SOC_PORT_NAME(unit, portB),
   1918                         bcm_errmsg(rv));
   1919                 return -1;
   1920         }
   1921 
   1922         /* Save the new speed to be set */
   1923         portResrc.speed = infoB->speed;
   1924 
   1925         /* Call the API to set the new port speed */
   1926         rv = bcm_port_resource_speed_set(unit, portB, &portResrc);
   1927 
   1928     } else {
   1929         /* Call the API to set the new port speed */
   1930         rv = bcm_port_speed_set(unit, portB, infoB->speed);
   1931     }
   1932 
   1933     if (rv < 0) {
   1934         cli_out("ERROR: traffic setup unit %d, "
   1935                 "port %s - speed %d set failed: %s\n",
   1936                 unit,
   1937                 SOC_PORT_NAME(unit, portB),
   1938                 infoB->speed,
   1939                 bcm_errmsg(rv));
   1940         return -1;
   1941     }
   1942 
   1943     if (((rv = bcm_port_duplex_set(unit, portA, infoA->duplex)) < 0) ||
   1944         ((rv = bcm_port_duplex_set(unit, portB, infoB->duplex)) < 0) ||
   1945         ((rv = bcm_port_loopback_set(unit, portA, infoA->loopback)) < 0) ||
   1946         ((rv = bcm_port_loopback_set(unit, portB, infoB->loopback)) < 0) ||
   1947         ((rv = bcm_port_info_restore(unit, portA, infoA)) < 0)) {
   1948         cli_out("ERROR: traffic setup unit %d, ports %s, %s:"
   1949                 " %s info restore failed: %s\n",
   1950                 unit,
   1951                 SOC_PORT_NAME(unit, portA),
   1952                 SOC_PORT_NAME(unit, portB),
   1953                 SOC_PORT_NAME(unit, portA),
   1954                 bcm_errmsg(rv));
   1955         cli_out("%s: duplex = %d, loopback = %d\n",
   1956                 SOC_PORT_NAME(unit, portA), infoA->duplex, infoA->loopback);
   1957         cli_out("%s: duplex = %d, loopback = %d\n",
   1958                 SOC_PORT_NAME(unit, portB), infoB->duplex, infoB->loopback);
   1959         return -1;
   1960     }
   1961     if ((rv = bcm_port_info_restore(unit, portB, infoB)) < 0) {
   1962         cli_out("ERROR: traffic setup unit %d, ports %s, %s:"
   1963                 " %s info restore failed: %s\n",
   1964                 unit,
   1965                 SOC_PORT_NAME(unit, portA),
   1966                 SOC_PORT_NAME(unit, portB),
   1967                 SOC_PORT_NAME(unit, portB),
   1968                 bcm_errmsg(rv));
   1969         return -1;
   1970     }
   1971 
   1972 #if defined(INCLUDE_MACSEC)
   1973      if (_traffic_setup_macsec(unit, portA, portB, test) < 0) {
   1974         cli_out("ERROR: MACSEC traffic setup unit %d, ports %s, %s: Failed\n",
   1975                 unit,
   1976                 SOC_PORT_NAME(unit, portA),
   1977                 SOC_PORT_NAME(unit, portB));
   1978         return -1;
   1979      }
   1980 #endif /* INCLUDE_MACSEC */
   1981 
   1982     cli_out("PORT ");
   1983 
   1984 
   1985     /* Setup VLAN broadcast domains including only each port-pair */
   1986 #ifdef BCM_XGS12_FABRIC_SUPPORT
   1987     if (SOC_IS_XGS12_FABRIC(unit)) {
   1988         int             mod, rv;
   1989         bcm_port_t      xport;
   1990 
   1991         /* Setup UC: each module id has every port in it (except CPU) */
   1992         PBMP_PORT_ITER(unit, xport) {
   1993             for (mod = 0; mod <= SOC_MODID_MAX(unit); mod++) {
   1994                 rv = bcm_stk_ucbitmap_set(unit, xport, mod,
   1995                                           PBMP_PORT_ALL(unit));
   1996                 if (rv < 0) {
   1997                     cli_out("ERROR: port %d module %d: "
   1998                             "bcm_stk_ucbitmap_set failed: %s\n",
   1999                             xport, mod, bcm_errmsg(rv));
   2000                     break;
   2001                 }
   2002             }
   2003         }
   2004 
   2005         /* Setup VID=1 to have every port in it (except CPU) */
   2006         BCM_PBMP_CLEAR(port_pbm);
   2007         rv = bcm_vlan_port_add(unit, VLAN_ID_DEFAULT,
   2008                                PBMP_PORT_ALL(unit), port_pbm);
   2009         if (rv < 0) {
   2010             cli_out("ERROR: vlan %d: add all ports failed: %s\n",
   2011                     VLAN_ID_DEFAULT, bcm_errmsg(rv));
   2012         }
   2013     }  else {
   2014 #endif /* BCM_XGS12_FABRIC_SUPPORT */
   2015 
   2016         /* StrataSwitch / Draco */
   2017         config->vidA = TRAFFIC_VID_BASE + portA;
   2018         config->vidB = config->vidA + 1;
   2019 
   2020         BCM_PBMP_CLEAR(port_pbm);
   2021         BCM_PBMP_PORT_ADD(port_pbm, portA);
   2022         BCM_PBMP_PORT_ADD(port_pbm, portB);
   2023 
   2024         bcm_vlan_port_remove(unit, VLAN_ID_DEFAULT, port_pbm);
   2025 
   2026         /*
   2027          * Internal MAC/PHY traffic. One VLAN, port A and B both
   2028          * members. Port based vlan entry is the same for both
   2029          * ports.
   2030          */
   2031         if ((mode == TRAFFIC_INTERNAL) ||
   2032             (mode == TRAFFIC_INTERNAL_PHY)) {
   2033 
   2034             /* Share VLAN */
   2035             config->vidB = config->vidA;
   2036 
   2037             if (bcm_vlan_create(unit, config->vidA) < 0) {
   2038                 cli_out("ERROR: ports %s, %s vlan %d: cannot create vlan\n",
   2039                         SOC_PORT_NAME(unit, portA),
   2040                         SOC_PORT_NAME(unit, portB),
   2041                         config->vidA);
   2042             }
   2043 
   2044             bcm_vlan_port_add(unit, config->vidA, port_pbm, port_pbm);
   2045 
   2046             if (bcm_port_untagged_vlan_set(unit, portA, config->vidA) < 0) {
   2047                 cli_out("ERROR: port %s vlan %d: cannot set default vlan\n",
   2048                         SOC_PORT_NAME(unit, portA),
   2049                         config->vidA);
   2050             }
   2051             if (bcm_port_untagged_vlan_set(unit, portB, config->vidA) < 0) {
   2052                 cli_out("ERROR: port %s vlan %d: cannot set default vlan\n",
   2053                         SOC_PORT_NAME(unit, portB),
   2054                         config->vidA);
   2055             }
   2056         } else {
   2057 
   2058             /* External cable traffic, 2 VLANS, port A and B both
   2059              * members, native (port-based VLAN id) is vidA for portA,
   2060              * and vidB for portB, from the CLI, the structure is:
   2061              *
   2062              * vlan create A PBM=portA,portB UBM=portA,portB
   2063              * vlan create B PBM=portA,portB UBM=portA,portB
   2064              * pvlan set portA A
   2065              * pvlan set portB B
   2066  */
   2067             if (bcm_vlan_create(unit, config->vidA) < 0) {
   2068                 cli_out("ERROR: ports %s, %s vlan %d: cannot create vlan\n",
   2069                         SOC_PORT_NAME(unit, portA),
   2070                         SOC_PORT_NAME(unit, portB),
   2071                         config->vidA);
   2072             }
   2073             if (bcm_vlan_create(unit, config->vidB) < 0) {
   2074                 cli_out("ERROR: ports %s, %s vlan %d: cannot create vlan\n",
   2075                         SOC_PORT_NAME(unit, portA),
   2076                         SOC_PORT_NAME(unit, portB),
   2077                         config->vidB);
   2078             }
   2079 
   2080             bcm_vlan_port_add(unit, config->vidA, port_pbm, port_pbm);
   2081             bcm_vlan_port_add(unit, config->vidB, port_pbm, port_pbm);
   2082 
   2083             if (bcm_port_untagged_vlan_set(unit, portA, config->vidA) < 0) {
   2084                 cli_out("ERROR: port %s vlan %d: cannot set default vlan\n",
   2085                         SOC_PORT_NAME(unit, portA),
   2086                         config->vidA);
   2087             }
   2088 
   2089             if (bcm_port_untagged_vlan_set(unit, portB, config->vidB) < 0) {
   2090                 cli_out("ERROR: port %s vlan %d: cannot set default vlan\n",
   2091                         SOC_PORT_NAME(unit, portB),
   2092                         config->vidB);
   2093             }
   2094 
   2095         }
   2096 #ifdef BCM_XGS12_FABRIC_SUPPORT
   2097     }
   2098 #endif
   2099 
   2100 #ifdef BCM_ESW_SUPPORT
   2101     if (SOC_IS_XGS3_SWITCH(unit)) {
   2102         if (IS_ST_PORT(unit, portA) || IS_ST_PORT(unit, portB)) {
   2103             int modid = _traffic_xgs3_test_modid_get(unit, portA);
   2104             if (modid < 0) {
   2105                 cli_out("ERROR: port %s: could not get modid\n",
   2106                         SOC_PORT_NAME(unit, portA));
   2107             }
   2108             _traffic_xgs3_modport_set(unit, modid, portA, portB);
   2109             _traffic_xgs3_modport_set(unit, modid, portB, portA);
   2110         }
   2111     }
   2112 #endif /* BCM_ESW_SUPPORT */
   2113 
   2114     cli_out("VLAN ");
   2115 
   2116     /* Setup ARL, for port to forward traffic of a given
   2117      * MAC address and vlan back into each port
   2118      */
   2119     if (!SOC_IS_XGS12_FABRIC(unit)) {
   2120         /* StrataSwitch / XGS switch */
   2121         if ((mode == TRAFFIC_INTERNAL) ||
   2122             (mode == TRAFFIC_INTERNAL_PHY)) {
   2123             /* DLF storm created */
   2124 
   2125         } else if (!IS_HG_PORT(unit, portA)) {
   2126             /* External
   2127              *
   2128              * l2 add PBM=portA MAC=00:00:00:00:00:portA V=B ST=T
   2129              * l2 add PBM=portA MAC=00:00:00:00:00:portB V=A ST=T
   2130              */
   2131             traffic_test_setup_l2addr(unit,
   2132                                       &config->l2A, config->vidB, portA);
   2133             traffic_test_setup_l2addr(unit,
   2134                                       &config->l2B, config->vidA, portB);
   2135 
   2136         }
   2137         cli_out("L2 ");
   2138     }
   2139 
   2140 
   2141     /* Force ports into STP forwarding state */
   2142     bcm_port_stp_set(unit, portA, BCM_STG_STP_FORWARD);
   2143     bcm_port_stp_set(unit, portB, BCM_STG_STP_FORWARD);
   2144 
   2145     /* Clear stats */
   2146     bcm_stat_clear(unit, portA);
   2147     bcm_stat_clear(unit, portB);
   2148     cli_out("STAT\n");
   2149 
   2150     return 0;
   2151 }
   2152 
   2153 /*
   2154  * Print bytes as %d,%2.2fK, %2.2fG, etc.
   2155  */
   2156 static void
   2157 traffic_show_number(uint64 v)
   2158 {
   2159 #ifdef COMPILER_HAS_DOUBLE
   2160     COMPILER_DOUBLE value;
   2161 
   2162     COMPILER_64_TO_DOUBLE(value, v);
   2163 
   2164     if (value < KILO(1.0)) {
   2165         cli_out("%d", (int)value) ;
   2166     } else if (value >= TERA(1.0)) {
   2167         value /= TERA(1.0);
   2168         cli_out("%2.2fT", value);
   2169     } else if (value >= GIGA(1.0)) {
   2170         value /= GIGA(1.0);
   2171         cli_out("%2.2fG", value);
   2172     } else if (value >= MEGA(1.0)) {
   2173         value /= MEGA(1.0);
   2174         cli_out("%2.2fM", value);
   2175     } else {
   2176         value /= KILO(1.0);
   2177         cli_out("%2.2fK", value);
   2178     }
   2179 #else
   2180     uint32 value;
   2181     int prec = 100;
   2182     char *s;
   2183 
   2184     s = _shr_scale_uint64(v, 1024, prec, &value);
   2185     if (*s) {
   2186         cli_out("%d.%02d%s", value / prec, value % prec, s);
   2187     } else {
   2188         cli_out("%d", value / prec);
   2189     }
   2190 #endif
   2191 }
   2192 
   2193 static void
   2194 traffic_show_measured_number(uint64 v, int interval)
   2195 {
   2196 #ifdef COMPILER_HAS_DOUBLE
   2197     COMPILER_DOUBLE value;
   2198 
   2199     COMPILER_64_TO_DOUBLE(value, v);
   2200 
   2201     value /= interval;
   2202 
   2203     if (value < KILO(1.0)) {
   2204         cli_out("%d", (int)value) ;
   2205     } else if (value >= TERA(1.0)) {
   2206         value /= TERA(1.0);
   2207         cli_out("%2.2fT", value);
   2208     } else  if (value >= GIGA(1.0)) {
   2209         value /= GIGA(1.0);
   2210         cli_out("%2.2fG", value);
   2211     } else if (value >= MEGA(1.0)) {
   2212         value /= MEGA(1.0);
   2213         cli_out("%2.2fM", value);
   2214     } else {
   2215         value /= KILO(1.0);
   2216         cli_out("%2.2fK", value);
   2217     }
   2218 #else
   2219     uint64 value64;
   2220     int t;
   2221 
   2222     value64 = v;
   2223 
   2224     /* Shift down to 32 bits */
   2225     t = 0;
   2226     while (COMPILER_64_HI(value64)) {
   2227         COMPILER_64_SHR(value64, 1);
   2228         t++;
   2229     }
   2230     /* Perform 32 bit division with rounding */
   2231     COMPILER_64_SET(value64, 0, _shr_div32r(COMPILER_64_LO(value64), interval));
   2232     /* Shift back - precision is still adequate */
   2233     COMPILER_64_SHL(value64, t);
   2234 
   2235     traffic_show_number(value64);
   2236 #endif
   2237 }
   2238 
   2239 /*
   2240  * Print rate as %d,%2.2fG, etc.
   2241  */
   2242 static void
   2243 traffic_show_measured_rate(uint64 v, int interval, int bytes)
   2244 {
   2245 #ifdef COMPILER_HAS_DOUBLE
   2246     double value = (COMPILER_64_HI(v) * 4294967296.0 + COMPILER_64_LO(v));
   2247     value /= interval;
   2248     if (bytes) {
   2249         value *=  8;
   2250     }
   2251     if (value < 1000.0) {
   2252         cli_out("%d", (int)value) ;
   2253     } else if (value >= 1000000000.0) {
   2254         value /= 1000000000.0;
   2255         cli_out("%2.2fG", value);
   2256     } else if (value >= 1000000.0) {
   2257         value /= 1000000.0;
   2258         cli_out("%2.2fM", value);
   2259     } else {
   2260         value /= 1000.0;
   2261         cli_out("%2.2fK", value);
   2262     }
   2263 #else
   2264     uint64 value;
   2265     uint32 val32;
   2266     int i;
   2267     int prec = 100;
   2268     char *s;
   2269 
   2270     /* Multiply by 8 if byte count */
   2271     if (bytes) {
   2272         COMPILER_64_SHL(v, 3);
   2273     }
   2274     /* Shift down to 32 bits */
   2275     i = 0;
   2276     while (COMPILER_64_HI(v)) {
   2277         COMPILER_64_SHR(v, 1);
   2278         i++;
   2279     }
   2280     /* Perform 32 bit division with rounding */
   2281     COMPILER_64_SET(value, 0, _shr_div32r(COMPILER_64_LO(v), interval));
   2282     /* Shift back - precision is still adequate */
   2283     COMPILER_64_SHL(value, i);
   2284 
   2285     s = _shr_scale_uint64(value, 1000, prec, &val32);
   2286     if (*s) {
   2287         cli_out("%d.%02d%s", val32 / prec, val32 % prec, s);
   2288     } else {
   2289         cli_out("%d", val32 / prec);
   2290     }
   2291 #endif
   2292 }
   2293 
   2294 /*
   2295  * Print time (in seconds) as minutes, hours, etc.
   2296  */
   2297 static void
   2298 traffic_show_runtime(uint32 value)
   2299 {
   2300     if (value >= 12*4*7*60*60*24) {
   2301         value /= 12*4*7*60*60*24;
   2302         cli_out("%d years", value);
   2303     } else if (value >= 4*7*60*60*24 ) {
   2304         value /= 4*7*60*60*24 ;
   2305         cli_out("%d months", value);
   2306     } else if (value >= 7*60*60*24 ) {
   2307         value /= 7*60*60*24 ;
   2308         cli_out("%d weeks", value);
   2309     } else if (value >= 60*60*24) {
   2310         value /= 60*60*24 ;
   2311         cli_out("%d days", value);
   2312     } else if (value >= 60*60) {
   2313         value /= 60*60;
   2314         cli_out("%d hours", value);
   2315     } else if (value >= 60) {
   2316         value /= 60;
   2317         cli_out("%d minutes", value);
   2318     } else {
   2319         cli_out("%d seconds", value) ;
   2320     }
   2321 }
   2322 
   2323 /*
   2324  * Run test structure.
   2325  */
   2326 int
   2327 traffic_run_test(traffic_test_t* test)
   2328 {
   2329     uint32      runtime;
   2330     int         port, portA, portB, interval;
   2331     int         waitloop;
   2332     int         rv;
   2333     pbmp_t      pbm, portpbm,failedpbm;
   2334     bcm_port_ability_t portA_ability;
   2335     bcm_port_ability_t portB_ability;
   2336     char        pfmt[SOC_PBMP_FMT_LEN];
   2337     char        bmstr[FORMAT_PBMP_MAX];
   2338     int         unit;
   2339     int         lastportA;
   2340     int         notraffic;
   2341     int         passed = 1;
   2342 #if  defined(BCM_ESW_SUPPORT)
   2343     uint32      curr_counter_flags;
   2344     int         curr_counter_interval;
   2345     pbmp_t      curr_counter_pbm;
   2346 #endif
   2347 #if defined(BCM_ENDURO_SUPPORT)
   2348     uint32      val=0;
   2349 #endif
   2350     uint64 rbyt, tbyt, rpkt, tpkt, rerr,raln, rdisc, dropped;
   2351     uint64 drbyt, dtbyt, drpkt, dtpkt, drerr, draln, drdisc, ddropped;
   2352 
   2353     COMPILER_64_ZERO(rbyt);    COMPILER_REFERENCE(&rbyt);
   2354     COMPILER_64_ZERO(tbyt);    COMPILER_REFERENCE(&tbyt);
   2355     COMPILER_64_ZERO(rpkt);    COMPILER_REFERENCE(&rpkt);
   2356     COMPILER_64_ZERO(tpkt);    COMPILER_REFERENCE(&tpkt);
   2357     COMPILER_64_ZERO(rerr);    COMPILER_REFERENCE(&rerr);
   2358     COMPILER_64_ZERO(raln);    COMPILER_REFERENCE(&raln);
   2359     COMPILER_64_ZERO(rdisc);   COMPILER_REFERENCE(&rdisc);
   2360     COMPILER_64_ZERO(dropped); COMPILER_REFERENCE(&dropped);
   2361     COMPILER_64_ZERO(drbyt);   COMPILER_REFERENCE(&drbyt);
   2362     COMPILER_64_ZERO(dtbyt);   COMPILER_REFERENCE(&dtbyt);
   2363     COMPILER_64_ZERO(drpkt);   COMPILER_REFERENCE(&drpkt);
   2364     COMPILER_64_ZERO(dtpkt);   COMPILER_REFERENCE(&dtpkt);
   2365     COMPILER_64_ZERO(drerr);   COMPILER_REFERENCE(&drerr);
   2366     COMPILER_64_ZERO(draln);   COMPILER_REFERENCE(&draln);
   2367     COMPILER_64_ZERO(drdisc);  COMPILER_REFERENCE(&drdisc);
   2368     COMPILER_64_ZERO(ddropped);COMPILER_REFERENCE(&ddropped);
   2369 
   2370     unit = test->unit;
   2371     BCM_IF_ERROR_RETURN
   2372         (traffic_test_setup_maxframe(test));
   2373 
   2374     (void)format_pbmp(unit, bmstr, sizeof(bmstr), test->ports);
   2375     cli_out("TRAFFIC: unit %d ports %s (%s), %d packets, mode %s\n",
   2376             unit,
   2377             bmstr,
   2378             SOC_PBMP_FMT(test->ports, pfmt),
   2379             test->npkts,
   2380             traffic_mode_str[test->mode]);
   2381 
   2382     /* Disable l2 address aging ... */
   2383     bcm_l2_age_timer_set(unit, 0);
   2384 
   2385     lastportA = -1;
   2386 
   2387     PBMP_ITER(test->ports, port) {
   2388         test->port_pair[port].portA = -1;
   2389         if (lastportA < 0) {    /* this will be a port A */
   2390             if (!IS_CD_PORT(unit, port)) {
   2391                 if (bcm_port_ability_local_get(unit, port, &portA_ability) < 0) {
   2392                     cli_out("ERROR: traffic setup unit %d, ports %s: "
   2393                             "ability get failed\n",
   2394                             unit, SOC_PORT_NAME(unit, port));
   2395                     return -1;
   2396                 }
   2397             }
   2398             lastportA = port;
   2399         } else {                /* this will be a port B */
   2400             if (!IS_CD_PORT(unit, port)) {
   2401                 if (bcm_port_ability_local_get(unit, port, &portB_ability) < 0) {
   2402                     cli_out("ERROR: traffic setup unit %d, ports %s: "
   2403                             "ability get failed\n",
   2404                             unit, SOC_PORT_NAME(unit, port));
   2405                     return -1;
   2406                 }
   2407                 /* coverity[uninit_use:FALSE] */
   2408                 if ((!(portA_ability.speed_full_duplex &
   2409                       portB_ability.speed_full_duplex) &&
   2410                     !(portA_ability.speed_half_duplex &
   2411                       portB_ability.speed_half_duplex)) ||
   2412                      (portA_ability.encap != portB_ability.encap)) {
   2413                     BCM_PBMP_PORT_REMOVE(test->ports, lastportA);
   2414                     cli_out("WARNING: no common speed between ports %s, %s:"
   2415                             " skip %s\n",
   2416                             SOC_PORT_NAME(unit, lastportA),
   2417                             SOC_PORT_NAME(unit, port),
   2418                             SOC_PORT_NAME(unit, lastportA));
   2419                     lastportA = port;
   2420                     portA_ability = portB_ability;
   2421                     continue;
   2422                 }
   2423             }
   2424 #if defined(BCM_GREYHOUND2_SUPPORT)
   2425             if (SOC_IS_GREYHOUND2(unit)) {
   2426                 int         speedmaxA, speedmaxB;
   2427                 bcm_port_abil_t max_speed_mask;
   2428 
   2429                 /* if testing with sp=maximun(default), make sure both portA and B support the least common maximun speed*/
   2430                 if (bcm_port_speed_max(unit, lastportA, &speedmaxA) < 0) {
   2431                     cli_out("Error: Port speed max get fail unit %d, ports %d: "
   2432                             "ability get failed\n",
   2433                             unit, lastportA);
   2434                     return -1;
   2435                 }
   2436                 if (speedmaxA > SOC_INFO(unit).port_speed_max[lastportA]) {
   2437                     speedmaxA = SOC_INFO(unit).port_speed_max[lastportA];
   2438                 }
   2439                 if (bcm_port_speed_max(unit, port, &speedmaxB) < 0) {
   2440                     cli_out("Error: Port speed max get fail unit %d, ports %d: "
   2441                             "ability get failed\n",
   2442                             unit, port);
   2443                     return -1;
   2444                 }
   2445                 if (speedmaxB > SOC_INFO(unit).port_speed_max[port]) {
   2446                     speedmaxB = SOC_INFO(unit).port_speed_max[port];
   2447                 }
   2448                 if (speedmaxA > speedmaxB) {
   2449                     max_speed_mask = SOC_PA_SPEED(speedmaxB);
   2450                     if (!(portA_ability.speed_full_duplex & max_speed_mask)) {
   2451                         BCM_PBMP_PORT_REMOVE(test->ports, lastportA);
   2452                         cli_out("WARNING: no common max speed between ports %s, %s:"
   2453                                 " skip %s\n",
   2454                                 SOC_PORT_NAME(unit, lastportA),
   2455                                 SOC_PORT_NAME(unit, port),
   2456                                 SOC_PORT_NAME(unit, lastportA));
   2457                         lastportA = port;
   2458                         portA_ability = portB_ability;
   2459                         continue;
   2460                     }
   2461                 } else if (speedmaxA < speedmaxB) {
   2462                     max_speed_mask = SOC_PA_SPEED(speedmaxA);
   2463                     if (!(portB_ability.speed_full_duplex & max_speed_mask)) {
   2464                         BCM_PBMP_PORT_REMOVE(test->ports, lastportA);
   2465                         cli_out("WARNING: no common max speed between ports %s, %s:"
   2466                                 " skip %s\n",
   2467                                 SOC_PORT_NAME(unit, lastportA),
   2468                                 SOC_PORT_NAME(unit, port),
   2469                                 SOC_PORT_NAME(unit, lastportA));
   2470                         lastportA = port;
   2471                         /* coverity[uninit_use:FALSE] */
   2472                         portA_ability = portB_ability;
   2473                         continue;
   2474                     }
   2475 
   2476                 }
   2477             }
   2478 #endif /* BCM_GREYHOUND2_SUPPORT */
   2479             test->port_pair[lastportA].portA = lastportA;
   2480             test->port_pair[lastportA].portB = port;
   2481             lastportA = -1;
   2482         }
   2483     }
   2484     if (lastportA != -1) {
   2485         BCM_PBMP_PORT_REMOVE(test->ports, lastportA);
   2486         cli_out("WARNING: odd number of ports, will not use port %s\n",
   2487                 SOC_PORT_NAME(unit, lastportA));
   2488     }
   2489 
   2490     cli_out("TRAFFIC: Port pairing:");
   2491     PBMP_ITER(test->ports, port) {
   2492         if (test->port_pair[port].portA != port) {
   2493             /* skip B ports and unused ports */
   2494             continue;
   2495         }
   2496         cli_out(" %s-%s",
   2497                 SOC_PORT_NAME(unit, test->port_pair[port].portA),
   2498                 SOC_PORT_NAME(unit, test->port_pair[port].portB));
   2499     }
   2500     cli_out("\n");
   2501 
   2502     /* First, configure forwarding behaviours */
   2503     PBMP_ITER(test->ports, port) {
   2504         if (test->port_pair[port].portA != port) {      /* skip B ports */
   2505             continue;
   2506         }
   2507         cli_out("TRAFFIC: setting up ports %s, %s: ",
   2508                 SOC_PORT_NAME(unit, test->port_pair[port].portA),
   2509                 SOC_PORT_NAME(unit, test->port_pair[port].portB));
   2510         traffic_test_setup_port_pair(test, port, test->mode, test->req_speed);
   2511     }
   2512 
   2513 #if defined(INCLUDE_MACSEC)
   2514     if (test->macsec_enabled) {
   2515         _traffic_setup_macsec_poll_task(unit, test);
   2516     }
   2517 #endif /* INCLUDE_MACSEC */
   2518 
   2519     SOC_PBMP_ASSIGN(pbm, test->ports);
   2520     (void)format_pbmp(unit, bmstr, sizeof(bmstr), pbm);
   2521     cli_out("TRAFFIC: waiting for link on ports %s (%s)\n",
   2522             bmstr, SOC_PBMP_FMT(pbm, pfmt));
   2523 
   2524     rv = bcm_link_wait(unit, &pbm, TRAFFIC_LINK_TIMEOUT);
   2525     if (!BCM_SUCCESS(rv)) {
   2526         SOC_PBMP_ASSIGN(portpbm, test->ports);
   2527         SOC_PBMP_REMOVE(portpbm, pbm);
   2528         (void)format_pbmp(unit, bmstr, sizeof(bmstr), portpbm);
   2529         test_error(unit, "TRAFFIC: failed waiting for link on %s (%s): %s\n",
   2530                    bmstr, SOC_PBMP_FMT(portpbm, pfmt), bcm_errmsg(rv));
   2531         return -1;
   2532     }
   2533 
   2534     /* Link is up - make sure port characteristics from PHY and MAC are match */
   2535     PBMP_ITER(test->ports, port) {
   2536         bcm_port_update(unit, port, 1);
   2537     }
   2538 
   2539     /* sleep for half second to allow MAC, serdes and PHY to stabilize.
   2540      * bcm_link_wait may not reflect the internal serdes link status
   2541      */
   2542     sal_usleep(500000);
   2543 
   2544     /* Wait to for MAC to be stable */ 
   2545     rv = bcm_link_wait(unit, &pbm, TRAFFIC_LINK_TIMEOUT);
   2546     if (!BCM_SUCCESS(rv)) {
   2547         SOC_PBMP_ASSIGN(portpbm, test->ports);
   2548         SOC_PBMP_REMOVE(portpbm, pbm);
   2549         (void)format_pbmp(unit, bmstr, sizeof(bmstr), portpbm);
   2550         test_error(unit, "TRAFFIC: failed waiting for link on %s (%s): %s\n",
   2551                    bmstr, SOC_PBMP_FMT(portpbm, pfmt), bcm_errmsg(rv));
   2552         return -1;
   2553     }
   2554 
   2555     /*
   2556      * Clear all H/W counters using soc driver,we do it here
   2557      * so that if we are running an external test, we won't see
   2558      * a false-carrier error if it occurs.
   2559      */
   2560 #ifdef BCM_ESW_SUPPORT
   2561     if (soc_counter_set32_by_port(unit, test->ports, 0) < 0) {
   2562         cli_out("ERROR: Clear counters failed\n");
   2563         return -1;
   2564     }
   2565 #endif    
   2566 
   2567     /* Finally, inject the frame on each port pair .... */
   2568     PBMP_ITER(test->ports, port) {
   2569         if (test->port_pair[port].portA != port) {      /* skip B ports */
   2570             continue;
   2571         }
   2572         cli_out("TRAFFIC: starting %d byte frames on ports %s, %s\n",
   2573                 test->pkt_size,
   2574                 SOC_PORT_NAME(unit, test->port_pair[port].portA),
   2575                 SOC_PORT_NAME(unit, test->port_pair[port].portB));
   2576         traffic_test_send_frames(test, port);
   2577     }
   2578 
   2579     /* Loop until user presses control-C, showing status */
   2580     interval = test->poll_interval; /* seconds */
   2581     runtime = 0;
   2582 
   2583     if (test->runtime <= test->poll_interval) {
   2584         test->runtime = test->poll_interval + 1;
   2585         cli_out("NOTICE: test will poll in %d seconds"
   2586                 ", using new test runtime of %d seconds.\n",
   2587                 test->poll_interval, test->poll_interval + 1);
   2588     }
   2589 
   2590     /* Save the current parameters for counter collection task. */
   2591 #ifdef BCM_ESW_SUPPORT
   2592         if (soc_counter_status(unit, &curr_counter_flags, &curr_counter_interval,
   2593                            &curr_counter_pbm) < 0) {
   2594             cli_out("ERROR: Failed to get counter collection status\n");
   2595             return -1;
   2596         }
   2597 #endif    
   2598 
   2599 
   2600 
   2601     /*
   2602      * Start (or re-start) counter collection with an interval which is two
   2603      * times longer than the polling interval of the test. This prevents
   2604      * the counter collection thread from syncing stats too often
   2605      * giving us predictable results when calling bcm_stat_sync below.
   2606      * Wrap-around should not be an issue since the HW has 64-bit counters.
   2607      */
   2608 #ifdef BCM_ESW_SUPPORT
   2609     if (soc_counter_start(unit, curr_counter_flags, 
   2610                           test->poll_interval * 2000000, 
   2611                           test->ports) < 0) {
   2612         cli_out("ERROR: Failed to start counter collection\n");
   2613         return -1;
   2614     }
   2615 #endif    
   2616 
   2617     SOC_PBMP_CLEAR(failedpbm); /*Initialize the pbm*/
   2618 
   2619     /* Wait a configurable amount of time, then check the stats */
   2620     waitloop = 0;
   2621     while (runtime <= test->runtime) {
   2622         waitloop += 1;
   2623 
   2624         {
   2625             /* syncing counters before thread goes to sleep */ 
   2626             sal_usleep(interval * SECOND_USEC);
   2627             bcm_stat_sync(unit);
   2628 
   2629             PBMP_ITER(test->ports, port) {
   2630                  portA =  test->port_pair[port].portA;
   2631                  portB =  test->port_pair[port].portB;
   2632                  if (port != portA) {
   2633                      continue;
   2634                  }
   2635                 bcm_stat_get(unit, port, snmpIfInOctets, &rbyt);
   2636                 bcm_stat_get(unit, port, snmpIfOutOctets, &tbyt);
   2637                 bcm_stat_get(unit, port, snmpDot1dTpPortOutFrames, &tpkt);
   2638                 bcm_stat_get(unit, port, snmpDot1dTpPortInFrames, &rpkt);
   2639                 bcm_stat_get(unit, port, snmpDot3StatsAlignmentErrors, &raln);
   2640                 bcm_stat_get(unit, port, snmpDot3StatsInternalMacReceiveErrors,
   2641                              &rdisc);
   2642                 bcm_stat_get(unit, port, snmpIfInDiscards, &dropped);
   2643  
   2644                 test->port_stats[port].rbyt = rbyt;
   2645                 test->port_stats[port].tbyt = tbyt;
   2646                 test->port_stats[port].rpkt = rpkt;
   2647                 test->port_stats[port].tpkt = tpkt;
   2648                 test->port_stats[port].raln = raln;
   2649                 test->port_stats[port].rdisc = rdisc;
   2650                 test->port_stats[port].dropped = dropped;
   2651             }
   2652         }
   2653 
   2654         sal_usleep(interval * SECOND_USEC);
   2655 
   2656         bcm_stat_sync(unit);
   2657 
   2658         if (waitloop == 1) {
   2659             cli_out("TRAFFIC: mode %s, %d byte frames, runtime ",
   2660                     traffic_mode_str[test->mode], test->pkt_size);
   2661             traffic_show_runtime(interval);
   2662             cli_out(" of ");
   2663             traffic_show_runtime(test->runtime);
   2664             cli_out("\n");
   2665             cli_out("TRAFFIC: press Ctrl-C to stop test\n");
   2666         } else {
   2667             cli_out("TRAFFIC: running... (%d%% complete)\n",
   2668                     (runtime*100)/test->runtime);
   2669         }
   2670         runtime += interval;
   2671 
   2672         /* Dump stats */
   2673         PBMP_ITER(test->ports, port) {
   2674             portA =  test->port_pair[port].portA;
   2675             portB =  test->port_pair[port].portB;
   2676             if (port != portA) {
   2677                 continue;
   2678             }
   2679             bcm_stat_get(unit, port, snmpIfInOctets, &rbyt);
   2680             bcm_stat_get(unit, port, snmpIfOutOctets, &tbyt);
   2681             bcm_stat_get(unit, port, snmpDot1dTpPortOutFrames, &tpkt);
   2682             bcm_stat_get(unit, port, snmpDot1dTpPortInFrames, &rpkt);
   2683             bcm_stat_get(unit, port, snmpDot3StatsAlignmentErrors, &raln);
   2684             bcm_stat_get(unit, port, snmpDot3StatsInternalMacReceiveErrors,
   2685                          &rdisc);
   2686             bcm_stat_get(unit, port, snmpIfInDiscards, &dropped);
   2687 
   2688             {
   2689                 int speed, duplex;
   2690                 uint32 dtpktl, dtbytl, drpktl, drbytl;
   2691                 uint32 dralnl, drdiscl, ddroppedl;
   2692 
   2693                 COMPILER_64_DELTA(drbyt, test->port_stats[port].rbyt, rbyt);
   2694                 COMPILER_64_DELTA(dtbyt, test->port_stats[port].tbyt, tbyt);
   2695                 COMPILER_64_DELTA(drpkt, test->port_stats[port].rpkt, rpkt);
   2696                 COMPILER_64_DELTA(dtpkt, test->port_stats[port].tpkt, tpkt);
   2697                 COMPILER_64_DELTA(draln, test->port_stats[port].raln, raln);
   2698                 COMPILER_64_DELTA(drdisc, test->port_stats[port].rdisc,
   2699                                   rdisc);
   2700                 COMPILER_64_DELTA(ddropped, test->port_stats[port].dropped,
   2701                                   dropped);
   2702 
   2703                 COMPILER_64_TO_32_LO(drbytl, drbyt);
   2704                 COMPILER_64_TO_32_LO(dtbytl, dtbyt);
   2705                 COMPILER_64_TO_32_LO(drpktl, drpkt);
   2706                 COMPILER_64_TO_32_LO(dtpktl, dtpkt);
   2707                 COMPILER_64_TO_32_LO(dralnl, draln);
   2708                 COMPILER_64_TO_32_LO(drdiscl, drdisc);
   2709                 COMPILER_64_TO_32_LO(ddroppedl, ddropped);
   2710 
   2711                 /* Ignore RX counters for BCM5670/BCM5675 */
   2712                 if (((SOC_IS_XGS_FABRIC(unit)) ||
   2713                      (SOC_IS_XGS3_SWITCH(unit))) &&
   2714                     (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) &&
   2715                     (test->mode == TRAFFIC_INTERNAL)) {
   2716                     drpktl = dtpktl;
   2717                     drbytl = dtbytl;
   2718                 }
   2719 
   2720 
   2721                 bcm_port_speed_get(unit, port, &speed);
   2722                 bcm_port_duplex_get(unit, port, &duplex);
   2723                 cli_out("Port %s (", SOC_PORT_NAME(unit, port));
   2724                 if (speed >= 1000) {
   2725                     if (speed % 1000) {
   2726                         cli_out("%d.%dG %s", speed / 1000,
   2727                                 (speed % 1000) / 100,
   2728                                 duplex ? "FD" : "HD");
   2729                     } else {
   2730                         cli_out("%dG %s", speed / 1000,
   2731                                 duplex ? "FD" : "HD");
   2732                     }
   2733                 } else if (speed == 0) {
   2734                     cli_out("-");
   2735                 } else {
   2736                     cli_out("%dM %s", speed, duplex ? "FD" : "HD");
   2737                 }
   2738                 cli_out("): %s\n",
   2739                         dralnl > 0 ? "ALN Error Detected" :
   2740                         drdiscl > 0 ? "Discard Error Detected" :
   2741                         ddroppedl > 0 ? "Dropped Error Detected" :
   2742                         (drpktl == 0 || dtpktl == 0 ||
   2743                         dtbytl == 0 || drbytl == 0) ?
   2744                         "FAIL->NO TRAFFIC" :"PASSED");
   2745 
   2746 
   2747                 cli_out("\tTX packets ");
   2748                 traffic_show_number(tpkt);
   2749                 cli_out(" +");
   2750                 traffic_show_measured_number(dtpkt, interval);
   2751                 cli_out("/s TX Bytes ");
   2752                 traffic_show_number(tbyt);
   2753                 cli_out("B +");
   2754                 traffic_show_measured_number(dtbyt, interval);
   2755                 cli_out("B/s [");
   2756                 traffic_show_measured_rate(dtbyt, interval, TRUE);
   2757                 cli_out("b/s]");
   2758                 cli_out("\n\tRX packets ");
   2759                 traffic_show_number(rpkt);
   2760                 cli_out(" +");
   2761                 traffic_show_measured_number(drpkt, interval);
   2762                 cli_out("/s RX bytes ");
   2763                 traffic_show_number(rbyt);
   2764                 cli_out("B +");
   2765                 traffic_show_measured_number(drbyt, interval);
   2766                 cli_out("B/s [");
   2767                 traffic_show_measured_rate(drbyt, interval, TRUE);
   2768                 cli_out("b/s]");
   2769                 cli_out("\n");
   2770 
   2771                 notraffic = 0;
   2772 
   2773                 /* Zero packet rate increase indicates failure */
   2774                 if (drpktl == 0 || dtpktl == 0 || dtbytl == 0 || drbytl == 0) {
   2775                     cli_out("ERROR: traffic stopped on ports %s, %s\n",
   2776                             SOC_PORT_NAME(unit, portA),
   2777                             SOC_PORT_NAME(unit, portB));
   2778                     notraffic = 1;
   2779                 }
   2780 
   2781                 if (notraffic || test->showstats) {
   2782                     /* Give us a clue .. */
   2783                     cli_out("PortA (%s) statistics:\n",
   2784                             SOC_PORT_NAME(unit, portA));
   2785                     BCM_PBMP_CLEAR(portpbm);
   2786                     BCM_PBMP_PORT_ADD(portpbm, portA);
   2787                     if (SOC_IS_ESW(unit)) {
   2788 #ifdef BCM_ESW_SUPPORT
   2789                         do_show_counters(unit,
   2790                                      INVALIDr,
   2791                                      portpbm,
   2792                                      SHOW_CTR_CHANGED|
   2793                                      SHOW_CTR_SAME|
   2794                                      SHOW_CTR_NZ);
   2795 #endif
   2796                     } else {
   2797                     }
   2798                     cli_out("PortB (%s) statistics:\n",
   2799                             SOC_PORT_NAME(unit, portB));
   2800                     BCM_PBMP_CLEAR(portpbm);
   2801                     BCM_PBMP_PORT_ADD(portpbm, portB);
   2802                     if (SOC_IS_ESW(unit)) {
   2803 #ifdef BCM_ESW_SUPPORT
   2804                         do_show_counters(unit,
   2805                                      INVALIDr,
   2806                                      portpbm,
   2807                                      SHOW_CTR_CHANGED|
   2808                                      SHOW_CTR_SAME|
   2809                                      SHOW_CTR_NZ);                        
   2810 #endif
   2811                     } else {
   2812                     }
   2813                 }
   2814 
   2815                 if (notraffic && test->stop_on_fail) {
   2816                     /* Restore original counter collection settings. */
   2817 #ifdef BCM_ESW_SUPPORT
   2818                     (void) soc_counter_start(unit, curr_counter_flags,
   2819                                              curr_counter_interval, 
   2820                                              curr_counter_pbm);
   2821 #endif    
   2822                     passed = 0;
   2823                     SOC_PBMP_PORT_ADD(failedpbm,port);
   2824                     if (test->run2end == 0) {
   2825                         cli_out("Exiting test..\n");
   2826                         return -1;
   2827                     }
   2828                 }
   2829             }
   2830         }
   2831     }
   2832 
   2833 #if defined(BCM_ENDURO_SUPPORT)    
   2834     if (SOC_IS_ENDURO(unit)) {
   2835         /* Check MMU parity error registers */
   2836         SOC_IF_ERROR_RETURN(READ_MEM_FAIL_INT_STATr(unit, &val));
   2837         if (val) {
   2838             cli_out("ERROR: MEM_FAIL_INT_STAT 0x%x\n", val);
   2839             return -1;
   2840         }
   2841         /* coverity[result_independent_of_operands] */
   2842         SOC_IF_ERROR_RETURN(READ_CMIC_CHIP_PARITY_INTR_STATUSr(unit, &val));
   2843         if (val) {
   2844             cli_out("ERROR: CMIC_CHIP_PARITY_INTR_STATUS 0x%x\n", val);
   2845             return -1;
   2846         }
   2847         SOC_IF_ERROR_RETURN(READ_EP_INTR_STATUSr(unit, &val));
   2848         if (val) {
   2849             cli_out("ERROR: EP_INTR_STATUS 0x%x\n", val);
   2850             return -1;
   2851         }
   2852         SOC_IF_ERROR_RETURN(READ_ECC_SINGLE_BIT_ERRORSr(unit, &val));
   2853         if (val) {
   2854             cli_out("ERROR: ECC_SINGLE_BIT_ERRORS 0x%x\n", val);
   2855             return -1;
   2856         }
   2857     }
   2858 #endif /* BCM_ENDURO_SUPPORT */
   2859 
   2860     if (passed) {
   2861         cli_out("TEST passed: ");
   2862         traffic_show_runtime(test->runtime);
   2863         cli_out("\n");
   2864     } else {
   2865         cli_out("TEST failed: \n");
   2866         PBMP_ITER(failedpbm, port) {
   2867             cli_out("Port %s: FAIL->NO TRAFFIC.\n",
   2868             SOC_PORT_NAME(unit, port));
   2869         }
   2870         cli_out("\n");
   2871     }
   2872 
   2873 #if defined(INCLUDE_MACSEC)
   2874     macsec_stop_poll_task = 1;
   2875 #endif
   2876 
   2877     /* Restore original counter collection settings. */
   2878 
   2879 #ifdef BCM_ESW_SUPPORT
   2880     if (soc_counter_start(unit, curr_counter_flags,
   2881                           curr_counter_interval, curr_counter_pbm) < 0) {
   2882         cli_out("ERROR: Failed to restore counter collection\n");
   2883         return -1;
   2884     }
   2885 #endif    
   2886 
   2887     return 0;
   2888 }
   2889 
   2890 
   2891 /*
   2892  * Run Traffic Test structure for the test CLI.
   2893  */
   2894 STATIC int
   2895 traffic_run_cli(int unit, args_t* args, void* pa)
   2896 {
   2897     return traffic_run_test(traf_test[unit]);
   2898 }
   2899 
   2900 
   2901 /*
   2902  * Parse Test Parameters, create test structure
   2903  */
   2904 int
   2905 traffic_test_init(int unit, args_t *a, void **pa)
   2906 {
   2907     parse_table_t       pt;
   2908     int             port = 0;
   2909     int             last_port = 0;
   2910     int             num_ports = 0;
   2911 
   2912     SOC_PBMP_ASSIGN(dfl_portbitmap, PBMP_PORT_ALL(unit));
   2913 
   2914     PBMP_ITER(dfl_portbitmap, port) {
   2915         last_port = port;
   2916         num_ports++;
   2917     }
   2918 
   2919     if (num_ports % 2) {
   2920         BCM_PBMP_PORT_REMOVE(dfl_portbitmap, last_port);
   2921     }
   2922 
   2923     parse_table_init(unit, &pt);
   2924     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   2925                     &dfl_pattern,NULL);
   2926     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL, 0,
   2927                     &dfl_pattern_inc,NULL);
   2928     parse_table_add(&pt, "TimeInSeconds", PQ_INT|PQ_DFL,0,
   2929                     &dfl_runtime,       NULL);
   2930     parse_table_add(&pt, "CounterPollInterval", PQ_INT|PQ_DFL,0,
   2931                     &dfl_poll_interval, NULL);
   2932     parse_table_add(&pt, "RunMode",     PQ_MULTI|PQ_DFL,0,
   2933                     &dfl_runmode,       traffic_mode_str);
   2934     parse_table_add(&pt, "SPeed",       PQ_MULTI|PQ_DFL,0,
   2935                     &dfl_speed, traffic_speed_str);
   2936     parse_table_add(&pt, "AutoNeg",     PQ_BOOL|PQ_DFL, 0,
   2937                     &dfl_autoneg, NULL);
   2938     parse_table_add(&pt, "Length",      PQ_INT|PQ_DFL,  0,
   2939                     &dfl_size,  NULL);
   2940     parse_table_add(&pt, "Count",      PQ_INT|PQ_DFL,  0,
   2941                     &dfl_count,  NULL);
   2942     parse_table_add(&pt, "PortBitMap",  PQ_PBMP|PQ_DFL, 0,
   2943                     &dfl_portbitmap,    NULL);
   2944     parse_table_add(&pt, "CleanUp",     PQ_BOOL|PQ_DFL, 0,
   2945                     &dfl_cleanup, NULL);
   2946     parse_table_add(&pt, "ShowStats",   PQ_BOOL|PQ_DFL, 0,
   2947                     &dfl_showstats, NULL);
   2948     parse_table_add(&pt, "Run2End",   PQ_BOOL|PQ_DFL, 0,
   2949                     &dfl_run2end, NULL);
   2950 #if defined(INCLUDE_MACSEC)
   2951     parse_table_add(&pt, "MacSEC",   PQ_BOOL|PQ_DFL, 0,
   2952                     &dfl_macsec, NULL);
   2953 #endif /* INCLUDE_MACSEC */ 
   2954 
   2955     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   2956         test_error(unit,
   2957                    "%s: Invalid option: %s\n",
   2958                    ARG_CMD(a),
   2959                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   2960         parse_arg_eq_done(&pt);
   2961         return -1;
   2962     }
   2963     parse_arg_eq_done(&pt);
   2964 
   2965     /* Alloc test, save H/W state, setup defaults */
   2966     traf_test[unit] = traffic_test_alloc(unit);
   2967 
   2968 #if defined(BCM_ENDURO_SUPPORT)
   2969     if (SOC_IS_ENDURO(unit)) {
   2970         /* Disable parity interrupt */
   2971         /* coverity[result_independent_of_operands] */
   2972         SOC_IF_ERROR_RETURN(WRITE_CMIC_CHIP_PARITY_INTR_ENABLEr(unit, 0));
   2973     }
   2974 #endif /* BCM_ENDURO_SUPPORT */
   2975 
   2976     return 0;
   2977 }
   2978 
   2979 int
   2980 traffic_test(int unit, args_t *a, void *pa)
   2981 {
   2982     return traffic_run_cli(unit, a, traf_test[unit]);
   2983 }
   2984 
   2985 int
   2986 traffic_test_done(int unit, void *pa)
   2987 {
   2988 #if defined(BCM_ENDURO_SUPPORT)
   2989     uint32 val = 0;
   2990 #endif
   2991     int rv = 0;
   2992 
   2993     if (traf_test[unit]->cleanup) {
   2994         /* nothing to do right here */
   2995     } else {
   2996         cli_out("WARNING: CleanupOnExit disabled: "
   2997                 "(H/W configuration still active for debug)\n");
   2998         cli_out("*** Zero EPC_LINK to stop traffic.\n");
   2999         cli_out("*** Reboot switch when done.\n");
   3000     }
   3001 
   3002     rv = traffic_test_free(traf_test[unit]);
   3003     sal_free(traf_test[unit]);
   3004 
   3005 #if defined(BCM_ENDURO_SUPPORT)    
   3006     if (SOC_IS_ENDURO(unit)) {
   3007        /* Check MMU outstanding packets/cells */ 
   3008         SOC_IF_ERROR_RETURN(READ_TOTAL_BUFFER_COUNT_PACKETr(unit, &val));
   3009         if (val) {
   3010 	    cli_out("ERROR: TOTAL_BUFFER_COUNT_PACKET 0x%x\n", val);
   3011         }
   3012         SOC_IF_ERROR_RETURN(READ_TOTAL_BUFFER_COUNT_CELLr(unit, &val));
   3013         if (val) {
   3014 	    cli_out("ERROR: TOTAL_BUFFER_COUNT_CELL 0x%x\n", val);
   3015         }
   3016         SOC_IF_ERROR_RETURN(READ_CFAPREADPOINTERr(unit, &val));
   3017         if (val != 0x1c) {
   3018 	    cli_out("ERROR: CFAPREADPOINTER 0x%x\n", val);
   3019         }
   3020         SOC_IF_ERROR_RETURN(READ_PFAPREADPOINTERr(unit, &val));
   3021         if (val != 0x1c) {
   3022 	    cli_out("ERROR: PFAPREADPOINTER 0x%x\n", val);
   3023         }
   3024     }
   3025 #endif /* BCM_ENDURO_SUPPORT */
   3026 
   3027     return rv;
   3028 }