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

l3.c (276820B)


      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  * L3 CLI commands
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <appl/diag/system.h>
     13 #include <appl/diag/parse.h>
     14 #include <appl/diag/dport.h>
     15 #include <appl/diag/shell.h>
     16 #include <appl/diag/bslcons.h>
     17 #include <shared/bsl.h>
     18 #include <soc/debug.h>
     19 #include <soc/hash.h>
     20 #if defined(BCM_TRIDENT2_SUPPORT)
     21 #include <soc/trident2.h>
     22 #endif /* BCM_TRIDENT2_SUPPORT */
     23 
     24 #ifdef ALPM_ENABLE
     25 #include <soc/alpm.h>
     26 #endif
     27 
     28 #include <bcm/error.h>
     29 #include <bcm/l3.h>
     30 #include <bcm/tunnel.h>
     31 #include <bcm/ipmc.h>
     32 #include <bcm/debug.h>
     33 #include <bcm/nat.h>
     34 
     35 #include <bcm_int/esw/l3.h>
     36 #include <bcm_int/esw/nat.h>
     37 #include <bcm_int/esw/katana.h>
     38 #include <bcm_int/common/multicast.h>
     39 #include <bcm_int/esw/port.h>
     40 
     41 #if defined(BCM_TRX_SUPPORT)
     42 #include <bcm_int/esw/trx.h>
     43 #include <bcm_int/esw/virtual.h>
     44 #endif /* BCM_TRX_SUPPORT */
     45 #if defined(BCM_TOMAHAWK3_SUPPORT)
     46 #include <bcm_int/esw/tomahawk3.h>
     47 #endif /* BCM_TOMAHAWK3_SUPPORT */
     48 
     49 #ifdef ALPM_ENABLE
     50 #include <bcm_int/esw/alpm.h>
     51 #include <bcm_int/esw/alpm_util.h>
     52 
     53 #endif
     54 
     55 #ifdef INCLUDE_L3
     56 #define ENV_EGRESS_OBJECT_ID "egr_object_id"
     57 
     58 #define L3X_MAX_BUCKET_SIZE     16
     59 #define L3X_BUCKET_SIZE(_u)     ((SOC_IS_RAVEN(_u) || SOC_IS_TR_VL(_u)) ? 16 : 8)
     60 #define L3X_IP_MULTICAST(_i)    (((uint32)(_i) & 0xf0000000) == 0xe0000000)
     61 
     62 /*
     63  * Function:
     64  *      _ipmc_cmd_entry_print
     65  * Description:
     66  *	Internal function to print out ipmc entry info
     67  * Parameters:
     68  *      unit   - device number.
     69  *	    info   - Pointer to bcm_ipmc_addr_t data structure.
     70  *      cookie - user cookie
     71  */
     72 STATIC int
     73 _ipmc_cmd_entry_print(int unit, bcm_ipmc_addr_t *info, void *cookie)
     74 {
     75     char s_ip_str[IP6ADDR_STR_LEN];
     76     char mc_ip_str[IP6ADDR_STR_LEN];
     77 
     78     /* Input parameters check. */
     79     if (NULL == info) {
     80         return (BCM_E_PARAM);
     81     }
     82 
     83     /* Print IPMC entry. */
     84     if (info->flags & BCM_IPMC_IP6) {
     85         format_ip6addr(s_ip_str, info->s_ip6_addr);
     86         format_ip6addr(mc_ip_str, info->mc_ip6_addr);
     87         cli_out("SRC IP ADDRESS: %s\n", s_ip_str);
     88         cli_out("MC  IP ADDRESS: %s\n", mc_ip_str);
     89         cli_out("VLAN  MOD  PORT V COS  TS   ");
     90         cli_out("%s     %s     %s  %s  %s\n", "Group", "GroupL2", "VRF", "CLASS", "HIT");
     91         cli_out("%3d %4d %5d %2d %3d %3d   0x%x 0x%x %2d,%5d,%4s %6d\n",
     92                 info->vid, info->mod_id, info->port_tgid,
     93                 info->v, info->cos,
     94                 info->ts, info->group, info->group_l2,
     95                 info->vrf, info->lookup_class,
     96                 (info->flags & BCM_IPMC_HIT) ? "y" :"no", info->l3a_intf);
     97     } else {
     98         format_ipaddr(s_ip_str, info->s_ip_addr);
     99         format_ipaddr(mc_ip_str, info->mc_ip_addr);
    100         cli_out("%-16s%-16s%4d %3d %4d %3d %3d %2d   0x%x %3d\n",
    101                 s_ip_str, mc_ip_str, info->vid,
    102                 info->mod_id, info->port_tgid,
    103                 info->v, info->cos, info->ts, info->group,
    104                 info->vrf);
    105         cli_out("0x%x %d %6s %6d\n",
    106                 info->group_l2, info->lookup_class, (info->flags & BCM_IPMC_HIT) ? "y" :"no", info->l3a_intf);
    107 
    108     }
    109     return (BCM_E_NONE);
    110 }
    111 #if defined(BCM_XGS_SWITCH_SUPPORT)
    112 char if_ipmc_usage[] =
    113     "Usages:\n\t"
    114 #ifdef COMPILER_STRING_CONST_LIMIT
    115     "  ipmc <options> [arg...]\n"
    116 #else
    117     "  ipmc init    - Init ipmc function.\n\t"
    118     "  ipmc detach  - Detach ipmc function.\n\t"
    119     "  ipmc config [Enable=<bool>] [CheckSrcPort=<bool>] "
    120                                   "[CheckSrcIp=<bool>]\n\t"
    121     "  ipmc table add Src_IP=<ipaddr> Mc_IP=<grpaddr> VlanID=<vid>\n\t"
    122     "         Group=<val> [GroupL2=<val>] [src_Port=<port>] [COS=<cosl>]\n\t"
    123     "         [TS=<tsl>] [Valid=<bool>] [NoCHECK=<bool>]\n\t"
    124     "         [Replace=<bool>] [VRF=<vrf>] [LookupClass=<val>]\n\t"
    125     "              - Add an entry into ipmc table\n\t"
    126     "  ipmc table del Src_IP=<ipaddr> Mc_IP=<macaddr> VlanID=<vid>\n\t"
    127     "              - Destroy an entry in ipmc table\n\t"
    128     "  ipmc table clear\n\t"
    129     "              - Delete all ipmc table\n\t"
    130     "  ipmc table show [entry]\n\t"
    131     "              - Display all ipmc table or a single one\n\t"
    132     "  ipmc egr set Port=<port> Mac=<macaddr> Vlan=<vid>\n\t"
    133     "                    Untag=<untag> Ttl_thresh=<ttl threshold>\n\t"
    134     "              - set egress IP Multicast configuration regs for a port\n\t"
    135     "  ipmc egr show [<port>]\n\t"
    136     "              - Display egress IP Multicast configuration regs for\n\t"
    137     "                all ports or a single port\n\t"
    138     "  ipmc counter show [<port>]\n\t"
    139     "              - Display IP Multicast counter information\n\t"
    140     "  ipmc ip6table add Src_IP=<ipaddr> Mc_IP=<grpaddr> VlanID=<vid>\n\t"
    141     "         Group=<val> [src_Port=<port>] [COS=<cosl>]\n\t"
    142     "         [NoCHECK=<bool>] [TS=<tsl>]\n\t"
    143     "         [Valid=<bool>] [LookupClass=<val>]\n\t"
    144     "              - Add an entry into ipmc table\n\t"
    145     "  ipmc ip6table del Src_IP=<ipaddr> Mc_IP=<macaddr> VlanID=<vid>\n\t"
    146     "              - Destroy an entry in ipmc table\n\t"
    147     "  ipmc ip6table clear\n\t"
    148     "              - Delete all ipmc table\n\t"
    149     "  ipmc ip6table show [entry]\n\t"
    150     "              - Display all ipmc table or a single one\n"
    151 #endif
    152     ;
    153 
    154 cmd_result_t
    155 if_ipmc(int unit, args_t *a)
    156 {
    157     char *table, *subcmd_s, *argstr;
    158     int subcmd = 0;
    159     parse_table_t pt;
    160     cmd_result_t retCode;
    161     bcm_mac_t mac;
    162     vlan_id_t vid;
    163     int vlan = 0;
    164     int r, i, entry = 0, one_entry_only = 0;
    165     int dport, port = 0, ttl_th = 1, untag = 1;
    166     char mac_str[SAL_MACADDR_STR_LEN];
    167     bcm_ipmc_counters_t counters;
    168     bcm_ip_t s_ip_addr = 0, mc_ip_addr = 0;
    169     bcm_ipmc_addr_t ipmc_data;
    170     bcm_pbmp_t pbmp;
    171     bcm_port_config_t pcfg;
    172     int valid = 1, cos = 0, ts = 0, nocheck = 0, replace = 0, group = 0, group_l2 = 0;
    173     int lookup_class = 0;
    174     int cfg_enable = 1, cfg_check_src_port = 1, cfg_check_src_ip = 1;
    175 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    176     int vrf = 0;
    177     bcm_ip6_t       ip6_addr, sip6_addr;
    178 #endif
    179 
    180 #define IPMC_ADD 1
    181 #define IPMC_DEL 2
    182 #define IPMC_CLEAR 3
    183 #define IPMC_SHOW 4
    184 #define IPMC_SET 5
    185 
    186     sal_memset(mac, 0x10, 6);
    187     sal_memset(&ipmc_data, 0, sizeof(ipmc_data));
    188 
    189     /* Check valid device to operation on ...*/
    190     if (! sh_check_attached(ARG_CMD(a), unit)) {
    191 	return CMD_FAIL;
    192     }
    193 
    194     if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) {
    195         cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a));
    196         return CMD_FAIL;
    197     }
    198 
    199     if ((table = ARG_GET(a)) == NULL) {
    200 	return CMD_USAGE;
    201     }
    202 
    203     if (sal_strcasecmp(table, "init") == 0) {
    204 	if ((r = bcm_ipmc_init(unit)) < 0) {
    205 	    cli_out("%s: error initializing: %s\n", ARG_CMD(a), bcm_errmsg(r));
    206 	}
    207         return CMD_OK;
    208     }
    209     if (sal_strcasecmp(table, "detach") == 0) {
    210 	if ((r = bcm_ipmc_detach(unit)) < 0) {
    211 	    cli_out("%s: error detaching: %s\n", ARG_CMD(a), bcm_errmsg(r));
    212 	}
    213         return CMD_OK;
    214     }
    215 
    216     if (sal_strcasecmp(table, "config") == 0) {
    217 	parse_table_init(unit, &pt);
    218 	parse_table_add(&pt, "Enable", PQ_DFL|PQ_BOOL, 0,
    219 			(void *)&cfg_enable, 0);
    220 	parse_table_add(&pt, "CheckSrcPort", PQ_DFL|PQ_BOOL, 0,
    221 			(void *)&cfg_check_src_port, 0);
    222 	parse_table_add(&pt, "CheckSrcIp", PQ_DFL|PQ_BOOL, 0,
    223 			(void *)&cfg_check_src_ip, 0);
    224 	if (parse_arg_eq(a, &pt) < 0) {
    225 	    cli_out("%s: Error: Unknown option: %s\n",
    226                     ARG_CMD(a), ARG_CUR(a));
    227             parse_arg_eq_done(&pt);
    228 	    return CMD_FAIL;
    229 	}
    230 	i = CMD_OK;
    231 	if (pt.pt_entries[0].pq_type & PQ_PARSED) {
    232 	    r = bcm_ipmc_enable(unit, cfg_enable);
    233 	    if (r < 0) {
    234 		cli_out("%s: Error: Enable failed: %s\n",
    235                         ARG_CMD(a), bcm_errmsg(r));
    236 		i = CMD_FAIL;
    237 	    }
    238 	}
    239 	if (pt.pt_entries[1].pq_type & PQ_PARSED) {
    240             /* bcm_ipmc_source_port_check is deprecated */
    241 	    r = BCM_E_UNAVAIL;
    242 	    if (r < 0) {
    243 		cli_out("%s: Error: check_source_port failed: %s\n",
    244                         ARG_CMD(a), bcm_errmsg(r));
    245 		i = CMD_FAIL;
    246 	    }
    247 	}
    248 	if (pt.pt_entries[2].pq_type & PQ_PARSED) {
    249             /* bcm_ipmc_source_ip_search is deprecated */
    250 	    r = BCM_E_UNAVAIL;
    251 	    if (r < 0) {
    252 		cli_out("%s: Error: check_source_ip failed: %s\n",
    253                         ARG_CMD(a), bcm_errmsg(r));
    254 		i = CMD_FAIL;
    255 	    }
    256 	}
    257         parse_arg_eq_done(&pt);
    258 	return (i);
    259     }
    260 
    261     if ((subcmd_s = ARG_GET(a)) == NULL) {
    262 	return CMD_USAGE;
    263     }
    264 
    265     if (sal_strcasecmp(subcmd_s, "add") == 0) {
    266 	subcmd = IPMC_ADD;
    267     }
    268 
    269     if (sal_strcasecmp(subcmd_s, "del") == 0) {
    270 	subcmd = IPMC_DEL;
    271     }
    272 
    273     if (sal_strcasecmp(subcmd_s, "clear") == 0) {
    274 	subcmd = IPMC_CLEAR;
    275     }
    276 
    277     if (sal_strcasecmp(subcmd_s, "show") == 0) {
    278 	subcmd = IPMC_SHOW;
    279     }
    280 
    281     if (sal_strcasecmp(subcmd_s, "set") == 0) {
    282 	subcmd = IPMC_SET;
    283     }
    284 
    285     /*    coverity[equality_cond : FALSE]    */
    286     if (!subcmd) {
    287 	return CMD_USAGE;
    288     }
    289 
    290     if (sal_strcasecmp(table, "table") == 0) {
    291 	switch (subcmd) {
    292 	case IPMC_ADD:
    293 	    parse_table_init(unit, &pt);
    294 	    parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP, 0,
    295 			    (void *)&s_ip_addr, 0);
    296 	    parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP, 0,
    297 			    (void *)&mc_ip_addr, 0);
    298 	    parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0);
    299         parse_table_add(&pt, "COS", PQ_DFL|PQ_INT, 0, (void *)&cos, 0);
    300 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    301 		parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0,
    302 				(void *)&vrf, 0);
    303 #endif
    304 	    parse_table_add(&pt, "Valid", PQ_DFL|PQ_BOOL, 0,
    305 			    (void *)&valid, 0);
    306 	    parse_table_add(&pt, "src_Port", PQ_INT, 0, (void *)&port, 0);
    307 	    parse_table_add(&pt, "TS", PQ_INT, 0, (void *)&ts, 0);
    308 	    parse_table_add(&pt, "NoCHECK", PQ_DFL|PQ_BOOL, 0,
    309 			    (void *)&nocheck, 0);
    310 	    parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 0,
    311 			    (void *)&replace, 0);
    312         parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 0,
    313                             (void *)&lookup_class, 0);
    314         parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0,
    315                             (void *)&group, 0);
    316         parse_table_add(&pt, "GroupL2", PQ_DFL|PQ_INT, 0,
    317                             (void *)&group_l2, 0);
    318         if (parse_arg_eq(a, &pt) < 0) {
    319 	        cli_out("%s: Error: Unknown option: %s\n",
    320                         ARG_CMD(a), ARG_CUR(a));
    321             parse_arg_eq_done(&pt);
    322 	        return CMD_FAIL;
    323         }
    324         bcm_ipmc_addr_t_init(&ipmc_data);
    325         if (pt.pt_entries[3].pq_type & PQ_PARSED) {
    326             ipmc_data.flags |= BCM_IPMC_SETPRI;
    327 		}
    328         parse_arg_eq_done(&pt);		
    329 	    vid = vlan;
    330         ipmc_data.s_ip_addr = s_ip_addr;
    331         ipmc_data.mc_ip_addr = mc_ip_addr;
    332         ipmc_data.vid = vid;
    333 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    334         ipmc_data.vrf = vrf;
    335 #endif
    336 	    ipmc_data.cos = cos;
    337 	    ipmc_data.ts = ts;
    338 	    ipmc_data.port_tgid = port; 
    339 	    ipmc_data.v = valid;
    340 	    if (nocheck) {
    341 		ipmc_data.flags |= BCM_IPMC_SOURCE_PORT_NOCHECK;
    342 	    }
    343         if (replace) {
    344             ipmc_data.flags |= BCM_IPMC_REPLACE;
    345         }
    346         ipmc_data.lookup_class = lookup_class;
    347         if (group) {
    348             ipmc_data.group = group;
    349         }
    350         if (group_l2) {
    351             ipmc_data.group_l2 = group_l2;
    352         }
    353 	    r = bcm_ipmc_add(unit, &ipmc_data);
    354 	    if (r < 0) {
    355 		cli_out("%s: Error Add to ipmc table %s\n", ARG_CMD(a),
    356                         bcm_errmsg(r));
    357 		return CMD_FAIL;
    358 	    }
    359 	    return CMD_OK;
    360 	    break;
    361 	case IPMC_DEL:
    362 	    parse_table_init(unit, &pt);
    363 	    parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP, 0,
    364 			    (void *)&s_ip_addr, 0);
    365 	    parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP, 0,
    366 			    (void *)&mc_ip_addr, 0);
    367 	    parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0);
    368 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    369 		parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0,
    370 				(void *)&vrf, 0);
    371 #endif
    372 	    if (!parseEndOk( a, &pt, &retCode))
    373 		return retCode;
    374         bcm_ipmc_addr_t_init(&ipmc_data);
    375         ipmc_data.s_ip_addr = s_ip_addr;
    376         ipmc_data.mc_ip_addr = mc_ip_addr;
    377         ipmc_data.vid = vlan;
    378 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    379 	        ipmc_data.vrf = vrf;
    380 #endif
    381 	    r = bcm_ipmc_remove(unit, &ipmc_data);
    382 	    if (r < 0) {
    383 		cli_out("%s: Error delete from ipmc table %s\n", ARG_CMD(a),
    384                         bcm_errmsg(r));
    385 		return CMD_FAIL;
    386 	    }
    387 	    return CMD_OK;
    388 	    break;
    389 	case IPMC_CLEAR:
    390 	    r = bcm_ipmc_remove_all(unit);
    391 	    if (r < 0) {
    392 		cli_out("%s: %s\n",
    393                         ARG_CMD(a), bcm_errmsg(r));
    394 		return CMD_FAIL;
    395 	    }
    396 	    return (CMD_OK);
    397 	    break;
    398     case IPMC_SHOW:
    399         if (ARG_CNT(a)) {
    400             if (!isint(ARG_CUR(a))) {
    401                 cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a),
    402                         ARG_CUR(a));
    403                 return (CMD_FAIL);
    404             }
    405             entry = parse_integer(ARG_GET(a));
    406             if (entry == 0)
    407                 return (CMD_OK);
    408             if (_BCM_MULTICAST_IS_SET(entry) && _BCM_MULTICAST_IS_L3(entry)) {
    409                 entry = _BCM_MULTICAST_ID_GET(entry);
    410             }
    411             if (entry < soc_mem_index_min(unit, L3_IPMCm) ||
    412                 entry > soc_mem_index_max(unit, L3_IPMCm)) {
    413                 cli_out("%s: ERROR: Entry # too high, only permitted %d\n",
    414                         ARG_CMD(a), soc_mem_index_max(unit, L3_IPMCm));
    415                 return(CMD_FAIL);
    416             }
    417             one_entry_only = 1;
    418         }
    419 
    420         cli_out("SRC IP ADDRESS  MC IP ADDRESS     VLAN MOD PORT V COS ");
    421         cli_out("TS   GROUP     %s\n",
    422                 "VRF");
    423         cli_out("%s %s %s %s\n",
    424                 "GROUP-L2 ", "CLASS", "HIT", "L3_IIF");
    425         if (one_entry_only) {
    426             /* bcm_ipmc_get_by_index is deprecated */
    427             r = BCM_E_UNAVAIL;
    428             return CMD_OK;
    429         }
    430         bcm_ipmc_traverse(unit, 0, _ipmc_cmd_entry_print, NULL);
    431         return (CMD_OK);
    432         break;
    433 	default:
    434 	    return CMD_USAGE;
    435 	    break;
    436 	}
    437 	return CMD_OK;
    438     }
    439 
    440     if (sal_strcasecmp(table, "egr") == 0) {
    441 	switch (subcmd) {
    442 	case IPMC_SET:
    443 	    parse_table_init(unit, &pt);
    444 	    parse_table_add(&pt, "Port", PQ_PORT, 0, (void *)&port, 0);
    445 	    parse_table_add(&pt, "MAC", PQ_DFL|PQ_MAC, 0, (void *)mac, 0);
    446 	    parse_table_add(&pt, "Vlan", PQ_INT, 0, (void *)&vlan, 0);
    447 	    parse_table_add(&pt, "Untag", PQ_DFL|PQ_BOOL, 0, (void *)&untag,
    448 			    0);
    449 	    parse_table_add(&pt, "Ttl_thresh", PQ_DFL|PQ_INT, 0,
    450 			    (void *)&ttl_th, 0);
    451 	    if (!parseEndOk( a, &pt, &retCode))
    452 		return retCode;
    453 	    vid = vlan;
    454 	    r = bcm_ipmc_egress_port_set(unit, port, mac, untag, vid,
    455 					 ttl_th);
    456 	    if (r < 0) {
    457 		cli_out("%s: Egress IP Multicast Configuration registers: %s\n",
    458                         ARG_CMD(a), bcm_errmsg(r));
    459 		return CMD_FAIL;
    460 	    }
    461 	    break;
    462 
    463 	case IPMC_SHOW:
    464             if ((argstr  = ARG_GET(a)) == NULL) { 
    465                 pbmp = pcfg.e;
    466             } else {
    467 		if (parse_bcm_port(unit, argstr, &port) < 0) {
    468 		    cli_out("%s: Invalid port string: %s\n", ARG_CMD(a),
    469                             argstr);
    470 		    return CMD_FAIL;
    471 		}
    472 		if (!BCM_PBMP_MEMBER(pcfg.e, port)) {
    473 		    cli_out("port %d is not a valid Ethernet port\n", port);
    474 		    return CMD_FAIL;
    475 		}
    476                 BCM_PBMP_CLEAR(pbmp);
    477                 BCM_PBMP_PORT_ADD(pbmp, port);
    478 	    }
    479 	    cli_out("Egress IP Multicast Configuration Register information\n");
    480 	    cli_out("Port      Mac Address    Vlan Untag TTL_THRESH\n");
    481 	    DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    482 		r = bcm_ipmc_egress_port_get(unit, port, mac, &untag, &vid,
    483 					     &ttl_th);
    484 		if (r == BCM_E_NONE) {
    485 		    format_macaddr(mac_str, mac);
    486 		    cli_out("%-4s  %-18s %4d   %s  %5d\n",
    487                             BCM_PORT_NAME(unit, port), mac_str,
    488                             vid, untag ? "Y" : "N", ttl_th);
    489 		}
    490 	    }
    491 	    return CMD_OK;
    492 	    break;
    493 	default:
    494 	    return CMD_USAGE;
    495 	    break;
    496 	}
    497 
    498 	return CMD_OK;
    499     }
    500 
    501     if (sal_strcasecmp(table, "counter") == 0) {
    502         if ((argstr  = ARG_GET(a)) == NULL) { 
    503             pbmp = pcfg.e;
    504         } else {
    505             if (parse_bcm_port(unit, argstr, &port) < 0) {
    506                 cli_out("%s: Invalid port string: %s\n", ARG_CMD(a),
    507                         argstr);
    508                 return CMD_FAIL;
    509             }
    510             if (!BCM_PBMP_MEMBER(pcfg.e, port)) {
    511                 cli_out("port %d is not a valid Ethernet port\n", port);
    512                 return CMD_FAIL;
    513             }
    514             BCM_PBMP_CLEAR(pbmp);
    515             BCM_PBMP_PORT_ADD(pbmp, port);
    516         }
    517 	cli_out("PORT      RMCA     TMCA     IMBP     IMRP    RIMDR    TIMDR\n");
    518         /* coverity[overrun-local] */
    519         DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) {
    520 	    r = bcm_ipmc_counters_get(unit, port, &counters);
    521 	    if (r == BCM_E_NONE) {
    522 		cli_out("%4d  %8d %8d %8d %8d %8d %8d\n",
    523                         port,
    524                         COMPILER_64_LO(counters.rmca),
    525                         COMPILER_64_LO(counters.tmca),
    526                         COMPILER_64_LO(counters.imbp),
    527                         COMPILER_64_LO(counters.imrp),
    528                         COMPILER_64_LO(counters.rimdr),
    529                         COMPILER_64_LO(counters.timdr));
    530 	    }
    531 	}
    532 	return CMD_OK;
    533     }
    534 
    535 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    536     if (sal_strcasecmp(table, "ip6table") == 0) {
    537         switch (subcmd) {
    538         /* ipmc ip6table add */
    539         case IPMC_ADD:
    540             parse_table_init(unit, &pt);
    541             parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP6, 0,
    542                             (void *)&sip6_addr, 0);
    543             parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP6, 0,
    544                             (void *)&ip6_addr, 0);
    545             parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0);
    546             parse_table_add(&pt, "Valid", PQ_DFL|PQ_BOOL, 0,
    547                             (void *)&valid, 0);
    548             parse_table_add(&pt, "COS", PQ_DFL|PQ_INT, 0, (void *)&cos, 0);
    549             parse_table_add(&pt, "src_Port", PQ_INT, 0, (void *)&port, 0);
    550             parse_table_add(&pt, "TS", PQ_INT, 0, (void *)&ts, 0);
    551             parse_table_add(&pt, "NoCHECK", PQ_DFL|PQ_BOOL, 0,
    552                             (void *)&nocheck, 0);
    553             parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 0,
    554                             (void *)&lookup_class, 0);
    555             parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0,
    556                             (void *)&group, 0);
    557             parse_table_add(&pt, "GroupL2", PQ_DFL|PQ_INT, 0,
    558                             (void *)&group_l2, 0);
    559             if (parse_arg_eq(a, &pt) < 0) {
    560                 cli_out("%s: Error: Unknown option: %s\n",
    561                         ARG_CMD(a), ARG_CUR(a));
    562                 parse_arg_eq_done(&pt);
    563                 return CMD_FAIL;
    564 			}
    565             bcm_ipmc_addr_t_init(&ipmc_data);
    566             if (pt.pt_entries[4].pq_type & PQ_PARSED) {
    567                 ipmc_data.flags |= BCM_IPMC_SETPRI;
    568             }
    569             parse_arg_eq_done(&pt); 
    570             sal_memcpy(ipmc_data.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
    571             sal_memcpy(ipmc_data.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN);
    572             ipmc_data.cos = cos;
    573             ipmc_data.vid = vlan;
    574             ipmc_data.flags |= BCM_IPMC_IP6;
    575             ipmc_data.ts = ts;
    576             ipmc_data.port_tgid = port;
    577             ipmc_data.v = valid;
    578             if (nocheck) {
    579                 ipmc_data.flags |= BCM_IPMC_SOURCE_PORT_NOCHECK;
    580             }
    581             ipmc_data.lookup_class = lookup_class;
    582             if (group) {
    583                 ipmc_data.group = group;
    584             }
    585             if (group_l2) {
    586                 ipmc_data.group_l2 = group_l2;
    587             }
    588             r = bcm_ipmc_add(unit, &ipmc_data);
    589             if (r < 0) {
    590                 cli_out("%s: Error Add to ipmc table %s\n", ARG_CMD(a),
    591                         bcm_errmsg(r));
    592                 return CMD_FAIL;
    593             }
    594             return CMD_OK;
    595             break;
    596         case IPMC_DEL:
    597         /* ipmc ip6table del */
    598             parse_table_init(unit, &pt);
    599             parse_table_add(&pt, "Src_IP", PQ_DFL|PQ_IP6, 0,
    600                             (void *)&sip6_addr, 0);
    601             parse_table_add(&pt, "Mc_IP", PQ_DFL|PQ_IP6, 0,
    602                             (void *)&ip6_addr, 0);
    603             parse_table_add(&pt, "VlanID", PQ_DFL|PQ_INT, 0, (void *)&vlan, 0);
    604             if (!parseEndOk( a, &pt, &retCode))
    605                 return retCode;
    606             bcm_ipmc_addr_t_init(&ipmc_data);
    607             sal_memcpy(ipmc_data.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
    608             sal_memcpy(ipmc_data.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN);
    609             ipmc_data.vid=vlan;
    610             ipmc_data.flags = BCM_IPMC_IP6;
    611             r = bcm_ipmc_remove(unit, &ipmc_data);
    612             if (r < 0) {
    613                 cli_out("%s: Error delete from ipmc table %s\n", ARG_CMD(a),
    614                         bcm_errmsg(r));
    615                 return CMD_FAIL;
    616             }
    617             return CMD_OK;
    618             break;
    619         case IPMC_CLEAR:
    620         /* ipmc ip6table clear */
    621             r = bcm_ipmc_remove_all(unit);
    622             if (r < 0) {
    623                 cli_out("%s: %s\n",
    624                         ARG_CMD(a), bcm_errmsg(r));
    625                 return CMD_FAIL;
    626             }
    627             return (CMD_OK);
    628             break;
    629         case IPMC_SHOW:
    630         /* ipmc ip6table show */
    631             if (ARG_CNT(a)) {
    632                 if (!isint(ARG_CUR(a))) {
    633                     cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a),
    634                             ARG_CUR(a));
    635                     return (CMD_FAIL);
    636                 }
    637                 entry = parse_integer(ARG_GET(a));
    638                 if (entry == 0)
    639                     return (CMD_OK);
    640                 if (entry < soc_mem_index_min(unit, L3_IPMCm) ||
    641                     entry > soc_mem_index_max(unit, L3_IPMCm)) {
    642                     cli_out("%s: ERROR: Entry # too high, only permitted %d\n",
    643                             ARG_CMD(a), soc_mem_index_max(unit, L3_IPMCm));
    644                     return(CMD_FAIL);
    645                 }
    646                 one_entry_only = 1;
    647             }
    648 
    649             if (one_entry_only) {
    650                 /* bcm_ipmc_get_by_index is deprecated */
    651                 r = BCM_E_UNAVAIL;
    652                 cli_out("%s: bcm_ipmc_get_by_index is deprecated %s\n",
    653                         ARG_CMD(a), bcm_errmsg(r));
    654             }
    655             bcm_ipmc_traverse(unit, BCM_IPMC_IP6, _ipmc_cmd_entry_print, NULL);
    656 
    657             return (CMD_OK);
    658             break;
    659         default:
    660             return CMD_USAGE;
    661             break;
    662         }
    663         return CMD_OK;
    664     }
    665 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    666 
    667     return CMD_USAGE;
    668 }
    669 #endif /* BCM_XGS_SWITCH_SUPPORT */
    670 #endif /* INCLUDE_L3 */
    671 
    672 #ifdef INCLUDE_L3
    673 char if_l3_usage[] =
    674     "Usages:\n\t"
    675 #ifdef COMPILER_STRING_CONST_LIMIT
    676     "  l3 <option> [args...]\n"
    677 #else
    678     "  l3 init    - Init L3 function.\n\t"
    679     "  l3 detach  - Detach L3 function.\n\n\t"
    680 
    681     "  l3 intf add <Vlan>=<val> <Mac>=<val> [<INtf>=<val>] [<VRF>=<val>]\n\t"
    682     "                   [<Mtu>=<val>] [<Group>=<val>]\n\t"
    683     "                   - Add an entry into l3 interface table\n\t"
    684     "  l3 intf destroy <INtf>=<val>\n\t"
    685     "                   - Destroy an entry in l3 interface table\n\t"
    686     "  l3 intf clear    - Destroy all intf\n\t"
    687     "  l3 intf show     - [<INtf>=<val>]\n\t"
    688     "                     Display all Intfs or a single one\n\n\t"
    689     
    690     "  l3 egress add <Mac>=<val> <INtf>=<val> [<Trunk>=<val>]\n\t"
    691     "                  <Port>=<val> [<MOdule>=<val>] [<L2tocpu>=<val>]\n\t" 
    692     "                  [<L3MC>=<val>] [<MplsLabel>=<val>] [<Drop>=<val>]\n\t"
    693     "                  [<CopyToCpu>=<val>]\n\t"
    694     "                  - Create egress object entry\n\t"
    695     "  l3 egress update <EgrId>=<val> <Mac>=<val> <INtf>=<val>\n\t"
    696     "                  [<Trunk>=<val>] <Port>=<val> [<MOdule>=<val>]\n\t"
    697     "                  [<L2tocpu>=<val>] [<L3MC>=<val>] [<MplsLabel>=<val>]\n\t"
    698     "                  - Update egress object entry\n\t"
    699     "  l3 egress delete <entry>\n\t"
    700     "                  - Delete egress object entry\n\t"
    701     "  l3 egress show [entry]\n\t"
    702     "                  -Show egress object entry\n\t"
    703     "  l3 egress find <Mac>=<val> <INtf>=<val> [<Trunk>=<val>]\n\t"
    704     "                  <Port>=<val> [<MOdule>=<val>] [<L2tocpu>=<val>]\n\t" 
    705     "                  [<L3MC>=<val>] [<MplsLabel>=<val>]\n\t"
    706     "                  - Find egress object entry\n\t"
    707     "  l3 multipath add <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    708     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    709     "                  - Create multipath egress object entry\n\t"
    710     "  l3 multipath maxadd <Size>=<val> [<MaxGrpSize>=<val>] [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    711     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    712     "                  - Create multipath egress object entry(dynamic grp size)\n\t"
    713     "  l3 multipath update <EgrId>=<val> <Size>=<val> [<INtf0>=<val>]\n\t"
    714     "                  [<INtf1>=<val>] [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    715     "                  - Update multipath egress object entry\n\t"
    716     "  l3 multipath delete <entry>\n\t"
    717     "                  - Delete multipath egress object entry\n\t"
    718     "  l3 multipath show [entry]\n\t"
    719     "                  -Show multipath egress object entry\n\t"
    720     "  l3 multipath insert <EgrId>=<val> <Intf>=<val>\n\t"
    721     "                  -Add interface to multipath egress object entry\n\t"
    722     "  l3 multipath remove <EgrId>=<val> <Intf>\n\t"
    723     "                  -Remove interface from multipath egress object entry\n\t"
    724     "  l3 multipath find <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    725     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    726     "                  - Find multipath egress object entry\n\t"
    727     "  l3 ecmp egress add <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    728     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    729     "                  - Create ecmp egress object entry\n\t"
    730     "  l3 ecmp egress maxadd <Size>=<val> [<MaxGrpSize>=<val>] [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    731     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    732     "                  - Create ecmp egress object entry(dynamic grp size)\n\t"
    733     "  l3 ecmp egress update <EgrId>=<val> <Size>=<val> [<INtf0>=<val>]\n\t"
    734     "                  [<INtf1>=<val>] [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    735     "                  - Update ecmp egress object entry\n\t"
    736     "  l3 ecmp egress delete <entry>\n\t"
    737     "                  - Delete ecmp egress object entry\n\t"
    738     "  l3 ecmp egress show [entry]\n\t"
    739     "                  -Show ecmp egress object entry\n\t"
    740     "  l3 ecmp egress insert <EgrId>=<val> <Intf>=<val>\n\t"
    741     "                  -Add interface to ecmp egress object entry\n\t"
    742     "  l3 ecmp egress remove <EgrId>=<val> <Intf>\n\t"
    743     "                  -Remove interface from ecmp egress object entry\n\t"
    744     "  l3 ecmp egress find <Size>=<val> [<INtf0>=<val>] [<INtf1>=<val>]\n\t"
    745     "                  [<INtf2>=<val>] [<INtf3>=<val>]\n\t"
    746     "                  - Find ecmp egress object entry\n\t"
    747     "  l3 l3table add <VRF>=<val> <IP>=<val> <Mac>=<val> <INtf>=<val>\n\t"
    748     "       [<Hit>=<val>] [<Trunk>=<val>] [MOdule=<val>] <Port>=<val>\n\t"
    749     "       <PRI>=<val> <RPE>=<val> [<Untag>=<val>] [<L2tocpu>=<val>]\n\t"
    750     "       [<HOST_AS_ROUTE>=<val>] [Replace=<bool>] <LookupClass>=<val>\n\t"
    751     "  l3 l3table destroy <VRF>=<val> <IP>=<val>\n\t"
    752     "                   - Destroy an entry in l3 table\n\t"
    753     "  l3 l3table clear - Destroy all l3 table\n\t"
    754     "  l3 l3table show  - Display all l3 table or a single one\n\t"
    755     "  l3 l3table age   - Age L3 table\n\t"
    756     "  l3 l3table sanity <Start=<index> End=<index>\n\t"
    757     "                   - Check l3x tables for (san)ity in the given range\n\t"
    758     "  l3 l3table hash <VRF>=<val> <IP>=<val> [<SrcIP>=<val>] [<SipKey>=<val>]\n\t"
    759     "                    [<VID>=<val>] [<Hash>=<hash_type>]\n\t"
    760     "                   - Calculate l3 hash index\n\t"
    761     "  l3 l3table ip6hash <IP>=<val> [<SrcIP>=<val>] [<SipKey>=<val>]\n\t"
    762     "                    [<VID>=<val>] [<Hash>=<hash_type>]\n\t"
    763     "                   - Calculate l3 hash index for IPv6 entry\n\t"
    764     "  l3 l3table untag  - Recalculate untagged bits for L3\n\n\t"
    765     "  l3 l3table conflict <VRF>=<val> <DIP>=<val> <DIP6>=<val>\n\t"
    766     "                     <SIP>=<val> <SIP6>=<val> <IP6>=<val> <IPMC>=<val>\n\t"
    767     "                     <VLAN>=<val> \n\t"
    768     "                     - Get conflicting l3 entries.\n\n\t"
    769 
    770     "  l3 defip add <VRF>=<val> <IP>=<val> <MaSk>=<val> <Mac>=<val>\n\t"
    771     "       <INtf>=<val> <Gateway>=<next hop Ip address> <Port>=<val>\n\t"
    772     "       [MOdule=<val>] [<Untag>=<val>] [<Local>=<val>] [<ECMP>=<1/0>]\n\t"
    773     "       [<Hit>=<val>] [<VLAN>=<val>](BCM5695 def route 0.0.0.0/0 only)\n\t"
    774     "       [<DstDiscard>=<val>] <PRI>=<val> <RPE>=<val> [Replace=<bool>]\n\t"
    775     "       [<MplsLabel>=<val>] <TunnelOpt>=<val> <LookupClass>=<val>\n\t"
    776     "                   - Add an IPv4 entry into DEFIP table\n\t"
    777     "  l3 defip destroy <VRF>=<val> <IP>=<val> <MaSk>=<val>\n\t"
    778     "       [<ECMP=<1/0> <Mac>=<val> <Gateway>=<next hop Ip address>\n\t"
    779     "        <INtf>=<val> <Port>=<val> [MOdule=<val>]\n\t"
    780     "       [<VLAN>=<val>](BCM5695 def route 0.0.0.0/0 only)\n\t"
    781     "                   - Destroy an IPv4 entry in def IP table\n\t"
    782     "  l3 defip clear   - Destroy all IPv4 DEFIP table\n\t"
    783     "  l3 defip age     - Age DEFIP(LPM) table(XGS Switch only)\n\t"
    784     "  l3 defip show [<START> [<COUNT>]]\n\t"
    785     "                   - Display all IPv4 DEFIP table or\n\t"
    786     "                     the entires in a specified range\n\t"
    787     "  l3 defip ecmp <max>=<val> - Set MAX number of ECMP paths allowed\n\t"
    788     "  l3 defip ecmphash <DIP>=<val> <SIP>=<val> <SIP6>=val <DIP6>=val\n\t"
    789     "                    <COUNT>=<val> <IP6>=val  <L4_SRC_PORT>=val\n\t"
    790     "                    <L4_DST_PORT>=val [<EHash>=<ECMP hash Sel>] \n\t"
    791     "                    [<Hash>=<L3 hash type>]\n\t"
    792     "                   - Calculate ECMP hash index (COUNT is zero based)\n\t"
    793 #ifdef FB_LPM_DEBUG
    794     "  l3 defip sanity - Check L3 lpm states in scaling mode\n\n\t"
    795 #endif
    796 
    797 #ifdef ALPM_ENABLE
    798     "  l3 alpm show [all] [<VRF>=<val>] [<Global-vrf>=<bool>] \n\t"
    799     "       [<Pivot>=<bool>] [<Bucket>=<bool>] [<Counter>=<bool>]\n\t"
    800     "       [BucketuSage=<bool>] [InternelDebug=<bool>\n\t"
    801     "                   - Show ALPM debug info\n\n\t"
    802 
    803     "  l3 alpm show brief [<Bucket>=<val>] [<Index>=<val>] \n\t"
    804     "                   - Show ALPM brief debug info\n\n\t"
    805 
    806     "  l3 alpm find [<VRF>=<val>] <IP4>=<val> <IP6>=<val> [<Length>=<val>]\n\t"
    807     "                   - Find hit longest prefix match route\n\n\t"   
    808 
    809     "  l3 alpm sanity [<memory>=<val>] [<index>=<val>] [<sw>=<0/1>]\n\t"
    810     "                   - Process sanity check for ALPM tables\n\n\t"
    811 
    812 #endif
    813 
    814     "  l3 ip6host add <VRF>=<val> <IP>=<val> <Mac>=<val> [MOdule=<val>]\n\t"
    815     "       <Port>=<val> [<Trunk>=<val>] <INtf>=<val> [<Hit>=<val>]\n\t"
    816     "       <PRI>=<val> <RPE>=<val> [<Replace>=<bool>]\n\t"
    817     "       [<HOST_AS_ROUTE>=<bool>] <LookupClass>=<val>\n\t"
    818     "                   - Add/Update an IPv6 entry\n\t"
    819     "  l3 ip6host delete <VRF>=<val> <IP>=<val>\n\t"
    820     "                   - Delete an IPv6 entry\n\t"
    821     "  l3 ip6host clear - Delete all IPv6 host entries\n\t"
    822     "  l3 ip6host age   - Age IPv6 host entries\n\t"
    823     "  l3 ip6host show  - Show all IPv6 host entries\n\n\t"
    824 
    825     "  l3 ip6route add  <VRF>=<val> <IP>=<val> <MaskLen>=<val> <Mac>=<val>\n\t" 
    826     "                   [MOdule=<val>] <Port>=<val> [<Trunk>=<val>]\n\t" 
    827     "                   <INtf>=<val> <VLan>=<val> [<Hit>=<val>]\n\t" 
    828     "                   [<ECMP>=<1/0>] [<DstDiscard>=<val>] <PRI>=<val>\n\t" 
    829     "                   <RPE>=<val> [Replace=<bool>] [<MplsLabel>=<val>]\n\t"
    830     "                   <TunnelOpt>=<val> <LookupClass>=<val>\n\t"
    831     "                    - Add IPv6 route\n\t"
    832     "  l3 ip6route delete <VRF>=<val> <IP>=<val> <MaskLen>=<val>\n\t"
    833     "       [<ECMP=<1/0> <Mac>=<val> <INtf>=<val> <Port>=<val> [MOdule=<val>]\n\t"
    834     "                    - Delete an IPv6 route\n\t"
    835     "  l3 ip6route clear - Delete all IPv6 routes\n\t"
    836     "  l3 ip6route age   - Clear all IPv6 route HIT bits\n\t"
    837     "  l3 ip6route show [<START> [<COUNT>]]\n\t"
    838     "                    - Display all IPv6 routes or\n\t"
    839     "                      the routes in a specified range\n\t"
    840 
    841     "  l3 tunnel_init set <INtf>=<val> <TYpe>=<val> <TTL>=<val>\n\t"
    842     "       <Mac>=<val> <DIP>=<val> <SIP>=<val> <DSCPSel>=<val> <DSCPV>=<val>\n\t"
    843     "       <DFSEL4>=<val> <DFSEL6>=<val> <SIP6>=<val> <DIP6>=<val>\n\t"
    844     "  l3 tunnel_init show <INtf>=<val>\n\t"
    845     "  l3 tunnel_init clear <INtf>=<val>\n\t"
    846 
    847     "  l3 tunnel_term add <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t"
    848     "       <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t"
    849     "       <L4DstPort>=<val> <L4SrcPort>=<val> <OuterTTL>=<bool> \n\t"
    850     "       <OuterDSCP>=<val> <InnerDSCP>=<val> <TrustDSCP>=<val> \n\t"
    851     "       <VLanid>=<val> <PBMP>=<val> <AllowIPv6Payload>=<bool> \n\t"
    852     "       <AllowIPv4Payload>=<bool> <Replace>=<bool>\n\t"
    853     "  l3 tunnel_term delete <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t"
    854     "       <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t"
    855     "       <L4DstPort>=<val> <L4SrcPort>=<val> \n\t"
    856     "  l3 tunnel_term show <TYPE>=<val> <VRF>=<val> <DIP>=<val> <SIP>=<val>\n\t"
    857     "       <DipMaskLen>=<val> <SipMaskLen>=<val> <DIP6>=<val> <SIP6>=<val>\n\t"
    858     "       <L4DstPort>=<val> <L4SrcPort>=<val> \n\t"
    859 
    860     "  l3 dscp_map add\n\t"
    861     "  l3 dscp_map destroy <DscpMapId>=<val>\n\t"
    862     "  l3 dscp_map set <DscpMapId>=<val> <Priority>=<val> <Color>=<val>\n\t"
    863     "                  <DSCPValue>=<val>\n\t"
    864     "  l3 dscp_map show <DscpMapId>=<val>\n\t"
    865     "  l3 dscp_map_port set <Port>=<val> <Priority>=<val> <Color>=<val>\n\t"
    866     "                  <DSCPValue>=<val>\n\t"
    867     "  l3 dscp_map_port show <Port>=<val>\n\t"
    868     "  l3 prefix_map add <IP>=<val>\n\t"
    869     "  l3 prefix_map delete <IP>=<val>\n\t"
    870     "                  - Destroy ip6 prefix map to IPv4 entry\n\t"
    871     "  l3 prefix_map clear\n\t"
    872     "                  - Flush ip6 prefix map to IPv4 entry\n\t"
    873     "  l3 prefix_map show [entry]\n\t"
    874     "                  - Show ip6 prefix map to IPv4 entry\n\t"
    875     "  l3 nat_ingress show\n\t"
    876     "                  - Show all NAT Ingress Rules\n\t"
    877     "  l3 nat_egress add <DNAT=0/1> <DIP=new_ip> <SIP=new_ip> <DIPMASK=mask>\n\t"
    878     "       <SIPMASK=mask> <SRCPORT=new_port> <DSTPORT=new_port>\n\t"
    879     "                  - Add a new Egress Translation Rule\n\t"
    880     "  l3 nat_egress show\n\t"
    881     "                  - Show all NAT Egress Translation Rules\n\t"
    882     "  l3 route test perf\n\t"
    883     "                  - Run IPv4/IPv6 route performance test\n\t"
    884     "\n"
    885 #endif
    886     ;
    887 
    888 
    889 /*
    890  * Function:
    891  *     _nat_ingress_traverse_cb
    892  * Description:
    893  *    Internal function to print out ingress nat info.
    894  * Parameters:
    895  *    unit      - (IN) Device number.
    896  *    index    - (IN) Ingress NAT index. 
    897  *    nat_info - (IN) Ingress NAT structure.
    898  *    ign       - (IN) Ingress NAT user data.
    899  */
    900 int
    901 _nat_ingress_traverse_cb(int unit, int index, 
    902                             bcm_l3_nat_ingress_t *nat_info, void *ign)
    903 {
    904     char ip_str[IP6ADDR_STR_LEN];
    905     
    906     format_ipaddr(ip_str, nat_info->ip_addr);
    907     cli_out("%-5d %-5d %-16s %-5d %-5d %-5d %-5d\n", 
    908             index, nat_info->nat_id, ip_str, nat_info->vrf, nat_info->l4_port, 
    909             nat_info->ip_proto, nat_info->nexthop);
    910     return BCM_E_NONE;
    911 }
    912 
    913 /*
    914  * Function:
    915  *     _nat_ingress_traverse_cb
    916  * Description:
    917  *    Internal function to print out ingress nat info.
    918  * Parameters:
    919  *    unit      - (IN) Device number.
    920  *    index    - (IN) Engress NAT index. 
    921  *    nat_info - (IN) Engress NAT structure.
    922  *    ign       - (IN) Engress NAT user data.
    923  */
    924 int
    925 _nat_egress_traverse_cb(int unit, int index, 
    926                             bcm_l3_nat_egress_t *nat_info, void *ign)
    927 {
    928     char ip_str[IP6ADDR_STR_LEN];
    929     char ip_mask_str[IP6ADDR_STR_LEN];
    930     uint32 flags = nat_info->flags;
    931     uint32 ref_count = 0;
    932 
    933     _bcm_esw_l3_nat_egress_reference_get(unit, nat_info->nat_id,
    934                                          &ref_count);
    935     if(flags & BCM_L3_NAT_EGRESS_SNAT)
    936     {
    937         format_ipaddr(ip_str, nat_info->sip_addr);
    938         format_ipaddr(ip_mask_str, nat_info->sip_addr_mask);
    939         cli_out("%-5d %-5s %-5d %-16s %-16s %-6d %-8d\n",
    940                 index, "SNAT", nat_info->nat_id, ip_str, 
    941                 ip_mask_str, nat_info->src_port, ref_count);
    942     }
    943     if(flags & BCM_L3_NAT_EGRESS_DNAT)
    944     {
    945         format_ipaddr(ip_str, nat_info->dip_addr);
    946         format_ipaddr(ip_mask_str, nat_info->dip_addr_mask);
    947         cli_out("%-5d %-5s %-5d %-16s %-16s %-6d %-8d\n",
    948                 index, "DNAT", nat_info->nat_id, ip_str, 
    949                 ip_mask_str, nat_info->dst_port, ref_count);
    950     }
    951     return BCM_E_NONE;
    952 }
    953 
    954 /*
    955  * Function:
    956  *      _l3_cmd_nat_ingress_show
    957  * Description:
    958  *     Service routine used to show net entries. 
    959  * Parameters:
    960  *      unit      - (IN) Device number.
    961  *      a         - (IN) Command arguments. 
    962  * Returns: 
    963  *      CMD_XXX
    964  */
    965 STATIC int
    966 _l3_cmd_nat_ingress_show(int unit, args_t *a)
    967 {
    968     int rv;
    969 
    970     uint32 flags = 0;
    971 
    972     /* -1 is special value to say all entries */
    973     cli_out("%-5s %-5s %-16s %-5s %-6s %-5s %-5s\n", "IDX", 
    974             "ID", "IP", "VRF", "L4Port", "IPProto", "NextHop");
    975     cli_out("*****SNAT Entries*****\n");
    976     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
    977     if( BCM_FAILURE( rv ) ) {
    978         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
    979         return rv;
    980     }
    981 
    982     flags = BCM_L3_NAT_INGRESS_TYPE_NAPT;
    983     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
    984     if( BCM_FAILURE( rv ) ) {
    985         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
    986         return rv;
    987     }
    988 
    989     cli_out("*****DNAT Entries*****\n");
    990     flags = BCM_L3_NAT_INGRESS_DNAT;
    991     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
    992     if( BCM_FAILURE( rv ) ) {
    993         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
    994         return rv;
    995     }
    996     flags = BCM_L3_NAT_INGRESS_DNAT | BCM_L3_NAT_INGRESS_TYPE_NAPT;
    997     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
    998     if( BCM_FAILURE( rv ) ) {
    999         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
   1000         return rv;
   1001     }
   1002 
   1003     cli_out("*****DNAT Pool Entries*****\n");
   1004     flags = BCM_L3_NAT_INGRESS_DNAT | BCM_L3_NAT_INGRESS_DNAT_POOL;
   1005     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
   1006     if( BCM_FAILURE( rv ) ) {
   1007         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
   1008         return rv;
   1009     }
   1010     flags = BCM_L3_NAT_INGRESS_DNAT
   1011             | BCM_L3_NAT_INGRESS_DNAT_POOL
   1012             | BCM_L3_NAT_INGRESS_TYPE_NAPT;
   1013     rv = bcm_l3_nat_ingress_traverse( unit, flags, 0, -1, _nat_ingress_traverse_cb, NULL );
   1014     if( BCM_FAILURE( rv ) ) {
   1015         cli_out("Failed in ingress_traverse: %s\n", bcm_errmsg(rv));
   1016         return rv;
   1017     }
   1018         
   1019     return CMD_OK;
   1020 }
   1021 
   1022 /*
   1023  * Function:
   1024  *      _l3_cmd_nat_egress_add
   1025  * Description:
   1026  *     Service routine used to add net entry. 
   1027  * Parameters:
   1028  *      unit      - (IN) Device number.
   1029  *      a         - (IN) Command arguments. 
   1030  * Returns: 
   1031  *      CMD_XXX
   1032  */
   1033 STATIC int
   1034 _l3_cmd_nat_egress_add(int unit, args_t *a)
   1035 {
   1036     parse_table_t     pt;     
   1037     cmd_result_t      retCode; 
   1038     bcm_ip_t          sip_addr = 0;
   1039     bcm_ip_t          dip_addr = 0;
   1040     bcm_ip_t          sip_mask = 0;
   1041     bcm_ip_t          dip_mask = 0;
   1042     int               src_port = 0;
   1043     int               dst_port = 0;
   1044     int               dnat     = 0;
   1045     int               rv; 
   1046     bcm_l3_nat_egress_t nat_info;
   1047 
   1048 
   1049     parse_table_init(unit, &pt);
   1050     parse_table_add(&pt, "DIP",  PQ_DFL | PQ_IP, 0, (void *)&dip_addr, 0);
   1051     parse_table_add(&pt, "SIP",  PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0);
   1052     parse_table_add(&pt, "DIPMASK",  PQ_DFL | PQ_IP, 0, (void *)&dip_mask, 0);
   1053     parse_table_add(&pt, "SIPMASK",  PQ_DFL | PQ_IP, 0, (void *)&sip_mask, 0);
   1054     parse_table_add(&pt, "SRCPORT", PQ_DFL | PQ_INT, 0, (void *)&src_port, 0);
   1055     parse_table_add(&pt, "SRCPORT", PQ_DFL | PQ_INT, 0, (void *)&dst_port, 0);
   1056     parse_table_add(&pt, "DNAT", PQ_DFL | PQ_INT, 0, (void *)&dnat, 0);
   1057     if (!parseEndOk(a, &pt, &retCode)) {
   1058         return retCode;
   1059     }
   1060 
   1061     bcm_l3_nat_egress_t_init( &nat_info );
   1062     if( dnat ) {
   1063         nat_info.flags = BCM_L3_NAT_EGRESS_DNAT;
   1064     }
   1065     else {
   1066         nat_info.flags = BCM_L3_NAT_EGRESS_SNAT;
   1067     }
   1068     nat_info.sip_addr = sip_addr;
   1069     nat_info.dip_addr = dip_addr;
   1070     nat_info.sip_addr_mask = sip_mask;
   1071     nat_info.dip_addr_mask = dip_mask;
   1072     nat_info.src_port = src_port;
   1073     nat_info.dst_port = dst_port;
   1074 
   1075     rv = bcm_l3_nat_egress_add(unit, &nat_info);
   1076     if (BCM_FAILURE(rv)) {
   1077         cli_out("Egress Add failed: %s\n", bcm_errmsg(rv));
   1078         return rv;
   1079     }
   1080     cli_out("NAT ID: %d\n", nat_info.nat_id);
   1081 
   1082     return CMD_OK;
   1083 }
   1084 
   1085 /*
   1086  * Function:
   1087  *      _l3_cmd_nat_egress_show
   1088  * Description:
   1089  *     Service routine used to show net egress info. 
   1090  * Parameters:
   1091  *      unit      - (IN) Device number.
   1092  *      a         - (IN) Command arguments. 
   1093  * Returns: 
   1094  *      CMD_XXX
   1095  */
   1096 STATIC int
   1097 _l3_cmd_nat_egress_show(int unit, args_t *a)
   1098 {
   1099     int rv;
   1100 
   1101     uint32 flags = 0;
   1102 
   1103     cli_out("%-5s %-5s %-5s %-16s %-16s %-6s %-8s\n", "IDX",
   1104             "TYPE", "ID", "IP", "MASK", "L4Port", "RefCount");
   1105     /* -1 is special value to say all entries */
   1106     rv = bcm_l3_nat_egress_traverse( unit, flags, 0, -1, _nat_egress_traverse_cb, NULL );
   1107     if( BCM_FAILURE( rv ) ) {
   1108         cli_out("Failed in egress_traverse: %s\n", bcm_errmsg(rv));
   1109         return rv;
   1110     }
   1111 
   1112     return CMD_OK;
   1113 }
   1114  
   1115 
   1116 
   1117 /*
   1118  * Function:
   1119  *      _l3_cmd_route_print
   1120  * Description:
   1121  *	Internal function to print out route info
   1122  * Parameters:
   1123  *      unit   - device number.
   1124  *      index  - Traversal index number
   1125  *	info   - Pointer to bcm_l3_route_t data structure.
   1126  *      cookie - user cookie
   1127  */
   1128 STATIC int
   1129 _l3_cmd_route_print(int unit, int index, bcm_l3_route_t *info, void *cookie)
   1130 {
   1131     char ip_str[IP6ADDR_STR_LEN + 3];
   1132     char if_mac_str[SAL_MACADDR_STR_LEN];
   1133     char vrf_str[20];
   1134     char *hit;
   1135     char *trunk;
   1136     int masklen;
   1137     int priority;
   1138 
   1139     hit = (info->l3a_flags & BCM_L3_HIT) ? "y" : "n";
   1140     trunk = (info->l3a_flags & BCM_L3_TGID) ? "t" : " ";
   1141     priority = info->l3a_pri;
   1142 
   1143     switch (info->l3a_vrf){
   1144       case BCM_L3_VRF_GLOBAL:
   1145           /* coverity[secure_coding : FALSE] */
   1146           sal_strcpy(vrf_str,"Global"); 
   1147           break;
   1148       case BCM_L3_VRF_OVERRIDE:
   1149           /* coverity[secure_coding : FALSE] */
   1150           sal_strcpy(vrf_str,"Override"); 
   1151           break;
   1152       default:
   1153           sal_sprintf(vrf_str,"%d",info->l3a_vrf);
   1154     }
   1155 
   1156     format_macaddr(if_mac_str, info->l3a_nexthop_mac);
   1157 
   1158     if (info->l3a_flags & BCM_L3_IP6) {
   1159         format_ip6addr(ip_str, info->l3a_ip6_net);
   1160         masklen = bcm_ip6_mask_length(info->l3a_ip6_mask);
   1161         cli_out("%-5d %-8s %-s/%d %18s %4d %4d %5d%1s %4d %4d %s", index, vrf_str,
   1162                 ip_str, masklen, if_mac_str, info->l3a_intf,
   1163                 info->l3a_modid, info->l3a_port_tgid, trunk, priority, 
   1164                 info->l3a_lookup_class, hit);
   1165     } else {
   1166         format_ipaddr_mask(ip_str, info->l3a_subnet, info->l3a_ip_mask);
   1167         cli_out("%-5d %-8s %-19s %18s %4d %4d %5d%1s %4d %4d %s", index, vrf_str,
   1168                 ip_str, if_mac_str, info->l3a_intf,
   1169                 info->l3a_modid, info->l3a_port_tgid, trunk, priority, 
   1170                 info->l3a_lookup_class, hit);
   1171 
   1172         if (SOC_CHIP_GROUP(unit) == SOC_CHIP_BCM5695 &&
   1173             info->l3a_subnet == 0) {
   1174             cli_out("   %d (Per VLAN)", info->l3a_vid);
   1175         }
   1176     }
   1177 
   1178     if (info->l3a_flags & BCM_L3_MULTIPATH) {
   1179         cli_out("      (ECMP)");
   1180     } else if (info->l3a_flags & BCM_L3_DEFIP_LOCAL) {
   1181         cli_out("      (LOCAL ROUTE)");
   1182     } 
   1183 
   1184     if (info->l3a_flags & BCM_L3_ROUTE_LABEL) {
   1185         cli_out(" (MPLS)%d", info->l3a_mpls_label);
   1186     } else if (info->l3a_tunnel_option) {
   1187         cli_out(" (UDP tunnel) %d", info->l3a_tunnel_option);
   1188     } 
   1189         cli_out("\n");
   1190     
   1191 
   1192     return BCM_E_NONE;
   1193 }
   1194 
   1195 
   1196 /*
   1197  * Function:
   1198  *      _l3_cmd_egress_intf_print
   1199  * Description:
   1200  *	Internal function to print out egress l3 interface info.
   1201  * Parameters:
   1202  *      unit      - (IN) Device number.
   1203  *      print_hdr - (IN) Print header indicator. 
   1204  *	    intf      - (IN) Pointer to bcm_l3_intf_t data structure.
   1205  */
   1206 STATIC int
   1207 _l3_cmd_egress_intf_print(int unit, int print_hdr, bcm_l3_intf_t *intf)
   1208 {
   1209     char if_mac_str[SAL_MACADDR_STR_LEN];
   1210 
   1211     if (NULL == intf) {
   1212         return (BCM_E_PARAM);
   1213     }
   1214 
   1215     if (print_hdr) {
   1216         cli_out("Unit  Intf  VRF Group VLAN    Source Mac     MTU TTL Tunnel InnerVlan  NATRealm\n");
   1217         cli_out("------------------------------------------------------------------\n");
   1218     }
   1219 
   1220     format_macaddr(if_mac_str, intf->l3a_mac_addr);
   1221     cli_out("%-5d %-5d %-5d %-5d %-4d %-18s %-4d %-4d %-5d %-5d %-5d\n", unit, 
   1222             intf->l3a_intf_id, intf->l3a_vrf, intf->l3a_group, 
   1223             intf->l3a_vid, if_mac_str, intf->l3a_mtu, intf->l3a_ttl,           
   1224             intf->l3a_tunnel_idx, intf->l3a_inner_vlan, intf->l3a_nat_realm_id);           
   1225     return (CMD_OK);
   1226 }
   1227 
   1228 
   1229 /*
   1230  * Function:
   1231  *      _l3_cmd_tunnel_init_print
   1232  * Description:
   1233  *	Internal function to print out tunnel initiator info.
   1234  * Parameters:
   1235  *      unit      - (IN) Device number.
   1236  *      interface - (IN) L3 egress interface. 
   1237  *	    info      - (IN) Pointer to bcm_tunnel_initiator_t data structure.
   1238  */
   1239 STATIC int
   1240 _l3_cmd_tunnel_init_print (int unit, bcm_if_t interface, bcm_tunnel_initiator_t *info)
   1241 {
   1242     char ip_str[IP6ADDR_STR_LEN + 3];
   1243     char if_mac_str[SAL_MACADDR_STR_LEN];
   1244 
   1245     cli_out("Tunnel initiator:\n");
   1246     cli_out("\tUnit        = %d\n", unit);
   1247     cli_out("\tInterface   = %d\n", interface);
   1248     cli_out("\tTUNNEL_TYPE = %d\n", info->type);
   1249     cli_out("\tTTL         = %d\n", info->ttl);
   1250     format_macaddr(if_mac_str, info->dmac);
   1251     cli_out("\tMAC_ADDR    = %-18s\n", if_mac_str);
   1252     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) { 
   1253         format_ip6addr(ip_str, info->dip6);
   1254         cli_out("\tDIP         = 0x%-s\n", ip_str);
   1255         format_ip6addr(ip_str, info->sip6);
   1256         cli_out("\tSIP         = 0x%-s\n", ip_str);
   1257     } else { 
   1258         cli_out("\tDIP         = 0x%08x\n", info->dip);
   1259         cli_out("\tSIP         = 0x%08x\n", info->sip);
   1260         if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) {
   1261             cli_out("\tCopy DF from inner header.\n");
   1262         } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) {
   1263             cli_out("\tForce DF to 1 for ipv4 payload.\n");
   1264         }
   1265         if (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) {
   1266             cli_out("\tForce DF to 1 for ipv6 payload.\n");
   1267         }
   1268     }
   1269     cli_out("\tDSCP_SEL    = 0x%x\n", info->dscp_sel);
   1270     cli_out("\tDSCP        = 0x%x\n", info->dscp);
   1271     cli_out("\tDSCP_MAP    = 0x%x\n", info->dscp_map);
   1272     return CMD_OK;
   1273 }
   1274 
   1275 /*
   1276  * Function:
   1277  *      _l3_cmd_tunnel_term_print
   1278  * Description:
   1279  *	Internal function to print out tunnel terminator info.
   1280  * Parameters:
   1281  *      unit      - (IN) Device number.
   1282  *	    info      - (IN) Pointer to bcm_tunnel_terminator_t data structure.
   1283  */
   1284 STATIC int
   1285 _l3_cmd_tunnel_term_print (int unit, bcm_tunnel_terminator_t *info)
   1286 {
   1287     char ip_str[IP6ADDR_STR_LEN + 3];
   1288     char buf_pbmp[SOC_PBMP_FMT_LEN];
   1289 
   1290     cli_out("Tunnel terminator:\n");
   1291     cli_out("\tUnit        = %d\n", unit);
   1292     cli_out("\tTUNNEL_TYPE = %d\n", info->type);
   1293     cli_out("\tVRF         = %d\n", info->vrf);
   1294     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) { 
   1295         format_ip6addr(ip_str, info->dip6);
   1296         cli_out("\tDIP         = 0x%-s\n", ip_str);
   1297         format_ip6addr(ip_str, info->dip6_mask);
   1298         cli_out("\tDIP MASK    = 0x%-s\n", ip_str);
   1299         format_ip6addr(ip_str, info->sip6);
   1300         cli_out("\tSIP         = 0x%-s\n", ip_str);
   1301         format_ip6addr(ip_str, info->sip6_mask);
   1302         cli_out("\tSIP MASK    = 0x%-s\n", ip_str);
   1303     } else { 
   1304         cli_out("\tDIP         = 0x%08x\n", info->dip);
   1305         cli_out("\tDIP_MASK    = 0x%08x\n", info->dip_mask);
   1306         cli_out("\tSIP         = 0x%08x\n", info->sip);
   1307         cli_out("\tSIP_MASK    = 0x%08x\n", info->sip_mask);
   1308     }
   1309 
   1310 
   1311     cli_out("\tL4 Destination Port    = 0x%08x\n", info->udp_dst_port);
   1312     cli_out("\tL4 Source Port         = 0x%08x\n", info->udp_src_port);
   1313     cli_out("\tVlan id                = 0x%08x\n", info->vlan);
   1314     format_pbmp(unit, buf_pbmp, sizeof(buf_pbmp), info->pbmp);
   1315     cli_out("\tPbmp                   = 0x%s\n", buf_pbmp);
   1316 
   1317     if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   1318         cli_out("\tCopy DSCP from outer ip header.\n");
   1319     } else if (info->flags & BCM_TUNNEL_TERM_KEEP_INNER_DSCP) {
   1320         cli_out("\tCopy DSCP from inner ip header.\n");
   1321     } 
   1322 
   1323 
   1324     if (info->flags & BCM_TUNNEL_TERM_DSCP_TRUST) {
   1325         cli_out("\tTrust incming DSCP based on inner/outer selection.\n");
   1326     }
   1327 
   1328     if (info->flags & BCM_TUNNEL_TERM_USE_OUTER_TTL) {
   1329         cli_out("\tCopy TTL from outer ip header.\n");
   1330     } 
   1331     return CMD_OK;
   1332 }
   1333 
   1334 
   1335 /*
   1336  * Function:
   1337  *      _l3_cmd_egress_mpath_obj_print
   1338  * Description:
   1339  *	 Internal function to print out multipath egress object info
   1340  * Parameters:
   1341  *      unit        - device number.
   1342  *      index       - Egress object id.
   1343  *      intf_count  - Interface count.
   1344  *      info        - Pointer to interfaces array.
   1345  *      user_data   - User cookie.
   1346  */
   1347 STATIC int
   1348 _l3_cmd_egress_mpath_obj_print(int unit, int index, int intf_count, bcm_if_t
   1349                                *info, void *user_data)
   1350 {
   1351     int    idx;
   1352     uint32 ref_count;
   1353 
   1354     cli_out("Multipath Egress Object %d\n", index);
   1355 
   1356     cli_out("Interfaces:");
   1357 
   1358     for (idx = 0; idx < intf_count; idx++) {
   1359         cli_out(" %d", info[idx]);
   1360         if (idx && (!(idx % 10))) {
   1361             cli_out("\n           ");
   1362         }
   1363     }
   1364 
   1365     /*
   1366      * Get the reference count for the multipath object. This ref count
   1367      * indicates the number of route references for this egress object. This is
   1368      * a read only object and used for debugging purposes. Hence, this is not
   1369      * exposed in the form of an API and retrieved internally
   1370      */
   1371     _bcm_esw_l3_egress_reference_get(unit, index, 1, &ref_count);
   1372 
   1373     cli_out("\nReference count: %d", ref_count);
   1374     cli_out("\n");
   1375     return BCM_E_NONE;
   1376 }
   1377 
   1378 /*
   1379  * Function:
   1380  *      _l3_cmd_egress_ecmp_obj_print
   1381  * Description:
   1382  *	 Internal function to print out ecmp egress object info
   1383  * Parameters:
   1384  *      unit        - device number.
   1385  *      ecmp        - ECMP group info.
   1386  *      intf_count  - Interface count. 
   1387  *      intf_array  - Array of Egress forwarding objects.
   1388  *      user_data   - User cookie. 
   1389  */
   1390 STATIC int
   1391 _l3_cmd_egress_ecmp_obj_print(int unit, bcm_l3_egress_ecmp_t *ecmp,
   1392                                int intf_count, bcm_if_t *intf_array,
   1393                                void *user_data)
   1394 {
   1395     int    idx; 
   1396     uint32 ref_count;
   1397 
   1398     cli_out("ECMP Egress Object %d\n", ecmp->ecmp_intf);
   1399 
   1400     cli_out("Interfaces:");
   1401  
   1402     for (idx = 0; idx < intf_count; idx++) {
   1403         cli_out(" %d", *intf_array);
   1404         if (idx && (!(idx % 10))) {
   1405             cli_out("\n           ");
   1406         } 
   1407         intf_array++;
   1408     }
   1409 
   1410     /*
   1411      * Get the reference count for the ecmp object. This ref count
   1412      * indicates the number of route references for this egress object. This is
   1413      * a read only object and used for debugging purposes. Hence, this is not
   1414      * exposed in the form of an API and retrieved internally
   1415      */
   1416     _bcm_esw_l3_egress_reference_get(unit, ecmp->ecmp_intf, 1, &ref_count);
   1417 
   1418     cli_out("\nReference count: %d", ref_count);
   1419     cli_out("\n");
   1420     return BCM_E_NONE;
   1421 }
   1422 
   1423 /*
   1424  * Function:
   1425  *      _l3_cmd_egress_obj_print
   1426  * Description:
   1427  *	 Internal function to print out egress object info
   1428  * Parameters:
   1429  *      unit   - device number.
   1430  *      index  - Egress object id. 
   1431  *   	info   - Pointer to bcm_l3_egres_t data structure.
   1432  *      cookie - user cookie
   1433  */
   1434 STATIC int
   1435 _l3_cmd_egress_obj_print(int unit, int index, bcm_l3_egress_t *info, void *cookie)
   1436 {
   1437     char if_mac_str[SAL_MACADDR_STR_LEN];
   1438     char *trunk;
   1439     int     port, tgid, module, id;
   1440     uint32  ref_count = 0;
   1441 
   1442     trunk = (info->flags & BCM_L3_TGID) ? "t" : " ";
   1443 
   1444     format_macaddr(if_mac_str, info->mac_addr);
   1445     if (BCM_GPORT_IS_SET(info->port)) {
   1446         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->port, &module, &port, &tgid, &id));
   1447         if (id != -1) {
   1448             port = id;
   1449         }
   1450     } else {
   1451         port = info->port;
   1452         module = info->module;
   1453         tgid = info->trunk;
   1454     }
   1455 
   1456     /*
   1457      * Get the reference count for the egress object. This ref count indicates
   1458      * the number of route references for this egress object. This is a read
   1459      * only object and used for debugging purposes. Hence, this is not exposed
   1460      * in the form of an API and retrieved internally
   1461      */
   1462     _bcm_esw_l3_egress_reference_get(unit, index, 0, &ref_count);
   1463 
   1464     BCM_IF_ERROR_RETURN(_bcm_esw_l3_egress_ref_dlb_update
   1465                                       (unit, index, &ref_count));
   1466 
   1467     cli_out("%d %18s %4d %4d %5d%1s %3d %9d %4s %4s %4u %4s\n", index,
   1468             if_mac_str, info->vlan, info->intf, 
   1469             ((info->flags & BCM_L3_TGID) ? tgid : port),
   1470             trunk, module, info->mpls_label, 
   1471             (info->flags & BCM_L3_COPY_TO_CPU) ? "yes" : "no" , 
   1472             (info->flags & BCM_L3_DST_DISCARD) ? "yes" : "no" ,
   1473             ref_count,
   1474             (info->flags & BCM_L3_IPMC) ? "yes" : "no");
   1475 
   1476     return BCM_E_NONE;
   1477 }
   1478 
   1479 /*
   1480  * Function:
   1481  *      _l3_cmd_host_print
   1482  * Description:
   1483  *	Internal function to print out host entry info
   1484  * Parameters:
   1485  *      unit   - device number.
   1486  *      index  - Traversal index number
   1487  *	info   - Pointer to bcm_l3_host_t data structure.
   1488  *      cookie - user cookie
   1489  */
   1490 STATIC int
   1491 _l3_cmd_host_print(int unit, int index, bcm_l3_host_t *info, void *cookie)
   1492 {
   1493     char ip_str[IP6ADDR_STR_LEN];
   1494     char if_mac_str[SAL_MACADDR_STR_LEN];
   1495     char *hit;
   1496     char *trunk = " ";
   1497     int     tgid=0, port, module, id;
   1498 
   1499     hit = (info->l3a_flags & BCM_L3_HIT) ? "y" : "n";
   1500     
   1501     format_macaddr(if_mac_str, info->l3a_nexthop_mac);
   1502     if (BCM_GPORT_IS_SET(info->l3a_port_tgid)) {
   1503         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, info->l3a_port_tgid, &module, 
   1504                                &port, &tgid, &id));
   1505 #ifdef BCM_RIOT_SUPPORT
   1506         /* VFI type virtual port */
   1507         if (_bcm_vp_is_vfi_type(unit, info->l3a_port_tgid)) {
   1508             port = id;
   1509         } else
   1510 #endif
   1511         {
   1512             if (!BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   1513                 /* For Tomahawk L3/NIV/PE extended view,ignore id = -1 check
   1514                  * as id > 0 is returned for VPs in extended view
   1515                  */
   1516                 if (id != -1) {
   1517                     return CMD_USAGE;
   1518                 }
   1519             }
   1520         }
   1521         if (tgid != -1) {
   1522             trunk = "t";
   1523         }
   1524     } else {
   1525         if (info->l3a_flags & BCM_L3_TGID) {
   1526             trunk = "t" ; 
   1527             tgid = info->l3a_port_tgid;
   1528             port = -1;
   1529         } else {
   1530             port = info->l3a_port_tgid;
   1531         }
   1532         module = info->l3a_modid;
   1533     }
   1534     
   1535     if (info->l3a_flags & BCM_L3_IP6) {
   1536         format_ip6addr(ip_str, info->l3a_ip6_addr);
   1537         cli_out("%-5d %-4d %-42s %18s %4d %4d %5d%1s   %6d %s      %-5d\n",
   1538                 index, info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf,
   1539                 module, (port == -1) ? tgid : port, trunk,
   1540                 info->l3a_lookup_class, hit, *(int *)cookie);
   1541     } else {
   1542         format_ipaddr(ip_str, info->l3a_ip_addr);
   1543         cli_out("%-5d %-4d %-16s %-18s %4d %4d %4d%1s   %6d %s      %-5d",
   1544                 index, info->l3a_vrf, ip_str, if_mac_str, info->l3a_intf,
   1545                 module, (port == -1) ? tgid : port, trunk,
   1546                 info->l3a_lookup_class, hit, *(int *)cookie);
   1547     }
   1548 
   1549     if (info->l3a_flags & BCM_L3_MULTIPATH) {
   1550         cli_out("      (ECMP)\n");
   1551     } else if (info->l3a_flags & BCM_L3_HOST_LOCAL) {
   1552         cli_out("      (LOCAL ROUTE)\n");    
   1553     } else { 
   1554         cli_out("\n");
   1555     }
   1556      
   1557     return BCM_E_NONE;
   1558 }
   1559 
   1560 
   1561 /*
   1562  * Function:
   1563  *      _l3_cmd_l3_key_print
   1564  * Description:
   1565  *	Internal function to print out host entry info
   1566  * Parameters:
   1567  *      unit   - device number.
   1568  *      index  - Traversal index number
   1569  */
   1570 STATIC int
   1571 _l3_cmd_l3_key_print(int unit, int index, bcm_l3_key_t *info)
   1572 {
   1573     char dip_str[IP6ADDR_STR_LEN];
   1574     char sip_str[IP6ADDR_STR_LEN];
   1575 
   1576     if (info->l3k_flags & BCM_L3_IPMC) {
   1577         if (info->l3k_flags & BCM_L3_IP6) {
   1578             format_ip6addr(dip_str, info->l3k_ip6_addr);
   1579             format_ip6addr(sip_str, info->l3k_sip6_addr);
   1580             cli_out("%-5d Group %-42s\n", index, dip_str);
   1581             cli_out("      Src %-42s\n", sip_str);
   1582             cli_out("      Vrf %-4d VLAN %-4d\n", info->l3k_vrf, info->l3k_vid);
   1583         } else {
   1584             format_ipaddr(dip_str, info->l3k_ip_addr);
   1585             format_ipaddr(sip_str, info->l3k_sip_addr);
   1586             cli_out("%-5d Group %-18s  Src %-18s Vrf %-4d Vlan %-4d\n", 
   1587                     index, dip_str, sip_str, info->l3k_vrf, info->l3k_vid);
   1588         }
   1589     } else {
   1590         if (info->l3k_flags & BCM_L3_IP6) {
   1591             format_ip6addr(dip_str, info->l3k_ip6_addr);
   1592             cli_out("%-5d VRF %-4d DIP %-18s\n",
   1593                     index, info->l3k_vrf, dip_str);
   1594         } else {
   1595             format_ipaddr(dip_str, info->l3k_ip_addr);
   1596             cli_out("%-5d VRF %-4d DIP %-18s\n", 
   1597                     index, info->l3k_vrf, dip_str);
   1598         }
   1599     }
   1600     return CMD_OK;
   1601 }
   1602 
   1603 
   1604 /*
   1605  * Function:
   1606  *      _l3_cmd_host_age_callback
   1607  * Description:
   1608  *	Internal function to print out host entry being aged out
   1609  * Parameters:
   1610  *      unit   - device number.
   1611  *      index  - Traversal index number
   1612  *	info   - Pointer to bcm_l3_host_t data structure.
   1613  *      cookie - user cookie
   1614  */
   1615 STATIC int
   1616 _l3_cmd_host_age_callback(int unit, int index, bcm_l3_host_t *info, void *cookie)
   1617 {
   1618     if (info->l3a_flags & BCM_L3_IP6) {
   1619         char ip_str[IP6ADDR_STR_LEN];
   1620 
   1621         format_ip6addr(ip_str, info->l3a_ip6_addr);
   1622         cli_out("IPv6 Address %s age out\n", ip_str);
   1623     } else {
   1624         cli_out("IP Address 0x%x age out\n", info->l3a_ip_addr);
   1625     }
   1626 
   1627     return BCM_E_NONE;
   1628 }
   1629 
   1630 /*
   1631  * Function:
   1632  *      _l3_cmd_route_age_callback
   1633  * Description:
   1634  *	Internal function to print out route being aged (HIT bit cleared)
   1635  * Parameters:
   1636  *      unit   - device number.
   1637  *      index  - Traversal index number
   1638  *	info   - Pointer to bcm_l3_host_t data structure.
   1639  *      cookie - user cookie
   1640  */
   1641 STATIC int
   1642 _l3_cmd_route_age_callback(int unit, int index, bcm_l3_route_t *net, void *cookie)
   1643 {
   1644     if (net->l3a_flags & BCM_L3_IP6) {
   1645         char ip_str[IP6ADDR_STR_LEN];
   1646         int masklen;
   1647 
   1648         format_ip6addr(ip_str, net->l3a_ip6_net);
   1649         masklen = bcm_ip6_mask_length(net->l3a_ip6_mask);
   1650         cli_out("Deleted unused route %s/%d)\n", ip_str, masklen);
   1651     } else {
   1652         cli_out("Deleted unused route 0x%x(mask 0x%x)\n",
   1653                 net->l3a_subnet, net->l3a_ip_mask);
   1654     }
   1655 
   1656     return BCM_E_NONE;
   1657 }
   1658 
   1659 /*
   1660  * L3 command catagory
   1661  */
   1662 enum _l3_cmd_t {
   1663     L3_ADD = 1,
   1664     L3_DESTROY,
   1665     L3_SET,
   1666     L3_CLEAR,
   1667     L3_SHOW,
   1668     L3_AGE,
   1669     L3_UPDATE,
   1670     L3_HASH,
   1671     L3_IP6HASH,
   1672     L3_SANITY,
   1673     L3_ECMP,
   1674     L3_ECMP_HASH, 
   1675     L3_INSERT, 
   1676     L3_REMOVE, 
   1677     L3_FIND,
   1678     L3_CONFLICT,
   1679     L3_TEST,
   1680     L3_MAXADD
   1681 };
   1682 
   1683 const char *cmd_tunnel_term_parse_type[] = {
   1684     "6to4",
   1685     "6to4-unchecked",
   1686     "isatap",
   1687     "ipip",
   1688     NULL
   1689 };
   1690 
   1691 
   1692 #if defined(BCM_XGS_SWITCH_SUPPORT)
   1693 /*
   1694  * Function:
   1695  *      _l3_cmd_l3_conflict_show
   1696  * Description:
   1697  * 	    Service routine used to show l3 table conflicting entries. 
   1698  * Parameters:
   1699  *      unit      - (IN) Device number.
   1700  *      a         - (IN) Command arguments. 
   1701  * Returns: 
   1702  *      CMD_XXX
   1703  */
   1704 
   1705 STATIC cmd_result_t
   1706 _l3_cmd_l3_conflict_show(int unit, args_t *a) 
   1707 {
   1708     parse_table_t     pt;     
   1709     cmd_result_t      retCode; 
   1710     bcm_ip6_t         sip6_addr;
   1711     bcm_ip6_t         ip6_addr;
   1712     bcm_ip_t          sip_addr = 0;
   1713     bcm_ip_t          ip_addr = 0;
   1714     int               vlan = 0;
   1715     int               ipmc = 0;
   1716     int               ip6 = 0;
   1717     bcm_vrf_t         vrf = BCM_L3_VRF_DEFAULT;
   1718     bcm_l3_key_t      ipkey;
   1719     bcm_l3_key_t      result[L3X_MAX_BUCKET_SIZE];
   1720     int               count;  
   1721     int               idx;
   1722     int               rv; 
   1723 
   1724     /* Stack variables initialization. */
   1725     sal_memset(sip6_addr, 0, sizeof(bcm_ip6_t));
   1726     sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t));
   1727     sal_memset(result, 0, L3X_MAX_BUCKET_SIZE * sizeof(bcm_l3_key_t));
   1728 
   1729     parse_table_init(unit, &pt);
   1730     parse_table_add(&pt, "DIP",  PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0);
   1731     parse_table_add(&pt, "SIP",  PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0);
   1732     parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   1733     parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)&sip6_addr, 0);
   1734     parse_table_add(&pt, "VRF",  PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   1735     parse_table_add(&pt, "VLAN", PQ_DFL | PQ_INT, 0, (void *)&vlan, 0);
   1736     parse_table_add(&pt, "IPMC", PQ_DFL | PQ_INT, 0, (void *)&ipmc, 0);
   1737     parse_table_add(&pt, "IP6",  PQ_DFL | PQ_INT, 0, (void *)&ip6, 0);
   1738     if (!parseEndOk(a, &pt, &retCode)) {
   1739         return retCode;
   1740     }
   1741 
   1742     /* Initialize data structures. */
   1743     sal_memset(&ipkey, 0, sizeof(bcm_l3_key_t));
   1744 
   1745     /* Fill tunnel info. */
   1746     if (ip6) { 
   1747         ipkey.l3k_flags |= BCM_L3_IP6; 
   1748         sal_memcpy(ipkey.l3k_ip6_addr, ip6_addr, sizeof(bcm_ip6_t));
   1749         sal_memcpy(ipkey.l3k_sip6_addr, sip6_addr, sizeof(bcm_ip6_t));
   1750     } else {
   1751         ipkey.l3k_ip_addr = ip_addr;
   1752         ipkey.l3k_sip_addr = sip_addr;
   1753     }
   1754 
   1755     if (ipmc) { 
   1756        ipkey.l3k_flags |= BCM_L3_IPMC; 
   1757     }
   1758     ipkey.l3k_vrf = vrf;
   1759     ipkey.l3k_vid = vlan & 0xfff;
   1760 
   1761     if ((rv = bcm_l3_host_conflict_get(unit, &ipkey, result, 
   1762                                        L3X_MAX_BUCKET_SIZE, &count)) < 0) {
   1763         cli_out("ERROR %s: getting l3 conflicts %s\n", 
   1764                 ARG_CMD(a), bcm_errmsg(rv));
   1765         return CMD_FAIL;
   1766     }
   1767 
   1768     for (idx = 0; idx < count; idx++) {
   1769         _l3_cmd_l3_key_print(unit, idx, result + idx);
   1770     }
   1771     return CMD_OK;
   1772 }
   1773 
   1774 /*
   1775  * Function:
   1776  *      _l3_cmd_defip_ecmp_hash
   1777  * Description:
   1778  * 	    Service routine used to calculate route ecmp hash 
   1779  * Parameters:
   1780  *      unit      - (IN) Device number.
   1781  *      a         - (IN) Command arguments. 
   1782  * Returns: 
   1783  *      CMD_XXX
   1784  */
   1785 STATIC cmd_result_t
   1786 _l3_cmd_defip_ecmp_hash(int unit, args_t *a) 
   1787 {
   1788     uint32                 l4_dst_port = 0;
   1789     uint32                 l4_src_port = 0;
   1790     int                    ecmp_count = 0;
   1791     bcm_ip6_t              dip6_addr;
   1792     bcm_ip6_t              sip6_addr;
   1793     bcm_ip_t               dip_addr = 0;
   1794     bcm_ip_t               sip_addr = 0;
   1795     cmd_result_t           retCode;
   1796     parse_table_t          pt;     
   1797     int                    rv;
   1798     int                    ip6 = 0;
   1799     int                    hash_select = XGS_HASH_COUNT;
   1800     int                    ecmp_hash_sel = 2;
   1801 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1802     soc_xgs3_ecmp_hash_t   data; 
   1803 #endif /* BCM_XGS3_SWITCH_SUPPORT */    
   1804 
   1805     if (!SOC_IS_XGS_SWITCH(unit)) {
   1806         cli_out("Command only valid for XGS switches\n");
   1807         return CMD_FAIL;
   1808     }
   1809 
   1810     sal_memset(dip6_addr, 0, sizeof (bcm_ip6_t));
   1811     sal_memset(sip6_addr, 0, sizeof (bcm_ip6_t));
   1812 
   1813     parse_table_init(unit, &pt);
   1814     parse_table_add(&pt, "DIP", PQ_DFL | PQ_IP, 0, (void *)&dip_addr, 0);
   1815     parse_table_add(&pt, "SIP", PQ_DFL | PQ_IP, 0, (void *)&sip_addr, 0);
   1816     parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)dip6_addr, 0);
   1817     parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)sip6_addr, 0);
   1818     parse_table_add(&pt, "IP6", PQ_DFL | PQ_INT, 0, (void *)&ip6, 0);
   1819     parse_table_add(&pt, "L4_SRC_PORT", PQ_DFL | PQ_INT, 0,
   1820                     (void *)&l4_dst_port, 0);
   1821     parse_table_add(&pt, "L4_DST_PORT", PQ_DFL | PQ_INT, 0, 
   1822                     (void *)&l4_src_port, 0);
   1823     parse_table_add(&pt, "COUNT", PQ_DFL | PQ_INT, 0,
   1824                     (void *)&ecmp_count, 0);
   1825     parse_table_add(&pt, "EHash", PQ_DFL | PQ_INT, 0,
   1826                     (void *)&ecmp_hash_sel, 0);
   1827     parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0,
   1828                     (void *)&hash_select, 0);
   1829     if (!parseEndOk(a, &pt, &retCode)) {
   1830         return retCode;
   1831     }
   1832 
   1833 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1834     if (SOC_IS_XGS3_SWITCH(unit)) {   /* FBX || ER */
   1835         sal_memset(&data, 0, sizeof (soc_xgs3_ecmp_hash_t));
   1836         /* Fill source/destination address. . */
   1837         if (ip6) { 
   1838             sal_memcpy(data.dip6, dip6_addr, sizeof(bcm_ip6_t));
   1839             sal_memcpy(data.sip6, sip6_addr, sizeof(bcm_ip6_t));
   1840             data.v6 = TRUE;
   1841         } else {
   1842             data.dip = dip_addr;
   1843             data.sip = sip_addr;
   1844         }
   1845         data.l4_src_port = l4_src_port & 0xffff;  /* TCP/UDP src port. */
   1846         data.l4_dst_port = l4_dst_port & 0xffff;  /* TCP/UDP dst port. */
   1847         data.ecmp_count = ecmp_count;      /* Zero based ecmp count. */
   1848 
   1849         rv = soc_xgs3_l3_ecmp_hash(unit, &data);
   1850         if (rv < 0){
   1851             cli_out("Internal error\n");
   1852             return CMD_FAIL;
   1853         } 
   1854         cli_out("ECMP hash is %d \n", rv);
   1855         return CMD_OK; 
   1856     } else 
   1857 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1858     if (ip6) {
   1859         cli_out("IPv6 is not supported.\n");
   1860         return CMD_OK; 
   1861     }
   1862 
   1863     cli_out("Command is not supported.\n"); 
   1864     return CMD_FAIL;
   1865 }
   1866 #endif /* BCM_XGS_SWITCH_SUPPORT*/
   1867 
   1868 /*
   1869  * Function:
   1870  *      _l3_cmd_tunnel_init_add
   1871  * Description:
   1872  * 	    Service routine used to add tunnel initiator to an interface.
   1873  * Parameters:
   1874  *      unit      - (IN) Device number.
   1875  *      a         - (IN) Command arguments. 
   1876  * Returns: 
   1877  *      CMD_XXX
   1878  */
   1879 
   1880 STATIC cmd_result_t
   1881 _l3_cmd_tunnel_init_add(int unit, args_t *a) 
   1882 {
   1883     bcm_tunnel_initiator_t tunnel_init;
   1884     bcm_l3_intf_t     intf;
   1885     bcm_tunnel_type_t type = 0;
   1886     parse_table_t     pt;     
   1887     cmd_result_t      retCode; 
   1888     bcm_ip6_t         sip6_addr;
   1889     bcm_ip6_t         ip6_addr;
   1890     bcm_mac_t         mac;
   1891     bcm_if_t          interface = 0;
   1892     bcm_ip_t          sip_addr = 0;
   1893     bcm_ip_t          ip_addr = 0;
   1894     int               ip4_df_sel = 0;
   1895     int               ip6_df_sel = 0;
   1896     int               dscp_val = 0;
   1897     int               dscp_sel = 0;
   1898     int               dscp_map = 0;
   1899     int               ttl = 0;
   1900     int               rv;
   1901 
   1902 
   1903     /* Stack variables initialization. */
   1904     sal_memset(&intf, 0, sizeof(bcm_l3_intf_t));
   1905     sal_memset(sip6_addr, 0, sizeof(bcm_ip6_t));
   1906     sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t));
   1907     sal_memset(mac, 0, sizeof(bcm_mac_t));
   1908 
   1909     parse_table_init(unit, &pt);
   1910     parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   1911     parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&type, 0);
   1912     parse_table_add(&pt, "TTL",  PQ_DFL|PQ_INT, 0, (void*)&ttl, 0);
   1913     parse_table_add(&pt, "Mac",  PQ_DFL|PQ_MAC, 0, (void *)mac, 0);
   1914     parse_table_add(&pt, "DIP",  PQ_DFL|PQ_IP, 0, (void *)&ip_addr, 0);
   1915     parse_table_add(&pt, "SIP",  PQ_DFL|PQ_IP, 0, (void *)&sip_addr, 0);
   1916     parse_table_add(&pt, "DIP6", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   1917     parse_table_add(&pt, "SIP6", PQ_DFL | PQ_IP6, 0, (void *)&sip6_addr, 0);
   1918     parse_table_add(&pt, "DSCPSel", PQ_DFL|PQ_INT, 0, (void *)&dscp_sel, 0);
   1919     parse_table_add(&pt, "DSCPV", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0);
   1920     parse_table_add(&pt, "DFSEL4", PQ_DFL|PQ_INT, 0, (void *)&ip4_df_sel, 0);
   1921     parse_table_add(&pt, "DFSEL6", PQ_DFL|PQ_BOOL, 0, (void *)&ip6_df_sel, 0);
   1922     parse_table_add(&pt, "DSCPMap", PQ_DFL|PQ_INT, 0, (void *)&dscp_map, 0);
   1923     if (!parseEndOk(a, &pt, &retCode)) {
   1924         return retCode;
   1925     }
   1926 
   1927     /* Initialize data structures. */
   1928     bcm_l3_intf_t_init(&intf);
   1929     bcm_tunnel_initiator_t_init(&tunnel_init);
   1930 
   1931     /* Fill tunnel info. */
   1932     intf.l3a_intf_id = interface;
   1933     tunnel_init.type = type;
   1934     tunnel_init.ttl = ttl;
   1935 
   1936     sal_memcpy(tunnel_init.dmac, mac, sizeof(mac));
   1937 
   1938     if (ip4_df_sel) { 
   1939         tunnel_init.flags |= (ip4_df_sel > 1) ?
   1940             BCM_TUNNEL_INIT_USE_INNER_DF : BCM_TUNNEL_INIT_IPV4_SET_DF;
   1941     }
   1942     if (ip6_df_sel) { 
   1943         tunnel_init.flags |= BCM_TUNNEL_INIT_IPV6_SET_DF;
   1944     }
   1945 
   1946     sal_memcpy(tunnel_init.dip6, ip6_addr, sizeof(bcm_ip6_t));
   1947     sal_memcpy(tunnel_init.sip6, sip6_addr, sizeof(bcm_ip6_t));
   1948     tunnel_init.dip = ip_addr;
   1949     tunnel_init.sip = sip_addr;
   1950     tunnel_init.dscp_sel = dscp_sel;
   1951     tunnel_init.dscp = dscp_val;
   1952     tunnel_init.dscp_map = dscp_map;
   1953 
   1954     if ((rv = bcm_tunnel_initiator_set(unit, &intf, &tunnel_init)) < 0) {
   1955         cli_out("ERROR %s: setting tunnel initiator for %d %s\n",
   1956                 ARG_CMD(a), interface, bcm_errmsg(rv));
   1957         return CMD_FAIL;
   1958     }
   1959     return CMD_OK;
   1960 }
   1961 
   1962 /*
   1963  * Function:
   1964  *      _l3_cmd_tunnel_init_show
   1965  * Description:
   1966  * 	    Service routine used to get & show tunnel initiator info. 
   1967  * Parameters:
   1968  *      unit      - (IN) Device number.
   1969  *      a         - (IN) Command arguments. 
   1970  * Returns: 
   1971  *      CMD_XXX
   1972  */
   1973 STATIC cmd_result_t
   1974 _l3_cmd_tunnel_init_show(int unit, args_t *a) 
   1975 {
   1976     bcm_tunnel_initiator_t tunnel_init;
   1977     bcm_l3_intf_t          intf;
   1978     parse_table_t          pt;     
   1979     cmd_result_t           retCode; 
   1980     bcm_if_t               interface;
   1981     int                    rv;
   1982 
   1983     parse_table_init(unit, &pt);
   1984     parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   1985     if (!parseEndOk(a, &pt, &retCode)) {
   1986         return retCode;
   1987     }
   1988 
   1989     bcm_tunnel_initiator_t_init(&tunnel_init);
   1990 
   1991     bcm_l3_intf_t_init(&intf);
   1992     intf.l3a_intf_id = interface;
   1993 
   1994     if ((rv = bcm_tunnel_initiator_get(unit, &intf, &tunnel_init)) < 0) {
   1995         cli_out("ERROR %s: getting tunnel initiator for %d %s\n",
   1996                 ARG_CMD(a), interface, bcm_errmsg(rv));
   1997         return CMD_FAIL;
   1998     }
   1999 
   2000     _l3_cmd_tunnel_init_print(unit, interface, &tunnel_init);
   2001     return CMD_OK;
   2002 }
   2003 
   2004 /*
   2005  * Function:
   2006  *      _l3_cmd_tunnel_init_clear
   2007  * Description:
   2008  * 	    Service routine used to remove tunnel initiator from an interface.
   2009  * Parameters:
   2010  *      unit      - (IN) Device number.
   2011  *      a         - (IN) Command arguments. 
   2012  * Returns: 
   2013  *      CMD_XXX
   2014  */
   2015 STATIC cmd_result_t
   2016 _l3_cmd_tunnel_init_clear(int unit, args_t *a) 
   2017 {
   2018     bcm_if_t               interface;
   2019     cmd_result_t           retCode; 
   2020     bcm_l3_intf_t          intf;
   2021     parse_table_t          pt;     
   2022     int                    rv;
   2023 
   2024     parse_table_init(unit, &pt);
   2025     parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   2026     if (!parseEndOk(a, &pt, &retCode)) {
   2027         return retCode;
   2028     }
   2029 
   2030     bcm_l3_intf_t_init(&intf);
   2031     intf.l3a_intf_id = interface;
   2032 
   2033     if ((rv = bcm_tunnel_initiator_clear(unit, &intf)) < 0) {
   2034         cli_out("ERROR %s: clearing tunnel initiator for %d %s\n",
   2035                 ARG_CMD(a), interface, bcm_errmsg(rv));
   2036         return CMD_FAIL;
   2037     }
   2038     return CMD_OK;
   2039 }
   2040 
   2041 /*
   2042  * Function:
   2043  *      _l3_cmd_tunnel_term_add
   2044  * Description:
   2045  * 	    Service routine used to add tunnel terminator entry.
   2046  * Parameters:
   2047  *      unit      - (IN) Device number.
   2048  *      a         - (IN) Command arguments. 
   2049  * Returns: 
   2050  *      CMD_XXX
   2051  */
   2052 STATIC cmd_result_t
   2053 _l3_cmd_tunnel_term_add(int unit, args_t *a) 
   2054 {
   2055     bcm_tunnel_terminator_t tunnel_term;
   2056     cmd_result_t      retCode; 
   2057     parse_table_t     pt;     
   2058     int               rv;
   2059     bcm_pbmp_t        pbmap;
   2060     bcm_ip6_t         sip6;
   2061     bcm_ip6_t         dip6;
   2062     int               vlan = 0;
   2063     int               dip = 0;
   2064     int               sip = 0;
   2065     int               sip_mask_len = 0; 
   2066     int               dip_mask_len = 0;
   2067     int               dport = 0; 
   2068     int               sport = 0; 
   2069     int               tnl_type = 0;
   2070     int               outer_ttl = 0;
   2071     int               outer_dscp = 0;
   2072     int               inner_dscp = 0;
   2073     int               trust_dscp = 0; 
   2074     int               allow_v4 = 0; 
   2075     int               allow_v6 = 0;
   2076     int               vrf = 0;
   2077     int               replace=0;
   2078     bcm_gport_t       remote_port = BCM_GPORT_INVALID;
   2079     bcm_gport_t       tunnel_id = 0;
   2080 
   2081     parse_table_init(unit, &pt);
   2082     sal_memset(sip6, 0, sizeof(bcm_ip6_t));
   2083     sal_memset(dip6, 0, sizeof(bcm_ip6_t));
   2084     sal_memset(&pbmap, 0, sizeof(bcm_pbmp_t));
   2085 
   2086     parse_table_add(&pt, "VRF",  PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   2087     parse_table_add(&pt, "DIP",  PQ_DFL|PQ_IP, 0, (void*)&dip, 0);
   2088     parse_table_add(&pt, "SIP",  PQ_DFL|PQ_IP, 0, (void*)&sip, 0);
   2089     parse_table_add(&pt, "DIP6",  PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0);
   2090     parse_table_add(&pt, "SIP6",  PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0);
   2091     parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0);
   2092     parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0);
   2093     parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0);
   2094     parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0);
   2095     parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0);
   2096     parse_table_add(&pt, "OuterDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&outer_dscp, 0);
   2097     parse_table_add(&pt, "OuterTTL", PQ_DFL|PQ_BOOL, 0, (void *)&outer_ttl, 0);
   2098     parse_table_add(&pt, "InnerDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&inner_dscp, 0);
   2099     parse_table_add(&pt, "TrustDSCP", PQ_DFL|PQ_BOOL, 0,(void *)&trust_dscp, 0);
   2100     parse_table_add(&pt, "VLanid", PQ_DFL|PQ_INT, 0, (void*)&vlan, 0);
   2101     parse_table_add(&pt, "AllowIPv6Payload", PQ_DFL|PQ_BOOL, 0, (void*)&allow_v4, 0);
   2102     parse_table_add(&pt, "AllowIPv4Payload", PQ_DFL|PQ_BOOL, 0, (void*)&allow_v6, 0);
   2103     parse_table_add(&pt, "PBMP", PQ_DFL|PQ_PBMP|PQ_BCM, 0, &pbmap, 0);
   2104     parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 0, &replace, 0);
   2105     parse_table_add(&pt, "RemoteTerminate", PQ_DFL|PQ_INT, 0, &remote_port, 0);
   2106     parse_table_add(&pt, "TunnelID", PQ_DFL|PQ_INT, 0, (void*)&tunnel_id, 0);
   2107 
   2108     if (!parseEndOk(a, &pt, &retCode)) {
   2109         return retCode;
   2110     }
   2111 
   2112     sal_memset(&tunnel_term, 0, sizeof (tunnel_term));
   2113 
   2114     if ((tnl_type == bcmTunnelTypeWlanWtpToAc) || 
   2115         (tnl_type == bcmTunnelTypeWlanAcToAc) ||
   2116         (tnl_type == bcmTunnelTypeWlanWtpToAc6) || 
   2117         (tnl_type == bcmTunnelTypeWlanAcToAc6)) { 
   2118         tunnel_term.flags |= BCM_TUNNEL_TERM_TUNNEL_WITH_ID;
   2119         tunnel_term.tunnel_id = tunnel_id;
   2120         if (remote_port != BCM_GPORT_INVALID) {
   2121             tunnel_term.flags |= BCM_TUNNEL_TERM_WLAN_REMOTE_TERMINATE;
   2122             tunnel_term.remote_port = remote_port;
   2123         }
   2124     }
   2125 
   2126     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) {
   2127         sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t));
   2128         sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t));
   2129         bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len);
   2130         bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len);
   2131     } else {
   2132         tunnel_term.sip = sip;
   2133         tunnel_term.dip = dip;
   2134         tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len);
   2135         tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len);
   2136     }
   2137 
   2138     tunnel_term.udp_dst_port = dport;
   2139     tunnel_term.udp_src_port = sport;
   2140     tunnel_term.type = tnl_type;
   2141     tunnel_term.vrf = vrf;
   2142 
   2143     if (outer_dscp) {
   2144         tunnel_term.flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   2145     }
   2146 
   2147     if (outer_ttl) {
   2148         tunnel_term.flags |= BCM_TUNNEL_TERM_USE_OUTER_TTL;
   2149     }
   2150     if (inner_dscp) {
   2151         tunnel_term.flags |= BCM_TUNNEL_TERM_KEEP_INNER_DSCP;
   2152     }
   2153 
   2154     if (trust_dscp) {
   2155         tunnel_term.flags |= BCM_TUNNEL_TERM_DSCP_TRUST;
   2156     }
   2157 
   2158     if (replace) {
   2159         tunnel_term.flags |= BCM_TUNNEL_REPLACE;
   2160     }
   2161 
   2162     tunnel_term.vlan = (bcm_vlan_t)vlan;
   2163     tunnel_term.pbmp = pbmap;
   2164 
   2165     if ((rv = bcm_tunnel_terminator_add(unit, &tunnel_term)) < 0) {
   2166         cli_out("ERROR %s: adding tunnel term %s\n",
   2167                 ARG_CMD(a), bcm_errmsg(rv));
   2168         return CMD_FAIL;
   2169     }
   2170     return CMD_OK;
   2171 }
   2172 
   2173 /*
   2174  * Function:
   2175  *      _l3_cmd_tunnel_term_delete
   2176  * Description:
   2177  * 	    Service routine used to delete tunnel terminator entry.
   2178  * Parameters:
   2179  *      unit      - (IN) Device number.
   2180  *      a         - (IN) Command arguments. 
   2181  * Returns: 
   2182  *      CMD_XXX
   2183  */
   2184 STATIC cmd_result_t
   2185 _l3_cmd_tunnel_term_delete(int unit, args_t *a) 
   2186 {
   2187     bcm_tunnel_terminator_t tunnel_term;
   2188     cmd_result_t      retCode; 
   2189     parse_table_t     pt;     
   2190     int               rv;
   2191     bcm_ip6_t         sip6;
   2192     bcm_ip6_t         dip6;
   2193     int               dip = 0;
   2194     int               sip = 0;
   2195     int               sip_mask_len = 0; 
   2196     int               dip_mask_len = 0;
   2197     int               tnl_type = 0;
   2198     int               vrf = 0;
   2199     int               dport = 0;
   2200     int               sport = 0;
   2201 
   2202     parse_table_init(unit, &pt);
   2203     sal_memset(sip6, 0, sizeof(bcm_ip6_t));
   2204     sal_memset(dip6, 0, sizeof(bcm_ip6_t));
   2205 
   2206     parse_table_add(&pt, "VRF",  PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   2207     parse_table_add(&pt, "DIP",  PQ_DFL|PQ_IP, 0, (void*)&dip, 0);
   2208     parse_table_add(&pt, "SIP",  PQ_DFL|PQ_IP, 0, (void*)&sip, 0);
   2209     parse_table_add(&pt, "DIP6",  PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0);
   2210     parse_table_add(&pt, "SIP6",  PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0);
   2211     parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0);
   2212     parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0);
   2213     parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0);
   2214     parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0);
   2215     parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0);
   2216 
   2217     if (!parseEndOk(a, &pt, &retCode)) {
   2218         return retCode;
   2219     }
   2220 
   2221     sal_memset(&tunnel_term, 0, sizeof (tunnel_term));
   2222 
   2223 
   2224     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) {
   2225         sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t));
   2226         sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t));
   2227         bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len);
   2228         bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len);
   2229     } else {
   2230         tunnel_term.sip = sip;
   2231         tunnel_term.dip = dip;
   2232         tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len);
   2233         tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len);
   2234     }
   2235 
   2236     tunnel_term.udp_dst_port = dport;
   2237     tunnel_term.udp_src_port = sport;
   2238     tunnel_term.type = tnl_type;
   2239     tunnel_term.vrf = vrf;
   2240 
   2241     if ((rv = bcm_tunnel_terminator_delete(unit, &tunnel_term)) < 0) {
   2242         cli_out("ERROR %s: adding tunnel term %s\n",
   2243                 ARG_CMD(a), bcm_errmsg(rv));
   2244         return CMD_FAIL;
   2245     }
   2246     return CMD_OK;
   2247 }
   2248 
   2249 /*
   2250  * Function:
   2251  *      _l3_cmd_tunnel_term_get
   2252  * Description:
   2253  * 	    Service routine used to read tunnel terminator entry.
   2254  * Parameters:
   2255  *      unit      - (IN) Device number.
   2256  *      a         - (IN) Command arguments. 
   2257  * Returns: 
   2258  *      CMD_XXX
   2259  */
   2260 STATIC cmd_result_t
   2261 _l3_cmd_tunnel_term_get(int unit, args_t *a) 
   2262 {
   2263     bcm_tunnel_terminator_t tunnel_term;
   2264     cmd_result_t      retCode; 
   2265     parse_table_t     pt;     
   2266     int               rv;
   2267     bcm_ip6_t         sip6;
   2268     bcm_ip6_t         dip6;
   2269     int               vlan = 0;
   2270     int               dip = 0;
   2271     int               sip = 0;
   2272     int               sip_mask_len = 0; 
   2273     int               dip_mask_len = 0;
   2274     int               tnl_type = 0;
   2275     int               vrf = 0;
   2276     int               dport = 0;
   2277     int               sport = 0;
   2278 
   2279     parse_table_init(unit, &pt);
   2280     sal_memset(sip6, 0, sizeof(bcm_ip6_t));
   2281     sal_memset(dip6, 0, sizeof(bcm_ip6_t));
   2282     sal_memset(&tunnel_term, 0, sizeof(bcm_tunnel_terminator_t));
   2283 
   2284     parse_table_add(&pt, "VRF",  PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   2285     parse_table_add(&pt, "DIP",  PQ_DFL|PQ_IP, 0, (void*)&dip, 0);
   2286     parse_table_add(&pt, "SIP",  PQ_DFL|PQ_IP, 0, (void*)&sip, 0);
   2287     parse_table_add(&pt, "DIP6",  PQ_DFL|PQ_IP6, 0, (void*)&dip6, 0);
   2288     parse_table_add(&pt, "SIP6",  PQ_DFL|PQ_IP6, 0, (void*)&sip6, 0);
   2289     parse_table_add(&pt, "DipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&dip_mask_len, 0);
   2290     parse_table_add(&pt, "SipMaskLen", PQ_DFL|PQ_INT, 0, (void*)&sip_mask_len, 0);
   2291     parse_table_add(&pt, "TYpe", PQ_DFL|PQ_INT, 0, (void*)&tnl_type, 0);
   2292     parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 0, (void*)&dport, 0);
   2293     parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 0, (void*)&sport, 0);
   2294     parse_table_add(&pt, "VLAN", PQ_DFL|PQ_INT, 0, (void*)&vlan, 0);
   2295 
   2296     if (!parseEndOk(a, &pt, &retCode)) {
   2297         return retCode;
   2298     }
   2299 
   2300     sal_memset(&tunnel_term, 0, sizeof (tunnel_term));
   2301 
   2302 
   2303     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_type)) {
   2304         sal_memcpy(tunnel_term.sip6, sip6, sizeof(bcm_ip6_t));
   2305         sal_memcpy(tunnel_term.dip6, dip6, sizeof(bcm_ip6_t));
   2306         bcm_ip6_mask_create(tunnel_term.sip6_mask, sip_mask_len);
   2307         bcm_ip6_mask_create(tunnel_term.dip6_mask, dip_mask_len);
   2308     } else {
   2309         tunnel_term.sip = sip;
   2310         tunnel_term.dip = dip;
   2311         tunnel_term.sip_mask = bcm_ip_mask_create(sip_mask_len);
   2312         tunnel_term.dip_mask = bcm_ip_mask_create(dip_mask_len);
   2313     }
   2314 
   2315     tunnel_term.udp_dst_port = dport;
   2316     tunnel_term.udp_src_port = sport;
   2317     tunnel_term.type = tnl_type;
   2318     tunnel_term.vrf = vrf;
   2319     tunnel_term.vlan = (bcm_vlan_t)vlan;
   2320 
   2321     if ((rv = bcm_tunnel_terminator_get(unit, &tunnel_term)) < 0) {
   2322         cli_out("ERROR %s: adding tunnel term %s\n",
   2323                 ARG_CMD(a), bcm_errmsg(rv));
   2324         return CMD_FAIL;
   2325     }
   2326 
   2327     _l3_cmd_tunnel_term_print(unit, &tunnel_term);
   2328     return CMD_OK;
   2329 }
   2330 
   2331 /*
   2332  * Function:
   2333  *      _l3_cmd_dscp_map_add
   2334  * Description:
   2335  * 	    Service routine used to add dscp map object.
   2336  * Parameters:
   2337  *      unit      - (IN) Device number.
   2338  *      a         - (IN) Command arguments. 
   2339  * Returns: 
   2340  *      CMD_XXX
   2341  */
   2342 STATIC cmd_result_t
   2343 _l3_cmd_dscp_map_add(int unit, args_t *a) 
   2344 {
   2345     int dscp_map_id = -1;
   2346     int               rv;
   2347 
   2348     rv = bcm_tunnel_dscp_map_create(unit, 0, &dscp_map_id);
   2349     if (BCM_FAILURE(rv)) {
   2350         cli_out("%s: Failed to create egress dscp map id: %s\n",
   2351                 ARG_CMD(a), bcm_errmsg(rv));
   2352         return (CMD_FAIL);
   2353     } else {
   2354         cli_out("%s: Returned DSCP Map ID %d\n", ARG_CMD(a), dscp_map_id);
   2355     }
   2356     return (CMD_OK);
   2357 }
   2358 
   2359 /*
   2360  * Function:
   2361  *      _l3_cmd_dscp_map_delete
   2362  * Description:
   2363  * 	    Service routine used to delete dscp map object.
   2364  * Parameters:
   2365  *      unit      - (IN) Device number.
   2366  *      a         - (IN) Command arguments. 
   2367  * Returns: 
   2368  *      CMD_XXX
   2369  */
   2370 STATIC cmd_result_t
   2371 _l3_cmd_dscp_map_delete(int unit, args_t *a) 
   2372 {
   2373     cmd_result_t      retCode; 
   2374     parse_table_t     pt;     
   2375     int               dscp_map_id = -1;
   2376     int               rv;
   2377 
   2378     parse_table_init(unit, &pt);
   2379     parse_table_add(&pt, "DscpMapId", PQ_DFL|PQ_INT, 0, (void*)&dscp_map_id, 0);
   2380     if (!parseEndOk(a, &pt, &retCode)) {
   2381         return retCode;
   2382     }
   2383 
   2384     if (-1 == dscp_map_id) {
   2385         return(CMD_USAGE);
   2386     }
   2387 
   2388     rv = bcm_tunnel_dscp_map_destroy(unit, dscp_map_id);
   2389     if (BCM_FAILURE(rv)) {
   2390         cli_out("%s: Error deleting entry from egress : %s\n",
   2391                 ARG_CMD(a), bcm_errmsg(rv));
   2392         return (CMD_FAIL);
   2393     } 
   2394     return (CMD_OK);
   2395 }
   2396 /*
   2397  * Function:
   2398  *      _l3_cmd_dscp_map_port_set
   2399  * Description:
   2400  * 	    Service routine used to set dscp map priority, color -> dscp mapping.
   2401  * Parameters:
   2402  *      unit      - (IN) Device number.
   2403  *      a         - (IN) Command arguments. 
   2404  * Returns: 
   2405  *      CMD_XXX
   2406  */
   2407 STATIC cmd_result_t
   2408 _l3_cmd_dscp_map_port_set(int unit, args_t *a) 
   2409 {
   2410     parse_table_t     pt;     
   2411     bcm_tunnel_dscp_map_t dscp_map;
   2412     int prio, color, dscp_val;
   2413     cmd_result_t      retCode; 
   2414     bcm_port_t        port = -1;
   2415     int rv;
   2416 
   2417     parse_table_init(unit, &pt);
   2418     parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 0, (void*)&port, 0);
   2419     parse_table_add(&pt, "Priority", PQ_DFL|PQ_INT, 0, (void*)&prio, 0);
   2420     parse_table_add(&pt, "Color",  PQ_DFL|PQ_INT, 0, (void*)&color, 0);
   2421     parse_table_add(&pt, "DSCPValue", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0);
   2422     if (!parseEndOk(a, &pt, &retCode)) {
   2423         return retCode;
   2424     }
   2425 
   2426     if (-1 == port) {
   2427         return (CMD_USAGE);
   2428     }
   2429 
   2430     dscp_map.priority = prio;
   2431     dscp_map.color = color;
   2432     dscp_map.dscp = dscp_val;
   2433 
   2434     rv = bcm_tunnel_dscp_map_port_set(unit, port, &dscp_map);
   2435 
   2436     if (BCM_FAILURE(rv)) {
   2437         cli_out("ERROR %s: setting tunnel DSCP Map for port %d %s\n",
   2438                 ARG_CMD(a), port, bcm_errmsg(rv));
   2439         return (CMD_FAIL);
   2440     }
   2441     return (CMD_OK);
   2442 }
   2443 
   2444 /*
   2445  * Function:
   2446  *      _l3_cmd_dscp_map_port_show
   2447  * Description:
   2448  * 	    Service routine used to show dscp map object.
   2449  * Parameters:
   2450  *      unit      - (IN) Device number.
   2451  *      a         - (IN) Command arguments. 
   2452  * Returns: 
   2453  *      CMD_XXX
   2454  */
   2455 STATIC cmd_result_t
   2456 _l3_cmd_dscp_map_port_show(int unit, args_t *a) 
   2457 {
   2458     parse_table_t     pt;     
   2459     bcm_tunnel_dscp_map_t dscp_map;
   2460     int prio;
   2461     cmd_result_t      retCode; 
   2462     bcm_port_t port = -1;
   2463     int rv;
   2464 
   2465     parse_table_init(unit, &pt);
   2466     parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0,
   2467                     (void *)&port, 0);
   2468     if (!parseEndOk(a, &pt, &retCode))
   2469         return retCode;
   2470 
   2471     if (-1 == port) {
   2472         return(CMD_USAGE);
   2473     }
   2474 
   2475     cli_out("\nDSCP Map for port %d:\n", port);
   2476     cli_out("\n-----------\n");
   2477     for (prio = 0; prio < 8; prio++) {
   2478         dscp_map.priority = prio;
   2479         dscp_map.color = bcmColorGreen;
   2480         rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map);
   2481         if (BCM_FAILURE(rv)) {
   2482             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2483             return CMD_FAIL;
   2484         }
   2485         cli_out(" Priority = %d, Color = Green,  DSCP = %d\n",
   2486                 prio, dscp_map.dscp);
   2487 
   2488         dscp_map.priority = prio;
   2489         dscp_map.color = bcmColorYellow;
   2490         rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map);
   2491         if (BCM_FAILURE(rv)) {
   2492             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2493             return CMD_FAIL;
   2494         }
   2495         cli_out(" Priority = %d, Color = Yellow, DSCP = %d\n",
   2496                 prio, dscp_map.dscp);
   2497 
   2498         dscp_map.priority = prio;
   2499         dscp_map.color = bcmColorRed;
   2500         rv = bcm_tunnel_dscp_map_port_get(unit, port, &dscp_map);
   2501         if (BCM_FAILURE(rv)) {
   2502             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2503             return CMD_FAIL;
   2504         }
   2505         cli_out(" Priority = %d, Color = Red,    DSCP = %d\n",
   2506                 prio, dscp_map.dscp);
   2507     }
   2508     return CMD_OK;
   2509 }
   2510 
   2511 
   2512 /*
   2513  * Function:
   2514  *      _l3_cmd_dscp_map_show
   2515  * Description:
   2516  * 	    Service routine used to set dscp map priority, color -> dscp mapping.
   2517  * Parameters:
   2518  *      unit      - (IN) Device number.
   2519  *      a         - (IN) Command arguments. 
   2520  * Returns: 
   2521  *      CMD_XXX
   2522  */
   2523 STATIC cmd_result_t
   2524 _l3_cmd_dscp_map_set(int unit, args_t *a) 
   2525 {
   2526     parse_table_t     pt;     
   2527     bcm_tunnel_dscp_map_t dscp_map;
   2528     int prio, color, dscp_val;
   2529     cmd_result_t      retCode; 
   2530     int dscp_map_id = -1;
   2531     int rv;
   2532 
   2533     parse_table_init(unit, &pt);
   2534     parse_table_add(&pt, "DscpMapId", PQ_DFL|PQ_INT, 0, 
   2535                     (void*)&dscp_map_id, 0);
   2536     parse_table_add(&pt, "Priority", PQ_DFL|PQ_INT, 0, (void*)&prio, 0);
   2537     parse_table_add(&pt, "Color",  PQ_DFL|PQ_INT, 0, (void*)&color, 0);
   2538     parse_table_add(&pt, "DSCPValue", PQ_DFL|PQ_INT, 0, (void *)&dscp_val, 0);
   2539     if (!parseEndOk(a, &pt, &retCode)) {
   2540         return retCode;
   2541     }
   2542 
   2543     if (-1 == dscp_map_id) {
   2544         return(CMD_USAGE);
   2545     }
   2546 
   2547     dscp_map.priority = prio;
   2548     dscp_map.color = color;
   2549     dscp_map.dscp = dscp_val;
   2550 
   2551     rv = bcm_tunnel_dscp_map_set(unit, dscp_map_id, &dscp_map);
   2552 
   2553     if (BCM_FAILURE(rv)) {
   2554         cli_out("ERROR %s: setting tunnel DSCP Map for %d %s\n",
   2555                 ARG_CMD(a), dscp_map_id, bcm_errmsg(rv));
   2556         return (CMD_FAIL);
   2557     }
   2558     return (CMD_OK);
   2559 }
   2560 
   2561 /*
   2562  * Function:
   2563  *      _l3_cmd_dscp_map_show
   2564  * Description:
   2565  * 	    Service routine used to show dscp map object.
   2566  * Parameters:
   2567  *      unit      - (IN) Device number.
   2568  *      a         - (IN) Command arguments. 
   2569  * Returns: 
   2570  *      CMD_XXX
   2571  */
   2572 STATIC cmd_result_t
   2573 _l3_cmd_dscp_map_show(int unit, args_t *a) 
   2574 {
   2575     parse_table_t     pt;     
   2576     bcm_tunnel_dscp_map_t dscp_map;
   2577     int prio;
   2578     cmd_result_t      retCode; 
   2579     int dscp_map_id = -1;
   2580     int rv;
   2581 
   2582     parse_table_init(unit, &pt);
   2583     parse_table_add(&pt, "DscpMapId", PQ_DFL | PQ_INT, 0,
   2584                     (void *)&dscp_map_id, 0);
   2585     if (!parseEndOk(a, &pt, &retCode))
   2586         return retCode;
   2587 
   2588     if (-1 == dscp_map_id) {
   2589         return(CMD_USAGE);
   2590     }
   2591 
   2592     cli_out("\nDSCP Map %d:\n", dscp_map_id);
   2593     cli_out("\n-----------\n");
   2594     for (prio = 0; prio < 8; prio++) {
   2595         dscp_map.priority = prio;
   2596         dscp_map.color = bcmColorGreen;
   2597         rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map);
   2598         if (BCM_FAILURE(rv)) {
   2599             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2600             return CMD_FAIL;
   2601         }
   2602         cli_out(" Priority = %d, Color = Green,  DSCP = %d\n",
   2603                 prio, dscp_map.dscp);
   2604 
   2605         dscp_map.priority = prio;
   2606         dscp_map.color = bcmColorYellow;
   2607         rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map);
   2608         if (BCM_FAILURE(rv)) {
   2609             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2610             return CMD_FAIL;
   2611         }
   2612         cli_out(" Priority = %d, Color = Yellow, DSCP = %d\n",
   2613                 prio, dscp_map.dscp);
   2614 
   2615         dscp_map.priority = prio;
   2616         dscp_map.color = bcmColorRed;
   2617         rv = bcm_tunnel_dscp_map_get(unit, dscp_map_id, &dscp_map);
   2618         if (BCM_FAILURE(rv)) {
   2619             cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2620             return CMD_FAIL;
   2621         }
   2622         cli_out(" Priority = %d, Color = Red,    DSCP = %d\n",
   2623                 prio, dscp_map.dscp);
   2624     }
   2625     return CMD_OK;
   2626 }
   2627 
   2628 /*
   2629  * Function:
   2630  *      _l3_cmd_egress_intf_create
   2631  * Description:
   2632  * 	    Service routine used to create/add egress l3 interface.
   2633  * Parameters:
   2634  *      unit      - (IN) Device number.
   2635  *      a         - (IN) Command arguments. 
   2636  * Returns: 
   2637  *      CMD_XXX
   2638  */
   2639 STATIC cmd_result_t
   2640 _l3_cmd_egress_intf_create(int unit, args_t *a) 
   2641 {
   2642     cmd_result_t      retCode; 
   2643     parse_table_t     pt;     
   2644     int               rv;
   2645     bcm_mac_t         mac;
   2646     bcm_l3_intf_t     intf;
   2647     bcm_if_t          interface = -1;
   2648     int               vid = 0;
   2649 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2650     int               inner_vlan = 0;
   2651     bcm_vrf_t         vrf = 0;
   2652     bcm_if_group_t    group = 0;
   2653     int               mtu = 0;    
   2654     int               nat_realm = 0;
   2655 #endif /* BCM_XGS_SWITCH_SUPPORT */
   2656 
   2657     parse_table_init(unit, &pt);
   2658     sal_memset(mac, 0, sizeof(bcm_mac_t));
   2659     bcm_l3_intf_t_init(&intf);
   2660 
   2661     parse_table_init(unit, &pt);
   2662     parse_table_add(&pt, "Vlan", PQ_DFL|PQ_INT, 0, &vid, NULL);
   2663     parse_table_add(&pt, "Mac",  PQ_DFL|PQ_MAC, 0, mac, NULL);
   2664     parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   2665 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2666     parse_table_add(&pt, "InnerVlan", PQ_DFL|PQ_INT, 0, &inner_vlan, NULL);
   2667     parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   2668     parse_table_add(&pt, "Group", PQ_DFL | PQ_INT, 0, (void *)&group, 0);
   2669     parse_table_add(&pt, "MTU", PQ_DFL | PQ_INT, 0, (void *)&mtu, 0);
   2670     parse_table_add(&pt, "NATrealm", PQ_DFL | PQ_INT, 0, (void *)&nat_realm, 0);
   2671 #endif
   2672     if (!parseEndOk(a, &pt, &retCode)) {
   2673         return retCode;
   2674     }
   2675 
   2676     sal_memcpy(intf.l3a_mac_addr, mac, sizeof(bcm_mac_t));
   2677     intf.l3a_vid = (bcm_vlan_t) vid;
   2678     intf.l3a_flags |= BCM_L3_ADD_TO_ARL;
   2679     if (interface != -1) {
   2680         intf.l3a_intf_id = interface;
   2681         intf.l3a_flags |= BCM_L3_WITH_ID;
   2682     }
   2683 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2684     intf.l3a_vrf = vrf;
   2685     intf.l3a_group = group;
   2686     intf.l3a_mtu = mtu;
   2687     intf.l3a_inner_vlan = inner_vlan;
   2688     intf.l3a_nat_realm_id = nat_realm;
   2689 #endif
   2690     rv = bcm_l3_intf_create(unit, &intf);
   2691     if (BCM_FAILURE(rv)) {
   2692         cli_out("%s: Error creating entry to L3 Intf table: %s\n",
   2693                 ARG_CMD(a), bcm_errmsg(rv));
   2694         return (CMD_FAIL);
   2695     }
   2696     return (CMD_OK);
   2697 }
   2698 /*
   2699  * Function:
   2700  *      _l3_cmd_egress_intf_delete
   2701  * Description:
   2702  * 	    Service routine used to remove egress l3 interface.
   2703  * Parameters:
   2704  *      unit      - (IN) Device number.
   2705  *      a         - (IN) Command arguments. 
   2706  * Returns: 
   2707  *      CMD_XXX
   2708  */
   2709 STATIC cmd_result_t
   2710 _l3_cmd_egress_intf_delete(int unit, args_t *a) 
   2711 {
   2712     bcm_l3_intf_t     intf;
   2713     cmd_result_t      retCode; 
   2714     parse_table_t     pt;     
   2715     int               rv;
   2716     bcm_if_t          interface = -1;
   2717 
   2718     if (!ARG_CNT(a)) {
   2719         cli_out("Expected command parameters: Intf=id\n");
   2720         return (CMD_FAIL);
   2721     }
   2722 
   2723     parse_table_init(unit, &pt);
   2724     parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   2725     if (!parseEndOk(a, &pt, &retCode)) {
   2726         return retCode;
   2727     }
   2728 
   2729     bcm_l3_intf_t_init(&intf);
   2730     intf.l3a_intf_id = interface;
   2731     if (-1 == interface) {
   2732         cli_out("Expected command parameters: Intf=id\n");
   2733         return (CMD_FAIL);
   2734     }
   2735 
   2736     if ((rv = bcm_l3_intf_delete(unit, &intf)) < 0) {
   2737         cli_out("%s: Error (%s) destroy interface (%d)\n",
   2738                 ARG_CMD(a), bcm_errmsg(rv), interface);
   2739         return (CMD_FAIL);
   2740     }
   2741 
   2742     return (CMD_OK);
   2743 }
   2744 
   2745 
   2746 /*
   2747  * Function:
   2748  *      _l3_cmd_egress_intf_delete_all
   2749  * Description:
   2750  * 	    Service routine used to flush all egress l3 interfaces.
   2751  * Parameters:
   2752  *      unit      - (IN) Device number.
   2753  *      a         - (IN) Command arguments. 
   2754  * Returns: 
   2755  *      CMD_XXX
   2756  */
   2757 STATIC cmd_result_t
   2758 _l3_cmd_egress_intf_delete_all(int unit, args_t *a) 
   2759 {
   2760     int             rv;
   2761     int             idx;
   2762     bcm_l3_intf_t   intf;
   2763     bcm_l3_info_t   l3_hw_status;
   2764 
   2765     if ((rv = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   2766         cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(rv));
   2767         return CMD_FAIL;
   2768     }
   2769 
   2770     bcm_l3_intf_t_init(&intf);
   2771     for (idx = 0; idx < l3_hw_status.l3info_max_intf; idx++) {
   2772         intf.l3a_intf_id = idx;
   2773         rv = bcm_l3_intf_delete(unit, &intf);
   2774 
   2775         if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   2776             cli_out("%s: Error destroy interface %d from L3 Intf"
   2777                     "table: %s\n", ARG_CMD(a), idx, bcm_errmsg(rv));
   2778             return (CMD_FAIL);
   2779         }
   2780     }
   2781     return (CMD_OK);
   2782 }
   2783 
   2784 /*
   2785  * Function:
   2786  *      _l3_cmd_egress_intf_show
   2787  * Description:
   2788  * 	    Service routine used to show l3 egress interfaces.
   2789  * Parameters:
   2790  *      unit      - (IN) Device number.
   2791  *      a         - (IN) Command arguments. 
   2792  * Returns: 
   2793  *      CMD_XXX
   2794  */
   2795 STATIC cmd_result_t
   2796 _l3_cmd_egress_intf_show(int unit, args_t *a) 
   2797 {
   2798     int             rv;
   2799     parse_table_t   pt;     
   2800     bcm_l3_intf_t   intf;
   2801     cmd_result_t    retCode;
   2802     bcm_l3_info_t   l3_hw_status;
   2803     int             free_l3intf;
   2804     int             print_hdr = TRUE;
   2805     bcm_if_t        interface = -1;
   2806     int             min_idx, max_idx;
   2807 
   2808     if ((rv = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   2809         cli_out("Error in L3 info access: %s\n",  bcm_errmsg(rv));
   2810         return CMD_FAIL;
   2811     }
   2812 
   2813     free_l3intf  = l3_hw_status.l3info_max_intf -
   2814         l3_hw_status.l3info_occupied_intf;
   2815 
   2816 
   2817     if (ARG_CNT(a)) {
   2818         parse_table_init(unit, &pt);
   2819         parse_table_add(&pt, "INtf", PQ_DFL|PQ_INT, 0, (void*)&interface, 0);
   2820         if (!parseEndOk(a, &pt, &retCode)) {
   2821             return retCode;
   2822         }
   2823     }
   2824 
   2825     /* Min index and max interfaces number depend on this soc feature. */
   2826     if (soc_feature(unit, soc_feature_l3_egr_intf_zero_invalid)) {
   2827         min_idx = 1;
   2828         } else {
   2829         min_idx = 0;
   2830     }
   2831     max_idx = min_idx + (l3_hw_status.l3info_max_intf - 1);
   2832 
   2833     if (interface != -1) {
   2834         if ((interface < 0)  || (interface > max_idx)) {
   2835             cli_out("Invalid interface index: %d\n", interface);
   2836             return (CMD_FAIL);
   2837         }  
   2838     }
   2839 
   2840     cli_out("Free L3INTF entries: %d\n", free_l3intf);
   2841 
   2842     if (interface != -1) {
   2843         sal_memset(&intf, 0, sizeof (bcm_l3_intf_t));
   2844         intf.l3a_intf_id = interface;
   2845         rv = bcm_l3_intf_get(unit, &intf);
   2846         if (BCM_SUCCESS(rv)) {
   2847             _l3_cmd_egress_intf_print(unit, TRUE, &intf);
   2848             return (CMD_OK);
   2849         } else {
   2850             cli_out("Error L3 interface %d: %s\n", interface, bcm_errmsg(rv));
   2851             return (CMD_FAIL);
   2852         }
   2853     }
   2854 
   2855     /* Note: last interface id is reserved for Copy To Cpu purposes. */
   2856     for (interface = min_idx; interface < max_idx; interface++) {
   2857         sal_memset(&intf, 0, sizeof (bcm_l3_intf_t));
   2858         intf.l3a_intf_id = interface;
   2859         rv = bcm_l3_intf_get(unit, &intf);
   2860         if (BCM_SUCCESS(rv)) {
   2861             _l3_cmd_egress_intf_print(unit, print_hdr, &intf);
   2862             print_hdr = FALSE;
   2863         } else if (rv == BCM_E_NOT_FOUND) {
   2864             continue;
   2865         } else if (BCM_FAILURE(rv)) {
   2866             cli_out("Error traverse l3 interfaces: %s\n", bcm_errmsg(rv));
   2867         }
   2868     }
   2869     return CMD_OK;
   2870 }
   2871 
   2872 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2873 /*
   2874  * Function:
   2875  *      _l3_cmd_egress_object_create
   2876  * Description:
   2877  * 	    Service routine used to create/update l3 egress object.
   2878  * Parameters:
   2879  *      unit      - (IN) Device number.
   2880  *      a         - (IN) Command arguments. 
   2881  * Returns: 
   2882  *      CMD_XXX
   2883  */
   2884 STATIC cmd_result_t
   2885 _l3_cmd_egress_object_create(int unit, args_t *a) 
   2886 {
   2887     cmd_result_t      retCode; 
   2888     parse_table_t     pt;     
   2889     int               rv;
   2890     bcm_mac_t         mac;
   2891     bcm_l3_egress_t   egress_object;
   2892     bcm_if_t          interface = -1;
   2893     bcm_port_t        port = 0;
   2894     bcm_module_t      module = 0;
   2895     bcm_trunk_t       trunk = -1;
   2896     int               l2tocpu = 0;
   2897     int               copytocpu = 0;
   2898     int               drop = 0;
   2899     int               l3mc = 0;
   2900     int               mpls_label = BCM_MPLS_LABEL_INVALID;
   2901     int               object_id = -1;
   2902     uint32            flags = 0;
   2903 
   2904     bcm_l3_egress_t_init(&egress_object);
   2905     sal_memset(mac, 0, sizeof(bcm_mac_t));
   2906 
   2907     parse_table_init(unit, &pt);
   2908     parse_table_add(&pt, "Mac",  PQ_DFL | PQ_MAC, 0, (void *)mac, 0);
   2909     parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   2910     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   2911     parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0);
   2912     parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0);
   2913     parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0);
   2914     parse_table_add(&pt, "CopyToCpu", PQ_DFL | PQ_BOOL, 0, (void *)&copytocpu, 0);
   2915     parse_table_add(&pt, "Drop", PQ_DFL | PQ_BOOL, 0, (void *)&drop, 0);
   2916     parse_table_add(&pt, "L3MC", PQ_DFL | PQ_BOOL, 0, (void *)&l3mc, 0);
   2917     parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0,
   2918                     (void *)&mpls_label, 0);
   2919     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   2920     if (!parseEndOk(a, &pt, &retCode))
   2921         return retCode;
   2922 
   2923     egress_object.intf   = interface;
   2924     egress_object.mpls_label = mpls_label;
   2925     sal_memcpy(egress_object.mac_addr, mac, sizeof(mac));
   2926 
   2927     if (BCM_GPORT_IS_SET(port)) {
   2928         egress_object.port = port;
   2929     } else {
   2930         egress_object.module = module;
   2931     if (trunk >= 0) {
   2932         egress_object.flags |= BCM_L3_TGID;
   2933         egress_object.trunk = trunk;
   2934     } else {
   2935         egress_object.port = port;
   2936     }
   2937     }
   2938 
   2939     if (l2tocpu) {
   2940         egress_object.flags |= BCM_L3_L2TOCPU;
   2941     }
   2942 
   2943     if (copytocpu) {
   2944         egress_object.flags |= (BCM_L3_COPY_TO_CPU);
   2945     }
   2946 
   2947     if (drop) {
   2948         egress_object.flags |= (BCM_L3_DST_DISCARD);
   2949     }
   2950 
   2951     if (l3mc) {
   2952         egress_object.flags |= (BCM_L3_IPMC);
   2953         if (MAC_ADDR_EQUAL(mac, _soc_mac_all_zeroes)){
   2954             /* Assert BCM_L3_KEEP_DSTMAC if no valid mac-da is assigned. */
   2955             egress_object.flags |= (BCM_L3_KEEP_DSTMAC);
   2956         }
   2957     }
   2958 
   2959     if (object_id >= 0) {
   2960         flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
   2961     }
   2962 
   2963 
   2964     rv = bcm_l3_egress_create(unit, flags, &egress_object, &object_id);
   2965     if (BCM_FAILURE(rv)) {
   2966         cli_out("%s: Error creating egress object entry: %s\n",
   2967                 ARG_CMD(a), bcm_errmsg(rv));
   2968         return (CMD_FAIL);
   2969     }
   2970 
   2971     var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE);
   2972     cli_out("New egress object index: %d\n", object_id);
   2973     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   2974     return (CMD_OK);
   2975 }
   2976 
   2977 /*
   2978  * Function:
   2979  *      _l3_cmd_egress_object_find
   2980  * Description:
   2981  * 	    Service routine used to locate id of l3 egress object.
   2982  * Parameters:
   2983  *      unit      - (IN) Device number.
   2984  *      a         - (IN) Command arguments. 
   2985  * Returns: 
   2986  *      CMD_XXX
   2987  */
   2988 STATIC cmd_result_t
   2989 _l3_cmd_egress_object_find(int unit, args_t *a) 
   2990 {
   2991     cmd_result_t      retCode; 
   2992     parse_table_t     pt;     
   2993     int               rv;
   2994     bcm_mac_t         mac;
   2995     bcm_l3_egress_t   egress_object;
   2996     bcm_if_t          interface = -1;
   2997     bcm_port_t        port = 0;
   2998     bcm_module_t      module = 0;
   2999     bcm_trunk_t       trunk = -1;
   3000     int               l2tocpu = 0;
   3001     int               l3mc = 0;
   3002     int               mpls_label = BCM_MPLS_LABEL_INVALID;
   3003     int               object_id = -1;
   3004 
   3005     bcm_l3_egress_t_init(&egress_object);
   3006     sal_memset(mac, 0, sizeof(bcm_mac_t));
   3007 
   3008     parse_table_init(unit, &pt);
   3009     parse_table_add(&pt, "Mac",  PQ_DFL | PQ_MAC, 0, (void *)mac, 0);
   3010     parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   3011     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   3012     parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0);
   3013     parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0);
   3014     parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0);
   3015     parse_table_add(&pt, "L3MC", PQ_DFL | PQ_BOOL, 0, (void *)&l3mc, 0);
   3016     parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0,
   3017                     (void *)&mpls_label, 0);
   3018     if (!parseEndOk(a, &pt, &retCode))
   3019         return retCode;
   3020 
   3021     egress_object.intf   = interface;
   3022     egress_object.mpls_label = mpls_label;
   3023     sal_memcpy(egress_object.mac_addr, mac, sizeof(mac));
   3024 
   3025     if (BCM_GPORT_IS_SET(port)) {
   3026         egress_object.port = port;
   3027     } else {
   3028         egress_object.module = module;
   3029     if (trunk >= 0) {
   3030         egress_object.flags |= BCM_L3_TGID;
   3031         egress_object.trunk = trunk;
   3032     } else {
   3033         egress_object.port = port;
   3034     }
   3035     }
   3036 
   3037     if (l2tocpu) {
   3038         egress_object.flags |= BCM_L3_L2TOCPU;
   3039     }
   3040 
   3041     if (l3mc) {
   3042         egress_object.flags |= BCM_L3_IPMC;
   3043         if (MAC_ADDR_EQUAL(mac, _soc_mac_all_zeroes)){
   3044             /* Assert BCM_L3_KEEP_DSTMAC if no valid mac-da is assigned. */
   3045             egress_object.flags |= (BCM_L3_KEEP_DSTMAC);
   3046         }
   3047     }
   3048 
   3049     rv = bcm_l3_egress_find(unit, &egress_object, &object_id);
   3050     if (BCM_FAILURE(rv)) {
   3051         if (rv != BCM_E_NOT_FOUND) {
   3052             cli_out("%s: Error finding egress object entry: %s\n",
   3053                     ARG_CMD(a), bcm_errmsg(rv));
   3054             return (CMD_FAIL);
   3055         }
   3056         cli_out("%s: Couldn't find entry\n",ARG_CMD(a));
   3057         return (CMD_OK);
   3058     }
   3059     var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE);
   3060     cli_out("Egress object interface id: %d\n", object_id);
   3061     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3062     return (CMD_OK);
   3063 }
   3064 
   3065 
   3066 /*
   3067  * Function:
   3068  *      _l3_cmd_egress_object_destroy
   3069  * Description:
   3070  * 	    Service routine used to destroy l3 egress object by id.
   3071  * Parameters:
   3072  *      unit      - (IN) Device number.
   3073  *      a         - (IN) Command arguments. 
   3074  * Returns: 
   3075  *      CMD_XXX
   3076  */
   3077 STATIC cmd_result_t
   3078 _l3_cmd_egress_object_destroy(int unit, args_t *a) 
   3079 {
   3080     int               rv;
   3081     int               object_id = -1;
   3082 
   3083     if (ARG_CNT(a)) {
   3084         if (!isint(ARG_CUR(a))) {
   3085             cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   3086             return (CMD_FAIL);
   3087         }
   3088         object_id = parse_integer(ARG_GET(a));
   3089     } else {
   3090         cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a));
   3091         return (CMD_FAIL);
   3092     }
   3093 
   3094     rv = bcm_l3_egress_destroy(unit, object_id);
   3095     if (BCM_FAILURE(rv))
   3096     { 
   3097         cli_out("%s: Error deleting egress object entry: %s\n", ARG_CMD(a),
   3098                 bcm_errmsg(rv));
   3099         return (CMD_FAIL);
   3100     }
   3101     return (CMD_OK);
   3102 }
   3103 
   3104 /*
   3105  * Function:
   3106  *      _l3_cmd_egress_object_show
   3107  * Description:
   3108  * 	    Service routine used to display l3 egress object/s.
   3109  *      specific one or all of them. 
   3110  * Parameters:
   3111  *      unit      - (IN) Device number.
   3112  *      a         - (IN) Command arguments. 
   3113  * Returns: 
   3114  *      CMD_XXX
   3115  */
   3116 STATIC cmd_result_t
   3117 _l3_cmd_egress_object_show(int unit, args_t *a) 
   3118 {
   3119     int               rv;
   3120     int               object_id = -1;
   3121     int               one_entry_only = 0;
   3122     bcm_l3_egress_t   egress_object;
   3123 
   3124     bcm_l3_egress_t_init(&egress_object);
   3125 
   3126     if (ARG_CNT(a)) {
   3127         if (!isint(ARG_CUR(a))) {
   3128             cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   3129             return (CMD_FAIL);
   3130         }
   3131         object_id = parse_integer(ARG_GET(a));
   3132         one_entry_only = 1;
   3133     }
   3134 
   3135     cli_out("Entry  Mac                 Vlan INTF PORT MOD MPLS_LABEL ToCpu Drop"
   3136             " RefCount L3MC\n");
   3137 
   3138     if (one_entry_only) {
   3139         rv = bcm_l3_egress_get(unit, object_id, &egress_object);
   3140         if (BCM_FAILURE(rv)) {
   3141             cli_out("%s: Error reading egress object entry: %s\n",
   3142                     ARG_CMD(a), bcm_errmsg(rv));
   3143             return (CMD_FAIL);
   3144         }
   3145         _l3_cmd_egress_obj_print(unit, object_id, &egress_object, NULL);
   3146     } else {
   3147         rv = bcm_l3_egress_traverse(unit, _l3_cmd_egress_obj_print, NULL);
   3148         if (BCM_FAILURE(rv)) {
   3149             cli_out("%s: Error reading egress object entry: %s\n",
   3150                     ARG_CMD(a), bcm_errmsg(rv));
   3151             return (CMD_FAIL);
   3152         }
   3153     }
   3154     return (CMD_OK);
   3155 }
   3156 
   3157 
   3158 /*
   3159  * Function:
   3160  *      _l3_cmd_egress_mpath_object_create
   3161  * Description:
   3162  * 	    Service routine used to create/update l3 multipath egress object.
   3163  * Parameters:
   3164  *      unit      - (IN) Device number.
   3165  *      a         - (IN) Command arguments. 
   3166  * Returns: 
   3167  *      CMD_XXX
   3168  */
   3169 STATIC cmd_result_t
   3170 _l3_cmd_egress_mpath_object_create(int unit, args_t *a) 
   3171 {
   3172     int               rv;
   3173     parse_table_t     pt;     
   3174     cmd_result_t      retCode; 
   3175     bcm_if_t          mpath_egr[32];
   3176     int               intf_count = 0;
   3177     int               object_id = -1;
   3178     int               flags = 0;
   3179 
   3180 
   3181     parse_table_init(unit, &pt);
   3182     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3183     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3184     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0);
   3185     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0);
   3186     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0);
   3187     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0);
   3188 
   3189     if (!parseEndOk(a, &pt, &retCode))  {
   3190         return retCode;
   3191     }
   3192 
   3193     if (object_id >= 0) {
   3194         flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
   3195     }
   3196 
   3197     rv = bcm_l3_egress_multipath_create(unit, flags, intf_count,
   3198                                         mpath_egr, &object_id);
   3199     if (BCM_FAILURE(rv)) {
   3200         cli_out("%s: Error creating mpath egress object entry: %s\n",
   3201                 ARG_CMD(a), bcm_errmsg(rv));
   3202         return (CMD_FAIL);
   3203     }
   3204 
   3205     var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE);
   3206     cli_out("New multipath egress object index: %d\n", object_id);
   3207     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3208     return (CMD_OK);
   3209 }
   3210 
   3211 /*
   3212  * Function:
   3213  *      _l3_cmd_egress_mpath_object_max_create
   3214  * Description:
   3215  * 	    Service routine used to create l3 multipath egress object
   3216  * 	    with dynamic ecmp group sizing.
   3217  * Parameters:
   3218  *      unit      - (IN) Device number.
   3219  *      a         - (IN) Command arguments.
   3220  * Returns:
   3221  *      CMD_XXX
   3222  */
   3223 STATIC cmd_result_t
   3224 _l3_cmd_egress_mpath_object_max_create(int unit, args_t *a)
   3225 {
   3226     int               rv;
   3227     parse_table_t     pt;
   3228     cmd_result_t      retCode;
   3229     bcm_if_t          mpath_egr[32];
   3230     int               max_paths = 0;
   3231     int               intf_count = 0;
   3232     int               object_id = -1;
   3233     int               flags = 0;
   3234 
   3235 
   3236     parse_table_init(unit, &pt);
   3237     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3238     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3239     parse_table_add(&pt, "MaxGrpSize",  PQ_DFL | PQ_INT, 0, (void *)&max_paths, 0);
   3240     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0);
   3241     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0);
   3242     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0);
   3243     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0);
   3244 
   3245     if (!parseEndOk(a, &pt, &retCode))  {
   3246         return retCode;
   3247     }
   3248 
   3249     if (object_id >= 0) {
   3250         flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
   3251     }
   3252 
   3253     rv = bcm_l3_egress_multipath_max_create(unit, flags, max_paths, intf_count,
   3254                                         mpath_egr, &object_id);
   3255     if (BCM_FAILURE(rv)) {
   3256         cli_out("%s: Error creating mpath egress object entry: %s\n",
   3257                 ARG_CMD(a), bcm_errmsg(rv));
   3258         return (CMD_FAIL);
   3259     }
   3260 
   3261     var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE);
   3262     cli_out("New multipath egress object index: %d\n", object_id);
   3263     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3264     return (CMD_OK);
   3265 }
   3266 
   3267 /*
   3268  * Function:
   3269  *      _l3_cmd_egress_mpath_object_lookup
   3270  * Description:
   3271  * 	    Service routine used to search for matching l3
   3272  *      multipath egress object.
   3273  * Parameters:
   3274  *      unit      - (IN) Device number.
   3275  *      a         - (IN) Command arguments.
   3276  * Returns:
   3277  *      CMD_XXX
   3278  */
   3279 STATIC cmd_result_t
   3280 _l3_cmd_egress_mpath_object_lookup(int unit, args_t *a)
   3281 {
   3282     int               rv;
   3283     parse_table_t     pt;
   3284     cmd_result_t      retCode;
   3285     bcm_if_t          mpath_egr[32];
   3286     int               intf_count = 0;
   3287     int               object_id = -1;
   3288 
   3289     parse_table_init(unit, &pt);
   3290     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3291     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[0], 0);
   3292     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[1], 0);
   3293     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[2], 0);
   3294     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&mpath_egr[3], 0);
   3295     if (!parseEndOk(a, &pt, &retCode)) {
   3296         return retCode;
   3297     }
   3298     rv = bcm_l3_egress_multipath_find(unit, intf_count, mpath_egr, &object_id);
   3299 
   3300     if (BCM_FAILURE(rv)) {
   3301         if (rv != BCM_E_NOT_FOUND) {
   3302             cli_out("%s: Error finding mpath egress object entry: %s\n",
   3303                     ARG_CMD(a), bcm_errmsg(rv));
   3304             return CMD_FAIL;
   3305         }
   3306         cli_out("%s: Couldn't find the entry\n",ARG_CMD(a));
   3307         return CMD_OK;
   3308     }
   3309 
   3310     var_set_integer(ENV_EGRESS_OBJECT_ID, object_id, TRUE, FALSE);
   3311     cli_out("Egress mpath object interface id: %d\n", object_id);
   3312     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3313     return CMD_OK;
   3314 }
   3315 
   3316 /*
   3317  * Function:
   3318  *      _l3_cmd_egress_mpath_object_destroy
   3319  * Description:
   3320  * 	    Service routine used to destroy l3 multipath egress object.
   3321  * Parameters:
   3322  *      unit      - (IN) Device number.
   3323  *      a         - (IN) Command arguments.
   3324  * Returns:
   3325  *      CMD_XXX
   3326  */
   3327 STATIC cmd_result_t
   3328 _l3_cmd_egress_mpath_object_destroy(int unit, args_t *a)
   3329 {
   3330     int               rv;
   3331     int               object_id = -1;
   3332 
   3333     if (ARG_CNT(a)) {
   3334         if (!isint(ARG_CUR(a))) {
   3335             cli_out("%s: Invalid object id: %s\n", ARG_CMD(a), ARG_CUR(a));
   3336             return (CMD_FAIL);
   3337         }
   3338         object_id = parse_integer(ARG_GET(a));
   3339     } else {
   3340         cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a));
   3341         return (CMD_FAIL);
   3342     }
   3343 
   3344     rv = bcm_l3_egress_multipath_destroy(unit, object_id);
   3345     if (BCM_FAILURE(rv)) {
   3346         cli_out("%s: Error deleting mpath egress object entry: %s\n",
   3347                 ARG_CMD(a), bcm_errmsg(rv));
   3348         return (CMD_FAIL);
   3349     }
   3350     return (CMD_OK);
   3351 }
   3352 
   3353 /*
   3354  * Function:
   3355  *      _l3_cmd_egress_mpath_object_show
   3356  * Description:
   3357  * 	    Service routine used to display l3 multipath egress object.
   3358  * Parameters:
   3359  *      unit      - (IN) Device number.
   3360  *      a         - (IN) Command arguments.
   3361  * Returns:
   3362  *      CMD_XXX
   3363  */
   3364 STATIC cmd_result_t
   3365 _l3_cmd_egress_mpath_object_show(int unit, args_t *a)
   3366 {
   3367     int               rv;
   3368     bcm_if_t          *mpath_egr = NULL;
   3369     int               one_entry_only = 0;
   3370     int               intf_count = 0;
   3371     int               object_id = -1;
   3372 
   3373     if (ARG_CNT(a)) {
   3374         if (!isint(ARG_CUR(a))) {
   3375             cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   3376             return (CMD_FAIL);
   3377         }
   3378         object_id = parse_integer(ARG_GET(a));
   3379         one_entry_only = 1;
   3380     }
   3381 
   3382     if (one_entry_only) {
   3383         rv = bcm_l3_egress_multipath_get(unit, object_id, 0, NULL,
   3384                                          &intf_count);
   3385         mpath_egr = sal_alloc((intf_count * sizeof(int)), "ecmp group");
   3386         if (mpath_egr == NULL) {
   3387             cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(BCM_E_MEMORY));
   3388             return (CMD_FAIL);
   3389         }
   3390         rv = bcm_l3_egress_multipath_get(unit, object_id, intf_count,
   3391                                          mpath_egr, &intf_count);
   3392         if (BCM_FAILURE(rv)) {
   3393             sal_free(mpath_egr);
   3394             cli_out("%s: Error reading egress object entry: %s\n",
   3395                     ARG_CMD(a), bcm_errmsg(rv));
   3396             return (CMD_FAIL);
   3397         }
   3398         _l3_cmd_egress_mpath_obj_print(unit, object_id, intf_count,
   3399                                        mpath_egr, NULL);
   3400         sal_free(mpath_egr);
   3401     } else {
   3402         rv = bcm_l3_egress_multipath_traverse(unit,
   3403                                               _l3_cmd_egress_mpath_obj_print,
   3404                                               NULL);
   3405     }
   3406     if (BCM_FAILURE(rv)) {
   3407         return (CMD_FAIL);
   3408     }
   3409     return (CMD_OK);
   3410 }
   3411 
   3412 /*
   3413  * Function:
   3414  *      _l3_cmd_egress_mpath_object_intf_insert
   3415  * Description:
   3416  * 	    Service routine used to add an egress interface to multipath
   3417  *      egress object.
   3418  * Parameters:
   3419  *      unit      - (IN) Device number.
   3420  *      a         - (IN) Command arguments.
   3421  * Returns:
   3422  *      CMD_XXX
   3423  */
   3424 STATIC cmd_result_t
   3425 _l3_cmd_egress_mpath_object_intf_insert(int unit, args_t *a)
   3426 {
   3427     int               rv;
   3428     parse_table_t     pt;
   3429     cmd_result_t      retCode;
   3430     int               object_id = -1;
   3431     int               interface = 0;
   3432 
   3433     parse_table_init(unit, &pt);
   3434     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3435     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   3436 
   3437     if (!parseEndOk(a, &pt, &retCode))
   3438         return retCode;
   3439 
   3440     rv = bcm_l3_egress_multipath_add(unit, object_id, interface);
   3441     if (BCM_FAILURE(rv)) {
   3442         cli_out("%s: Error adding interface to egress obj: %s\n",
   3443                 ARG_CMD(a), bcm_errmsg(rv));
   3444         return (CMD_FAIL);
   3445     }
   3446     return (CMD_OK);
   3447 }
   3448 
   3449 
   3450 /*
   3451  * Function:
   3452  *      _l3_cmd_egress_mpath_object_intf_remove
   3453  * Description:
   3454  * 	    Service routine used to remove an egress interface
   3455  *      from multipath  egress object.
   3456  * Parameters:
   3457  *      unit      - (IN) Device number.
   3458  *      a         - (IN) Command arguments.
   3459  * Returns:
   3460  *      CMD_XXX
   3461  */
   3462 STATIC cmd_result_t
   3463 _l3_cmd_egress_mpath_object_intf_remove(int unit, args_t *a)
   3464 {
   3465     int               rv;
   3466     parse_table_t     pt;
   3467     cmd_result_t      retCode;
   3468     int               object_id = -1;
   3469     int               interface = 0;
   3470 
   3471     parse_table_init(unit, &pt);
   3472     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3473     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   3474 
   3475     if (!parseEndOk(a, &pt, &retCode))
   3476         return retCode;
   3477 
   3478     rv = bcm_l3_egress_multipath_delete(unit, object_id, interface);
   3479     if (BCM_FAILURE(rv)) {
   3480         cli_out("%s: Error deleting interface from egress obj: %s\n",
   3481                 ARG_CMD(a), bcm_errmsg(rv));
   3482         return (CMD_FAIL);
   3483     }
   3484     return (CMD_OK);
   3485 }
   3486 
   3487 /*
   3488  * Function:
   3489  *      _l3_cmd_egress_ecmp_object_create
   3490  * Description:
   3491  * 	    Service routine used to create/update l3 ecmp egress object.
   3492  * Parameters:
   3493  *      unit      - (IN) Device number.
   3494  *      a         - (IN) Command arguments.
   3495  * Returns:
   3496  *      CMD_XXX
   3497  */
   3498 STATIC cmd_result_t
   3499 _l3_cmd_egress_ecmp_object_create(int unit, args_t *a)
   3500 {
   3501     int               rv;
   3502     parse_table_t     pt;
   3503     cmd_result_t      retCode;
   3504     bcm_if_t          ecmp_egr[32];
   3505     int               intf_count = 0;
   3506     int               object_id = -1;
   3507     bcm_l3_egress_ecmp_t ecmp;
   3508 
   3509 
   3510     parse_table_init(unit, &pt);
   3511     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3512     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3513     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0);
   3514     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0);
   3515     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0);
   3516     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0);
   3517 
   3518     if (!parseEndOk(a, &pt, &retCode))  { 
   3519         return retCode;
   3520     }
   3521 
   3522     bcm_l3_egress_ecmp_t_init(&ecmp);
   3523     if (object_id >= 0) {
   3524         ecmp.flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
   3525         ecmp.ecmp_intf = object_id;
   3526     }
   3527 
   3528     rv = bcm_l3_egress_ecmp_create(unit, &ecmp, intf_count, ecmp_egr);
   3529     if (BCM_FAILURE(rv)) {
   3530         cli_out("%s: Error creating ecmp egress object entry: %s\n",
   3531                 ARG_CMD(a), bcm_errmsg(rv));
   3532         return (CMD_FAIL);
   3533     }
   3534 
   3535     var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE);
   3536     cli_out("New ecmp egress object index: %d\n", ecmp.ecmp_intf);
   3537     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3538     return (CMD_OK);
   3539 }
   3540 
   3541 /*
   3542  * Function:
   3543  *      _l3_cmd_egress_ecmp_object_max_create
   3544  * Description:
   3545  * 	    Service routine used to create l3 ecmp egress object
   3546  * 	    with dynamic ecmp group sizing.
   3547  * Parameters:
   3548  *      unit      - (IN) Device number.
   3549  *      a         - (IN) Command arguments. 
   3550  * Returns: 
   3551  *      CMD_XXX
   3552  */
   3553 STATIC cmd_result_t
   3554 _l3_cmd_egress_ecmp_object_max_create(int unit, args_t *a)
   3555 {
   3556     int               rv;
   3557     parse_table_t     pt;     
   3558     cmd_result_t      retCode; 
   3559     bcm_if_t          ecmp_egr[32];
   3560     int               max_paths = 0;
   3561     int               intf_count = 0;
   3562     int               object_id = -1;
   3563     bcm_l3_egress_ecmp_t ecmp;
   3564 
   3565 
   3566     parse_table_init(unit, &pt);
   3567     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3568     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3569     parse_table_add(&pt, "MaxGrpSize",  PQ_DFL | PQ_INT, 0, (void *)&max_paths, 0);
   3570     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0);
   3571     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0);
   3572     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0);
   3573     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0);
   3574 
   3575     if (!parseEndOk(a, &pt, &retCode))  { 
   3576         return retCode;
   3577     }
   3578 
   3579     bcm_l3_egress_ecmp_t_init(&ecmp);
   3580     if (object_id >= 0) {
   3581         ecmp.flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
   3582         ecmp.ecmp_intf = object_id;
   3583     }
   3584 
   3585     ecmp.max_paths = max_paths;
   3586     rv = bcm_l3_egress_ecmp_create(unit, &ecmp, intf_count, ecmp_egr);
   3587     if (BCM_FAILURE(rv)) {
   3588         cli_out("%s: Error creating ecmp egress object entry: %s\n",
   3589                 ARG_CMD(a), bcm_errmsg(rv));
   3590         return (CMD_FAIL);
   3591     }
   3592 
   3593     var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE);
   3594     cli_out("New ecmp egress object index: %d\n", ecmp.ecmp_intf);
   3595     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3596     return (CMD_OK);
   3597 }
   3598 
   3599 /*
   3600  * Function:
   3601  *      _l3_cmd_egress_ecmp_object_lookup
   3602  * Description:
   3603  * 	    Service routine used to search for matching l3 
   3604  *      ecmp egress object.
   3605  * Parameters:
   3606  *      unit      - (IN) Device number.
   3607  *      a         - (IN) Command arguments. 
   3608  * Returns: 
   3609  *      CMD_XXX
   3610  */
   3611 STATIC cmd_result_t
   3612 _l3_cmd_egress_ecmp_object_lookup(int unit, args_t *a)
   3613 {
   3614     int               rv;
   3615     parse_table_t     pt;     
   3616     cmd_result_t      retCode; 
   3617     bcm_if_t          ecmp_egr[32];
   3618     int               intf_count = 0;
   3619     bcm_l3_egress_ecmp_t ecmp;
   3620 
   3621     parse_table_init(unit, &pt);
   3622     parse_table_add(&pt, "Size",  PQ_DFL | PQ_INT, 0, (void *)&intf_count, 0);
   3623     parse_table_add(&pt, "Intf0", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[0], 0);
   3624     parse_table_add(&pt, "Intf1", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[1], 0);
   3625     parse_table_add(&pt, "Intf2", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[2], 0);
   3626     parse_table_add(&pt, "Intf3", PQ_DFL | PQ_INT, 0, (void *)&ecmp_egr[3], 0);
   3627     if (!parseEndOk(a, &pt, &retCode)) {
   3628         return retCode;
   3629     }
   3630 
   3631     bcm_l3_egress_ecmp_t_init(&ecmp);
   3632     rv = bcm_l3_egress_ecmp_find(unit, intf_count, ecmp_egr, &ecmp);
   3633 
   3634     if (BCM_FAILURE(rv)) {
   3635         if (rv != BCM_E_NOT_FOUND) {
   3636             cli_out("%s: Error finding ecmp egress object entry: %s\n",
   3637                     ARG_CMD(a), bcm_errmsg(rv));
   3638             return CMD_FAIL;
   3639         } 
   3640         cli_out("%s: Couldn't find the entry\n",ARG_CMD(a));
   3641         return CMD_OK;
   3642     }
   3643 
   3644     var_set_integer(ENV_EGRESS_OBJECT_ID, ecmp.ecmp_intf, TRUE, FALSE);
   3645     cli_out("Egress ecmp object interface id: %d\n", ecmp.ecmp_intf);
   3646     cli_out("Environment variable (%s) was set\n", ENV_EGRESS_OBJECT_ID);
   3647     return CMD_OK;
   3648 } 
   3649 
   3650 /*
   3651  * Function:
   3652  *      _l3_cmd_egress_ecmp_object_destroy
   3653  * Description:
   3654  * 	    Service routine used to destroy l3 ecmp egress object.
   3655  * Parameters:
   3656  *      unit      - (IN) Device number.
   3657  *      a         - (IN) Command arguments. 
   3658  * Returns: 
   3659  *      CMD_XXX
   3660  */
   3661 STATIC cmd_result_t
   3662 _l3_cmd_egress_ecmp_object_destroy(int unit, args_t *a)
   3663 {
   3664     int               rv;
   3665     int               object_id = -1;
   3666     bcm_l3_egress_ecmp_t ecmp;
   3667 
   3668     if (ARG_CNT(a)) {
   3669         if (!isint(ARG_CUR(a))) {
   3670             cli_out("%s: Invalid object id: %s\n", ARG_CMD(a), ARG_CUR(a));
   3671             return (CMD_FAIL);
   3672         }
   3673         object_id = parse_integer(ARG_GET(a));
   3674     } else {
   3675         cli_out("%s: Invalid arguments: %s\n", ARG_CMD(a), ARG_CUR(a));
   3676         return (CMD_FAIL);
   3677     }
   3678 
   3679     bcm_l3_egress_ecmp_t_init(&ecmp);
   3680     ecmp.ecmp_intf = object_id;
   3681     rv = bcm_l3_egress_ecmp_destroy(unit, &ecmp);
   3682     if (BCM_FAILURE(rv)) {
   3683         cli_out("%s: Error deleting ecmp egress object entry: %s\n",
   3684                 ARG_CMD(a), bcm_errmsg(rv));
   3685         return (CMD_FAIL);
   3686     }
   3687     return (CMD_OK);
   3688 }
   3689 
   3690 /*
   3691  * Function:
   3692  *      _l3_cmd_egress_ecmp_object_show
   3693  * Description:
   3694  * 	    Service routine used to display l3 ecmp egress object.
   3695  * Parameters:
   3696  *      unit      - (IN) Device number.
   3697  *      a         - (IN) Command arguments. 
   3698  * Returns: 
   3699  *      CMD_XXX
   3700  */
   3701 STATIC cmd_result_t
   3702 _l3_cmd_egress_ecmp_object_show(int unit, args_t *a)
   3703 {
   3704     int               rv;
   3705     bcm_if_t          *ecmp_egr = NULL;
   3706     int               one_entry_only = 0;
   3707     int               intf_count = 0;
   3708     int               object_id = -1;
   3709     bcm_l3_egress_ecmp_t ecmp;
   3710 
   3711     if (ARG_CNT(a)) {
   3712         if (!isint(ARG_CUR(a))) {
   3713             cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   3714             return (CMD_FAIL);
   3715         }
   3716         object_id = parse_integer(ARG_GET(a));
   3717         one_entry_only = 1;
   3718     }
   3719 
   3720     bcm_l3_egress_ecmp_t_init(&ecmp);
   3721     if (one_entry_only) {
   3722         ecmp.ecmp_intf = object_id;
   3723         rv = bcm_l3_egress_ecmp_get(unit, &ecmp, 0, NULL, &intf_count);
   3724         ecmp_egr = sal_alloc((intf_count * sizeof(int)), "ecmp group");
   3725         if (ecmp_egr == NULL) {
   3726             cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(BCM_E_MEMORY));
   3727             return (CMD_FAIL);
   3728         }
   3729         rv = bcm_l3_egress_ecmp_get(unit, &ecmp, intf_count, ecmp_egr,
   3730                                     &intf_count);
   3731         if (BCM_FAILURE(rv)) {
   3732             sal_free(ecmp_egr);
   3733             cli_out("%s: Error reading egress object entry: %s\n",
   3734                     ARG_CMD(a), bcm_errmsg(rv));
   3735             return (CMD_FAIL);
   3736         } 
   3737         _l3_cmd_egress_ecmp_obj_print(unit, &ecmp, intf_count, ecmp_egr,
   3738                                        NULL);
   3739         sal_free(ecmp_egr);
   3740     } else {
   3741         rv = bcm_l3_egress_ecmp_traverse(unit, _l3_cmd_egress_ecmp_obj_print,
   3742                                          NULL);
   3743     }
   3744     if (BCM_FAILURE(rv)) {
   3745         return (CMD_FAIL);
   3746     }
   3747     return (CMD_OK);
   3748 }
   3749 
   3750 /*
   3751  * Function:
   3752  *      _l3_cmd_egress_ecmp_object_intf_insert
   3753  * Description:
   3754  * 	    Service routine used to add an egress interface to ecmp
   3755  *      egress object. 
   3756  * Parameters:
   3757  *      unit      - (IN) Device number.
   3758  *      a         - (IN) Command arguments. 
   3759  * Returns: 
   3760  *      CMD_XXX
   3761  */
   3762 STATIC cmd_result_t
   3763 _l3_cmd_egress_ecmp_object_intf_insert(int unit, args_t *a)
   3764 {
   3765     int               rv;
   3766     parse_table_t     pt;     
   3767     cmd_result_t      retCode; 
   3768     int               object_id = -1;
   3769     int               interface = 0;
   3770     bcm_l3_egress_ecmp_t ecmp;
   3771 
   3772     parse_table_init(unit, &pt);
   3773     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3774     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   3775 
   3776     if (!parseEndOk(a, &pt, &retCode))
   3777         return retCode;
   3778 
   3779     bcm_l3_egress_ecmp_t_init(&ecmp);
   3780     ecmp.ecmp_intf = object_id;
   3781     rv = bcm_l3_egress_ecmp_add(unit, &ecmp, interface);
   3782     if (BCM_FAILURE(rv)) {
   3783         cli_out("%s: Error adding interface to egress obj: %s\n", 
   3784                 ARG_CMD(a), bcm_errmsg(rv));
   3785         return (CMD_FAIL);
   3786     }
   3787     return (CMD_OK);
   3788 }
   3789 
   3790 
   3791 /*
   3792  * Function:
   3793  *      _l3_cmd_egress_ecmp_object_intf_remove
   3794  * Description:
   3795  * 	    Service routine used to remove an egress interface 
   3796  *      from ecmp  egress object.
   3797  * Parameters:
   3798  *      unit      - (IN) Device number.
   3799  *      a         - (IN) Command arguments. 
   3800  * Returns: 
   3801  *      CMD_XXX
   3802  */
   3803 STATIC cmd_result_t
   3804 _l3_cmd_egress_ecmp_object_intf_remove(int unit, args_t *a)
   3805 {
   3806     int               rv;
   3807     parse_table_t     pt;     
   3808     cmd_result_t      retCode; 
   3809     int               object_id = -1;
   3810     int               interface = 0;
   3811     bcm_l3_egress_ecmp_t ecmp;
   3812 
   3813     parse_table_init(unit, &pt);
   3814     parse_table_add(&pt, "EgrId", PQ_DFL | PQ_INT, 0, (void *)&object_id, 0);
   3815     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   3816 
   3817     if (!parseEndOk(a, &pt, &retCode))
   3818         return retCode;
   3819 
   3820     bcm_l3_egress_ecmp_t_init(&ecmp);
   3821     ecmp.ecmp_intf = object_id;
   3822     rv = bcm_l3_egress_ecmp_delete(unit, &ecmp, interface);
   3823     if (BCM_FAILURE(rv)) {
   3824         cli_out("%s: Error deleting interface from egress obj: %s\n",
   3825                 ARG_CMD(a), bcm_errmsg(rv));
   3826         return (CMD_FAIL);
   3827     }
   3828     return (CMD_OK);
   3829 }
   3830 
   3831 /*
   3832  * Function:
   3833  *      _l3_cmd_prefix_map_add
   3834  * Description:
   3835  * 	    Service routine used to add prefix map.
   3836  * Parameters:
   3837  *      unit      - (IN) Device number.
   3838  *      a         - (IN) Command arguments. 
   3839  * Returns: 
   3840  *      CMD_XXX
   3841  */
   3842 STATIC cmd_result_t
   3843 _l3_cmd_prefix_map_add(int unit, args_t *a) 
   3844 {
   3845     bcm_ip6_t         ip6_addr;
   3846     cmd_result_t      retCode;
   3847     parse_table_t     pt;
   3848     int               rv;
   3849 
   3850     sal_memset(&ip6_addr, 0, sizeof(bcm_ip6_t));
   3851     parse_table_init(unit, &pt);
   3852 
   3853     parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   3854     if (!parseEndOk(a, &pt, &retCode))
   3855         return retCode;
   3856 
   3857     rv = bcm_l3_ip6_prefix_map_add(unit, ip6_addr);
   3858     if (BCM_FAILURE(rv)) {
   3859         cli_out("%s: Error adding ip6 prefix map: %s\n", ARG_CMD(a),
   3860                 bcm_errmsg(rv));
   3861         return (CMD_FAIL);
   3862     }
   3863     return (CMD_OK);
   3864 }
   3865 
   3866 /*
   3867  * Function:
   3868  *      _l3_cmd_prefix_map_delete
   3869  * Description:
   3870  * 	    Service routine used to delete prefix map.
   3871  * Parameters:
   3872  *      unit      - (IN) Device number.
   3873  *      a         - (IN) Command arguments. 
   3874  * Returns: 
   3875  *      CMD_XXX
   3876  */
   3877 STATIC cmd_result_t
   3878 _l3_cmd_prefix_map_delete(int unit, args_t *a) 
   3879 {
   3880     bcm_ip6_t         ip6_addr;
   3881     cmd_result_t      retCode;
   3882     parse_table_t     pt;
   3883     int               rv;
   3884 
   3885     sal_memset(&ip6_addr, 0, sizeof(bcm_ip6_t));
   3886     parse_table_init(unit, &pt);
   3887 
   3888     parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   3889     if (!parseEndOk(a, &pt, &retCode))
   3890         return retCode;
   3891 
   3892     rv = bcm_l3_ip6_prefix_map_delete(unit, ip6_addr);
   3893     if (BCM_FAILURE(rv)) {
   3894         cli_out("%s: Error adding ip6 prefix map: %s\n",
   3895                 ARG_CMD(a), bcm_errmsg(rv));
   3896         return (CMD_FAIL);
   3897     }
   3898     return (CMD_OK);
   3899 }
   3900 
   3901 /*
   3902  * Function:
   3903  *      _l3_cmd_prefix_map_delete_all
   3904  * Description:
   3905  * 	    Service routine used to flush all prefix maps.
   3906  * Parameters:
   3907  *      unit      - (IN) Device number.
   3908  *      a         - (IN) Command arguments. 
   3909  * Returns: 
   3910  *      CMD_XXX
   3911  */
   3912 STATIC cmd_result_t
   3913 _l3_cmd_prefix_map_delete_all(int unit, args_t *a) 
   3914 {
   3915     int               rv;
   3916 
   3917     if ((rv = bcm_l3_ip6_prefix_map_delete_all(unit)) < 0) {
   3918         cli_out("%s: Error flushing prefix map : %s\n",
   3919                 ARG_CMD(a), bcm_errmsg(rv));
   3920         return (CMD_FAIL);
   3921     } 
   3922     return (CMD_OK);
   3923 }
   3924 
   3925 #define BCM_DIAG_CMD_PREFIX_MAP_SIZE  (10)
   3926 /*
   3927  * Function:
   3928  *      _l3_cmd_prefix_map_show
   3929  * Description:
   3930  * 	    Service routine used display prefix maps.
   3931  * Parameters:
   3932  *      unit      - (IN) Device number.
   3933  *      a         - (IN) Command arguments. 
   3934  * Returns: 
   3935  *      CMD_XXX
   3936  */
   3937 STATIC cmd_result_t
   3938 _l3_cmd_prefix_map_show(int unit, args_t *a) 
   3939 {
   3940     int        rv;
   3941     int        idx;
   3942     bcm_ip6_t  prefix_map[BCM_DIAG_CMD_PREFIX_MAP_SIZE];
   3943     char       ip_str[IP6ADDR_STR_LEN + 3];
   3944     int        intf_count = 0;     
   3945 
   3946     rv = bcm_l3_ip6_prefix_map_get(unit,  BCM_DIAG_CMD_PREFIX_MAP_SIZE, 
   3947                                    prefix_map, &intf_count);
   3948     if (BCM_FAILURE(rv)) {
   3949         cli_out("%s: Error reading prefix map entry: %s\n",
   3950                 ARG_CMD(a), bcm_errmsg(rv));
   3951         return (CMD_FAIL);
   3952     } 
   3953 
   3954     if (intf_count > 0) {
   3955         cli_out("Entry  IP6_ADDR\n");
   3956     }
   3957 
   3958     for (idx = 0; idx < intf_count; idx++) {
   3959         format_ip6addr(ip_str, prefix_map[idx]);
   3960          cli_out("%-5d %s\n", idx, ip_str);
   3961     }
   3962 
   3963     return (CMD_OK);
   3964 }
   3965 #undef BCM_DIAG_CMD_PREFIX_MAP_SIZE 
   3966 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   3967 
   3968 /*
   3969  * Function:
   3970  *      _l3_cmd_route_add
   3971  * Description:
   3972  * 	    Service routine used to add route.
   3973  * Parameters:
   3974  *      unit      - (IN) Device number.
   3975  *      a         - (IN) Command arguments. 
   3976  *      v6        - (IN) IPv6 route indication.
   3977  * Returns:
   3978  *      CMD_XXX
   3979  */
   3980 STATIC cmd_result_t
   3981 _l3_cmd_route_add(int unit, args_t *a, int v6) 
   3982 {
   3983     bcm_l3_route_t  route_info;
   3984     cmd_result_t    retCode;
   3985     bcm_mac_t       mac;
   3986     parse_table_t   pt;
   3987     int             rv;
   3988     int             interface = 0;
   3989     bcm_ip_t        ip_addr = 0;
   3990     bcm_ip_t        ip_mask = 0;
   3991     int		        module = 0;
   3992     int             trunk = -1;
   3993     int             untag = 0;
   3994     int             port = 0;
   3995     int             hits = 0;
   3996     int             vlan = 0;
   3997     int             ipmc = 0;
   3998 #if defined(BCM_XGS_SWITCH_SUPPORT)
   3999     int             ecmp = 0;
   4000     int             local_route = 0;
   4001 #endif /* BCM_XGS_SWITCH_SUPPORT */
   4002 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4003     int             lookup_class = 0;
   4004     int             tunnel_opt = 0;
   4005     int             mpls_label = 0;
   4006     int             replace = 0;
   4007     int             rpe = 0;
   4008     int             pri = 0;
   4009     int             dst_discard = 0;
   4010     int             vrf = 0;
   4011     int             plen = 0;
   4012     bcm_ip6_t       ip6_addr;
   4013 #endif
   4014 
   4015     bcm_l3_route_t_init(&route_info);
   4016     sal_memset(mac, 0, sizeof(bcm_mac_t));
   4017     parse_table_init(unit, &pt);
   4018 
   4019     parse_table_add(&pt, "Mac",     PQ_DFL | PQ_MAC,  0, (void *)mac, 0);
   4020     parse_table_add(&pt, "Port",    PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   4021     parse_table_add(&pt, "INtf",    PQ_DFL | PQ_INT,  0, (void *)&interface, 0);
   4022     parse_table_add(&pt, "MOdule",  PQ_DFL | PQ_INT,  0, (void *)&module, 0);
   4023     parse_table_add(&pt, "Trunk",   PQ_DFL | PQ_INT,  0, (void *)&trunk, 0);
   4024     parse_table_add(&pt, "Untag",   PQ_DFL | PQ_BOOL, 0, (void *)&untag, 0);
   4025     parse_table_add(&pt, "Hit",     PQ_DFL | PQ_BOOL, 0, (void *)&hits, 0);
   4026 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4027     parse_table_add(&pt, "VRF",     PQ_DFL | PQ_INT,  0, (void *)&vrf, 0);
   4028     parse_table_add(&pt, "DstDiscard", PQ_DFL | PQ_INT, 0, 
   4029                     (void *)&dst_discard, 0);
   4030     parse_table_add(&pt, "PRI",     PQ_DFL|PQ_INT,    0, (void *)&pri, 0);
   4031     parse_table_add(&pt, "RPE",     PQ_DFL|PQ_BOOL,   0, (void *)&rpe, 0);
   4032     parse_table_add(&pt, "Replace", PQ_DFL | PQ_BOOL, 0, (void *)&replace, 0);
   4033     parse_table_add(&pt, "MplsLabel", PQ_DFL | PQ_INT, 0,
   4034                     (void *)&mpls_label, 0);
   4035     parse_table_add(&pt, "TunnelOpt", PQ_DFL | PQ_INT, 0,
   4036                     (void *)&tunnel_opt, 0);
   4037     parse_table_add(&pt, "LookupClass", PQ_DFL | PQ_INT, 0, (void *)&lookup_class, 0);
   4038     parse_table_add(&pt, "VLAN",    PQ_DFL | PQ_INT,  0, (void *)&vlan, 0);
   4039     parse_table_add(&pt, "IPMC",    PQ_DFL | PQ_INT,  0, (void *)&ipmc, 0);
   4040     if(v6) {
   4041         sal_memset(ip6_addr, 0, sizeof(bcm_ip6_t));
   4042         parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   4043         parse_table_add(&pt, "MaskLen", PQ_DFL | PQ_INT, 0, (void *)&plen, 0);
   4044     } else  
   4045 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   4046     {
   4047         parse_table_add(&pt, "IP",   PQ_DFL | PQ_IP,   0, (void *)&ip_addr, 0);
   4048         parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP,   0, (void *)&ip_mask, 0);
   4049     }
   4050 
   4051 #if defined(BCM_XGS_SWITCH_SUPPORT)
   4052     parse_table_add(&pt, "ECMP",    PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0);
   4053     parse_table_add(&pt, "Local",   PQ_DFL | PQ_BOOL, 0, (void *)&local_route, 0);
   4054 #endif /* BCM_XGS_SWITCH_SUPPORT */
   4055 
   4056     if (!parseEndOk(a, &pt, &retCode)) {
   4057         return retCode;
   4058     }
   4059 
   4060 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4061     route_info.l3a_vrf     = vrf;
   4062     if (dst_discard) {
   4063         route_info.l3a_flags |= BCM_L3_DST_DISCARD;
   4064     }
   4065     if (rpe) {
   4066         route_info.l3a_flags |= BCM_L3_RPE;
   4067     }
   4068     if (replace) {
   4069         route_info.l3a_flags |= BCM_L3_REPLACE;
   4070     }
   4071     if (ipmc) {
   4072         route_info.l3a_flags |= BCM_L3_IPMC;
   4073         BCM_MULTICAST_L3_SET(route_info.l3a_mc_group, interface);
   4074     }
   4075     route_info.l3a_pri = pri;
   4076 
   4077     if (lookup_class) {
   4078         route_info.l3a_lookup_class= lookup_class;
   4079     }
   4080 
   4081     if (mpls_label) { 
   4082         route_info.l3a_mpls_label = mpls_label;
   4083         route_info.l3a_flags |= BCM_L3_ROUTE_LABEL;
   4084     } else if (tunnel_opt) {
   4085         route_info.l3a_tunnel_option = tunnel_opt;
   4086     }
   4087     if (v6) {
   4088         sal_memcpy(route_info.l3a_ip6_net, ip6_addr, BCM_IP6_ADDRLEN);
   4089         bcm_ip6_mask_create(route_info.l3a_ip6_mask, plen);
   4090         route_info.l3a_flags |= BCM_L3_IP6;
   4091     } else 
   4092 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   4093     { 
   4094         route_info.l3a_subnet  = ip_addr;
   4095         route_info.l3a_ip_mask = ip_mask;
   4096     }
   4097 
   4098     route_info.l3a_intf = interface;
   4099     route_info.l3a_vid = vlan;
   4100     sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(bcm_mac_t));
   4101 
   4102     if (BCM_GPORT_IS_SET(port)) {
   4103         route_info.l3a_port_tgid = port;
   4104     } else {
   4105     if (trunk >= 0) {
   4106         route_info.l3a_flags |= BCM_L3_TGID;
   4107         route_info.l3a_port_tgid = trunk;
   4108     } else {
   4109         route_info.l3a_port_tgid = port;
   4110     }
   4111         route_info.l3a_modid = module;
   4112     }
   4113 
   4114     if (untag) {
   4115         route_info.l3a_flags |= BCM_L3_UNTAG;
   4116     }
   4117 
   4118     if (hits) {
   4119         route_info.l3a_flags |= BCM_L3_HIT;
   4120     }
   4121 
   4122 #ifdef BCM_XGS_SWITCH_SUPPORT
   4123     if (ecmp) {
   4124         route_info.l3a_flags |= BCM_L3_MULTIPATH;
   4125     }
   4126 
   4127     if (local_route) {
   4128         route_info.l3a_flags |= BCM_L3_DEFIP_LOCAL;
   4129     }
   4130 #endif
   4131     rv = bcm_l3_route_add(unit, &route_info);
   4132     if (BCM_FAILURE(rv)) {
   4133         cli_out("%s: Error adding route table: %s\n", 
   4134                 ARG_CMD(a), bcm_errmsg(rv));
   4135         return (CMD_FAIL);
   4136     }
   4137     return (CMD_OK);
   4138 }
   4139 
   4140 /*
   4141  * Function:
   4142  *      _l3_cmd_host_add
   4143  * Description:
   4144  * 	    Service routine used to add host entry.
   4145  * Parameters:
   4146  *      unit      - (IN) Device number.
   4147  *      a         - (IN) Command arguments. 
   4148  *      v6        - (IN) IPv6 route indication.
   4149  * Returns:
   4150  *      CMD_XXX
   4151  */
   4152 STATIC cmd_result_t
   4153 _l3_cmd_host_add(int unit, args_t *a, int v6) 
   4154 {
   4155     bcm_l3_host_t   host_info;
   4156     cmd_result_t    retCode;
   4157     bcm_mac_t       mac;
   4158     parse_table_t   pt;
   4159     int             rv;
   4160     int             host_as_route = 0;
   4161     int             interface = 0;
   4162     bcm_ip_t        ip_addr = 0;
   4163     int		        module = 0;
   4164     int             trunk = -1;
   4165     int             untag = 0;
   4166     int             port = 0;
   4167     int             hits = 0;
   4168     int             replace = 0;
   4169 #ifdef BCM_XGS_SWITCH_SUPPORT
   4170     int             l2tocpu = 0;
   4171 #endif /* BCM_XGS_SWITCH_SUPPORT */ 
   4172 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4173     int             rpe = 0;
   4174     int             pri = 0;
   4175     int             vrf = 0;
   4176     int             lookup_class = 0;
   4177     bcm_ip6_t       ip6_addr;
   4178 #endif
   4179 
   4180     bcm_l3_host_t_init(&host_info);
   4181     sal_memset(mac, 0, sizeof(bcm_mac_t));
   4182     parse_table_init(unit, &pt);
   4183 
   4184     parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0);
   4185 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4186     parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   4187     parse_table_add(&pt, "PRI", PQ_DFL|PQ_INT, 0, (void *)&pri, 0);
   4188     parse_table_add(&pt, "RPE", PQ_DFL|PQ_BOOL, 0, (void *)&rpe, 0);
   4189     parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 0, (void *)&lookup_class, 0);
   4190     if (v6) {
   4191 	    parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   4192     } else 
   4193 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   4194     {
   4195         parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0);
   4196     }
   4197     parse_table_add(&pt, "Replace", PQ_DFL | PQ_BOOL, 0, (void *)&replace, 0);
   4198     parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   4199     parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   4200     parse_table_add(&pt, "Hit", PQ_DFL | PQ_BOOL, 0, (void *)&hits, 0);
   4201     parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void *)&module, 0);
   4202     parse_table_add(&pt, "Trunk", PQ_DFL | PQ_INT, 0, (void *)&trunk, 0);
   4203     parse_table_add(&pt, "Untag", PQ_DFL | PQ_BOOL, 0, (void *)&untag, 0);
   4204     parse_table_add(&pt, "HOST_AS_ROUTE", PQ_DFL | PQ_BOOL, 0, 
   4205                     (void *)&host_as_route, 0);
   4206 #ifdef BCM_XGS_SWITCH_SUPPORT
   4207     parse_table_add(&pt, "L2tocpu", PQ_DFL | PQ_BOOL, 0, (void *)&l2tocpu, 0);
   4208 #endif
   4209     if (!parseEndOk(a, &pt, &retCode))
   4210         return retCode;
   4211 
   4212 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   4213     host_info.l3a_vrf     = vrf;
   4214     host_info.l3a_pri     = pri;
   4215     host_info.l3a_lookup_class = lookup_class;
   4216 
   4217     if (rpe) {
   4218         host_info.l3a_flags |= BCM_L3_RPE;
   4219     }
   4220 
   4221     if (v6) {
   4222         sal_memcpy(host_info.l3a_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
   4223         host_info.l3a_flags |= BCM_L3_IP6;
   4224     } else 
   4225 #endif
   4226     {
   4227         host_info.l3a_ip_addr = ip_addr;
   4228     } 
   4229 
   4230     if (host_as_route) {
   4231         host_info.l3a_flags |= BCM_L3_HOST_AS_ROUTE;
   4232     } 
   4233     host_info.l3a_intf = interface;
   4234     sal_memcpy(host_info.l3a_nexthop_mac, mac, sizeof(mac));
   4235 
   4236     if (BCM_GPORT_IS_SET(port)) {
   4237         host_info.l3a_port_tgid = port;
   4238     } else {
   4239     host_info.l3a_modid = module;
   4240     if (trunk >= 0) {
   4241         host_info.l3a_flags |= BCM_L3_TGID;
   4242         host_info.l3a_port_tgid = trunk;
   4243     } else {
   4244         host_info.l3a_port_tgid = port;
   4245     }
   4246     }
   4247 
   4248     if (hits) {
   4249         host_info.l3a_flags |= BCM_L3_HIT;
   4250     }
   4251     if (untag) {
   4252         host_info.l3a_flags |= BCM_L3_UNTAG;
   4253     }
   4254 
   4255     if (replace) {
   4256         host_info.l3a_flags |= BCM_L3_REPLACE;
   4257     }
   4258 
   4259 #ifdef BCM_XGS_SWITCH_SUPPORT
   4260     if (l2tocpu) {
   4261         host_info.l3a_flags |= BCM_L3_L2TOCPU;
   4262     }
   4263 #endif
   4264     rv = bcm_l3_host_add(unit, &host_info);
   4265     if (BCM_FAILURE(rv)) {
   4266         cli_out("%s: Error creating entry in L3 host table: %s\n",
   4267                 ARG_CMD(a), bcm_errmsg(rv));
   4268         return (CMD_FAIL);
   4269     }
   4270     return (CMD_OK);
   4271 } 
   4272 
   4273 /* Struct to track performance data of a collection of API
   4274    calls (or table operations).  Recommended units: micro seconds(us) */
   4275 typedef struct _l3_route_perf_data_s {
   4276     int     count;  /* Number of times the functions is called. */
   4277     int     max;    /* Maximum call time. */
   4278     int     min;    /* Minimum call time. */
   4279     int     total;  /* Total duration time. */
   4280 } _l3_route_perf_data_t;
   4281 
   4282 /* Initalizes a _l3_route_perf_data_t structure */
   4283 void
   4284 _l3_route_perf_data_init(_l3_route_perf_data_t *perf)
   4285 {
   4286     perf->count = 0;
   4287     perf->min = 0;
   4288     perf->max = 0;
   4289     perf->total = 0;
   4290 }
   4291 
   4292 /* Adds a time measurement to a perf_data_t instance.   */
   4293 void
   4294 _l3_route_perf_data_add(_l3_route_perf_data_t *perf, int duration)
   4295 {
   4296     if (perf->count == 0) {
   4297         perf->count = 1;
   4298         perf->min = duration;
   4299         perf->max = duration;
   4300         perf->total = duration;
   4301     } else {
   4302         perf->count++;
   4303         if (duration > perf->max) {
   4304             perf->max = duration;
   4305         }
   4306         if (duration < perf->min) {
   4307             perf->min = duration;
   4308         }
   4309         perf->total += duration;
   4310     }
   4311 }
   4312 
   4313 /* Dumps perf stats */
   4314 void
   4315 _l3_route_perf_data_print(_l3_route_perf_data_t *perf, int route_cnt, const char *label)
   4316 {
   4317     if( perf->count > 0) {
   4318         /*int u_avg = perf->total / perf->count;*/
   4319         uint32 temp;
   4320 
   4321         /*cli_out("Performance Dump: %s :\n", label);
   4322         cli_out("  Min: %d uSec\n", perf->min);
   4323         cli_out("  Max: %d uSec\n", perf->max);
   4324         cli_out("  Avg: %d uSec\n", u_avg);
   4325         cli_out("  Total: %d.%3d Sec\n", (perf->total / 1000000), (perf->total%1000000/1000));
   4326         cli_out("  Count: %d\n", perf->count);*/
   4327 
   4328         temp = route_cnt * perf->count;
   4329         if (temp > 4294) {
   4330             uint32 temp2 = 0;
   4331             uint32 rem = 0, divn;
   4332             while ((int)temp > 0) {
   4333                 divn = (temp > 2147) ? 2147 : temp;
   4334                 divn = divn * 1000000;
   4335                 temp2 += (divn + rem) / perf->total;
   4336                 rem = (divn + rem) % perf->total;
   4337                 temp -= 2147;
   4338             }
   4339             temp = temp2;
   4340         } else {
   4341             temp = temp * 1000000 / perf->total;
   4342         }
   4343         cli_out(" %7d ", temp);
   4344     } else {
   4345         cli_out("    -    ");
   4346     }
   4347 }
   4348 
   4349 /*
   4350  * Performance test to add IPv4 routes
   4351  * Same as arch_ipv4_route_add_001 but also measure route update times
   4352  * and runs the while test 10 times to get 10 different data points.
   4353  */
   4354 int _l3_route_perf_egr_mode[SOC_MAX_NUM_DEVICES];
   4355 int _l3_route_perf_obj_id[SOC_MAX_NUM_DEVICES];
   4356 int _l3_route_perf_obj2_id[SOC_MAX_NUM_DEVICES];
   4357 int _l3_route_perf_vrf = 100;
   4358 
   4359 
   4360 STATIC void
   4361 _l3_route_perf_test_setup(int unit)
   4362 {
   4363     /* Setup */
   4364     int rv;
   4365 
   4366     bcm_l3_intf_t l3_intf;
   4367 
   4368     bcm_l3_egress_t   egress_object;
   4369     bcm_l3_egress_t   egress_object2;
   4370     bcm_mac_t         mac;
   4371 
   4372     /* Turn off back ground threads */
   4373     sh_process_command(unit, "l2mode");
   4374     sh_process_command(unit, "l2mode off");
   4375     sh_process_command(unit, "linkscan");
   4376     sh_process_command(unit, "linkscan off");
   4377     sh_process_command(unit, "counter");
   4378     sh_process_command(unit, "counter off");
   4379     sh_process_command(unit, "memscan");
   4380     sh_process_command(unit, "memscan off");
   4381     sh_process_command(unit, "sramscan");
   4382     sh_process_command(unit, "sramscan off");
   4383 
   4384     /* L3 Egress Mode */
   4385     rv = bcm_switch_control_get(unit, bcmSwitchL3EgressMode,
   4386                                 &_l3_route_perf_egr_mode[unit]);
   4387     if (BCM_FAILURE(rv)) {
   4388         cli_out("Perf: Get L3 Egress Mode failed: %s\n", bcm_errmsg(rv));
   4389         return;
   4390     }
   4391     rv = bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1);
   4392     if (BCM_FAILURE(rv)) {
   4393         cli_out("Perf: Set L3 Egress Mode failed: %s\n", bcm_errmsg(rv));
   4394         return;
   4395     }
   4396 
   4397     /* L3 Interface */
   4398     bcm_l3_intf_t_init(&l3_intf);
   4399     l3_intf.l3a_flags = BCM_L3_WITH_ID;
   4400     l3_intf.l3a_intf_id = 1;
   4401     l3_intf.l3a_mac_addr[5] = 0x1;
   4402     l3_intf.l3a_vid = 1;
   4403     l3_intf.l3a_vrf = _l3_route_perf_vrf;
   4404     rv = bcm_l3_intf_create(unit, &l3_intf);
   4405     if (BCM_FAILURE(rv)) {
   4406         cli_out("Perf: Create L3 intf failed: %s\n", bcm_errmsg(rv));
   4407         return;
   4408     }
   4409 
   4410     /* L3 Egress */
   4411     bcm_l3_egress_t_init(&egress_object);
   4412     sal_memset(mac, 0, sizeof(bcm_mac_t));
   4413     mac[5] = 0x1;
   4414     egress_object.intf = 1;
   4415     egress_object.module = 0;
   4416     egress_object.port = 1;
   4417     sal_memcpy(egress_object.mac_addr, mac, sizeof(mac));
   4418 
   4419     rv = bcm_l3_egress_create(unit, 0, &egress_object,
   4420                               &_l3_route_perf_obj_id[unit]);
   4421     if (BCM_FAILURE(rv)) {
   4422         cli_out("Perf: Error creating egress object entry: %s\n",
   4423                 bcm_errmsg(rv));
   4424         return ;
   4425     }
   4426 
   4427     bcm_l3_egress_t_init(&egress_object2);
   4428     sal_memset(mac, 0, sizeof(bcm_mac_t));
   4429     mac[5] = 0x2;
   4430     egress_object2.intf = 1;
   4431     egress_object2.module = 0;
   4432     egress_object2.port = 1;
   4433     sal_memcpy(egress_object2.mac_addr, mac, sizeof(mac));
   4434 
   4435     rv = bcm_l3_egress_create(unit, 0, &egress_object2,
   4436                               &_l3_route_perf_obj2_id[unit]);
   4437     if (BCM_FAILURE(rv)) {
   4438         cli_out("Perf: Error creating egress object2 entry: %s\n",
   4439                 bcm_errmsg(rv));
   4440         return ;
   4441     }
   4442 
   4443     return ;
   4444 }
   4445 
   4446 STATIC void
   4447 _l3_route_perf_test_clean(int unit)
   4448 {
   4449     int rv;
   4450     bcm_l3_intf_t intf;
   4451 
   4452     rv = bcm_l3_egress_destroy(unit, _l3_route_perf_obj2_id[unit]);
   4453     if (BCM_FAILURE(rv) && rv != BCM_E_BUSY) {
   4454         cli_out("Perf: Error deleting egress object2 entry: %s\n",
   4455                 bcm_errmsg(rv));
   4456         return ;
   4457     }
   4458 
   4459     rv = bcm_l3_egress_destroy(unit, _l3_route_perf_obj_id[unit]);
   4460     if (BCM_FAILURE(rv) && rv != BCM_E_BUSY) {
   4461         cli_out("Perf: Error deleting egress object entry: %s\n",
   4462                 bcm_errmsg(rv));
   4463         return ;
   4464     }
   4465 
   4466     bcm_l3_intf_t_init(&intf);
   4467     intf.l3a_intf_id = 1;
   4468 
   4469     if ((rv = bcm_l3_intf_delete(unit, &intf)) < 0) {
   4470         cli_out("Perf: Error (%s) destroy interface (%d)\n",
   4471                 bcm_errmsg(rv), 1);
   4472         return ;
   4473     }
   4474 
   4475     rv = bcm_switch_control_set(unit, bcmSwitchL3EgressMode,
   4476                                 _l3_route_perf_egr_mode[unit]);
   4477     if (BCM_FAILURE(rv)) {
   4478         cli_out("Perf: Set L3 Egress Mode failed: %s\n", bcm_errmsg(rv));
   4479         return;
   4480     }
   4481 
   4482     /* Turn on back ground threads */
   4483     sh_process_command(unit, "l2mode on");
   4484     sh_process_command(unit, "linkscan on");
   4485     sh_process_command(unit, "counter on");
   4486     sh_process_command(unit, "memscan on");
   4487     sh_process_command(unit, "sramscan on");
   4488 
   4489     return ;
   4490 
   4491 }
   4492 
   4493 #define _L3_ROUTE_PERF_OP_ADD   1
   4494 #define _L3_ROUTE_PERF_OP_UPD   2
   4495 #define _L3_ROUTE_PERF_OP_GET   3
   4496 #define _L3_ROUTE_PERF_OP_DEL   4
   4497 
   4498 char *_l3_route_perf_op_str[] = {
   4499     "Invalid",
   4500     "Insert",
   4501     "Update",
   4502     "Lookup",
   4503     "Delete"
   4504 };
   4505 
   4506 STATIC int
   4507 _l3_route_perf_v4_op_test(int unit, int op, int use_api, int set_idx,
   4508                           _l3_route_perf_data_t *route_perf, int *route_cnt, int vrf)
   4509 {
   4510     int         rv = 0;
   4511     int         inx, idx;
   4512     int         start, end, duration = 0;
   4513     bcm_l3_route_t base_route;
   4514     _bcm_defip_cfg_t base_defip;
   4515 
   4516     int (*op_func[5])(int, bcm_l3_route_t *) = {
   4517         NULL,
   4518         bcm_l3_route_add,
   4519         bcm_l3_route_add,
   4520         bcm_l3_route_get,
   4521         bcm_l3_route_delete
   4522     };
   4523 
   4524 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4525     int (*op_func_defip[5])(int, _bcm_defip_cfg_t *) = {
   4526         NULL,
   4527         bcm_esw_alpm_insert,
   4528         bcm_esw_alpm_update,
   4529         bcm_esw_alpm_lookup,
   4530         bcm_esw_alpm_delete
   4531     };
   4532 #endif
   4533     /* 4K Entries */
   4534     uint32 ip, start_ip = 0x01010101;
   4535     uint32 ip_mask = 0xffffffff;
   4536     int loop = 4 * 1024;
   4537 
   4538     /* 1K Entries */
   4539     int loop_ip = 1 * 1024;
   4540     int j;
   4541     uint32 prfx[4] = {22, 23, 24, 20};
   4542     uint32 mask[4] = {0xfffffc00, 0xfffffe00, 0xffffff00, 0xfffff000};
   4543     uint32 ipv4[4] = {0x02020202, 0x29020202, 0x61020202, 0x8C010101};
   4544     uint32 ipAddr;
   4545     uint32 ipMask;
   4546     uint32 base_ip;
   4547 
   4548     *route_cnt = 0;
   4549 
   4550     bcm_l3_route_t_init(&base_route);
   4551     sal_memset(&base_defip, 0, sizeof(base_defip));
   4552 
   4553     /* Insert entry */
   4554     /*cli_out("%s 4K IPv4 routes with mask - 0x%08x\n",
   4555             _l3_route_perf_op_str[op], ip_mask);*/
   4556     start = sal_time_usecs();
   4557     ip = start_ip + set_idx * loop;
   4558 
   4559     for (inx = 0; inx < loop; inx++) {
   4560         if (use_api) {
   4561             base_route.l3a_vrf = vrf;
   4562             base_route.l3a_subnet = ip;
   4563             base_route.l3a_ip_mask = ip_mask;
   4564             base_route.l3a_intf = _l3_route_perf_obj_id[unit];
   4565             if (op == _L3_ROUTE_PERF_OP_UPD) {
   4566                 base_route.l3a_flags = BCM_L3_REPLACE;
   4567                 base_route.l3a_intf = _l3_route_perf_obj2_id[unit];
   4568             }
   4569 
   4570             rv = op_func[op](unit, &base_route);
   4571         } else {
   4572 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4573             sal_memset(&base_defip, 0, sizeof(base_defip));
   4574             base_defip.defip_vrf = vrf;
   4575             base_defip.defip_ip_addr = ip;
   4576             base_defip.defip_sub_len = bcm_ip_mask_length(ip_mask);
   4577             base_defip.defip_intf = _l3_route_perf_obj_id[unit];
   4578             if (op == _L3_ROUTE_PERF_OP_UPD) {
   4579                 base_defip.defip_flags = BCM_L3_REPLACE;
   4580                 base_defip.defip_intf = _l3_route_perf_obj2_id[unit];
   4581             }
   4582 
   4583             rv = op_func_defip[op](unit, &base_defip);
   4584 #endif
   4585         }
   4586         if (rv < 0) {
   4587             end = sal_time_usecs();
   4588             duration = end - start;
   4589             /*cli_out("%s %dth route returned msg: %s\n",
   4590                     _l3_route_perf_op_str[op], inx,
   4591                     bcm_errmsg(rv));*/
   4592             goto End4;
   4593         } else {
   4594             *route_cnt += 1;
   4595         }
   4596 
   4597         ip++;
   4598     }
   4599     end = sal_time_usecs();
   4600     duration = end - start;
   4601 
   4602     bcm_l3_route_t_init(&base_route);
   4603     sal_memset(&base_defip, 0, sizeof(base_defip));
   4604 
   4605     for (j = 0; j < 4; j++) {
   4606         /*cli_out("%s 1K IPv4 routes with mask - 0x%08x\n",
   4607                 _l3_route_perf_op_str[op], mask[j]);*/
   4608         start = sal_time_usecs();
   4609         for (idx = 0; idx < loop_ip; idx++) {
   4610             base_ip = ((loop_ip + idx + loop_ip * set_idx) << (32 - prfx[j]));
   4611             ipAddr = base_ip + ipv4[j];
   4612             ipMask = mask[j];
   4613 
   4614             if (use_api) {
   4615                 base_route.l3a_vrf = vrf;
   4616                 base_route.l3a_subnet = ipAddr;
   4617                 base_route.l3a_ip_mask = ipMask;
   4618                 base_route.l3a_intf = _l3_route_perf_obj_id[unit];
   4619                 if (op == _L3_ROUTE_PERF_OP_UPD) {
   4620                     base_route.l3a_flags = BCM_L3_REPLACE;
   4621                     base_route.l3a_intf = _l3_route_perf_obj2_id[unit];
   4622                 }
   4623 
   4624                 rv = op_func[op](unit, &base_route);
   4625             } else {
   4626 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4627                 sal_memset(&base_defip, 0, sizeof(base_defip));
   4628                 base_defip.defip_vrf = vrf;
   4629                 base_defip.defip_ip_addr = ipAddr;
   4630                 base_defip.defip_sub_len = bcm_ip_mask_length(ipMask);
   4631                 base_defip.defip_intf = _l3_route_perf_obj_id[unit];
   4632                 if (op == _L3_ROUTE_PERF_OP_UPD) {
   4633                     base_defip.defip_flags = BCM_L3_REPLACE;
   4634                     base_defip.defip_intf = _l3_route_perf_obj2_id[unit];
   4635                 }
   4636 
   4637                 rv = op_func_defip[op](unit, &base_defip);
   4638 #endif
   4639             }
   4640             if (rv < 0) {
   4641                 end = sal_time_usecs();
   4642                 duration += end - start;
   4643                 /*cli_out("%s %dth route returned msg: %s\n",
   4644                         _l3_route_perf_op_str[op], idx,
   4645                         bcm_errmsg(rv));*/
   4646                 goto End4;
   4647                 /*return;*/
   4648             } else {
   4649                 *route_cnt += 1;
   4650             }
   4651         }
   4652         end = sal_time_usecs();
   4653         duration += end - start;
   4654     }
   4655 
   4656 End4:
   4657     _l3_route_perf_data_add(route_perf, duration);
   4658     return rv;
   4659 }
   4660 
   4661 STATIC void
   4662 _l3_route_perf_v4_test(int unit, int loops, int nsets, int use_api,
   4663                        int op_bitmap, int vrf, uint8 alpm_mode)
   4664 {
   4665     int run, i;
   4666     int route_added = 0, set_size = 0, route_cnt = 0, tot_route = 0;
   4667     bcm_l3_route_t base_route;
   4668     _bcm_defip_cfg_t base_defip;
   4669     void *pb = NULL;
   4670 
   4671     _l3_route_perf_data_t *route_add_perf = NULL;
   4672     _l3_route_perf_data_t *route_get_perf = NULL;
   4673     _l3_route_perf_data_t *route_del_perf = NULL;
   4674     _l3_route_perf_data_t *route_upd_perf = NULL;
   4675 
   4676     route_add_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "add_perf");
   4677     route_get_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "get_perf");
   4678     route_del_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "del_perf");
   4679     route_upd_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "upd_perf");
   4680 
   4681     for (i = 0; i < nsets; i++) {
   4682         _l3_route_perf_data_init(&route_add_perf[i]);
   4683         _l3_route_perf_data_init(&route_get_perf[i]);
   4684         _l3_route_perf_data_init(&route_del_perf[i]);
   4685         _l3_route_perf_data_init(&route_upd_perf[i]);
   4686     }
   4687 
   4688     for (run = 0; run < loops; run ++) {
   4689         int     rv = 0;
   4690 
   4691         route_added = 0;
   4692 
   4693         /* Default route */
   4694         if (use_api) {
   4695             bcm_l3_route_t_init(&base_route);
   4696             base_route.l3a_intf = _l3_route_perf_obj_id[unit];
   4697             base_route.l3a_vrf = vrf;
   4698             base_route.l3a_subnet = 0;
   4699             base_route.l3a_ip_mask = 0;
   4700             rv = bcm_l3_route_add(unit, &base_route);
   4701         } else {
   4702             sal_memset(&base_defip, 0, sizeof(base_defip));
   4703 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4704             base_defip.defip_intf = _l3_route_perf_obj_id[unit];
   4705             base_defip.defip_vrf  = vrf;
   4706             rv = bcm_esw_alpm_insert(unit, &base_defip);
   4707 #endif
   4708         }
   4709 
   4710         if (BCM_FAILURE(rv)) {
   4711             cli_out("Unable to add IPv4 default route (return %d)\n", rv);
   4712             goto done;
   4713         }
   4714 
   4715         for (i = 0; i < nsets; i++) {
   4716             rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_ADD, use_api, i,
   4717                                            &route_add_perf[i], &route_cnt, vrf);
   4718             route_added += route_cnt;
   4719             if (BCM_FAILURE(rv)) {
   4720                 nsets = i + 1;
   4721                 if (i == 0) {
   4722                     set_size = route_cnt;
   4723                 }
   4724                 break;
   4725             } else {
   4726                 set_size = route_cnt;
   4727             }
   4728         }
   4729 
   4730         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_UPD - 1))) {
   4731             for (i = 0; i < nsets; i++) {
   4732                 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_UPD, use_api, i,
   4733                                                &route_upd_perf[i], &route_cnt, vrf);
   4734                 if (BCM_FAILURE(rv)) {
   4735                     break;
   4736                 }
   4737             }
   4738         }
   4739 
   4740         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_GET - 1))) {
   4741             for (i = 0; i < nsets; i++) {
   4742                 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_GET, use_api, i,
   4743                                                &route_get_perf[i], &route_cnt, vrf);
   4744                 if (BCM_FAILURE(rv)) {
   4745                     break;
   4746                 }
   4747             }
   4748         }
   4749 
   4750         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) {
   4751             for (i = 0; i < nsets; i++) {
   4752                 rv = _l3_route_perf_v4_op_test(unit, _L3_ROUTE_PERF_OP_DEL, use_api, i,
   4753                                                &route_del_perf[i], &route_cnt, vrf);
   4754                 if (BCM_FAILURE(rv)) {
   4755                     break;
   4756                 }
   4757             }
   4758 
   4759             /* Cleanup */
   4760             /* Delete the default route */
   4761             if (use_api) {
   4762                 rv = bcm_l3_route_delete(unit, &base_route);
   4763             } else {
   4764 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4765                 rv = bcm_esw_alpm_delete(unit, &base_defip);
   4766 #endif
   4767             }
   4768 
   4769             if (BCM_FAILURE(rv)) {
   4770                 cli_out("Failed to delete IPv4 default route (return %d)\n", rv);
   4771                 goto done;
   4772             }
   4773 
   4774             /* For test purpose, flush heap memory by allocate 16MB and free,
   4775                in order to trigger garbage defragmentation before next run */
   4776             pb = NULL;
   4777             pb = sal_alloc(1024*1024*16, "alpm_mem_flush");
   4778             if (pb) {
   4779                 sal_free(pb);
   4780             }
   4781 	}
   4782     }
   4783 
   4784     cli_out("IPv4 (%s) performance test: Added routes = %d\n",
   4785             (alpm_mode == 2 ? "Combined" : (vrf < 0 ? "Global" : "Private")),
   4786             route_added);
   4787     cli_out(" Set RouteCnt TotRoute  RPS:Add  Update   Lookup   Delete \n");
   4788 
   4789     tot_route = 0;
   4790     for (i = 0; i < nsets; i++) {
   4791         if ((tot_route + set_size) > route_added) {
   4792             route_cnt = route_added - tot_route;
   4793         } else {
   4794             route_cnt = set_size;
   4795         }
   4796         tot_route += route_cnt;
   4797 
   4798         cli_out("%3d  %7d  %7d ", i, route_cnt, tot_route);
   4799 
   4800         _l3_route_perf_data_print(&route_add_perf[i], route_cnt, "");
   4801         _l3_route_perf_data_print(&route_upd_perf[i], route_cnt, "");
   4802         _l3_route_perf_data_print(&route_get_perf[i], route_cnt, "");
   4803         _l3_route_perf_data_print(&route_del_perf[i], route_cnt, "");
   4804         cli_out("\n");
   4805     }
   4806     cli_out("\n");
   4807 
   4808 done:
   4809     sal_free(route_add_perf);
   4810     sal_free(route_upd_perf);
   4811     sal_free(route_get_perf);
   4812     sal_free(route_del_perf);
   4813 }
   4814 
   4815 STATIC int
   4816 _l3_route_perf_v6_op_test(int unit, int op, int use_api, int set_idx,
   4817                           _l3_route_perf_data_t *route_perf, int *route_cnt, int vrf)
   4818 {
   4819     int         i, rv = 0;
   4820     int         start, end, duration = 0;
   4821     bcm_l3_route_t base_route;
   4822     _bcm_defip_cfg_t base_defip;
   4823 
   4824     int (*op_func[5])(int, bcm_l3_route_t *) = {
   4825         NULL,
   4826         bcm_l3_route_add,
   4827         bcm_l3_route_add,
   4828         bcm_l3_route_get,
   4829         bcm_l3_route_delete
   4830     };
   4831 
   4832 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4833     int (*op_func_defip[5])(int, _bcm_defip_cfg_t *) = {
   4834         NULL,
   4835         bcm_esw_alpm_insert,
   4836         bcm_esw_alpm_update,
   4837         bcm_esw_alpm_lookup,
   4838         bcm_esw_alpm_delete
   4839     };
   4840 #endif
   4841 
   4842     /* 1022 Entries */
   4843     int    count = 1022;
   4844     bcm_ip6_t v6_mask = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
   4845     bcm_ip6_t v6_ip   = {0x70,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04};
   4846     int pfx_bit_loc = 32;
   4847     int pfx = 0x110 + count * set_idx;
   4848 
   4849     *route_cnt = 0;
   4850 
   4851     bcm_l3_route_t_init(&base_route);
   4852     sal_memset(&base_defip, 0, sizeof(base_defip));
   4853 
   4854     /* Insert entry */
   4855     increment_ip6addr(v6_ip, pfx_bit_loc/8 - 1, pfx);
   4856     start = sal_time_usecs();
   4857     for (i = 0; i < count; i++) {
   4858         increment_ip6addr(v6_ip, pfx_bit_loc/8 - 1, 1);
   4859 
   4860         if (use_api) {
   4861             base_route.l3a_vrf = vrf;
   4862             sal_memcpy(base_route.l3a_ip6_net, v6_ip, sizeof(v6_ip));
   4863             sal_memcpy(base_route.l3a_ip6_mask, v6_mask, sizeof(v6_mask));
   4864             base_route.l3a_intf = _l3_route_perf_obj_id[unit];
   4865             if (op == _L3_ROUTE_PERF_OP_UPD) {
   4866                 base_route.l3a_flags = BCM_L3_REPLACE;
   4867                 base_route.l3a_intf = _l3_route_perf_obj2_id[unit];
   4868             }
   4869             base_route.l3a_flags |= BCM_L3_IP6;
   4870 
   4871             rv = op_func[op](unit, &base_route);
   4872         } else {
   4873 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4874             sal_memset(&base_defip, 0, sizeof(base_defip));
   4875             base_defip.defip_vrf = vrf;
   4876             sal_memcpy(base_defip.defip_ip6_addr, v6_ip, sizeof(v6_ip));
   4877             base_defip.defip_sub_len = bcm_ip6_mask_length(v6_mask);
   4878             base_defip.defip_intf = _l3_route_perf_obj_id[unit];
   4879             if (op == _L3_ROUTE_PERF_OP_UPD) {
   4880                 base_defip.defip_flags = BCM_L3_REPLACE;
   4881                 base_defip.defip_intf = _l3_route_perf_obj2_id[unit];
   4882             }
   4883             base_defip.defip_flags |= BCM_L3_IP6;
   4884 
   4885             rv = op_func_defip[op](unit, &base_defip);
   4886 #endif
   4887         }
   4888         if (rv < 0) {
   4889             end = sal_time_usecs();
   4890             duration = end - start;
   4891             /*cli_out("%s %dth route returned msg: %s\n",
   4892                     _l3_route_perf_op_str[op], i,
   4893                     bcm_errmsg(rv));*/
   4894             goto End6;
   4895         } else {
   4896             *route_cnt += 1;
   4897         }
   4898     }
   4899     end = sal_time_usecs();
   4900     duration = end - start;
   4901 
   4902 End6:
   4903     _l3_route_perf_data_add(route_perf, duration);
   4904     return rv;
   4905 }
   4906 
   4907 STATIC void
   4908 _l3_route_perf_v6_test(int unit, int loops, int nsets, int use_api,
   4909                        int op_bitmap, int vrf, uint8 alpm_mode)
   4910 {
   4911     int run, i;
   4912     int route_added = 0, set_size = 0, route_cnt = 0, tot_route = 0;
   4913     bcm_l3_route_t base_route;
   4914     _bcm_defip_cfg_t base_defip;
   4915     void *pb = NULL;
   4916 
   4917     _l3_route_perf_data_t *route_add_perf = NULL;
   4918     _l3_route_perf_data_t *route_get_perf = NULL;
   4919     _l3_route_perf_data_t *route_del_perf = NULL;
   4920     _l3_route_perf_data_t *route_upd_perf = NULL;
   4921 
   4922     route_add_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "add_perf");
   4923     route_get_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "get_perf");
   4924     route_del_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "del_perf");
   4925     route_upd_perf = sal_alloc(sizeof(_l3_route_perf_data_t) * nsets, "upd_perf");
   4926 
   4927     for (i = 0; i < nsets; i++) {
   4928         _l3_route_perf_data_init(&route_add_perf[i]);
   4929         _l3_route_perf_data_init(&route_get_perf[i]);
   4930         _l3_route_perf_data_init(&route_del_perf[i]);
   4931         _l3_route_perf_data_init(&route_upd_perf[i]);
   4932     }
   4933 
   4934     for (run = 0; run < loops; run ++) {
   4935         int     rv = 0;
   4936 
   4937         route_added = 0;
   4938 
   4939         /* Default route */
   4940         if (use_api) {
   4941             bcm_l3_route_t_init(&base_route);
   4942             base_route.l3a_intf = _l3_route_perf_obj_id[unit];
   4943             base_route.l3a_vrf = vrf;
   4944             base_route.l3a_flags = BCM_L3_IP6;
   4945             rv = bcm_l3_route_add(unit, &base_route);
   4946         } else {
   4947             sal_memset(&base_defip, 0, sizeof(base_defip));
   4948 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   4949             base_defip.defip_intf = _l3_route_perf_obj_id[unit];
   4950             base_defip.defip_vrf  = vrf;
   4951             base_defip.defip_flags = BCM_L3_IP6;
   4952             rv = bcm_esw_alpm_insert(unit, &base_defip);
   4953 #endif
   4954         }
   4955 
   4956         if (BCM_FAILURE(rv)) {
   4957             cli_out("Unable to add IPv6 default route (return %d)\n", rv);
   4958             goto done;
   4959         }
   4960 
   4961         for (i = 0; i < nsets; i++) {
   4962             rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_ADD, use_api, i,
   4963                                            &route_add_perf[i], &route_cnt, vrf);
   4964             route_added += route_cnt;
   4965             if (BCM_FAILURE(rv)) {
   4966                 nsets = i + 1;
   4967                 if (i == 0) {
   4968                     set_size = route_cnt;
   4969                 }
   4970                 break;
   4971             } else {
   4972                 set_size = route_cnt;
   4973             }
   4974         }
   4975 
   4976         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_UPD - 1))) {
   4977             for (i = 0; i < nsets; i++) {
   4978                 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_UPD, use_api, i,
   4979                                                &route_upd_perf[i], &route_cnt, vrf);
   4980                 if (BCM_FAILURE(rv)) {
   4981                     break;
   4982                 }
   4983             }
   4984         }
   4985 
   4986         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_GET - 1))) {
   4987             for (i = 0; i < nsets; i++) {
   4988                 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_GET, use_api, i,
   4989                                                &route_get_perf[i], &route_cnt, vrf);
   4990                 if (BCM_FAILURE(rv)) {
   4991                     break;
   4992                 }
   4993             }
   4994         }
   4995 
   4996         if (op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) {
   4997             for (i = 0; i < nsets; i++) {
   4998                 rv = _l3_route_perf_v6_op_test(unit, _L3_ROUTE_PERF_OP_DEL, use_api, i,
   4999                                                &route_del_perf[i], &route_cnt, vrf);
   5000                 if (BCM_FAILURE(rv)) {
   5001                     break;
   5002                 }
   5003             }
   5004 
   5005             /* Cleanup */
   5006             /* Delete the default route */
   5007             if (use_api) {
   5008                 rv = bcm_l3_route_delete(unit, &base_route);
   5009             } else {
   5010 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(ALPM_ENABLE)
   5011                 rv = bcm_esw_alpm_delete(unit, &base_defip);
   5012 #endif
   5013             }
   5014 
   5015             if (BCM_FAILURE(rv)) {
   5016                 cli_out("Failed to delete IPv6 default route (return %d)\n", rv);
   5017                 goto done;
   5018             }
   5019 
   5020             /* For test purpose, flush heap memory by allocate 16MB and free,
   5021                in order to trigger garbage defragmentation before next run */
   5022             pb = NULL;
   5023             pb = sal_alloc(1024*1024*16, "alpm_mem_flush");
   5024             if (pb) {
   5025                 sal_free(pb);
   5026             }
   5027 	}
   5028     }
   5029 
   5030     cli_out("IPv6 (%s) performance test: Added routes = %d\n",
   5031             (alpm_mode == 2 ? "Combined" : (vrf < 0 ? "Global" : "Private")),
   5032             route_added);
   5033     cli_out(" Set RouteCnt TotRoute  RPS:Add  Update   Lookup   Delete \n");
   5034 
   5035     tot_route = 0;
   5036     for (i = 0; i < nsets; i++) {
   5037         if ((tot_route + set_size) > route_added) {
   5038             route_cnt = route_added - tot_route;
   5039         } else {
   5040             route_cnt = set_size;
   5041         }
   5042         tot_route += route_cnt;
   5043 
   5044         cli_out("%3d  %7d  %7d ", i, route_cnt, tot_route);
   5045 
   5046         _l3_route_perf_data_print(&route_add_perf[i], route_cnt, "");
   5047         _l3_route_perf_data_print(&route_upd_perf[i], route_cnt, "");
   5048         _l3_route_perf_data_print(&route_get_perf[i], route_cnt, "");
   5049         _l3_route_perf_data_print(&route_del_perf[i], route_cnt, "");
   5050         cli_out("\n");
   5051     }
   5052     cli_out("\n");
   5053 
   5054 done:
   5055     sal_free(route_add_perf);
   5056     sal_free(route_upd_perf);
   5057     sal_free(route_get_perf);
   5058     sal_free(route_del_perf);
   5059 
   5060 }
   5061 
   5062 STATIC cmd_result_t
   5063 _l3_cmd_route_perf_test(int unit, args_t *a)
   5064 {
   5065     int cons_st;
   5066     int ip_type = 3;
   5067     int loops = 3;
   5068     int nonset, nsets = -1;
   5069     int op_bitmap = 0xf;
   5070     int use_api = 1;
   5071 
   5072     cmd_result_t cmd_rv = CMD_OK;
   5073     parse_table_t pt;
   5074     uint8 alpm_mode = 0;
   5075 
   5076     /* v4v6: 1 (IPv4 only), 2 (IPv6 only), 3 (IPv4 first then IPv6), 4 (IPv6 first then IPv4)
   5077        OPs: bit0 (Add), bit1 (Update), bit2 (Lookup), bit3 (Delete)
   5078        For capacity test: bit3 (Delete) must be disabled from OPs, e.g.
   5079          l3 route test perf v4v6=3 Ops=7
   5080        When not Delete, loops will be forced to 1.
   5081        Global routes will be included automatically for Parallel or TCAM mixed modes.
   5082     */
   5083 
   5084     parse_table_init(unit, &pt);
   5085     parse_table_add(&pt, "v4v6", PQ_DFL | PQ_INT, (void *)3,
   5086                     (void *)&ip_type, 0);
   5087     parse_table_add(&pt, "loops", PQ_DFL | PQ_INT, (void *)3,
   5088                     (void *)&loops, 0);
   5089     parse_table_add(&pt, "nsets", PQ_DFL | PQ_INT, (void *)-1,
   5090                     (void *)&nsets, 0);
   5091     parse_table_add(&pt, "UseApi", PQ_DFL | PQ_INT, (void *)1,
   5092                     (void *)&use_api, 0);
   5093     parse_table_add(&pt, "OPs", PQ_DFL | PQ_INT, (void *)0xf,
   5094                     (void *)&op_bitmap, 0);
   5095 
   5096     if (!parseEndOk(a, &pt, &cmd_rv)) {
   5097         return cmd_rv;
   5098     }
   5099     /* OP_ADD is must */
   5100     if ((op_bitmap & (1 << (_L3_ROUTE_PERF_OP_ADD - 1))) == 0) {
   5101         return CMD_USAGE;
   5102     }
   5103 
   5104     /* Force loops=1 if not OP_DEL */
   5105     if ((op_bitmap & (1 << (_L3_ROUTE_PERF_OP_DEL - 1))) == 0) {
   5106         loops = 1;
   5107     }
   5108 
   5109     cons_st = bslcons_is_enabled();
   5110     if (cons_st) {
   5111         bslcons_enable(0);
   5112     }
   5113     _l3_route_perf_test_setup(unit);
   5114     bslcons_enable(cons_st);
   5115 
   5116 #ifdef ALPM_ENABLE
   5117     if (soc_feature(unit, soc_feature_alpm)) {
   5118         alpm_mode = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0);
   5119     }
   5120 #endif
   5121     cli_out("Test runs: %d\n", loops);
   5122     cli_out("ALPM mode: %s\n",
   5123             alpm_mode == 1 ? "Parallel" :
   5124             alpm_mode == 2 ? "Combined" :
   5125             alpm_mode == 3 ? "ALPM/TCAM Mixed" : "Disabled");
   5126 
   5127     nonset = (nsets == -1);
   5128 
   5129     if ((ip_type == 1) || (ip_type == 3)) { /* IPv4 first */
   5130         if (nonset) {
   5131             nsets = 130;
   5132         }
   5133         /* Private VRF 100 */
   5134         _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap,
   5135                                _l3_route_perf_vrf, alpm_mode);
   5136 
   5137          /* Global low route test for Paralle & ALPM/TCAM mixed modes */
   5138         if ((alpm_mode == 1) || (alpm_mode == 3)) {
   5139             _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap,
   5140                                    BCM_L3_VRF_GLOBAL, alpm_mode);
   5141         }
   5142     }
   5143 
   5144     if (ip_type != 1) { /* IPv6 */
   5145         if (nonset) {
   5146             nsets = 300;
   5147         }
   5148         /* Private VRF 100 */
   5149         _l3_route_perf_v6_test(unit, loops, nsets, use_api, op_bitmap,
   5150                                _l3_route_perf_vrf, alpm_mode);
   5151 
   5152          /* Global low route test for Paralle & ALPM/TCAM mixed modes */
   5153         if ((alpm_mode == 1) || (alpm_mode == 3)) {
   5154             _l3_route_perf_v6_test(unit, loops, nsets, use_api, op_bitmap,
   5155                                    BCM_L3_VRF_GLOBAL, alpm_mode);
   5156         }
   5157     }
   5158 
   5159     if (ip_type == 4) { /* then IPv4 */
   5160         if (nonset) {
   5161             nsets = 130;
   5162         }
   5163         /* Private VRF 100 */
   5164         _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap,
   5165                                _l3_route_perf_vrf, alpm_mode);
   5166 
   5167          /* Global low route test for Paralle & ALPM/TCAM mixed modes */
   5168         if ((alpm_mode == 1) || (alpm_mode == 3)) {
   5169             _l3_route_perf_v4_test(unit, loops, nsets, use_api, op_bitmap,
   5170                                    BCM_L3_VRF_GLOBAL, alpm_mode);
   5171         }
   5172     }
   5173 
   5174     cons_st = bslcons_is_enabled();
   5175     if (cons_st) {
   5176         bslcons_enable(0);
   5177     }
   5178     _l3_route_perf_test_clean(unit);
   5179     bslcons_enable(cons_st);
   5180 
   5181     return CMD_OK;
   5182 }
   5183 
   5184 #ifdef ALPM_ENABLE
   5185 /* Usage: 
   5186  *   l3 alpm show [all] [VRF=<val>] [global-vrf=<bool>]
   5187  *                [Pivot=<bool>] [Bucket=<bool> [Counter=<bool] 
   5188  *                [BucketuSage=<bool>] [InternalDebug=<bool>
   5189  *  l3 alpm show brief [<Bucket>=<val>] [<Index>=<val>]
   5190  *                  - Show ALPM brief debug info
   5191  */
   5192 
   5193 STATIC cmd_result_t
   5194 _l3_cmd_alpm_debug_show(int unit, args_t *a)
   5195 {
   5196     int rv = CMD_OK;
   5197     cmd_result_t cmd_rv;
   5198     uint32 flags = 0;
   5199     char *c = NULL;
   5200     
   5201     int vrf = -1;
   5202     int global_vrf = 0;
   5203     int pivot = 0;
   5204     int bucket = 0;
   5205     int counter = 0;
   5206     int bkt_usage = 0;
   5207     int internal_debug = 0;
   5208     int index = -1;
   5209     
   5210     parse_table_t   pt;
   5211 
   5212     c = ARG_CUR(a);
   5213 
   5214     if (c != NULL && sal_strcasecmp(c, "brief") == 0) {
   5215         ARG_NEXT(a);
   5216         
   5217         bucket = -1;
   5218         index = -1;
   5219 
   5220         if (ARG_CNT(a)) {
   5221             parse_table_init(unit, &pt);
   5222             parse_table_add(&pt, "Bucket", PQ_DFL | PQ_INT, (void *)-1, 
   5223                             (void *)&bucket, 0);
   5224             parse_table_add(&pt, "Index", PQ_DFL | PQ_INT, (void *)-1, 
   5225                             (void *)&index, 0);
   5226             if (!parseEndOk(a, &pt, &cmd_rv)) {
   5227                 return cmd_rv;
   5228             }
   5229         }
   5230 
   5231 #if defined(BCM_TOMAHAWK_SUPPORT)
   5232         if (soc_feature(unit, soc_feature_alpm2)) {
   5233             rv = bcm_esw_alpm_debug_brief_show(unit, bucket, index);
   5234         } else
   5235 #endif
   5236 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5237         if (SOC_IS_TOMAHAWKX(unit) ||
   5238             SOC_IS_APACHE(unit) ||
   5239             SOC_IS_TRIDENT3X(unit)) {
   5240             rv = soc_th_alpm_debug_brief_show(unit, bucket, index);
   5241         } else 
   5242 #endif
   5243         {
   5244             rv = soc_alpm_debug_brief_show(unit, bucket, index);
   5245         }
   5246         if (rv < 0) {
   5247             return CMD_USAGE;
   5248         }
   5249         return CMD_OK;
   5250         
   5251     } else if (c != NULL && sal_strcasecmp(c, "all") == 0) {
   5252         ARG_NEXT(a);
   5253     } else {
   5254         parse_table_init(unit, &pt);
   5255         parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, (void *)-1, 
   5256                         (void *)&vrf, 0);
   5257         parse_table_add(&pt, "Global-VRF", PQ_DFL | PQ_BOOL, 0, 
   5258                         (void *)&global_vrf, 0);
   5259         parse_table_add(&pt, "Pivot", PQ_DFL | PQ_BOOL, 0, 
   5260                         (void *)&pivot, 0);
   5261         parse_table_add(&pt, "Bucket", PQ_DFL | PQ_BOOL, 0, 
   5262                         (void *)&bucket, 0);
   5263         parse_table_add(&pt, "Counter", PQ_DFL | PQ_BOOL, 0, 
   5264                         (void *)&counter, 0);   
   5265         parse_table_add(&pt, "BucketuSage", PQ_DFL | PQ_BOOL, 0,
   5266                         (void *)&bkt_usage, 0); 
   5267         parse_table_add(&pt, "InternalDebug", PQ_DFL | PQ_BOOL, 0,
   5268                         (void *)&internal_debug, 0);     
   5269 
   5270         if (!parseEndOk(a, &pt, &cmd_rv)) {
   5271             return cmd_rv;
   5272         }
   5273 
   5274         if (global_vrf == TRUE) {
   5275             vrf = SOC_VRF_MAX(unit) + 1;
   5276         }
   5277 
   5278         if (pivot == TRUE) {
   5279             flags |= SOC_ALPM_DEBUG_SHOW_FLAG_PVT;
   5280         }
   5281 
   5282         if (bucket == TRUE) {
   5283             flags |= SOC_ALPM_DEBUG_SHOW_FLAG_BKT;
   5284         }
   5285 
   5286         if (counter == TRUE) {
   5287             flags |= SOC_ALPM_DEBUG_SHOW_FLAG_CNT;
   5288         }
   5289 
   5290         if (internal_debug == TRUE) {
   5291             flags |= SOC_ALPM_DEBUG_SHOW_FLAG_INTDBG;
   5292         }
   5293 
   5294         if (bkt_usage == TRUE) {
   5295             flags |= SOC_ALPM_DEBUG_SHOW_FLAG_BKTUSG;
   5296         }
   5297     }
   5298 
   5299     if (flags == 0) {
   5300         flags = SOC_ALPM_DEBUG_SHOW_FLAG_ALL;
   5301     }
   5302 
   5303 #ifdef BCM_TOMAHAWK_SUPPORT
   5304     if (soc_feature(unit, soc_feature_alpm2)) {
   5305         rv = bcm_esw_alpm_debug_show(unit, vrf, flags);
   5306     } else if (SOC_IS_TOMAHAWKX(unit) ||
   5307                SOC_IS_APACHE(unit) ||
   5308                SOC_IS_TRIDENT3X(unit)) {
   5309         rv = soc_th_alpm_debug_show(unit, vrf, flags);
   5310     } else
   5311 #endif
   5312     {
   5313         rv = soc_alpm_debug_show(unit, vrf, flags);
   5314     }
   5315     if (rv < 0) {
   5316         return CMD_USAGE;
   5317     }
   5318 
   5319     return CMD_OK;
   5320 }
   5321 
   5322 /* Usage: 
   5323  *   l3 alpm find [<VRF>=<val>] <IP4>=<val> <IP6>=<val> [<Length>=<val>]
   5324  */
   5325 STATIC cmd_result_t
   5326 _l3_cmd_alpm_find(int unit, args_t *a)
   5327 {
   5328     int             rv = BCM_E_NONE;
   5329     cmd_result_t    cmd_rv = CMD_OK;
   5330     bcm_ip6_t       ip6addr = {0};
   5331     bcm_ip_t        ip4addr = 0;
   5332     int             ip_len = BCM_L3_IP4_MAX_NETLEN;
   5333     bcm_vrf_t       vrf = 1;
   5334     parse_table_t   pt; 
   5335     int             for_host = 0;
   5336     int             index;
   5337     char            ip_str[IP6ADDR_STR_LEN];
   5338     int             is_ip4 = 0;
   5339     int             is_ip6 = 0;
   5340 
   5341     bcm_l3_host_t   host;
   5342     bcm_l3_route_t  route;
   5343     bcm_l3_route_t  input;
   5344     
   5345     char            *subcmd = NULL;
   5346 
   5347     int arg_index_placeholder = ARG_CUR_INDEX(a);
   5348     while ((subcmd = ARG_CUR(a)) != NULL) {
   5349         if (parse_cmp("ip4", subcmd, '=')) {
   5350             is_ip4 = 1;
   5351         }
   5352 
   5353         if (parse_cmp("ip6", subcmd, '=')) {
   5354             is_ip6 = 1;
   5355         }
   5356 
   5357         ARG_NEXT(a);
   5358     }
   5359 
   5360     while (arg_index_placeholder < ARG_CUR_INDEX(a)) {
   5361         ARG_PREV(a);
   5362     }
   5363 
   5364 
   5365     if ((is_ip4 && is_ip6) || (!is_ip4 && !is_ip6)) {
   5366         return CMD_USAGE;
   5367     }
   5368 
   5369 
   5370     parse_table_init(unit, &pt);
   5371     parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, (void *)1, 
   5372                     (void *)&vrf, 0);    
   5373     parse_table_add(&pt, "IP4", PQ_DFL | PQ_IP, 0,
   5374                     (void *)&ip4addr, 0);    
   5375     parse_table_add(&pt, "IP6", PQ_DFL | PQ_IP6, 0,
   5376                     (void *)&ip6addr, 0); 
   5377     parse_table_add(&pt, "Length", PQ_DFL | PQ_INT, 
   5378                     (void *)BCM_L3_IP4_MAX_NETLEN, 
   5379                     (void *)&ip_len, 0);
   5380     
   5381     if (!parseEndOk(a, &pt, &cmd_rv)) {
   5382         return cmd_rv;
   5383     }      
   5384 
   5385     if (is_ip4 != 0) {
   5386         if (ip_len == BCM_L3_IP4_MAX_NETLEN) {
   5387             for_host = 1;
   5388         }
   5389     } else {
   5390         if (ip_len == BCM_L3_IP6_MAX_NETLEN) {
   5391             for_host = 1;
   5392         }
   5393     }
   5394 
   5395     bcm_l3_host_t_init(&host);
   5396     bcm_l3_route_t_init(&route);
   5397     bcm_l3_route_t_init(&input);
   5398     if (for_host) {
   5399         host.l3a_vrf = vrf;
   5400         if (is_ip4 != 0) {
   5401             host.l3a_ip_addr = ip4addr;
   5402             format_ipaddr(ip_str, ip4addr);
   5403         } else {
   5404             host.l3a_flags |= BCM_L3_IP6;
   5405             sal_memcpy(host.l3a_ip6_addr, ip6addr, BCM_IP6_ADDRLEN);
   5406             format_ip6addr(ip_str, ip6addr);
   5407         }
   5408 
   5409         rv = bcm_l3_route_find(unit, &host, &route);
   5410     } else {
   5411         input.l3a_vrf = vrf;
   5412         if (is_ip4 != 0) {
   5413             input.l3a_subnet = ip4addr;
   5414             input.l3a_ip_mask = bcm_ip_mask_create(ip_len);
   5415             format_ipaddr(ip_str, ip4addr);
   5416         } else {
   5417             input.l3a_flags |= BCM_L3_IP6;
   5418             bcm_ip6_mask_create(input.l3a_ip6_mask, ip_len);
   5419             sal_memcpy(input.l3a_ip6_net, ip6addr, BCM_IP6_ADDRLEN);
   5420             format_ip6addr(ip_str, ip6addr);
   5421         }
   5422 
   5423         rv = bcm_l3_subnet_route_find(unit, &input, &route);
   5424     }
   5425     cli_out("Matching <%d, %s/%d> ==> %s\n", vrf, ip_str, ip_len, 
   5426             bcm_errmsg(rv));
   5427     
   5428     if (rv >= 0) {
   5429         if (route.l3a_flags & BCM_L3_IP6) {
   5430             cli_out("%-7s %-6s %-41s %-18s %-4s %4s %5s %1s %4s %4s %s\n", "#", 
   5431                     "VRF", "Net-addr", "Next-Hop-Mac", "INTF", "MODID", "PORT", 
   5432                     "PRI", "CLASS", "HIT", "VLAN");
   5433         } else {
   5434             cli_out("%-7s %-6s %-19s %-18s %-4s %4s %5s %1s %4s %4s %s\n", "#", 
   5435                     "VRF", "Net-addr", "Next-Hop-Mac", "INTF", "MODID", "PORT", 
   5436                     "PRI", "CLASS", "HIT", "VLAN");
   5437         }
   5438         
   5439         index = route.l3a_tunnel_option;
   5440         route.l3a_tunnel_option = 0;
   5441         _l3_cmd_route_print(unit, index, &route, NULL);
   5442     } 
   5443 
   5444     return CMD_OK;
   5445 }
   5446 
   5447 /* Process L3 ALPM Sanity Check 
   5448  * l3 alpm sanity [<memory>=<val>] [<index>=<val>] 
   5449  */
   5450 STATIC cmd_result_t
   5451 _l3_cmd_alpm_sanity_check(int unit, args_t *a)
   5452 {
   5453     cmd_result_t    cmd_rv = CMD_OK;
   5454     int             rv = BCM_E_NONE;
   5455     static char     *mem_name = NULL;
   5456     int             index = -1;
   5457     int             check_sw = 1;
   5458     int             copyno;
   5459     parse_table_t   pt;
   5460     soc_mem_t       mem;
   5461     int             def_type = 0;
   5462     char *def_mem[] = {"L3_DEFIP", "L3_DEFIP_LEVEL1"};
   5463 
   5464     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
   5465         def_type = 1;
   5466     }
   5467 
   5468     parse_table_init(unit, &pt);
   5469     parse_table_add(&pt, "Memory", PQ_STRING|PQ_STATIC,
   5470                     def_mem[def_type], &mem_name, 0);
   5471     parse_table_add(&pt, "Index",  PQ_INT, (void *)-1, &index, 0);
   5472     parse_table_add(&pt, "Sw",  PQ_INT, (void *)1, &check_sw, 0);
   5473     /* alpm2 OK without args */
   5474     if (!soc_feature(unit, soc_feature_alpm2) || ARG_CNT(a)) {
   5475         if (!parseEndOk(a, &pt, &cmd_rv)) {
   5476         return cmd_rv;
   5477     }
   5478 
   5479     if (parse_memory_name(unit, &mem, mem_name, &copyno, 0) < 0) {
   5480         cli_out("Parse memory name failed\n");
   5481         return CMD_USAGE;
   5482         }
   5483     }
   5484 #if defined(BCM_TOMAHAWK_SUPPORT)
   5485     if (soc_feature(unit, soc_feature_alpm2)) {
   5486         rv = bcm_esw_alpm_sanity_check(unit, mem, index, check_sw);
   5487     } else
   5488 #endif
   5489 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   5490     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) {
   5491         rv = soc_th_alpm_sanity_check(unit, mem, index, check_sw);
   5492     } else 
   5493 #endif
   5494     {
   5495         rv = soc_alpm_sanity_check(unit, mem, index, check_sw);
   5496     }
   5497     if (BCM_FAILURE(rv)) {
   5498         cli_out("%s: ALPM sanity check failed: %s\n",
   5499                 ARG_CMD(a), bcm_errmsg(rv));
   5500         return (CMD_FAIL);
   5501     }
   5502     return (CMD_OK);
   5503 }
   5504 
   5505 
   5506 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   5507 char cmd_esw_alpm_usage[] =
   5508     "Parameters: <init|cust1|v4|v6|pvt|bkt|fmt> <show|add>\n\t"
   5509     "alpm init\n\t"
   5510     "alpm hitbit <enable|disable>\n\t"
   5511     "alpm trace <enable|disable|clear>\n\t"
   5512     "alpm trace sanity [enable=<val>] [Start=<val>] [End=<val>]\n\t"
   5513     "alpm trace wrap <enable|disable>\n\t"
   5514     "alpm trace dump [Showflags=<yes|no>] [File=<filename>]\n\t"
   5515     "alpm table dump [raw|chg|all|nocache] <mem> <index> <fmt> [<ent> <vrf_id>]\n\t"
   5516     "\tFor Trident3, only accept L3_DEFIP_ALPM_RAW in <mem>\n\t"
   5517     "\tFor Tomahawk3, other usage can be:\n\t"
   5518     "\talpm table dump [nocache] <LEVEL1 mem> <index or -1(all)> <levels to print(1|2|3)> <entry 0|1>\n\t"
   5519     "\t<index> is used to index <mem>\n\t"
   5520     "\t<fmt> is used to parse <mem>\n\t"
   5521     "\t<ent> is used to index entry in <mem>\n\t"
   5522     "alpm debug info on [pvt|rte|cnt|hit|all|none]\n\t"
   5523     "alpm bkt show [acb_idx]\n\t"
   5524     "alpm fmt show [acb_idx]\n\t"
   5525     "alpm pvtlen show [acb_idx]\n\t"
   5526     "alpm stat show [acb_idx]\n\t"
   5527     "alpm tcam show\n\t"
   5528     "alpm config show [acb_idx]\n\t"
   5529     "alpm pvt show [acb_idx] [bkt]\n";
   5530 
   5531 bcm_ip_t    base_ipv4 = 0x1000001;
   5532 bcm_ip6_t   base_ipv6 = {
   5533     0x2a,0x01,0x01,0x11,0xf4,0x00,0xe0,0x87,
   5534     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
   5535 };
   5536 
   5537 
   5538 /* Dump ALPM trace log */
   5539 STATIC int
   5540 _cmd_esw_alpm_trace_dump(int u, int showflags, char *filename)
   5541 {
   5542     int rv = BCM_E_NONE;
   5543     _alpm_log_t *p;
   5544     char data[300];
   5545 #ifndef NO_FILEIO
   5546     FILE *fp = NULL;
   5547 #endif
   5548 
   5549 #ifdef NO_FILEIO
   5550     if (filename[0] != 0) {
   5551         cli_out("File IO is not supported\n");
   5552         return BCM_E_UNAVAIL;
   5553     }
   5554 #endif
   5555 
   5556     if (ALPMTR(u) == NULL) {
   5557         cli_out("alpm trace not initialized yet\n");
   5558         return BCM_E_INIT;
   5559     }
   5560 
   5561     cli_out("### ALPM trace enable:%d wrap enable:%d wrap:%d count:%d "
   5562             "showflags:%d file:%s ###\n",
   5563             ALPMTR_TRACE_EN(u), ALPMTR_WRAP_EN(u),
   5564             ALPMTR_WRAP(u), ALPMTR_CNT(u), showflags, filename);
   5565 
   5566 #ifndef NO_FILEIO
   5567     if (filename[0] != 0) {
   5568         fp = sal_fopen(filename, "w");
   5569         if (fp == NULL) {
   5570             rv = BCM_E_FAIL;
   5571             cli_out("Open file %s failed\n", filename);
   5572             goto done;
   5573         }
   5574     }
   5575 #endif
   5576 
   5577     if (ALPMTR_CNT(u) == 0) {
   5578         goto done;
   5579     }
   5580 
   5581 #ifndef NO_FILEIO
   5582     if (ALPMTR_CNT(u) > ALPM_TRACE_DUMP_SIZE && !fp) {
   5583         cli_out("Too big to dump! Suggest to use: alpm trace dump file=<name>\n");
   5584         goto done;
   5585     }
   5586 #endif
   5587 
   5588     p = ALPMTR_START(u);
   5589 
   5590     do {
   5591         alpm_trace_print(u, showflags, p, data);
   5592 
   5593 #ifndef NO_FILEIO
   5594         if (fp) {
   5595             sal_fprintf(fp, "%s", data);
   5596         } else
   5597 #endif
   5598         {
   5599             cli_out("%s", data);
   5600         }
   5601 
   5602         p++;
   5603         if (p == &ALPMTR(u)->buf[ALPM_TRACE_SIZE]) {
   5604             p = ALPMTR_BUF(u);
   5605         }
   5606 
   5607     } while (p != ALPMTR_CURR(u));
   5608 
   5609     sal_sprintf(data, "\n### ALPM trace enable:%d wrap enable:%d wrap:%d count:%d "
   5610                 "showflags:%d file:%s ###\n",
   5611             ALPMTR_TRACE_EN(u), ALPMTR_WRAP_EN(u),
   5612             ALPMTR_WRAP(u), ALPMTR_CNT(u), showflags, filename);
   5613 #ifndef NO_FILEIO
   5614     if (fp) {
   5615         sal_fprintf(fp, "%s", data);
   5616     } else
   5617 #endif
   5618     {
   5619         cli_out("%s", data);
   5620     }
   5621 
   5622 done:
   5623 #ifndef NO_FILEIO
   5624     if (fp) {
   5625         sal_fclose(fp);
   5626     }
   5627 #endif
   5628     return rv;
   5629 }
   5630 
   5631 cmd_result_t
   5632 cmd_esw_alpm(int unit, args_t *a)
   5633 {
   5634     char  *table, *subcmd_s;
   5635     int   subcmd = 0;
   5636     int   acb_bmp = 3;
   5637     int   flags = 0;
   5638     int   index = 0;
   5639     int   fmt = 1;
   5640     int   ent_idx = 0;
   5641     int   vrf_id = 1;
   5642     int   copyno;
   5643     soc_mem_t mem;
   5644 
   5645     if (!soc_feature(unit, soc_feature_alpm2)) {
   5646         cli_out("Feature alpm2 is unavailable\n");
   5647         return CMD_OK;
   5648     }
   5649 
   5650     if ((table = ARG_GET(a)) == NULL) {
   5651         return CMD_USAGE;
   5652     }
   5653 
   5654     if (!soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) {
   5655         cli_out("ALPM is disabled!\n" );
   5656         ARG_DISCARD(a);
   5657         return CMD_OK;
   5658     }
   5659 
   5660     if (sal_strcasecmp(table, "init") == 0) {
   5661         bcm_esw_alpm_init(unit);
   5662         return CMD_OK;
   5663     }
   5664 
   5665     if (sal_strcasecmp(table, "hitbit") == 0) {
   5666         int rv;
   5667         if ((subcmd_s = ARG_GET(a)) == NULL) {
   5668             cli_out("Current settings:\n");
   5669             cli_out("\tInterval=%d\n", alpm_dist_hitbit_interval_get(unit));
   5670             return CMD_OK;
   5671         }
   5672         if (sal_strcasecmp(subcmd_s, "disable") == 0 ||
   5673             sal_strcasecmp(subcmd_s, "off") == 0) {
   5674             if (ALPMC(unit) && !ALPM_HIT_SKIP(unit)) {
   5675                 rv = bcm_esw_alpm_hit_deinit(unit);
   5676                 ALPM_HIT_SKIP(unit) = 1;
   5677                 if (BCM_SUCCESS(rv)) {
   5678                     cli_out("ALPM hitbit disable OK!\n");
   5679                 } else {
   5680                     cli_out("ALPM hitbit disable failed!\n");
   5681                 }
   5682             }
   5683         } else if (sal_strcasecmp(subcmd_s, "enable") == 0 ||
   5684                    sal_strcasecmp(subcmd_s, "on") == 0) {
   5685             if (ALPMC(unit) && ALPM_HIT_SKIP(unit)) {
   5686                 ALPM_HIT_SKIP(unit) = 0;
   5687                 rv = bcm_esw_alpm_hit_init(unit);
   5688                 if (BCM_SUCCESS(rv)) {
   5689                     cli_out("ALPM hitbit enable OK!\n");
   5690                 } else {
   5691                     cli_out("ALPM hitbit enable failed!\n");
   5692                 }
   5693             }
   5694         } else {
   5695             return CMD_USAGE;
   5696         }
   5697         return CMD_OK;
   5698     }
   5699 
   5700     if (sal_strcasecmp(table, "trace") == 0) {
   5701         if ((subcmd_s = ARG_GET(a)) == NULL) {
   5702             return CMD_USAGE;
   5703         }
   5704         if (sal_strcasecmp(subcmd_s, "enable") == 0) {
   5705             (void)alpm_trace_set(unit, TRUE);
   5706         } else if (sal_strcasecmp(subcmd_s, "disable") == 0) {
   5707             (void)alpm_trace_set(unit, FALSE);
   5708         } else if (sal_strcasecmp(subcmd_s, "clear") == 0) {
   5709             (void)alpm_trace_clear(unit);
   5710         } else if (sal_strcasecmp(subcmd_s, "sanity") == 0) {
   5711             parse_table_t pt;
   5712             int enable = -1, start = 0, end = -1;
   5713 
   5714             parse_table_init(unit, &pt);
   5715             /* -1 for show, 0 for disable, >0 for freq */
   5716             parse_table_add(&pt, "enable", PQ_DFL | PQ_INT, (void *)-1,
   5717                             (void *)&enable, 0);
   5718             parse_table_add(&pt, "Start", PQ_DFL | PQ_INT, (void *)0,
   5719                             (void *)&start, 0);
   5720             parse_table_add(&pt, "End", PQ_DFL | PQ_INT, (void *)-1,
   5721                             (void *)&end, 0); /* end=-1 means forever */
   5722             if (parse_arg_eq(a, &pt) < 0) {
   5723                 parse_arg_eq_done(&pt);
   5724                 return CMD_USAGE;
   5725             }
   5726 
   5727             (void)alpm_trace_sanity(unit, enable, start, end);
   5728             parse_arg_eq_done(&pt);
   5729 
   5730         } else if (sal_strcasecmp(subcmd_s, "dump") == 0) {
   5731             parse_table_t pt;
   5732             char *filename = NULL;
   5733 
   5734             parse_table_init(unit, &pt);
   5735             parse_table_add(&pt, "Showflags", PQ_BOOL, (void *)0,
   5736                             (void *)&flags, 0);
   5737             parse_table_add(&pt, "File", PQ_STRING, NULL,
   5738                                     (void *)&filename, NULL);
   5739             if (parse_arg_eq(a, &pt) < 0) {
   5740                 parse_arg_eq_done(&pt);
   5741                 return CMD_USAGE;
   5742             }
   5743 
   5744             (void) _cmd_esw_alpm_trace_dump(unit, flags, filename);
   5745             parse_arg_eq_done(&pt);
   5746 
   5747         } else if (sal_strcasecmp(subcmd_s, "wrap") == 0) {
   5748             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5749                 return CMD_USAGE;
   5750             }
   5751             if (sal_strcasecmp(subcmd_s, "enable") == 0) {
   5752                 (void)alpm_trace_wrap_set(unit, TRUE);
   5753             } else if (sal_strcasecmp(subcmd_s, "disable") == 0) {
   5754                 (void)alpm_trace_wrap_set(unit, FALSE);
   5755             } else {
   5756                 return CMD_USAGE;
   5757             }
   5758         } else {
   5759             return CMD_USAGE;
   5760         }
   5761         return CMD_OK;
   5762     }
   5763 
   5764     if (!sal_strcasecmp(table, "table")) {
   5765         if ((subcmd_s = ARG_GET(a)) == NULL) {
   5766             return CMD_USAGE;
   5767         }
   5768         if (!sal_strcasecmp(subcmd_s, "dump")) {
   5769             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5770                 return CMD_USAGE;
   5771             }
   5772             for (;;) {
   5773                 if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "raw")) {
   5774                     flags |= ALPM_DUMP_TABLE_RAW;
   5775                     subcmd_s = ARG_GET(a);
   5776                 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "all")) {
   5777                     flags |= ALPM_DUMP_TABLE_ALL;
   5778                     subcmd_s = ARG_GET(a);
   5779                 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "chg")) {
   5780                     flags |= ALPM_DUMP_TABLE_CHANGED;
   5781                     subcmd_s = ARG_GET(a);
   5782                 } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "nocache")) {
   5783                     flags |= ALPM_DUMP_TABLE_NOCACHE;
   5784                     subcmd_s = ARG_GET(a);
   5785                 } else {
   5786                     break;
   5787                 }
   5788             } /* for */
   5789 
   5790             if (subcmd_s == NULL) {
   5791                 return CMD_USAGE;
   5792             }
   5793 
   5794             if (parse_memory_name(unit, &mem, subcmd_s, &copyno, 0) >= 0) {
   5795                 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_ALPM_LEVEL2m) &&
   5796                     mem != L3_DEFIP_ALPM_LEVEL2m &&
   5797                     mem != L3_DEFIP_ALPM_LEVEL3m &&
   5798                     mem != L3_DEFIP_PAIR_LEVEL1m &&
   5799                     mem != L3_DEFIP_LEVEL1m) {
   5800                     return CMD_USAGE;
   5801                 }
   5802                 if (SOC_MEM_IS_VALID(unit, L3_DEFIP_ALPM_RAWm) &&
   5803                     mem != L3_DEFIP_ALPM_RAWm) {
   5804                     return CMD_USAGE;
   5805                 }
   5806 
   5807                 if (copyno == COPYNO_ALL) {
   5808                     copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   5809                 }
   5810             } else {
   5811                 return CMD_USAGE;
   5812             }
   5813 
   5814             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5815                 return CMD_USAGE;
   5816             }
   5817 
   5818             if (mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_PAIR_LEVEL1m) {
   5819                 index = parse_integer(subcmd_s);
   5820             } else {
   5821                 index = parse_memory_index(unit, mem, subcmd_s);
   5822             }
   5823 
   5824             if ((subcmd_s = ARG_GET(a)) == NULL || !isint(subcmd_s)) {
   5825                 return CMD_USAGE;
   5826             }
   5827             fmt = parse_integer(subcmd_s);
   5828             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5829                 ent_idx = -1; /* all entries in the bank */
   5830             } else {
   5831                 if (!isint(subcmd_s)) {
   5832                     return CMD_USAGE;
   5833                 }
   5834                 ent_idx = parse_integer(subcmd_s);
   5835             }
   5836             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5837                 vrf_id = 1; /* all entries in the bank */
   5838             } else {
   5839                 if (!isint(subcmd_s)) {
   5840                     return CMD_USAGE;
   5841                 }
   5842                 vrf_id = parse_integer(subcmd_s);
   5843             }
   5844             if (soc_feature(unit, soc_feature_alpm2)) {
   5845                 (void)alpm_table_dump(unit, vrf_id, mem, copyno, index,
   5846                                       fmt, ent_idx, flags);
   5847             } else {
   5848                 cli_out("cmd is not supported\n");
   5849             }
   5850             return CMD_OK;
   5851         }
   5852         return CMD_USAGE;
   5853     }
   5854 
   5855 
   5856     if (!sal_strcasecmp(table, "debug")) {
   5857         if ((subcmd_s = ARG_GET(a)) == NULL) {
   5858             return CMD_USAGE;
   5859         }
   5860         if (!sal_strcasecmp(subcmd_s, "info")) {
   5861             if ((subcmd_s = ARG_GET(a)) == NULL) {
   5862                 return CMD_USAGE;
   5863             }
   5864             if (!sal_strcasecmp(subcmd_s, "on")) {
   5865                 if ((subcmd_s = ARG_GET(a)) == NULL) {
   5866                     (void)alpm_dbg_info_bmp_show(unit);
   5867                     return CMD_OK;
   5868                 }
   5869                 for (;;) {
   5870                     if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "pvt")) {
   5871                         flags |= _ALPM_DBG_INFO_PVT;
   5872                         subcmd_s = ARG_GET(a);
   5873                     } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "rte")) {
   5874                         flags |= _ALPM_DBG_INFO_RTE;
   5875                         subcmd_s = ARG_GET(a);
   5876                     } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "cnt")) {
   5877                         flags |= _ALPM_DBG_INFO_CNT;
   5878                         subcmd_s = ARG_GET(a);
   5879                     } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "hit")) {
   5880                         flags |= _ALPM_DBG_INFO_HIT;
   5881                         subcmd_s = ARG_GET(a);
   5882                     } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "all")) {
   5883                         flags |= _ALPM_DBG_INFO_ALL;
   5884                         subcmd_s = ARG_GET(a);
   5885                     } else if (subcmd_s != NULL && !sal_strcasecmp(subcmd_s, "none")) {
   5886                         flags = 0;
   5887                         subcmd_s = ARG_GET(a);
   5888                     } else {
   5889                         break;
   5890                     }
   5891                 } /* for */
   5892 
   5893                 (void)alpm_dbg_info_bmp_set(unit, flags);
   5894                 return CMD_OK;
   5895             }
   5896         }
   5897         return CMD_USAGE;
   5898     }
   5899 
   5900     if (sal_strcasecmp(table, "util") == 0) {
   5901         int i;
   5902         ip6_addr_t ip6;
   5903         char buf[IP6ADDR_STR_LEN];
   5904 #define IP6_STR_CNT 6
   5905         char *ip6_str[IP6_STR_CNT] = {
   5906             "ffff::ffff:ffff:ffff:ffff:ffff:ffff",
   5907             "eeee::eeee:eeee:eeee:eeee:eeee",
   5908             "dddd:dddd::dddd",
   5909             "cccc:cccc::",
   5910             "bbbb::",
   5911             "::aaaa"
   5912         };
   5913 
   5914         for (i = 0; i < IP6_STR_CNT; i++) {
   5915             if (ip6_str[i] != NULL) {
   5916                 parse_ip6addr(ip6_str[i], ip6);
   5917                 sal_memset(buf, 0, sizeof(buf));
   5918                 format_ip6addr(buf, ip6);
   5919                 cli_out(" Original: %s\n", ip6_str[i]);
   5920                 cli_out("Converted: %s\n", buf);
   5921             }
   5922         }
   5923         return CMD_OK;
   5924     }
   5925 
   5926 
   5927     if (sal_strcasecmp(table, "load") == 0) {
   5928         if ((subcmd_s = ARG_CUR(a)) == NULL) {
   5929     	    return CMD_USAGE;
   5930         }
   5931         return CMD_OK;
   5932     }
   5933 
   5934     if ((subcmd_s = ARG_GET(a)) == NULL) {
   5935 	    return CMD_USAGE;
   5936     }
   5937 
   5938     if (sal_strcasecmp(subcmd_s, "show") == 0) {
   5939 	    subcmd = L3_SHOW;
   5940     }
   5941     if (sal_strcasecmp(subcmd_s, "add") == 0) {
   5942 	    subcmd = L3_ADD;
   5943     }
   5944 
   5945     if ((subcmd == L3_SHOW) &&
   5946         (sal_strcasecmp(table, "bkt") == 0 ||
   5947          sal_strcasecmp(table, "pvt") == 0 ||
   5948          sal_strcasecmp(table, "fmt") == 0 ||
   5949          sal_strcasecmp(table, "pvtlen") == 0 ||
   5950          sal_strcasecmp(table, "stat") == 0 ||
   5951          sal_strcasecmp(table, "config") == 0
   5952         )
   5953        ) {
   5954         subcmd_s = ARG_GET(a);
   5955         if (subcmd_s != NULL) {
   5956             acb_bmp = parse_integer(subcmd_s);
   5957         } else {
   5958             acb_bmp = 3;
   5959         }
   5960     }
   5961 
   5962     if (sal_strcasecmp(table, "bkt") == 0) {
   5963         switch (subcmd) {
   5964             /* alpm bkt show */
   5965             case L3_SHOW:
   5966                 alpm_cb_bkt_dump(unit, acb_bmp);
   5967                 return CMD_OK;
   5968             default:
   5969                 return (CMD_USAGE);
   5970         }
   5971 
   5972         return CMD_OK;
   5973     }
   5974 
   5975     if (sal_strcasecmp(table, "pvt") == 0) {
   5976         int bkt = -1;
   5977         switch (subcmd) {
   5978             /* alpm pvt show */
   5979             case L3_SHOW:
   5980                 subcmd_s = ARG_GET(a);
   5981                 if (subcmd_s != NULL) {
   5982                     bkt = parse_integer(subcmd_s);
   5983                 } else {
   5984                     bkt = -1;
   5985                 }
   5986 
   5987                 alpm_cb_pvt_dump(unit, acb_bmp, bkt);
   5988                 return CMD_OK;
   5989             default:
   5990                 return (CMD_USAGE);
   5991         }
   5992 
   5993         return CMD_OK;
   5994     }
   5995 
   5996     if (sal_strcasecmp(table, "fmt") == 0) {
   5997         switch (subcmd) {
   5998             /* alpm fmt show */
   5999             case L3_SHOW:
   6000                 alpm_cb_fmt_dump(unit, acb_bmp);
   6001                 return CMD_OK;
   6002             default:
   6003                 return (CMD_USAGE);
   6004         }
   6005 
   6006         return CMD_OK;
   6007     }
   6008 
   6009     if (sal_strcasecmp(table, "pvtlen") == 0) {
   6010         switch (subcmd) {
   6011             /* alpm pvtlen show */
   6012             case L3_SHOW:
   6013                 alpm_cb_pvtlen_dump(unit, acb_bmp);
   6014                 return CMD_OK;
   6015             default:
   6016                 return (CMD_USAGE);
   6017         }
   6018 
   6019         return CMD_OK;
   6020     }
   6021 
   6022     if (sal_strcasecmp(table, "stat") == 0) {
   6023         switch (subcmd) {
   6024             /* alpm stat show */
   6025             case L3_SHOW:
   6026                 alpm_cb_stat_dump(unit, acb_bmp);
   6027                 return CMD_OK;
   6028             default:
   6029                 return (CMD_USAGE);
   6030         }
   6031 
   6032         return CMD_OK;
   6033     }
   6034 
   6035     if (sal_strcasecmp(table, "tcam") == 0) {
   6036         switch (subcmd) {
   6037             /* alpm stat show */
   6038             case L3_SHOW:
   6039                 bcm_esw_alpm_tcam_zone_state_dump(unit);
   6040                 return CMD_OK;
   6041             default:
   6042                 return (CMD_USAGE);
   6043         }
   6044 
   6045         return CMD_OK;
   6046     }
   6047 
   6048     if (sal_strcasecmp(table, "config") == 0) {
   6049         switch (subcmd) {
   6050             /* alpm config show */
   6051             case L3_SHOW:
   6052                 alpm_cb_conf_dump(unit, acb_bmp);
   6053                 return CMD_OK;
   6054             default:
   6055                 return (CMD_USAGE);
   6056         }
   6057 
   6058         return CMD_OK;
   6059     }
   6060 
   6061 
   6062     return CMD_USAGE;
   6063 }
   6064 #endif /* BCM_TRIDENT3_SUPPORT or BCM_TOMAHAWK_SUPPORT */
   6065 #endif
   6066 
   6067 cmd_result_t
   6068 if_l3(int unit, args_t *a)
   6069 {
   6070     char           *table, *subcmd_s;
   6071     int             subcmd = 0;
   6072     parse_table_t   pt;
   6073     cmd_result_t    retCode;
   6074     bcm_mac_t      mac;
   6075     int             id = 0;
   6076     int             r, first_entry, last_entry; 
   6077     int             num_entries = 0;
   6078     int             free_l3, free_defip;
   6079 #if defined(BCM_XGS_SWITCH12_SUPPORT)
   6080     int             free_lpm_blk;
   6081 #endif
   6082     bcm_l3_info_t   l3_hw_status;
   6083     char            ip_str[IP6ADDR_STR_LEN + 3];
   6084     bcm_ip_t       ip_addr = 0, mask = 0;
   6085 #ifdef BCM_XGS_SWITCH_SUPPORT
   6086     int             interface = 0, port = 0;
   6087     int		    module = 0;
   6088     bcm_vlan_t      vlan = 0;
   6089     bcm_ip_t	    gateway = 0;
   6090     int             sip_key = 2, hash_select = XGS_HASH_COUNT;
   6091     uint8           key[SOC_MAX_MEM_WORDS * 4];
   6092     int             ecmp = 0, max_ecmp = 0;
   6093 #endif
   6094     uint32          flags;
   6095     bcm_l3_route_t  route_info;
   6096     bcm_l3_host_t   ip_info;
   6097 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6098     bcm_ip6_t       ip6_addr, sip6_addr;
   6099     int             urpf = 0, vrf = 0;
   6100     int egress_flag = FALSE;
   6101 #endif
   6102 #if defined(BCM_FIREBOLT_SUPPORT)
   6103     int i;
   6104 #endif  /* BCM_FIREBOLT_SUPPORT */
   6105     soc_mem_t uc_mem = L3_ENTRY_IPV4_UNICASTm;
   6106 
   6107 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   6108     int ext_tcam_flag = 0;
   6109     int defip_128_max = 0;    
   6110     int defip_128_free = 0;
   6111     int defip_64_max = 0;
   6112     int defip_64_free  = 0;
   6113 #endif
   6114     void *user_data = NULL;
   6115 
   6116     sal_memset(mac, 0, sizeof(bcm_mac_t));
   6117 
   6118     /* Check valid device to operation on ... */
   6119     if (!sh_check_attached(ARG_CMD(a), unit)) {
   6120 	return CMD_FAIL;
   6121     }
   6122 
   6123     if ((table = ARG_GET(a)) == NULL) {
   6124 	return CMD_USAGE;
   6125     }
   6126 
   6127     /* L3 init */
   6128     if (sal_strcasecmp(table, "init") == 0) {
   6129 	if ((r = bcm_l3_init(unit)) < 0) {
   6130 	    cli_out("%s: error initializing: %s\n", ARG_CMD(a), bcm_errmsg(r));
   6131 	}
   6132 	return CMD_OK;
   6133     }
   6134 
   6135     /* L3 detach */
   6136     if (sal_strcasecmp(table, "detach") == 0) {
   6137 	if ((r = bcm_l3_cleanup(unit)) < 0) {
   6138 	    cli_out("%s: error detaching: %s\n", ARG_CMD(a), bcm_errmsg(r));
   6139 	}
   6140 	return CMD_OK;
   6141     }
   6142     if (sal_strcasecmp(table, "defipinfo") == 0) {
   6143 #if defined(BCM_KATANA_SUPPORT)
   6144         if (SOC_IS_KATANAX(unit)) {
   6145             bcm_l3_info_t l3_info;
   6146             bcm_l3_info_t_init(&l3_info);
   6147             if ((r = bcm_l3_info(unit, &l3_info)) < 0) {
   6148                 cli_out("%s: Error L3 info: %s\n", ARG_CMD(a), bcm_errmsg(r));
   6149                 return CMD_FAIL;
   6150             }
   6151             _bcm_kt_l3_info_dump(unit);
   6152         }
   6153 #endif
   6154         return CMD_OK;
   6155     }
   6156 
   6157     if ((subcmd_s = ARG_GET(a)) == NULL) {
   6158 	return CMD_USAGE;
   6159     }
   6160 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6161     if ((sal_strcasecmp(table, "ecmp") == 0) &&
   6162         (sal_strcasecmp(subcmd_s, "egress") == 0)) {
   6163         egress_flag = TRUE;
   6164         if ((subcmd_s = ARG_GET(a)) == NULL) {
   6165             return CMD_USAGE;
   6166         }
   6167     }
   6168 #endif
   6169     if (sal_strcasecmp(subcmd_s, "add") == 0) {
   6170 	subcmd = L3_ADD;
   6171     }
   6172     if (sal_strcasecmp(subcmd_s, "update") == 0) {
   6173 	subcmd = L3_UPDATE;
   6174     }
   6175     if (sal_strcasecmp(subcmd_s, "destroy") == 0 ||
   6176         sal_strcasecmp(subcmd_s, "delete") == 0) {
   6177 	subcmd = L3_DESTROY;
   6178     }
   6179     if (sal_strcasecmp(subcmd_s, "set") == 0) {
   6180 	subcmd = L3_SET;
   6181     }
   6182     if (sal_strcasecmp(subcmd_s, "clear") == 0) {
   6183 	subcmd = L3_CLEAR;
   6184     }
   6185     if (sal_strcasecmp(subcmd_s, "show") == 0) {
   6186 	subcmd = L3_SHOW;
   6187     }
   6188     if (sal_strcasecmp(subcmd_s, "age") == 0) {
   6189 	subcmd = L3_AGE;
   6190     }
   6191 #ifdef BCM_XGS_SWITCH_SUPPORT
   6192     if (sal_strcasecmp(subcmd_s, "conflict") == 0) {
   6193 	subcmd = L3_CONFLICT;
   6194     }
   6195     if (sal_strcasecmp(subcmd_s, "hash") == 0) {
   6196 	subcmd = L3_HASH;
   6197     }
   6198     if (sal_strcasecmp(subcmd_s, "ip6hash") == 0) {
   6199 	subcmd = L3_IP6HASH;
   6200     }
   6201     if (sal_strcasecmp(subcmd_s, "sanity") == 0) {
   6202 	subcmd = L3_SANITY;
   6203     }
   6204     if (sal_strcasecmp(subcmd_s, "ecmp") == 0) {
   6205 	subcmd = L3_ECMP;
   6206     }
   6207     if (sal_strcasecmp(subcmd_s, "ecmphash") == 0) {
   6208 	subcmd = L3_ECMP_HASH;
   6209     }
   6210     if (sal_strcasecmp(subcmd_s, "maxadd") == 0) {
   6211 	subcmd = L3_MAXADD;
   6212     }
   6213 #endif
   6214     if (sal_strcasecmp(subcmd_s, "insert") == 0) {
   6215 	subcmd = L3_INSERT;
   6216     }
   6217     if (sal_strcasecmp(subcmd_s, "remove") == 0) {
   6218 	subcmd = L3_REMOVE;
   6219     }
   6220     if (sal_strcasecmp(subcmd_s, "find") == 0) {
   6221 	subcmd = L3_FIND;
   6222     }
   6223     if (sal_strcasecmp(subcmd_s, "test") == 0) {
   6224 	subcmd = L3_TEST;
   6225     }
   6226     if (!subcmd) {
   6227 	return CMD_USAGE;
   6228     }
   6229 
   6230     if (sal_strcasecmp(table, "intf") == 0) {
   6231         switch (subcmd) {
   6232             /* l3 intf add */
   6233           case L3_ADD:
   6234               return _l3_cmd_egress_intf_create(unit, a); 
   6235               /* l3 intf destroy */
   6236           case L3_DESTROY:
   6237               return  _l3_cmd_egress_intf_delete(unit, a);
   6238               /* l3 intf clear */
   6239           case L3_CLEAR:
   6240               return _l3_cmd_egress_intf_delete_all(unit, a); 
   6241               /* l3 intf show */
   6242           case L3_SHOW:
   6243               return _l3_cmd_egress_intf_show(unit, a);
   6244           default:
   6245               return (CMD_USAGE);
   6246         }
   6247     }
   6248 
   6249     if (sal_strcasecmp(table, "egress") == 0) {
   6250 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6251         switch (subcmd) {
   6252             /* l3 egress add/update */
   6253           case L3_ADD:
   6254           case L3_UPDATE:
   6255               return _l3_cmd_egress_object_create(unit, a);
   6256               /* l3 egress destroy */
   6257           case L3_DESTROY:
   6258               return _l3_cmd_egress_object_destroy(unit, a);
   6259               /* l3 egress show */
   6260           case L3_SHOW:
   6261               return _l3_cmd_egress_object_show(unit, a); 
   6262               /* l3 egress find */
   6263           case L3_FIND:
   6264               return _l3_cmd_egress_object_find(unit, a); 
   6265           default:
   6266               return (CMD_USAGE);
   6267         }
   6268     /*    coverity[unreachable]    */
   6269 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   6270     /*    coverity[unreachable]    */
   6271         cli_out("Unsupported command. \n");
   6272         return (CMD_OK);
   6273     }
   6274     if (sal_strcasecmp(table, "prefix_map") == 0) {
   6275 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6276         switch (subcmd) {
   6277             /* l3 prefix_map add */
   6278           case L3_ADD:
   6279               return _l3_cmd_prefix_map_add(unit, a);
   6280               /* l3 prefix_map delete */
   6281           case L3_DESTROY:
   6282               return _l3_cmd_prefix_map_delete(unit, a);
   6283               /* l3 prefix_map show */
   6284           case L3_SHOW:
   6285               return _l3_cmd_prefix_map_show(unit, a);
   6286               /* l3 egress clear */
   6287           case L3_CLEAR: 
   6288               return _l3_cmd_prefix_map_delete_all(unit, a);
   6289           default:
   6290               cli_out("Unsupported command. \n");
   6291               return CMD_OK;
   6292     /*    coverity[unreachable]    */
   6293         }
   6294     /** coverity[unreachable]    **/
   6295         return CMD_OK;
   6296     /*    coverity[unreachable]    */
   6297 #else
   6298         /* coverity[unreachable]    */
   6299         cli_out("Unsupported command. \n");
   6300         return CMD_OK;
   6301 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   6302     }
   6303     if (sal_strcasecmp(table, "multipath") == 0) {
   6304 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6305         switch (subcmd) {
   6306             /* l3 multipath add */
   6307           case L3_ADD:
   6308           case L3_UPDATE:
   6309               return _l3_cmd_egress_mpath_object_create(unit, a); 
   6310               /* l3 multipath max add */
   6311           case L3_MAXADD:
   6312               return _l3_cmd_egress_mpath_object_max_create(unit, a); 
   6313               /* l3 multipath destroy */
   6314           case L3_DESTROY:
   6315               return _l3_cmd_egress_mpath_object_destroy(unit, a); 
   6316               /* l3 multipath show */
   6317           case L3_SHOW:
   6318               return _l3_cmd_egress_mpath_object_show(unit, a); 
   6319           case L3_INSERT:
   6320               return _l3_cmd_egress_mpath_object_intf_insert(unit, a);
   6321           case L3_REMOVE:
   6322               return _l3_cmd_egress_mpath_object_intf_remove(unit, a);
   6323           case L3_FIND:
   6324     /** coverity[unreachable]    **/
   6325               return _l3_cmd_egress_mpath_object_lookup(unit, a);
   6326     /** coverity[unreachable]    **/
   6327           default:
   6328               cli_out("Unsupported command. \n");
   6329     /** coverity[unreachable]    **/
   6330               return CMD_OK;
   6331     /** coverity[unreachable]    **/
   6332          }
   6333     /** coverity[unreachable]    **/
   6334          return CMD_OK;
   6335 #else
   6336         /* coverity[unreachable] */
   6337         cli_out("Unsupported command. \n");
   6338         return CMD_OK;
   6339 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   6340     }
   6341     if (sal_strcasecmp(table, "ecmp") == 0) {
   6342 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6343         if (!egress_flag) {
   6344             cli_out("Unsupported command. \n");
   6345             return CMD_OK;
   6346         }
   6347         switch (subcmd) {
   6348           /* l3 ecmp add */
   6349           case L3_ADD:
   6350           case L3_UPDATE:
   6351               return _l3_cmd_egress_ecmp_object_create(unit, a);
   6352           /* l3 ecmp max add */
   6353           case L3_MAXADD:
   6354               return _l3_cmd_egress_ecmp_object_max_create(unit, a);
   6355           /* l3 ecmp destroy */
   6356           case L3_DESTROY:
   6357               return _l3_cmd_egress_ecmp_object_destroy(unit, a);
   6358           /* l3 ecmp show */
   6359           case L3_SHOW:
   6360               return _l3_cmd_egress_ecmp_object_show(unit, a);
   6361           case L3_INSERT:
   6362               return _l3_cmd_egress_ecmp_object_intf_insert(unit, a);
   6363           case L3_REMOVE:
   6364               return _l3_cmd_egress_ecmp_object_intf_remove(unit, a);
   6365           case L3_FIND:
   6366               /** coverity[unreachable]    **/
   6367               return _l3_cmd_egress_ecmp_object_lookup(unit, a);
   6368           /** coverity[unreachable]    **/
   6369           default:
   6370               cli_out("Unsupported command. \n");
   6371               /** coverity[unreachable]    **/
   6372               return CMD_OK;
   6373          /** coverity[unreachable]    **/
   6374          }
   6375          /** coverity[unreachable]    **/
   6376          return CMD_OK;
   6377 #else
   6378         /* coverity[unreachable] */
   6379         cli_out("Unsupported command. \n");
   6380         return CMD_OK;
   6381 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   6382     }
   6383 
   6384     if (sal_strcasecmp(table, "l3table") == 0) {
   6385         switch (subcmd) {
   6386 
   6387             /* l3 l3table add */
   6388           case L3_ADD:
   6389               return _l3_cmd_host_add(unit, a, FALSE);
   6390               /* l3 l3table destroy */
   6391           case L3_DESTROY:
   6392               parse_table_init(unit, &pt);
   6393 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6394               parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   6395 #endif
   6396               parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0);
   6397               if (!parseEndOk(a, &pt, &retCode))
   6398                   return retCode;
   6399 
   6400               bcm_l3_host_t_init(&ip_info);
   6401 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   6402               ip_info.l3a_vrf     = vrf;
   6403 #endif
   6404               ip_info.l3a_ip_addr = ip_addr;
   6405 
   6406               if ((r = bcm_l3_host_delete(unit, &ip_info)) < 0) {
   6407                   format_ipaddr(ip_str, ip_addr);
   6408                   cli_out("%s: Error destroy %s from L3 "
   6409                           "table: %s\n", ARG_CMD(a), ip_str, bcm_errmsg(r));
   6410                   return CMD_FAIL;
   6411               }
   6412               break;
   6413 
   6414               /* l3 l3table clear */
   6415           case L3_CLEAR:
   6416               bcm_l3_host_delete_all(unit, NULL);
   6417               break;
   6418 
   6419               /* l3 l3table show */
   6420           case L3_SHOW:
   6421               if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   6422                   cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r));
   6423                   return CMD_FAIL;
   6424               }
   6425               free_l3 = l3_hw_status.l3info_max_host -
   6426                   l3_hw_status.l3info_occupied_host;
   6427               last_entry = l3_hw_status.l3info_max_host;
   6428               if (ARG_CNT(a)) {
   6429                   if (!isint(ARG_CUR(a))) {
   6430                       cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   6431                       return (CMD_FAIL);
   6432                   }
   6433                   first_entry = parse_integer(ARG_GET(a));
   6434                   if (first_entry > last_entry) {
   6435                       cli_out("%s: Error: Illegal entry number (0 to %d)\n",
   6436                               ARG_CMD(a), last_entry);
   6437                       return (CMD_FAIL);
   6438                   }
   6439                   last_entry = first_entry;
   6440               } else {
   6441                   first_entry = 0;
   6442               }
   6443 
   6444               cli_out("Unit %d, free L3 table entries: %d\n", unit, free_l3);
   6445               cli_out("Entry VRF IP address       Mac Address           "
   6446                       "INTF MOD PORT    CLASS HIT    H/W Index\n");
   6447               user_data = soc_cm_salloc(unit, sizeof(int), "l3host hw index");
   6448               if (NULL == user_data) {
   6449                   cli_out("Failed to allocate memory\n");
   6450                   return CMD_FAIL;
   6451               }
   6452               bcm_l3_host_traverse(unit, _BCM_L3_SHOW_INDEX, first_entry,
   6453                                    last_entry, _l3_cmd_host_print, user_data);
   6454               if (user_data) {
   6455                   soc_cm_sfree(unit, user_data);
   6456               }
   6457               return CMD_OK;
   6458 
   6459               /* l3 l3table age */
   6460           case L3_AGE:
   6461               flags = BCM_L3_S_HIT;
   6462 
   6463               bcm_l3_host_age(unit, flags, _l3_cmd_host_age_callback, NULL);
   6464               return CMD_OK;
   6465 
   6466 #ifdef BCM_XGS_SWITCH_SUPPORT
   6467           case L3_HASH:
   6468 
   6469               parse_table_init(unit, &pt);
   6470 #if defined(BCM_TRX_SUPPORT)
   6471               if (SOC_IS_TRX(unit)) {
   6472                   parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0,
   6473                                   (void *)&vrf, 0);
   6474               }
   6475 #endif
   6476               sal_memset(&ip_addr, 0, sizeof(ip_addr));
   6477               sal_memset(&gateway, 0, sizeof(gateway));
   6478               parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0);
   6479               parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP, 0,
   6480                               (void *)&gateway, 0);
   6481               parse_table_add(&pt, "VID", PQ_DFL | PQ_INT, 0,
   6482                               (void *)&id, 0);
   6483               parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0,
   6484                               (void *)&hash_select, 0);
   6485               parse_table_add(&pt, "SIPKey", PQ_DFL | PQ_INT, 0,
   6486                               (void *)&sip_key, 0);
   6487               if (!parseEndOk(a, &pt, &retCode))
   6488                   return retCode;
   6489               vlan = id;
   6490 
   6491 #ifdef BCM_ISM_SUPPORT
   6492               if (soc_feature(unit, soc_feature_ism_memory)) {
   6493                   int b, rc, index, key_nbits, loop;
   6494                   l3_entry_1_entry_t l3_ipv4_uentry;
   6495                   l3_entry_2_entry_t l3_ipv4_mentry;
   6496                   soc_field_t keyflds[MAX_FIELDS], lsbfld;
   6497                   uint32 bucket, sizes[_SOC_ISM_MAX_BANKS];
   6498                   uint8 act_zero_lsb, act_offset, zero_lsb = 0, offset = 48;
   6499                   uint8 banks[_SOC_ISM_MAX_BANKS], bcount, num_flds;
   6500                   soc_mem_t l3_entry_mem;
   6501                   int mcast_flag =0;
   6502                   void *entry;
   6503 
   6504                   if (L3X_IP_MULTICAST(ip_addr)) {
   6505                       mcast_flag = 1;
   6506                       l3_entry_mem = L3_ENTRY_2m;
   6507                       entry = &l3_ipv4_mentry;
   6508                       sal_memset(&l3_ipv4_mentry, 0, sizeof(l3_ipv4_mentry)); 
   6509                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 
   6510                               KEY_TYPE_0f, SOC_MEM_KEY_L3_ENTRY_2_IPV4MC_IPV4_MULTICAST);
   6511                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry, 
   6512                               KEY_TYPE_1f, SOC_MEM_KEY_L3_ENTRY_2_IPV4MC_IPV4_MULTICAST);
   6513                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry,
   6514                               VALID_0f, 1);
   6515                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry,
   6516                               IPV4MC__GROUP_IP_ADDRf, ip_addr);
   6517                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry,
   6518                               IPV4MC__SOURCE_IP_ADDRf, gateway);
   6519                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry,
   6520                               VRF_IDf, vrf);
   6521                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv4_mentry,
   6522                               IPV4MC__VLAN_IDf, vlan);
   6523                   } else {
   6524                       l3_entry_mem = L3_ENTRY_1m;
   6525                       entry = &l3_ipv4_uentry;
   6526                       sal_memset(&l3_ipv4_uentry, 0, sizeof(l3_ipv4_uentry)); 
   6527                       soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry, VALIDf, 1);
   6528                       soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry,
   6529                               IP_ADDRf, ip_addr);
   6530                       soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry,
   6531                               VRF_IDf, vrf);
   6532                       soc_L3_ENTRY_1m_field32_set(unit, &l3_ipv4_uentry,
   6533                               KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_IPV4UC_IPV4_UNICAST);
   6534                   }
   6535 
   6536                   rc = soc_ism_get_banks_for_mem(unit, l3_entry_mem, banks, sizes,
   6537                           &bcount);
   6538                   if (rc || !bcount) {
   6539                       cli_out("Error retreiving bank info: Test aborted.\n");
   6540                       return CMD_FAIL;
   6541                   }
   6542                   rc = soc_generic_get_hash_key(unit, l3_entry_mem, entry,
   6543                           keyflds, &lsbfld, &num_flds);
   6544                   if (rc) {
   6545                       cli_out("Error constructing key: Test aborted.\n");
   6546                       return CMD_FAIL;
   6547                   }
   6548                   sal_memset(key, 0, sizeof(key));
   6549                   soc_ism_gen_key_from_keyfields(unit, l3_entry_mem, 
   6550                           entry, keyflds, key, num_flds);
   6551 
   6552                   key_nbits = soc_ism_mem_max_key_bits_get(unit, l3_entry_mem);
   6553                   cli_out("Hash(%s)[%d] of key 0x",
   6554                           (mcast_flag) ? "Ipv4MC" : "IPv4UC", hash_select);
   6555                   for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   6556                       cli_out("%02x", key[loop - 1]);
   6557                   }
   6558                   cli_out("\n");
   6559                   for (b = 0; b < bcount; b++) {
   6560                       rc = soc_ism_mem_hash_config_get(unit, l3_entry_mem, &act_zero_lsb);
   6561                       if (rc) {
   6562                           cli_out("Error retreiving hash config: Test aborted.\n");
   6563                           return CMD_FAIL;
   6564                       }
   6565                       rc = soc_ism_hash_offset_config_get(unit, banks[b], &act_offset);
   6566                       if (rc) {
   6567                           cli_out("Error retreiving hash offset: Test aborted.\n");
   6568                           return CMD_FAIL;
   6569                       }
   6570                       switch(hash_select) {
   6571                           case XGS_HASH_CRC16_UPPER: 
   6572                               offset = 48 - soc_ism_get_hash_bits(sizes[b]);
   6573                               break;
   6574                           case XGS_HASH_CRC16_LOWER:
   6575                               offset = 32;
   6576                               break;
   6577                           case XGS_HASH_LSB:
   6578                               offset = 48; zero_lsb = 1;
   6579                               break;
   6580                           case XGS_HASH_ZERO:
   6581                               break;
   6582                           case XGS_HASH_CRC32_UPPER: 
   6583                               offset = 32 - soc_ism_get_hash_bits(sizes[b]);
   6584                               break;
   6585                           case XGS_HASH_CRC32_LOWER: 
   6586                               offset = 0;
   6587                               break;
   6588                           case XGS_HASH_COUNT: 
   6589                               offset = act_offset; zero_lsb = act_zero_lsb;
   6590                               break;
   6591                           default: 
   6592                               if (hash_select > 63) {
   6593                                   cli_out("Invalid hash offset value !!\n");
   6594                                   return CMD_FAIL;
   6595                               }
   6596                               offset = hash_select; if (hash_select >= 48) { zero_lsb = 1; }
   6597                               break;
   6598                       }
   6599                       /* get config */
   6600                       if (zero_lsb != act_zero_lsb) {
   6601                           rc = soc_ism_mem_hash_config(unit, l3_entry_mem, zero_lsb);
   6602                           if (rc) {
   6603                               cli_out("Error setting hash config: Test aborted.\n");
   6604                               return CMD_FAIL;
   6605                           }
   6606                       }
   6607                       if (offset != act_offset) {
   6608                           rc = soc_ism_hash_offset_config(unit, banks[b], offset);
   6609                           if (rc) {
   6610                               cli_out("Error setting hash offset: Test aborted.\n");
   6611                               return CMD_FAIL;
   6612                           }
   6613                       }
   6614                       rc = soc_generic_hash(unit, l3_entry_mem, entry, 1 << banks[b], 0,
   6615                               &index, NULL, &bucket, NULL);
   6616                       if (rc) {
   6617                           cli_out("Error calculating hash: Test aborted.\n");
   6618                           return CMD_FAIL;
   6619                       }
   6620                       cli_out("\tBank[%d] num: %d, bucket: %d, index: %d\n", b, 
   6621                               banks[b], bucket, index);
   6622                       /* restore config */
   6623                       if (zero_lsb != act_zero_lsb) {
   6624                           rc = soc_ism_mem_hash_config(unit, l3_entry_mem, act_zero_lsb);
   6625                           if (rc) {
   6626                               cli_out("Error setting hash config: Test aborted.\n");
   6627                               return CMD_FAIL;
   6628                           }
   6629                       }
   6630                       if (offset != act_offset) {
   6631                           rc = soc_ism_hash_offset_config(unit, banks[b], act_offset);
   6632                           if (rc) {
   6633                               cli_out("Error setting hash offset: Test aborted.\n");
   6634                               return CMD_FAIL;
   6635                           }
   6636                       }
   6637                   }
   6638                   return CMD_OK;
   6639               }
   6640 #endif /* BCM_ISM_SUPPORT */
   6641 
   6642 #ifdef BCM_TRX_SUPPORT
   6643               if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
   6644 
   6645                   int mcast_flag = 0;
   6646                   int hash_bucket;
   6647                   int key_nbits;
   6648                   l3_entry_ipv4_multicast_entry_t  l3x_ip4_mentry;
   6649                   l3_entry_ipv4_unicast_entry_t    l3x_ip4_uentry;
   6650                   soc_field_t key_type_field;
   6651                   int key_type_value;
   6652 
   6653                   if (hash_select == FB_HASH_COUNT) {
   6654                       /* Get the hash selection from hardware */
   6655                       uint32          regval;
   6656                       int             rv;
   6657                       if ((rv = READ_HASH_CONTROLr(unit, &regval)) < 0) {
   6658                           cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv));
   6659                           return CMD_FAIL;
   6660                       }
   6661                       hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval,
   6662                                                       L3_HASH_SELECTf);
   6663                   }
   6664 
   6665                   if (L3X_IP_MULTICAST(ip_addr)) {
   6666                       /* Given IP address is multicast IP address */
   6667                       mcast_flag = 1;
   6668                       key_type_field = (SOC_MEM_FIELD_VALID(unit, 
   6669                                         L3_ENTRY_IPV4_MULTICASTm, KEY_TYPEf))?
   6670                                         KEY_TYPEf : KEY_TYPE_0f;
   6671 #if defined(BCM_TRIDENT2_SUPPORT)
   6672                       if (SOC_IS_TRIDENT2X(unit)) {
   6673                           key_type_value = TD2_L3_HASH_KEY_TYPE_V4MC;
   6674                       } else
   6675 #endif /* BCM_TRIDENT2_SUPPORT */
   6676                       {
   6677                           key_type_value = TR_L3_HASH_KEY_TYPE_V4MC;
   6678                       }
   6679 
   6680                       sal_memset(&l3x_ip4_mentry, 0,
   6681                                  sizeof(l3_entry_ipv4_multicast_entry_t));
   6682 
   6683                            
   6684                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6685                                           (uint32 *) &l3x_ip4_mentry, 
   6686                                           key_type_field, key_type_value);
   6687 
   6688                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6689                                           (uint32 *) &l3x_ip4_mentry,
   6690                                           GROUP_IP_ADDRf, ip_addr);
   6691 
   6692                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6693                                           (uint32 *) &l3x_ip4_mentry,
   6694                                           SOURCE_IP_ADDRf, gateway);
   6695 
   6696                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6697                                           (uint32 *) &l3x_ip4_mentry, VLAN_IDf,
   6698                                           vlan);
   6699 
   6700                       /* prevent the case once VRF_ID field is not existed */
   6701                       if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_MULTICASTm, VRF_IDf)) {
   6702                           soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6703                                               (uint32 *) &l3x_ip4_mentry, 
   6704                                               VRF_IDf, vrf);
   6705                       }
   6706                       /* coverity[overrun-buffer-val : FALSE]    */
   6707                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   6708                                                                (uint32 *) &l3x_ip4_mentry, key);
   6709                   } else {
   6710                       /* Given IP address is Unicast IP address */
   6711 #if defined(BCM_TRIDENT2_SUPPORT)
   6712                       if (SOC_IS_TRIDENT2X(unit)) {
   6713                           key_type_value = TD2_L3_HASH_KEY_TYPE_V4UC;
   6714                       } else
   6715 #endif /* BCM_TRIDENT2_SUPPORT */
   6716                       {
   6717                           key_type_value = TR_L3_HASH_KEY_TYPE_V4UC;
   6718                       }
   6719                       sal_memset(&l3x_ip4_uentry, 0,
   6720                                  sizeof(l3_entry_ipv4_unicast_entry_t));
   6721 
   6722                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm,
   6723                                           (uint32 *) &l3x_ip4_mentry, KEY_TYPEf, 
   6724                                           key_type_value);
   6725 
   6726                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm,
   6727                                           (uint32 *) &l3x_ip4_uentry,
   6728                                           IP_ADDRf, ip_addr);
   6729 
   6730                       /* prevent the case once VRF_ID field is not existed */
   6731                       if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, VRF_IDf)) {
   6732                           soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm,
   6733                                               (uint32 *) &l3x_ip4_uentry, 
   6734                                               VRF_IDf, vrf);
   6735                       }
   6736                       /* coverity[overrun-buffer-val : FALSE]    */
   6737                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   6738                                                                (uint32 *) &l3x_ip4_uentry,
   6739                                                                key);
   6740                   }
   6741 
   6742                   hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key);
   6743 
   6744                   if (mcast_flag) {
   6745                       cli_out("Hash(IPMC)[%d] of key "
   6746                               "0x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x "
   6747                               "is bucket 0x%03x (%d)\n", hash_select,
   6748                               key[9], key[8], key[7], key[6], key[5],
   6749                               key[4], key[3], key[2], key[1], key[0],
   6750                               hash_bucket, hash_bucket);
   6751                   } else {
   6752                       cli_out("Hash(UC)[%d] of key "
   6753                               "0x%02x%02x%02x%02x "
   6754                               "is bucket 0x%03x (%d)\n", hash_select,
   6755                               key[3], key[2], key[1], key[0],
   6756                               hash_bucket, hash_bucket);
   6757                   }
   6758                   break;
   6759               }
   6760 #endif /* end of BCM_TRX_SUPPORT*/
   6761 #ifdef BCM_FIREBOLT_SUPPORT
   6762               if (SOC_IS_FBX(unit)) {
   6763 
   6764                   int mcast_flag = 0;
   6765                   int hash_bucket;
   6766                   int key_nbits;
   6767                   l3_entry_ipv4_multicast_entry_t  l3x_ip4_mentry;
   6768                   l3_entry_ipv4_unicast_entry_t    l3x_ip4_uentry;
   6769 
   6770                   if (hash_select == FB_HASH_COUNT) {
   6771                       /* Get the hash selection from hardware */
   6772                       uint32          regval;
   6773                       int             rv;
   6774                       if ((rv = READ_HASH_CONTROLr(unit, &regval)) < 0) {
   6775                           cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv));
   6776                           return CMD_FAIL;
   6777                       }
   6778                       hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval,
   6779                                                       L3_HASH_SELECTf);
   6780                   }
   6781 
   6782                   if (L3X_IP_MULTICAST(ip_addr)) {
   6783                       /* Given IP address is multicast IP address */
   6784                       mcast_flag = 1;
   6785                       sal_memset(&l3x_ip4_mentry, 0,
   6786                                  sizeof(l3_entry_ipv4_multicast_entry_t));
   6787 
   6788                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6789                                           (uint32 *) &l3x_ip4_mentry, IPMCf, 1);
   6790 
   6791                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6792                                           (uint32 *) &l3x_ip4_mentry,
   6793                                           GROUP_IP_ADDRf, ip_addr);
   6794 
   6795                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6796                                           (uint32 *) &l3x_ip4_mentry,
   6797                                           SOURCE_IP_ADDRf, gateway);
   6798 
   6799                       soc_mem_field32_set(unit, L3_ENTRY_IPV4_MULTICASTm,
   6800                                           (uint32 *) &l3x_ip4_mentry, VLAN_IDf,
   6801                                           vlan);
   6802                       /* coverity[overrun-buffer-val : FALSE]    */
   6803                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   6804                                                                (uint32 *) &l3x_ip4_mentry, key);
   6805                   } else {
   6806                       /* Given IP address is Unicast IP address */
   6807                       sal_memset(&l3x_ip4_uentry, 0,
   6808                                  sizeof(l3_entry_ipv4_unicast_entry_t));
   6809 
   6810 #ifdef BCM_TRIDENT3_SUPPORT
   6811                       if (SOC_IS_TRIDENT3X(unit)) {
   6812                           uc_mem = L3_ENTRY_SINGLEm;
   6813                       }
   6814 #endif
   6815                       if (L3X_IP_MULTICAST(ip_addr)) {
   6816                           soc_mem_field32_set(unit, uc_mem,
   6817                                               (uint32 *) &l3x_ip4_uentry, IPMCf, 1);
   6818                       }
   6819 
   6820                       soc_mem_field32_set(unit, uc_mem,
   6821                                           (uint32 *) &l3x_ip4_uentry,
   6822                                           IP_ADDRf, ip_addr);
   6823                       /* coverity[overrun-buffer-val : FALSE]    */
   6824                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   6825                                                                (uint32 *) &l3x_ip4_uentry,
   6826                                                                key);
   6827                   }
   6828 
   6829                   hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key);
   6830 
   6831                   if (mcast_flag) {
   6832                       cli_out("Hash(IPMC)[%d] of key "
   6833                               "0x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x "
   6834                               "is bucket 0x%03x (%d)\n", hash_select,
   6835                               key[9], key[8], key[7], key[6], key[5],
   6836                               key[4], key[3], key[2], key[1], key[0],
   6837                               hash_bucket, hash_bucket);
   6838                   } else {
   6839                       cli_out("Hash(UC)[%d] of key "
   6840                               "0x%02x%02x%02x%02x "
   6841                               "is bucket 0x%03x (%d)\n", hash_select,
   6842                               key[3], key[2], key[1], key[0],
   6843                               hash_bucket, hash_bucket);
   6844                   }
   6845               }
   6846 #endif /* end of BCM_FIREBOLT_SUPPORT */
   6847               break;
   6848 
   6849               /* l3 l3table ip6hash */
   6850           case L3_IP6HASH:
   6851               if (!SOC_IS_FBX(unit)) {
   6852                   cli_out("Command valid only for FB and ER switches\n");
   6853                   return CMD_FAIL;
   6854               }
   6855 #ifdef BCM_XGS3_SWITCH_SUPPORT
   6856               parse_table_init(unit, &pt);
   6857 #if defined(BCM_TRX_SUPPORT)
   6858               if (SOC_IS_TRX(unit)) {
   6859                   parse_table_add(&pt, "VRF", PQ_DFL|PQ_INT, 0,
   6860                                   (void *)&vrf, 0);
   6861               }
   6862 #endif
   6863               sal_memset(&ip6_addr, 0, sizeof(ip6_addr));
   6864               sal_memset(&sip6_addr, 0, sizeof(sip6_addr));
   6865               parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0,
   6866                               (void *)&ip6_addr, 0);
   6867               parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP6, 0,
   6868                               (void *)&sip6_addr, 0);
   6869               parse_table_add(&pt, "VID", PQ_DFL | PQ_INT, 0,
   6870                               (void *)&id, 0);
   6871               parse_table_add(&pt, "Hash", PQ_DFL | PQ_INT, 0,
   6872                               (void *)&hash_select, 0);
   6873               parse_table_add(&pt, "SIPKey", PQ_DFL | PQ_INT, 0,
   6874                               (void *)&sip_key, 0);
   6875               if (!parseEndOk(a, &pt, &retCode)) {
   6876                   return retCode;
   6877               }
   6878               vlan = id;
   6879 
   6880 #ifdef BCM_ISM_SUPPORT
   6881               if (soc_feature(unit, soc_feature_ism_memory)) {
   6882                   int b, rc, index, loop, key_nbits;
   6883                   l3_entry_2_entry_t l3_ipv6_uentry;
   6884                   l3_entry_4_entry_t l3_ipv6_mentry;
   6885                   soc_field_t keyflds[MAX_FIELDS], lsbfld;
   6886                   uint32 bucket, sizes[_SOC_ISM_MAX_BANKS];
   6887                   uint8 act_zero_lsb, act_offset, zero_lsb = 0, offset = 48;
   6888                   uint8 banks[_SOC_ISM_MAX_BANKS], bcount, num_flds;
   6889                   soc_mem_t l3_entry_mem;
   6890                   int mcast_flag = 0;
   6891                   void *entry;
   6892 
   6893                   if (BCM_IP6_MULTICAST(ip6_addr)) {
   6894                       soc_field_t typef[] = {KEY_TYPE_0f, KEY_TYPE_1f, 
   6895                                              KEY_TYPE_2f, KEY_TYPE_3f};
   6896                       mcast_flag = 1;
   6897                       l3_entry_mem = L3_ENTRY_4m;
   6898                       entry = &l3_ipv6_mentry;
   6899                       sal_memset(&l3_ipv6_mentry, 0, sizeof(l3_ipv6_mentry)); 
   6900                       soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry,
   6901                               VALID_0f, 1);
   6902                       soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry,
   6903                               IPV6MC__GROUP_IP_ADDR_LWR_96f, ip6_addr,
   6904                               SOC_MEM_IP6_LOWER_96BIT);
   6905                       soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry,
   6906                               IPV6MC__GROUP_IP_ADDR_UPR_24f, ip6_addr,
   6907                               SOC_MEM_IP6_BITS_119_96);
   6908                       soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry,
   6909                               IPV6MC__SOURCE_IP_ADDR_LWR_64f, sip6_addr,
   6910                               SOC_MEM_IP6_LOWER_ONLY);
   6911                       soc_mem_ip6_addr_set(unit, L3_ENTRY_4m, &l3_ipv6_mentry,
   6912                               IPV6MC__SOURCE_IP_ADDR_UPR_64f, sip6_addr,
   6913                               SOC_MEM_IP6_UPPER_ONLY);
   6914                       soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry,
   6915                               IPV6MC__VRF_IDf, vrf);
   6916                       soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry,
   6917                               IPV6MC__VLAN_IDf, id);
   6918                       for (i = 0; i < 4; i++) {
   6919                           soc_L3_ENTRY_4m_field32_set(unit, &l3_ipv6_mentry, 
   6920                                   typef[i],
   6921                                   SOC_MEM_KEY_L3_ENTRY_4_IPV6MC_IPV6_MULTICAST);
   6922                       }
   6923                   } else {
   6924                       l3_entry_mem = L3_ENTRY_2m;
   6925                       entry = &l3_ipv6_uentry;
   6926                       sal_memset(&l3_ipv6_uentry, 0, sizeof(l3_ipv6_uentry)); 
   6927                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry,
   6928                               VALID_0f, 1);
   6929                       soc_mem_ip6_addr_set(unit, L3_ENTRY_2m, &l3_ipv6_uentry,
   6930                               IPV6UC__IP_ADDR_LWR_64f, ip6_addr,
   6931                               SOC_MEM_IP6_LOWER_ONLY);
   6932                       soc_mem_ip6_addr_set(unit, L3_ENTRY_2m, &l3_ipv6_uentry,
   6933                               IPV6UC__IP_ADDR_UPR_64f, ip6_addr,
   6934                               SOC_MEM_IP6_UPPER_ONLY);
   6935                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry,
   6936                               VRF_IDf, vrf);
   6937                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 
   6938                               KEY_TYPE_0f,
   6939                               SOC_MEM_KEY_L3_ENTRY_2_IPV6UC_IPV6_UNICAST);
   6940                       soc_L3_ENTRY_2m_field32_set(unit, &l3_ipv6_uentry, 
   6941                               KEY_TYPE_1f,
   6942                               SOC_MEM_KEY_L3_ENTRY_2_IPV6UC_IPV6_UNICAST);
   6943                   }
   6944 
   6945                   rc = soc_ism_get_banks_for_mem(unit, l3_entry_mem, banks, sizes,
   6946                           &bcount);
   6947                   if (rc || !bcount) {
   6948                       cli_out("Error retreiving bank info: Test aborted.\n");
   6949                       return CMD_FAIL;
   6950                   }
   6951                   rc = soc_generic_get_hash_key(unit, l3_entry_mem, entry,
   6952                           keyflds, &lsbfld, &num_flds);
   6953                   if (rc) {
   6954                       cli_out("Error constructing key: Test aborted.\n");
   6955                       return CMD_FAIL;
   6956                   }
   6957                   sal_memset(key, 0, sizeof(key));
   6958                   soc_ism_gen_key_from_keyfields(unit, l3_entry_mem, 
   6959                           entry, keyflds, key, num_flds);
   6960 
   6961                   key_nbits = soc_ism_mem_max_key_bits_get(unit, l3_entry_mem);
   6962                   cli_out("Hash(%s)[%d] of key 0x",
   6963                           (mcast_flag) ? "Ipv6MC" : "IPv6UC", hash_select);
   6964                   for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   6965                       cli_out("%02x", key[loop - 1]);
   6966                   }
   6967                   cli_out("\n");
   6968                   for (b = 0; b < bcount; b++) {
   6969                       rc = soc_ism_mem_hash_config_get(unit, l3_entry_mem, &act_zero_lsb);
   6970                       if (rc) {
   6971                           cli_out("Error retreiving hash config: Test aborted.\n");
   6972                           return CMD_FAIL;
   6973                       }
   6974                       rc = soc_ism_hash_offset_config_get(unit, banks[b], &act_offset);
   6975                       if (rc) {
   6976                           cli_out("Error retreiving hash offset: Test aborted.\n");
   6977                           return CMD_FAIL;
   6978                       }
   6979                       switch(hash_select) {
   6980                           case XGS_HASH_CRC16_UPPER: 
   6981                               offset = 48 - soc_ism_get_hash_bits(sizes[b]);
   6982                               break;
   6983                           case XGS_HASH_CRC16_LOWER: 
   6984                               offset = 32;
   6985                               break;
   6986                           case XGS_HASH_LSB: 
   6987                               offset = 48; zero_lsb = 1;
   6988                               break;
   6989                           case XGS_HASH_ZERO:
   6990                               break;
   6991                           case XGS_HASH_CRC32_UPPER: 
   6992                               offset = 32 - soc_ism_get_hash_bits(sizes[b]);
   6993                               break;
   6994                           case XGS_HASH_CRC32_LOWER: 
   6995                               offset = 0;
   6996                               break;
   6997                           case XGS_HASH_COUNT: 
   6998                               offset = act_offset; zero_lsb = act_zero_lsb;
   6999                               break;
   7000                           default:
   7001                               if (hash_select > 63) {
   7002                                   cli_out("Invalid hash offset value !!\n");
   7003                                   return CMD_FAIL;
   7004                               }
   7005                               offset = hash_select; if (hash_select >= 48) { zero_lsb = 1; }
   7006                               break;
   7007                       }
   7008                       /* get config */
   7009                       if (zero_lsb != act_zero_lsb) {
   7010                           rc = soc_ism_mem_hash_config(unit, l3_entry_mem, zero_lsb);
   7011                           if (rc) {
   7012                               cli_out("Error setting hash config: Test aborted.\n");
   7013                               return CMD_FAIL;
   7014                           }
   7015                       }
   7016                       if (offset != act_offset) {
   7017                           rc = soc_ism_hash_offset_config(unit, banks[b], offset);
   7018                           if (rc) {
   7019                               cli_out("Error setting hash offset: Test aborted.\n");
   7020                               return CMD_FAIL;
   7021                           }
   7022                       }
   7023                       rc = soc_generic_hash(unit, l3_entry_mem, entry, 1 << banks[b], 0,
   7024                               &index, NULL, &bucket, NULL);
   7025                       if (rc) {
   7026                           cli_out("Error calculating hash: Test aborted.\n");
   7027                           return CMD_FAIL;
   7028                       }
   7029                       cli_out("\tBank[%d] num: %d, bucket: %d, index: %d\n", b, 
   7030                               banks[b], bucket, index);
   7031                       /* restore config */
   7032                       if (zero_lsb != act_zero_lsb) {
   7033                           rc = soc_ism_mem_hash_config(unit, l3_entry_mem, act_zero_lsb);
   7034                           if (rc) {
   7035                               cli_out("Error setting hash config: Test aborted.\n");
   7036                               return CMD_FAIL;
   7037                           }
   7038                       }
   7039                       if (offset != act_offset) {
   7040                           rc = soc_ism_hash_offset_config(unit, banks[b], act_offset);
   7041                           if (rc) {
   7042                               cli_out("Error setting hash offset: Test aborted.\n");
   7043                               return CMD_FAIL;
   7044                           }
   7045                       }
   7046                   }
   7047                   return CMD_OK;
   7048               }
   7049 #endif /* BCM_ISM_SUPPORT */
   7050 
   7051               if (hash_select == FB_HASH_COUNT) {
   7052                   /* Get the hash selection from hardware */
   7053                   uint32 regval;
   7054                   int rv;
   7055 
   7056                   if ((rv = READ_HASH_CONTROLr(unit, &regval)) < 0) {
   7057                       cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv));
   7058                       return CMD_FAIL;
   7059                   }
   7060                   hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval,
   7061                                                   L3_HASH_SELECTf);
   7062               }
   7063 #endif
   7064 #ifdef BCM_TRX_SUPPORT
   7065               if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
   7066                   int key_nbits;
   7067                   int hash_bucket = 0;
   7068                   int mcast_flag =0;
   7069                   int loop;
   7070                   l3_entry_ipv6_unicast_entry_t    l3x_ip6_uentry;
   7071                   l3_entry_ipv6_multicast_entry_t  l3x_ip6_mentry;
   7072                   soc_field_t vrf_field, vlan_field;
   7073                   int key_type_value;
   7074 
   7075                   if (BCM_IP6_MULTICAST(ip6_addr)) {
   7076                       soc_field_t typef[] = {KEY_TYPE_0f, KEY_TYPE_1f, 
   7077                                              KEY_TYPE_2f, KEY_TYPE_3f};
   7078                       mcast_flag  = 1;
   7079 
   7080 #if defined(BCM_TRIDENT2_SUPPORT)
   7081                       if (SOC_IS_TRIDENT2X(unit)) {
   7082                           key_type_value = TD2_L3_HASH_KEY_TYPE_V6MC;
   7083                       } else
   7084 #endif /* BCM_TRIDENT2_SUPPORT */
   7085                       {
   7086                           key_type_value = TR_L3_HASH_KEY_TYPE_V6MC;
   7087                       }
   7088                       sal_memset(&l3x_ip6_mentry, 0,
   7089                                  sizeof(l3_entry_ipv6_multicast_entry_t));
   7090 
   7091                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7092                                            &l3x_ip6_mentry,
   7093                                            GROUP_IP_ADDR_LWR_64f,
   7094                                            (uint8*) &ip6_addr,
   7095                                            SOC_MEM_IP6_LOWER_ONLY);
   7096 
   7097                       ip6_addr[0] = 0x0;
   7098                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7099                                            &l3x_ip6_mentry, GROUP_IP_ADDR_UPR_56f,
   7100                                            (uint8*) &ip6_addr,
   7101                                            SOC_MEM_IP6_UPPER_ONLY);
   7102 
   7103                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7104                                            &l3x_ip6_mentry, SOURCE_IP_ADDR_LWR_64f,
   7105                                            (uint8*) &sip6_addr,
   7106                                            SOC_MEM_IP6_LOWER_ONLY);
   7107 
   7108                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7109                                            &l3x_ip6_mentry, SOURCE_IP_ADDR_UPR_64f,
   7110                                            (uint8*) &sip6_addr,
   7111                                            SOC_MEM_IP6_UPPER_ONLY);
   7112 
   7113                        vlan_field = (SOC_MEM_FIELD_VALID(unit, 
   7114                                         L3_ENTRY_IPV6_MULTICASTm, VLAN_IDf))? \
   7115                                         VLAN_IDf: VLAN_ID_0f;
   7116 
   7117                        soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit,
   7118                                            &l3x_ip6_mentry, vlan_field, vlan);
   7119 
   7120                        vrf_field = (SOC_MEM_FIELD_VALID(unit, 
   7121                                         L3_ENTRY_IPV6_MULTICASTm, VRF_IDf))? \
   7122                                         VRF_IDf: VRF_ID_0f;
   7123 
   7124                       /* prevent the case once VRF_ID field is not existed */
   7125                       if (soc_mem_field_valid(unit, 
   7126                                         L3_ENTRY_IPV6_MULTICASTm, vrf_field)) {
   7127                           soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit,
   7128                                            &l3x_ip6_mentry, vrf_field, vrf);
   7129                       }
   7130 
   7131                       for (i=0; i < 4; i++) {
   7132                           soc_L3_ENTRY_IPV6_MULTICASTm_field32_set
   7133                               (unit, &l3x_ip6_mentry, typef[i], 
   7134                                key_type_value);
   7135                       }
   7136                       /* coverity[overrun-buffer-val : FALSE]    */
   7137                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   7138                                                                (uint32 *) &l3x_ip6_mentry, key);
   7139                   } else {
   7140 #if defined(BCM_TRIDENT2_SUPPORT)
   7141                       if (SOC_IS_TRIDENT2X(unit)) {
   7142                           key_type_value = TD2_L3_HASH_KEY_TYPE_V6UC;
   7143                       } else
   7144 #endif /* BCM_TRIDENT2_SUPPORT */
   7145                       {
   7146                           key_type_value = TR_L3_HASH_KEY_TYPE_V6UC;
   7147                       }
   7148                       sal_memset(&l3x_ip6_uentry, 0,
   7149                                  sizeof(l3_entry_ipv6_unicast_entry_t));
   7150 
   7151                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm,
   7152                                            &l3x_ip6_uentry, IP_ADDR_LWR_64f,
   7153                                            ip6_addr, SOC_MEM_IP6_LOWER_ONLY);
   7154 
   7155                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm,
   7156                                            &l3x_ip6_uentry, IP_ADDR_UPR_64f,
   7157                                            ip6_addr, SOC_MEM_IP6_UPPER_ONLY);
   7158 
   7159                       soc_L3_ENTRY_IPV6_UNICASTm_field32_set
   7160                           (unit, &l3x_ip6_uentry, KEY_TYPE_1f, key_type_value);
   7161 
   7162                       soc_L3_ENTRY_IPV6_UNICASTm_field32_set
   7163                           (unit, &l3x_ip6_uentry, KEY_TYPE_0f, key_type_value);
   7164 
   7165                        vrf_field = (SOC_MEM_FIELD_VALID(unit, 
   7166                                         L3_ENTRY_IPV6_UNICASTm, VRF_IDf))? \
   7167                                         VRF_IDf: VRF_ID_0f;
   7168 
   7169                       /* prevent the case once VRF_ID field is not existed */
   7170                       if (soc_mem_field_valid(unit, 
   7171                                         L3_ENTRY_IPV6_UNICASTm, vrf_field)) {
   7172                           soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit,
   7173                                                &l3x_ip6_mentry, vrf_field, vrf);
   7174                       }
   7175                       /* coverity[overrun-buffer-val : FALSE]    */
   7176                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   7177                                                                (uint32 *) &l3x_ip6_uentry, key);
   7178                   }
   7179                   hash_bucket = soc_fb_l3_hash(unit, hash_select, key_nbits, key);
   7180                   if (mcast_flag) {
   7181                       cli_out("Hash(IPMC)[%d] of key 0x",hash_select);
   7182                       for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   7183                           cli_out("%02x", key[loop - 1]);
   7184                       }
   7185                       cli_out(" ");
   7186                       cli_out("is bucket 0x%3x (%d)\n", hash_bucket,
   7187                               hash_bucket);
   7188                   } else {
   7189                       cli_out("Hash(UC)[%d] of key 0x",hash_select);
   7190                       for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   7191                           cli_out("%02x", key[loop - 1]);
   7192                       }
   7193                       cli_out(" ");
   7194                       cli_out("is bucket 0x%3x (%d)\n", hash_bucket,
   7195                               hash_bucket);
   7196                   }
   7197                   break;
   7198               }
   7199 #endif /* BCM_TRX_SUPPORT */
   7200 #ifdef BCM_FIREBOLT_SUPPORT
   7201               if (SOC_IS_FBX(unit)) {
   7202                   int key_nbits;
   7203                   int hash_bucket = 0;
   7204                   int mcast_flag =0;
   7205                   int loop;
   7206                   l3_entry_ipv6_unicast_entry_t    l3x_ip6_uentry;
   7207                   l3_entry_ipv6_multicast_entry_t  l3x_ip6_mentry;
   7208 
   7209                   if (BCM_IP6_MULTICAST(ip6_addr)) {
   7210                       soc_field_t v6f[] = {V6_0f, V6_1f, V6_2f, V6_3f};
   7211                       soc_field_t mcf[] = {IPMC_0f, IPMC_1f, IPMC_2f, IPMC_3f};
   7212                       soc_field_t vidf[] = {VLAN_ID_0f, VLAN_ID_1f, VLAN_ID_2f,
   7213                           VLAN_ID_3f};
   7214                           mcast_flag  = 1;
   7215 
   7216                           sal_memset(&l3x_ip6_mentry, 0,
   7217                                      sizeof(l3_entry_ipv6_multicast_entry_t));
   7218 
   7219                           soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7220                                                &l3x_ip6_mentry,
   7221                                                GROUP_IP_ADDR_LWR_64f,
   7222                                                (uint8*) &ip6_addr,
   7223                                                SOC_MEM_IP6_LOWER_ONLY);
   7224 
   7225                           ip6_addr[0] = 0x0;
   7226                           soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7227                                                &l3x_ip6_mentry, GROUP_IP_ADDR_UPR_56f,
   7228                                                (uint8*) &ip6_addr,
   7229                                                SOC_MEM_IP6_UPPER_ONLY);
   7230 
   7231                           soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7232                                                &l3x_ip6_mentry, SOURCE_IP_ADDR_LWR_64f,
   7233                                                (uint8*) &sip6_addr,
   7234                                                SOC_MEM_IP6_LOWER_ONLY);
   7235 
   7236                           soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_MULTICASTm,
   7237                                                &l3x_ip6_mentry, SOURCE_IP_ADDR_UPR_64f,
   7238                                                (uint8*) &sip6_addr,
   7239                                                SOC_MEM_IP6_UPPER_ONLY);
   7240 
   7241                           for (i=0; i < 4; i++) {
   7242                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit,
   7243                                                                        &l3x_ip6_mentry, v6f[i], 1);
   7244                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit,
   7245                                                                        &l3x_ip6_mentry, mcf[i], 1);
   7246                               soc_L3_ENTRY_IPV6_MULTICASTm_field32_set(unit,
   7247                                                                        &l3x_ip6_mentry, vidf[i], vlan);
   7248                           }
   7249                           /* coverity[overrun-buffer-val : FALSE]    */
   7250                           key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   7251                                                                    (uint32 *) &l3x_ip6_mentry, key);
   7252                   } else {
   7253                       sal_memset(&l3x_ip6_uentry, 0,
   7254                                  sizeof(l3_entry_ipv6_unicast_entry_t));
   7255 
   7256                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm,
   7257                                            &l3x_ip6_uentry, IP_ADDR_LWR_64f,
   7258                                            ip6_addr, SOC_MEM_IP6_LOWER_ONLY);
   7259 
   7260                       soc_mem_ip6_addr_set(unit, L3_ENTRY_IPV6_UNICASTm,
   7261                                            &l3x_ip6_uentry, IP_ADDR_UPR_64f,
   7262                                            ip6_addr, SOC_MEM_IP6_UPPER_ONLY);
   7263 
   7264                       soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit,
   7265                                                              &l3x_ip6_uentry,
   7266                                                              V6_1f, 1);
   7267 
   7268                       soc_L3_ENTRY_IPV6_UNICASTm_field32_set(unit,
   7269                                                              &l3x_ip6_uentry,
   7270                                                              V6_0f, 1);
   7271                       /* coverity[overrun-buffer-val : FALSE]    */
   7272                       key_nbits = soc_fb_l3x_base_entry_to_key(unit,
   7273                                                                (uint32 *) &l3x_ip6_uentry, key);
   7274                   }
   7275                   hash_bucket = soc_fb_l3_hash(unit, hash_select,
   7276                                                key_nbits, key);
   7277                   if (mcast_flag) {
   7278                       cli_out("Hash(IPMC)[%d] of key 0x",hash_select);
   7279                       for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   7280                           cli_out("%02x", key[loop - 1]);
   7281                       }
   7282                       cli_out(" ");
   7283                       cli_out("is bucket 0x%3x (%d)\n", hash_bucket,
   7284                               hash_bucket);
   7285                   } else {
   7286                       cli_out("Hash(UC)[%d] of key 0x",hash_select);
   7287                       for (loop = BITS2BYTES(key_nbits); loop > 0; loop--) {
   7288                           cli_out("%02x", key[loop - 1]);
   7289                       }
   7290                       cli_out(" ");
   7291                       cli_out("is bucket 0x%3x (%d)\n", hash_bucket,
   7292                               hash_bucket);
   7293                   }
   7294               }
   7295 #endif /* BCM_FIREBOLT_SUPPORT */
   7296               break;
   7297 
   7298               /* l3 l3table sanity */
   7299           case L3_SANITY:
   7300               cli_out("Command only valid for XGS2 switches\n");
   7301               return CMD_FAIL;
   7302           case L3_CONFLICT:
   7303             return _l3_cmd_l3_conflict_show(unit, a);
   7304 #endif /* BCM_XGS_SWITCH_SUPPORT*/
   7305           default:
   7306               return CMD_USAGE;
   7307               break;
   7308         }
   7309 
   7310         return CMD_OK;
   7311     }
   7312 
   7313     if (sal_strcasecmp(table, "defip") == 0) {
   7314 	switch (subcmd) {
   7315         /* l3 defip add */
   7316 	case L3_ADD:
   7317         return _l3_cmd_route_add(unit, a, FALSE); 
   7318         /* l3 defip destroy */
   7319 	case L3_DESTROY:
   7320 	    parse_table_init(unit, &pt);
   7321 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7322 	    parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   7323 #endif
   7324 	    parse_table_add(&pt, "IP", PQ_DFL | PQ_IP, 0, (void *)&ip_addr, 0);
   7325 	    parse_table_add(&pt, "MaSk", PQ_DFL | PQ_IP, 0, (void *)&mask, 0);
   7326 #ifdef BCM_XGS_SWITCH_SUPPORT
   7327 	    parse_table_add(&pt, "ECMP", PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0);
   7328 	    parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0);
   7329 	    parse_table_add(&pt, "Gateway", PQ_DFL | PQ_IP, 0, (void *)&gateway, 0);
   7330 	    parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   7331 	    parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void*)&module, 0);
   7332 	    parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   7333 	    parse_table_add(&pt, "VLAN", PQ_DFL | PQ_INT, 0, (void *)&id, 0);
   7334 #endif
   7335 	    if (!parseEndOk(a, &pt, &retCode)) {
   7336 	        return retCode;
   7337 	    }
   7338 
   7339             bcm_l3_route_t_init(&route_info);
   7340 
   7341 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7342 	    route_info.l3a_vrf     = vrf;
   7343 #endif
   7344 	    route_info.l3a_subnet = ip_addr;
   7345 	    route_info.l3a_ip_mask = mask;
   7346 	    route_info.l3a_vid = id; 
   7347 	    if (((mask & 0x80000000) == 0) && ip_addr != 0) {
   7348 	        cli_out("%s: Invalid mask\n", ARG_CMD(a));
   7349 	        return CMD_FAIL;
   7350 	    }
   7351 #ifdef BCM_XGS_SWITCH_SUPPORT
   7352 
   7353 	    if (ecmp) {
   7354 	        route_info.l3a_flags     |= BCM_L3_MULTIPATH;
   7355 	        sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac));
   7356 	        route_info.l3a_nexthop_ip = gateway;
   7357 	        route_info.l3a_intf       = interface;
   7358 	        route_info.l3a_modid      = module;
   7359 	        route_info.l3a_port_tgid  = port;
   7360 	    }
   7361 #endif
   7362 
   7363         if ((r = bcm_l3_route_delete(unit, &route_info)) < 0) {
   7364             format_ipaddr(ip_str, ip_addr);
   7365             cli_out("%s: Error deleting %d.%d.%d.%d from DEF IP "
   7366                     "table: %s\n", ARG_CMD(a),
   7367                     (route_info.l3a_subnet >> 24) & 0xff,
   7368                     (route_info.l3a_subnet >> 16) & 0xff,
   7369                     (route_info.l3a_subnet >> 8) & 0xff,
   7370                     route_info.l3a_subnet & 0xff,
   7371                     bcm_errmsg(r));
   7372             return CMD_FAIL;
   7373         }
   7374 	    break;
   7375 
   7376         /* l3 defip clear */
   7377 	case L3_CLEAR:
   7378 	    bcm_l3_route_delete_all(unit, NULL);
   7379 	    break;
   7380 
   7381         /* l3 defip age */
   7382 	case L3_AGE:
   7383 	    bcm_l3_route_age(unit, 0, _l3_cmd_route_age_callback, NULL);
   7384 	    return CMD_OK;
   7385 
   7386         /* l3 defip show */
   7387         case L3_SHOW:
   7388             if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   7389                 cli_out("%s: Error L3 accessing: %s\n",
   7390                         ARG_CMD(a), bcm_errmsg(r));
   7391                 return CMD_FAIL;
   7392             }
   7393             free_defip = l3_hw_status.l3info_max_route -
   7394                          l3_hw_status.l3info_occupied_route;
   7395 #if defined(BCM_XGS_SWITCH12_SUPPORT)
   7396             free_lpm_blk = l3_hw_status.l3info_max_lpm_block -
   7397                            l3_hw_status.l3info_used_lpm_block;
   7398 #endif
   7399             last_entry = l3_hw_status.l3info_max_route;
   7400             num_entries = last_entry;
   7401     
   7402             if (ARG_CNT(a)) {
   7403                 if (!isint(ARG_CUR(a))) {
   7404                     cli_out("%s: Invalid entry number: %s\n", ARG_CMD(a),
   7405                             ARG_CUR(a));
   7406                     return (CMD_FAIL);
   7407                 }
   7408                 first_entry = parse_integer(ARG_GET(a));
   7409                 if (first_entry > last_entry) {
   7410                     cli_out("%s: Error: Illegal entry number (0 to %d)\n",
   7411                             ARG_CMD(a), last_entry);
   7412                     return (CMD_FAIL);
   7413                 }
   7414                 if (ARG_CNT(a)) {
   7415                     int tmp_last_entry = 0;
   7416                     if (!isint(ARG_CUR(a))) {
   7417                         cli_out("%s: Invalid count: %s\n", ARG_CMD(a),
   7418                                 ARG_CUR(a));
   7419                         return (CMD_FAIL);
   7420                     }
   7421                     tmp_last_entry =
   7422                         parse_integer(ARG_GET(a)) + first_entry - 1;
   7423                     if ((tmp_last_entry > last_entry) ||
   7424                         (tmp_last_entry < first_entry)) {
   7425                         cli_out("%s: Error: Illegal entry count (1 to %d)\n",
   7426                                 ARG_CMD(a), last_entry - first_entry + 1);
   7427                         return (CMD_FAIL);
   7428                     }
   7429                     last_entry = tmp_last_entry;
   7430                 } else {
   7431                     last_entry = first_entry;
   7432                 }
   7433             } else {
   7434                 first_entry = 0;
   7435             }
   7436 
   7437             cli_out("Unit %d, Total Number of DEFIP entries: %d\n",
   7438                     unit, num_entries);
   7439             cli_out("#     VRF     Net addr             Next Hop Mac      "
   7440                     "  INTF MODID PORT PRIO CLASS HIT VLAN\n");
   7441             bcm_l3_route_traverse(unit, 0, first_entry, last_entry,
   7442                                       _l3_cmd_route_print, NULL);
   7443             return CMD_OK;
   7444 
   7445 #ifdef BCM_XGS_SWITCH_SUPPORT
   7446         /* l3 defip ecmp <MAX>=<val> */
   7447         case L3_ECMP:
   7448             parse_table_init(unit, &pt);
   7449             parse_table_add(&pt, "MAX", PQ_DFL | PQ_INT, 0, (void *)&max_ecmp, 0);
   7450             if (!parseEndOk(a, &pt, &retCode)) {
   7451                 return retCode;
   7452             }
   7453 
   7454             bcm_l3_route_max_ecmp_set(unit, max_ecmp);
   7455             break;
   7456 
   7457         /* l3 defip ecmphash */
   7458         case L3_ECMP_HASH:
   7459             return _l3_cmd_defip_ecmp_hash(unit, a);
   7460 #endif /* BCM_XGS_SWITCH_SUPPORT */
   7461 #ifdef FB_LPM_DEBUG
   7462         /* l3 defip state check */
   7463         case L3_SANITY:
   7464             if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
   7465                 if ((r = lpm128_state_verify(unit)) < 0) {
   7466                     return (CMD_FAIL);
   7467                 }
   7468                 cli_out("Successful: Unit %d, Checking lpm states passed!\n",
   7469                         unit);
   7470             } else {
   7471                 cli_out("Error: Command only valid for LPM scaling mode\n");
   7472             }
   7473         break;
   7474 #endif /* FB_LPM_DEBUG */
   7475 	default:
   7476 	    return CMD_USAGE;
   7477 	    break;
   7478 	}
   7479 
   7480 	return CMD_OK;
   7481     }
   7482 
   7483 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7484 
   7485 #ifdef ALPM_ENABLE   
   7486     if (sal_strcasecmp(table, "alpm") == 0) {
   7487         if (SOC_IS_TD2_TT2(unit) &&
   7488             soc_feature(unit, soc_feature_alpm) &&
   7489             soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) {
   7490             switch (subcmd) {
   7491             case L3_SHOW:
   7492                 return _l3_cmd_alpm_debug_show(unit, a);
   7493             case L3_FIND:
   7494                 return _l3_cmd_alpm_find(unit, a);
   7495             case L3_SANITY:
   7496                 return _l3_cmd_alpm_sanity_check(unit, a);
   7497             default:
   7498                return CMD_USAGE;
   7499             }
   7500             return CMD_OK;
   7501             
   7502         } else {
   7503             cli_out("ALPM is unsupported or disabled!\n" );
   7504             ARG_DISCARD(a);
   7505             return CMD_OK; 
   7506         } 
   7507     }
   7508 #endif
   7509 
   7510     if (sal_strcasecmp(table, "ip6host") == 0) {
   7511 	switch (subcmd) {
   7512         /* l3 ip6host add */
   7513 	case L3_ADD:
   7514         return _l3_cmd_host_add(unit, a, TRUE);
   7515         /* l3 ip6host delete */
   7516 	case L3_DESTROY:
   7517 	    parse_table_init(unit, &pt);
   7518 	    parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   7519 	    parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   7520 	    if (!parseEndOk(a, &pt, &retCode)) {
   7521 		return retCode;
   7522             }
   7523 
   7524             sal_memcpy(ip_info.l3a_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
   7525             ip_info.l3a_vrf     = vrf;
   7526             ip_info.l3a_flags   = BCM_L3_IP6;
   7527 	    if ((r = bcm_l3_host_delete(unit, &ip_info)) < 0) {
   7528 		cli_out("%s: Error deleting from L3 table %s\n",
   7529                         ARG_CMD(a), bcm_errmsg(r));
   7530 		return CMD_FAIL;
   7531 	    }
   7532 	    break;
   7533 
   7534         /* l3 ip6host clear */
   7535 	case L3_CLEAR:
   7536             ip_info.l3a_flags   = BCM_L3_IP6;
   7537 	    bcm_l3_host_delete_all(unit, &ip_info);
   7538 	    break;
   7539 
   7540         /* l3 ip6host age */
   7541 	case L3_AGE:
   7542 	    bcm_l3_host_age(unit, BCM_L3_HIT | BCM_L3_IP6,
   7543                             _l3_cmd_host_age_callback, NULL);
   7544 	    return CMD_OK;
   7545 
   7546         /* l3 ip6host show */
   7547 	case L3_SHOW:
   7548             if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   7549                 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r));
   7550                 return CMD_FAIL;
   7551             }
   7552             free_l3 = (l3_hw_status.l3info_max_host -
   7553                        l3_hw_status.l3info_occupied_host) / 2;
   7554             last_entry = l3_hw_status.l3info_max_host / 2;
   7555             if (ARG_CNT(a)) {
   7556                 if (!isint(ARG_CUR(a))) {
   7557                     cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   7558                     return (CMD_FAIL);
   7559                 }
   7560                 first_entry = parse_integer(ARG_GET(a));
   7561                 if (first_entry > last_entry) {
   7562                     cli_out("%s: Error: Illegal entry number (0 to %d)\n",
   7563                             ARG_CMD(a), last_entry);
   7564                     return (CMD_FAIL);
   7565                 }
   7566                 last_entry = first_entry;
   7567 	    } else {
   7568                 first_entry = 0;
   7569             }
   7570 
   7571             cli_out("Unit %d, free IPv6 table entries: %d\n", unit, free_l3);
   7572             cli_out("Entry VRF IP address                         "
   7573                     "          Mac Address        INTF MOD PORT     CLASS HIT"
   7574                     "     H/W Index\n");
   7575             user_data = soc_cm_salloc(unit, sizeof(int), "l3host hw index");
   7576             if (NULL == user_data) {
   7577                 cli_out("Failed to allocate memory\n");
   7578                 return CMD_FAIL;
   7579             }
   7580             bcm_l3_host_traverse(unit, BCM_L3_IP6 | _BCM_L3_SHOW_INDEX,
   7581                                  first_entry, last_entry,
   7582                                  _l3_cmd_host_print, user_data);
   7583             cli_out("\n");
   7584             if (user_data) {
   7585                 soc_cm_sfree(unit, user_data);
   7586             }
   7587 	    return CMD_OK;
   7588         default:
   7589             return CMD_USAGE;
   7590             break;
   7591         }
   7592         return CMD_OK;
   7593     }
   7594 
   7595     if (sal_strcasecmp(table, "ip6route") == 0) {
   7596         bcm_ip6_t ip6_mask;
   7597         int masklen = -1;
   7598         int mask_len_max = 
   7599             soc_feature(unit, soc_feature_lpm_prefix_length_max_128) ? 128 : 64;
   7600 
   7601 	switch (subcmd) {
   7602         /* l3 ip6route add */
   7603 	case L3_ADD:
   7604         return _l3_cmd_route_add(unit, a, TRUE); 
   7605         
   7606         /* l3 ip6route delete */
   7607 	case L3_DESTROY:
   7608 	    parse_table_init(unit, &pt);
   7609 	    parse_table_add(&pt, "VRF", PQ_DFL | PQ_INT, 0, (void *)&vrf, 0);
   7610 	    parse_table_add(&pt, "IP", PQ_DFL | PQ_IP6, 0, (void *)&ip6_addr, 0);
   7611 	    parse_table_add(&pt, "MaskLen", PQ_DFL | PQ_INT, 0,
   7612                             (void *)&masklen, 0);
   7613             parse_table_add(&pt, "ECMP", PQ_DFL | PQ_BOOL, 0, (void *)&ecmp, 0);
   7614             parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, (void *)mac, 0);
   7615             parse_table_add(&pt, "Port", PQ_DFL | PQ_PORT, 0, (void *)&port, 0);
   7616             parse_table_add(&pt, "MOdule", PQ_DFL | PQ_INT, 0, (void*)&module, 0);
   7617             parse_table_add(&pt, "INtf", PQ_DFL | PQ_INT, 0, (void *)&interface, 0);
   7618             if (!parseEndOk(a, &pt, &retCode)) {
   7619                 return retCode;
   7620             }
   7621 
   7622         if ((masklen < 0) || (masklen > mask_len_max)) {
   7623             cli_out("%s: Invalid prefix length.\n", ARG_CMD(a));
   7624             return CMD_FAIL;
   7625         }
   7626             bcm_l3_route_t_init(&route_info);
   7627 
   7628         route_info.l3a_vrf = vrf;
   7629 	    sal_memcpy(route_info.l3a_ip6_net, ip6_addr, BCM_IP6_ADDRLEN);
   7630             bcm_ip6_mask_create(ip6_mask, masklen);
   7631             sal_memcpy(route_info.l3a_ip6_mask, ip6_mask, BCM_IP6_ADDRLEN);
   7632 	    sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac));
   7633             route_info.l3a_flags = BCM_L3_IP6;
   7634             if (ecmp) {
   7635                 route_info.l3a_flags     |= BCM_L3_MULTIPATH;
   7636                 sal_memcpy(route_info.l3a_nexthop_mac, mac, sizeof(mac));
   7637                 route_info.l3a_intf       = interface;
   7638                 route_info.l3a_modid      = module;
   7639                 route_info.l3a_port_tgid  = port;
   7640             }
   7641 
   7642             if ((r = bcm_l3_route_delete(unit, &route_info)) < 0) {
   7643                 format_ip6addr(ip_str, ip6_addr);
   7644                 cli_out("ERROR %s: delete %s/%d from DEF IP "
   7645                         "table: %s\n", ARG_CMD(a), ip_str, masklen, bcm_errmsg(r));
   7646                 return CMD_FAIL;
   7647             }
   7648             break;
   7649 
   7650         /* l3 ip6route clear */
   7651 	case L3_CLEAR:
   7652             route_info.l3a_flags   = BCM_L3_IP6;
   7653 	    bcm_l3_route_delete_all(unit, &route_info);
   7654 	    break;
   7655 
   7656         /* l3 defip age */
   7657 	case L3_AGE:
   7658 	    bcm_l3_route_age(unit, BCM_L3_IP6, _l3_cmd_route_age_callback, NULL);
   7659 	    break;
   7660 
   7661         /* l3 ip6route show */
   7662     case L3_SHOW:
   7663 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7664 #ifdef BCM_TRX_SUPPORT
   7665         ext_tcam_flag = EXT_TCAM_IS_L3_ENABLED(unit);
   7666 #endif
   7667         if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) &&
   7668             soc_feature(unit, soc_feature_l3_shared_defip_table) &&
   7669             !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) &&
   7670               soc_feature(unit, soc_feature_alpm)) &&
   7671             !ext_tcam_flag) {
   7672             if ((r = bcm_switch_object_count_get(unit,
   7673                      bcmSwitchObjectL3RouteV6Routes64bMax,
   7674                      &defip_64_max)) < 0) {
   7675                 cli_out("%s: Error getting max number of 64bv6: %s\n",
   7676                         ARG_CMD(a), bcm_errmsg(r));
   7677                 return CMD_FAIL;         
   7678             }
   7679             if ((r = bcm_switch_object_count_get(unit, 
   7680                      bcmSwitchObjectL3RouteV6Routes128bMax, 
   7681                      &defip_128_max)) < 0) {
   7682                 cli_out("%s: Error getting max number of 128bv6: %s\n", 
   7683                         ARG_CMD(a), bcm_errmsg(r));
   7684                 return CMD_FAIL;         
   7685             }
   7686             num_entries = defip_64_max + defip_128_max;
   7687             last_entry = num_entries - 1 ;
   7688             if ((r = bcm_switch_object_count_get(unit, 
   7689                      bcmSwitchObjectL3RouteV6Routes64bFree, 
   7690                      &defip_64_free)) < 0) {
   7691                 cli_out("%s: Error getting free number of 64bv6: %s\n", 
   7692                         ARG_CMD(a), bcm_errmsg(r));
   7693                 return CMD_FAIL;         
   7694             }
   7695             if ((r = bcm_switch_object_count_get(unit, 
   7696                      bcmSwitchObjectL3RouteV6Routes128bFree, 
   7697                      &defip_128_free)) < 0) {
   7698                 cli_out("%s: Error getting free number of 128bv6: %s\n", 
   7699                         ARG_CMD(a), bcm_errmsg(r));
   7700                 return CMD_FAIL;         
   7701             }
   7702             free_defip = defip_64_free + defip_128_free;  
   7703         } else
   7704 #endif
   7705         {
   7706             if ((r = bcm_l3_info(unit, &l3_hw_status)) < 0) {
   7707                 cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r));
   7708                 return CMD_FAIL;
   7709             }
   7710             if (soc_feature(unit, soc_feature_urpf)) {
   7711                 if ((r = bcm_switch_control_get(unit,
   7712                           bcmSwitchL3UrpfRouteEnable, &urpf)) < 0) {
   7713                     cli_out("%s: Error L3 accessing: %s\n", ARG_CMD(a), bcm_errmsg(r));
   7714                     return CMD_FAIL;
   7715                 }
   7716             }
   7717             free_defip = (l3_hw_status.l3info_max_route -
   7718                           l3_hw_status.l3info_occupied_route) / 2;
   7719             last_entry = l3_hw_status.l3info_max_route / 2;
   7720             num_entries = last_entry;
   7721             if (urpf) {
   7722                 free_defip = (l3_hw_status.l3info_max_route -
   7723                               (l3_hw_status.l3info_occupied_route * 2)) / 4;
   7724                 last_entry = last_entry / 2;
   7725                 num_entries = last_entry + 1;
   7726             }
   7727 
   7728         }
   7729         if (ARG_CNT(a)) {
   7730             if (!isint(ARG_CUR(a))) {
   7731                 cli_out("%s: Invalid number: %s\n", ARG_CMD(a), ARG_CUR(a));
   7732                 return (CMD_FAIL);
   7733             }
   7734             first_entry = parse_integer(ARG_GET(a));
   7735             if (first_entry > last_entry) {
   7736                 cli_out("%s: Error: Illegal entry number (0 to %d)\n",
   7737                         ARG_CMD(a), last_entry);
   7738                 return (CMD_FAIL);
   7739             }
   7740             if (ARG_CNT(a)) {
   7741                 int tmp_last_entry = 0;
   7742                 if (!isint(ARG_CUR(a))) {
   7743                     cli_out("%s: Invalid count: %s\n", ARG_CMD(a), ARG_CUR(a));
   7744                     return (CMD_FAIL);
   7745                 }
   7746                 tmp_last_entry = parse_integer(ARG_GET(a)) + first_entry - 1;
   7747                 if ((tmp_last_entry > last_entry) ||
   7748                     (tmp_last_entry < first_entry)) {
   7749                     cli_out("%s: Error: Illegal entry count (1 to %d)\n",
   7750                             ARG_CMD(a), last_entry - first_entry + 1);
   7751                     return (CMD_FAIL);
   7752                 }
   7753                 last_entry = tmp_last_entry;
   7754             } else {
   7755                 last_entry = first_entry;
   7756             }
   7757         } else {
   7758             first_entry = 0;
   7759         }
   7760 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7761         if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) &&
   7762             soc_feature(unit, soc_feature_l3_shared_defip_table) &&
   7763             !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) &&
   7764               soc_feature(unit, soc_feature_alpm))) {
   7765             cli_out("Unit %d, Total Number of IPv6 entries: %d "
   7766                     "(IPv6/64 %d, IPv6/128 %d)\n", unit, num_entries,
   7767                     defip_64_max, defip_128_max);
   7768         } else 
   7769 #endif
   7770         cli_out("Unit %d, Total Number of IPv6 entries: %d\n",
   7771                 unit, num_entries);
   7772         bcm_l3_route_max_ecmp_get(unit, &max_ecmp);
   7773         if (max_ecmp) {
   7774             cli_out("Max number of ECMP paths %d\n", max_ecmp);
   7775         }
   7776 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7777         if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIUMPH3(unit)) &&
   7778             soc_feature(unit, soc_feature_l3_shared_defip_table) &&
   7779             !(soc_property_get(unit, spn_L3_ALPM_ENABLE, 0) &&
   7780               soc_feature(unit, soc_feature_alpm))) {
   7781             cli_out("Free IPv6 entries available: %d "
   7782                     "(IPv6/64 %d, IPv6/128 %d)\n", free_defip,
   7783                     defip_64_free, defip_128_free);
   7784         } else 
   7785 #endif
   7786         cli_out("Free IPv6 entries available: %d\n", free_defip);
   7787 
   7788         cli_out("#     VRF     Net addr                                "
   7789                 "     Next Hop Mac      "
   7790                 "  INTF MODID PORT PRIO CLASS HIT VLAN\n");
   7791         bcm_l3_route_traverse(unit, BCM_L3_IP6, first_entry, last_entry,
   7792                               _l3_cmd_route_print, NULL);
   7793         return CMD_OK;
   7794 
   7795         default:
   7796             return CMD_USAGE;
   7797             break;
   7798         }
   7799         return CMD_OK;
   7800     }
   7801 
   7802     if (sal_strcasecmp(table, "tunnel_init") == 0) {
   7803         switch (subcmd) {
   7804 
   7805         /* l3 tunnel_init set */
   7806         case L3_SET:
   7807             return _l3_cmd_tunnel_init_add(unit, a);
   7808         /* l3 tunnel_init show */
   7809         case L3_SHOW:
   7810             return _l3_cmd_tunnel_init_show(unit, a);
   7811         /* l3 tunnel_init clear */
   7812         case L3_CLEAR:
   7813             return _l3_cmd_tunnel_init_clear(unit, a);
   7814         default:
   7815             return CMD_USAGE;
   7816             break;
   7817         }
   7818         return CMD_OK;
   7819     }
   7820 
   7821     if (sal_strcasecmp(table, "tunnel_term") == 0) {
   7822         switch (subcmd) {
   7823         /* l3 tunnel_term add */
   7824         case L3_ADD:
   7825             return _l3_cmd_tunnel_term_add(unit, a); 
   7826         /* l3 tunnel_term delete */
   7827         case L3_DESTROY:
   7828             return _l3_cmd_tunnel_term_delete(unit, a); 
   7829         /* l3 tunnel_term show */
   7830         case L3_SHOW:
   7831             return _l3_cmd_tunnel_term_get(unit, a); 
   7832         default:
   7833             return CMD_USAGE;
   7834             break;
   7835         }
   7836         return CMD_OK;
   7837     }
   7838 
   7839     if (sal_strcasecmp(table, "dscp_map_port") == 0) {
   7840         switch (subcmd) {
   7841             /* l3 dscp_map_port show */
   7842           case L3_SHOW:
   7843               return _l3_cmd_dscp_map_port_show(unit, a); 
   7844               /* l3 dscp_map_port set */
   7845           case L3_ADD:
   7846           case L3_SET:
   7847               return _l3_cmd_dscp_map_port_set(unit, a); 
   7848           default:
   7849               return (CMD_USAGE);
   7850         }
   7851         return CMD_OK;
   7852     }
   7853     if (sal_strcasecmp(table, "dscp_map") == 0) {
   7854         switch (subcmd) {
   7855             /* l3 dscp_map add */
   7856           case L3_ADD:
   7857               return _l3_cmd_dscp_map_add(unit, a); 
   7858               /* l3 dscp_map destroy */
   7859           case L3_DESTROY:
   7860               return _l3_cmd_dscp_map_delete(unit, a); 
   7861 
   7862               /* l3 dscp_map show */
   7863           case L3_SHOW:
   7864               return _l3_cmd_dscp_map_show(unit, a); 
   7865               /* l3 dscp_map set */
   7866           case L3_SET:
   7867               return _l3_cmd_dscp_map_set(unit, a); 
   7868 
   7869           default:
   7870               return CMD_USAGE;
   7871         }
   7872         return CMD_OK;
   7873     }
   7874     if (soc_feature(unit, soc_feature_nat)) {
   7875         if (sal_strcasecmp(table, "nat_ingress") == 0) {
   7876             switch (subcmd) {
   7877                 /* l3 nat_ingress show */
   7878             case L3_SHOW:
   7879                 return _l3_cmd_nat_ingress_show(unit, a);
   7880             default:
   7881                 return CMD_USAGE;
   7882             }
   7883             return CMD_OK;
   7884         }
   7885         if (sal_strcasecmp(table, "nat_egress") == 0) {
   7886             switch (subcmd) {
   7887                 /* l3 nat_egress show */
   7888             case L3_SHOW:
   7889                 return _l3_cmd_nat_egress_show(unit, a);
   7890             case L3_ADD:
   7891                 return _l3_cmd_nat_egress_add(unit, a);
   7892             default:
   7893                 return CMD_USAGE;
   7894             }
   7895             return CMD_OK;
   7896         }
   7897     }
   7898 
   7899     if (sal_strcasecmp(table, "route") == 0) {
   7900         char *subcmd2;
   7901         switch (subcmd) {
   7902             /* l3 route test */
   7903             case L3_TEST:
   7904                 subcmd2 = ARG_GET(a);
   7905                 if ((subcmd2 != NULL) && sal_strcasecmp(subcmd2, "perf") == 0) {
   7906                     return _l3_cmd_route_perf_test(unit, a);
   7907                 } else {
   7908                     return CMD_USAGE;
   7909                 }
   7910             default:
   7911                 return CMD_USAGE;
   7912         }
   7913         return CMD_OK;
   7914     }
   7915 
   7916 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7917 
   7918     return CMD_USAGE;
   7919 }
   7920 #endif /* INCLUDE_L3 */