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

lpm.c (7051B)


      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  * File:        lpm.c
      7  * Purpose:     Trident3 flex LPM table routines
      8  * Requires:
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/mem.h>
     15 #include <soc/debug.h>
     16 
     17 #if defined(BCM_HELIX5_SUPPORT) && defined(INCLUDE_L3)
     18 
     19 #include <soc/lpm.h>
     20 #include <soc/format.h>
     21 #include <soc/esw/flow_db.h>
     22 
     23 static
     24 int
     25 _ipmask2pfx(uint32 ipv4m, int *mask_len)
     26 {
     27     *mask_len = 0;
     28     while (ipv4m & (1 << 31)) {
     29         *mask_len += 1;
     30         ipv4m <<= 1;
     31     }
     32 
     33     return ((ipv4m) ? SOC_E_PARAM : SOC_E_NONE);
     34 }
     35 /*
     36  * Function:
     37  *      soc_hx5_lpm_flex_ip4entry0_to_1
     38  * Purpose:
     39  *      copy half-wide flex entry from src to dest.
     40  *      src and dst can be same.
     41  * Parameters:
     42  *      unit      - (IN)SOC unit number.
     43  *      src       - (IN)source buffer
     44  *      dest      - (IN)destination buffer
     45  *      copy_hit  - (IN)copy hit bit as well
     46  * Returns:
     47  *      BCM_E_XXX
     48  */
     49 int
     50 soc_hx5_lpm_flex_ip4entry0_to_1(int u, void *src, void *dst, uint32 key_type, int copy_hit)
     51 {
     52     uint32      ipv4a;
     53     soc_mem_t   view_id;
     54     uint32      ipv4_pdd[SOC_MAX_MEM_WORDS];
     55 
     56     SOC_IF_ERROR_RETURN(
     57         soc_flow_db_mem_to_view_id_get(u,
     58                     L3_DEFIPm,
     59                     key_type,
     60                     SOC_FLOW_DB_DATA_TYPE_INVALID,
     61                     0,
     62                     NULL,
     63                     (uint32*) &view_id));
     64 
     65     ipv4a = soc_mem_field32_get(u, view_id, src, VALID0f);
     66     soc_mem_field32_set(u, view_id, dst, VALID1f, ipv4a);
     67 
     68     ipv4a = soc_mem_field32_get(u, view_id, src, KEY_MODE0f);
     69     soc_mem_field32_set(u, view_id, dst, KEY_MODE0f, ipv4a);
     70 
     71     if (SOC_MEM_FIELD_VALID(u, view_id, KEY_MODE_MASK0f)) {
     72         ipv4a = soc_mem_field32_get(u, view_id, src, KEY_MODE_MASK0f);
     73         soc_mem_field32_set(u, view_id, dst, KEY_MODE_MASK1f, ipv4a);
     74     }
     75 
     76     ipv4a = soc_mem_field32_get(u, view_id, src, IP_ADDR0f);
     77     soc_mem_field32_set(u, view_id, dst, IP_ADDR1f, ipv4a);
     78 
     79     ipv4a = soc_mem_field32_get(u, view_id, src, IP_ADDR_MASK0f);
     80     soc_mem_field32_set(u, view_id, dst, IP_ADDR_MASK1f, ipv4a);
     81 
     82     if (SOC_MEM_FIELD_VALID(u, view_id, VRF_ID_0f)) {
     83         ipv4a = soc_mem_field32_get(u, view_id, src, VRF_ID_0f);
     84         soc_mem_field32_set(u, view_id, dst, VRF_ID_1f, ipv4a);
     85         ipv4a = soc_mem_field32_get(u, view_id, src, VRF_ID_MASK0f);
     86         soc_mem_field32_set(u, view_id, dst, VRF_ID_MASK1f, ipv4a);
     87     }
     88 
     89     if (SOC_MEM_FIELD_VALID(u, view_id, ENTRY_TYPE0f)) {
     90         ipv4a = soc_mem_field32_get(u, view_id, src, ENTRY_TYPE0f);
     91         soc_mem_field32_set(u, view_id, dst, ENTRY_TYPE1f, ipv4a);
     92         ipv4a = soc_mem_field32_get(u, view_id, src, ENTRY_TYPE_MASK0f);
     93         soc_mem_field32_set(u, view_id, dst, ENTRY_TYPE_MASK1f, ipv4a);
     94     }
     95 
     96     soc_mem_field_get(u, L3_DEFIPm, src, POLICY_DATA0f, ipv4_pdd);
     97     soc_mem_field_set(u, L3_DEFIPm, dst, POLICY_DATA1f, ipv4_pdd);
     98 
     99     if (copy_hit) {
    100         ipv4a = soc_mem_field32_get(u, view_id, src, HIT0f);
    101         soc_mem_field32_set(u, view_id, dst, HIT1f, ipv4a);
    102     }
    103 
    104     return(SOC_E_NONE);
    105 }
    106 /*
    107  * Function:
    108  *      soc_hx5_lpm_flex_vrf_get
    109  * Purpose:
    110  *      Service routine used to translate hw flex entry specific vrf id to API format.
    111  * Parameters:
    112  *      unit      - (IN)SOC unit number.
    113  *      lpm_entry - (IN)Route info buffer from hw.
    114  *      view_id   - (IN)View-id for the flex entry
    115  *      vrf_id    - (OUT)Virtual router id.
    116  * Returns:
    117  *      BCM_E_XXX
    118  */
    119 STATIC int
    120 soc_hx5_lpm_flex_vrf_get(int unit, void *lpm_entry, uint32 view_id, int *vrf)
    121 {
    122     int vrf_id;
    123 
    124     /* Get Virtual Router id if supported. */
    125     if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)){
    126         vrf_id = soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_0f);
    127 
    128         /* Special vrf's handling. */
    129         if (soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_MASK0f)) {
    130             *vrf = vrf_id;
    131         } else if (SOC_VRF_MAX(unit) == vrf_id) {
    132             *vrf = SOC_L3_VRF_GLOBAL;
    133         } else {
    134             *vrf = SOC_L3_VRF_OVERRIDE;
    135             if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) {
    136                 uint32 action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
    137                                                 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf);
    138                 if (soc_format_field32_get(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    139                                            &action_set, GLOBAL_ROUTEf)) {
    140                     *vrf = SOC_L3_VRF_GLOBAL;
    141                 }
    142             }
    143 #if 0
    144     
    145             /* GLOBAL_HIGH is meaningless for lpm, use it to indicate OVERRIDE */
    146             if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_HIGH0f)) {
    147                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f)){
    148                     *vrf = SOC_L3_VRF_OVERRIDE;
    149                 }
    150             }
    151 #endif
    152         }
    153     } else {
    154         /* No vrf support on this device. */
    155         *vrf = SOC_L3_VRF_DEFAULT;
    156     }
    157     return (SOC_E_NONE);
    158 }
    159 /*
    160  * Function:
    161  *      soc_hx5_lpm_flex_prefix_length_get
    162  * Purpose:
    163  *      soc_hx5_lpm_flex_prefix_length_get (Extract vrf weighted  prefix lenght from the 
    164  *      hw entry based on ip, mask & vrf)
    165  * Parameters:
    166  *      unit      - (IN)SOC unit number.
    167  *      entry     - (IN)Route info buffer from hw.
    168  *      pfx_len   - (OUT)Prefix len
    169  * Returns:
    170  *      BCM_E_XXX
    171  */
    172 int
    173 soc_hx5_lpm_flex_prefix_length_get(int u, void *entry, int *ipv6, int *vrf_id, int *pfx, uint32 key_type)
    174 {
    175     int         rv;
    176     uint32      ipv4a;
    177     soc_mem_t   view_id;
    178 
    179     if (pfx == NULL) {
    180         return SOC_E_INTERNAL;
    181     }
    182 
    183     SOC_IF_ERROR_RETURN(
    184         soc_flow_db_mem_to_view_id_get(u,
    185                     L3_DEFIPm,
    186                     key_type,
    187                     SOC_FLOW_DB_DATA_TYPE_INVALID,
    188                     0,
    189                     NULL,
    190                     (uint32*) &view_id));
    191 
    192     *ipv6 = soc_mem_field32_get(u, view_id, entry, KEY_MODE0f);
    193 
    194     if (*ipv6) {
    195         ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK0f);
    196         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    197             return(rv);
    198         }
    199         if (SOC_MEM_FIELD_VALID(u, view_id, IP_ADDR_MASK1f)) {
    200             ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK1f);
    201             if (*pfx) {
    202                 if (ipv4a != 0xffffffff)  {
    203                     return(SOC_E_PARAM);
    204                 }
    205                 *pfx += 32;
    206             } else {
    207                 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    208                     return(rv);
    209                 }
    210             }
    211         }
    212     } else {
    213         ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK0f);
    214         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    215             return(rv);
    216         }
    217     }
    218 
    219     SOC_IF_ERROR_RETURN(soc_hx5_lpm_flex_vrf_get(u, entry, view_id, vrf_id));
    220 
    221     return (SOC_E_NONE);
    222 }
    223 #endif