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

pe_mode.c (18271B)


      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:       pe_mode.c
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <appl/diag/system.h>
     12 
     13 #ifdef PE_MODE_CMD
     14 
     15 #include <netinet/in.h>
     16 #include <bcm/extender.h>
     17 #include <bcm/link.h>
     18 
     19 
     20 #define PE_MODE_ID_ETHERTYPE       0x869f
     21 #define LLDP_TLV_HDR_TYPE_MASK     0xfe00
     22 #define LLDP_TLV_HDR_TYPE_SHIFT    9
     23 #define LLDP_TLV_HDR_LEN_MASK      0x01ff
     24 
     25 #define BCM_TLV_TYPE               127
     26 #define BCM_TLV_OUI_VAL            0x18c086
     27 #define BCM_MODE_TLV_SUBTYPE_VAL   0x01
     28 #define BCM_TAG_TLV_SUBTYPE_VAL    0x02
     29 #define BCM_ECID_TLV_SUBTYPE_VAL   0x03
     30 #define BCM_PRE_DEFINED_ECID0      0x11
     31 #define BCM_PRE_DEFINED_ECID1      0x22
     32 #define BCM_PRE_DEFINED_ECID2      0x33
     33 #define BCM_PRE_DEFINED_ECID3      0x44
     34 
     35 #define BCM_MODE_TLV_DETECTED_FLAG 1
     36 #define BCM_TAG_TLV_DETECTED_FLAG  2
     37 #define BCM_ECID_TLV_DETECTED_FLAG 4
     38 #define LLDP_TLV_PARSER_DONE       0xFF
     39 
     40 #define LLDP_TLV_HDR_LEN           2
     41 #define LLDP_TLV_OUI_LEN           3
     42 #define BCM_ECID_VAL_LEN           4
     43 
     44 typedef struct pe_port_info_s {
     45     int count;
     46     bcm_gport_t pe_gport;
     47     bcm_gport_t extender_port_id[4];
     48 } pe_port_info_t;
     49 
     50 int pemode_init(int unit);
     51 int pe_mode_enable(int unit);
     52 
     53 #endif /* PE_MODE_CMD */
     54 
     55 
     56 /*
     57  * Function: cmd_pemode
     58  * Purpose: initialize pemode
     59  * Parameters:  u - SOC unit #
     60  *              a - pointer to args
     61  * Returns: CMD_OK/CMD_FAIL
     62  */
     63 cmd_result_t
     64 cmd_pemode(int u, args_t *a)
     65 {
     66 
     67 #ifdef PE_MODE_CMD
     68     pemode_init(u);
     69     pe_mode_enable(u);
     70 #else
     71     cli_out("cmd_pemode() API calls commented out\n");
     72 #endif /* PE_MODE_CMD */
     73 
     74     return CMD_OK;
     75 }
     76 
     77 
     78 #ifdef PE_MODE_CMD
     79 
     80 int pe_port_enable(int unit, int pe_port)
     81 {
     82     int rv;
     83     /* extender ports */
     84     bcm_extender_port_t extender_port[4];
     85     int pe_etag_pcp[4] = {0, 2, 4, 6};
     86     int pe_etag_vid[4] = {0x11, 0x22, 0x33, 0x44};
     87     int i, num_pe_port = 4;
     88 
     89     bcm_gport_t pe_gport;       /* gport to access the extended ports */
     90     int val;
     91     bcm_vlan_t vlan_id, def_vlan_id;
     92     int flags, mgroup;
     93     bcm_vlan_control_vlan_t vlan_ctrl;
     94 
     95     /* get the gport of pe_gport */
     96     rv = bcm_port_gport_get(unit, pe_port, &pe_gport);
     97     if (BCM_FAILURE(rv)) {
     98         cli_out("bcm_port_gport_get() failed (%s)\n", bcm_errmsg(rv));
     99         return rv;
    100     }
    101 
    102     rv = bcm_port_control_get(unit, pe_port, bcmPortControlExtenderType, &val) ;
    103     if (BCM_FAILURE(rv)) {
    104         cli_out("Failed to get port %d extender type: %s\n", pe_port, bcm_errmsg(rv));
    105         return rv;
    106     }
    107     if (BCM_PORT_EXTENDER_TYPE_SWITCH == val) {
    108         /* cli_out("Port is in PE MODE already, return without any operations.\n"); */
    109         return BCM_E_NONE;
    110     }
    111 
    112     /* set port type for the pe_port */
    113     rv = bcm_port_control_set(unit, pe_gport, bcmPortControlExtenderType, BCM_PORT_EXTENDER_TYPE_SWITCH);
    114     if (BCM_FAILURE(rv)) {
    115         cli_out("bcm_port_control_set() failed (%s)\n", bcm_errmsg(rv));
    116         return rv;
    117     }
    118 
    119     /* add pe port */
    120     for (i=0; i<num_pe_port; i++) {
    121         /* initialize each of the port extender port structures */
    122         bcm_extender_port_t_init(&extender_port[i]);
    123         extender_port[i].flags = 0;
    124         extender_port[i].port = pe_gport;
    125         extender_port[i].extended_port_vid = pe_etag_vid[i];
    126         extender_port[i].pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_DEFAULT;
    127         extender_port[i].pcp = pe_etag_pcp[i];
    128         extender_port[i].de = 0;
    129         rv = bcm_extender_port_add(unit, &extender_port[i]);
    130         if (BCM_FAILURE(rv)) {
    131             cli_out("bcm_extender_port_add(%d) failed (%s)\n", i, bcm_errmsg(rv));
    132             return rv;
    133         }
    134         /*
    135         cli_out("bcm_extender_port_add(%d) ep_vid: 0x%x; ep_id: 0x%x\n", i,
    136                 extender_port[i].extended_port_vid, extender_port[i].extender_port_id);
    137         */
    138     }
    139 
    140     /* get default vlan */
    141     bcm_vlan_default_get(unit, &def_vlan_id);
    142     vlan_id = def_vlan_id;
    143 
    144     /* don't remove the Etag on egress of pe port */
    145     rv = bcm_port_control_set(unit, pe_gport, bcmPortControlEtagEgressDelete, 0);
    146     if (BCM_FAILURE(rv)) {
    147         cli_out("bcm_port_control_set(%d) failed (%s)\n", pe_port, bcm_errmsg(rv));
    148         return rv;
    149     }
    150 
    151     /* configure entender port vlans for untagged packets */
    152     for (i=0; i<num_pe_port; i++) {
    153         rv = bcm_port_untagged_vlan_set(unit, extender_port[i].extender_port_id, vlan_id);
    154         if (BCM_FAILURE(rv)) {
    155             cli_out("Set default vlan on extender port %#x failed: %s \n",
    156                     extender_port[i].extender_port_id,	bcm_errmsg(rv));
    157             return rv;
    158         }
    159     }
    160 
    161     bcm_vlan_control_vlan_t_init(&vlan_ctrl);
    162     rv = bcm_vlan_control_vlan_get(unit, vlan_id, &vlan_ctrl);
    163     if(BCM_FAILURE(rv)) {
    164         cli_out("Failed to get vlan %d information: %s\n", vlan_id, bcm_errmsg(rv));
    165         return rv;
    166     }
    167     mgroup = vlan_ctrl.broadcast_group;
    168 
    169     /* Multicast is not created */
    170     if (!mgroup) {
    171         /* create multicast group */
    172         flags = BCM_MULTICAST_TYPE_EXTENDER;
    173         rv = bcm_multicast_create(unit, flags, &mgroup);
    174         if (BCM_FAILURE(rv)) {
    175             cli_out("Create multigroup failed: %s\n", bcm_errmsg(rv));
    176             return rv;
    177         }
    178 
    179         /* configure multicast group vlans */
    180         bcm_vlan_control_vlan_t_init(&vlan_ctrl);
    181         vlan_ctrl.broadcast_group        = mgroup;
    182         vlan_ctrl.unknown_multicast_group = mgroup;
    183         vlan_ctrl.unknown_unicast_group   = mgroup;
    184         rv = bcm_vlan_control_vlan_set(unit, vlan_id, vlan_ctrl);
    185         if(BCM_FAILURE(rv)) {
    186             cli_out("Failed to configure multicast group on vlan %d: %s\n", vlan_id, bcm_errmsg(rv));
    187             return rv;
    188         }
    189     }
    190 
    191     /* add pe_port to new vlan */
    192     flags = BCM_VLAN_PORT_UNTAGGED;
    193     rv = bcm_vlan_gport_add(unit, vlan_id, pe_gport, flags);
    194     if (BCM_FAILURE(rv)) {
    195         cli_out("Failed to configure port %#x as untagged port: %s\n", pe_gport, bcm_errmsg(rv));
    196         return rv;
    197     }
    198     for (i=0; i<num_pe_port; i++) {
    199         rv = bcm_vlan_gport_add(unit, vlan_id, extender_port[i].extender_port_id, flags);
    200         if (BCM_FAILURE(rv)) {
    201             cli_out("Error to add extender port %#x to vlan %d: %s\n", 
    202                     extender_port[i].extender_port_id, vlan_id, bcm_errmsg(rv));
    203             return rv;
    204         }
    205     }
    206 
    207     cli_out("Port %d has been configured as PE mode\n", pe_port);	
    208     return BCM_E_NONE;
    209 }
    210 
    211 
    212 int extender_port_traverse_cb(int unit, bcm_extender_port_t *extender_port, void *user_data)
    213 {
    214     pe_port_info_t pe_port_info;
    215     sal_memcpy(&pe_port_info, user_data, sizeof(pe_port_info));
    216     if (extender_port->port == pe_port_info.pe_gport) {
    217         if (pe_port_info.count >= 4) {
    218             cli_out("Error, number of extender port of port %#x is bigger than 4\n", 
    219                    pe_port_info.pe_gport);
    220             return BCM_E_NONE;
    221         }
    222         pe_port_info.extender_port_id[pe_port_info.count] = extender_port->extender_port_id;
    223         pe_port_info.count ++;
    224     }
    225     sal_memcpy(user_data, &pe_port_info, sizeof(pe_port_info));
    226     return BCM_E_NONE;
    227 }
    228 
    229 
    230 int pe_port_disable(int unit, int pe_port) 
    231 {
    232     int rv;
    233     int i;
    234     bcm_gport_t pe_gport;       /* gport to access the extended ports */
    235     int flags, val;
    236     bcm_vlan_t vlan_id, def_vlan_id;
    237     pe_port_info_t pe_port_info;
    238 
    239     /* get the gport of pe_gport */
    240     rv = bcm_port_gport_get(unit, pe_port, &pe_gport);
    241     if (BCM_FAILURE(rv)) {
    242         cli_out("bcm_port_gport_get() failed (%s)\n", bcm_errmsg(rv));
    243         return rv;
    244     }
    245 
    246     rv = bcm_port_control_get(unit, pe_port, bcmPortControlExtenderType, &val);
    247     if (BCM_FAILURE(rv)) {
    248         cli_out("Failed to get port %d extender type: %s\n", pe_port, bcm_errmsg(rv));
    249         return rv;
    250     }
    251     if (BCM_PORT_EXTENDER_TYPE_SWITCH != val) {
    252         cli_out("Port %d is not in PE mode\n", pe_port);
    253         return BCM_E_NONE;
    254     }
    255 
    256     /* get default vlan */
    257     bcm_vlan_default_get(unit, &def_vlan_id);
    258     vlan_id = def_vlan_id;
    259 
    260     sal_memset(&pe_port_info, 0, sizeof(pe_port_info));
    261     pe_port_info.pe_gport = pe_gport;
    262     rv = bcm_extender_port_traverse(0, extender_port_traverse_cb, (void*)&pe_port_info);
    263     if (BCM_FAILURE(rv)) {
    264         cli_out("Failed to get extender ports of port 0x%x: %s\n", pe_gport, bcm_errmsg(rv));
    265         return rv;
    266     }
    267     for (i=0; i<pe_port_info.count; i++)
    268     {
    269         rv = bcm_vlan_gport_delete(unit, vlan_id, pe_port_info.extender_port_id[i]);
    270         if (BCM_FAILURE(rv)) {
    271             cli_out("Error in deleting extender port 0x%x from vlan %d: %s\n", 
    272                     pe_port_info.extender_port_id[i], vlan_id, bcm_errmsg(rv));
    273             return rv;
    274         }
    275         rv = bcm_extender_port_delete(unit, pe_port_info.extender_port_id[i]);
    276         if (BCM_FAILURE(rv)) {
    277             cli_out("bcm_extender_port_delete(0x%x) failed (%s)\n", 
    278                     pe_port_info.extender_port_id[i], bcm_errmsg(rv));
    279             return rv;
    280         }
    281     }
    282 
    283     /* set port to ethernet port */
    284     rv = bcm_port_control_set(unit, pe_gport, bcmPortControlExtenderType, BCM_PORT_EXTENDER_TYPE_NONE);
    285     if (BCM_FAILURE(rv)) {
    286         cli_out("bcm_port_control_set() failed (%s)\n", bcm_errmsg(rv));
    287         return rv;
    288     }
    289  
    290     rv = bcm_port_control_set(unit, pe_gport, bcmPortControlEtagEgressDelete, 1);
    291     if (BCM_FAILURE(rv)) {
    292         cli_out("Configure port(%d) to delete ETAG failed (%s)\n", pe_port, bcm_errmsg(rv));
    293         return rv;
    294     }
    295     /* add pe_port to new vlan */
    296     flags = BCM_VLAN_PORT_UNTAGGED;
    297     rv = bcm_vlan_gport_add(unit, vlan_id, pe_gport, flags);
    298     if (BCM_FAILURE(rv)) {
    299         cli_out("Failed to configure port 0x%x as untagged port: %s\n", pe_gport, bcm_errmsg(rv));
    300         return rv;
    301     }
    302 
    303     cli_out("PE mode on port %d has been disabled\n", pe_port);
    304 
    305     return BCM_E_NONE;
    306 }
    307 
    308 
    309 void dump_pkt(bcm_pkt_t *pkt)
    310 {
    311     int i;
    312     cli_out("Packet from port %d", pkt->src_port);
    313     cli_out("\n");
    314     for (i=0; i<16; i++) {
    315         cli_out("===");
    316     }
    317     cli_out("\n");
    318     for (i=0; i<16; i++) {
    319         cli_out("%02d ", i);
    320     }
    321     cli_out("\n");
    322     for (i=0; i<16; i++) {
    323         cli_out("===");
    324     }
    325 
    326     cli_out("\n%02x ", pkt->pkt_data->data[0]);
    327     for (i=1; i<pkt->pkt_len; i++) {
    328         if (i%16) {
    329             cli_out("%02x ", pkt->pkt_data->data[i]);
    330         } else {
    331             cli_out("\n%02x ", pkt->pkt_data->data[i]);
    332         }
    333     }
    334     cli_out("\n");
    335 }
    336 
    337 
    338 int brcm_tlv_parser(char *data, int *length)
    339 {
    340     int subtype, tlv_hdr, tlv_len, tlv_type;
    341     int tlv_oui;
    342     /*int op_mode, tag_mode;*/
    343     uint16      *tlvptr=(uint16*)data;
    344     uint8       *uint8ptr;
    345     uint8       ecid[4];
    346 
    347     tlv_hdr = ntohs(*tlvptr);
    348     tlv_len = tlv_hdr & LLDP_TLV_HDR_LEN_MASK;
    349     tlv_type = (tlv_hdr & LLDP_TLV_HDR_TYPE_MASK) >> LLDP_TLV_HDR_TYPE_SHIFT;
    350     /* cli_out("%s() tlv_hdr 0x%x; tlv_len 0x%x; tlv type 0x%x\n", __FUNCTION__, tlv_hdr, tlv_len, tlv_type); */
    351     *length = tlv_len + LLDP_TLV_HDR_LEN;
    352     if (!tlv_type)
    353     {
    354         return LLDP_TLV_PARSER_DONE;
    355     }
    356     /* Parser BRCM OUI only */
    357     if (BCM_TLV_TYPE == tlv_type) {
    358         uint8ptr =  (uint8*)(data+LLDP_TLV_HDR_LEN);
    359         tlv_oui = *(uint8ptr++)<<16;
    360         tlv_oui += *(uint8ptr++)<<8;
    361         tlv_oui += *(uint8ptr++);
    362         /*cli_out("BCM TLV OUI value: 0x%x\n", tlv_oui);*/
    363         if (tlv_oui == BCM_TLV_OUI_VAL) {
    364             subtype = data[LLDP_TLV_HDR_LEN+LLDP_TLV_OUI_LEN];
    365             /*cli_out("BCM TLV subtype value: 0x%x\n", subtype);*/
    366             switch(subtype) {
    367                 case BCM_MODE_TLV_SUBTYPE_VAL:
    368                     /*op_mode = data[LLDP_TLV_HDR_LEN+LLDP_TLV_OUI_LEN+1];*/
    369                     /*cli_out("Opertaion mode: %d\n", op_mode);*/
    370                     return BCM_MODE_TLV_DETECTED_FLAG;
    371                     break;
    372                 case BCM_TAG_TLV_SUBTYPE_VAL:
    373                     /*tag_mode = data[LLDP_TLV_HDR_LEN+LLDP_TLV_OUI_LEN+1];*/
    374                     /*cli_out("Tag mode: %d\n", tag_mode);*/
    375                     return BCM_TAG_TLV_DETECTED_FLAG;
    376                     break;
    377                 case BCM_ECID_TLV_SUBTYPE_VAL:
    378                     uint8ptr =  (uint8*)(data+LLDP_TLV_HDR_LEN+LLDP_TLV_OUI_LEN+1);
    379                     ecid[0] = *(uint8ptr++);
    380                     ecid[1] = *(uint8ptr++);
    381                     ecid[2] = *(uint8ptr++);
    382                     ecid[3] = *(uint8ptr++);
    383                     if (BCM_PRE_DEFINED_ECID0 != ecid[0]) {
    384                         cli_out("Unexpected TLV ECID0 value: 0x%x\n", ecid[0]);
    385                         return 0;
    386                     } else if (BCM_PRE_DEFINED_ECID1 != ecid[1]) {
    387                         cli_out("Unexpected TLV ECID1 value: 0x%x\n", ecid[1]);
    388                         return 0;
    389                     } else if (BCM_PRE_DEFINED_ECID2 != ecid[2]) {
    390                         cli_out("Unexpected TLV ECID2 value: 0x%x\n", ecid[2]);
    391                         return 0;
    392                     } else if (BCM_PRE_DEFINED_ECID3 != ecid[3]) {
    393                         cli_out("Unexpected TLV ECID3 value: 0x%x\n", ecid[3]);
    394                         return 0;
    395                     } else {
    396                         /*cli_out("ECID TLV is detected: 0x%x, 0x%x, 0x%x, 0x%x\n", ecid[0], ecid[1], ecid[2], ecid[3]);*/
    397                     }
    398                     return BCM_ECID_TLV_DETECTED_FLAG;
    399                     break;
    400                 default:
    401                     cli_out("Unknown subtype in BRCM TLV: %d\n", subtype);
    402                     return 0;
    403             }
    404         }
    405     }
    406     return 0;
    407 }
    408 
    409 
    410 int is_brcm_pe_pkt(bcm_pkt_t* pkt)
    411 {
    412     int offset, length;
    413     int ether_type, rv, flags;
    414     uint16      *ethtype;
    415 
    416     /* Check ether type: offset:16, length: 2*/
    417     offset = 16;
    418     length = 2;
    419     ethtype = (uint16*)(pkt->pkt_data->data+offset);
    420     ether_type = ntohs(*ethtype);
    421     /* cli_out("%s() ethtype 0x%x\n", __FUNCTION__, ether_type); */
    422     if (ether_type != PE_MODE_ID_ETHERTYPE) {
    423         return 0;
    424     }
    425 
    426     /* TLV parser started */
    427     offset += length;
    428     flags = 0;
    429     do {
    430         rv = brcm_tlv_parser((char*)(pkt->pkt_data->data+offset), &length);
    431         if (rv == LLDP_TLV_PARSER_DONE) {
    432             break;
    433         } else {
    434             flags |= rv;
    435         }
    436 
    437         /* dead loop protection */
    438         if (length <= LLDP_TLV_HDR_LEN) {
    439             break;
    440         }
    441 
    442         offset += length;
    443         if (offset >= pkt->pkt_len - 4) {
    444             break;
    445         }
    446     } while (1);
    447     /* print flags; */
    448     if (flags == (BCM_MODE_TLV_DETECTED_FLAG | BCM_TAG_TLV_DETECTED_FLAG | BCM_ECID_TLV_DETECTED_FLAG)) {
    449         return 1;
    450     } else {
    451        cli_out("Failed to parser packet\n");
    452        dump_pkt(pkt);
    453     }
    454     return 0;
    455 }
    456 
    457 
    458 bcm_rx_t pe_protocol_parser(int unit, bcm_pkt_t* pkt, void* cookie)
    459 {
    460     int rv;
    461 
    462     if (NULL == pkt) {
    463         cli_out("pkt is NULL\n");
    464         return BCM_RX_HANDLED;
    465     }
    466 
    467     rv = is_brcm_pe_pkt(pkt);
    468     if (rv) {
    469         if (pe_port_enable(unit, pkt->src_port)) {
    470             cli_out("\nFailed to configure port %d into PE mdoe\n", pkt->src_port);
    471         }
    472         return BCM_RX_HANDLED;
    473     }
    474     else {
    475         return BCM_RX_NOT_HANDLED;
    476     }
    477 }
    478 
    479 
    480 void pe_disable_on_linkdown(int unit, bcm_port_t port, bcm_port_info_t *info)
    481 {
    482     if (info->linkstatus == 0) {
    483         pe_port_disable(unit, port);
    484     }
    485     return;
    486 }
    487 
    488 
    489 int pemode_init(int unit)
    490 {
    491     int rv;
    492     int port;
    493     bcm_gport_t gport;
    494     bcm_port_config_t port_config;
    495     int val;
    496 
    497     bcm_port_config_t_init(&port_config);
    498 
    499     /* bcmSwitchL3EgressMode must be set */
    500     rv = bcm_switch_control_set(unit, bcmSwitchL3EgressMode, 1);
    501     if (BCM_FAILURE(rv)) {
    502         cli_out("Error to configure device into L3EgressMode: %s\n", bcm_errmsg(rv));
    503         return rv;
    504     }
    505 
    506     /* initialize the port extender module */
    507     rv = bcm_extender_init(unit);
    508     if (BCM_FAILURE(rv)) {
    509         cli_out("bcm_extender_init() failed: %s\n", bcm_errmsg(rv));
    510         return rv;
    511     }
    512 
    513     /* set extender ethertype to    0x893f (BR tag) */
    514     rv = bcm_switch_control_set(unit, bcmSwitchEtagEthertype, 0x893f);
    515     if (BCM_FAILURE(rv)) {
    516         cli_out("Error to configure extender more ether type: %s\n", bcm_errmsg(rv));
    517         return rv;
    518     }
    519     
    520     rv = bcm_port_config_get(unit, &port_config);
    521     if (BCM_FAILURE(rv)) {
    522         cli_out("Failed to get port config: %s\n", bcm_errmsg(rv));
    523         return rv;
    524     }
    525 
    526     cli_out("Initializing PE Mode\n");
    527     /* configure the switch to remove the Etag on egress of ethernet port */
    528     BCM_PBMP_ITER(port_config.all, port){
    529         rv = bcm_port_gport_get(unit, port, &gport);
    530         if (BCM_FAILURE(rv)) {
    531             cli_out("bcm_port_gport_get(%d) failed (%s)\n", port, bcm_errmsg(rv));
    532             return rv;
    533         }
    534 
    535         rv = bcm_port_control_get(unit, port, bcmPortControlExtenderType, &val);
    536         if (BCM_FAILURE(rv)) {
    537             cli_out("Failed to get port %d extender type: %s\n", port, bcm_errmsg(rv));
    538             return rv;
    539         }
    540 
    541         /* If the port is in PE mode, then next*/
    542         if (BCM_PORT_EXTENDER_TYPE_NONE != val) {
    543             cli_out("Port %d is Port Extender, do not reconfigure\n", port);
    544             continue;
    545         }
    546 
    547         /* Ethernet port, delete ETAG on egress */
    548         rv = bcm_port_control_set(unit, gport, bcmPortControlEtagEgressDelete, 1);
    549         if (BCM_FAILURE(rv)) {
    550             cli_out("Configure port(%d) to delete ETAG failed (%s)\n", port, bcm_errmsg(rv));
    551             return rv;
    552         }
    553     }
    554 
    555     return BCM_E_NONE;
    556 }
    557 
    558 
    559 int pe_mode_enable(int unit)
    560 {
    561     bcm_rx_cfg_t rx_cfg;
    562 
    563     cli_out("Initializing PE-ID packet and Link-Down Callbacks\n");
    564     bcm_rx_cfg_t_init(&rx_cfg);
    565     bcm_rx_cfg_get(unit, &rx_cfg);
    566 
    567     bcm_rx_register(unit, "PE PACKET PARSER", pe_protocol_parser, BCM_RX_PRIO_MAX, NULL, BCM_RCO_F_ALL_COS);
    568     bcm_linkscan_register(unit, pe_disable_on_linkdown);
    569     if (!bcm_rx_active(unit)) {
    570         cli_out("Starting RX process\n");
    571         bcm_rx_start(unit, &rx_cfg);
    572     } else {
    573         cli_out("RX process is already started\n");
    574     }
    575     return CMD_OK;
    576 }
    577 
    578 #endif /* PE_MODE_CMD */
    579