/* * Helper function for call_modgroup, and call_modredundantloadbalance * * Returns 0 for "stop", and "1" for continue. */ static int call_one(int component, modcallable *p, REQUEST *request, int *priority, int *result) { int r; #ifdef RAD_REQUEST_OPTION_STOP_NOW /* * A module has taken too long to process the request, * and we've been told to stop processing it. */ if (request->options & RAD_REQUEST_OPTION_STOP_NOW) { *result = RLM_MODULE_FAIL; return 0; } #endif /* Call this child by recursing into modcall */ r = modcall(component, p, request); #if 0 DEBUG2("%s: action for %s is %s", comp2str[component], lrad_int2str(rcode_table, r, "??"), action2str(p->actions[r])); #endif /* * Find an action to go with the child's result. If it is * "return", break out of the loop so the rest of the * children in the list will be skipped. */ if (p->actions[r] == MOD_ACTION_RETURN) { *result = r; return 0; } /* If "reject" break out of the loop and return reject */ if (p->actions[r] == MOD_ACTION_REJECT) { *result = RLM_MODULE_REJECT; return 0; } /* * Otherwise, the action is a number, the preference * level of this return code. If no higher preference has * been seen yet, remember this one . */ if (p->actions[r] >= *priority) { *result = r; *priority = p->actions[r]; } return 1; }
/* If you suspect a bug in the parser, you'll want to use these dump * functions. dump_tree should reproduce a whole tree exactly as it was found * in radiusd.conf, but in long form (all actions explicitly defined) */ static void dump_mc(modcallable *c, int indent) { int i; if(c->type==MOD_SINGLE) { modsingle *single = mod_callabletosingle(c); DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t", single->modinst->name); } else { modgroup *g = mod_callabletogroup(c); modcallable *p; DEBUG("%.*sgroup {", indent, "\t\t\t\t\t\t\t\t\t\t\t"); for(p = g->children;p;p = p->next) dump_mc(p, indent+1); } for(i = 0; i<RLM_MODULE_NUMCODES; ++i) { DEBUG("%.*s%s = %s", indent+1, "\t\t\t\t\t\t\t\t\t\t\t", lrad_int2str(rcode_table, i, "??"), action2str(c->actions[i])); } DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t"); }
/* * The guts of the protocol. This handles the many paths a request can * make, including retrying the request and acknowledgements, and dealing * with timeouts and successfull replies. */ static void state_machine( proto_t * p, p_action_t action, pkt_t * pkt) { pstate_t curstate; p_action_t retaction; proto_debug(1, _("protocol: state_machine: initial: p %p action %s pkt %p\n"), p, action2str(action), (void *)NULL); assert(p != NULL); assert(action == PA_RCVDATA || pkt == NULL); assert(p->state != NULL); for (;;) { proto_debug(1, _("protocol: state_machine: p %p state %s action %s\n"), p, pstate2str(p->state), action2str(action)); if (pkt != NULL) { proto_debug(1, _("protocol: pkt: %s (t %d) orig REQ (t %d cur %d)\n"), pkt_type2str(pkt->type), (int)CURTIME, (int)p->origtime, (int)p->curtime); proto_debug(1, _("protocol: pkt contents:\n-----\n%s-----\n"), pkt->body); } /* * p->state is a function pointer to the current state a request * is in. * * We keep track of the last state we were in so we can make * sure states which return PA_CONTINUE really have transitioned * the request to a new state. */ curstate = p->state; if (action == PA_ABORT) /* * If the passed action indicates a terminal error, then we * need to move to abort right away. */ retaction = PA_ABORT; else /* * Else we run the state and perform the action it * requests. */ retaction = (*curstate)(p, action, pkt); proto_debug(1, _("protocol: state_machine: p %p state %s returned %s\n"), p, pstate2str(p->state), action2str(retaction)); /* * The state function is expected to return one of the following * p_action_t's. */ switch (retaction) { /* * Request is still waiting for more data off of the network. * Setup to receive another pkt, and wait for the recv event * to occur. */ case PA_CONTPEND: (*p->continuation)(p->datap, pkt, p->security_handle); /* FALLTHROUGH */ case PA_PENDING: proto_debug(1, _("protocol: state_machine: p %p state %s: timeout %d\n"), p, pstate2str(p->state), (int)p->timeout); /* * Get the security layer to register a receive event for this * security handle on our behalf. Have it timeout in p->timeout * seconds. */ security_recvpkt(p->security_handle, recvpkt_callback, p, (int)p->timeout); return; /* * Request has moved to another state. Loop and run it again. */ case PA_CONTINUE: assert(p->state != curstate); proto_debug(1, _("protocol: state_machine: p %p: moved from %s to %s\n"), p, pstate2str(curstate), pstate2str(p->state)); continue; /* * Request has failed in some way locally. The security_handle will * contain an appropriate error message via security_geterror(). Set * pkt to NULL to indicate failure to the callback, and then * fall through to the common finish code. * * Note that remote failures finish via PA_FINISH, because they did * complete successfully locally. */ case PA_ABORT: pkt = NULL; /* FALLTHROUGH */ /* * Request has completed successfully. * Free up resources the request has used, call the continuation * function specified by the caller and quit. */ case PA_FINISH: (*p->continuation)(p->datap, pkt, p->security_handle); security_close(p->security_handle); amfree(p->hostname); amfree(p->req.body); amfree(p); return; default: assert(0); break; /* in case asserts are turned off */ } /*NOTREACHED*/ } /*NOTREACHED*/ }
static void stats_print(struct stats_record *stats_rec, struct stats_record *stats_prev, bool err_only) { unsigned int nr_cpus = bpf_num_possible_cpus(); int rec_i = 0, i, to_cpu; double t = 0, pps = 0; /* Header */ printf("%-15s %-7s %-12s %-12s %-9s\n", "XDP-event", "CPU:to", "pps", "drop-pps", "extra-info"); /* tracepoint: xdp:xdp_redirect_* */ if (err_only) rec_i = REDIR_ERROR; for (; rec_i < REDIR_RES_MAX; rec_i++) { struct record_u64 *rec, *prev; char *fmt1 = "%-15s %-7d %'-12.0f %'-12.0f %s\n"; char *fmt2 = "%-15s %-7s %'-12.0f %'-12.0f %s\n"; rec = &stats_rec->xdp_redirect[rec_i]; prev = &stats_prev->xdp_redirect[rec_i]; t = calc_period_u64(rec, prev); for (i = 0; i < nr_cpus; i++) { struct u64rec *r = &rec->cpu[i]; struct u64rec *p = &prev->cpu[i]; pps = calc_pps_u64(r, p, t); if (pps > 0) printf(fmt1, "XDP_REDIRECT", i, rec_i ? 0.0: pps, rec_i ? pps : 0.0, err2str(rec_i)); } pps = calc_pps_u64(&rec->total, &prev->total, t); printf(fmt2, "XDP_REDIRECT", "total", rec_i ? 0.0: pps, rec_i ? pps : 0.0, err2str(rec_i)); } /* tracepoint: xdp:xdp_exception */ for (rec_i = 0; rec_i < XDP_ACTION_MAX; rec_i++) { struct record_u64 *rec, *prev; char *fmt1 = "%-15s %-7d %'-12.0f %'-12.0f %s\n"; char *fmt2 = "%-15s %-7s %'-12.0f %'-12.0f %s\n"; rec = &stats_rec->xdp_exception[rec_i]; prev = &stats_prev->xdp_exception[rec_i]; t = calc_period_u64(rec, prev); for (i = 0; i < nr_cpus; i++) { struct u64rec *r = &rec->cpu[i]; struct u64rec *p = &prev->cpu[i]; pps = calc_pps_u64(r, p, t); if (pps > 0) printf(fmt1, "Exception", i, 0.0, pps, action2str(rec_i)); } pps = calc_pps_u64(&rec->total, &prev->total, t); if (pps > 0) printf(fmt2, "Exception", "total", 0.0, pps, action2str(rec_i)); } /* cpumap enqueue stats */ for (to_cpu = 0; to_cpu < MAX_CPUS; to_cpu++) { char *fmt1 = "%-15s %3d:%-3d %'-12.0f %'-12.0f %'-10.2f %s\n"; char *fmt2 = "%-15s %3s:%-3d %'-12.0f %'-12.0f %'-10.2f %s\n"; struct record *rec, *prev; char *info_str = ""; double drop, info; rec = &stats_rec->xdp_cpumap_enqueue[to_cpu]; prev = &stats_prev->xdp_cpumap_enqueue[to_cpu]; t = calc_period(rec, prev); for (i = 0; i < nr_cpus; i++) { struct datarec *r = &rec->cpu[i]; struct datarec *p = &prev->cpu[i]; pps = calc_pps(r, p, t); drop = calc_drop(r, p, t); info = calc_info(r, p, t); if (info > 0) { info_str = "bulk-average"; info = pps / info; /* calc average bulk size */ } if (pps > 0) printf(fmt1, "cpumap-enqueue", i, to_cpu, pps, drop, info, info_str); } pps = calc_pps(&rec->total, &prev->total, t); if (pps > 0) { drop = calc_drop(&rec->total, &prev->total, t); info = calc_info(&rec->total, &prev->total, t); if (info > 0) { info_str = "bulk-average"; info = pps / info; /* calc average bulk size */ } printf(fmt2, "cpumap-enqueue", "sum", to_cpu, pps, drop, info, info_str); } } /* cpumap kthread stats */ { char *fmt1 = "%-15s %-7d %'-12.0f %'-12.0f %'-10.0f %s\n"; char *fmt2 = "%-15s %-7s %'-12.0f %'-12.0f %'-10.0f %s\n"; struct record *rec, *prev; double drop, info; char *i_str = ""; rec = &stats_rec->xdp_cpumap_kthread; prev = &stats_prev->xdp_cpumap_kthread; t = calc_period(rec, prev); for (i = 0; i < nr_cpus; i++) { struct datarec *r = &rec->cpu[i]; struct datarec *p = &prev->cpu[i]; pps = calc_pps(r, p, t); drop = calc_drop(r, p, t); info = calc_info(r, p, t); if (info > 0) i_str = "sched"; if (pps > 0 || drop > 0) printf(fmt1, "cpumap-kthread", i, pps, drop, info, i_str); } pps = calc_pps(&rec->total, &prev->total, t); drop = calc_drop(&rec->total, &prev->total, t); info = calc_info(&rec->total, &prev->total, t); if (info > 0) i_str = "sched-sum"; printf(fmt2, "cpumap-kthread", "total", pps, drop, info, i_str); } /* devmap ndo_xdp_xmit stats */ { char *fmt1 = "%-15s %-7d %'-12.0f %'-12.0f %'-10.2f %s %s\n"; char *fmt2 = "%-15s %-7s %'-12.0f %'-12.0f %'-10.2f %s %s\n"; struct record *rec, *prev; double drop, info, err; char *i_str = ""; char *err_str = ""; rec = &stats_rec->xdp_devmap_xmit; prev = &stats_prev->xdp_devmap_xmit; t = calc_period(rec, prev); for (i = 0; i < nr_cpus; i++) { struct datarec *r = &rec->cpu[i]; struct datarec *p = &prev->cpu[i]; pps = calc_pps(r, p, t); drop = calc_drop(r, p, t); info = calc_info(r, p, t); err = calc_err(r, p, t); if (info > 0) { i_str = "bulk-average"; info = (pps+drop) / info; /* calc avg bulk */ } if (err > 0) err_str = "drv-err"; if (pps > 0 || drop > 0) printf(fmt1, "devmap-xmit", i, pps, drop, info, i_str, err_str); } pps = calc_pps(&rec->total, &prev->total, t); drop = calc_drop(&rec->total, &prev->total, t); info = calc_info(&rec->total, &prev->total, t); err = calc_err(&rec->total, &prev->total, t); if (info > 0) { i_str = "bulk-average"; info = (pps+drop) / info; /* calc avg bulk */ } if (err > 0) err_str = "drv-err"; printf(fmt2, "devmap-xmit", "total", pps, drop, info, i_str, err_str); } printf("\n"); }
return "read unprotect"; case ACT_ERASE_ONLY: return "flash erase"; case ACT_CRC: return "memory crc"; default: return ""; }; } static void err_multi_action(enum actions new) { fprintf(stderr, "ERROR: Invalid options !\n" "\tCan't execute \"%s\" and \"%s\" at the same time.\n", action2str(action), action2str(new)); } static int is_addr_in_ram(uint32_t addr) { return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; } static int is_addr_in_flash(uint32_t addr) { return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; } /* returns the page that contains address "addr" */ static int flash_addr_to_page_floor(uint32_t addr) {