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