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

mirror.c (32362B)


      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  * Mirror CLI commands
      8  */
      9 
     10 #include <appl/diag/system.h>
     11 #include <appl/diag/parse.h>
     12 #include <appl/diag/dport.h>
     13 #include <shared/bsl.h>
     14 #include <bcm/error.h>
     15 #include <bcm/mirror.h>
     16 #include <bcm/stack.h>
     17 #include <bcm/debug.h>
     18 #include <bcm_int/control.h>
     19 #include <bcm_int/esw/mirror.h>
     20 
     21 #ifdef BCM_TRIUMPH2_SUPPORT
     22 #include <bcm_int/esw/triumph2.h>
     23 #ifdef BCM_TRIDENT_SUPPORT
     24 #include <bcm_int/esw/trident.h>
     25 #endif
     26 #ifdef BCM_TRIUMPH3_SUPPORT
     27 #include <bcm_int/esw/triumph3.h>
     28 #endif
     29 #ifdef BCM_TRIUMPH_SUPPORT
     30 #include <bcm_int/esw/triumph.h>
     31 #endif
     32 #ifdef BCM_MPLS_SUPPORT
     33 #include <bcm_int/esw/mpls.h>
     34 #endif
     35 #endif
     36 
     37 
     38 static int
     39 show_mirror_destination_cb(int unit, bcm_mirror_destination_t * mirror_dest,
     40                            void *user_data)
     41 {
     42     int        *count = (int *) user_data;
     43 
     44     (*count)++;
     45     cli_out("Mirror Dest %2d: ", *count);
     46     cli_out("Mirror ID: %2d; ", BCM_GPORT_MIRROR_GET(mirror_dest->mirror_dest_id));
     47     if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_L2) {
     48         cli_out("%s ", "L2 Tunnel to");
     49     }
     50     if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_IP_GRE) {
     51         cli_out("IPv%d GRE Tunnel\n", mirror_dest->version);
     52 
     53         if (4 == mirror_dest->version) {
     54             char        buffer[SAL_IPADDR_STR_LEN];
     55 
     56             format_ipaddr(buffer, mirror_dest->src_addr);
     57             cli_out("\tSrc IP=%s\n", buffer);
     58             format_ipaddr(buffer, mirror_dest->dst_addr);
     59             cli_out("\tDst IP=%s\n", buffer);
     60         } else if (6 == mirror_dest->version) {
     61             char        buffer[IP6ADDR_STR_LEN];
     62 
     63             format_ip6addr(buffer, mirror_dest->src6_addr);
     64             cli_out("\tSrc IP=%s\n", buffer);
     65             format_ip6addr(buffer, mirror_dest->dst6_addr);
     66             cli_out("\tDst IP=%s\n", buffer);
     67             cli_out("\tFlow Label=0x%04x\n", mirror_dest->flow_label);
     68         }
     69         cli_out("\tsrc_mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
     70                 mirror_dest->src_mac[0], mirror_dest->src_mac[1],
     71                 mirror_dest->src_mac[2], mirror_dest->src_mac[3],
     72                 mirror_dest->src_mac[4], mirror_dest->src_mac[5]);
     73         cli_out("\tdst_mac=%02x:%02x:%02x:%02x:%02x:%02x\n", mirror_dest->dst_mac[0],
     74                 mirror_dest->dst_mac[1], mirror_dest->dst_mac[2],
     75                 mirror_dest->dst_mac[3], mirror_dest->dst_mac[4],
     76                 mirror_dest->dst_mac[5]);
     77 
     78         cli_out("\tvlan_id=0x%04x\n", mirror_dest->vlan_id);
     79         cli_out("\ttpid=0x%04x\n", mirror_dest->tpid);
     80         cli_out("\tttl=%d\n", mirror_dest->ttl);
     81         cli_out("\ttos=%d\n", mirror_dest->tos);
     82 	cli_out("\tmirrored to ");
     83     }
     84     if (mirror_dest->flags & BCM_MIRROR_DEST_PAYLOAD_UNTAGGED) {
     85         cli_out("%s ", "Payload Untagged");
     86     }
     87     if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_TRILL) {
     88         cli_out("%s ", "Trill Tunnel to");
     89     }
     90     if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_NIV) {
     91         cli_out("%s ", "NIV Tunnel to");
     92     }
     93     if (mirror_dest->flags & BCM_MIRROR_DEST_TUNNEL_ETAG) {
     94         cli_out("%s ", "ETAG Tunnel to");
     95     }
     96 
     97     if (BCM_GPORT_IS_LOCAL(mirror_dest->gport)) {
     98         cli_out("local port %s",
     99                 BCM_PORT_NAME(unit, BCM_GPORT_LOCAL_GET(mirror_dest->gport)));
    100     } else if (BCM_GPORT_IS_MODPORT(mirror_dest->gport)) {
    101         bcm_port_t  local_port;
    102 
    103         if (bcm_port_local_get(unit, mirror_dest->gport, &local_port) != BCM_E_NONE) {
    104             cli_out("modport %d/%d", BCM_GPORT_MODPORT_MODID_GET(mirror_dest->gport),
    105                     BCM_GPORT_MODPORT_PORT_GET(mirror_dest->gport));
    106         } else {
    107             cli_out("local port %s", BCM_PORT_NAME(unit, local_port));
    108         }
    109     } else if (BCM_GPORT_IS_TRUNK(mirror_dest->gport)) {
    110         cli_out("trunk group %d", BCM_GPORT_TRUNK_GET(mirror_dest->gport));
    111     } else {
    112         cli_out("GPORT 0x%08X", mirror_dest->gport);
    113     }
    114     cli_out("\n");
    115     return BCM_E_NONE;
    116 }
    117 
    118 cmd_result_t
    119 _if_esw_mirror_dest(int unit, args_t *a)
    120 {
    121     parse_table_t               pt;
    122     cmd_result_t                retCode;
    123     bcm_gport_t                 mirror_dest_id = 0;
    124     bcm_port_t                  src_port = 0, dest_port = 0;
    125     bcm_ip_t                    src_ip = 0, dest_ip = 0;
    126     bcm_ip6_t                   src_ip6,dest_ip6;
    127     uint32                      flow_lable;
    128     uint32                      mirror_port_flags = 0;
    129     bcm_mac_t                   src_mac, dest_mac;
    130     bcm_vlan_t                  vid = BCM_VLAN_INVALID;
    131     uint16                      tpid;
    132     int                         vlan_id = -1, tag_id = -1;
    133     int                         ttl = 0,tos = 0, version = 0;
    134     int                         rv, mode = 0, tunnel = 0, strip_vlan = 0;
    135     bcm_mirror_destination_t    mirror_dest;
    136     char                        *cmd = NULL;
    137     char *modeList[] = {"OFF", "Ingress", "Egress", "EgressTrue", "IngressEgress", NULL};
    138     char *tunnelList[] = {"OFF","L2", "GRE", NULL};
    139 
    140     if ((cmd = ARG_GET(a)) == NULL) {
    141         return CMD_USAGE;
    142     }
    143     if (0 == sal_strcasecmp("show", cmd)) {
    144         int         md_count = 0;
    145 
    146         rv = bcm_mirror_destination_traverse(unit, show_mirror_destination_cb,
    147                                              &md_count);
    148         if (BCM_FAILURE(rv)) {
    149             cli_out("%s bcm_mirror_destination_traverse() failed  %s\n",
    150                     ARG_CMD(a), bcm_errmsg(rv));
    151             return CMD_FAIL;
    152         }
    153 	if (md_count == 0) {
    154 	    cli_out("No mirror destinations currently defined\n");
    155 	}
    156         return CMD_OK;
    157     }
    158 
    159     sal_memset(src_ip6, 0, sizeof(bcm_ip6_t));
    160     sal_memset(dest_ip6, 0, sizeof(bcm_ip6_t));
    161     sal_memset(src_mac, 0, sizeof(bcm_mac_t));
    162     sal_memset(dest_mac, 0, sizeof(bcm_mac_t));
    163     
    164     parse_table_init(unit, &pt);
    165     
    166     parse_table_add(&pt, "Id", PQ_DFL | PQ_INT,0, &mirror_dest_id, NULL);
    167     parse_table_add(&pt, "Mode", PQ_DFL | PQ_MULTI,(void *)(0), &mode, modeList);
    168     parse_table_add(&pt, "Tunnel", PQ_DFL | PQ_MULTI,(void *)(0), &tunnel, tunnelList);
    169     parse_table_add(&pt, "SrcPort", PQ_DFL | PQ_PORT, 0, &src_port, NULL);
    170     parse_table_add(&pt, "DestPort", PQ_DFL | PQ_PORT, 0, &dest_port, NULL);
    171     parse_table_add(&pt, "SrcIP", PQ_DFL | PQ_IP, 0, (void *)&src_ip, NULL);
    172     parse_table_add(&pt, "DestIP", PQ_DFL | PQ_IP, 0, (void *)&dest_ip, NULL);
    173     parse_table_add(&pt, "SrcIP6", PQ_DFL | PQ_IP6, 0, (void *)&src_ip6, NULL);
    174     parse_table_add(&pt, "DestIP6", PQ_DFL | PQ_IP6, 0, (void *)&dest_ip6, NULL);
    175     parse_table_add(&pt, "SrcMAC", PQ_DFL|PQ_MAC, 0, (void *)src_mac, NULL);
    176     parse_table_add(&pt, "DestMAC", PQ_DFL|PQ_MAC, 0, (void *)dest_mac, NULL);
    177     parse_table_add(&pt, "VLAN", PQ_DFL|PQ_INT, 0, (void *)&vlan_id, NULL);
    178     parse_table_add(&pt, "tpid", PQ_DFL|PQ_INT, 0, (void *)&tag_id, NULL);
    179     parse_table_add(&pt, "Version",  PQ_DFL|PQ_INT, 0, (void*)&version, NULL);
    180     parse_table_add(&pt, "TTL",  PQ_DFL|PQ_INT, 0, (void*)&ttl, NULL);
    181     parse_table_add(&pt, "TOS",  PQ_DFL|PQ_INT, 0, (void*)&tos, NULL);
    182     parse_table_add(&pt, "FlowLable",  PQ_DFL|PQ_INT, 0, (void*)&flow_lable, NULL);
    183     parse_table_add(&pt, "NoVLAN",  PQ_DFL|PQ_BOOL, 0, (void*)&strip_vlan, NULL);
    184 
    185     if (!parseEndOk( a, &pt, &retCode)) {
    186 	return retCode;
    187     }
    188 
    189     vid = (bcm_vlan_t) (vlan_id & 0xffff);
    190     tpid = (uint16) (tag_id & 0xffff);
    191     bcm_mirror_destination_t_init(&mirror_dest);
    192 
    193     switch (mode) {
    194         case 1:
    195             mirror_port_flags |= BCM_MIRROR_PORT_INGRESS;
    196             break;
    197         case 2:
    198             mirror_port_flags |= BCM_MIRROR_PORT_EGRESS;
    199             break;
    200         case 3:
    201             mirror_port_flags |= BCM_MIRROR_PORT_EGRESS_TRUE;
    202             break;
    203         case 4:
    204             mirror_port_flags |=
    205                 (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS);
    206             break;
    207        default:
    208             break;
    209     }
    210 
    211     switch (tunnel) {
    212         case 1:
    213             mirror_dest.flags |= BCM_MIRROR_DEST_TUNNEL_L2;
    214             sal_memcpy(mirror_dest.src_mac, src_mac, sizeof(src_mac));
    215             sal_memcpy(mirror_dest.dst_mac, dest_mac, sizeof(dest_mac));
    216             mirror_dest.vlan_id = vid;
    217             mirror_dest.tpid = tpid;
    218             break;
    219         case 2:
    220             mirror_dest.flags |= BCM_MIRROR_DEST_TUNNEL_IP_GRE;
    221             sal_memcpy(mirror_dest.src_mac, src_mac, sizeof(src_mac));
    222             sal_memcpy(mirror_dest.dst_mac, dest_mac, sizeof(dest_mac));
    223             mirror_dest.vlan_id = vid;
    224             mirror_dest.tpid = tpid;
    225             mirror_dest.src_addr = src_ip;
    226             mirror_dest.dst_addr = dest_ip;
    227             mirror_dest.ttl = ttl;
    228             mirror_dest.tos = tos;
    229             mirror_dest.flow_label = flow_lable;
    230             mirror_dest.version = version;
    231             sal_memcpy(mirror_dest.src6_addr, src_ip6, sizeof(src_ip6));
    232             sal_memcpy(mirror_dest.dst6_addr, dest_ip6, sizeof(dest_ip6));
    233             break;
    234         default:
    235             break;
    236     }
    237 
    238     if (strip_vlan) {
    239         mirror_dest.flags |= BCM_MIRROR_DEST_PAYLOAD_UNTAGGED;
    240     }
    241 
    242     if (!BCM_GPORT_IS_SET(dest_port)) {
    243         rv = bcm_port_gport_get(unit, dest_port, &dest_port);
    244         if (BCM_FAILURE(rv)) {
    245             cli_out("Illegal port [%d]\n", dest_port);
    246             return CMD_FAIL;
    247         }
    248     }
    249 
    250     /* Dest port can be trunk, api handles this with no flags */
    251     mirror_dest.gport = dest_port;
    252 
    253     if (mirror_dest_id != 0) {
    254         mirror_dest.flags |= BCM_MIRROR_DEST_WITH_ID;
    255         mirror_dest.mirror_dest_id = mirror_dest_id;
    256     }
    257 
    258     if (0 == sal_strcasecmp("create", cmd)) {
    259         rv = bcm_mirror_destination_create(unit, &mirror_dest);
    260         if (BCM_FAILURE(rv)) {
    261             cli_out("%s bcm_mirror_destination_create() failed  %s\n", 
    262                     ARG_CMD(a), bcm_errmsg(rv));
    263             return CMD_FAIL;
    264         }
    265         cli_out(" Mirror Id = 0x%x\n", mirror_dest.mirror_dest_id);
    266         return CMD_OK;
    267     } else if (0 == sal_strcasecmp("add", cmd)) {
    268         rv = bcm_mirror_port_dest_add(unit, src_port,
    269                                       mirror_port_flags, mirror_dest_id);
    270         if (BCM_FAILURE(rv)) {
    271             cli_out("%s bcm_mirror_port_dest_add() failed  %s\n", 
    272                     ARG_CMD(a), bcm_errmsg(rv));
    273             return CMD_FAIL;
    274         }
    275         return CMD_OK;
    276     } else if (0 == sal_strcasecmp("destroy", cmd)) {
    277         if (0 == mirror_dest_id) {
    278             cli_out("%s mirror destination id is missing\n", ARG_CMD(a));
    279             return CMD_FAIL;
    280         }
    281         rv = bcm_mirror_destination_destroy(unit, mirror_dest_id);
    282         if (BCM_FAILURE(rv)) {
    283             cli_out("%s bcm_mirror_destination_destroy failed()  %s\n", 
    284                     ARG_CMD(a), bcm_errmsg(rv));
    285             return CMD_FAIL;
    286         }
    287         return CMD_OK;
    288     } else if (0 == sal_strcasecmp("delete", cmd)) {
    289         rv = bcm_mirror_port_dest_delete(unit, src_port,
    290                                          mirror_port_flags, mirror_dest_id);
    291         if (BCM_FAILURE(rv)) {
    292             cli_out("%s bcm_mirror_port_dest_delete failed %s\n", 
    293                     ARG_CMD(a), bcm_errmsg(rv));
    294             return CMD_FAIL;
    295         }
    296         return CMD_OK;
    297     }
    298 
    299     return CMD_USAGE;
    300 }
    301 
    302 static void _dmirror_show(int unit, int port, int dstmod, int dstport, uint32 flags);
    303 static int
    304 _mirror_show(int unit)
    305 {
    306     const uint32 flags[3] = { BCM_MIRROR_PORT_INGRESS, BCM_MIRROR_PORT_EGRESS,
    307                               BCM_MIRROR_PORT_EGRESS_TRUE };
    308     bcm_gport_t mirror_dest[BCM_MIRROR_MTP_COUNT];
    309     bcm_port_config_t pcfg;
    310     int         count = 0;
    311     int         fc;
    312     int         mirror_dest_count;
    313     int         port, dport;
    314     int         rv;
    315 #if defined(INCLUDE_L3) && defined(BCM_TRIUMPH2_SUPPORT)
    316     bcm_gport_t gport = 0;
    317     int         vp = 0;
    318     int         first = TRUE;
    319 #endif
    320 
    321     if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) {
    322         cli_out("Error: bcm ports not initialized\n");
    323         return CMD_FAIL;
    324     }
    325 
    326     /* coverity[overrun-local] */
    327     DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) {
    328         for (fc = 0; fc < sizeof(flags) / sizeof(uint32); fc++) {
    329             if(flags[fc] == BCM_MIRROR_PORT_EGRESS_TRUE) {
    330                 if(!soc_feature(unit, soc_feature_egr_mirror_true))
    331                     continue;
    332             }
    333             rv =
    334               bcm_mirror_port_dest_get(unit,
    335                                        port,
    336                                        flags[fc],
    337                                        BCM_MIRROR_MTP_COUNT, mirror_dest,
    338                                        &mirror_dest_count);
    339             if (rv < 0) {
    340                 cli_out("bcm_mirror_port_dest_get() FAILED: %s\n", bcm_errmsg(rv));
    341                 return CMD_FAIL;
    342             }
    343             if (mirror_dest_count != 0) {
    344                 int         i;
    345 
    346                 for (i = 0; i < mirror_dest_count; i++) {
    347                     bcm_mirror_destination_t mirror_dest_desc;
    348 
    349                     bcm_mirror_destination_t_init(&mirror_dest_desc);
    350                     mirror_dest_desc.flags = flags[fc];
    351                     rv =
    352                       bcm_mirror_destination_get(unit, mirror_dest[i],
    353                                                  &mirror_dest_desc);
    354                     if (rv < 0) {
    355                         cli_out("bcm_mirror_destination_get() FAILED: %s\n",
    356                                 bcm_errmsg(rv));
    357                         return CMD_FAIL;
    358                     }
    359                     _dmirror_show(unit, port, 0, mirror_dest_desc.gport, flags[fc]);
    360                 }
    361                 count += mirror_dest_count;
    362             }
    363         }
    364     }
    365         
    366 #if defined(INCLUDE_L3) && defined(BCM_TRIUMPH2_SUPPORT)
    367     if (SOC_MEM_IS_VALID(unit,SOURCE_VPm)) {
    368         for (vp = soc_mem_index_min(unit, SOURCE_VPm);
    369              vp <= soc_mem_index_max(unit, SOURCE_VPm);
    370              vp++) {
    371             gport = 0;
    372             BCM_GPORT_VP_GROUP_SET(gport, vp);
    373             
    374             for (fc = 0; fc < sizeof(flags) / sizeof(uint32); fc++) {
    375                 if(flags[fc] == BCM_MIRROR_PORT_EGRESS_TRUE) {
    376                     if(!soc_feature(unit, soc_feature_egr_mirror_true))
    377                         continue;
    378                 }
    379                 rv =
    380                   bcm_mirror_port_dest_get(unit,
    381                                            gport,
    382                                            flags[fc],
    383                                            BCM_MIRROR_MTP_COUNT, mirror_dest,
    384                                            &mirror_dest_count);
    385                 if (BCM_E_INTERNAL == rv) {
    386                     continue;
    387                 } else if (rv < 0) {
    388                     cli_out("bcm_mirror_port_dest_get() FAILED: %s\n", bcm_errmsg(rv));
    389                     return CMD_FAIL;
    390                 }
    391                 
    392                 if (first) {
    393                     cli_out("-----------------------------------------\n");
    394                     first = FALSE;
    395                 }
    396                 
    397                 if (mirror_dest_count != 0) {
    398                     int         i;
    399 
    400                     for (i = 0; i < mirror_dest_count; i++) {
    401                         bcm_mirror_destination_t mirror_dest_desc;
    402 
    403                         bcm_mirror_destination_t_init(&mirror_dest_desc);
    404                         mirror_dest_desc.flags = flags[fc];
    405                         rv =
    406                           bcm_mirror_destination_get(unit, mirror_dest[i],
    407                                                      &mirror_dest_desc);
    408                         if (rv < 0) {
    409                             cli_out("bcm_mirror_destination_get() FAILED: %s\n",
    410                                     bcm_errmsg(rv));
    411                             return CMD_FAIL;
    412                         }
    413                         _dmirror_show(unit, gport, 0, mirror_dest_desc.gport, flags[fc]);
    414                     }
    415                     count += mirror_dest_count;
    416                 }
    417             }
    418         }
    419     }
    420 #endif
    421     if (count == 0) {
    422         cli_out("No mirror ports configured\n");
    423     }
    424     return CMD_OK;
    425 }
    426 
    427 cmd_result_t
    428 if_esw_mirror(int unit, args_t *a)
    429 {
    430     int		rv;
    431     soc_port_t	port, dport;
    432     char	pfmt[SOC_PBMP_FMT_LEN];
    433     char	bmstr[FORMAT_PBMP_MAX];
    434     char *modeList[] = {"Off", "L2", "L3", NULL};
    435     int		argMode = -1, argPort = -1;
    436     bcm_pbmp_t argIngBmp, argEgrBmp;
    437     bcm_port_config_t   pcfg;
    438     parse_table_t	pt;
    439     cmd_result_t	retCode;
    440     char            *subcmd = NULL;
    441 
    442     BCM_PBMP_CLEAR(argIngBmp);
    443     BCM_PBMP_CLEAR(argEgrBmp);
    444 
    445     if (!sh_check_attached(ARG_CMD(a), unit)) {
    446         return CMD_FAIL;
    447     }
    448 
    449     if ((subcmd = ARG_GET(a)) != NULL) {
    450         if (parse_cmp("DEST", subcmd, '\0')) {
    451             return _if_esw_mirror_dest(unit, a);
    452         } else if ((ARG_CNT(a) == 0) && parse_cmp("SHow", subcmd, '\0')) {
    453             /* coverity[stack_use_overflow : FALSE] */
    454 	        return _mirror_show(unit);
    455 	    }
    456         /* no sub command going down, all arguments are treated as mirror parameter
    457            decrement processed parameter count by 1 to check it properly */
    458         ARG_PREV(a);
    459     }
    460 
    461     if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) {
    462         cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a));
    463         return CMD_FAIL;
    464     }
    465 
    466     if (!SOC_IS_XGS12_FABRIC(unit) ) {
    467 	rv = bcm_mirror_to_get(unit, &argPort);
    468 	if (rv < 0) {
    469 	    cli_out("%s: bcm_mirror_to_get() failed: %s\n", ARG_CMD(a),
    470                     bcm_errmsg(rv));
    471 	    return CMD_FAIL;
    472 	}
    473 
    474 	rv = bcm_mirror_mode_get(unit, &argMode);
    475 	if (rv < 0) {
    476 	    cli_out("%s: bcm_mirror_mode_get() failed: %s\n", ARG_CMD(a),
    477                     bcm_errmsg(rv));
    478 	    return CMD_FAIL;
    479 	}
    480 
    481 	BCM_PBMP_CLEAR(argIngBmp);
    482 	BCM_PBMP_CLEAR(argEgrBmp);
    483 
    484 	/* coverity[overrun-local] */
    485         DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) {
    486 	    int enable;
    487 
    488 	    rv = bcm_mirror_ingress_get(unit, port, &enable);
    489 	    /* coverity[overrun-local] */
    490             if (rv < 0 && !IS_CPU_PORT(unit, port)) {
    491 		cli_out("%s: bcm_mirror_ingress_get() failed: %s\n", ARG_CMD(a),
    492                         bcm_errmsg(rv));
    493 		return CMD_FAIL;
    494 	    }
    495 
    496 	    if (enable) {
    497 		/* coverity[overrun-local] */
    498                 BCM_PBMP_PORT_ADD(argIngBmp, port);
    499 	    }
    500 
    501 	    rv = bcm_mirror_egress_get(unit, port, &enable);
    502 	    if (rv < 0 && !IS_CPU_PORT(unit, port)) {
    503 		cli_out("%s: bcm_mirror_egress_get() failed: %s\n", ARG_CMD(a),
    504                         bcm_errmsg(rv));
    505 		return CMD_FAIL;
    506 	    }
    507 
    508 	    if (enable) {
    509 		/* coverity[overrun-local] */
    510                 BCM_PBMP_PORT_ADD(argEgrBmp, port);
    511 	    }
    512 	}
    513 
    514 	parse_table_init(unit, &pt);
    515 	parse_table_add(&pt, "Mode", PQ_DFL|PQ_MULTI,
    516 			(void *)(0), &argMode, modeList);
    517 	parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM,
    518 			(void *)(0), &argPort, NULL);
    519 	parse_table_add(&pt, "IngressBitMap", PQ_DFL|PQ_PBMP|PQ_BCM,
    520 			(void *)(0), &argIngBmp, NULL);
    521 	parse_table_add(&pt, "EgressBitMap", PQ_DFL|PQ_PBMP|PQ_BCM,
    522 			(void *)(0), &argEgrBmp, NULL);
    523 	if (!parseEndOk( a, &pt, &retCode)) {
    524 	    return retCode;
    525 	}
    526 
    527 	rv = bcm_mirror_to_set(unit, argPort);
    528 	if (rv < 0) {
    529 	    cli_out("%s: bcm_mirror_to_set() failed: %s\n", ARG_CMD(a),
    530                     bcm_errmsg(rv));
    531 	    return CMD_FAIL;
    532 	}
    533 
    534 	switch (argMode) {
    535 	case 0:
    536 	    rv = bcm_mirror_mode_set(unit, BCM_MIRROR_DISABLE);
    537 	    break;
    538 	case 1:
    539 	    rv = bcm_mirror_mode_set(unit, BCM_MIRROR_L2);
    540 	    break;
    541 	case 2:
    542 	    rv = bcm_mirror_mode_set(unit, BCM_MIRROR_L2_L3);
    543 	    break;
    544 	}
    545 
    546 	if (rv < 0) {
    547 	    cli_out("%s: bcm_mirror_mode_set() failed: %s\n", ARG_CMD(a),
    548                     bcm_errmsg(rv));
    549 	    return CMD_FAIL;
    550 	}
    551 
    552 	if (argMode == 0) {	/* skip ingress/egress for disable case */
    553 	    return CMD_OK;
    554 	}
    555 
    556 	/* coverity[overrun-local] */
    557         DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) {
    558 	    rv = bcm_mirror_ingress_set(unit, port,
    559 					BCM_PBMP_MEMBER(argIngBmp, port) ? 1 : 0);
    560 	    if (rv < 0 && !BCM_PBMP_MEMBER(pcfg.cpu, port)) {
    561 		cli_out("%s: bcm_mirror_ingress_set() failed: %s\n", ARG_CMD(a),
    562                         bcm_errmsg(rv));
    563 		return CMD_FAIL;
    564 	    }
    565 	    rv = bcm_mirror_egress_set(unit, port,
    566 				       BCM_PBMP_MEMBER(argEgrBmp, port) ? 1 : 0);
    567 	    if (rv < 0 && !BCM_PBMP_MEMBER(pcfg.cpu, port)) {
    568 		cli_out("%s: bcm_mirror_egress_set failed: %s\n", ARG_CMD(a),
    569                         bcm_errmsg(rv));
    570 		return CMD_FAIL;
    571 	    }
    572 	}
    573 
    574 	return CMD_OK;
    575     } else {
    576 	/* Hercules chip */
    577 
    578 	if (ARG_CNT(a) == 0) {
    579 	    /* Dump mirroring bitmaps */
    580 	    cli_out("Mirroring configuration:\n");
    581             /* coverity[overrun-local] */
    582             DPORT_BCM_PBMP_ITER(unit, pcfg.port, dport, port) {
    583 		if ( (rv = bcm_mirror_to_pbmp_get(unit,
    584 						  port, &argIngBmp)) <  0){
    585 		    cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv));
    586 		    return CMD_FAIL;
    587 		}
    588 		format_bcm_pbmp(unit, bmstr, sizeof(bmstr), argIngBmp);
    589 		cli_out("\t%s\tmirror bitmap %s, %s\n",
    590                         BCM_PORT_NAME(unit, port),
    591                         SOC_PBMP_FMT(argIngBmp, pfmt),
    592                         bmstr);
    593 	    }
    594 	} else {
    595 	    parse_table_init(unit, &pt);
    596 	    parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM,
    597 			    (void *)( 0), &argPort, NULL);
    598 	    parse_table_add(&pt, "BitMap", PQ_DFL|PQ_PBMP|PQ_BCM,
    599 			    (void *)(0), &argIngBmp, NULL);
    600 	    if (!parseEndOk( a, &pt, &retCode)) {
    601 		return retCode;
    602 	    }
    603 
    604 	    if ( (rv = bcm_mirror_to_pbmp_set(unit, argPort, argIngBmp)) < 0) {
    605 		cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv));
    606 		return CMD_FAIL;
    607 	    }
    608 	}
    609     }
    610 
    611     return CMD_OK;
    612 }
    613 
    614 static void
    615 _dmirror_show(int unit, int port, int dstmod, int dstport, uint32 flags)
    616 {
    617     int rv, show_dest;
    618     bcm_port_t local_port;
    619     bcm_gport_t gport;
    620     char *mstr;
    621     char *vptype = "";
    622     uint16 tpid, vlan;
    623     int vp = 0;
    624 
    625     show_dest = 1;
    626     if (flags & BCM_MIRROR_PORT_INGRESS) {
    627         if (flags & (BCM_MIRROR_PORT_EGRESS|BCM_MIRROR_PORT_EGRESS_TRUE)) {
    628             mstr = "Mirror all";
    629         } else {
    630             mstr = "Mirror ingress";
    631         }
    632     } else if (flags & BCM_MIRROR_PORT_EGRESS) {
    633         mstr = "Mirror egress";
    634     } else if (flags & BCM_MIRROR_PORT_EGRESS_TRUE) {
    635         mstr = "Mirror egress true";
    636     } else if (flags & BCM_MIRROR_PORT_ENABLE) {
    637         mstr = "Mirror";
    638     } else {
    639         mstr = "-";
    640         show_dest = 0;
    641     }
    642 
    643     if (BCM_GPORT_IS_SET(port)) {
    644 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
    645         bcm_module_t mod_out;
    646         bcm_trunk_t trunk_id;
    647         int id;
    648         bcm_vlan_port_t vlan_vp;
    649 
    650         vp = BCM_GPORT_VP_GROUP_GET(port);
    651 
    652         BCM_GPORT_VLAN_PORT_ID_SET(port, vp);
    653         bcm_vlan_port_t_init(&vlan_vp);
    654         vlan_vp.vlan_port_id = port;
    655         rv = bcm_vlan_port_find(unit, &vlan_vp);
    656         if (BCM_E_NONE == rv) {
    657             (void)_bcm_esw_gport_resolve(unit, vlan_vp.port, &mod_out,
    658                 &port, &trunk_id, &id);
    659             vptype = "Vlan";
    660         }
    661 #ifdef BCM_TRIDENT_SUPPORT
    662         if (rv != BCM_E_NONE) {
    663             bcm_niv_port_t niv_port;
    664     
    665             BCM_GPORT_NIV_PORT_ID_SET(port, vp);
    666             bcm_niv_port_t_init(&niv_port);
    667             niv_port.niv_port_id = port;
    668             rv = bcm_niv_port_get(unit, &niv_port);
    669             if (BCM_E_NONE == rv) {
    670                 (void)_bcm_esw_gport_resolve(unit, niv_port.port, &mod_out,
    671                     &port, &trunk_id, &id);
    672                 vptype = "Niv";
    673             }
    674         }
    675 #endif /* BCM_TRIDENT_SUPPORT */
    676 #ifdef BCM_TRIUMPH3_SUPPORT
    677         if (rv != BCM_E_NONE) {
    678             bcm_extender_port_t extender_port;
    679     
    680             BCM_GPORT_EXTENDER_PORT_ID_SET(port, vp);
    681             bcm_extender_port_t_init(&extender_port);
    682             extender_port.extender_port_id = port;
    683             rv = bcm_extender_port_get(unit, &extender_port);
    684             if (BCM_E_NONE == rv) {
    685                 (void)_bcm_esw_gport_resolve(unit, extender_port.port, &mod_out,
    686                     &port, &trunk_id, &id);
    687                 vptype = "Extender";
    688             }
    689         }
    690 #endif /* BCM_TRIUMPH3_SUPPORT */
    691 #ifdef BCM_MPLS_SUPPORT
    692         if (rv != BCM_E_NONE) {
    693             bcm_mpls_port_t mpls_port;
    694             int vpn0;
    695      
    696             BCM_GPORT_MPLS_PORT_ID_SET(port, vp);
    697             bcm_mpls_port_t_init(&mpls_port);
    698             mpls_port.mpls_port_id = port;
    699             _BCM_MPLS_VPN_SET(vpn0,_BCM_MPLS_VPN_TYPE_VPWS,0);
    700             rv = bcm_mpls_port_get(unit, vpn0, &mpls_port);
    701             if (BCM_E_NONE == rv) {
    702                 (void)_bcm_esw_gport_resolve(unit, mpls_port.port, &mod_out,
    703                     &port, &trunk_id, &id);
    704                 vptype = "Mpls";
    705             }
    706         }
    707 #endif  /* BCM_MPLS_SUPPORT */
    708 #endif
    709         cli_out("%s vp%d(%4s): %s", vptype, vp, BCM_PORT_NAME(unit, port), mstr);
    710     } else {
    711         cli_out("%4s: %s", BCM_PORT_NAME(unit, port), mstr);
    712     }
    713     
    714     if (show_dest) {
    715         if (BCM_GPORT_IS_MODPORT(dstport)) {
    716             gport = dstport;
    717             dstmod = BCM_GPORT_MODPORT_MODID_GET(gport);
    718             dstport = BCM_GPORT_MODPORT_PORT_GET(gport);
    719         } else {
    720             BCM_GPORT_MODPORT_SET(gport, dstmod, dstport);
    721         }
    722         if (bcm_port_local_get(unit, gport, &local_port) != BCM_E_NONE) {
    723             local_port = -1;
    724         }
    725         if (BCM_GPORT_IS_TRUNK(dstport)) {
    726             cli_out(" to trunk group %d", BCM_GPORT_TRUNK_GET(dstport));
    727         } else if (flags & BCM_MIRROR_PORT_DEST_TRUNK) {
    728             cli_out(" to trunk group %d", dstport);
    729         } else if (local_port >= 0) {
    730             cli_out(" to local port %s", BCM_PORT_NAME(unit, local_port));
    731         } else {
    732             cli_out(" to module %d, port %d", dstmod, dstport);
    733         }
    734         if (local_port >= 0) {
    735             rv = bcm_mirror_vlan_get(unit, local_port, &tpid, &vlan);
    736             if (rv == BCM_E_NONE && vlan > 0) {
    737                 cli_out(" (TPID=0x%04X(%d), VLAN=0x%04X(%d))", tpid, tpid, vlan, vlan);
    738             }
    739         }
    740     }
    741     cli_out("\n");
    742 }
    743 
    744 char if_dmirror_usage[] =
    745     "Parameters: <ports> [Mode=<Off|On|Ingress|Egress|All>]\n"
    746     "\t[DestPort=<port>] [DestModule=<modid>] [DestTrunk=<tgid>]\n"
    747     "\t[MirrorTagProtocolID=<tpid>] [MirrorVlanID=<vid>\n"
    748     "\tDestTrunk overrides DestModule/DestPort.\n"
    749     "\tTPID and VLAN are set only if DestPort is a local port.\n";
    750 
    751 cmd_result_t
    752 if_dmirror(int unit, args_t *a)
    753 {
    754     int	rv;
    755     int port, dport, dstmod, dstport;
    756     int mymodid;
    757     uint32 flags;
    758     parse_table_t pt;
    759     cmd_result_t retCode;
    760     bcm_pbmp_t pbm, tmp_pbm;
    761     bcm_port_config_t pcfg;
    762     char *mstr;
    763     int argDestPort = -1, argDestMod = -1, argDestTrunk = -1;
    764     int argMode = -1, argTpid = -1, argVlan = -1;
    765 
    766     char *modeList[] = {"OFF", "ON", "Ingress", "Egress", "All", NULL};
    767 
    768     if (!sh_check_attached(ARG_CMD(a), unit)) {
    769 	return CMD_FAIL;
    770     }
    771 
    772     if (SOC_IS_XGS12_FABRIC(unit) ) {
    773         cli_out("%s: command not supported for switch fabric chips\n", ARG_CMD(a));
    774         return CMD_FAIL;
    775     }
    776 
    777     if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) {
    778         cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a));
    779         return CMD_FAIL;
    780     }
    781 
    782     rv = bcm_stk_my_modid_get(unit, &mymodid);
    783     if (rv < 0) {
    784         cli_out("%s: bcm_stk_my_modid_get: %s\n", ARG_CMD(a),
    785                 bcm_errmsg(rv));
    786         return CMD_FAIL;
    787     }
    788 
    789     if ((mstr = ARG_GET(a)) == NULL) {
    790         return CMD_USAGE;
    791     }
    792 
    793     if ((ARG_CNT(a) == 0) && parse_cmp("SHow", mstr, '\0')) {
    794         int         count = 0;
    795 
    796         /* coverity[overrun-local] */
    797         DPORT_BCM_PBMP_ITER(unit, pcfg.all, dport, port) {
    798             rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags);
    799             if (rv < 0) {
    800                 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a), bcm_errmsg(rv));
    801                 return CMD_FAIL;
    802             }
    803             if (flags != 0) {
    804                 count++;
    805                 _dmirror_show(unit, port, dstmod, dstport, flags);
    806             }
    807         }
    808         if (count == 0) {
    809             cli_out("%s: No mirror ports configured\n", ARG_CMD(a));
    810         }
    811         return CMD_OK;
    812     }
    813     if (parse_bcm_pbmp(unit, mstr, &pbm) < 0) {
    814         cli_out("%s: Error: unrecognized port bitmap: %s\n",
    815                 ARG_CMD(a), mstr);
    816         return CMD_FAIL;
    817     }
    818 
    819     if (soc_feature(unit, soc_feature_cpuport_mirror)) {
    820         BCM_PBMP_AND(pbm, pcfg.all);
    821     } else {
    822         BCM_PBMP_AND(pbm, pcfg.port);
    823     }
    824 
    825     if (BCM_PBMP_IS_NULL(pbm)) {
    826         cli_out("%s: Error: unsupported port bitmap: %s\n",
    827                 ARG_CMD(a), mstr);
    828         return CMD_FAIL;
    829     }
    830 
    831     if (ARG_CNT(a) == 0) {
    832         /* Show FE ports separately (for Tucana) */
    833         tmp_pbm = pbm;
    834         BCM_PBMP_AND(tmp_pbm, pcfg.fe);
    835         /* coverity[overrun-local] */
    836         DPORT_BCM_PBMP_ITER(unit, tmp_pbm, dport, port) {
    837             rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags);
    838             if (rv < 0) {
    839                 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a),
    840                         bcm_errmsg(rv));
    841                 return CMD_FAIL;
    842             }
    843             _dmirror_show(unit, port, dstmod, dstport, flags);
    844         }
    845         /* Show non-FE ports */
    846         tmp_pbm = pbm;
    847         BCM_PBMP_REMOVE(tmp_pbm, pcfg.fe);
    848         DPORT_BCM_PBMP_ITER(unit, tmp_pbm, dport, port) {
    849             rv = bcm_mirror_port_get(unit, port, &dstmod, &dstport, &flags);
    850             if (rv < 0) {
    851                 cli_out("%s: bcm_mirror_port_get: %s\n", ARG_CMD(a),
    852                         bcm_errmsg(rv));
    853                 return CMD_FAIL;
    854             }
    855             _dmirror_show(unit, port, dstmod, dstport, flags);
    856         }
    857         return CMD_OK;
    858     }
    859 
    860     parse_table_init(unit, &pt);
    861     parse_table_add(&pt, "DestPort", PQ_DFL|PQ_PORT,
    862                     (void *)(0), &argDestPort, NULL);
    863     parse_table_add(&pt, "DestModule", PQ_DFL|PQ_INT,
    864                     (void *)(0), &argDestMod, NULL);
    865     parse_table_add(&pt, "DestTrunk", PQ_DFL|PQ_INT,
    866                     (void *)(0), &argDestTrunk, NULL);
    867     parse_table_add(&pt, "MirrorTagProtocolID", PQ_DFL|PQ_INT,
    868                     (void *)(0), &argTpid, NULL);
    869     parse_table_add(&pt, "MirrorVlanID", PQ_DFL|PQ_INT,
    870                     (void *)(0), &argVlan, NULL);
    871     parse_table_add(&pt, "Mode", PQ_DFL|PQ_MULTI,
    872                     (void *)(0), &argMode, modeList);
    873     if (!parseEndOk( a, &pt, &retCode)) {
    874         return retCode;
    875     }
    876 
    877     flags = 0;
    878 
    879     if (argMode < 0) {
    880         cli_out("%s: must specify a mode\n", ARG_CMD(a));
    881         return CMD_USAGE;
    882     }
    883 
    884     if ((argMode > 0) && (argDestPort < 0) && (argDestTrunk < 0)) {
    885         cli_out("%s: missing DestPort or DestTrunk\n", ARG_CMD(a));
    886         return CMD_USAGE;
    887     }
    888     if ((argDestPort >= 0) && (argDestTrunk >= 0)) {
    889         cli_out("%s: cannot specify both DestPort and DestTrunk\n", ARG_CMD(a));
    890         return CMD_USAGE;
    891     }
    892 
    893     if (argDestTrunk < 0) {
    894         dstport = argDestPort;
    895     } else {
    896         dstport = argDestTrunk;
    897         flags |= BCM_MIRROR_PORT_DEST_TRUNK;
    898     }
    899 
    900     switch (argMode) {
    901     case 1:
    902         flags |= BCM_MIRROR_PORT_ENABLE;
    903         break;
    904     case 2:
    905         flags |= BCM_MIRROR_PORT_INGRESS;
    906         break;
    907     case 3:
    908         flags |= BCM_MIRROR_PORT_EGRESS;
    909         break;
    910     case 4:
    911         flags |= (BCM_MIRROR_PORT_INGRESS | BCM_MIRROR_PORT_EGRESS);
    912         break;
    913     default:
    914         break;
    915     }
    916 
    917     DPORT_BCM_PBMP_ITER(unit, pbm, dport, port) {
    918         rv = bcm_mirror_port_set(unit, port, argDestMod, dstport, flags);
    919 
    920         if (rv < 0) {
    921             cli_out("%s: bcm_mirror_port_set: %s\n", ARG_CMD(a),
    922                     bcm_errmsg(rv));
    923             return CMD_FAIL;
    924         }
    925 
    926         if (argDestMod < 0 || argDestMod == mymodid) {
    927             if (argTpid >= 0 && argVlan >= 0 && argDestTrunk < 0) {
    928                 rv = bcm_mirror_vlan_set(unit, dstport, argTpid, argVlan);
    929 
    930                 if (rv < 0) {
    931                     cli_out("%s: bcm_mirror_vlan_set failed: %s\n", ARG_CMD(a),
    932                             bcm_errmsg(rv));
    933                     return CMD_FAIL;
    934                 }
    935             }
    936         }
    937     }
    938 
    939     return CMD_OK;
    940 }