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 (7149B)


      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_TRIDENT3_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_td3_lpm_flex_ip4entry0_to_0
     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_td3_lpm_flex_ip4entry0_to_0(int u, void *src, void *dst, uint32 key_type, int copy_hit)
     51 {
     52     uint32      ipv4a;
     53     uint32      ipv4_pdd[SOC_MAX_MEM_WORDS];
     54 
     55     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, VALID0f);
     56     soc_mem_field32_set(u, L3_DEFIPm, dst, VALID0f, ipv4a);
     57     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE0f);
     58     soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE0f, ipv4a);
     59     soc_mem_field_get(u, L3_DEFIPm, src, MASK0f, ipv4_pdd);
     60     soc_mem_field_set(u, L3_DEFIPm, dst, MASK0f, ipv4_pdd);
     61     soc_mem_field_get(u, L3_DEFIPm, src, KEY0f, ipv4_pdd);
     62     soc_mem_field_set(u, L3_DEFIPm, dst, KEY0f, ipv4_pdd);
     63     soc_mem_field_get(u, L3_DEFIPm, src, POLICY_DATA0f, ipv4_pdd);
     64     soc_mem_field_set(u, L3_DEFIPm, dst, POLICY_DATA0f, ipv4_pdd);
     65 
     66     if (copy_hit) {
     67         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, HIT0f);
     68         soc_mem_field32_set(u, L3_DEFIPm, dst, HIT0f, ipv4a);
     69     }
     70     return(SOC_E_NONE);
     71 }
     72 /*
     73  * Function:
     74  *      soc_td3_lpm_flex_ip4entry0_to_1
     75  * Purpose:
     76  *      copy half-wide flex entry from src to dest.
     77  *      src and dst can be same.
     78  * Parameters:
     79  *      unit      - (IN)SOC unit number.
     80  *      src       - (IN)source buffer
     81  *      dest      - (IN)destination buffer
     82  *      copy_hit  - (IN)copy hit bit as well
     83  * Returns:
     84  *      BCM_E_XXX
     85  */
     86 int
     87 soc_td3_lpm_flex_ip4entry0_to_1(int u, void *src, void *dst, uint32 key_type, int copy_hit)
     88 {
     89     uint32      ipv4a;
     90     uint32      ipv4_pdd[SOC_MAX_MEM_WORDS];
     91 
     92     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, VALID0f);
     93     soc_mem_field32_set(u, L3_DEFIPm, dst, VALID1f, ipv4a);
     94     ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, DATA_TYPE0f);
     95     soc_mem_field32_set(u, L3_DEFIPm, dst, DATA_TYPE1f, ipv4a);
     96     soc_mem_field_get(u, L3_DEFIPm, src, MASK0f, ipv4_pdd);
     97     soc_mem_field_set(u, L3_DEFIPm, dst, MASK1f, ipv4_pdd);
     98     soc_mem_field_get(u, L3_DEFIPm, src, KEY0f, ipv4_pdd);
     99     soc_mem_field_set(u, L3_DEFIPm, dst, KEY1f, ipv4_pdd);
    100     soc_mem_field_get(u, L3_DEFIPm, src, POLICY_DATA0f, ipv4_pdd);
    101     soc_mem_field_set(u, L3_DEFIPm, dst, POLICY_DATA1f, ipv4_pdd);
    102 
    103     if (copy_hit) {
    104         ipv4a = soc_mem_field32_get(u, L3_DEFIPm, src, HIT0f);
    105         soc_mem_field32_set(u, L3_DEFIPm, dst, HIT1f, ipv4a);
    106     }
    107 
    108     return(SOC_E_NONE);
    109 }
    110 /*
    111  * Function:
    112  *      soc_td3_lpm_flex_vrf_get
    113  * Purpose:
    114  *      Service routine used to translate hw flex entry specific vrf id to API format.
    115  * Parameters:
    116  *      unit      - (IN)SOC unit number.
    117  *      lpm_entry - (IN)Route info buffer from hw.
    118  *      view_id   - (IN)View-id for the flex entry
    119  *      vrf_id    - (OUT)Virtual router id.
    120  * Returns:
    121  *      BCM_E_XXX
    122  */
    123 STATIC int
    124 soc_td3_lpm_flex_vrf_get(int unit, void *lpm_entry, uint32 view_id, int *vrf)
    125 {
    126     int vrf_id;
    127 
    128     /* Get Virtual Router id if supported. */
    129     if (SOC_MEM_FIELD_VALID(unit, view_id, VRF_ID_MASK0f)){
    130         vrf_id = soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_0f);
    131 
    132         /* Special vrf's handling. */
    133         if (soc_mem_field32_get(unit, view_id, lpm_entry, VRF_ID_MASK0f)) {
    134             *vrf = vrf_id;
    135         } else if (SOC_VRF_MAX(unit) == vrf_id) {
    136             *vrf = SOC_L3_VRF_GLOBAL;
    137         } else {
    138             *vrf = SOC_L3_VRF_OVERRIDE;
    139             if (SOC_MEM_FIELD_VALID(unit, view_id, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf)) {
    140                 uint32 action_set = soc_mem_field32_get(unit, view_id, lpm_entry,
    141                                                 FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETf);
    142                 if (soc_format_field32_get(unit, FORWARDING_3_MISC_ATTRIBUTES_ACTION_SETfmt,
    143                                            &action_set, GLOBAL_ROUTEf)) {
    144                     *vrf = SOC_L3_VRF_GLOBAL;
    145                 }
    146             }
    147 #if 0
    148     
    149             /* GLOBAL_HIGH is meaningless for lpm, use it to indicate OVERRIDE */
    150             if (SOC_MEM_FIELD_VALID(unit, L3_DEFIPm, GLOBAL_HIGH0f)) {
    151                 if (SOC_MEM_OPT_F32_GET(unit, L3_DEFIPm, lpm_entry, GLOBAL_HIGH0f)){
    152                     *vrf = SOC_L3_VRF_OVERRIDE;
    153                 }
    154             }
    155 #endif
    156         }
    157     } else {
    158         /* No vrf support on this device. */
    159         *vrf = SOC_L3_VRF_DEFAULT;
    160     }
    161     return (SOC_E_NONE);
    162 }
    163 /*
    164  * Function:
    165  *      soc_td3_lpm_flex_prefix_length_get
    166  * Purpose:
    167  *      soc_td3_lpm_flex_prefix_length_get (Extract vrf weighted  prefix lenght from the 
    168  *      hw entry based on ip, mask & vrf)
    169  * Parameters:
    170  *      unit      - (IN)SOC unit number.
    171  *      entry     - (IN)Route info buffer from hw.
    172  *      pfx_len   - (OUT)Prefix len
    173  * Returns:
    174  *      BCM_E_XXX
    175  */
    176 int
    177 soc_td3_lpm_flex_prefix_length_get(int u, void *entry, int *ipv6, int *vrf_id, int *pfx, uint32 key_type)
    178 {
    179     int         rv;
    180     uint32      ipv4a;
    181     soc_mem_t   view_id;
    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_td3_lpm_flex_vrf_get(u, entry, view_id, vrf_id));
    220 
    221     return (SOC_E_NONE);
    222 }
    223 #endif