1 /* 2 * Copyright (C) Mellanox Technologies Ltd. 2001-2019. ALL RIGHTS RESERVED. 3 * 4 * See file LICENSE for terms. 5 */ 6 7 #ifndef UCS_CONFIG_PARSER_H 8 #define UCS_CONFIG_PARSER_H 9 10 #include "types.h" 11 12 #include <ucs/datastruct/list.h> 13 #include <ucs/type/status.h> 14 #include <ucs/sys/stubs.h> 15 16 #include <stdio.h> 17 18 19 #define UCS_DEFAULT_ENV_PREFIX "UCX_" 20 #define UCS_CONFIG_ARRAY_MAX 128 21 22 BEGIN_C_DECLS 23 24 /** @file parser.h */ 25 26 /* 27 * Configuration varaibles syntax: 28 * 29 * name: <env_prefix><table_prefix><field_name> 30 * 31 * - env_prefix: supplied by user to ucs_config_read_XXX() API 32 * - table_prefix: defined in sub-tables. e.g IB_, UD_, ... 33 * - field_name: field_name as defined in the table. e.g ZCOPY_THRESH 34 * 35 * Examples of full variable names: 36 * - UCS_CIB_RNDV_THRESH 37 * - UCS_IB_TX_MODERATION 38 */ 39 40 typedef struct ucs_config_parser { 41 int (*read) (const char *buf, void *dest, const void *arg); 42 int (*write)(char *buf, size_t max, 43 const void *src, const void *arg); 44 ucs_status_t (*clone)(const void *src, void *dest, const void *arg); 45 void (*release)(void *ptr, const void *arg); 46 void (*help)(char *buf, size_t max, const void *arg); 47 const void *arg; 48 } ucs_config_parser_t; 49 50 51 typedef struct ucs_config_array { 52 size_t elem_size; 53 ucs_config_parser_t parser; 54 } ucs_config_array_t; 55 56 57 typedef struct ucs_config_field { 58 const char *name; 59 const char *dfl_value; 60 const char *doc; 61 size_t offset; 62 ucs_config_parser_t parser; 63 } ucs_config_field_t; 64 65 66 typedef struct ucs_ib_port_spec { 67 char *device_name; 68 unsigned port_num; 69 } ucs_ib_port_spec_t; 70 71 72 typedef struct ucs_range_spec { 73 unsigned first; /* the first value in the range */ 74 unsigned last; /* the last value in the range */ 75 } ucs_range_spec_t; 76 77 78 typedef struct ucs_config_global_list_entry { 79 const char *name; /* configuration table name */ 80 const char *prefix; /* configuration prefix */ 81 ucs_config_field_t *table; /* array of configuration fields */ 82 size_t size; /* size of config structure */ 83 ucs_list_link_t list; /* entry in global list */ 84 } ucs_config_global_list_entry_t; 85 86 87 typedef struct ucs_config_bw_spec { 88 char *name; 89 double bw; 90 } ucs_config_bw_spec_t; 91 92 93 #define UCS_CONFIG_EMPTY_GLOBAL_LIST_ENTRY \ 94 { \ 95 .name = "", \ 96 .prefix = "", \ 97 .table = NULL, \ 98 .size = 0, \ 99 } 100 101 102 #define UCS_CONFIG_REGISTER_TABLE_ENTRY(_entry) \ 103 UCS_STATIC_INIT { \ 104 ucs_list_add_tail(&ucs_config_global_list, &(_entry)->list); \ 105 } \ 106 \ 107 UCS_STATIC_CLEANUP { \ 108 ucs_list_del(&(_entry)->list); \ 109 } 110 111 #define UCS_CONFIG_REGISTER_TABLE(_table, _name, _prefix, _type) \ 112 static ucs_config_global_list_entry_t _table##_config_entry = { \ 113 .table = _table, \ 114 .name = _name, \ 115 .prefix = _prefix, \ 116 .size = sizeof(_type) \ 117 }; \ 118 UCS_CONFIG_REGISTER_TABLE_ENTRY(&_table##_config_entry); 119 120 extern ucs_list_link_t ucs_config_global_list; 121 122 /* 123 * Parsing and printing different data types 124 */ 125 126 int ucs_config_sscanf_string(const char *buf, void *dest, const void *arg); 127 int ucs_config_sprintf_string(char *buf, size_t max, const void *src, const void *arg); 128 ucs_status_t ucs_config_clone_string(const void *src, void *dest, const void *arg); 129 void ucs_config_release_string(void *ptr, const void *arg); 130 131 int ucs_config_sscanf_int(const char *buf, void *dest, const void *arg); 132 int ucs_config_sprintf_int(char *buf, size_t max, const void *src, const void *arg); 133 ucs_status_t ucs_config_clone_int(const void *src, void *dest, const void *arg); 134 135 int ucs_config_sscanf_uint(const char *buf, void *dest, const void *arg); 136 int ucs_config_sprintf_uint(char *buf, size_t max, const void *src, const void *arg); 137 ucs_status_t ucs_config_clone_uint(const void *src, void *dest, const void *arg); 138 139 int ucs_config_sscanf_ulong(const char *buf, void *dest, const void *arg); 140 int ucs_config_sprintf_ulong(char *buf, size_t max, const void *src, const void *arg); 141 ucs_status_t ucs_config_clone_ulong(const void *src, void *dest, const void *arg); 142 143 int ucs_config_sscanf_double(const char *buf, void *dest, const void *arg); 144 int ucs_config_sprintf_double(char *buf, size_t max, const void *src, const void *arg); 145 ucs_status_t ucs_config_clone_double(const void *src, void *dest, const void *arg); 146 147 int ucs_config_sscanf_hex(const char *buf, void *dest, const void *arg); 148 int ucs_config_sprintf_hex(char *buf, size_t max, const void *src, const void *arg); 149 150 int ucs_config_sscanf_bool(const char *buf, void *dest, const void *arg); 151 int ucs_config_sprintf_bool(char *buf, size_t max, const void *src, const void *arg); 152 153 int ucs_config_sscanf_ternary(const char *buf, void *dest, const void *arg); 154 int ucs_config_sprintf_ternary(char *buf, size_t max, const void *src, const void *arg); 155 156 int ucs_config_sscanf_on_off(const char *buf, void *dest, const void *arg); 157 158 int ucs_config_sscanf_on_off_auto(const char *buf, void *dest, const void *arg); 159 int ucs_config_sprintf_on_off_auto(char *buf, size_t max, const void *src, const void *arg); 160 161 int ucs_config_sscanf_enum(const char *buf, void *dest, const void *arg); 162 int ucs_config_sprintf_enum(char *buf, size_t max, const void *src, const void *arg); 163 void ucs_config_help_enum(char *buf, size_t max, const void *arg); 164 165 int ucs_config_sscanf_bitmap(const char *buf, void *dest, const void *arg); 166 int ucs_config_sprintf_bitmap(char *buf, size_t max, const void *src, const void *arg); 167 void ucs_config_help_bitmap(char *buf, size_t max, const void *arg); 168 169 int ucs_config_sscanf_bitmask(const char *buf, void *dest, const void *arg); 170 int ucs_config_sprintf_bitmask(char *buf, size_t max, const void *src, const void *arg); 171 172 int ucs_config_sscanf_time(const char *buf, void *dest, const void *arg); 173 int ucs_config_sprintf_time(char *buf, size_t max, const void *src, const void *arg); 174 175 int ucs_config_sscanf_bw(const char *buf, void *dest, const void *arg); 176 int ucs_config_sprintf_bw(char *buf, size_t max, const void *src, const void *arg); 177 178 int ucs_config_sscanf_bw_spec(const char *buf, void *dest, const void *arg); 179 int ucs_config_sprintf_bw_spec(char *buf, size_t max, const void *src, const void *arg); 180 ucs_status_t ucs_config_clone_bw_spec(const void *src, void *dest, const void *arg); 181 void ucs_config_release_bw_spec(void *ptr, const void *arg); 182 183 int ucs_config_sscanf_signo(const char *buf, void *dest, const void *arg); 184 int ucs_config_sprintf_signo(char *buf, size_t max, const void *src, const void *arg); 185 186 int ucs_config_sscanf_memunits(const char *buf, void *dest, const void *arg); 187 int ucs_config_sprintf_memunits(char *buf, size_t max, const void *src, const void *arg); 188 189 int ucs_config_sscanf_ulunits(const char *buf, void *dest, const void *arg); 190 int ucs_config_sprintf_ulunits(char *buf, size_t max, const void *src, const void *arg); 191 192 int ucs_config_sscanf_range_spec(const char *buf, void *dest, const void *arg); 193 int ucs_config_sprintf_range_spec(char *buf, size_t max, const void *src, const void *arg); 194 ucs_status_t ucs_config_clone_range_spec(const void *src, void *dest, const void *arg); 195 196 int ucs_config_sscanf_array(const char *buf, void *dest, const void *arg); 197 int ucs_config_sprintf_array(char *buf, size_t max, const void *src, const void *arg); 198 ucs_status_t ucs_config_clone_array(const void *src, void *dest, const void *arg); 199 void ucs_config_release_array(void *ptr, const void *arg); 200 void ucs_config_help_array(char *buf, size_t max, const void *arg); 201 202 int ucs_config_sscanf_table(const char *buf, void *dest, const void *arg); 203 ucs_status_t ucs_config_clone_table(const void *src, void *dest, const void *arg); 204 void ucs_config_release_table(void *ptr, const void *arg); 205 void ucs_config_help_table(char *buf, size_t max, const void *arg); 206 207 ucs_status_t ucs_config_clone_log_comp(const void *src, void *dst, const void *arg); 208 209 void ucs_config_release_nop(void *ptr, const void *arg); 210 void ucs_config_help_generic(char *buf, size_t max, const void *arg); 211 212 #define UCS_CONFIG_DEPRECATED_FIELD_OFFSET SIZE_MAX 213 214 /* Forward declaration of array. Should be in header file. */ 215 #define UCS_CONFIG_DECLARE_ARRAY(_name) \ 216 extern ucs_config_array_t ucs_config_array_##_name; 217 218 /* Definition of array of specific type. Should be in source file. */ 219 #define UCS_CONFIG_DEFINE_ARRAY(_name, _elem_size, ...) \ 220 ucs_config_array_t ucs_config_array_##_name = {_elem_size, __VA_ARGS__}; 221 222 #define UCS_CONFIG_TYPE_STRING {ucs_config_sscanf_string, ucs_config_sprintf_string, \ 223 ucs_config_clone_string, ucs_config_release_string, \ 224 ucs_config_help_generic, "string"} 225 226 #define UCS_CONFIG_TYPE_INT {ucs_config_sscanf_int, ucs_config_sprintf_int, \ 227 ucs_config_clone_int, ucs_config_release_nop, \ 228 ucs_config_help_generic, "integer"} 229 230 #define UCS_CONFIG_TYPE_UINT {ucs_config_sscanf_uint, ucs_config_sprintf_uint, \ 231 ucs_config_clone_uint, ucs_config_release_nop, \ 232 ucs_config_help_generic, "unsigned integer"} 233 234 #define UCS_CONFIG_TYPE_ULONG {ucs_config_sscanf_ulong, ucs_config_sprintf_ulong, \ 235 ucs_config_clone_ulong, ucs_config_release_nop, \ 236 ucs_config_help_generic, "unsigned long"} 237 238 #define UCS_CONFIG_TYPE_ULUNITS {ucs_config_sscanf_ulunits, ucs_config_sprintf_ulunits, \ 239 ucs_config_clone_ulong, ucs_config_release_nop, \ 240 ucs_config_help_generic, \ 241 "unsigned long: <number>, \"inf\", or \"auto\""} 242 243 #define UCS_CONFIG_TYPE_DOUBLE {ucs_config_sscanf_double, ucs_config_sprintf_double, \ 244 ucs_config_clone_double, ucs_config_release_nop, \ 245 ucs_config_help_generic, "floating point number"} 246 247 #define UCS_CONFIG_TYPE_HEX {ucs_config_sscanf_hex, ucs_config_sprintf_hex, \ 248 ucs_config_clone_uint, ucs_config_release_nop, \ 249 ucs_config_help_generic, \ 250 "hex representation of a number or \"auto\""} 251 252 #define UCS_CONFIG_TYPE_BOOL {ucs_config_sscanf_bool, ucs_config_sprintf_bool, \ 253 ucs_config_clone_int, ucs_config_release_nop, \ 254 ucs_config_help_generic, "<y|n>"} 255 256 #define UCS_CONFIG_TYPE_TERNARY {ucs_config_sscanf_ternary, ucs_config_sprintf_ternary, \ 257 ucs_config_clone_int, ucs_config_release_nop, \ 258 ucs_config_help_generic, "<yes|no|try>"} 259 260 #define UCS_CONFIG_TYPE_ON_OFF {ucs_config_sscanf_on_off, ucs_config_sprintf_on_off_auto, \ 261 ucs_config_clone_int, ucs_config_release_nop, \ 262 ucs_config_help_generic, "<on|off>"} 263 264 #define UCS_CONFIG_TYPE_ON_OFF_AUTO {ucs_config_sscanf_on_off_auto, ucs_config_sprintf_on_off_auto, \ 265 ucs_config_clone_int, ucs_config_release_nop, \ 266 ucs_config_help_generic, "<on|off|auto>"} 267 268 #define UCS_CONFIG_TYPE_ENUM(t) {ucs_config_sscanf_enum, ucs_config_sprintf_enum, \ 269 ucs_config_clone_uint, ucs_config_release_nop, \ 270 ucs_config_help_enum, t} 271 272 #define UCS_CONFIG_TYPE_BITMAP(t) {ucs_config_sscanf_bitmap, ucs_config_sprintf_bitmap, \ 273 ucs_config_clone_uint, ucs_config_release_nop, \ 274 ucs_config_help_bitmap, t} 275 276 #define UCS_CONFIG_TYPE_BITMASK {ucs_config_sscanf_bitmask, ucs_config_sprintf_bitmask, \ 277 ucs_config_clone_uint, ucs_config_release_nop, \ 278 ucs_config_help_generic, "bit count"} 279 280 #define UCS_CONFIG_TYPE_TIME {ucs_config_sscanf_time, ucs_config_sprintf_time, \ 281 ucs_config_clone_double, ucs_config_release_nop, \ 282 ucs_config_help_generic, "time value: <number>[s|us|ms|ns]"} 283 284 #define UCS_CONFIG_TYPE_BW {ucs_config_sscanf_bw, ucs_config_sprintf_bw, \ 285 ucs_config_clone_double, ucs_config_release_nop, \ 286 ucs_config_help_generic, \ 287 "bandwidth value: <number>[T|G|M|K]B|b[[p|/]s] or \"auto\""} 288 289 #define UCS_CONFIG_TYPE_BW_SPEC {ucs_config_sscanf_bw_spec, ucs_config_sprintf_bw_spec, \ 290 ucs_config_clone_bw_spec, ucs_config_release_bw_spec, \ 291 ucs_config_help_generic, \ 292 "device_name:<number>[T|G|M|K]B|b[[p|/]s] or device_name:auto"} 293 294 #define UCS_CONFIG_TYPE_LOG_COMP {ucs_config_sscanf_enum, ucs_config_sprintf_enum, \ 295 ucs_config_clone_log_comp, ucs_config_release_nop, \ 296 ucs_config_help_enum, ucs_log_level_names} 297 298 #define UCS_CONFIG_TYPE_SIGNO {ucs_config_sscanf_signo, ucs_config_sprintf_signo, \ 299 ucs_config_clone_int, ucs_config_release_nop, \ 300 ucs_config_help_generic, "system signal (number or SIGxxx)"} 301 302 #define UCS_CONFIG_TYPE_MEMUNITS {ucs_config_sscanf_memunits, ucs_config_sprintf_memunits, \ 303 ucs_config_clone_ulong, ucs_config_release_nop, \ 304 ucs_config_help_generic, \ 305 "memory units: <number>[b|kb|mb|gb], \"inf\", or \"auto\""} 306 307 #define UCS_CONFIG_TYPE_ARRAY(a) {ucs_config_sscanf_array, ucs_config_sprintf_array, \ 308 ucs_config_clone_array, ucs_config_release_array, \ 309 ucs_config_help_array, &ucs_config_array_##a} 310 311 #define UCS_CONFIG_TYPE_TABLE(t) {ucs_config_sscanf_table, NULL, \ 312 ucs_config_clone_table, ucs_config_release_table, \ 313 ucs_config_help_table, t} 314 315 #define UCS_CONFIG_TYPE_RANGE_SPEC {ucs_config_sscanf_range_spec,ucs_config_sprintf_range_spec, \ 316 ucs_config_clone_range_spec, ucs_config_release_nop, \ 317 ucs_config_help_generic, "numbers range: <number>-<number>"} 318 319 #define UCS_CONFIG_TYPE_DEPRECATED {(ucs_field_type(ucs_config_parser_t, read)) ucs_empty_function_do_assert, \ 320 (ucs_field_type(ucs_config_parser_t, write)) ucs_empty_function_do_assert, \ 321 (ucs_field_type(ucs_config_parser_t, clone)) ucs_empty_function_do_assert, \ 322 (ucs_field_type(ucs_config_parser_t, release))ucs_empty_function_do_assert, \ 323 (ucs_field_type(ucs_config_parser_t, help)) ucs_empty_function_do_assert, \ 324 ""} 325 326 /** 327 * Helpers for using an array of strings 328 */ 329 #define UCS_CONFIG_TYPE_STRING_ARRAY \ 330 UCS_CONFIG_TYPE_ARRAY(string) 331 332 UCS_CONFIG_DECLARE_ARRAY(string) 333 334 335 /** 336 * Helpers for Bandwidth units (see UCS_CONFIG_TYPE_BW) 337 */ 338 #define UCS_CONFIG_BW_AUTO ((double)-2) 339 #define UCS_CONFIG_BW_IS_AUTO(_value) ((ssize_t)(_value) == UCS_CONFIG_BW_AUTO) 340 341 342 /** 343 * Set default values for options. 344 * 345 * @param opts User-defined options structure to fill. 346 * @param fields Array of fields which define how to parse. 347 */ 348 ucs_status_t 349 ucs_config_parser_set_default_values(void *opts, ucs_config_field_t *fields); 350 351 352 /** 353 * Fill existing opts structure. 354 * 355 * @param opts User-defined options structure to fill. 356 * @param fields Array of fields which define how to parse. 357 * @param env_prefix Prefix to add to all environment variables, 358 * env_prefix may consist of multiple sub preifxes 359 * @param table_prefix Optional prefix to add to the variables of top-level table. 360 * @param ignore_errors Whether to ignore parsing errors and continue parsing 361 * other fields. 362 */ 363 ucs_status_t ucs_config_parser_fill_opts(void *opts, ucs_config_field_t *fields, 364 const char *env_prefix, 365 const char *table_prefix, 366 int ignore_errors); 367 368 /** 369 * Perform deep copy of the options structure. 370 * 371 * @param src User-defined options structure to copy from. 372 * @param dst User-defined options structure to copy to. 373 * @param table Array of fields which define the structure of the options. 374 */ 375 ucs_status_t ucs_config_parser_clone_opts(const void *src, void *dst, 376 ucs_config_field_t *fields); 377 378 /** 379 * Release the options fields. 380 * NOTE: Does not release the structure itself. 381 * 382 * @param opts User-defined options structure. 383 * @param table Array of fields which define the options. 384 */ 385 void ucs_config_parser_release_opts(void *opts, ucs_config_field_t *fields); 386 387 /** 388 * Print the options - names, values, documentation. 389 * 390 * @param stream Output stream to print to. 391 * @param opts User-defined options structure. 392 * @param fields Array of fields which define the options. 393 * @param table_prefix Optional prefix to add to the variables of top-level table. 394 * @param prefix Prefix to add to all environment variables. 395 * @param flags Flags which control the output. 396 */ 397 void ucs_config_parser_print_opts(FILE *stream, const char *title, const void *opts, 398 ucs_config_field_t *fields, const char *table_prefix, 399 const char *prefix, ucs_config_print_flags_t flags); 400 401 /** 402 * Print all options defined in the library - names, values, documentation. 403 * 404 * @param stream Output stream to print to. 405 * @param prefix Prefix to add to all environment variables. 406 * @param flags Flags which control the output. 407 */ 408 void ucs_config_parser_print_all_opts(FILE *stream, const char *prefix, 409 ucs_config_print_flags_t flags); 410 411 /** 412 * Read a value from options structure. 413 * 414 * @param opts User-defined options structure. 415 * @param fields Array of fields which define how to parse. 416 * @param name Option name including subtable prefixes. 417 * @param value Filled with option value (as a string). 418 * @param max Number of bytes reserved in 'value'. 419 */ 420 ucs_status_t ucs_config_parser_get_value(void *opts, ucs_config_field_t *fields, 421 const char *name, char *value, size_t max); 422 423 /** 424 * Modify existing opts structure with new setting. 425 * 426 * @param opts User-defined options structure. 427 * @param fields Array of fields which define how to parse. 428 * @param name Option name to modify. 429 * @param value Value to assign. 430 */ 431 ucs_status_t ucs_config_parser_set_value(void *opts, ucs_config_field_t *fields, 432 const char *name, const char *value); 433 434 /** 435 * Wrapper for `ucs_config_parser_warn_unused_env_vars` 436 * that ensures that this is called once 437 * 438 * @param env_prefix Environment variable prefix. 439 * env_prefix may consist of multiple sub prefixex 440 */ 441 442 void ucs_config_parser_warn_unused_env_vars_once(const char *env_prefix); 443 444 /** 445 * Translate configuration value of "MEMUNITS" type to actual value. 446 * 447 * @param config_size Size specified by configuration. 448 * @param auto_size Default size when configured to 'auto'. 449 * @param max_size Maximal size to trim "inf". 450 */ 451 size_t ucs_config_memunits_get(size_t config_size, size_t auto_size, 452 size_t max_size); 453 454 /** 455 * Look for a string in config names array. 456 * 457 * @param config_names lookup array of counters patterns. 458 * @param str string to search. 459 */ 460 int ucs_config_names_search(ucs_config_names_array_t config_names, 461 const char *str); 462 463 END_C_DECLS 464 465 #endif 466