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

flexflow_vpn.c (12605B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  */
      6 
      7 
      8 #include <sal/core/libc.h>
      9 #if defined(INCLUDE_L3)
     10 
     11 #include <bcm/flow.h>
     12 #include <bcm_int/esw/flow.h>
     13 #include <bcm/error.h>
     14 #include <soc/drv.h>
     15 #include <bcm_int/esw/vpn.h>
     16 #include <bcm_int/esw/virtual.h>
     17 #include <bcm_int/esw/trx.h>
     18 #include <bcm_int/common/multicast.h>
     19 #include <bcm_int/esw/trident3.h>
     20 
     21 /* Function:
     22  *      bcmi_esw_flow_vpn_is_valid
     23  * Purpose:
     24  *      Find if given FLOW VPN is Valid 
     25  * Parameters:
     26  *      unit     - Device Number
     27  *      vpn   - FLOW VPN
     28  * Returns:
     29  *      BCM_E_XXXX
     30  */
     31 int
     32 bcmi_esw_flow_vpn_is_valid( int unit, bcm_vpn_t vpn)
     33 {
     34     bcm_vpn_t flow_vpn_min=0;
     35     int vfi_index=-1, num_vfi=0;
     36 
     37     num_vfi = soc_mem_index_count(unit, VFIm);
     38 
     39     /* Check for Valid vpn */
     40     _BCM_FLOW_VPN_SET(flow_vpn_min, _BCM_VPN_TYPE_VFI, 0);
     41     if ( vpn < flow_vpn_min || vpn > (flow_vpn_min+num_vfi-1) ) {
     42         return BCM_E_PARAM;
     43     }
     44 
     45     _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI,  vpn);
     46 
     47     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeFlow)) {
     48         return BCM_E_NOT_FOUND;
     49     }
     50     return BCM_E_NONE;
     51 }
     52 
     53  /* Function:
     54  *      bcmi_esw_flow_vpn_is_eline
     55  * Purpose:
     56  *      Find if given FLOW VPN is ELINE
     57  * Parameters:
     58  *      unit     - Device Number
     59  *      vpn      - FLOW VPN
     60  *      isEline  - Flag 
     61  * Returns:
     62  *      BCM_E_XXXX
     63  * Assumes:
     64  *      vpn is valid
     65  */
     66 
     67 int
     68 bcmi_esw_flow_vpn_is_eline( int unit, bcm_vpn_t vpn, uint8 *isEline)
     69 {
     70     int vfi_index=-1;
     71     vfi_entry_t vfi_entry;
     72 
     73     BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, vpn));
     74 
     75     _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI,  vpn);
     76     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
     77 
     78     /* Set the returned VPN id */
     79     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
     80         *isEline = 1;  /* ELINE */
     81     } else {
     82         *isEline = 0;  /* ELAN */
     83     }
     84     return BCM_E_NONE;
     85 }
     86 
     87 /*
     88  * Function:
     89  *      bcmi_esw_flow_vpn_create
     90  * Purpose:
     91  *      Create an L2 Flow VPN.  This is a service plane and is 
     92  *      independent of the connectivity protocol.
     93  *   Parameters:
     94  *      unit        - (IN)  Unit ID.
     95  *      info    - (IN/OUT)  VPN structure
     96  */
     97 int bcmi_esw_flow_vpn_create(int unit, bcm_vpn_t *vpn,
     98                             bcm_flow_vpn_config_t *info)
     99 {
    100     int rv = BCM_E_NONE;
    101     vfi_entry_t vfi_entry;
    102     int vfi_index=-1;
    103     int bc_group=0, umc_group=0, uuc_group=0;
    104     int bc_group_type=0, umc_group_type=0, uuc_group_type=0;
    105     uint8 vpn_alloc_flag=0;
    106     int proto_pkt_idx = 0;
    107     uint32 profile_idx = 0;
    108 
    109     if (!vpn) {
    110         return BCM_E_PARAM;
    111     }
    112 
    113     /*Allocate VFI*/
    114     if (info->flags & BCM_FLOW_VPN_REPLACE) {
    115         BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_valid(unit, *vpn));
    116         _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, *vpn);
    117     } else if (info->flags & BCM_FLOW_VPN_WITH_ID) {
    118         rv = bcmi_esw_flow_vpn_is_valid(unit, *vpn);
    119         if (BCM_E_NONE == rv) {
    120             return BCM_E_EXISTS;
    121         } else if (BCM_E_NOT_FOUND != rv) {
    122             return rv;
    123         }
    124         _BCM_FLOW_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, *vpn);
    125         BCM_IF_ERROR_RETURN(_bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeFlow, vfi_index));
    126         vpn_alloc_flag = 1;
    127     } else {
    128         BCM_IF_ERROR_RETURN(_bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeFlow, &vfi_index));
    129         _BCM_FLOW_VPN_SET(*vpn, _BCM_VPN_TYPE_VFI, vfi_index);
    130         vpn_alloc_flag = 1;
    131     }
    132 
    133     /*Initial and configure VFI*/
    134     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    135     if (info->flags & BCM_FLOW_VPN_ELINE) {
    136         soc_VFIm_field32_set(unit, &vfi_entry, PT2PT_ENf, 0x1);
    137     } else if (info->flags & BCM_FLOW_VPN_ELAN) {
    138         /* Check that the groups are valid. */
    139         bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group);
    140         bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group);
    141         umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group);
    142         umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group);
    143         uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group);
    144         uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group);
    145 
    146         if ((bc_group_type != _BCM_MULTICAST_TYPE_FLOW) ||
    147             (umc_group_type != _BCM_MULTICAST_TYPE_FLOW) ||
    148             (uuc_group_type != _BCM_MULTICAST_TYPE_FLOW) ||
    149             (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
    150             (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
    151             (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) {
    152             rv = BCM_E_PARAM;
    153             _BCM_FLOW_CLEANUP(rv)
    154         }
    155 
    156         /* Commit the entry to HW */
    157         soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
    158                 UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group);
    159         soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
    160                 UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group);
    161         soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
    162                 BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group);
    163     }
    164     rv = _bcm_td3_def_vfi_profile_add(unit,
    165             info->flags & BCM_FLOW_VPN_ELINE, &profile_idx);
    166     if (BCM_E_NONE == rv) {
    167         soc_VFIm_field32_set(unit, &vfi_entry, VFI_PROFILE_PTRf, profile_idx);
    168     }
    169     _BCM_FLOW_CLEANUP(rv)
    170 
    171     /* Configure protocol packet control */
    172     rv = _bcm_xgs3_protocol_packet_actions_validate(unit, &info->protocol_pkt);
    173     _BCM_FLOW_CLEANUP(rv)
    174     proto_pkt_idx = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
    175     rv = _bcm_xgs3_protocol_pkt_ctrl_set(unit, proto_pkt_idx, &info->protocol_pkt, &proto_pkt_idx);
    176     _BCM_FLOW_CLEANUP(rv)
    177     soc_VFIm_field32_set(unit, &vfi_entry, PROTOCOL_PKT_INDEXf, proto_pkt_idx);
    178 
    179     /*Write VFI to ASIC*/
    180     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
    181     _BCM_FLOW_CLEANUP(rv)
    182 
    183    return BCM_E_NONE;
    184 
    185 cleanup:
    186     if (vpn_alloc_flag) {
    187         (void) _bcm_vfi_free(unit, _bcmVfiTypeFlow, vfi_index);
    188     }
    189 
    190     return rv;
    191 }
    192 
    193 /*
    194  * Function:
    195  *      bcmi_esw_flow_vpn_destroy
    196  * Purpose:
    197  *      Delete L2/L3 VPN
    198  *   Parameters:
    199  *      unit   - (IN)  Unit ID.
    200  *      vpn    - (IN)  VPN Id
    201  */
    202 int bcmi_esw_flow_vpn_destroy(int unit, bcm_vpn_t vpn)
    203 {
    204     int vfi = 0;
    205     vfi_entry_t vfi_entry;
    206     uint8 isEline = 0;
    207 #if 0
    208     uint32 stat_counter_id;
    209     int num_ctr = 0; 
    210 #endif
    211     int ref_count;
    212     int index;
    213 
    214     /* Get vfi index */
    215     BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline));
    216     if (isEline == 0x1 ) {
    217         _BCM_FLOW_VPN_GET(vfi, _BCM_FLOW_VPN_TYPE_ELINE, vpn);
    218     } else if (isEline == 0x0 ) {
    219         _BCM_FLOW_VPN_GET(vfi, _BCM_FLOW_VPN_TYPE_ELAN, vpn);
    220     }
    221 
    222     /* Delete all FLOW ports on this VPN */
    223     BCM_IF_ERROR_RETURN(bcmi_esw_flow_port_delete_all(unit, vpn));
    224 
    225 #if 0
    226     /* TBD: Need to check on this piece of code */
    227     /* Check counters before delete vpn */
    228     if (bcm_esw_vxlan_stat_id_get(unit, BCM_GPORT_INVALID, vpn,
    229                    bcmVxlanOutPackets, &stat_counter_id) == BCM_E_NONE) { 
    230         num_ctr++;
    231     } 
    232     if (bcm_esw_vxlan_stat_id_get(unit, BCM_GPORT_INVALID, vpn,
    233                    bcmVxlanInPackets, &stat_counter_id) == BCM_E_NONE) {
    234         num_ctr++;
    235     }
    236 
    237     if (num_ctr != 0) {
    238         BCM_IF_ERROR_RETURN(
    239            bcm_esw_vxlan_stat_detach(unit, BCM_GPORT_INVALID, vpn));  
    240     }
    241 #endif
    242 
    243     /* Delete protocol packet control */
    244     sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
    245     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry));
    246     index = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
    247     BCM_IF_ERROR_RETURN(
    248         _bcm_prot_pkt_ctrl_ref_count_get(unit, index, &ref_count));
    249     if (ref_count > 0) {
    250         BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_delete(unit, index));
    251     }
    252 
    253     /* Reset VFI table */
    254     (void)_bcm_vfi_free(unit, _bcmVfiTypeFlow, vfi);
    255 
    256     return BCM_E_NONE;
    257 }
    258 
    259 /*
    260  * Function:
    261  *      bcmi_esw_flow_vpn_destroy_all
    262  * Purpose:
    263  *      Delete all VPN's
    264  *   Parameters:
    265  *      unit   - (IN)  Unit ID.
    266  */
    267 int bcmi_esw_flow_vpn_destroy_all(int unit)
    268 {
    269     int num_vfi = 0, idx = 0;
    270     bcm_vpn_t vpn = 0;
    271 
    272     /* Destroy all FLOW VPNs */
    273     num_vfi = soc_mem_index_count(unit, VFIm);
    274     for (idx = 0; idx < num_vfi; idx++) {
    275         if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeFlow)) {
    276             _BCM_FLOW_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx);
    277             BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_destroy(unit, vpn));
    278         }
    279     }
    280     return BCM_E_NONE;
    281 
    282 }
    283 
    284 /*
    285  * Function:
    286  *      bcmi_esw_flow_vpn_get
    287  * Purpose:
    288  *      Get VPN properties
    289  *   Parameters:
    290  *      unit   - (IN)  Unit ID.
    291  *      vpn    - (IN)  VPN Id
    292  *      info    - (IN/OUT)  VPN structure
    293  */
    294 int bcmi_esw_flow_vpn_get(int unit, bcm_vpn_t vpn,
    295                          bcm_flow_vpn_config_t *info)
    296 {
    297     int rv = BCM_E_NONE;
    298     int vfi_index = -1;
    299     vfi_entry_t vfi_entry;
    300     uint8 isEline=0;
    301     int proto_pkt_inx;
    302     uint32 dt, dv;
    303 
    304     /*Get vfi table*/
    305     BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_is_eline(unit, vpn, &isEline));
    306     if (isEline == 0x1 ) {
    307         _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELINE, vpn);
    308     } else if (isEline == 0x0 ) {
    309         _BCM_FLOW_VPN_GET(vfi_index, _BCM_FLOW_VPN_TYPE_ELAN, vpn);
    310     }
    311     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    312 
    313     /* Get info associated with vfi table */
    314     if (isEline) {
    315         info->flags =  BCM_FLOW_VPN_ELINE;
    316     } else {
    317          info->flags =  BCM_FLOW_VPN_ELAN;
    318 
    319 
    320          dv = soc_mem_field32_dest_get(unit, VFIm,
    321                  &vfi_entry, BC_DESTINATIONf, &dt);
    322          if (dt == SOC_MEM_FIF_DEST_IPMC) {
    323              _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
    324                      _BCM_MULTICAST_TYPE_FLOW, dv);
    325          } else {
    326              return BCM_E_INTERNAL;
    327          }
    328 
    329          dv = soc_mem_field32_dest_get(unit, VFIm,
    330                  &vfi_entry, UUC_DESTINATIONf, &dt);
    331          if (dt == SOC_MEM_FIF_DEST_IPMC) {
    332              _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
    333                      _BCM_MULTICAST_TYPE_FLOW, dv);
    334          } else {
    335              return BCM_E_INTERNAL;
    336          }
    337 
    338          dv = soc_mem_field32_dest_get(unit, VFIm,
    339                  &vfi_entry, UMC_DESTINATIONf, &dt);
    340          if (dt == SOC_MEM_FIF_DEST_IPMC) {
    341              _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
    342                      _BCM_MULTICAST_TYPE_FLOW, dv);
    343          } else {
    344              return BCM_E_INTERNAL;
    345          }
    346     }
    347     /*Get protocol packet control*/
    348     proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
    349     BCM_IF_ERROR_RETURN(_bcm_xgs3_protocol_pkt_ctrl_get(unit,proto_pkt_inx, &info->protocol_pkt));
    350 
    351     return rv;
    352 }
    353 
    354 /*
    355  * Function:
    356  *      bcmi_esw_flow_vpn_traverse
    357  * Purpose:
    358  *      Traverse VPN's
    359  *   Parameters:
    360  *      unit      - (IN)  Unit ID.
    361  *      cb        - (IN)  callback function
    362  *      user_data -  (IN) User context data
    363  */
    364 int bcmi_esw_flow_vpn_traverse(int unit,
    365                               bcm_flow_vpn_traverse_cb cb,
    366                               void *user_data)
    367 {
    368     int idx, num_vfi;
    369     int vpn;
    370     bcm_flow_vpn_config_t info;
    371 
    372     if (cb == NULL) {
    373          return BCM_E_PARAM;
    374     }
    375 
    376     /* FLOW VPNs */
    377     num_vfi = soc_mem_index_count(unit, VFIm);
    378     for (idx = 0; idx < num_vfi; idx++) {
    379          if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeFlow)) {
    380               _BCM_FLOW_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx);
    381               bcm_flow_vpn_config_t_init(&info);
    382               BCM_IF_ERROR_RETURN(bcmi_esw_flow_vpn_get(unit, vpn, &info));
    383               BCM_IF_ERROR_RETURN(cb(unit, vpn, &info, user_data));
    384          }
    385     }
    386     return BCM_E_NONE;
    387 }
    388 
    389  /* Function:
    390  *      bcmi_flow_vpnid_get
    391  * Purpose:
    392  *      Get L2-VPN instance for FLOW VPN
    393  * Parameters:
    394  *      unit     - Device Number
    395  *      vfi_index   - vfi_index
    396  *      vid     (OUT) VLAN Id (l2vpn id)
    397 
    398  * Returns:
    399  *      BCM_E_XXXX
    400  */
    401 int
    402 bcmi_esw_flow_vpnid_get(int unit, int vfi_index, bcm_vlan_t *vid)
    403 {
    404     vfi_entry_t vfi_entry;
    405 
    406     BCM_IF_ERROR_RETURN
    407         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
    408 
    409     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
    410         _BCM_FLOW_VPN_SET(*vid, _BCM_FLOW_VPN_TYPE_ELINE, vfi_index);
    411     } else {
    412         _BCM_FLOW_VPN_SET(*vid, _BCM_FLOW_VPN_TYPE_ELAN, vfi_index);
    413     }
    414     return BCM_E_NONE;
    415 }
    416 #endif