alpm_tr.c (9928B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * File: alpm_tr.c 7 * Purpose: ALPM trace & log 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <soc/mem.h> 13 #include <soc/drv.h> 14 #include <soc/debug.h> 15 #include <soc/error.h> 16 #include <soc/format.h> 17 #include <soc/lpm.h> 18 #include <soc/trident2.h> 19 #include <soc/tomahawk.h> 20 21 #include <shared/util.h> 22 #include <shared/l3.h> 23 24 #if defined(ALPM_ENABLE) 25 26 #include <bcm/l3.h> 27 #include <bcm_int/esw/l3.h> 28 #include <bcm_int/esw/firebolt.h> 29 #include <bcm_int/esw/alpm.h> 30 #include <bcm_int/esw/alpm_util.h> 31 32 #include <sal/appl/io.h> 33 34 _alpm_trace_t *alpm_trace[SOC_MAX_NUM_DEVICES]; 35 36 /* ALPM trace log enable */ 37 int 38 alpm_trace_set(int u, int val) 39 { 40 if (ALPMTR(u) == NULL) { 41 cli_out("alpm trace not initialized yet\n"); 42 return BCM_E_INIT; 43 } 44 45 ALPMTR_TRACE_EN(u) = val; 46 return BCM_E_NONE; 47 } 48 49 /* ALPM trace wrap enable */ 50 int 51 alpm_trace_wrap_set(int u, int val) 52 { 53 if (ALPMTR(u) == NULL) { 54 cli_out("alpm trace not initialized yet\n"); 55 return BCM_E_INIT; 56 } 57 58 ALPMTR_WRAP_EN(u) = val; 59 return BCM_E_NONE; 60 } 61 62 /* ALPM trace log clear */ 63 int 64 alpm_trace_clear(int u) 65 { 66 if (ALPMTR(u) == NULL) { 67 cli_out("alpm trace not initialized yet\n"); 68 return BCM_E_INIT; 69 } 70 71 if (ALPMTR_INITED(u)) { 72 ALPMTR_CNT(u) = 0; 73 ALPMTR_CURR(u) = ALPMTR_START(u) = ALPMTR_BUF(u); 74 cli_out("alpm trace log deleted\n"); 75 } 76 77 return BCM_E_NONE; 78 } 79 80 /* ALPM trace periodic sanity check (route add & delete) 81 enable = -1 for show trace sanity, 82 enable = 0 means trace sanity check disabled 83 enable > 0 means sanity check freq 84 */ 85 int 86 alpm_trace_sanity(int u, int enable, int start, int end) 87 { 88 if (ALPMTR(u) == NULL) { 89 cli_out("alpm trace not initialized yet\n"); 90 return BCM_E_INIT; 91 } 92 93 if (enable >= 0) { 94 ALPMTR_SANITY_EN(u) = enable; 95 ALPMTR_SANITY_START(u) = start; 96 ALPMTR_SANITY_END(u) = end; 97 } 98 99 if (ALPMTR_SANITY_EN(u) == 0) { 100 cli_out("alpm trace sanity disabled\n"); 101 } else { 102 cli_out("alpm trace sanity enabled (enable:%d start:%d end:%d)\n", 103 ALPMTR_SANITY_EN(u), ALPMTR_SANITY_START(u), 104 ALPMTR_SANITY_END(u)); 105 } 106 107 return BCM_E_NONE; 108 } 109 110 /* ALPM trace log for defip route op (ALPM_TRACE_ADD or ALPM_TRACE_DELETE) */ 111 int 112 alpm_trace_log(int u, int op, _bcm_defip_cfg_t *cfg, int nh_idx, int rc) 113 { 114 int i, alloc_sz; 115 int rv = BCM_E_NONE; 116 117 if (ALPMTR(u) == NULL) { 118 return BCM_E_INIT; 119 } 120 if (!ALPMTR_TRACE_EN(u)) { 121 return rv; 122 } 123 if ((!ALPMTR_WRAP_EN(u)) && ALPMTR_WRAP(u)) { 124 return rv; /* if trace wrap is disabled and next log will be wrapped */ 125 } 126 127 if (!ALPMTR_INITED(u)) { 128 ALPMTR_CNT(u) = 0; 129 /* Use ALPM_TRACE_SIZE+1 just for reaching buf limit check */ 130 alloc_sz = sizeof(_alpm_log_t) * (ALPM_TRACE_SIZE + 1); 131 ALPM_ALLOC_EG(ALPMTR_BUF(u), alloc_sz, "alpm trace log"); 132 ALPMTR_CURR(u) = ALPMTR_START(u) = ALPMTR_BUF(u); 133 ALPMTR_INITED(u) = TRUE; 134 } 135 136 if (ALPMTR_BUF(u) == NULL) { 137 return rv; 138 } 139 140 ALPMTR_CURR(u)->op = op; 141 ALPMTR_CURR(u)->rc = rc; 142 ALPMTR_CURR(u)->seq = ALPMTR_CNT(u); 143 if (cfg) { 144 ALPMTR_CURR(u)->flags = cfg->defip_flags; 145 ALPMTR_CURR(u)->vrf = cfg->defip_vrf; 146 ALPMTR_CURR(u)->nh_idx = nh_idx; 147 ALPMTR_CURR(u)->sublen = (uint16)(cfg->defip_sub_len & 0xffff); 148 if (cfg->defip_flags & BCM_L3_IP6) { 149 for (i = 0; i < 16; i++) { 150 ALPMTR_CURR(u)->u.ip6[i] = cfg->defip_ip6_addr[i]; 151 } 152 } else { 153 ALPMTR_CURR(u)->u.ip = cfg->defip_ip_addr; 154 } 155 } 156 /* When current log reaches start log (rollover), except 157 the initial setting curr=start (without log cnt) */ 158 if ((ALPMTR_CURR(u) == ALPMTR_START(u)) && ALPMTR_CNT(u)) { 159 ALPMTR_START(u)++; /* advancing start log */ 160 /* when start log reaches buf limit, it goes to buf[0] */ 161 if (ALPMTR_START(u) == &ALPMTR(u)->buf[ALPM_TRACE_SIZE]) { 162 ALPMTR_START(u) = ALPMTR_BUF(u); 163 } 164 } 165 166 ALPMTR_CURR(u)++; 167 /* when current log reaches buf limit, it goes to buf[0] */ 168 if (ALPMTR_CURR(u) == &ALPMTR(u)->buf[ALPM_TRACE_SIZE]) { 169 ALPMTR_CURR(u) = ALPMTR_BUF(u); 170 ALPMTR_WRAP(u) = TRUE; /* next log will be wrapped */ 171 } 172 173 ALPMTR_CNT(u)++; 174 175 /* Periodic sanity check */ 176 if (ALPMTR_SANITY_EN(u) && (ALPMTR_CNT(u) >= ALPMTR_SANITY_START(u)) && 177 (((ALPMTR_CNT(u) - ALPMTR_SANITY_START(u)) % ALPMTR_SANITY_EN(u)) == 0) && 178 (ALPMTR_SANITY_END(u) <= 0 || ALPMTR_CNT(u) <= ALPMTR_SANITY_END(u))) { 179 rv = bcm_esw_alpm_sanity_check(u, 0, 0, 1); 180 if (BCM_FAILURE(rv)) { 181 ALPM_ERR(("ALPM trace sanity failed!\n")); 182 } 183 } 184 185 return rv; 186 187 bad: 188 if (ALPMTR_BUF(u) != NULL) { 189 alpm_util_free(ALPMTR_BUF(u)); 190 ALPMTR_BUF(u) = NULL; 191 } 192 return rv; 193 } 194 195 /* ALPM trace log (pointer p) display in (data) string */ 196 void 197 alpm_trace_print(int u, int showflags, _alpm_log_t *p, char *data) 198 { 199 int egress_idx_min; 200 char flags_st[14] = {0}; 201 char rc_st[40] = {0}; 202 char ip_st[SAL_IPADDR_STR_LEN]; /* only for IPv4 */ 203 char mask_st[SAL_IPADDR_STR_LEN]; 204 205 egress_idx_min = (p->flags & BCM_L3_MULTIPATH) ? /* 200000 : 100000 */ 206 BCM_XGS3_MPATH_EGRESS_IDX_MIN(u) : BCM_XGS3_EGRESS_IDX_MIN(u); 207 208 rc_st[0] = 0; 209 if (BCM_FAILURE(p->rc)) { 210 sal_sprintf(rc_st, "; #seq=%d return failed (%d)", p->seq, p->rc); 211 } else { 212 sal_sprintf(rc_st, "; #seq=%d", p->seq); 213 } 214 215 flags_st[0] = 0; 216 if (showflags) { 217 sal_sprintf(flags_st, " f=0x%08x", p->flags); 218 } 219 220 if (p->op == ALPM_TRACE_OP_DELETE_ALL) { 221 sal_sprintf(data, "l3 defip clear %s\n", rc_st); 222 } else { 223 if (p->flags & BCM_L3_IP6) { /* IPv6 */ 224 if (p->op == ALPM_TRACE_OP_ADD) { /* l3 ip6route add */ 225 sal_sprintf(data, "l3 ip6route add vrf=%d ip=%02x%02x:%02x%02x:%02x%02x" 226 ":%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x " 227 "masklen=%d intf=%d replace=%d ecmp=%d%s%s\n", 228 p->vrf, 229 p->u.ip6[0], 230 p->u.ip6[1], 231 p->u.ip6[2], 232 p->u.ip6[3], 233 p->u.ip6[4], 234 p->u.ip6[5], 235 p->u.ip6[6], 236 p->u.ip6[7], 237 p->u.ip6[8], 238 p->u.ip6[9], 239 p->u.ip6[10], 240 p->u.ip6[11], 241 p->u.ip6[12], 242 p->u.ip6[13], 243 p->u.ip6[14], 244 p->u.ip6[15], 245 p->sublen, 246 p->nh_idx + egress_idx_min, 247 p->flags & BCM_L3_REPLACE ? 1 : 0, 248 p->flags & BCM_L3_MULTIPATH ? 1 : 0, 249 flags_st, rc_st); 250 } else { /* l3 ip6route delete */ 251 sal_sprintf(data, "l3 ip6route delete vrf=%d ip=%02x%02x:%02x%02x:" 252 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:" 253 "%02x%02x masklen=%d%s%s\n", 254 p->vrf, 255 p->u.ip6[0], 256 p->u.ip6[1], 257 p->u.ip6[2], 258 p->u.ip6[3], 259 p->u.ip6[4], 260 p->u.ip6[5], 261 p->u.ip6[6], 262 p->u.ip6[7], 263 p->u.ip6[8], 264 p->u.ip6[9], 265 p->u.ip6[10], 266 p->u.ip6[11], 267 p->u.ip6[12], 268 p->u.ip6[13], 269 p->u.ip6[14], 270 p->u.ip6[15], 271 p->sublen, 272 flags_st, rc_st); 273 } 274 } else { /* IPv4 */ 275 alpm_util_fmt_ipaddr(ip_st, p->u.ip); 276 alpm_util_fmt_ipaddr(mask_st, bcm_ip_mask_create(p->sublen)); 277 if (p->op == ALPM_TRACE_OP_ADD) { /* l3 defip add */ 278 sal_sprintf(data, "l3 defip add vrf=%d ip=%s mask=%s intf=%d replace=%d ecmp=%d%s%s\n", 279 p->vrf, 280 ip_st, 281 mask_st, 282 p->nh_idx + egress_idx_min, 283 p->flags & BCM_L3_REPLACE ? 1 : 0, 284 p->flags & BCM_L3_MULTIPATH ? 1 : 0, 285 flags_st, rc_st); 286 } else { /* l3 defip delete */ 287 sal_sprintf(data, "l3 defip delete vrf=%d ip=%s mask=%s%s%s\n", 288 p->vrf, 289 ip_st, 290 mask_st, 291 flags_st, rc_st); 292 } 293 } 294 } 295 } 296 297 int 298 bcm_esw_alpm_trace_init(int u) 299 { 300 int rv = BCM_E_NONE; 301 int alloc_sz; 302 303 alloc_sz = sizeof(_alpm_trace_t); 304 ALPM_ALLOC_EG(ALPMTR(u), alloc_sz, "ALPMTR"); 305 306 /* Init ALPMTR variables */ 307 ALPMTR_TRACE_EN(u) = soc_property_get(u, "alpm_trace_enable", 0); 308 ALPMTR_SANITY_EN(u) = soc_property_get(u, "alpm_trace_sanity", 0); 309 ALPMTR_WRAP_EN(u) = soc_property_get(u, "alpm_trace_wrap", 0); 310 311 ALPM_INFO(("bcm_esw_alpm_trace_init: trace %d wrap %d\n", 312 ALPMTR_TRACE_EN(u), ALPMTR_WRAP_EN(u))); 313 return rv; 314 bad: 315 bcm_esw_alpm_trace_deinit(u); 316 return rv; 317 } 318 319 int 320 bcm_esw_alpm_trace_deinit(int u) 321 { 322 int rv = BCM_E_NONE; 323 324 if (ALPMTR(u) != NULL) { 325 326 if (ALPMTR_BUF(u) != NULL) { 327 alpm_util_free(ALPMTR_BUF(u)); 328 ALPMTR_BUF(u) = NULL; 329 } 330 331 alpm_util_free(ALPMTR(u)); 332 ALPMTR(u) = NULL; 333 } 334 335 ALPM_INFO(("bcm_esw_alpm_trace_deinit!\n")); 336 return rv; 337 } 338 339 #endif /* ALPM_ENABLE */