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

ipmc.c (19490B)


      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:        ipmc.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 
     12 #include <bcm/types.h>
     13 #include <bcm/error.h>
     14 #include <shared/bsl.h>
     15 #include <bcm/l3.h>
     16 #include <bcmx/ipmc.h>
     17 
     18 #include <appl/diag/parse.h>
     19 #include <appl/diag/shell.h>
     20 #include <appl/diag/system.h>
     21 
     22 #include "bcmx.h"
     23 
     24 #ifdef  INCLUDE_L3
     25 
     26 char bcmx_cmd_ipmc_usage[] =
     27     "Usages:\n"
     28 #ifdef COMPILER_STRING_CONST_LIMIT
     29     "  ipmc init | add | lookup\n"
     30     "  ipmc test add\n"
     31 #else
     32     "  ipmc init\n"
     33     "         - Initialize BMCX mcast stuff\n"
     34     "  ipmc add [L2Ports=<user-port-list>] [UntagPorts=<user-port-list>]\n"
     35     "         [L3Ports=<user-port-list>] [SrcIP=<IP>] [McIP=<IP>]\n"
     36     "         [CosDst=<COS Value>] [Trunk=<True|False>] [PortTgid=<user-port>]\n"
     37     "         [Vlanid=<id>] [TTL=<ttl>] [CPUDrop=<True|False>]\n"
     38     "         [Replace=<True|False>]\n"
     39     "        - Add IP Multicast address & associated with port(s)\n"
     40     "  ipmc lookup [SrcIP=<IP>] [McIP=<IP>] [Vlanid=<id>]\n"
     41     "        - Lookup an IP Mcast Address entry\n"
     42     "  ipmc test add Ports=<Max. number of ports in the system>\n"
     43     "        - add -> Adds 256 ipmc incremental addresses\n"
     44     "  ipmc egr set [Port=<user-port>] [Mac=<macaddr>] [Vlan=<id>] \n"
     45     "                  [Untag=<True|False>] [Ttl_thresh=<ttl_threshold>]\n"
     46     "        - Set egress IP Multicast configuration regs for a port\n"
     47     "  ipmc v6 add [SrcIP=<IP>] [McIP=<IP>] [L2Ports=<user-port-list>]\n"
     48     "         [UntagPorts=<user-port-list>] [L3Ports=<user-port-list>]\n"
     49     "         [CosDst=<COS Value>] [Trunk=<True|False>] [PortTgid=<user-port>]\n"
     50     "         [Vlanid=<id>] [TTL=<ttl>] [CPUDrop=<True|False>]\n"
     51     "              - Add an IPv6 MCAST entry into ipmc table\n"
     52     "  ipmc v6 del [SrcIP=<IP>] [McIP=<IP>] [Vlanid=<id>]\n"
     53     "        - Delete IPv6 MCAST entry from ipmc table\n"
     54 #endif
     55     ;
     56 
     57 cmd_result_t
     58 bcmx_cmd_ipmc(int unit, args_t *args)
     59 {
     60     char                *subcmd = NULL;
     61     static int          initted = 0;
     62     static sal_mac_addr_t arg_macaddr;
     63     static int          arg_cos_dst = 0,
     64                         arg_vlan = VLAN_ID_DEFAULT;
     65     int                 arg_trunk = 0;
     66     int                 replace = 0;
     67     int                 arg_ttl = 0;
     68     uint32              arg_src_ip = 0;
     69     uint32              arg_mc_ip = 0;
     70     int                 rv = CMD_OK;
     71     int                 i, u_port_num;
     72     int                 arg_max_ports;
     73     parse_table_t       pt;
     74     char                *port_str = NULL;
     75     char                *l2_plist_str = NULL;
     76     char                *l3_plist_str = NULL;
     77     char                *puntag_list_str = NULL;
     78     bcmx_ipmc_addr_t    ipmcxaddr;
     79     char                port_list[256];
     80     bcmx_lplist_t       l2_port_list;     /* L2 Port logical port list*/
     81     bcmx_lplist_t       l3_port_list;     /* L3 logical port list */
     82     bcmx_lplist_t       l2_untag_list;
     83     bcmx_uport_t        uport;
     84     bcmx_lport_t        lport;
     85     int                 count;
     86 
     87     /*
     88      * Initialize MAC address field for the user to the first real
     89      * address which does not conflict
     90      */
     91     if (! initted) {
     92         arg_macaddr[0] = 0;
     93         arg_macaddr[1] = 0;
     94         arg_macaddr[2] = 0;
     95         arg_macaddr[3] = 0;
     96         arg_macaddr[4] = 0;
     97         arg_macaddr[5] = 0;
     98         bcmx_lplist_init(&l2_port_list, 0, 0);
     99         bcmx_lplist_init(&l3_port_list, 0, 0);
    100         bcmx_lplist_init(&l2_untag_list, 0, 0);
    101     }
    102 
    103     if ((subcmd = ARG_GET(args)) == NULL) {
    104         return CMD_USAGE;
    105     }
    106 
    107     if (! sal_strcasecmp(subcmd, "init")) {
    108         rv = bcmx_ipmc_init();
    109 
    110         if (rv < 0) {
    111             cli_out("ERROR: %s\n", bcm_errmsg(rv));
    112             return CMD_FAIL;
    113         }
    114 
    115         return CMD_OK;
    116     }
    117     else if (! sal_strcasecmp(subcmd, "add")) {
    118         parse_table_init(unit, &pt);
    119         parse_table_add(&pt, "L2Ports",      PQ_STRING,
    120                         0, &l2_plist_str, NULL);
    121         parse_table_add(&pt, "UntagPorts",      PQ_STRING,
    122                         0, &puntag_list_str, NULL);
    123         parse_table_add(&pt, "L3Ports",      PQ_STRING,
    124                         0, &l3_plist_str, NULL);
    125         parse_table_add(&pt, "SrcIP",      PQ_DFL|PQ_IP,
    126                         0, &arg_src_ip,NULL);
    127         parse_table_add(&pt, "McIP",      PQ_DFL|PQ_IP,
    128                         0, &arg_mc_ip,NULL);
    129         parse_table_add(&pt, "Vlanid",          PQ_DFL|PQ_INT,
    130                         0, &arg_vlan,       NULL);
    131         parse_table_add(&pt, "CosDst",       PQ_DFL|PQ_INT,
    132                         0, &arg_cos_dst,        NULL);
    133         parse_table_add(&pt, "Trunk",      PQ_DFL|PQ_BOOL,
    134                         0, &arg_trunk,NULL);
    135         parse_table_add(&pt, "PortTgid",   PQ_DFL|PQ_STRING,
    136                         0, &port_str,       NULL);
    137         parse_table_add(&pt, "Replace",      PQ_DFL|PQ_BOOL,
    138                         0, &replace,NULL);
    139 
    140         if (parse_arg_eq(args, &pt) < 0) {
    141             cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args));
    142             parse_arg_eq_done(&pt);
    143             return CMD_FAIL;
    144         }
    145 
    146 	    bcmx_ipmc_addr_t_init(&ipmcxaddr);
    147         ipmcxaddr.s_ip_addr = arg_src_ip;
    148         ipmcxaddr.mc_ip_addr = arg_mc_ip;
    149         ipmcxaddr.vid = arg_vlan;
    150         bcmx_lplist_clear(&ipmcxaddr.l2_ports);
    151         if (bcmx_lplist_parse(&ipmcxaddr.l2_ports, l2_plist_str) < 0) {
    152             sal_printf("%s: Error: could not parse l2 portlist: %s\n",
    153                        ARG_CMD(args), l2_plist_str);
    154             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    155             parse_arg_eq_done(&pt);
    156             return CMD_FAIL;
    157         }
    158         bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports);
    159         if (bcmx_lplist_parse(&ipmcxaddr.l2_untag_ports, puntag_list_str) < 0) {
    160             sal_printf("%s: Error: could not parse untag portlist: %s\n",
    161                        ARG_CMD(args), puntag_list_str);
    162             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    163             parse_arg_eq_done(&pt);
    164             return CMD_FAIL;
    165         }
    166         bcmx_lplist_clear(&ipmcxaddr.l3_ports);
    167         if (bcmx_lplist_parse(&ipmcxaddr.l3_ports, l3_plist_str) < 0) {
    168             sal_printf("%s: Error: could not parse l3 portlist: %s\n",
    169                        ARG_CMD(args), l3_plist_str);
    170             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    171             parse_arg_eq_done(&pt);
    172             return CMD_FAIL;
    173         }
    174         ipmcxaddr.ts = arg_trunk;
    175 
    176         if (arg_trunk == 0) { /* non trunk port */
    177             /* convert user port to logical port */
    178             if (port_str == NULL) {
    179                 sal_printf("%s: Error: port is required if not a trunk port\n",
    180                            ARG_CMD(args));
    181                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    182                 parse_arg_eq_done(&pt);
    183                 return CMD_FAIL;
    184             }
    185             uport = bcmx_uport_parse(port_str, NULL);
    186             lport = bcmx_uport_to_lport(uport);
    187             if (lport == BCMX_NO_SUCH_LPORT) {
    188                 sal_printf("%s: Error: could not parse port: %s\n",
    189                            ARG_CMD(args), port_str);
    190                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    191                 parse_arg_eq_done(&pt);
    192                 return CMD_FAIL;
    193             }
    194             ipmcxaddr.port_tgid = lport;
    195         }
    196         parse_arg_eq_done(&pt);
    197 
    198         ipmcxaddr.cos = arg_cos_dst;
    199         if (replace) {
    200             ipmcxaddr.flags |= BCM_IPMC_REPLACE;
    201         }
    202         rv = bcmx_ipmc_add(&ipmcxaddr);
    203         if (rv < 0) {
    204             cli_out("ERROR: %s\n", bcm_errmsg(rv));
    205             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    206             return CMD_FAIL;
    207         }
    208         bcmx_ipmc_addr_t_free(&ipmcxaddr);
    209         return CMD_OK;
    210     }
    211     else if (! sal_strcasecmp(subcmd, "lookup") || ! sal_strcasecmp(subcmd, "lkup")) {
    212         
    213         /*
    214          * Lookup an arl entry
    215          */
    216         parse_table_init(unit, &pt);
    217         parse_table_add(&pt, "SrcIP",      PQ_DFL|PQ_IP,
    218                         0, &arg_src_ip,NULL);
    219         parse_table_add(&pt, "McIP",      PQ_DFL|PQ_IP,
    220                         0, &arg_mc_ip,NULL);
    221         parse_table_add(&pt, "Vlanid",          PQ_DFL|PQ_HEX,
    222                         0, &arg_vlan,       NULL);
    223 
    224         if (parse_arg_eq(args, &pt) < 0) {
    225             cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args));
    226             parse_arg_eq_done(&pt);
    227             return CMD_FAIL;
    228         }
    229         parse_arg_eq_done(&pt);
    230 
    231         bcmx_ipmc_addr_t_init(&ipmcxaddr);
    232         rv = bcmx_ipmc_find(&ipmcxaddr);
    233 
    234         if (rv < 0) {
    235             cli_out("ERROR: %s\n", bcm_errmsg(rv));
    236             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    237             return CMD_FAIL;
    238         } else { /* Found it.  Display. */
    239             cli_out("SourceIP 0x%x MCastIP 0x%x Vlan %d COS %d\n",
    240                     ipmcxaddr.s_ip_addr, ipmcxaddr.mc_ip_addr,
    241                     ipmcxaddr.vid, ipmcxaddr.cos);
    242             cli_out("l2 uports:");
    243             BCMX_LPLIST_ITER(ipmcxaddr.l2_ports, lport, count) {
    244                 cli_out(" %s", bcmx_lport_to_uport_str(lport));
    245             }
    246             cli_out("\n");
    247             cli_out("l2 untag uports:");
    248             BCMX_LPLIST_ITER(ipmcxaddr.l2_untag_ports, lport, count) {
    249                 cli_out(" %s", bcmx_lport_to_uport_str(lport));
    250             }
    251             cli_out("\n");
    252             cli_out("l3 uports:");
    253             BCMX_LPLIST_ITER(ipmcxaddr.l3_ports, lport, count) {
    254                 cli_out(" %s", bcmx_lport_to_uport_str(lport));
    255             }
    256             cli_out("\n");
    257             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    258             return CMD_OK;
    259         }
    260     }
    261     else if (! sal_strcasecmp(subcmd, "test")) {
    262 
    263         if ((subcmd = ARG_GET(args)) == NULL) {
    264             return CMD_USAGE;
    265         }
    266         if (! sal_strcasecmp(subcmd, "add")) {
    267             parse_table_init(unit, &pt);
    268             parse_table_add(&pt, "Ports",      PQ_DFL|PQ_INT,
    269                             0, &arg_max_ports,NULL);
    270             
    271             if (parse_arg_eq(args, &pt) < 0) {
    272                 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args));
    273                 parse_arg_eq_done(&pt);
    274                 return CMD_FAIL;
    275             }
    276             parse_arg_eq_done(&pt);
    277             arg_mc_ip = 0xe1010100;
    278             arg_src_ip = 0xa010100;
    279 
    280             for (i=0; i<256; i++) {
    281                 
    282                 arg_vlan = 2;
    283                 bcmx_ipmc_addr_t_init(&ipmcxaddr);
    284                 ipmcxaddr.s_ip_addr = arg_src_ip;
    285                 ipmcxaddr.mc_ip_addr = arg_mc_ip;
    286                 ipmcxaddr.vid = arg_vlan;
    287                 u_port_num = i % arg_max_ports;
    288                 sal_sprintf(port_list,"%d,%d,%d,%d",(u_port_num%arg_max_ports)+1,
    289                         ((u_port_num+1)%arg_max_ports)+1,
    290                         ((u_port_num+2)%arg_max_ports)+1,
    291                         ((u_port_num+3)%arg_max_ports)+1);
    292                 bcmx_lplist_clear(&ipmcxaddr.l2_ports);
    293                 if (bcmx_lplist_parse(&ipmcxaddr.l2_ports,
    294                                       port_list) < 0) {
    295                     sal_printf("%s: Error: could not parse portlist: %s\n",
    296                                ARG_CMD(args), port_list);
    297                     bcmx_ipmc_addr_t_free(&ipmcxaddr);
    298                     return CMD_FAIL;
    299                 }
    300                 
    301                 u_port_num = (i+10) % arg_max_ports;
    302                 sal_sprintf(port_list,"%d,%d,%d,%d",(u_port_num%arg_max_ports)+1,
    303                         ((u_port_num+1)%arg_max_ports)+1,
    304                         ((u_port_num+2)%arg_max_ports)+1,
    305                         ((u_port_num+3)%arg_max_ports)+1);
    306                 bcmx_lplist_clear(&ipmcxaddr.l3_ports);
    307                 if (bcmx_lplist_parse(&ipmcxaddr.l3_ports,
    308                                       port_list) < 0) {
    309                     sal_printf("%s: Error: could not parse portlist: %s\n",
    310                                ARG_CMD(args), port_list);
    311                     bcmx_ipmc_addr_t_free(&ipmcxaddr);
    312                     return CMD_FAIL;
    313                 }
    314                 
    315                 bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports);
    316                 
    317                 ipmcxaddr.ts = 0;
    318                 ipmcxaddr.port_tgid = (i % arg_max_ports)+1;
    319                 ipmcxaddr.cos = arg_cos_dst;
    320                 
    321                 rv = bcmx_ipmc_add(&ipmcxaddr);
    322                 if (rv < 0) {
    323                     cli_out("ERROR: %s\n", bcm_errmsg(rv));
    324                     bcmx_ipmc_addr_t_free(&ipmcxaddr);
    325                     return CMD_FAIL;
    326                 }
    327                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    328                 arg_src_ip += 1;
    329                 arg_mc_ip += 1;
    330             }
    331         }
    332         return CMD_OK;
    333     } else if (sal_strcasecmp(subcmd, "egr") == 0) {
    334         int arg_untag;
    335         
    336         if ((subcmd = ARG_GET(args)) == NULL) {
    337             return CMD_FAIL;
    338         }
    339         
    340         if (sal_strcasecmp(subcmd, "set")) {
    341             return CMD_FAIL;
    342         }
    343         
    344         parse_table_init(unit, &pt);
    345         parse_table_add(&pt, "Port", PQ_STRING, 0, &port_str, NULL);
    346         parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, &arg_macaddr, NULL);
    347         parse_table_add(&pt, "Vlan", PQ_DFL | PQ_INT, 0, &arg_vlan, 0);
    348         parse_table_add(&pt, "Untag", PQ_DFL | PQ_INT,
    349                         0, &arg_untag, NULL);
    350         parse_table_add(&pt, "Ttl_thresh", PQ_DFL | PQ_INT, 0,
    351                         &arg_ttl, NULL);
    352         if (!parse_arg_eq(args, &pt)) {
    353             sal_printf("%s: Unknown options: %s\n",
    354                        ARG_CMD(args), ARG_CUR(args));
    355             parse_arg_eq_done(&pt);
    356             return(CMD_FAIL);
    357         }
    358         
    359         uport = bcmx_uport_parse(port_str, NULL);
    360         lport = BCMX_UPORT_TO_LPORT(uport);
    361         if (lport == BCMX_NO_SUCH_LPORT) {
    362             sal_printf("%s: bad port given: %s\n", ARG_CMD(args), port_str);
    363             parse_arg_eq_done(&pt);
    364             return CMD_FAIL;
    365         }
    366         parse_arg_eq_done(&pt);
    367         rv = bcmx_ipmc_egress_port_set(lport, arg_macaddr, arg_untag,
    368                                        arg_vlan, arg_ttl);
    369         if (rv < 0) {
    370             cli_out("\nERROR %s\n", bcm_errmsg(rv));
    371             return CMD_FAIL;
    372         }
    373         return CMD_OK;
    374     }
    375 #if defined(BCM_XGS3_SWITCH_SUPPORT)
    376     else if (sal_strcasecmp(subcmd, "v6") == 0) {
    377         bcm_ip6_t       ip6_addr, sip6_addr;
    378         
    379         if ((subcmd = ARG_GET(args)) == NULL) {
    380             return CMD_FAIL;
    381         }
    382         
    383         if (sal_strcasecmp(subcmd, "add") == 0) {
    384             
    385             parse_table_init(unit, &pt);
    386             parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP6, 0,
    387                             (void *)&sip6_addr, NULL);
    388             parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP6, 0,
    389                             (void *)&ip6_addr, NULL);
    390             parse_table_add(&pt, "L3Ports", PQ_STRING, 0, &l3_plist_str, NULL);
    391             parse_table_add(&pt, "L2Ports", PQ_STRING, 0, &l2_plist_str, NULL);
    392             parse_table_add(&pt, "UntagPorts",      PQ_STRING,
    393                             0, &puntag_list_str, NULL);
    394             parse_table_add(&pt, "Vlanid",          PQ_DFL|PQ_INT,
    395                             0, &arg_vlan,       NULL);
    396             parse_table_add(&pt, "CosDst",       PQ_DFL|PQ_INT,
    397                             0, &arg_cos_dst,        NULL);
    398             parse_table_add(&pt, "Trunk",      PQ_DFL|PQ_BOOL,
    399                             0, &arg_trunk,NULL);
    400             parse_table_add(&pt, "PortTgid", PQ_INT, 0, &u_port_num, 0);
    401             
    402             if (parse_arg_eq(args, &pt) < 0) {
    403                 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args));
    404                 parse_arg_eq_done(&pt);
    405                 return CMD_FAIL;
    406             }
    407             bcmx_ipmc_addr_t_init(&ipmcxaddr);
    408             
    409             sal_memcpy(ipmcxaddr.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN);
    410             sal_memcpy(ipmcxaddr.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
    411             ipmcxaddr.vid = arg_vlan;
    412             
    413             bcmx_lplist_clear(&ipmcxaddr.l2_ports);
    414             if (bcmx_lplist_parse(&ipmcxaddr.l2_ports, l2_plist_str) < 0) {
    415                 sal_printf("%s: Error: could not parse l2 portlist: %s\n",
    416                            ARG_CMD(args), l2_plist_str);
    417                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    418                 parse_arg_eq_done(&pt);
    419                 return CMD_FAIL;
    420             }
    421             bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports);
    422             if (bcmx_lplist_parse(&ipmcxaddr.l2_untag_ports, 
    423                                   puntag_list_str) < 0) {
    424                 sal_printf("%s: Error: could not parse untag portlist: %s\n",
    425                            ARG_CMD(args), puntag_list_str);
    426                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    427                 parse_arg_eq_done(&pt);
    428                 return CMD_FAIL;
    429             }
    430             bcmx_lplist_clear(&ipmcxaddr.l3_ports);
    431             if (bcmx_lplist_parse(&ipmcxaddr.l3_ports, l3_plist_str) < 0) {
    432                 sal_printf("%s: Error: could not parse l3 portlist: %s\n",
    433                            ARG_CMD(args), l3_plist_str);
    434                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    435                 parse_arg_eq_done(&pt);
    436                 return CMD_FAIL;
    437             }
    438             ipmcxaddr.ts = arg_trunk;
    439             
    440             if (arg_trunk == 0) { /* non trunk port */
    441                 ipmcxaddr.port_tgid = u_port_num; 
    442             }
    443             parse_arg_eq_done(&pt);
    444             
    445             ipmcxaddr.cos = arg_cos_dst;
    446             ipmcxaddr.flags |= BCM_IPMC_IP6;
    447             rv = bcmx_ipmc_add(&ipmcxaddr);
    448             if (rv < 0) {
    449                 cli_out("ERROR: %s\n", bcm_errmsg(rv));
    450                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    451                 return CMD_FAIL;
    452             }
    453             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    454             return CMD_OK;
    455         } else if (sal_strcasecmp(subcmd, "del") == 0) {
    456             
    457             parse_table_init(unit, &pt);
    458             parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP6, 0,
    459                             (void *)&sip6_addr, NULL);
    460             parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP6, 0,
    461                             (void *)&ip6_addr, NULL);
    462             parse_table_add(&pt, "Vlanid",          PQ_DFL|PQ_INT,
    463                             0, &arg_vlan,       NULL);
    464 
    465             if (parse_arg_eq(args, &pt) < 0) {
    466                 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args));
    467                 parse_arg_eq_done(&pt);
    468                 return CMD_FAIL;
    469             }
    470             parse_arg_eq_done(&pt);
    471 
    472             bcmx_ipmc_addr_t_init(&ipmcxaddr);
    473                
    474             sal_memcpy(ipmcxaddr.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN);
    475             sal_memcpy(ipmcxaddr.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN);
    476             ipmcxaddr.vid = arg_vlan;
    477             ipmcxaddr.flags |= BCM_IPMC_IP6;
    478             rv = bcmx_ipmc_remove(&ipmcxaddr);
    479             if (rv < 0) {
    480                 cli_out("ERROR: %s\n", bcm_errmsg(rv));
    481                 bcmx_ipmc_addr_t_free(&ipmcxaddr);
    482                 return CMD_FAIL;
    483             }
    484             bcmx_ipmc_addr_t_free(&ipmcxaddr);
    485             return CMD_OK;
    486         }
    487     }
    488 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    489     
    490     else {
    491         return CMD_USAGE;
    492     }
    493     return CMD_FAIL;
    494 }
    495 
    496 #endif  /* INCLUDE_L3 */