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

multicast.c (21418B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:    multicast.c
      8  * Purpose: Multicast CLI commands
      9  */
     10 
     11 #include <appl/diag/system.h>
     12 #include <appl/diag/parse.h>
     13 #include <shared/bsl.h>
     14 #include <bcm/error.h>
     15 
     16 #include <bcm/multicast.h>
     17 #include <bcm_int/common/multicast.h>
     18 #include <bcm_int/esw/multicast.h>
     19 
     20 char cmd_multicast_usage[] =
     21     "Usages:\n"
     22     "\tcreate Type=L2|L3|VPLS|SUBPORT|MIN|WLAN|TRILL [Group=<num>]\n"
     23     "\tdestroy Group=<num>\n"
     24     "\tl3encap Group=<num> Port=<num> Intf=<num>\n"
     25     "\tl2encap Group=<num> Port=<num> Vlan=<num>\n"
     26     "\tvplsencap Group=<num> Port=<num> MplsPortId=<num>\n"
     27     "\tsubportencap Group=<num> Port=<num> SubPort=<num>\n"
     28     "\tmimencap Group=<num> Port=<num> MimPortId=<num>\n"
     29     "\twlanencap Group=<num> Port=<num> WlanPortId=<num>\n"
     30     "\tadd Group=<num> Port=<num> EncapId=<num>\n"
     31     "\tdelete Group=<num> [Port=<num> EncapId=<num>]\n"
     32     "\tshow [Group=<num>]\n";
     33 
     34 const char *cmd_multicast_parse_type[] = {
     35     "NONE",
     36     "L2",
     37     "L3",
     38     "VPLS",
     39     "SUBPORT",
     40     "MIM",
     41     "WLAN",
     42     "VLAN",
     43     "TRILL",
     44     "NIV",
     45     "EGRESS_OBJECT",
     46     "L2GRE",
     47     "VXLAN",
     48     "PORTS_GROUP",
     49     "EXTENDER"
     50 };
     51 
     52 int
     53 _cmd_multicast_traverse_cb(int unit, bcm_multicast_t group, uint32 flags, 
     54                            void *user_data)
     55 {
     56     int rv, i, port_count;
     57     bcm_gport_t *port_array = NULL;
     58     bcm_if_t    *encap_id_array = NULL;
     59     int         port_max = 0;
     60 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
     61     bcm_gport_t *q_array = NULL;
     62 #endif
     63  
     64     /* first, get the port count.
     65      * port_max = 0, port_array & encap_id_array = NULL
     66      */
     67     rv = bcm_multicast_egress_get(unit, group, port_max, port_array,
     68                                   encap_id_array, &port_count);
     69     if (rv < 0) {
     70         cli_out("%s ERROR: egress port count get failed - %s\n",
     71                 ARG_CMD((args_t *)user_data), bcm_errmsg(rv));
     72         return rv;
     73     }
     74     if (port_count) {
     75         /* allocate proper size port_array & encap_id_array */
     76         port_array = (bcm_gport_t *)sal_alloc
     77                      (sizeof(bcm_gport_t) * port_count,
     78                       "_cmd_multicast_traverse_cb : port_array");
     79         if (port_array == NULL) {
     80             cli_out("%s ERROR: port_array mem alloc failed\n",
     81                    ARG_CMD((args_t *)user_data));
     82             return BCM_E_MEMORY;
     83         }
     84         encap_id_array = (bcm_if_t *)sal_alloc(
     85                          sizeof(bcm_if_t) *port_count,
     86                          "_cmd_multicast_traverse_cb : encap_id_array");
     87         if (encap_id_array == NULL) {
     88             cli_out("%s ERROR: encap_id_array mem alloc failed\n",
     89                    ARG_CMD((args_t *)user_data));
     90             sal_free(port_array);
     91             return BCM_E_MEMORY;
     92         }
     93 
     94         rv = bcm_multicast_egress_get(unit, group, port_count,
     95                                       port_array, encap_id_array,
     96                                       &port_count);
     97         if (rv < 0) {
     98             cli_out("%s ERROR: egress get failure - %s\n",
     99                    ARG_CMD((args_t *)user_data), bcm_errmsg(rv));
    100             sal_free(port_array);
    101             sal_free(encap_id_array);
    102             return rv;
    103         }
    104         if (_BCM_MULTICAST_TYPE_GET(group) >=
    105             COUNTOF(cmd_multicast_parse_type)) {
    106             cli_out("Group 0x%x (%s)\n", group,
    107                    "UNKNOWN");
    108         } else {
    109             cli_out("Group 0x%x (%s)\n", group,
    110                    cmd_multicast_parse_type[_BCM_MULTICAST_TYPE_GET(group)]);
    111         }
    112         for (i = 0; i < port_count; i++) {
    113             cli_out("\tport %s, encap id %d\n",
    114                    mod_port_name(unit, -1, port_array[i]), encap_id_array[i]);
    115         }
    116 
    117         sal_free(port_array);
    118         sal_free(encap_id_array);
    119     }
    120 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 
    121     if (SOC_IS_KATANAX(unit)) {
    122         /* Subscrber replications
    123          */
    124         port_max = BCM_MULTICAST_PORT_MAX;
    125         port_count = 0;
    126         port_array = sal_alloc(port_max * sizeof(bcm_gport_t),
    127                                "mcast port array");
    128         if (port_array == NULL) {
    129             return BCM_E_MEMORY;
    130         }
    131         encap_id_array = sal_alloc(port_max * sizeof(bcm_if_t),
    132                                 "mcast encap array");
    133         if (encap_id_array == NULL) {
    134             sal_free (port_array);
    135             return BCM_E_MEMORY;
    136         }
    137         q_array = sal_alloc(port_max * sizeof(bcm_if_t),
    138                                 "mcast q array");
    139         if (q_array == NULL) {
    140             sal_free (port_array);
    141             sal_free (encap_id_array);
    142             return BCM_E_MEMORY;
    143         }
    144         sal_memset(q_array, 0, (port_max * sizeof(bcm_if_t)));
    145 
    146         rv = bcm_multicast_egress_subscriber_get(unit, group,
    147                                       port_max, port_array,
    148                                       encap_id_array, q_array, &port_count);
    149         if (rv < 0) {
    150             cli_out("%s ERROR: egress port count get failed - ?%s\n",
    151                    ARG_CMD((args_t *)user_data), bcm_errmsg(rv));
    152             sal_free(port_array);
    153             sal_free(encap_id_array);
    154             sal_free(q_array);
    155             return rv;
    156         }
    157         if (port_count == 0) {
    158             sal_free(port_array);
    159             sal_free(encap_id_array);
    160             sal_free(q_array);
    161             return BCM_E_NONE;
    162         }
    163         if (_BCM_MULTICAST_TYPE_GET(group) >=
    164             COUNTOF(cmd_multicast_parse_type)) {
    165             cli_out("Group 0x%x (%s)\n", group,
    166                    "UNKNOWN");
    167         } else {
    168             cli_out("Group 0x%x (%s)\n", group,
    169                    cmd_multicast_parse_type[_BCM_MULTICAST_TYPE_GET(group)]);
    170         }
    171         for (i = 0; i < port_count; i++) {
    172             cli_out("\tport %s, encap id %d replication queue id %d\n",
    173                    mod_port_name(unit, -1, port_array[i]),
    174                    encap_id_array[i],q_array[i]);
    175         }
    176 
    177         sal_free(port_array);
    178         sal_free(encap_id_array);
    179         sal_free(q_array);
    180     }
    181 #endif
    182     return BCM_E_NONE;
    183 }
    184 
    185 cmd_result_t
    186 cmd_multicast(int unit, args_t *a)
    187 {
    188     char *subcmd = NULL;
    189     parse_table_t pt;
    190     int rv, type;
    191     uint32 flags;
    192     bcm_multicast_t group;
    193     bcm_gport_t port;
    194     bcm_if_t intf; /* for l3_encap_get */
    195     bcm_vlan_t vlan; /* for l2_encap_get */
    196     bcm_gport_t mpls_port_id; /* for vpls_encap_get */
    197     bcm_gport_t subport; /* for subport_encap_get */
    198     bcm_gport_t mim_port_id; /* for mim_encap_get */
    199     bcm_gport_t wlan_port_id; /* for wlan_encap_get */
    200     bcm_if_t encap_id;
    201     char buf[20];
    202 
    203     subcmd = ARG_GET(a);
    204     if (subcmd == NULL) {
    205         return CMD_USAGE;
    206     }
    207 
    208     if (!sal_strcasecmp(subcmd, "create")) {
    209         parse_table_init(unit, &pt);
    210         parse_table_add(&pt, "Type", PQ_MULTI, 0, &type,
    211                         cmd_multicast_parse_type);
    212         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    213         if (parse_arg_eq(a, &pt) < 0) {
    214             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    215             parse_arg_eq_done(&pt);
    216             return CMD_FAIL;
    217         }
    218         parse_arg_eq_done(&pt);
    219 
    220         switch (type) {
    221         case _BCM_MULTICAST_TYPE_L2:
    222             flags = BCM_MULTICAST_TYPE_L2;
    223             break;
    224         case _BCM_MULTICAST_TYPE_L3:
    225             flags = BCM_MULTICAST_TYPE_L3;
    226             break;
    227         case _BCM_MULTICAST_TYPE_VPLS:
    228             flags = BCM_MULTICAST_TYPE_VPLS;
    229             break;
    230         case _BCM_MULTICAST_TYPE_SUBPORT:
    231             flags = BCM_MULTICAST_TYPE_SUBPORT;
    232             break;
    233         case _BCM_MULTICAST_TYPE_MIM:
    234             flags = BCM_MULTICAST_TYPE_MIM;
    235             break;
    236         case _BCM_MULTICAST_TYPE_WLAN:
    237             flags = BCM_MULTICAST_TYPE_WLAN;
    238             break;
    239         case _BCM_MULTICAST_TYPE_TRILL:
    240             flags = BCM_MULTICAST_TYPE_TRILL;
    241             break;
    242         default:
    243             return CMD_FAIL;
    244         }
    245         if (group != -1) {
    246             flags |= BCM_MULTICAST_WITH_ID;
    247             if (!_BCM_MULTICAST_IS_SET(group)) {
    248                 /* Encode the group properly for the selected type */
    249                 _BCM_MULTICAST_GROUP_SET(group, type, group);
    250             }
    251         }
    252         rv = bcm_multicast_create(unit, flags, &group);
    253         if (rv < 0) {
    254             cli_out("%s ERROR: fail to create %s group - %s\n",
    255                     ARG_CMD(a), cmd_multicast_parse_type[type],
    256                     bcm_errmsg(rv));
    257             return CMD_FAIL;
    258         }
    259 
    260         cli_out("group id 0x%x\n", group);
    261         sal_sprintf(buf, "0x%x", group);
    262         var_set("multicast_group", buf, TRUE, FALSE);
    263         return CMD_OK;
    264     }
    265 
    266     if (!sal_strcasecmp(subcmd, "destroy")) {
    267         parse_table_init(unit, &pt);
    268         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    269         if (parse_arg_eq(a, &pt) < 0 || group == -1) {
    270             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    271             parse_arg_eq_done(&pt);
    272             return CMD_FAIL;
    273         }
    274         parse_arg_eq_done(&pt);
    275 
    276         rv = bcm_multicast_destroy(unit, group);
    277         if (rv < 0) {
    278             cli_out("%s ERROR: fail to destroy group %d - %s\n",
    279                     ARG_CMD(a), group, bcm_errmsg(rv));
    280             return CMD_FAIL;
    281         }
    282         return CMD_OK;
    283     }
    284 
    285     if (!sal_strcasecmp(subcmd, "l3encap")) {
    286         parse_table_init(unit, &pt);
    287         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    288         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    289                         0);
    290         parse_table_add(&pt, "Intf", PQ_INT, (void *)-1, &intf, 0);
    291         if (parse_arg_eq(a, &pt) < 0) {
    292             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    293             parse_arg_eq_done(&pt);
    294             return CMD_FAIL;
    295         }
    296         parse_arg_eq_done(&pt);
    297 
    298         if (intf == -1) {
    299             cli_out("%s: Interface not specified\n", ARG_CMD(a));
    300             return CMD_FAIL;
    301         }
    302 
    303         if (!BCM_GPORT_IS_SET(port)) {
    304             BCM_GPORT_LOCAL_SET(port, port);
    305         }
    306         rv = bcm_multicast_l3_encap_get(unit, group, port, intf, &encap_id);
    307         if (rv < 0) {
    308             cli_out("%s ERROR: fail to get L3 encap - %s\n",
    309                     ARG_CMD(a), bcm_errmsg(rv));
    310             return CMD_FAIL;
    311         }
    312         cli_out("Encap ID %d\n", encap_id);
    313         return CMD_OK;
    314     }
    315 
    316     if (!sal_strcasecmp(subcmd, "l2encap")) {
    317         parse_table_init(unit, &pt);
    318         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    319         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    320                         0);
    321         parse_table_add(&pt, "Vlan", PQ_INT, (void *)BCM_VLAN_INVALID, &vlan,
    322                         0);
    323         if (parse_arg_eq(a, &pt) < 0) {
    324             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    325             parse_arg_eq_done(&pt);
    326             return CMD_FAIL;
    327         }
    328         parse_arg_eq_done(&pt);
    329 
    330         if (!BCM_GPORT_IS_SET(port)) {
    331             BCM_GPORT_LOCAL_SET(port, port);
    332         }
    333         rv = bcm_multicast_l2_encap_get(unit, group, port, vlan, &encap_id);
    334         if (rv < 0) {
    335             cli_out("%s ERROR: fail to get L2 encap - %s\n",
    336                     ARG_CMD(a), bcm_errmsg(rv));
    337             return CMD_FAIL;
    338         }
    339         cli_out("Encap ID %d\n", encap_id);
    340         return CMD_OK;
    341     }
    342 
    343     if (!sal_strcasecmp(subcmd, "vplsencap")) {
    344         parse_table_init(unit, &pt);
    345         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    346         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    347                         0);
    348         parse_table_add(&pt, "MplsPortId", PQ_INT, (void *)BCM_GPORT_INVALID,
    349                         &mpls_port_id, 0);
    350         if (parse_arg_eq(a, &pt) < 0) {
    351             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    352             parse_arg_eq_done(&pt);
    353             return CMD_FAIL;
    354         }
    355         parse_arg_eq_done(&pt);
    356 
    357         if (group < 0) {
    358             cli_out("%s: Group not specified\n", ARG_CMD(a));
    359             return CMD_FAIL;
    360         }
    361         if (port == BCM_GPORT_INVALID) {
    362             cli_out("%s: Port not specified\n", ARG_CMD(a));
    363             return CMD_FAIL;
    364         }
    365         if (mpls_port_id == BCM_GPORT_INVALID) {
    366             cli_out("%s: MplsPortId not specified\n", ARG_CMD(a));
    367             return CMD_FAIL;
    368         }
    369 
    370         if (!BCM_GPORT_IS_SET(port)) {
    371             BCM_GPORT_LOCAL_SET(port, port);
    372         }
    373         if (!BCM_GPORT_IS_SET(mpls_port_id)) {
    374             BCM_GPORT_MPLS_PORT_ID_SET(mpls_port_id, mpls_port_id);
    375         }
    376         rv = bcm_multicast_vpls_encap_get(unit, group, port, mpls_port_id,
    377                                           &encap_id);
    378         if (rv < 0) {
    379             cli_out("%s ERROR: fail to get VPLS encap - %s\n",
    380                     ARG_CMD(a), bcm_errmsg(rv));
    381             return CMD_FAIL;
    382         }
    383         cli_out("Encap ID %d\n", encap_id);
    384         return CMD_OK;
    385     }
    386 
    387     if (!sal_strcasecmp(subcmd, "subportEncap")) {
    388         parse_table_init(unit, &pt);
    389         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    390         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    391                         0);
    392         parse_table_add(&pt, "SubPort", PQ_INT, (void *)BCM_GPORT_INVALID,
    393                         &subport, 0);
    394         if (parse_arg_eq(a, &pt) < 0) {
    395             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    396             parse_arg_eq_done(&pt);
    397             return CMD_FAIL;
    398         }
    399         parse_arg_eq_done(&pt);
    400 
    401         if (group < 0) {
    402             cli_out("%s: Group not specified\n", ARG_CMD(a));
    403             return CMD_FAIL;
    404         }
    405         if (port == BCM_GPORT_INVALID) {
    406             cli_out("%s: Port not specified\n", ARG_CMD(a));
    407             return CMD_FAIL;
    408         }
    409         if (subport == BCM_GPORT_INVALID) {
    410             cli_out("%s: SubPort not specified\n", ARG_CMD(a));
    411             return CMD_FAIL;
    412         }
    413 
    414         if (!BCM_GPORT_IS_SET(port)) {
    415             BCM_GPORT_LOCAL_SET(port, port);
    416         }
    417         if (!BCM_GPORT_IS_SET(subport)) {
    418             BCM_GPORT_SUBPORT_PORT_SET(subport, subport);
    419         }
    420         rv = bcm_multicast_subport_encap_get(unit, group, port, subport,
    421                                              &encap_id);
    422         if (rv < 0) {
    423             cli_out("%s ERROR: fail to get subport encap - %s\n",
    424                     ARG_CMD(a), bcm_errmsg(rv));
    425             return CMD_FAIL;
    426         }
    427         cli_out("Encap ID %d\n", encap_id);
    428         return CMD_OK;
    429     }
    430 
    431     if (!sal_strcasecmp(subcmd, "mimencap")) {
    432         parse_table_init(unit, &pt);
    433         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    434         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    435                         0);
    436         parse_table_add(&pt, "MimPortId", PQ_INT, (void *)BCM_GPORT_INVALID,
    437                         &mim_port_id, 0);
    438         if (parse_arg_eq(a, &pt) < 0) {
    439             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    440             parse_arg_eq_done(&pt);
    441             return CMD_FAIL;
    442         }
    443         parse_arg_eq_done(&pt);
    444 
    445         if (group < 0) {
    446             cli_out("%s: Group not specified\n", ARG_CMD(a));
    447             return CMD_FAIL;
    448         }
    449         if (port == BCM_GPORT_INVALID) {
    450             cli_out("%s: Port not specified\n", ARG_CMD(a));
    451             return CMD_FAIL;
    452         }
    453         if (mim_port_id == BCM_GPORT_INVALID) {
    454             cli_out("%s: MimPortId not specified\n", ARG_CMD(a));
    455             return CMD_FAIL;
    456         }
    457 
    458         if (!BCM_GPORT_IS_SET(port)) {
    459             BCM_GPORT_LOCAL_SET(port, port);
    460         }
    461         if (!BCM_GPORT_IS_SET(mim_port_id)) {
    462             BCM_GPORT_MIM_PORT_ID_SET(mim_port_id, mim_port_id);
    463         }
    464         rv = bcm_multicast_mim_encap_get(unit, group, port, mim_port_id,
    465                                          &encap_id);
    466         if (rv < 0) {
    467             cli_out("%s ERROR: fail to get MIM encap - %s\n",
    468                     ARG_CMD(a), bcm_errmsg(rv));
    469             return CMD_FAIL;
    470         }
    471         cli_out("Encap ID %d\n", encap_id);
    472         return CMD_OK;
    473     }
    474 
    475     if (!sal_strcasecmp(subcmd, "wlanencap")) {
    476         parse_table_init(unit, &pt);
    477         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    478         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    479                         0);
    480         parse_table_add(&pt, "WlanPortId", PQ_INT, (void *)BCM_GPORT_INVALID,
    481                         &wlan_port_id, 0);
    482         if (parse_arg_eq(a, &pt) < 0) {
    483             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    484             parse_arg_eq_done(&pt);
    485             return CMD_FAIL;
    486         }
    487         parse_arg_eq_done(&pt);
    488 
    489         if (group < 0) {
    490             cli_out("%s: Group not specified\n", ARG_CMD(a));
    491             return CMD_FAIL;
    492         }
    493         if (port == BCM_GPORT_INVALID) {
    494             cli_out("%s: Port not specified\n", ARG_CMD(a));
    495             return CMD_FAIL;
    496         }
    497         if (wlan_port_id == BCM_GPORT_INVALID) {
    498             cli_out("%s: WlanPortId not specified\n", ARG_CMD(a));
    499             return CMD_FAIL;
    500         }
    501 
    502         if (!BCM_GPORT_IS_SET(port)) {
    503             BCM_GPORT_LOCAL_SET(port, port);
    504         }
    505         if (!BCM_GPORT_IS_SET(wlan_port_id)) {
    506             BCM_GPORT_WLAN_PORT_ID_SET(wlan_port_id, wlan_port_id);
    507         }
    508         rv = bcm_multicast_wlan_encap_get(unit, group, port, wlan_port_id,
    509                                           &encap_id);
    510         if (rv < 0) {
    511             cli_out("%s ERROR: fail to get WLAN encap - %s\n",
    512                     ARG_CMD(a), bcm_errmsg(rv));
    513             return CMD_FAIL;
    514         }
    515         cli_out("Encap ID %d\n", encap_id);
    516         return CMD_OK;
    517     }
    518 
    519     if (!sal_strcasecmp(subcmd, "add")) {
    520         parse_table_init(unit, &pt);
    521         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    522         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    523                         0);
    524         parse_table_add(&pt, "EncapId", PQ_INT, (void *)BCM_IF_INVALID,
    525                         &encap_id, 0);
    526 
    527         if (parse_arg_eq(a, &pt) < 0 || group < 0 ||
    528             port == BCM_GPORT_INVALID) {
    529             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    530             parse_arg_eq_done(&pt);
    531             return CMD_FAIL;
    532         }
    533         parse_arg_eq_done(&pt);
    534 
    535         if (!BCM_GPORT_IS_SET(port)) {
    536             BCM_GPORT_LOCAL_SET(port, port);
    537         }
    538         rv = bcm_multicast_egress_add(unit, group, port, encap_id);
    539         if (rv < 0) {
    540             cli_out("%s ERROR: egress add failure - %s\n",
    541                     ARG_CMD(a), bcm_errmsg(rv));
    542             return CMD_FAIL;
    543         }
    544         return CMD_OK;
    545     }
    546 
    547     if (!sal_strcasecmp(subcmd, "delete")) {
    548         parse_table_init(unit, &pt);
    549         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    550         parse_table_add(&pt, "Port", PQ_PORT, (void *)BCM_GPORT_INVALID, &port,
    551                         0);
    552         parse_table_add(&pt, "EncapId", PQ_INT, (void *)BCM_IF_INVALID,
    553                         &encap_id, 0);
    554         if (parse_arg_eq(a, &pt) < 0 || group < 0) {
    555             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    556             parse_arg_eq_done(&pt);
    557             return CMD_FAIL;
    558         }
    559         parse_arg_eq_done(&pt);
    560 
    561         if (port == BCM_GPORT_INVALID && encap_id == BCM_IF_INVALID) {
    562             rv = bcm_multicast_egress_delete_all(unit, group);
    563             if (rv < 0) {
    564                 cli_out("%s ERROR: egress delete all failure - %s\n",
    565                         ARG_CMD(a), bcm_errmsg(rv));
    566                 return CMD_FAIL;
    567             }
    568         } else {
    569             if (port == BCM_GPORT_INVALID) {
    570                 return CMD_FAIL;
    571             }
    572             if (!BCM_GPORT_IS_SET(port)) {
    573                 BCM_GPORT_LOCAL_SET(port, port);
    574             }
    575             rv = bcm_multicast_egress_delete(unit, group, port, encap_id);
    576             if (rv < 0) {
    577                 cli_out("%s ERROR: egress delete failure - %s\n",
    578                         ARG_CMD(a), bcm_errmsg(rv));
    579                 return CMD_FAIL;
    580             }
    581         }
    582         return CMD_OK;
    583     }
    584 
    585     if (!sal_strcasecmp(subcmd, "show")) {
    586         parse_table_init(unit, &pt);
    587         parse_table_add(&pt, "Group", PQ_INT, (void *)-1, &group, 0);
    588         if (parse_arg_eq(a, &pt) < 0) {
    589             cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a));
    590             parse_arg_eq_done(&pt);
    591             return CMD_FAIL;
    592         }
    593         parse_arg_eq_done(&pt);
    594 
    595 
    596         if (group < 0) {
    597             rv = bcm_multicast_group_traverse(unit,
    598                                               &_cmd_multicast_traverse_cb,
    599                                               BCM_MULTICAST_TYPE_MASK, a);
    600         } else {
    601             rv = _cmd_multicast_traverse_cb(unit, group, 0, a);
    602         }
    603 
    604         if (BCM_FAILURE(rv)) {
    605             return CMD_FAIL;
    606         }
    607 
    608         return CMD_OK;
    609     }
    610 
    611     return CMD_USAGE;
    612 }