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

oam.c (48285B)


      1 /*
      2  * 
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 #include <appl/diag/system.h>
     10 #include <appl/diag/parse.h>
     11 #include <shared/bsl.h>
     12 #include <bcm/error.h>
     13 #include <bcm/oam.h>
     14 #include <bcm_int/esw/port.h>
     15 #include <bcm_int/esw/oam.h>
     16 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
     17 #include <bcm/rx.h>
     18 #include <soc/higig.h>
     19 #endif /* !BCM_ENDURO_SUPPORT || !BCM_ENDURO_SUPPORT*/
     20 
     21 #define CLEAN_UP_AND_RETURN(_result) \
     22     parse_arg_eq_done(&parse_table); \
     23     return (_result);
     24 
     25 #define _isprintable(_c) (((_c) > 32) && ((_c) < 127))
     26 
     27 #define GROUP_LIST_HEADER \
     28     "ID  Name                                             TX_RD CPU_COPY AlarmPri\n" \
     29     "--- ------------------------------------------------ ----- -------- ---------\n"
     30 
     31 #define ENDPOINT_LIST_HEADER \
     32     "ID   Grp Name L Period CLDLO VLAN Mod Port Tr MAC address       PktPri IntPri TLV\n" \
     33     "---- --- ---- - ------ ------ ---- --- ---- -- ----------------- ------ ------ --- \n"
     34 
     35 static int events_on = 0;
     36 
     37 static void print_group_faults(const char *header_string_p, uint32 faults)
     38 {
     39     cli_out("%s: %s %s %s %s\n", header_string_p,
     40             (faults & BCM_OAM_GROUP_FAULT_REMOTE) ? "RDI" : "",
     41             (faults & BCM_OAM_GROUP_FAULT_CCM_TIMEOUT) ? "CCM_TIMEOUT" : "",
     42             (faults & BCM_OAM_GROUP_FAULT_CCM_ERROR) ? "CCM_ERROR" : "",
     43             (faults & BCM_OAM_GROUP_FAULT_CCM_XCON) ? "CCM_XCON" : "");
     44 }
     45 
     46 static int _cmd_esw_oam_group_print(int unit, bcm_oam_group_info_t *group_info_p,
     47     void *user_data)
     48 {
     49     char name_string[BCM_OAM_GROUP_NAME_LENGTH + 1];
     50     int byte_index;
     51     char byte;
     52 
     53     /* Do another get to clear persistent faults */
     54 
     55     group_info_p->clear_persistent_faults =
     56         BCM_OAM_GROUP_FAULT_REMOTE |
     57         BCM_OAM_GROUP_FAULT_CCM_TIMEOUT |
     58         BCM_OAM_GROUP_FAULT_CCM_ERROR |
     59         BCM_OAM_GROUP_FAULT_CCM_XCON;
     60 
     61     bcm_oam_group_get(unit, group_info_p->id, group_info_p);
     62 
     63     for (byte_index = 0; byte_index < BCM_OAM_GROUP_NAME_LENGTH;
     64         ++byte_index)
     65     {
     66         byte = group_info_p->name[byte_index];
     67 
     68         name_string[byte_index] = _isprintable(byte) ? byte : '.';
     69     }
     70 
     71     name_string[byte_index] = 0;
     72 
     73     cli_out("%3d %48s %3c %6c %9d\n", group_info_p->id, name_string,
     74             (group_info_p->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? '*' : ' ',
     75             (group_info_p->flags & BCM_OAM_GROUP_COPY_TO_CPU) ? '*' : ' ',
     76             group_info_p->lowest_alarm_priority);
     77 
     78     if (group_info_p->faults != 0)
     79     {
     80         print_group_faults("           Faults", group_info_p->faults);
     81     }
     82 
     83     if (group_info_p->persistent_faults != 0)
     84     {
     85         print_group_faults("Persistent faults", group_info_p->persistent_faults);
     86     }
     87 
     88     return BCM_E_NONE;
     89 }
     90 
     91 static void print_endpoint_faults(const char *header_string_p,
     92                                   uint32 faults, bcm_oam_endpoint_type_t type)
     93 {
     94     if ((type == bcmOAMEndpointTypeBHHMPLS) ||
     95         (type == bcmOAMEndpointTypeBHHMPLSVccv)||
     96         (type == bcmOAMEndpointTypeBhhSection)||
     97         (type == bcmOAMEndpointTypeBhhSectionInnervlan)||
     98         (type == bcmOAMEndpointTypeBhhSectionOuterVlan)||
     99         (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)) {
    100         cli_out("%s: %s %s %s %s %s %s %s\n", header_string_p,
    101                 (faults & BCM_OAM_BHH_FAULT_CCM_TIMEOUT) ? "CCM_TIMEOUT" : "",
    102                 (faults & BCM_OAM_BHH_FAULT_CCM_RDI) ? "RDI" : "",
    103                 (faults & BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL) ? "MEG_LEVEL" : "",
    104                 (faults & BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID) ? "MEG_ID" : "",
    105                 (faults & BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID) ? "MEP_ID" : "",
    106                 (faults & BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD) ? "CCM_PERIOD" : "",
    107                 (faults & BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY) ? "CCM_PRIORITY" : "");
    108     } else {
    109         cli_out("%s: %s %s %s %s\n", header_string_p,
    110                 (faults & BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT) ? "CCM_TIMEOUT" : "",
    111                 (faults & BCM_OAM_ENDPOINT_FAULT_REMOTE) ? "RDI" : "",
    112                 (faults & BCM_OAM_ENDPOINT_FAULT_PORT_DOWN) ? "PORT_DOWN" : "",
    113                 (faults & BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN) ? "INTERFACE_DOWN" : "");
    114     }
    115 }
    116 
    117 static int _cmd_esw_oam_endpoint_print(int unit,
    118     bcm_oam_endpoint_info_t *endpoint_info_p, void *user_data)
    119 {
    120     int local_tx;
    121     int local_rx;
    122     int is_remote;
    123     bcm_module_t module_id;
    124     bcm_port_t port_id;
    125     bcm_trunk_t trunk_id;
    126     bcm_port_t local_id;
    127     char mac_address_string[MACADDR_STR_LEN];
    128     int rc = BCM_E_NONE;
    129 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    130 
    131     int i;
    132 #endif
    133     /* Do another get to clear persistent faults */
    134 
    135     endpoint_info_p->clear_persistent_faults =
    136         BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT |
    137         BCM_OAM_ENDPOINT_FAULT_REMOTE |
    138         BCM_OAM_ENDPOINT_FAULT_PORT_DOWN |
    139         BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN;
    140 
    141     rc = bcm_oam_endpoint_get(unit, endpoint_info_p->id, endpoint_info_p);
    142     if (BCM_FAILURE(rc)) {  
    143         cli_out("bcm_oam_endpoint_get failure\n");
    144         return rc;
    145     }
    146 
    147     is_remote = endpoint_info_p->flags & BCM_OAM_ENDPOINT_REMOTE;
    148     local_tx = !is_remote && endpoint_info_p->ccm_period > 0;
    149 
    150     local_rx = !is_remote && (endpoint_info_p->flags &
    151         (BCM_OAM_ENDPOINT_CCM_RX | BCM_OAM_ENDPOINT_LOOPBACK |
    152             BCM_OAM_ENDPOINT_DELAY_MEASUREMENT | 
    153             BCM_OAM_ENDPOINT_LOSS_MEASUREMENT |BCM_OAM_ENDPOINT_LINKTRACE));
    154 
    155     cli_out("%4d %3d ", endpoint_info_p->id, endpoint_info_p->group);
    156     
    157     if (is_remote || local_tx)
    158     {
    159         cli_out("%04X ", endpoint_info_p->name);
    160     }
    161     else
    162     {
    163         cli_out("     ");
    164     }
    165    
    166     if ((endpoint_info_p->level >= 0) && 
    167         (endpoint_info_p->level <=7)) {
    168         cli_out("%1d ", endpoint_info_p->level);
    169     }
    170     else
    171     {
    172         cli_out("     ");
    173     }
    174 
    175     if (is_remote || local_tx)
    176     {
    177         cli_out("%6d ", endpoint_info_p->ccm_period);
    178     }
    179     else
    180     {
    181         cli_out("       ");
    182     }
    183 
    184     if (local_rx)
    185     {
    186         cli_out("%c%c%c%c%c ",
    187                 (endpoint_info_p->flags & BCM_OAM_ENDPOINT_CCM_RX) ? '*' : ' ',
    188                 (endpoint_info_p->flags & BCM_OAM_ENDPOINT_LOOPBACK) ? '*' : ' ',
    189                 (endpoint_info_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ?
    190                 '*' : ' ',
    191                 (endpoint_info_p->flags & BCM_OAM_ENDPOINT_LINKTRACE) ?
    192                 '*' : ' ',
    193                 (endpoint_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) ?
    194                 '*' : ' ');
    195     }
    196     else
    197     {
    198         cli_out("     ");
    199     }
    200 
    201     if (endpoint_info_p->vlan != BCM_VLAN_INVALID) {
    202         cli_out("%4d ", endpoint_info_p->vlan);
    203     }
    204     else
    205     {
    206         cli_out("     ");
    207     }
    208 
    209     if (BCM_FAILURE(_bcm_esw_gport_resolve(unit, endpoint_info_p->gport,
    210         &module_id, &port_id, &trunk_id, &local_id)))
    211     {
    212         cli_out("Bad GPORT   ");
    213     }
    214     else if (BCM_GPORT_IS_LOCAL(endpoint_info_p->gport))
    215     {
    216         cli_out("    %4d    ", port_id);
    217     }
    218     else if (BCM_GPORT_IS_MODPORT(endpoint_info_p->gport))
    219     {
    220         cli_out("%3d %4d    ", module_id, port_id);
    221     }
    222     else if (BCM_GPORT_IS_TRUNK(endpoint_info_p->gport))
    223     {
    224         cli_out("         %2d ", trunk_id);
    225     } else if (BCM_GPORT_IS_MIM_PORT(endpoint_info_p->gport) ||
    226                BCM_GPORT_IS_MPLS_PORT(endpoint_info_p->gport)) {
    227         cli_out("0x%8x", endpoint_info_p->gport);
    228     }
    229     else
    230     {
    231         cli_out("            ");
    232     }
    233 
    234     if (local_tx)
    235     {
    236         format_macaddr(mac_address_string, endpoint_info_p->src_mac_address);
    237 
    238         cli_out("%17s %6d %6d %3c\n",
    239                 mac_address_string,
    240                 endpoint_info_p->pkt_pri,
    241                 endpoint_info_p->int_pri,
    242                 (endpoint_info_p->flags & (BCM_OAM_ENDPOINT_PORT_STATE_TX
    243                 | BCM_OAM_ENDPOINT_INTERFACE_STATE_TX) ? '*' : ' '));
    244     }
    245     else
    246     {
    247         cli_out("\n");
    248     }
    249 
    250     if (endpoint_info_p->faults != 0)
    251     {
    252         print_endpoint_faults("           Faults", endpoint_info_p->faults,
    253                               endpoint_info_p->type);
    254     }
    255 
    256     if (endpoint_info_p->persistent_faults != 0)
    257     {
    258         print_endpoint_faults("Persistent faults",
    259             endpoint_info_p->persistent_faults, endpoint_info_p->type);
    260     }
    261 
    262 #if defined(BCM_SABER2_SUPPORT)
    263     if (SOC_IS_SABER2(unit)) {
    264         if (endpoint_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
    265             cli_out("    Priority mapping id: ");
    266             cli_out(" %d ", endpoint_info_p->pri_map_id);
    267             cli_out("\n");
    268         }
    269     } else
    270 #endif /* BCM_SABER2_SUPPORT */
    271 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    272     if (endpoint_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
    273         cli_out("    Priority mapping: ");
    274         for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
    275              cli_out(" %d ", endpoint_info_p->pri_map[i]);
    276         }
    277         cli_out("\n");
    278     }
    279 #endif /* BCM_ENDURO_SUPPORT */
    280 
    281     return BCM_E_NONE;
    282 }
    283 
    284 static int _cmd_esw_oam_group_endpoints_traverse(int unit,
    285     bcm_oam_group_info_t *group_info_p, void *user_data)
    286 {
    287     return bcm_oam_endpoint_traverse(unit, group_info_p->id,
    288         _cmd_esw_oam_endpoint_print, NULL);
    289 }
    290 
    291 static int _cmd_esw_oam_event_handle(int unit, uint32 flags,
    292     bcm_oam_event_type_t event_type, bcm_oam_group_t group,
    293     bcm_oam_endpoint_t endpoint, void *user_data)
    294 {
    295     int group_valid = 0;
    296     int endpoint_valid = 0;
    297     const char *oam_event_string;
    298 
    299     switch (event_type)
    300     {
    301         case bcmOAMEventEndpointPortDown:
    302             oam_event_string = "Port down";
    303             endpoint_valid = 1;
    304             break;
    305 
    306         case bcmOAMEventEndpointPortUp:
    307             oam_event_string = "Port up";
    308             endpoint_valid = 1;
    309             break;
    310 
    311         case bcmOAMEventEndpointInterfaceDown:
    312             oam_event_string = "Interface down";
    313             endpoint_valid = 1;
    314             break;
    315 
    316         case bcmOAMEventEndpointInterfaceUp:
    317             oam_event_string = "Interface up";
    318             endpoint_valid = 1;
    319             break;
    320 
    321         case bcmOAMEventGroupCCMxcon:
    322             oam_event_string = "CCM xcon";
    323             group_valid = 1;
    324             break;
    325 
    326         case bcmOAMEventGroupCCMError:
    327             oam_event_string = "CCM error";
    328             group_valid = 1;
    329             break;
    330 
    331         case bcmOAMEventGroupRemote:
    332             oam_event_string = "Some remote defect";
    333             group_valid = 1;
    334             endpoint_valid = 1;
    335             break;
    336 
    337         case bcmOAMEventGroupCCMTimeout:
    338             oam_event_string = "Some CCM timeout";
    339             group_valid = 1;
    340             endpoint_valid = 1;
    341             break;
    342 
    343         default:
    344             oam_event_string = "Unknown event";
    345     }
    346 
    347     cli_out("OAM event: %s%s", oam_event_string,
    348             (flags & BCM_OAM_EVENT_FLAGS_MULTIPLE) ? " (multiple)" : "");
    349 
    350     if (group_valid)
    351     {
    352         cli_out(" - Group %d", group);
    353     }
    354 
    355     if (endpoint_valid)
    356     {
    357         cli_out(" - Endpoint %d", endpoint);
    358     }
    359 
    360     cli_out("\n");
    361 
    362     return BCM_E_NONE;
    363 }
    364 
    365 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    366 static int 
    367 _cmd_esw_oam_tx(int unit, int flags, bcm_gport_t gport_dst, bcm_mac_t *mac_dst,
    368  bcm_mac_t *mac_src, bcm_oam_endpoint_info_t *endpoint_info)
    369 {
    370     bcm_pkt_t pkt;
    371     enet_hdr_t *ep = NULL;
    372     oam_hdr_t *op = NULL;
    373     int vp = 0;        
    374     int rv = 0;
    375     bcm_module_t module_id, dst_module_id;
    376     bcm_port_t port_id, dst_port_id;
    377     bcm_trunk_t trunk_id, dst_trunk_id;
    378     int local_id, dst_local_id;
    379     soc_higig_hdr_t *xgh = (soc_higig_hdr_t *)pkt._higig;
    380 
    381     sal_memset(&pkt, 0, sizeof(bcm_pkt_t));
    382     
    383     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, endpoint_info->gport,
    384         &module_id, &port_id, &trunk_id, &local_id));
    385 
    386     if (BCM_GPORT_IS_MIM_PORT(endpoint_info->gport) ||
    387         BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
    388         vp = 1;
    389     }
    390 
    391     if ((endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) ||
    392          BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
    393         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport_dst,
    394             &dst_module_id, &dst_port_id, &dst_trunk_id, &dst_local_id));
    395     }
    396 
    397     sal_memset(xgh, 0, sizeof(pkt._higig));
    398     soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG2_START);
    399     soc_higig_field_set(unit, xgh, HG_opcode, SOC_HIGIG_OP_UC);
    400     soc_higig_field_set(unit, xgh, HG_cos, 0x7);
    401     
    402     if (vp) {
    403         soc_higig_field_set(unit, xgh, HG_ppd_type, 0x2);
    404         soc_higig_field_set(unit, xgh, HG_fwd_type, 0x4);
    405         soc_higig_field_set(unit, xgh, HG_multipoint, 0x0);
    406         soc_higig_field_set(unit, xgh, HG_dst_type, 0);
    407             soc_higig_field_set(unit, xgh, HG_src_type, 0);
    408         if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
    409             soc_higig_field_set(unit, xgh, HG_dst_vp, dst_local_id);
    410             /* coverity[copy_paste_error : FALSE] */
    411             soc_higig_field_set(unit, xgh, HG_src_vp, local_id);
    412         } else {
    413             soc_higig_field_set(unit, xgh, HG_dst_vp, local_id);
    414             soc_higig_field_set(unit, xgh, HG_src_vp, local_id);
    415         }
    416     } else {
    417         soc_higig_field_set(unit, xgh, HG_ppd_type, 0x0);
    418         soc_higig_field_set(unit, xgh, HG_vlan_tag, endpoint_info->vlan);
    419         if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) {
    420             soc_higig_field_set(unit, xgh, HG_dst_mod, dst_module_id);
    421             soc_higig_field_set(unit, xgh, HG_dst_port, dst_port_id);
    422             if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
    423                 soc_higig_field_set(unit, xgh, HG_tgid, trunk_id);
    424                 soc_higig_field_set(unit, xgh, HG_src_t, 1);
    425             } else {
    426                 soc_higig_field_set(unit, xgh, HG_src_mod, module_id);
    427                 soc_higig_field_set(unit, xgh, HG_src_port, port_id);
    428             }
    429         } else {
    430             if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
    431                 soc_higig_field_set(unit, xgh, HG_dst_mod, dst_module_id);
    432                 soc_higig_field_set(unit, xgh, HG_dst_port, dst_port_id);
    433                 soc_higig_field_set(unit, xgh, HG_src_mod, dst_module_id);
    434                 soc_higig_field_set(unit, xgh, HG_src_port, 0);
    435             } else {
    436                 soc_higig_field_set(unit, xgh, HG_dst_mod, module_id);
    437                 soc_higig_field_set(unit, xgh, HG_dst_port, port_id);
    438                 soc_higig_field_set(unit, xgh, HG_src_mod, module_id);
    439                 soc_higig_field_set(unit, xgh, HG_src_port, 0);
    440             }
    441         }
    442     }
    443 
    444     pkt.alloc_ptr = (uint8 *)soc_cm_salloc(unit, 128, "TX");        
    445     if (pkt.alloc_ptr == NULL) {        
    446         cli_out("WARNING: Could not alloc tx buffer. Memory error.\n");    
    447         return (BCM_E_MEMORY);
    448     } else {        
    449         pkt._pkt_data.data = pkt.alloc_ptr;        
    450         pkt.pkt_data = &pkt._pkt_data;        
    451         pkt.blk_count = 1;        
    452         pkt._pkt_data.len = 128;    
    453     }        
    454 
    455     /* setup the packet */    
    456     pkt.flags &= ~BCM_TX_CRC_FLD;    
    457     pkt.flags |= BCM_TX_CRC_REGEN; 
    458     pkt.flags |= BCM_TX_HG_READY | BCM_TX_ETHER;
    459     
    460     sal_memset(pkt.pkt_data[0].data, 0, pkt.pkt_data[0].len);        
    461     ep = (enet_hdr_t *)(pkt.pkt_data[0].data);
    462     
    463     ENET_SET_MACADDR(ep->en_dhost, mac_dst);    
    464     ENET_SET_MACADDR(ep->en_shost, mac_src);
    465     
    466     ep->en_tag_tpid = bcm_htons(0x8100);
    467     ep->en_tag_ctrl = bcm_htons(VLAN_CTRL(5, 0, endpoint_info->vlan));
    468     ep->en_tag_len  = bcm_htons(0x8902);
    469 
    470     op = (oam_hdr_t *)(&ep->en_snap_dsap);
    471     op->mdl_ver = (endpoint_info->level << 5);
    472     op->flags = 0;
    473     if (flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) {
    474         op->opcode = 43;
    475         op->first_tlvoffset = 12;
    476     } else {
    477         op->opcode = 47;
    478         op->first_tlvoffset = 32;
    479     }
    480 
    481     if ((rv = bcm_tx(unit, &pkt, NULL)) != BCM_E_NONE) {        
    482         LOG_ERROR(BSL_LS_SOC_COMMON,
    483                   (BSL_META_U(unit,
    484                               "bcm_tx failed: Unit %d: %s\n"),                   
    485                    unit, bcm_errmsg(rv)));
    486     }
    487 
    488     soc_cm_sfree(unit, pkt.alloc_ptr);
    489     return (rv);
    490 }
    491 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    492 
    493 char cmd_esw_oam_usage[] = 
    494 #ifdef COMPILER_STRING_CONST_LIMIT
    495     "Usage: oam <option> [args...]\n"
    496 #else
    497     "\n"
    498     "  init\n"
    499     "  group add [ID=<id>] Name=<name> [RemoteDefect]\n"
    500     "      [CopyToCpu=true|false] [LowestAlarmPri=<0-6>]\n"
    501     "       - Create a Maintenance Association Group.\n"
    502     "  group replace ID=<id> Name=<name> [RemoteDefect]\n"
    503     "      [CopyToCpu=true|false] [LowestAlarmPri=<0-6>]\n"
    504     "       - Re-configure an existing Maintenance Association Group.\n"
    505     "  group delete <id>\n"
    506     "       - Destory a Maintenance Association Group.\n"
    507     "  group show\n"
    508     "       - Display all Maintenance Association Groups.\n"
    509     "  endpoint add Group=<group_id> [ID=<id>]\n"
    510     "      [Remote] [CCM] [LB] [DM] [LM] [LT] [PBBTE] [UpMEP]\n"
    511     "      Name=name Level=<level> PERiod=<period> Vlan=<vlan>\n"
    512     "      Port=<port>|ModPort=<modid.port>|TrunkGroupId=<tid>\n"
    513     "      TrunkIndex=<port_index>*\n"
    514     "      [SrcMACaddress=<mac>] [DstMACaddress=<mac>]\n"
    515     "      [PktPri=<pri>] [IntPri=<int_pri>]\n"
    516     "      [TLV] [PortTlv=<1|2>] [IntfTlv=<1-7>]\n"
    517 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    518     "      [P0=#] [P1=#]\n"
    519 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    520 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    521     "      [OpcodeFlags=<flags>] [CPUPri=<cpu_pri>]\n"
    522     "      (*must be specified if TrunkGroupId is set)\n"
    523     "       - Create a Maintenance Endpoint.\n"
    524 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    525     "  endpoint replace Group=<group_id> [ID=<id>]\n"
    526     "      [Remote] [CCM] [LB] [DM] [LM] [LT] [PBBTE] [UpMEP]\n"
    527     "      Name=name Level=<level> PERiod=<period> Vlan=<vlan>\n"
    528     "      Port=<port>|ModPort=<modid.port>|TrunkGroupId=<tid>\n"
    529     "      TrunkIndex=<port_index>*\n"
    530     "      [SrcMACaddress=<mac>] [DstMACaddress=<mac>]\n"
    531     "      [PktPri=<pri>] [IntPri=<int_pri>]\n"
    532     "      [TLV] [PortTlv=<1|2>] [IntfTlv=<1-7>]\n"
    533 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    534     "      [P0=#] [P1=#]\n"
    535 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    536 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    537     "      [OpcodeFlags=<flags>] [CPUPri=<cpu_pri>]\n"
    538     "      (*must be specified if TrunkGroupId is set)\n"
    539     "       - Re-configure an existing Maintenance Endpoint.\n"
    540 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    541     "  endpoint delete <id>\n"
    542     "       - Destroy a Maintenance Endpoint.\n"
    543     "  endpoint show\n"
    544     "       - Display all Maintenance Endpoints.\n"
    545     "  events [on|off]\n"
    546     "       - Register for events notification.\n"
    547 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    548     "  tx ID=<endpointid> [DM] [LM] [DstPort=<port>]\n"
    549     "      [DstMACaddress=<mac>] [SrcMACaddress=<mac>\n"
    550     "       - Transmit LM or DM packets.\n"
    551 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
    552 #endif
    553     ;
    554 
    555 cmd_result_t cmd_esw_oam(int unit, args_t *args)
    556 {
    557     char *arg_string_p = NULL;
    558     parse_table_t parse_table;
    559     bcm_oam_group_info_t group_info;
    560     bcm_oam_endpoint_info_t endpoint_info;
    561     int remote_defect = 0;
    562     char *name_string_p = NULL;
    563     int is_remote = 0;
    564     int local_tx;
    565     int rx_ccm = 0;
    566     int rx_lb = 0;
    567     int rx_lm = 0;
    568     int rx_dm = 0;
    569     int rx_lt = 0;
    570     int pbbte = 0;
    571     int up_mep = 0;
    572     int endpoint_name;
    573     int level;
    574     int ccm_period;
    575     int vlan;
    576     bcm_port_t port;
    577     bcm_mod_port_t modport = {-1, -1};
    578     int trunk_id;
    579     int pkt_pri;
    580     int int_pri;
    581     bcm_oam_event_types_t event_types = {{0}};
    582     int result;
    583     int copy_to_cpu = 0;
    584     int lowest_alarm_priority = 0;
    585     int port_tlv = 0;
    586     int intf_tlv = 0;
    587     int tlv = 0;
    588 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    589     int i, pri_map[BCM_OAM_INTPRI_MAX];
    590     bcm_gport_t gport_dst = BCM_GPORT_INVALID;
    591     bcm_mac_t mac_src ={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
    592     bcm_mac_t mac_dst ={ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
    593 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    594 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    595     int cpu_pri;
    596     uint32 opcode_flags = 0;
    597 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
    598     int trunk_index = _BCM_OAM_INVALID_INDEX;
    599 
    600     arg_string_p = ARG_GET(args);
    601 
    602     if (arg_string_p == NULL)
    603     {
    604         return CMD_USAGE;
    605     }
    606 
    607     if (!sh_check_attached(ARG_CMD(args), unit))
    608     {
    609         return CMD_FAIL;
    610     }
    611 
    612     if (sal_strcasecmp(arg_string_p, "init") == 0)
    613     {
    614         result = bcm_oam_init(unit);
    615 
    616         if (BCM_FAILURE(result))
    617         {
    618             cli_out("Command failed.  %s.\n", bcm_errmsg(result));
    619 
    620             return CMD_FAIL;
    621         }
    622 
    623         cli_out("OAM module initialized.\n");
    624     }
    625     else if (sal_strcasecmp(arg_string_p, "group") == 0)
    626     {
    627 		/* BCM.0> oam group ... */
    628         arg_string_p = ARG_GET(args);
    629 
    630 		/* BCM.0> oam group show */
    631         if (arg_string_p == NULL ||
    632             sal_strcasecmp(arg_string_p, "show") == 0)
    633         {
    634             cli_out(GROUP_LIST_HEADER);
    635 
    636             if (BCM_FAILURE(bcm_oam_group_traverse(unit,
    637                 _cmd_esw_oam_group_print, NULL)))
    638             {
    639                 return CMD_FAIL;
    640             }
    641         }
    642         else if (sal_strcasecmp(arg_string_p, "delete") == 0)
    643         {
    644             if (ARG_CNT(args) <= 0) {
    645                 cli_out("MISSING GROUP ID\n");
    646                 return CMD_FAIL;
    647             }
    648 
    649             /* BCM.0> oam group delete ... */
    650             if (BCM_FAILURE(bcm_oam_group_destroy(unit,
    651                 parse_integer(ARG_GET(args)))))
    652             {
    653                 return CMD_FAIL;
    654             }
    655         }
    656         else
    657         {
    658 			/* BCM.0> oam group add ... */
    659 			/* BCM.0> oam group replace ... */
    660             bcm_oam_group_info_t_init(&group_info);
    661 
    662             if (sal_strcasecmp(arg_string_p, "replace") == 0)
    663             {
    664                 group_info.flags |= BCM_OAM_GROUP_REPLACE;
    665             }
    666             else if (sal_strcasecmp(arg_string_p, "add") != 0)
    667             {
    668                 cli_out("Invalid OAM group command: %s\n", arg_string_p);
    669 
    670                 return CMD_FAIL;
    671             }
    672 
    673             parse_table_init(unit, &parse_table);
    674 
    675             parse_table_add(&parse_table, "ID", PQ_INT,
    676                 (void *) BCM_OAM_GROUP_INVALID, &group_info.id, NULL);
    677 
    678             parse_table_add(&parse_table, "Name", PQ_STRING | PQ_DFL, 0,
    679                 &name_string_p, NULL);
    680 
    681             parse_table_add(&parse_table, "RemoteDefect",
    682                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    683                 &remote_defect, NULL);
    684 
    685 			parse_table_add(&parse_table, "CopyTocpu", PQ_DFL | PQ_BOOL, 0,
    686                 &copy_to_cpu, NULL);
    687 		
    688     		parse_table_add(&parse_table, "LowestAlarmPri", PQ_DFL | PQ_INT,
    689 								0, &lowest_alarm_priority, 0);
    690 
    691             if (parse_arg_eq(args, &parse_table) < 0 || ARG_CNT(args) > 0)
    692             {
    693                 cli_out("Invalid option: %s\n", ARG_CUR(args));
    694 
    695                 CLEAN_UP_AND_RETURN(CMD_FAIL);
    696             }
    697 
    698             if (group_info.id != BCM_OAM_GROUP_INVALID)
    699             {
    700                 group_info.flags |= BCM_OAM_GROUP_WITH_ID;
    701             }
    702 
    703             if (name_string_p == NULL)
    704             {
    705                 cli_out("A group name is required.\n");
    706 
    707                 CLEAN_UP_AND_RETURN(CMD_FAIL);
    708             }
    709 
    710             sal_strncpy((char *)group_info.name, name_string_p,
    711                         BCM_OAM_GROUP_NAME_LENGTH - 1);
    712 
    713             if (remote_defect)
    714             {
    715                 group_info.flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX;
    716             }
    717 
    718 			if (copy_to_cpu) 
    719 			{
    720                 group_info.flags |= BCM_OAM_GROUP_COPY_TO_CPU;
    721 			}
    722 
    723 			switch (lowest_alarm_priority) {
    724 				case 0:
    725                 	group_info.lowest_alarm_priority =
    726 							bcmOAMGroupFaultAlarmPriorityDefectsAll;
    727 					break;
    728 				case 1:
    729                 	group_info.lowest_alarm_priority =
    730 							bcmOAMGroupFaultAlarmPriorityDefectRDICCM;
    731 					break;
    732 				case 2:
    733                 	group_info.lowest_alarm_priority =
    734 							bcmOAMGroupFaultAlarmPriorityDefectMACStatus;
    735 					break;
    736 				case 3:
    737                 	group_info.lowest_alarm_priority =
    738 							bcmOAMGroupFaultAlarmPriorityDefectRemoteCCM;
    739 					break;
    740 				case 4:
    741                 	group_info.lowest_alarm_priority =
    742 							bcmOAMGroupFaultAlarmPriorityDefectErrorCCM;
    743 					break;
    744 				case 5:
    745                 	group_info.lowest_alarm_priority =
    746 							bcmOAMGroupFaultAlarmPriorityDefectXconCCM;
    747 					break;
    748 				case 6:
    749                 	group_info.lowest_alarm_priority =
    750 							bcmOAMGroupFaultAlarmPriorityDefectsNone;
    751 					break;
    752 				default:
    753                 	group_info.lowest_alarm_priority =
    754 							bcmOAMGroupFaultAlarmPriorityDefectsAll;
    755 			}
    756 
    757             result = bcm_oam_group_create(unit, &group_info);
    758 
    759             if (BCM_FAILURE(result))
    760             {
    761                 cli_out("Command failed.  %s.\n", bcm_errmsg(result));
    762 
    763                 CLEAN_UP_AND_RETURN(CMD_FAIL);
    764             }
    765 
    766             parse_arg_eq_done(&parse_table);
    767             
    768             cli_out("OAM group %d created.\n", group_info.id);
    769         }
    770     }
    771 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    772     else if (sal_strcasecmp(arg_string_p, "tx") == 0)
    773     {    
    774         parse_table_init(unit, &parse_table);
    775 
    776         parse_table_add(&parse_table, "ID", PQ_INT,
    777             (void *) BCM_OAM_GROUP_INVALID, &endpoint_info.id, NULL);
    778 
    779         parse_table_add(&parse_table, "DM",
    780             PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    781             &rx_dm, NULL);
    782 
    783         parse_table_add(&parse_table, "LM",
    784             PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    785             &rx_lm, NULL);
    786 
    787         parse_table_add(&parse_table, "DstPort", PQ_PORT, (void *)-1, &port,
    788                 NULL);
    789 
    790         parse_table_add(&parse_table, "DstMACaddress", PQ_MAC | PQ_DFL, 0,
    791                 &mac_dst, NULL);
    792 
    793         parse_table_add(&parse_table, "SrcMACaddress", PQ_MAC | PQ_DFL, 0,
    794                 &mac_src, NULL);
    795         
    796         if (parse_arg_eq(args, &parse_table) < 0 || ARG_CNT(args) > 0)
    797         {
    798             cli_out("Invalid option: %s\n", ARG_CUR(args));
    799 
    800             CLEAN_UP_AND_RETURN(CMD_FAIL);
    801         }
    802 
    803         result = bcm_oam_endpoint_get(unit, endpoint_info.id, &endpoint_info);
    804         
    805         if (BCM_FAILURE(result))
    806         {
    807             cli_out("Command failed.  %s.\n", bcm_errmsg(result));
    808         
    809             CLEAN_UP_AND_RETURN(CMD_FAIL);
    810         }
    811         
    812         if (!rx_dm && !rx_lm) {
    813             
    814             cli_out("DM or LM is required.\n");
    815 
    816             CLEAN_UP_AND_RETURN(CMD_FAIL);
    817         }
    818 
    819         if (endpoint_info.flags & BCM_OAM_ENDPOINT_UP_FACING) {
    820             if (port != -1) {
    821                 if (BCM_GPORT_IS_MIM_PORT(port) || BCM_GPORT_IS_MPLS_PORT(port)) {
    822                     gport_dst = port;
    823                 } else {
    824                     BCM_GPORT_LOCAL_SET(gport_dst, port);
    825                 }
    826             } else {
    827                 cli_out("Destination port is required for UP MEP.\n");
    828                 CLEAN_UP_AND_RETURN(CMD_FAIL);
    829             }
    830         } else if (BCM_GPORT_IS_TRUNK(endpoint_info.gport)) {
    831             if (port != -1) {
    832                 BCM_GPORT_LOCAL_SET(gport_dst, port);
    833             } else {
    834                 cli_out("Destination port is required for down MEP created on TRUNK.\n");
    835                 CLEAN_UP_AND_RETURN(CMD_FAIL);
    836             }
    837         }
    838 
    839         if (rx_dm) {
    840             pbbte |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
    841         } else {
    842             pbbte |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
    843         }
    844 
    845         result = _cmd_esw_oam_tx(unit, pbbte, gport_dst,
    846                                  &mac_dst, &mac_src, &endpoint_info);
    847         if (BCM_FAILURE(result)) {
    848             cli_out("Command failed.  %s.\n", bcm_errmsg(result));
    849             CLEAN_UP_AND_RETURN(CMD_FAIL);
    850         }
    851         parse_arg_eq_done(&parse_table);
    852     }
    853 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
    854 
    855     /* oam endpoint .... */
    856     else if (sal_strcasecmp(arg_string_p, "endpoint") == 0)
    857     {
    858         arg_string_p = ARG_GET(args);
    859 
    860         /* oam endpoint show .... */
    861         if (arg_string_p == NULL ||
    862             sal_strcasecmp(arg_string_p, "show") == 0)
    863         {
    864             
    865             cli_out(ENDPOINT_LIST_HEADER);
    866 
    867             if (BCM_FAILURE(bcm_oam_group_traverse(unit,
    868                 _cmd_esw_oam_group_endpoints_traverse, NULL)))
    869             {
    870                 return CMD_FAIL;
    871             }
    872         }
    873 
    874         /* oam endpoint delete .... */
    875         else if (sal_strcasecmp(arg_string_p, "delete") == 0)
    876         {
    877             if (ARG_CNT(args) <= 0) {
    878                 cli_out("MISSING ENDPOINT ID\n");
    879                 return CMD_FAIL;
    880             }
    881 
    882             result = bcm_oam_endpoint_destroy(unit,
    883                 parse_integer(ARG_GET(args)));
    884 
    885             if (BCM_FAILURE(result))
    886             {
    887                 cli_out("Command failed. %s\n", bcm_errmsg(result));
    888 
    889                 return CMD_FAIL;
    890             }
    891         }
    892         else
    893         {
    894             bcm_oam_endpoint_info_t_init(&endpoint_info);
    895 
    896             /* oam endpoint replace .... */
    897             if (sal_strcasecmp(arg_string_p, "replace") == 0)
    898             {
    899                 endpoint_info.flags |= BCM_OAM_ENDPOINT_REPLACE;
    900             }
    901 
    902             /* oam endpoint add .... */
    903             else if (sal_strcasecmp(arg_string_p, "add") != 0)
    904             {
    905                 cli_out("Invalid OAM endpoint command: %s\n", arg_string_p);
    906 
    907                 return CMD_FAIL;
    908             }
    909             
    910             parse_table_init(unit, &parse_table);
    911 
    912             parse_table_add(&parse_table, "Group", PQ_INT, (void *) -1,
    913                 &endpoint_info.group, NULL);
    914 
    915             parse_table_add(&parse_table, "ID", PQ_INT,
    916                 (void *) BCM_OAM_ENDPOINT_INVALID, &endpoint_info.id, NULL);
    917 
    918             parse_table_add(&parse_table, "Remote",
    919                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    920                 &is_remote, NULL);
    921 
    922             parse_table_add(&parse_table, "CCM",
    923                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    924                 &rx_ccm, NULL);
    925 
    926             parse_table_add(&parse_table, "LB",
    927                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    928                 &rx_lb, NULL);
    929 
    930             parse_table_add(&parse_table, "DM",
    931                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    932                 &rx_dm, NULL);
    933 
    934             parse_table_add(&parse_table, "LM",
    935                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    936                 &rx_lm, NULL);
    937 
    938             parse_table_add(&parse_table, "LT",
    939                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    940                 &rx_lt, NULL);
    941 
    942             parse_table_add(&parse_table, "PBBTE",
    943                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    944                 &pbbte, NULL);
    945 
    946             parse_table_add(&parse_table, "UpMEP",
    947                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
    948                 &up_mep, NULL);
    949 
    950 
    951             /* Needed for remote and local tx, not for local rx */
    952 
    953             parse_table_add(&parse_table, "Name", PQ_HEX, (void *) -1,
    954                 &endpoint_name, NULL);
    955 
    956             /* Needed for all types */
    957 
    958             parse_table_add(&parse_table, "Level", PQ_INT, (void *) -1,
    959                 &level, NULL);
    960 
    961             /* Needed for remote and local tx, not for local rx */
    962 
    963             parse_table_add(&parse_table, "PERiod", PQ_INT, (void *) -1,
    964                 &ccm_period, NULL);
    965 
    966             /* Needed for all types */
    967 
    968             parse_table_add(&parse_table, "Vlan", PQ_INT,
    969                 (void *) BCM_VLAN_INVALID, &vlan, NULL);
    970 
    971             parse_table_add(&parse_table, "Port", PQ_PORT, (void *) -1, &port,
    972                 NULL);
    973 
    974             parse_table_add(&parse_table, "ModPort", PQ_MOD_PORT | PQ_DFL, 0,
    975                 &modport, NULL);
    976 
    977             parse_table_add(&parse_table, "TrunkGroupId", PQ_INT,
    978                 (void *) BCM_TRUNK_INVALID, &trunk_id, NULL);
    979             
    980             parse_table_add(&parse_table, "TrunkIndex", PQ_INT,
    981                 (void *) -1, &trunk_index, NULL);
    982 
    983             /* Needed for local tx, not remote or local rx */
    984 
    985             parse_table_add(&parse_table, "SrcMACaddress", PQ_MAC | PQ_DFL, 0,
    986                 &endpoint_info.src_mac_address, NULL);
    987 
    988             parse_table_add(&parse_table, "DstMACaddress", PQ_MAC | PQ_DFL, 0,
    989                 &endpoint_info.dst_mac_address, NULL);
    990 
    991             /* Needed for local tx, not remote or local rx */
    992 
    993             parse_table_add(&parse_table, "PktPri", PQ_INT, 0, &pkt_pri,
    994                 NULL);
    995 
    996             /* Needed for local tx, not remote or local rx */
    997 
    998             parse_table_add(&parse_table, "IntPri", PQ_INT, 0, &int_pri,
    999                 NULL);
   1000 
   1001             parse_table_add(&parse_table, "TLV",
   1002                 PQ_NO_EQ_OPT | PQ_DFL | PQ_BOOL, 0,
   1003                 &tlv, NULL);
   1004 
   1005             /* Insert port status in transmitted CCM PDU. */
   1006             parse_table_add(&parse_table, "PortTlv", PQ_INT, (void *) 0,
   1007                 &port_tlv, NULL);
   1008 
   1009             /* Insert interface status in transmitted CCM PDU. */
   1010             parse_table_add(&parse_table, "IntfTlv", PQ_INT, (void *) 0,
   1011                 &intf_tlv, NULL);
   1012 
   1013 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1014             sal_memset(pri_map, 0, BCM_OAM_INTPRI_MAX*sizeof(int));
   1015             /* Priority mapping for LM counter index */
   1016             parse_table_add(&parse_table, "P0", PQ_INT,
   1017                 (void *)( 0), &pri_map[0], NULL);
   1018             parse_table_add(&parse_table, "P1", PQ_INT,
   1019                 (void *)( 0), &pri_map[1], NULL);
   1020             parse_table_add(&parse_table, "P2", PQ_INT,
   1021                 (void *)( 0), &pri_map[2], NULL);
   1022             parse_table_add(&parse_table, "P3", PQ_INT,
   1023                 (void *)( 0), &pri_map[3], NULL);
   1024             parse_table_add(&parse_table, "P4", PQ_INT,
   1025                 (void *)( 0), &pri_map[4], NULL);
   1026             parse_table_add(&parse_table, "P5", PQ_INT,
   1027                 (void *)( 0), &pri_map[5], NULL);
   1028             parse_table_add(&parse_table, "P6", PQ_INT,
   1029                 (void *)( 0), &pri_map[6], NULL);
   1030             parse_table_add(&parse_table, "P7", PQ_INT,
   1031                 (void *)( 0), &pri_map[7], NULL);
   1032             parse_table_add(&parse_table, "P8", PQ_INT,
   1033                 (void *)( 0), &pri_map[8], NULL);
   1034             parse_table_add(&parse_table, "P9", PQ_INT,
   1035                 (void *)( 0), &pri_map[9], NULL);
   1036             parse_table_add(&parse_table, "P10", PQ_INT,
   1037                 (void *)( 0), &pri_map[10], NULL);
   1038             parse_table_add(&parse_table, "P11", PQ_INT,
   1039                 (void *)( 0), &pri_map[11], NULL);
   1040             parse_table_add(&parse_table, "P12", PQ_INT,
   1041                 (void *)( 0), &pri_map[12], NULL);
   1042             parse_table_add(&parse_table, "P13", PQ_INT,
   1043                 (void *)( 0), &pri_map[13], NULL);
   1044             parse_table_add(&parse_table, "P14", PQ_INT,
   1045                 (void *)( 0), &pri_map[14], NULL);
   1046             parse_table_add(&parse_table, "P15", PQ_INT,
   1047                 (void *)( 0), &pri_map[15], NULL);
   1048 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
   1049 
   1050 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1051             parse_table_add(&parse_table, "OpcodeFlags", PQ_HEX, (void *) (0),
   1052                                           &opcode_flags, NULL);
   1053 
   1054             parse_table_add(&parse_table, "CPUPri", PQ_INT, 0, &cpu_pri,
   1055                                           NULL);
   1056 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
   1057 
   1058             if (parse_arg_eq(args, &parse_table) < 0 || ARG_CNT(args) > 0)
   1059             {
   1060                 cli_out("Invalid option: %s\n", ARG_CUR(args));
   1061 
   1062                 parse_arg_eq_done(&parse_table);
   1063 
   1064                 return CMD_FAIL;
   1065             }
   1066 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1067             for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) {
   1068                 endpoint_info.pri_map[i] = (uint8)pri_map[i];
   1069             }
   1070 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
   1071 
   1072             /* Insert TLV in CCM PDU. */
   1073             if (tlv) {
   1074                 endpoint_info.flags |= (BCM_OAM_ENDPOINT_PORT_STATE_TX
   1075                                         | BCM_OAM_ENDPOINT_INTERFACE_STATE_TX);
   1076             }
   1077 
   1078             /* Update port TLV status value. */
   1079             if (port_tlv) {
   1080                 endpoint_info.port_state = port_tlv;
   1081                 endpoint_info.flags |= BCM_OAM_ENDPOINT_PORT_STATE_UPDATE;
   1082             }
   1083 
   1084             /* Update interface TLV status value. */
   1085             if (intf_tlv) {
   1086                 endpoint_info.interface_state = intf_tlv;
   1087                 endpoint_info.flags |= BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE;
   1088             }
   1089 
   1090             local_tx = !is_remote && (ccm_period > 0);
   1091 
   1092             if (endpoint_info.id != BCM_OAM_ENDPOINT_INVALID)
   1093             {
   1094                 endpoint_info.flags |= BCM_OAM_ENDPOINT_WITH_ID;
   1095             }
   1096 
   1097             /* Check for parameters needed for all types */
   1098 
   1099             if (endpoint_info.group < 0)
   1100             {
   1101                 cli_out("A group is required.\n");
   1102 
   1103                 CLEAN_UP_AND_RETURN(CMD_FAIL);
   1104             }
   1105 
   1106             if ((level < 0) && (!is_remote))
   1107             {
   1108                 cli_out("A level is required.\n");
   1109 
   1110                 CLEAN_UP_AND_RETURN(CMD_FAIL);
   1111             }
   1112 
   1113             if ((vlan == BCM_VLAN_INVALID) && (!is_remote))
   1114             {
   1115                 cli_out("A VLAN is required.\n");
   1116 
   1117                 CLEAN_UP_AND_RETURN(CMD_FAIL);
   1118             }
   1119 
   1120             if (endpoint_name < 0)
   1121             {
   1122                 cli_out("An endpoint name is required.\n");
   1123 
   1124                 CLEAN_UP_AND_RETURN(CMD_FAIL);
   1125             }
   1126 
   1127             if (modport.port != -1)
   1128             {
   1129                 BCM_GPORT_MODPORT_SET(endpoint_info.gport, modport.mod,
   1130                     modport.port);
   1131 
   1132                 endpoint_info.trunk_index = _BCM_OAM_INVALID_INDEX;
   1133             }
   1134             else if (port != -1)
   1135             {
   1136                 if (BCM_GPORT_IS_MIM_PORT(port) || BCM_GPORT_IS_MPLS_PORT(port)) {
   1137                     endpoint_info.gport = port;
   1138                 } else {
   1139                     BCM_GPORT_LOCAL_SET(endpoint_info.gport, port);
   1140                 }
   1141 
   1142                 endpoint_info.trunk_index = _BCM_OAM_INVALID_INDEX;
   1143             }
   1144             else if (trunk_id != BCM_TRUNK_INVALID)
   1145             {
   1146                 /* 
   1147                  * Trunk index value is required to determine the
   1148                  * designation port for Tx.
   1149                  */
   1150                 if ((1 == local_tx) && (-1 == trunk_index)) {
   1151 
   1152                     cli_out("A TrunkIndex value is required.\n");
   1153 
   1154                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1155                 }
   1156  
   1157                 BCM_GPORT_TRUNK_SET(endpoint_info.gport, trunk_id);
   1158 
   1159                 endpoint_info.trunk_index = trunk_index;
   1160             }
   1161             else
   1162             {
   1163                 if (!is_remote) {
   1164                     cli_out("An port or trunk group ID is required.\n");
   1165 
   1166                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1167                 }
   1168             }
   1169 
   1170             endpoint_info.level = level;
   1171             endpoint_info.vlan = vlan;
   1172             endpoint_info.name = (uint16) endpoint_name;
   1173 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1174             endpoint_info.opcode_flags = opcode_flags;
   1175 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT */
   1176 
   1177             /* Check for parameters needed for remote and local tx */
   1178 
   1179             if (is_remote || local_tx)
   1180             {
   1181                 if (ccm_period < 0)
   1182                 {
   1183                     cli_out("A CCM period is required.\n");
   1184 
   1185                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1186                 }
   1187 
   1188                 endpoint_info.ccm_period = ccm_period;
   1189             }
   1190             
   1191             /* Check for parameters needed only for local tx */
   1192 
   1193             if (local_tx)
   1194             {
   1195                 if (BCM_MAC_IS_ZERO(endpoint_info.src_mac_address))
   1196                 {
   1197                     cli_out("Source MAC address is required for CCM TX.\n");
   1198 
   1199                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1200                 }
   1201 
   1202 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1203                 if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH3(unit)) {
   1204                     if (BCM_MAC_IS_ZERO(endpoint_info.dst_mac_address)) {
   1205                         cli_out("Destination MAC address is required for CCM TX.\n");
   1206 
   1207                         CLEAN_UP_AND_RETURN(CMD_FAIL);
   1208                     }
   1209                 }
   1210 #endif /* !BCM_ENDURO_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
   1211 
   1212                 if (pkt_pri < 0)
   1213                 {
   1214                     cli_out("A packet priority is required.\n");
   1215 
   1216                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1217                 }
   1218 
   1219                 if (int_pri < 0)
   1220                 {
   1221                     cli_out("An internal priority is required.\n");
   1222 
   1223                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1224                 }
   1225 
   1226 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1227                 if (cpu_pri < 0)
   1228                 {
   1229                     cli_out("A cpu queue is required.\n");
   1230 
   1231                     CLEAN_UP_AND_RETURN(CMD_FAIL);
   1232                 }
   1233                 endpoint_info.cpu_qid = cpu_pri;
   1234 #endif /* !BCM_KATANA_SUPPORT || !BCM_TRIUMPH3_SUPPORT*/
   1235 
   1236                 endpoint_info.pkt_pri = pkt_pri;
   1237                 endpoint_info.int_pri = int_pri;
   1238             }
   1239 
   1240             if (is_remote)
   1241             {
   1242                 endpoint_info.flags |= BCM_OAM_ENDPOINT_REMOTE;
   1243             }
   1244 
   1245             if (rx_ccm)
   1246             {
   1247                 endpoint_info.flags |= BCM_OAM_ENDPOINT_CCM_RX;
   1248             }
   1249 
   1250             if (rx_lb)
   1251             {
   1252                 endpoint_info.flags |= BCM_OAM_ENDPOINT_LOOPBACK;
   1253             }
   1254 
   1255             if (rx_dm)
   1256             {
   1257                 endpoint_info.flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT;
   1258             }
   1259             
   1260             if (rx_lm)
   1261             {
   1262                 endpoint_info.flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT;
   1263             }
   1264 
   1265             if (rx_lt)
   1266             {
   1267                 endpoint_info.flags |= BCM_OAM_ENDPOINT_LINKTRACE;
   1268             }
   1269             
   1270             if (pbbte)
   1271             {
   1272                 endpoint_info.flags |= BCM_OAM_ENDPOINT_PBB_TE;
   1273             }
   1274 
   1275             if (up_mep)
   1276             {
   1277                 endpoint_info.flags |= BCM_OAM_ENDPOINT_UP_FACING;
   1278             }
   1279 
   1280             endpoint_info.type = bcmOAMEndpointTypeEthernet;
   1281 
   1282             result = bcm_oam_endpoint_create(unit, &endpoint_info);
   1283 
   1284             if (BCM_FAILURE(result))
   1285             {
   1286                 cli_out("Command failed. %s\n", bcm_errmsg(result));
   1287 
   1288                 parse_arg_eq_done(&parse_table);
   1289 
   1290                 return CMD_FAIL;
   1291             }
   1292 
   1293             parse_arg_eq_done(&parse_table);
   1294             
   1295             cli_out("OAM endpoint %d created.\n", endpoint_info.id);
   1296         }
   1297     }
   1298     else if (sal_strcasecmp(arg_string_p, "events") == 0)
   1299     {
   1300         arg_string_p = ARG_GET(args);
   1301 
   1302         if (arg_string_p != NULL)
   1303         {
   1304             if (sal_strcasecmp(arg_string_p, "on") == 0)
   1305             {
   1306                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointPortDown);
   1307                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointPortUp);
   1308                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDown);
   1309                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUp);
   1310                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMxcon);
   1311                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMError);
   1312                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupRemote);
   1313                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMTimeout);
   1314 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1315                 if (SOC_IS_KATANA(unit)
   1316                     || SOC_IS_TRIUMPH3(unit)) {
   1317                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceTestingToUp);
   1318                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUnknownToUp);
   1319                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDormantToUp);
   1320                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceNotPresentToUp);
   1321                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceLLDownToUp);
   1322                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceTesting);
   1323                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUnkonwn);
   1324                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDormant);
   1325                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceNotPresent);
   1326                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceLLDown);
   1327                 }
   1328 #endif /* BCM_KATANA_SUPPORT */
   1329 
   1330                 if (BCM_FAILURE(bcm_oam_event_register(unit, event_types,
   1331                     _cmd_esw_oam_event_handle, NULL)))
   1332                 {
   1333                     cli_out("Failed to enable OAM events.\n");
   1334 
   1335                     return CMD_FAIL;
   1336                 }
   1337 
   1338                 events_on = 1;
   1339             }
   1340             else if (sal_strcasecmp(arg_string_p, "off") == 0)
   1341             {
   1342                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointPortDown);
   1343                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointPortUp);
   1344                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDown);
   1345                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUp);
   1346                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMxcon);
   1347                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMError);
   1348                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupRemote);
   1349                 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventGroupCCMTimeout);
   1350 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   1351                 if (SOC_IS_KATANA(unit)
   1352                     || SOC_IS_TRIUMPH3(unit)) {
   1353                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceTestingToUp);
   1354                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUnknownToUp);
   1355                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDormantToUp);
   1356                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceNotPresentToUp);
   1357                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceLLDownToUp);
   1358                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceTesting);
   1359                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceUnkonwn);
   1360                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceDormant);
   1361                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceNotPresent);
   1362                     BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEndpointInterfaceLLDown);
   1363                 }
   1364 #endif /* BCM_KATANA_SUPPORT */
   1365 
   1366                 if (BCM_FAILURE(bcm_oam_event_unregister(unit, event_types,
   1367                     _cmd_esw_oam_event_handle)))
   1368                 {
   1369                     cli_out("Failed to disable OAM events.\n");
   1370 
   1371                     return CMD_FAIL;
   1372                 }
   1373 
   1374                 events_on = 0;
   1375             }
   1376             else
   1377             {
   1378                 cli_out("Invalid OAM events option: %s\n", arg_string_p);
   1379 
   1380                 return CMD_FAIL;
   1381             }
   1382         }
   1383 
   1384         cli_out("OAM events %s\n", events_on ? "on" : "off");
   1385     }
   1386     else
   1387     {
   1388         cli_out("Invalid OAM subcommand: %s\n", arg_string_p);
   1389 
   1390         return CMD_FAIL;
   1391     }
   1392 
   1393     return CMD_OK;
   1394 }