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

streaming_l3uc.c (31417B)


      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  * The l3uc test checks TDM and L3 unicast functionality and performance by
      8  * streaming IPv4/IPv6 packets on all ports at maximum rate. All ports are
      9  * configured in MAC loopback mode and each port is paired with a same speed
     10  * port. The test calculates the number of packets needed to saturate the ports
     11  * and send the IPv4/IPv6 packets from the CPU to each port pairs initially.
     12  * Then the packets are L3 switched between the port pairs indefinitely. The
     13  * MAC DA, MAC SA, and VLAN are changed every time a packet is L3 switched. Once
     14  * the traffic reaches steady state, rate calculation is done by dividing the
     15  * transmit packet count changes and transmit byte count changes over a
     16  * programmable interval. The rates are checked against expected rates based on
     17  * port configuration and oversubscription ratio. Finally, packet integrity
     18  * check is achieved by redirecting the packets back to the CPU and compared
     19  * against expected packets.
     20  *
     21  * Configuration parameters passed from CLI:
     22  * PktSize: Packet size in bytes. Set to 0 for worst case packet sizes on all
     23  *          ports (145B for ENET, 76B for HG2). Set to 1 for random packet sizes
     24  * FloodCnt: Number of packets in each swill. Setting this to 0 will let the
     25  *           test calculate the number of packets that can be sent to achieve
     26  *           a lossless swirl at full rate. Set to 0 by default.
     27  * RateCalcInt: Interval in seconds over which rate is to be calculated
     28  * TolLr: Rate tolerance percentage for linerate ports (1% by default).
     29  * TolOv: Rate tolerance percentage for oversubscribed ports (3% by default).
     30  * ChkPktInteg: Set to 0 to disable packet integrity checks, 1 to enable
     31                 (default).
     32  * MaxNumCells: Max number of cells for random packet sizes. Default = 4. Set
     33  *              to 0 for random.
     34  * IPv6: Set to 1 to send IPv6 packets, 0 to send IPv4 packets (default).
     35  */
     36 
     37 #include <appl/diag/system.h>
     38 #include <shared/alloc.h>
     39 #include <shared/bsl.h>
     40 
     41 #include <soc/cm.h>
     42 #include <soc/dma.h>
     43 #include <soc/drv.h>
     44 #include <soc/dcb.h>
     45 #include <soc/cmicm.h>
     46 #include <soc/cmic.h>
     47 
     48 #include <sal/types.h>
     49 #include <appl/diag/parse.h>
     50 #include <bcm/port.h>
     51 #include <bcm/vlan.h>
     52 
     53 #include "testlist.h"
     54 #include "gen_pkt.h"
     55 #include "streaming_lib.h"
     56 
     57 #define MAC_DA {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}
     58 #define MAC_SA {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54}
     59 #define VLAN 0x0a00
     60 #define TTL 255
     61 #define IPV4_ADDR 0xc0a80001
     62 #define IPV6_ADDR { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
     63                     0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x00, 0x01 };
     64 
     65 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_L3) && \
     66          (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT))
     67 
     68 #define PKT_SIZE_PARAM_DEFAULT 0
     69 #define FLOOD_PKT_CNT_PARAM_DEFAULT 0
     70 #define RATE_CALC_INTERVAL_PARAM_DEFAULT 10
     71 #define RATE_TOLERANCE_LR_PARAM_DEFAULT 1
     72 #define RATE_TOLERANCE_OV_PARAM_DEFAULT 3
     73 #define CHECK_PACKET_INTEGRITY_PARAM_DEFAULT 1
     74 #define MAX_NUM_CELLS_PARAM_DEFAULT 4
     75 #define IPV6_PARAM_DEFAULT 0
     76 #define SPEEDUP_FACTOR_PARAM_DEFAULT 1
     77 
     78 typedef struct l3uc_s {
     79     uint32 pkt_size_param;
     80     uint32 flood_pkt_cnt_param;
     81     uint32 rate_calc_interval_param;
     82     uint32 rate_tolerance_lr_param;
     83     uint32 rate_tolerance_ov_param;
     84     uint32 check_packet_integrity_param;
     85     uint32 max_num_cells_param;
     86     uint32 loopback_mode_param;
     87     uint32 scaling_factor_param;
     88     uint32 ipv6_param;
     89     uint32 dst_port[SOC_MAX_NUM_PORTS];
     90     uint32 bad_input;
     91     int test_fail;
     92     uint32 pkt_seed;
     93     uint32 **rand_pkt_sizes;
     94 } l3uc_t;
     95 
     96 static l3uc_t *l3uc_parray[SOC_MAX_NUM_DEVICES];
     97 /* static rate_calc_t *rate_calc_parray[SOC_MAX_NUM_DEVICES]; */
     98 
     99 const char l3uc_test_usage[] =
    100 #ifdef COMPILER_STRING_CONST_LIMIT
    101     "\nDocumentation too long to be displayed with -pedantic compiler\n";
    102 #else
    103     "L3UC test usage:\n"
    104     " \n"
    105     "PktSize:     Packet size in bytes. Set to 1 for random packet sizes.\n"
    106     "             Set to 0 (default) for worst case packet sizes on all ports\n"
    107     "             (145B for ENET, 76B for HG2).\n"
    108     "FloodCnt:    Number of packets swirl between each port pair.\n"
    109     "             Set to 0 (default) for a lossless swirl at full rate.\n"
    110     "RateCalcInt: Interval in seconds over which rate is to be calculated.\n"
    111     "TolLr:       Rate tolerance percentage for line rate ports.\n"
    112     "             (1 percentage by default)\n"
    113     "TolOv:       Rate tolerance percentage for oversubscribed ports.\n"
    114     "             (3 percentage by default).\n"
    115     "ChkPktInteg: Set to 0 to disable packet integrity checks.\n"
    116     "             Set to 1 to enable (default).\n"
    117     "MaxNumCells: Maximum number of cells for random packet sizes.\n"
    118     "             Set to 0 for random cell sizes. (default is 4)\n"
    119     "LoopbackMode: Loopback mode. Set to 1 for MAC loopback, 2 for PHY loopback.\n"
    120     "              (default is MAC loopback)\n"
    121     "IPv6:        Set to 1 to send IPv6 packets; 0 to send IPv4 (default).\n"
    122     ;
    123 #endif
    124 
    125 
    126 /*
    127  * Function:
    128  *      l3uc_parse_test_params
    129  * Purpose:
    130  *      Parse CLI parameters, create test structure and flag bad inputs.
    131  * Parameters:
    132  *      unit - StrataSwitch Unit #.
    133  *      a - Pointer to arguments
    134  *
    135  * Returns:
    136  *     Nothing
    137  * Notes:
    138  *      l3uc_p->bad_input set from here - tells test to crash out in case
    139  *      CLI input combination is invalid.
    140  */
    141 static void
    142 l3uc_parse_test_params(int unit, args_t *a)
    143 {
    144     parse_table_t parse_table;
    145     l3uc_t *l3uc_p = l3uc_parray[unit];
    146     uint32 min_pkt_size = l3uc_p->ipv6_param ? MIN_IPV6_PKT_SIZE : MIN_PKT_SIZE;
    147 
    148     /* default parameter value */
    149     l3uc_p->bad_input = 0;
    150     l3uc_p->pkt_size_param = PKT_SIZE_PARAM_DEFAULT;
    151     l3uc_p->flood_pkt_cnt_param = FLOOD_PKT_CNT_PARAM_DEFAULT;
    152     l3uc_p->rate_calc_interval_param = RATE_CALC_INTERVAL_PARAM_DEFAULT;
    153     l3uc_p->rate_tolerance_lr_param = RATE_TOLERANCE_LR_PARAM_DEFAULT;
    154     l3uc_p->rate_tolerance_ov_param = RATE_TOLERANCE_OV_PARAM_DEFAULT;
    155     l3uc_p->check_packet_integrity_param
    156                             = CHECK_PACKET_INTEGRITY_PARAM_DEFAULT;
    157     l3uc_p->max_num_cells_param = MAX_NUM_CELLS_PARAM_DEFAULT;
    158     l3uc_p->loopback_mode_param = BCM_PORT_LOOPBACK_MAC;
    159     l3uc_p->ipv6_param = IPV6_PARAM_DEFAULT;
    160     l3uc_p->scaling_factor_param = SPEEDUP_FACTOR_PARAM_DEFAULT;
    161 
    162     /*Parse CLI opts */
    163     parse_table_init(unit, &parse_table);
    164     parse_table_add(&parse_table, "PktSize", PQ_INT|PQ_DFL, 0,
    165                     &(l3uc_p->pkt_size_param), NULL);
    166     parse_table_add(&parse_table, "FloodCnt", PQ_INT|PQ_DFL, 0,
    167                     &(l3uc_p->flood_pkt_cnt_param), NULL);
    168     parse_table_add(&parse_table, "RateCalcInt", PQ_INT|PQ_DFL, 0,
    169                     &(l3uc_p->rate_calc_interval_param), NULL);
    170     parse_table_add(&parse_table, "TolLr", PQ_INT|PQ_DFL, 0,
    171                     &(l3uc_p->rate_tolerance_lr_param), NULL);
    172     parse_table_add(&parse_table, "TolOv", PQ_INT|PQ_DFL, 0,
    173                     &(l3uc_p->rate_tolerance_ov_param), NULL);
    174     parse_table_add(&parse_table, "ChkPktInteg", PQ_INT|PQ_DFL, 0,
    175                     &(l3uc_p->check_packet_integrity_param), NULL);
    176     parse_table_add(&parse_table, "MaxNumCells", PQ_INT|PQ_DFL, 0,
    177                     &(l3uc_p->max_num_cells_param), NULL);
    178     parse_table_add(&parse_table, "LoopbackMode", PQ_INT|PQ_DFL, 0,
    179                     &l3uc_p->loopback_mode_param, NULL);
    180     parse_table_add(&parse_table, "IPv6", PQ_INT|PQ_DFL, 0,
    181                     &(l3uc_p->ipv6_param), NULL);
    182     parse_table_add(&parse_table, "ScalingFactor", PQ_INT|PQ_DFL, 0,
    183                     &(l3uc_p->scaling_factor_param), NULL);
    184 
    185     if (parse_arg_eq(a, &parse_table) < 0 || ARG_CNT(a) != 0) {
    186         cli_out("%s", l3uc_test_usage);
    187         test_error(unit, "\n*ERROR PARSING ARGS\n");
    188     }
    189 
    190     cli_out("\n");
    191     cli_out("------------- PRINTING TEST PARAMS ------------------\n");
    192     cli_out("PktSize      = %0d\n", l3uc_p->pkt_size_param);
    193     cli_out("RateCalcInt  = %0d\n", l3uc_p->rate_calc_interval_param);
    194     cli_out("FloodCnt     = %0d\n", l3uc_p->flood_pkt_cnt_param);
    195     cli_out("TolLr        = %0d\n", l3uc_p->rate_tolerance_lr_param);
    196     cli_out("TolOv        = %0d\n", l3uc_p->rate_tolerance_ov_param);
    197     cli_out("ChkPktInteg  = %0d\n", l3uc_p->check_packet_integrity_param);
    198     cli_out("MaxNumCells  = %0d\n", l3uc_p->max_num_cells_param);
    199     cli_out("LoopbackMode = %0d\n", l3uc_p->loopback_mode_param);
    200     cli_out("IPv6         = %0d\n", l3uc_p->ipv6_param);
    201     cli_out("ScalingFactor= %0d\n", l3uc_p->scaling_factor_param);
    202     cli_out("-----------------------------------------------------\n");
    203 
    204     if (l3uc_p->max_num_cells_param == 0) {
    205         /* coverity[dont_call : FALSE] */
    206         l3uc_p->max_num_cells_param = (sal_rand() % (MTU_CELL_CNT - 1)) + 1;
    207     }
    208 
    209     if (l3uc_p->pkt_size_param == 0) {
    210         cli_out
    211             ("\nUsing worst case packet sizes - 145B for Ethernet "
    212              "and 76B (64B + 12B hg-hdr) for HG2");
    213     } else if (l3uc_p->pkt_size_param == 1) {
    214         cli_out("\nUsing random packet sizes");
    215     } else if (l3uc_p->pkt_size_param < min_pkt_size) {
    216         test_error(unit,"\n*ERROR: Packet size cannot be lower than %0dB\n",
    217                 min_pkt_size);
    218         l3uc_p->bad_input = 1;
    219     } else if (l3uc_p->pkt_size_param > MTU) {
    220         test_error(unit,"\n*ERROR: Packet size higher than %0dB (Device MTU)\n",
    221                 MTU);
    222         l3uc_p->bad_input = 1;
    223     }
    224 
    225     if (l3uc_p->flood_pkt_cnt_param == 0) {
    226         cli_out("\nFloodCnt=0, test will automatically calculate number of"
    227                 " packets to flood each port");
    228     }
    229 }
    230 
    231 /*
    232  * Function:
    233  *      l3uc_set_port_property
    234  * Purpose:
    235  *      Set rand_pkt_sizes arrays.
    236  * Parameters:
    237  *      unit: StrataSwitch Unit #.
    238  *      pbmp - Device port bitmap
    239  *      pkt_size_param - Packet size in bytes
    240  *      max_num_cells_param - Maximum number of cells
    241  *
    242  * Returns:
    243  *     Nothing
    244  */
    245 static void
    246 l3uc_set_port_property(int unit, pbmp_t pbmp, int pkt_size_param,
    247                          int max_num_cells_param)
    248 {
    249     int p, j;
    250     uint32 pkt_size;
    251     l3uc_t *l3uc_p = l3uc_parray[unit];
    252 
    253     l3uc_p->rand_pkt_sizes =
    254         (uint32 **) sal_alloc(SOC_MAX_NUM_PORTS * sizeof(uint32 *),
    255                               "rand_pkt_sizes_array*");
    256 
    257     for (p = 0; p < SOC_MAX_NUM_PORTS; p++) {
    258         l3uc_p->rand_pkt_sizes[p] =
    259             (uint32 *) sal_alloc(TARGET_CELL_COUNT * sizeof(uint32),
    260                                 "rand_pkt_sizes_array");
    261     }
    262 
    263     PBMP_ITER(pbmp, p) {
    264         if (p < SOC_MAX_NUM_PORTS) {
    265             for (j = 0; j < TARGET_CELL_COUNT; j++) {
    266                 do {
    267                     /* coverity[dont_call : FALSE] */
    268                     pkt_size = (sal_rand() % (MTU - MIN_PKT_SIZE + 1)) +
    269                                MIN_PKT_SIZE;
    270                 } while (stream_get_pkt_cell_cnt(unit, pkt_size, p) >
    271                          max_num_cells_param);
    272                 l3uc_p->rand_pkt_sizes[p][j] = pkt_size;
    273             }
    274         }
    275     }
    276 }
    277 
    278 /*
    279  * Function:
    280  *      l3uc_set_up_ports
    281  * Purpose:
    282  *      Enable port bridging and HiGig lookup for HG2 ports
    283  * Parameters:
    284  *      unit - StrataSwitch Unit #.
    285  *      pbmp - Device port bitmap
    286  *
    287  * Returns:
    288  *     Nothing
    289  */
    290 static void
    291 l3uc_set_up_ports(int unit, pbmp_t pbmp)
    292 {
    293     int i, p;
    294     lport_tab_entry_t lport_tab_entry;
    295     port_tab_entry_t port_tab_entry;
    296     soc_field_t ihg_lookup_fields[] = {
    297         HYBRID_MODE_ENABLEf,
    298         USE_MH_PKT_PRIf,
    299         USE_MH_VIDf,
    300         HG_LOOKUP_ENABLEf,
    301         REMOVE_MH_SRC_PORTf
    302     };
    303     uint32 ihg_lookup_values[] = { 0x0, 0x1, 0x1, 0x1, 0x0 };
    304 
    305     cli_out("\nEnabling HG_LOOKUP on HG ports");
    306     if (SOC_REG_IS_VALID(unit, IHG_LOOKUPr)) {
    307         PBMP_ITER(pbmp, p) {
    308             if (p < SOC_MAX_NUM_PORTS && IS_HG_PORT(unit, p)) {
    309                 soc_reg_fields32_modify(unit, IHG_LOOKUPr, p, 5,
    310                                         ihg_lookup_fields, ihg_lookup_values);
    311             }
    312         }
    313     } else {
    314         cli_out("\n*ERROR, invalid reg %s\n", SOC_REG_NAME(unit, IHG_LOOKUPr));
    315     }
    316 
    317     cli_out("\nEnabling Port bridging");
    318     if (SOC_MEM_IS_VALID(unit, LPORT_TABm)) {
    319         for (i = 0; i < soc_mem_index_max(unit, LPORT_TABm); i++) {
    320             (void) soc_mem_read(unit, LPORT_TABm, COPYNO_ALL, i,
    321                          lport_tab_entry.entry_data);
    322             soc_mem_field32_set(unit, LPORT_TABm, lport_tab_entry.entry_data,
    323                                 ALLOW_SRC_MODf, 0x1);
    324             soc_mem_field32_set(unit, LPORT_TABm, lport_tab_entry.entry_data,
    325                                 PORT_BRIDGEf, 0x1);
    326             (void) soc_mem_write(unit, LPORT_TABm, COPYNO_ALL, i,
    327                           lport_tab_entry.entry_data);
    328         }
    329     } else {
    330         cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, LPORT_TABm));
    331     }
    332 
    333     if (SOC_MEM_IS_VALID(unit, PORT_TABm)) {
    334         for (i = 0; i < soc_mem_index_max(unit, PORT_TABm); i++) {
    335             (void) soc_mem_read(unit, PORT_TABm, COPYNO_ALL, i,
    336                          port_tab_entry.entry_data);
    337             soc_mem_field32_set(unit, PORT_TABm, port_tab_entry.entry_data,
    338                                 PORT_BRIDGEf, 0x1);
    339             (void) soc_mem_write(unit, PORT_TABm, COPYNO_ALL, i,
    340                               port_tab_entry.entry_data);
    341         }
    342     } else {
    343         cli_out("\n*ERROR, invalid mem %s\n", SOC_MEM_NAME(unit, PORT_TABm));
    344     }
    345 }
    346 
    347 /*
    348  * Function:
    349  *      l3uc_lossless_flood_cnt
    350  * Purpose:
    351  *      Calculates number of packets that need to be sent to a port for a
    352  *      lossless swirl.
    353  * Parameters:
    354  *      unit - StrataSwitch Unit #.
    355  *      pkt_size : Packet size in bytes
    356  *      port: Test port no
    357  * Returns:
    358  *     Number of packets needed for lossless flooding
    359  */
    360 static uint32
    361 l3uc_lossless_flood_cnt(int unit, int port)
    362 {
    363     uint32 pkt_size, flood_cnt = 0;
    364     int param_flood_cnt, param_pkt_size;
    365     l3uc_t *l3uc_p = l3uc_parray[unit];
    366 
    367     param_flood_cnt = l3uc_p->flood_pkt_cnt_param;
    368     param_pkt_size = l3uc_p->pkt_size_param;
    369 
    370     if (param_flood_cnt == 0) {
    371         if (param_pkt_size == 0) {           
    372             pkt_size = stream_get_wc_pkt_size(unit, IS_HG_PORT(unit, port));
    373         } else {
    374             pkt_size = param_pkt_size;
    375         }
    376         flood_cnt = stream_get_ll_flood_cnt(unit, port, pkt_size, NULL);
    377     } else {
    378         flood_cnt = param_flood_cnt;
    379     }
    380 
    381     return (flood_cnt);
    382 }
    383 
    384 /*
    385  * Function:
    386  *      l3uc_set_up_streams
    387  * Purpose:
    388  *      VLAN programming for l3uc. Each port is put on an unique VLAN.
    389  * Parameters:
    390  *      unit: StrataSwitch Unit #.
    391  *
    392  * Returns:
    393  *     BCM_E_XXXX
    394  */
    395 static bcm_error_t
    396 l3uc_set_up_streams(int unit)
    397 {
    398     int p, j;
    399     int src_port, dst_port;
    400     int l2_id;
    401     pbmp_t pbm, ubm;
    402     bcm_l2_station_t l2_station;
    403     bcm_l3_intf_t l3_intf;
    404     bcm_l3_egress_t l3_egress;
    405     bcm_if_t egr_obj_id;
    406     bcm_l3_host_t l3_host;
    407     bcm_field_qset_t f_qset;
    408     bcm_field_group_t f_group;
    409     bcm_field_entry_t f_entry;
    410     l3uc_t *l3uc_p = l3uc_parray[unit];
    411     bcm_mac_t nhop_mac = MAC_DA;
    412     bcm_mac_t router_mac = MAC_SA;
    413     bcm_vlan_t vlan = VLAN;
    414     bcm_ip_t ipv4_da = IPV4_ADDR;
    415     bcm_ip6_t ipv6_da = IPV6_ADDR;
    416 
    417     BCM_PBMP_CLEAR(ubm);
    418     BCM_IF_ERROR_RETURN(bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1));
    419     BCM_IF_ERROR_RETURN(bcm_port_control_set(unit, 0, bcmPortControlIP4, 1));
    420     BCM_IF_ERROR_RETURN(bcm_port_control_set(unit, 0, bcmPortControlIP6, 1));
    421     BCM_IF_ERROR_RETURN(bcm_field_init(unit));
    422     BCM_FIELD_QSET_INIT(f_qset);
    423     BCM_FIELD_QSET_ADD(f_qset, bcmFieldQualifyOuterVlanId);
    424     BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, f_qset,
    425                                                BCM_FIELD_GROUP_PRIO_ANY,
    426                                                &f_group));
    427 
    428     PBMP_ITER(PBMP_E_ALL(unit), p) {
    429         if (p < SOC_MAX_NUM_PORTS) {
    430             src_port = p;
    431             dst_port = l3uc_p->dst_port[p];
    432             nhop_mac[2] = dst_port;
    433             router_mac[2] = src_port;
    434             vlan = VLAN + src_port;
    435             ipv4_da = IPV4_ADDR | (src_port << 8);
    436             ipv6_da[14] = src_port;
    437 
    438             /* Create VLAN */
    439             BCM_IF_ERROR_RETURN(bcm_vlan_create(unit, vlan));
    440             BCM_PBMP_CLEAR(pbm);
    441             BCM_PBMP_PORT_ADD(pbm, src_port);
    442             BCM_IF_ERROR_RETURN(bcm_vlan_port_add(unit, vlan, pbm, ubm));
    443 
    444             /* Add L2 Station */
    445             bcm_l2_station_t_init(&l2_station);
    446             sal_memcpy(l2_station.dst_mac, nhop_mac, 6);
    447             sal_memcpy(l2_station.dst_mac_mask, "ff:ff:ff:ff:ff:ff", 6);
    448             l2_station.vlan = vlan;
    449             l2_station.vlan_mask = 0xfff;
    450             l2_station.flags |= BCM_L2_STATION_IPV4 | BCM_L2_STATION_IPV6;
    451             BCM_IF_ERROR_RETURN(bcm_l2_station_add(unit, &l2_id, &l2_station));
    452             LOG_INFO(BSL_LS_APPL_TESTS,
    453                      (BSL_META_U(unit, "\nAdded L2 Station: ")));
    454             LOG_INFO(BSL_LS_APPL_TESTS,
    455                      (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, vlan 0x%x"),
    456                                  l2_station.dst_mac[5], l2_station.dst_mac[4],
    457                                  l2_station.dst_mac[3], l2_station.dst_mac[2],
    458                                  l2_station.dst_mac[1], l2_station.dst_mac[0],
    459                                  l2_station.vlan));
    460 
    461             /* Create L3 Interfaces */
    462             bcm_l3_intf_t_init(&l3_intf);
    463             l3_intf.l3a_flags |= BCM_L3_ADD_TO_ARL;
    464             sal_memcpy(l3_intf.l3a_mac_addr, router_mac, 6);
    465             l3_intf.l3a_vid = vlan;
    466             BCM_IF_ERROR_RETURN(bcm_l3_intf_create(unit, &l3_intf));
    467             LOG_INFO(BSL_LS_APPL_TESTS,
    468                      (BSL_META_U(unit, "\nAdded L3 Interface: intf %0d, "),
    469                                  l3_intf.l3a_intf_id));
    470             LOG_INFO(BSL_LS_APPL_TESTS,
    471                      (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, vlan 0x%x"),
    472                                  l3_intf.l3a_mac_addr[5], l3_intf.l3a_mac_addr[4],
    473                                  l3_intf.l3a_mac_addr[3], l3_intf.l3a_mac_addr[2],
    474                                  l3_intf.l3a_mac_addr[1], l3_intf.l3a_mac_addr[0],
    475                                  l3_intf.l3a_vid));
    476 
    477             /* Create Next Hop Egress Object */
    478             bcm_l3_egress_t_init(&l3_egress);
    479             sal_memcpy(l3_egress.mac_addr, nhop_mac, 6);
    480             l3_egress.intf = l3_intf.l3a_intf_id;
    481             l3_egress.port = src_port;
    482             BCM_IF_ERROR_RETURN(bcm_l3_egress_create(unit, 0, &l3_egress,
    483                                                      &egr_obj_id));
    484             LOG_INFO(BSL_LS_APPL_TESTS,
    485                      (BSL_META_U(unit, "\nAdded L3 Next Hop: nhop_id %0d, intf %0d, "),
    486                                  egr_obj_id, l3_egress.intf));
    487             LOG_INFO(BSL_LS_APPL_TESTS,
    488                      (BSL_META_U(unit, "mac %2x:%2x:%2x:%2x:%2x:%2x, port %0d"),
    489                                  l3_egress.mac_addr[5], l3_egress.mac_addr[4],
    490                                  l3_egress.mac_addr[3], l3_egress.mac_addr[2],
    491                                  l3_egress.mac_addr[1], l3_egress.mac_addr[0],
    492                                  l3_egress.port));
    493 
    494             /* Associate IP Address with Egress Object */
    495             bcm_l3_host_t_init(&l3_host);
    496             if (l3uc_p->ipv6_param) {
    497                 l3_host.l3a_flags = BCM_L3_IP6;
    498                 sal_memcpy(l3_host.l3a_ip6_addr, ipv6_da, 16);
    499             } else {
    500                 l3_host.l3a_ip_addr = ipv4_da;
    501             }
    502             l3_host.l3a_intf = egr_obj_id;
    503             BCM_IF_ERROR_RETURN(bcm_l3_host_add(unit, &l3_host));
    504             LOG_INFO(BSL_LS_APPL_TESTS,
    505                      (BSL_META_U(unit, "\nAdded L3 Table: nhop_id %0d, ip "),
    506                                  egr_obj_id));
    507             if (l3uc_p->ipv6_param) {
    508                 for (j = 0; j < 16; j++) {
    509                     LOG_INFO(BSL_LS_APPL_TESTS,
    510                              (BSL_META_U(unit, "%0d."),
    511                                          l3_host.l3a_ip6_addr[j]));
    512                 }
    513             } else {
    514                 LOG_INFO(BSL_LS_APPL_TESTS,
    515                          (BSL_META_U(unit, "%0d.%0d.%0d.%0d"),
    516                                      (l3_host.l3a_ip_addr) >> 24 & 0xff,
    517                                      (l3_host.l3a_ip_addr) >> 16 & 0xff,
    518                                      (l3_host.l3a_ip_addr) >> 8 & 0xff,
    519                                      l3_host.l3a_ip_addr & 0xff));
    520             }
    521 
    522             /* Program FP to L3 Switch */
    523             {
    524                 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, f_group, &f_entry));
    525                 BCM_IF_ERROR_RETURN(bcm_field_qualify_OuterVlanId(unit, f_entry,
    526                                                            VLAN + dst_port, 0xfff));
    527                 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, f_entry,
    528                                                          bcmFieldActionL3Switch,
    529                                                          egr_obj_id, 0));
    530                 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, f_entry));
    531                 LOG_INFO(BSL_LS_APPL_TESTS,
    532                          (BSL_META_U(unit, "\nAdded FP L3 Switch vlan 0x%x to "),
    533                                      VLAN + dst_port));
    534                 LOG_INFO(BSL_LS_APPL_TESTS,
    535                          (BSL_META_U(unit, "nhop_id %0d\n"), egr_obj_id));
    536             }
    537         }
    538     }
    539 
    540     return BCM_E_NONE;
    541 }
    542 
    543 /*
    544  * Function:
    545  *      l3uc_send_pkts
    546  * Purpose:
    547  *      Send packets to flood VLANs and create a swirl on each port.
    548  * Parameters:
    549  *      unit - StrataSwitch Unit #.
    550  *
    551  * Returns:
    552  *     Nothing
    553  */
    554 static void
    555 l3uc_send_pkts(int unit)
    556 {
    557     uint8 mac_da[] = MAC_DA;
    558     uint8 mac_sa[] = MAC_SA;
    559     int port, i = 0;
    560     uint32 pkt_size = 0,  pkt_count = 0, flood_cnt = 0;
    561     uint8 src_port;
    562     uint8 dst_port;
    563     uint32 use_random_packet_sizes = 0;
    564     l3uc_t *l3uc_p = l3uc_parray[unit];
    565     stream_pkt_t *tx_pkt;
    566 
    567     tx_pkt = sal_alloc(sizeof(stream_pkt_t), "tx_pkt");
    568     sal_memset(tx_pkt, 0, sizeof(stream_pkt_t));
    569 
    570     if (l3uc_p->pkt_size_param == 1) {
    571         use_random_packet_sizes = 1;
    572     }
    573 
    574     cli_out("\n==================================================\n");
    575     cli_out("\nSending packets ...\n\n");
    576     PBMP_ITER(PBMP_E_ALL(unit), port) {
    577         if (port < SOC_MAX_NUM_PORTS) {
    578             i++;
    579             src_port = port;
    580             dst_port = l3uc_p->dst_port[port];
    581             if (i % 2 == 0) {
    582                 flood_cnt = 0;
    583                 continue;
    584             } else {
    585                 flood_cnt = l3uc_lossless_flood_cnt(unit, port);
    586             }
    587 
    588             if (l3uc_p->pkt_size_param == 0) {
    589                 pkt_size = stream_get_wc_pkt_size(unit, IS_HG_PORT(unit, port));
    590             } else {
    591                 pkt_size = l3uc_p->pkt_size_param;
    592             }
    593 
    594             tx_pkt->port = port;
    595             tx_pkt->num_pkt = flood_cnt;
    596             tx_pkt->pkt_seed = l3uc_p->pkt_seed + port;
    597             tx_pkt->pkt_size = pkt_size;
    598             tx_pkt->rand_pkt_size_en = use_random_packet_sizes;
    599             tx_pkt->rand_pkt_size = NULL;
    600             tx_pkt->tx_vlan = VLAN + src_port;
    601             sal_memcpy(tx_pkt->mac_da, mac_da, NUM_BYTES_MAC_ADDR);
    602             sal_memcpy(tx_pkt->mac_sa, mac_sa, NUM_BYTES_MAC_ADDR);
    603             tx_pkt->mac_da[2] = dst_port;
    604             tx_pkt->mac_sa[2] = src_port;
    605             if (tx_pkt->rand_pkt_size_en) {
    606                 tx_pkt->rand_pkt_size = l3uc_p->rand_pkt_sizes[port];
    607             }
    608             tx_pkt->l3_en   = 1;
    609             tx_pkt->ipv6_en = l3uc_p->ipv6_param;
    610             tx_pkt->ip_da   = IPV4_ADDR | (dst_port << 8);
    611             tx_pkt->ip_sa   = IPV4_ADDR | (src_port << 8);
    612             tx_pkt->ttl     = TTL;
    613             stream_tx_pkt(unit, tx_pkt);
    614 
    615             /* print */
    616             cli_out("flood_cnt for stream %0d = %0d\n", i/2, tx_pkt->cnt_pkt);
    617             pkt_count += tx_pkt->cnt_pkt;
    618         }
    619     }
    620     cli_out("\nTotal packet sent: %d\n\n", pkt_count);
    621     sal_free(tx_pkt);
    622 }
    623 
    624 /*
    625  * Function:
    626  *      l3uc_chk_port_rate
    627  * Purpose:
    628  *      Check actual port rates against expected port rates.
    629  * Parameters:
    630  *      unit - StrataSwitch Unit #.
    631  *
    632  * Returns:
    633  *     SOC_E_XXXX
    634  */
    635 static bcm_error_t
    636 l3uc_chk_port_rate(int unit)
    637 {
    638     int port;
    639     bcm_error_t rv = BCM_E_NONE;
    640     stream_rate_t *rate_calc;
    641     l3uc_t *l3uc_p = l3uc_parray[unit];
    642 
    643     rate_calc = (stream_rate_t *)
    644                  sal_alloc(sizeof(stream_rate_t), "rate_calc");
    645     if (rate_calc == NULL) {
    646         test_error(unit, "Failed to allocate memory for rate_calc\n");
    647         return BCM_E_FAIL;
    648     }
    649     sal_memset(rate_calc, 0, sizeof(stream_rate_t));
    650 
    651     rate_calc->mode         = 0; /* check act_rate against config_rate */
    652     rate_calc->pkt_size     = l3uc_p->pkt_size_param;
    653     rate_calc->interval_len = l3uc_p->rate_calc_interval_param;
    654     rate_calc->tolerance_lr = l3uc_p->rate_tolerance_lr_param;
    655     rate_calc->tolerance_os = l3uc_p->rate_tolerance_ov_param;
    656     rate_calc->scaling_factor = l3uc_p->scaling_factor_param;
    657 
    658     SOC_PBMP_CLEAR(rate_calc->pbmp);
    659     PBMP_ITER(PBMP_E_ALL(unit), port) {
    660         if (port < SOC_MAX_NUM_PORTS) {
    661             SOC_PBMP_PORT_ADD(rate_calc->pbmp, port);
    662         }
    663     }
    664 
    665     rv = stream_chk_port_rate(unit, PBMP_PORT_ALL(unit), rate_calc);
    666 
    667     sal_free(rate_calc);
    668     return rv;
    669 }
    670 
    671 /*
    672  * Function:
    673  *      l3uc_chk_pkt_integrity
    674  * Purpose:
    675  *      Redirect all packets back to CPU and check packet integrity
    676  * Parameters:
    677  *      unit - StrataSwitch Unit #.
    678  *
    679  * Returns:
    680  *     Nothing
    681  */
    682 static bcm_error_t
    683 l3uc_chk_pkt_integrity(int unit)
    684 {
    685     int idx = 0, port, dst_port, src_port, is_even;
    686     int param_pkt_seed;
    687     uint32 flood_cnt;
    688     uint8 mac_da[] = MAC_DA;
    689     uint8 mac_sa[] = MAC_SA;
    690     stream_integrity_t *pkt_intg;
    691     bcm_error_t rv = BCM_E_NONE;
    692     l3uc_t *l3uc_p = l3uc_parray[unit];
    693 
    694     param_pkt_seed = l3uc_p->pkt_seed;
    695 
    696     pkt_intg = sal_alloc(sizeof(stream_integrity_t), "pkt_intg");
    697     if (pkt_intg == NULL) {
    698         test_error(unit, "Failed to allocate memory for pkt_intg\n");
    699         return BCM_E_FAIL;
    700     }
    701     sal_memset(pkt_intg, 0, sizeof(stream_integrity_t));
    702 
    703     pkt_intg->type = PKT_TYPE_L3UC;
    704     pkt_intg->ipv6_en = (l3uc_p->ipv6_param > 0) ? 1 : 0;
    705     SOC_PBMP_CLEAR(pkt_intg->rx_pbmp);
    706     PBMP_ITER(PBMP_E_ALL(unit), port) {
    707         if (port < SOC_MAX_NUM_PORTS) {
    708             is_even = (idx % 2 == 0) ? (1) : (0);
    709             src_port = port;
    710             dst_port = l3uc_p->dst_port[port];
    711             /* rx_pbmp */
    712             if (is_even == 1) {
    713                 SOC_PBMP_PORT_ADD(pkt_intg->rx_pbmp, port);
    714             }
    715             /* rx_vlan: used to forward pkt to CPU */
    716             pkt_intg->rx_vlan[port] = VLAN + dst_port;
    717             /* tx_vlan: used to re-generate ref_pkt */
    718             pkt_intg->tx_vlan[port] = VLAN + src_port;
    719             /* port_flood_cnt */
    720             if (is_even) {
    721                 flood_cnt = l3uc_lossless_flood_cnt(unit, port);
    722             } else {
    723                 flood_cnt = 0;
    724             }
    725             pkt_intg->port_flood_cnt[port] = flood_cnt;
    726             /* port_pkt_seed */
    727             pkt_intg->port_pkt_seed[port] = param_pkt_seed + port;
    728             /* mac_da, mac_sa */
    729             mac_da[2] = dst_port;
    730             mac_sa[2] = src_port;
    731             sal_memcpy(pkt_intg->mac_da[port], mac_da, NUM_BYTES_MAC_ADDR);
    732             sal_memcpy(pkt_intg->mac_sa[port], mac_sa, NUM_BYTES_MAC_ADDR);
    733             /* ip_da, ip_sa */
    734             pkt_intg->ip_da[port] = IPV4_ADDR | (dst_port << 8);
    735             pkt_intg->ip_sa[port] = IPV4_ADDR | (src_port << 8);
    736 
    737             idx++;
    738         }
    739     }
    740 
    741     if (stream_chk_pkt_integrity(unit, pkt_intg) != BCM_E_NONE) {
    742         rv = BCM_E_FAIL;
    743     }
    744 
    745     sal_free(pkt_intg);
    746     return rv;
    747 }
    748 
    749 /*
    750  * Function:
    751  *      l3uc_test_init
    752  * Purpose:
    753  *      Test init function. Parse CLI params and do necessary init.
    754  * Parameters:
    755  *      unit - StrataSwitch Unit #.
    756  *
    757  * Returns:
    758  *     Nothing
    759  */
    760 int
    761 l3uc_test_init(int unit, args_t *a, void **pa)
    762 {
    763     int i, p, src_port;
    764     l3uc_t *l3uc_p;
    765 
    766     l3uc_p = l3uc_parray[unit];
    767     l3uc_p = sal_alloc(sizeof(l3uc_t), "l3uc_test");
    768     sal_memset(l3uc_p, 0, sizeof(l3uc_t));
    769     l3uc_parray[unit] = l3uc_p;
    770 
    771     cli_out("\nCalling l3uc_test_init");
    772     l3uc_parse_test_params(unit, a);
    773 
    774     for (p = 0; p < SOC_MAX_NUM_PORTS; p++) {
    775         l3uc_p->dst_port[p] = 0;
    776     }
    777 
    778     i = 0;
    779     src_port = 0;
    780     PBMP_ITER(PBMP_E_ALL(unit), p) {
    781         if (p < SOC_MAX_NUM_PORTS) {
    782             if (i % 2 == 0) {
    783                 src_port = p;
    784             } else {
    785                 l3uc_p->dst_port[src_port] = p;
    786                 l3uc_p->dst_port[p] = src_port;
    787             }
    788             i++;
    789         }
    790     }
    791 
    792     l3uc_p->test_fail = 0;
    793 
    794     return BCM_E_NONE;
    795 }
    796 
    797 
    798 /*
    799  * Function:
    800  *      l3uc_test
    801  * Purpose:
    802  *      Set up ports/streams and send packets.
    803  * Parameters:
    804  *      unit - StrataSwitch Unit #.
    805  *
    806  * Returns:
    807  *     Nothing
    808  */
    809 int
    810 l3uc_test(int unit, args_t *a, void *pa)
    811 {
    812     int rv = BCM_E_NONE;
    813     l3uc_t *l3uc_p = l3uc_parray[unit];
    814 
    815     if (l3uc_p->bad_input) {
    816         goto done;
    817     }
    818 
    819     cli_out("\nCalling l3uc_test");
    820 
    821     stream_set_lpbk(unit, PBMP_PORT_ALL(unit), l3uc_p->loopback_mode_param);
    822     stream_turn_off_cmic_mmu_bkp(unit);
    823     stream_turn_off_fc(unit, PBMP_PORT_ALL(unit));
    824     l3uc_p->pkt_seed = sal_rand();
    825     l3uc_set_port_property(unit, PBMP_PORT_ALL(unit), l3uc_p->pkt_size_param,
    826                              l3uc_p->max_num_cells_param);
    827     l3uc_set_up_ports(unit, PBMP_PORT_ALL(unit));
    828     l3uc_set_up_streams(unit);
    829     l3uc_send_pkts(unit);
    830 
    831     /* check counter */
    832     if (stream_chk_mib_counters(unit, PBMP_PORT_ALL(unit), 0) != BCM_E_NONE) {
    833         l3uc_p->test_fail = 1;
    834     }
    835     /* check rate */
    836     if (l3uc_chk_port_rate(unit) != BCM_E_NONE) {
    837         l3uc_p->test_fail = 1;
    838     }
    839     /* check integrity */
    840     if (l3uc_chk_pkt_integrity(unit) != BCM_E_NONE) {
    841         l3uc_p->test_fail = 1;
    842     }
    843 
    844 
    845 done:
    846     return rv;
    847 }
    848 
    849 
    850 /*
    851  * Function:
    852  *      l3uc_test_cleanup
    853  * Purpose:
    854  *      Do test end checks and free all allocated memory.
    855  * Parameters:
    856  *      unit - StrataSwitch Unit #.
    857  *
    858  * Returns:
    859  *     Nothing
    860  */
    861 int
    862 l3uc_test_cleanup(int unit, void *pa)
    863 {
    864     int i;
    865     bcm_error_t rv = BCM_E_NONE;
    866     l3uc_t *l3uc_p = l3uc_parray[unit];
    867 
    868     cli_out("\nCalling l3uc_test_cleanup");
    869 
    870     if (l3uc_p->bad_input == 1) {
    871         l3uc_p->test_fail = 1;
    872     }
    873     if (l3uc_p->test_fail == 1) {
    874         rv = BCM_E_FAIL;
    875     }
    876 
    877     cli_out("\n==================================================");
    878     cli_out("\n==================================================");
    879     if (l3uc_p->test_fail == 1) {
    880         cli_out("\n[L3UC test failed]\n\n");
    881     } else {
    882         cli_out("\n[L3UC test passed]\n\n");
    883     }
    884 
    885     /* free mem */
    886     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    887         sal_free(l3uc_p->rand_pkt_sizes[i]);
    888     }
    889     sal_free(l3uc_p->rand_pkt_sizes);
    890     sal_free(l3uc_p);
    891     bcm_vlan_init(unit);
    892     return rv;
    893 }
    894 #endif /* BCM_ESW_SUPPORT && INCLUDE_L3 */