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