From: Alan T. DeKok Date: Mon, 12 Jan 2026 22:42:04 +0000 (-0500) Subject: tweaks and cleanups for the statistics structures X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a8bd5d6d3e9165aedd59a00482d562f5e9b685f;p=thirdparty%2Ffreeradius-server.git tweaks and cleanups for the statistics structures --- diff --git a/share/dictionary/radius/dictionary.stats b/share/dictionary/radius/dictionary.stats index 1c601bf53f8..a1f6a525761 100644 --- a/share/dictionary/radius/dictionary.stats +++ b/share/dictionary/radius/dictionary.stats @@ -3,6 +3,8 @@ # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 # Version $Id$ # + +# mib-2 is 1.3.6.1.2.1 DEFINE mib-2 tlv internal BEGIN mib-2 @@ -11,16 +13,10 @@ ATTRIBUTE radiusMIB 67 tlv ATTRIBUTE radiusAuthentication 67.1 tlv ATTRIBUTE radiusAuthServMIB 67.1.1 tlv ATTRIBUTE radiusAuthServMIBObjects 67.1.1.1 tlv + +# radiusAuthServ is 1.3.6.1.2.1.67.1.1.1.1 ATTRIBUTE radiusAuthServ 67.1.1.1.1 tlv -# -# These names are huge and long. They also have most of the "full path" in them. -# we arguably want to convert these to more RADIUS style names, especially for -# the C structure names. -# -# i.e. get rid of the "radiusAuthServ" prefix, and change mashed camel case to -# camel case with dashes. -# ATTRIBUTE radiusAuthServIdent .1 string ATTRIBUTE radiusAuthServUpTime .2 time_delta precision=centiseconds ATTRIBUTE radiusAuthServResetTime .3 time_delta precision=centiseconds diff --git a/src/bin/radict.c b/src/bin/radict.c index 165853a933d..e13deea0bab 100644 --- a/src/bin/radict.c +++ b/src/bin/radict.c @@ -38,20 +38,24 @@ RCSID("$Id$") #endif typedef enum { - RADICT_OUT_FANCY = 1, + RADICT_OUT_INVALID = 0, + RADICT_OUT_FANCY, RADICT_OUT_CSV, RADICT_OUT_DICT, RADICT_OUT_STRUCT, RADICT_OUT_STATS_LINK, - RADICT_OUT_ATTR_DEF, + RADICT_OUT_ATTRS_H, + RADICT_OUT_BASE_C_DA_DEF, RADICT_OUT_ATTR_AUTOLOAD, + RADICT_OUT_STATS_H, } radict_out_t; static fr_dict_t *dicts[255]; static bool print_values = false; static bool print_headers = false; static bool print_recursive = false; -static bool mibs = false; +static char const *mib = NULL; +static char const *parent_oid = NULL; static radict_out_t output_format = RADICT_OUT_FANCY; static fr_dict_t **dict_end = dicts; @@ -72,7 +76,7 @@ static void usage(void) fprintf(stderr, " -E Export dictionary definitions.\n"); fprintf(stderr, " -h Print help text.\n"); fprintf(stderr, " -H Show the headers of each field.\n"); - fprintf(stderr, " -M Mangle names for MIBs.\n"); + fprintf(stderr, " -M Mangle names for MIB, and set MIB root.\n"); fprintf(stderr, " -p Set protocol by name\n"); fprintf(stderr, " -r Write out attributes recursively.\n"); fprintf(stderr, " -V Write out all attribute values.\n"); @@ -87,7 +91,7 @@ static int load_dicts(char const *dict_dir, char const *protocol) DIR *dir; struct dirent *dp; - INFO("Reading directory %s", dict_dir); + DEBUG("Reading directory %s", dict_dir); dir = opendir(dict_dir); if (!dir) { @@ -143,7 +147,7 @@ static int load_dicts(char const *dict_dir, char const *protocol) goto error; } - INFO("Loading dictionary: %s/dictionary", file_str); + DEBUG("Loading dictionary: %s/dictionary", file_str); if (fr_dict_protocol_afrom_file(dict_end, dp->d_name, NULL, __FILE__) < 0) { goto error; } @@ -327,7 +331,7 @@ static void da_normalize_name(fr_dict_attr_t const *da, char buffer[static FR_DI * The RADIUS MIBs have lots of repetition. So we do some simple mangling of the names to make * them easier to understand. */ - if (mibs && da->parent) { + if (mib && da->parent) { size_t len; len = strlen(da->parent->name); @@ -491,14 +495,14 @@ static void da_print_struct(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "} "); - fprintf(fp, "fr_"); + fprintf(fp, "fr_stats_"); da_print_name(fp, fr_dict_root(parent->dict)); fprintf(fp, "_"); da_print_name(fp, parent); fprintf(fp, "_t;\n"); } -static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent) +static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent, char const *prefix) { int i; fr_dict_attr_t const *da; @@ -508,10 +512,10 @@ static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent) da_normalize_name(parent, parent_name); - fprintf(fp, "static fr_dict_attr_t const *attr_%s;\n", parent_name); + fprintf(fp, "%sfr_dict_attr_t const *attr_%s;\n", prefix, parent_name); for (i = 1; (da = fr_dict_attr_child_by_num(parent, i)) != NULL; i++) { - fprintf(fp, "static fr_dict_attr_t const *attr_%s_", parent_name); + fprintf(fp, "%sfr_dict_attr_t const *attr_%s_", prefix, parent_name); da_print_name(fp, da); fprintf(fp, ";\n"); } @@ -519,6 +523,16 @@ static void da_print_attr_def(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "\n\n"); } +static void da_print_attrs_h(FILE *fp, fr_dict_attr_t const *parent) +{ + da_print_attr_def(fp, parent, "extern HIDDEN "); +} + +static void da_print_base_c_da_def(FILE *fp, fr_dict_attr_t const *parent) +{ + da_print_attr_def(fp, parent, ""); +} + /** Map data types to enum names representing those types */ #define ENUM_NAME(_x) [_x] = STRINGIFY(_x) @@ -580,18 +594,19 @@ static void da_print_stats_link(FILE *fp, fr_dict_attr_t const *parent) da_normalize_name(fr_dict_root(parent->dict), dict_name); da_normalize_name(parent, parent_name); - fprintf(fp, "fr_stats_link_t const fr_%s_%s_stats_link_t[] = {\n", dict_name, parent_name); + fprintf(fp, "fr_stats_link_t const fr_stats_link_%s_%s = {\n", dict_name, parent_name); - fprintf(fp, "\t.name = \"fr_%s_%s_t\",\n", dict_name, parent_name); - fprintf(fp, "\t.da_p = &attr_%s,\n", parent_name); - fprintf(fp, "\t.size = sizeof(fr_%s_%s_t),\n", dict_name, parent_name); + fprintf(fp, "\t.name = \"fr_stats_%s_%s_t\",\n", dict_name, parent_name); + fprintf(fp, "\t.root_p = &attr_%s,\n", parent_name); + if (mib) fprintf(fp, "\t.mib = \"%s\",\n", mib); + fprintf(fp, "\t.size = sizeof(fr_stats_%s_%s_t),\n", dict_name, parent_name); for (i = 1; fr_dict_attr_child_by_num(parent, i) != NULL; i++) { num_elements = i; } fprintf(fp, "\t.num_elements = %d,\n", num_elements); - fprintf(fp, "\t.entry = {\n"); + fprintf(fp, "\t.entry = (fr_stats_link_entry_t[]) { /* -Wgnu-flexible-array-initializer */\n"); /* * For locality, also print out data type and size. That way we _can_ dereference the da, but we @@ -605,7 +620,7 @@ static void da_print_stats_link(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "\t\t\t.type = %s,\n", fr_type_to_enum_name[da->type]); - fprintf(fp, "\t\t\t.offset = offsetof(fr_%s_%s_t, ", dict_name, parent_name); + fprintf(fp, "\t\t\t.offset = offsetof(fr_stats_%s_%s_t, ", dict_name, parent_name); da_print_name(fp, da); fprintf(fp, "),\n"); @@ -614,7 +629,7 @@ static void da_print_stats_link(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "\t\t},\n"); } - fprintf(fp, "\t};\n"); + fprintf(fp, "\t},\n"); fprintf(fp, "};\n\n"); } @@ -631,13 +646,14 @@ static void da_print_attr_autoload(FILE *fp, fr_dict_attr_t const *parent) da_normalize_name(parent, parent_name); /* - * @todo - print the full path to the name. - * - * @todo - print the enum for the data type + * Define the parent. */ fprintf(fp, "{ .out = &attr_%s, .name = \"%s\", .type = %s, .dict = &dict_%s },\n", - parent_name, parent->name, fr_type_to_enum_name[parent->type], dict_name); + parent_name, parent_oid, fr_type_to_enum_name[parent->type], dict_name); + /* + * And each child + */ for (i = 1; (da = fr_dict_attr_child_by_num(parent, i)) != NULL; i++) { fprintf(fp, "{ .out = &attr_%s_", parent_name); da_print_name(fp, da); @@ -648,6 +664,24 @@ static void da_print_attr_autoload(FILE *fp, fr_dict_attr_t const *parent) fprintf(fp, "\n\n"); } +static void da_print_stats_h(FILE *fp, fr_dict_attr_t const *parent) +{ + char dict_name[FR_DICT_ATTR_MAX_NAME_LEN + 1]; + char parent_name[FR_DICT_ATTR_MAX_NAME_LEN + 1]; + + CHECK_TYPE(parent); + + da_normalize_name(fr_dict_root(parent->dict), dict_name); + da_normalize_name(parent, parent_name); + + da_print_struct(fp, parent); + + fprintf(fp, "\n"); + + fprintf(fp, "extern fr_stats_link_t const fr_stats_link_%s_%s;\n\n", dict_name, parent_name); +} + + static void _raddict_export(fr_dict_t const *dict, uint64_t *count, uintptr_t *low, uintptr_t *high, fr_dict_attr_t const *da, unsigned int lvl) { unsigned int i; @@ -698,6 +732,35 @@ static void raddict_export(uint64_t *count, uintptr_t *low, uintptr_t *high, fr_ _raddict_export(dict, count, low, high, fr_dict_root(dict), 0); } +static fr_table_num_ordered_t const format_table[] = { + { L("fancy"), RADICT_OUT_FANCY }, + { L("csv"), RADICT_OUT_CSV }, + { L("dict"), RADICT_OUT_DICT }, + { L("struct"), RADICT_OUT_STRUCT }, + { L("stats_link"), RADICT_OUT_STATS_LINK }, + { L("attrs.h"), RADICT_OUT_ATTRS_H }, + { L("da_def"), RADICT_OUT_BASE_C_DA_DEF }, + { L("attr_autoload"), RADICT_OUT_ATTR_AUTOLOAD }, + { L("stats.h"), RADICT_OUT_STATS_H }, +}; +static size_t format_table_len = NUM_ELEMENTS(format_table); + +static fr_table_ptr_ordered_t const function_table[] = { + { L("fancy"), NULL }, + { L("csv"), NULL }, + { L("dict"), NULL }, + { L("struct"), (void *) da_print_struct }, + { L("stats_link"), (void *) da_print_stats_link }, + { L("attrs.h"), (void *) da_print_attrs_h }, + { L("da_def"), (void *) da_print_base_c_da_def }, + { L("attr_autoload"), (void *) da_print_attr_autoload }, + { L("stats.h"), (void *) da_print_stats_h }, +}; +static size_t function_table_len = NUM_ELEMENTS(function_table); + +typedef void (*da_print_func_t)(FILE *fp, fr_dict_attr_t const *da); + + /** * * @hidecallgraph @@ -712,6 +775,7 @@ int main(int argc, char *argv[]) bool file_export = false; bool alias = false; char const *protocol = NULL; + da_print_func_t func = NULL; TALLOC_CTX *autofree; @@ -734,7 +798,7 @@ int main(int argc, char *argv[]) fr_debug_lvl = 1; fr_log_fp = stdout; - while ((c = getopt(argc, argv, "AcfF:ED:Mp:rVxhH")) != -1) switch (c) { + while ((c = getopt(argc, argv, "AcfF:ED:M:p:rVxhH")) != -1) switch (c) { case 'A': alias = true; break; @@ -752,31 +816,13 @@ int main(int argc, char *argv[]) break; case 'F': - if (strcmp(optarg, "csv") == 0) { - output_format = RADICT_OUT_CSV; - - } else if (strcmp(optarg, "full") == 0) { - output_format = RADICT_OUT_CSV; - - } else if (strcmp(optarg, "dict") == 0) { - output_format = RADICT_OUT_DICT; - - } else if (strcmp(optarg, "struct") == 0) { - output_format = RADICT_OUT_STRUCT; - - } else if (strcmp(optarg, "stats_link") == 0) { - output_format = RADICT_OUT_STATS_LINK; - - } else if (strcmp(optarg, "attr_def") == 0) { - output_format = RADICT_OUT_ATTR_DEF; - - } else if (strcmp(optarg, "attr_autoload") == 0) { - output_format = RADICT_OUT_ATTR_AUTOLOAD; - - } else { + output_format = fr_table_value_by_str(format_table, optarg, RADICT_OUT_INVALID); + if (output_format == RADICT_OUT_INVALID) { fprintf(stderr, "Invalid output format '%s'\n", optarg); fr_exit(EXIT_FAILURE); } + + func = (da_print_func_t) fr_table_value_by_str(function_table, optarg, NULL); break; case 'E': @@ -788,7 +834,7 @@ int main(int argc, char *argv[]) break; case 'M': - mibs = true; + mib = optarg; break; case 'p': @@ -830,7 +876,7 @@ int main(int argc, char *argv[]) goto finish; } - INFO("Loading dictionary: %s/%s", dict_dir, FR_DICTIONARY_FILE); + DEBUG("Loading dictionary: %s/%s", dict_dir, FR_DICTIONARY_FILE); if (fr_dict_internal_afrom_file(dict_end++, FR_DICTIONARY_INTERNAL_DIR, __FILE__) < 0) { fr_perror("radict - Loading internal dictionary failed"); @@ -926,26 +972,11 @@ int main(int argc, char *argv[]) continue; } - switch (output_format) { - default: + if (!func) { da_print_info(*dict_p, da, 0); - break; - - case RADICT_OUT_STRUCT: - da_print_struct(stdout, da); - break; - - case RADICT_OUT_STATS_LINK: - da_print_stats_link(stdout, da); - break; - - case RADICT_OUT_ATTR_DEF: - da_print_attr_def(stdout, da); - break; - - case RADICT_OUT_ATTR_AUTOLOAD: - da_print_attr_autoload(stdout, da); - break; + } else { + parent_oid = attr; + func(stdout, da); } found = true; } while (++dict_p < dict_end); diff --git a/src/lib/util/stats.c b/src/lib/util/stats.c index aac8850cbaa..636df52aa7a 100644 --- a/src/lib/util/stats.c +++ b/src/lib/util/stats.c @@ -28,6 +28,9 @@ RCSID("$Id$") /** Convert a statistics structure to #fr_pair_t * + * @param[in] ctx talloc ctx + * @param[out] out where the output pairs will be stored + * @param[in] inst data structure defining this instance of the statistics */ int fr_stats_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_stats_instance_t const *inst) { @@ -253,22 +256,21 @@ bool fr_stats_iter_next(fr_stats_iter_t *iter) return false; } -int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter) +int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_instance_t const *inst, unsigned int index) { fr_value_box_t *box; uint8_t const *field; fr_dict_attr_t const *da; - fr_assert(iter->inst); - fr_assert(iter->current < iter->inst->def->num_elements); + if (index >= inst->def->num_elements) return 0; - da = *(iter->inst->def->entry[iter->current].da_p); + da = *(inst->def->entry[index].da_p); fr_assert(da != NULL); - box = fr_value_box_alloc(ctx, iter->inst->def->entry[iter->current].type, da); + box = fr_value_box_alloc(ctx, inst->def->entry[index].type, da); if (!box) return -1; - field = ((uint8_t const *) iter->inst->stats) + iter->inst->def->entry[iter->current].offset; + field = ((uint8_t const *) inst->stats) + inst->def->entry[index].offset; #undef COPY #define COPY(_type, _field) \ @@ -278,7 +280,7 @@ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_i switch (box->type) { case FR_TYPE_STRING: - if (!iter->inst->def->entry[iter->current].size) { + if (!inst->def->entry[index].size) { char const *str; memcpy(&str, field, sizeof(str)); @@ -294,7 +296,7 @@ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_i /* * Find the trailing NUL within the fixed-size field. */ - end = memchr(field, '\0', iter->inst->def->entry[iter->current].size); + end = memchr(field, '\0', inst->def->entry[index].size); if (fr_value_box_bstrndup(box, box, da, (char const *) field, (size_t) (end - field), false) < 0) { @@ -305,7 +307,7 @@ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_i case FR_TYPE_OCTETS: if (fr_value_box_memdup(box, box, da, field, - iter->inst->def->entry[iter->current].size, false) < 0) { + inst->def->entry[index].size, false) < 0) { goto fail; } break; @@ -330,3 +332,10 @@ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_i } +int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter) +{ + fr_assert(iter->inst); + fr_assert(iter->current < iter->inst->def->num_elements); + + return fr_stats_index_to_value_box(ctx, out, iter->inst, iter->current); +} diff --git a/src/lib/util/stats.h b/src/lib/util/stats.h index 99308162822..ab482eed32e 100644 --- a/src/lib/util/stats.h +++ b/src/lib/util/stats.h @@ -44,6 +44,7 @@ typedef struct { typedef struct { char const *name; //!< name of the stats structure fr_dict_attr_t const **root_p; //!< point to the autoload definition of the DA for this structure + char const *mib; //!< MIB root size_t size; //!< overall size of the structure size_t num_elements; //!< number of elements in the table. Note no "NULL" terminator fr_stats_link_entry_t entry[]; //!< the field entries, in offset order @@ -51,16 +52,12 @@ typedef struct { /** Common header for all statistics instances * - * def pointer to the definition of the structure for this instance - * path the full path to this instance - * uctx for any necessary callbacks - * entry in the doubly linked list of statics which all use the same "def". + * def pointer to the linking definition of the structure for this instance + * + * @todo - if we need additional tracking data (rb trees, dlists, etc.), they can go here. */ #define STATS_HEADER_COMMON \ - fr_stats_link_t const *def; \ - char const *path; \ - void *uctx; \ - fr_dlist_t entry + fr_stats_link_t const *def /** Generic statistics structure * @@ -83,7 +80,24 @@ typedef struct { /** Macro used when declaring a variable which contains the statistics * */ -#define FR_STATS_ENTRY(_name) fr_stats_## _name ## _instance_t +#define FR_STATS_ENTRY_DECL(_name, _var) fr_stats_## _name ## _instance_t _var; + +/** Macro used when initializing a variable which contains the statistics + * + */ +#define FR_STATS_ENTRY_INIT(_name, _var, _mib) \ + _var = (fr_stats_## _name ## _instance_t) { \ + .def = fr_stats_link_ ## _name ## _t, \ + .mib = _mib, \ + fr_stats_## _name ## _t stats = {}, \ + } + + +/** Macro used when referencing a linking structure + * + * .def = FR_STATS_LINK_NAME(radius_auth_serv), + */ +#define FR_STATS_LINK_NAME(_name) fr_stats_link_ ## _name ## _t /** Macro used to increment one field in the statistics structure * @@ -99,9 +113,10 @@ int fr_stats_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_stats_instance_t int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *out, fr_pair_list_t *in) CC_HINT(nonnull); int fr_stats_merge(fr_stats_instance_t *out, fr_stats_instance_t const *in) CC_HINT(nonnull); -void fr_stats_iter_init(fr_stats_instance_t const *in, fr_stats_iter_t *iter); -bool fr_stats_iter_next(fr_stats_iter_t *iter); -int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter); +void fr_stats_iter_init(fr_stats_instance_t const *in, fr_stats_iter_t *iter) CC_HINT(nonnull); +bool fr_stats_iter_next(fr_stats_iter_t *iter) CC_HINT(nonnull); +int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter) CC_HINT(nonnull); +int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_instance_t const *in, unsigned int index) CC_HINT(nonnull); #ifdef __cplusplus