/* * Copyright (C) Mellanox Technologies Ltd. 2001-2019. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifndef UCS_CONFIG_PARSER_H #define UCS_CONFIG_PARSER_H #include "types.h" #include #include #include #include #define UCS_CONFIG_PREFIX "UCX_" #define UCS_CONFIG_ARRAY_MAX 128 BEGIN_C_DECLS /** @file parser.h */ /* * Configuration varaibles syntax: * * name: * * - env_prefix: supplied by user to ucs_config_read_XXX() API * - table_prefix: defined in sub-tables. e.g IB_, UD_, ... * - field_name: field_name as defined in the table. e.g ZCOPY_THRESH * * Examples of full variable names: * - UCS_CIB_RNDV_THRESH * - UCS_IB_TX_MODERATION */ typedef struct ucs_config_parser { int (*read) (const char *buf, void *dest, const void *arg); int (*write)(char *buf, size_t max, const void *src, const void *arg); ucs_status_t (*clone)(const void *src, void *dest, const void *arg); void (*release)(void *ptr, const void *arg); void (*help)(char *buf, size_t max, const void *arg); const void *arg; } ucs_config_parser_t; typedef struct ucs_config_array { size_t elem_size; ucs_config_parser_t parser; } ucs_config_array_t; typedef struct ucs_config_field { const char *name; const char *dfl_value; const char *doc; size_t offset; ucs_config_parser_t parser; } ucs_config_field_t; typedef struct ucs_ib_port_spec { char *device_name; unsigned port_num; } ucs_ib_port_spec_t; typedef struct ucs_range_spec { unsigned first; /* the first value in the range */ unsigned last; /* the last value in the range */ } ucs_range_spec_t; typedef struct ucs_config_global_list_entry { const char *name; /* configuration table name */ const char *prefix; /* configuration prefix */ ucs_config_field_t *table; /* array of configuration fields */ size_t size; /* size of config structure */ ucs_list_link_t list; /* entry in global list */ } ucs_config_global_list_entry_t; typedef struct ucs_config_bw_spec { char *name; double bw; } ucs_config_bw_spec_t; #define UCS_CONFIG_EMPTY_GLOBAL_LIST_ENTRY \ { \ .name = "", \ .prefix = "", \ .table = NULL, \ .size = 0, \ } #define UCS_CONFIG_REGISTER_TABLE_ENTRY(_entry) \ UCS_STATIC_INIT { \ extern ucs_list_link_t ucs_config_global_list; \ ucs_list_add_tail(&ucs_config_global_list, &(_entry)->list); \ } \ \ UCS_STATIC_CLEANUP { \ ucs_list_del(&(_entry)->list); \ } #define UCS_CONFIG_REGISTER_TABLE(_table, _name, _prefix, _type) \ static ucs_config_global_list_entry_t _table##_config_entry = { \ .table = _table, \ .name = _name, \ .prefix = _prefix, \ .size = sizeof(_type) \ }; \ UCS_CONFIG_REGISTER_TABLE_ENTRY(&_table##_config_entry); /* * Parsing and printing different data types */ int ucs_config_sscanf_string(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_string(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_string(const void *src, void *dest, const void *arg); void ucs_config_release_string(void *ptr, const void *arg); int ucs_config_sscanf_int(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_int(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_int(const void *src, void *dest, const void *arg); int ucs_config_sscanf_uint(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_uint(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_uint(const void *src, void *dest, const void *arg); int ucs_config_sscanf_ulong(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_ulong(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_ulong(const void *src, void *dest, const void *arg); int ucs_config_sscanf_double(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_double(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_double(const void *src, void *dest, const void *arg); int ucs_config_sscanf_hex(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_hex(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_bool(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_bool(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_ternary(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_ternary(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_on_off(const char *buf, void *dest, const void *arg); int ucs_config_sscanf_on_off_auto(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_on_off_auto(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_enum(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_enum(char *buf, size_t max, const void *src, const void *arg); void ucs_config_help_enum(char *buf, size_t max, const void *arg); int ucs_config_sscanf_bitmap(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_bitmap(char *buf, size_t max, const void *src, const void *arg); void ucs_config_help_bitmap(char *buf, size_t max, const void *arg); int ucs_config_sscanf_bitmask(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_bitmask(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_time(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_time(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_bw(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_bw(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_bw_spec(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_bw_spec(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_bw_spec(const void *src, void *dest, const void *arg); void ucs_config_release_bw_spec(void *ptr, const void *arg); int ucs_config_sscanf_signo(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_signo(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_memunits(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_memunits(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_ulunits(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_ulunits(char *buf, size_t max, const void *src, const void *arg); int ucs_config_sscanf_range_spec(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_range_spec(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_range_spec(const void *src, void *dest, const void *arg); int ucs_config_sscanf_array(const char *buf, void *dest, const void *arg); int ucs_config_sprintf_array(char *buf, size_t max, const void *src, const void *arg); ucs_status_t ucs_config_clone_array(const void *src, void *dest, const void *arg); void ucs_config_release_array(void *ptr, const void *arg); void ucs_config_help_array(char *buf, size_t max, const void *arg); int ucs_config_sscanf_table(const char *buf, void *dest, const void *arg); ucs_status_t ucs_config_clone_table(const void *src, void *dest, const void *arg); void ucs_config_release_table(void *ptr, const void *arg); void ucs_config_help_table(char *buf, size_t max, const void *arg); void ucs_config_release_nop(void *ptr, const void *arg); void ucs_config_help_generic(char *buf, size_t max, const void *arg); #define UCS_CONFIG_DEPRECATED_FIELD_OFFSET SIZE_MAX /* Forward declaration of array. Should be in header file. */ #define UCS_CONFIG_DECLARE_ARRAY(_name) \ extern ucs_config_array_t ucs_config_array_##_name; /* Definition of array of specific type. Should be in source file. */ #define UCS_CONFIG_DEFINE_ARRAY(_name, _elem_size, ...) \ ucs_config_array_t ucs_config_array_##_name = {_elem_size, __VA_ARGS__}; #define UCS_CONFIG_TYPE_STRING {ucs_config_sscanf_string, ucs_config_sprintf_string, \ ucs_config_clone_string, ucs_config_release_string, \ ucs_config_help_generic, "string"} #define UCS_CONFIG_TYPE_INT {ucs_config_sscanf_int, ucs_config_sprintf_int, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, "integer"} #define UCS_CONFIG_TYPE_UINT {ucs_config_sscanf_uint, ucs_config_sprintf_uint, \ ucs_config_clone_uint, ucs_config_release_nop, \ ucs_config_help_generic, "unsigned integer"} #define UCS_CONFIG_TYPE_ULONG {ucs_config_sscanf_ulong, ucs_config_sprintf_ulong, \ ucs_config_clone_ulong, ucs_config_release_nop, \ ucs_config_help_generic, "unsigned long"} #define UCS_CONFIG_TYPE_ULUNITS {ucs_config_sscanf_ulunits, ucs_config_sprintf_ulunits, \ ucs_config_clone_ulong, ucs_config_release_nop, \ ucs_config_help_generic, \ "unsigned long: , \"inf\", or \"auto\""} #define UCS_CONFIG_TYPE_DOUBLE {ucs_config_sscanf_double, ucs_config_sprintf_double, \ ucs_config_clone_double, ucs_config_release_nop, \ ucs_config_help_generic, "floating point number"} #define UCS_CONFIG_TYPE_HEX {ucs_config_sscanf_hex, ucs_config_sprintf_hex, \ ucs_config_clone_uint, ucs_config_release_nop, \ ucs_config_help_generic, \ "hex representation of a number or \"auto\""} #define UCS_CONFIG_TYPE_BOOL {ucs_config_sscanf_bool, ucs_config_sprintf_bool, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, ""} #define UCS_CONFIG_TYPE_TERNARY {ucs_config_sscanf_ternary, ucs_config_sprintf_ternary, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, ""} #define UCS_CONFIG_TYPE_ON_OFF {ucs_config_sscanf_on_off, ucs_config_sprintf_on_off_auto, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, ""} #define UCS_CONFIG_TYPE_ON_OFF_AUTO {ucs_config_sscanf_on_off_auto, ucs_config_sprintf_on_off_auto, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, ""} #define UCS_CONFIG_TYPE_ENUM(t) {ucs_config_sscanf_enum, ucs_config_sprintf_enum, \ ucs_config_clone_uint, ucs_config_release_nop, \ ucs_config_help_enum, t} #define UCS_CONFIG_TYPE_BITMAP(t) {ucs_config_sscanf_bitmap, ucs_config_sprintf_bitmap, \ ucs_config_clone_uint, ucs_config_release_nop, \ ucs_config_help_bitmap, t} #define UCS_CONFIG_TYPE_BITMASK {ucs_config_sscanf_bitmask, ucs_config_sprintf_bitmask, \ ucs_config_clone_uint, ucs_config_release_nop, \ ucs_config_help_generic, "bit count"} #define UCS_CONFIG_TYPE_TIME {ucs_config_sscanf_time, ucs_config_sprintf_time, \ ucs_config_clone_double, ucs_config_release_nop, \ ucs_config_help_generic, "time value: [s|us|ms|ns]"} #define UCS_CONFIG_TYPE_BW {ucs_config_sscanf_bw, ucs_config_sprintf_bw, \ ucs_config_clone_double, ucs_config_release_nop, \ ucs_config_help_generic, \ "bandwidth value: [T|G|M|K]B|b[[p|/]s] or \"auto\""} #define UCS_CONFIG_TYPE_BW_SPEC {ucs_config_sscanf_bw_spec, ucs_config_sprintf_bw_spec, \ ucs_config_clone_bw_spec, ucs_config_release_bw_spec, \ ucs_config_help_generic, \ "device_name:[T|G|M|K]B|b[[p|/]s] or device_name:auto"} #define UCS_CONFIG_TYPE_SIGNO {ucs_config_sscanf_signo, ucs_config_sprintf_signo, \ ucs_config_clone_int, ucs_config_release_nop, \ ucs_config_help_generic, "system signal (number or SIGxxx)"} #define UCS_CONFIG_TYPE_MEMUNITS {ucs_config_sscanf_memunits, ucs_config_sprintf_memunits, \ ucs_config_clone_ulong, ucs_config_release_nop, \ ucs_config_help_generic, \ "memory units: [b|kb|mb|gb], \"inf\", or \"auto\""} #define UCS_CONFIG_TYPE_ARRAY(a) {ucs_config_sscanf_array, ucs_config_sprintf_array, \ ucs_config_clone_array, ucs_config_release_array, \ ucs_config_help_array, &ucs_config_array_##a} #define UCS_CONFIG_TYPE_TABLE(t) {ucs_config_sscanf_table, NULL, \ ucs_config_clone_table, ucs_config_release_table, \ ucs_config_help_table, t} #define UCS_CONFIG_TYPE_RANGE_SPEC {ucs_config_sscanf_range_spec,ucs_config_sprintf_range_spec, \ ucs_config_clone_range_spec, ucs_config_release_nop, \ ucs_config_help_generic, "numbers range: -"} #define UCS_CONFIG_TYPE_DEPRECATED {(ucs_field_type(ucs_config_parser_t, read)) ucs_empty_function_do_assert, \ (ucs_field_type(ucs_config_parser_t, write)) ucs_empty_function_do_assert, \ (ucs_field_type(ucs_config_parser_t, clone)) ucs_empty_function_do_assert, \ (ucs_field_type(ucs_config_parser_t, release))ucs_empty_function_do_assert, \ (ucs_field_type(ucs_config_parser_t, help)) ucs_empty_function_do_assert, \ ""} /* * Helpers for using an array of strings. */ #define UCS_CONFIG_TYPE_STRING_ARRAY \ UCS_CONFIG_TYPE_ARRAY(string) UCS_CONFIG_DECLARE_ARRAY(string) /** * Set default values for options. * * @param opts User-defined options structure to fill. * @param fields Array of fields which define how to parse. */ ucs_status_t ucs_config_parser_set_default_values(void *opts, ucs_config_field_t *fields); /** * Fill existing opts structure. * * @param opts User-defined options structure to fill. * @param fields Array of fields which define how to parse. * @param env_prefix Prefix to add to all environment variables. * @param table_prefix Optional prefix to add to the variables of top-level table. * @param ignore_errors Whether to ignore parsing errors and continue parsing * other fields. */ ucs_status_t ucs_config_parser_fill_opts(void *opts, ucs_config_field_t *fields, const char *env_prefix, const char *table_prefix, int ignore_errors); /** * Perform deep copy of the options structure. * * @param src User-defined options structure to copy from. * @param dst User-defined options structure to copy to. * @param table Array of fields which define the structure of the options. */ ucs_status_t ucs_config_parser_clone_opts(const void *src, void *dst, ucs_config_field_t *fields); /** * Release the options fields. * NOTE: Does not release the structure itself. * * @param opts User-defined options structure. * @param table Array of fields which define the options. */ void ucs_config_parser_release_opts(void *opts, ucs_config_field_t *fields); /** * Print the options - names, values, documentation. * * @param stream Output stream to print to. * @param opts User-defined options structure. * @param fields Array of fields which define the options. * @param table_prefix Optional prefix to add to the variables of top-level table. * @param flags Flags which control the output. */ void ucs_config_parser_print_opts(FILE *stream, const char *title, const void *opts, ucs_config_field_t *fields, const char *table_prefix, ucs_config_print_flags_t flags); /** * Print all options defined in the library - names, values, documentation. * * @param stream Output stream to print to. * @param flags Flags which control the output. */ void ucs_config_parser_print_all_opts(FILE *stream, ucs_config_print_flags_t flags); /** * Read a value from options structure. * * @param opts User-defined options structure. * @param fields Array of fields which define how to parse. * @param name Option name including subtable prefixes. * @param value Filled with option value (as a string). * @param max Number of bytes reserved in 'value'. */ ucs_status_t ucs_config_parser_get_value(void *opts, ucs_config_field_t *fields, const char *name, char *value, size_t max); /** * Modify existing opts structure with new setting. * * @param opts User-defined options structure. * @param fields Array of fields which define how to parse. * @param name Option name to modify. * @param value Value to assign. */ ucs_status_t ucs_config_parser_set_value(void *opts, ucs_config_field_t *fields, const char *name, const char *value); /** * Check all UCX_ environment variables have been used so far by the * configuration parser, issue a warning if not. Called just before program exit. */ void ucs_config_parser_warn_unused_env_vars(); /** * Wrapper for `ucs_config_parser_warn_unused_env_vars` * that ensures that this is called once */ void ucs_config_parser_warn_unused_env_vars_once(); /** * Translate configuration value of "MEMUNITS" type to actual value. * * @param config_size Size specified by configuration. * @param auto_size Default size when configured to 'auto'. * @param max_size Maximal size to trim "inf". */ size_t ucs_config_memunits_get(size_t config_size, size_t auto_size, size_t max_size); /** * Look for a string in config names array. * * @param config_names lookup array of counters patterns. * @param str string to search. */ int ucs_config_names_search(ucs_config_names_array_t config_names, const char *str); END_C_DECLS #endif