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