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


      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:     Maverick2 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_MAVERICK2_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_mv2_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_mv2_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_mv2_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_mv2_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         }
    144     } else {
    145         /* No vrf support on this device. */
    146         *vrf = SOC_L3_VRF_DEFAULT;
    147     }
    148     return (SOC_E_NONE);
    149 }
    150 /*
    151  * Function:
    152  *      soc_mv2_lpm_flex_prefix_length_get
    153  * Purpose:
    154  *      soc_mv2_lpm_flex_prefix_length_get (Extract vrf weighted  prefix lenght from the
    155  *      hw entry based on ip, mask & vrf)
    156  * Parameters:
    157  *      unit      - (IN)SOC unit number.
    158  *      entry     - (IN)Route info buffer from hw.
    159  *      pfx_len   - (OUT)Prefix len
    160  * Returns:
    161  *      BCM_E_XXX
    162  */
    163 int
    164 soc_mv2_lpm_flex_prefix_length_get(int u, void *entry, int *ipv6, int *vrf_id, int *pfx, uint32 key_type)
    165 {
    166     int         rv;
    167     uint32      ipv4a;
    168     soc_mem_t   view_id;
    169 
    170     if (pfx == NULL) {
    171         return SOC_E_INTERNAL;
    172     }
    173 
    174     SOC_IF_ERROR_RETURN(
    175         soc_flow_db_mem_to_view_id_get(u,
    176                     L3_DEFIPm,
    177                     key_type,
    178                     SOC_FLOW_DB_DATA_TYPE_INVALID,
    179                     0,
    180                     NULL,
    181                     (uint32*) &view_id));
    182 
    183     *ipv6 = soc_mem_field32_get(u, view_id, entry, KEY_MODE0f);
    184 
    185     if (*ipv6) {
    186         ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK0f);
    187         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    188             return(rv);
    189         }
    190         if (SOC_MEM_FIELD_VALID(u, view_id, IP_ADDR_MASK1f)) {
    191             ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK1f);
    192             if (*pfx) {
    193                 if (ipv4a != 0xffffffff)  {
    194                     return(SOC_E_PARAM);
    195                 }
    196                 *pfx += 32;
    197             } else {
    198                 if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    199                     return(rv);
    200                 }
    201             }
    202         }
    203     } else {
    204         ipv4a = soc_mem_field32_get(u, view_id, entry, IP_ADDR_MASK0f);
    205         if ((rv = _ipmask2pfx(ipv4a, pfx)) < 0) {
    206             return(rv);
    207         }
    208     }
    209 
    210     SOC_IF_ERROR_RETURN(soc_mv2_lpm_flex_vrf_get(u, entry, view_id, vrf_id));
    211 
    212     return (SOC_E_NONE);
    213 }
    214 #endif