/* SPDX-License-Identifier: LGPL-2.1+ * Copyright © 2019 VMware, Inc. */ #include "alloc-util.h" #include "extract-word.h" #include "fileio.h" #include "parse-util.h" #include "tc-util.h" #include "time-util.h" int tc_init(double *ret_ticks_in_usec, uint32_t *ret_hz) { static double ticks_in_usec = -1; static uint32_t hz; if (ticks_in_usec < 0) { uint32_t clock_resolution, ticks_to_usec, usec_to_ticks; _cleanup_free_ char *line = NULL; double clock_factor; int r; r = read_one_line_file("/proc/net/psched", &line); if (r < 0) return r; r = sscanf(line, "%08x%08x%08x%08x", &ticks_to_usec, &usec_to_ticks, &clock_resolution, &hz); if (r < 4) return -EIO; clock_factor = (double) clock_resolution / USEC_PER_SEC; ticks_in_usec = (double) ticks_to_usec / usec_to_ticks * clock_factor; } if (ret_ticks_in_usec) *ret_ticks_in_usec = ticks_in_usec; if (ret_hz) *ret_hz = hz; return 0; } int tc_time_to_tick(usec_t t, uint32_t *ret) { double ticks_in_usec; usec_t a; int r; assert(ret); r = tc_init(&ticks_in_usec, NULL); if (r < 0) return r; a = t * ticks_in_usec; if (a > UINT32_MAX) return -ERANGE; *ret = a; return 0; } int parse_tc_percent(const char *s, uint32_t *percent) { int r; assert(s); assert(percent); r = parse_permille(s); if (r < 0) return r; *percent = (double) r / 1000 * UINT32_MAX; return 0; } int tc_transmit_time(uint64_t rate, uint32_t size, uint32_t *ret) { return tc_time_to_tick(USEC_PER_SEC * ((double)size / (double)rate), ret); } int tc_fill_ratespec_and_table(struct tc_ratespec *rate, uint32_t *rtab, uint32_t mtu) { uint32_t cell_log = 0; int r; if (mtu == 0) mtu = 2047; while ((mtu >> cell_log) > 255) cell_log++; for (size_t i = 0; i < 256; i++) { uint32_t sz; sz = (i + 1) << cell_log; if (sz < rate->mpu) sz = rate->mpu; r = tc_transmit_time(rate->rate, sz, &rtab[i]); if (r < 0) return r; } rate->cell_align = -1; rate->cell_log = cell_log; rate->linklayer = TC_LINKLAYER_ETHERNET; return 0; } int parse_handle(const char *t, uint32_t *ret) { _cleanup_free_ char *word = NULL; uint16_t major, minor; int r; assert(t); assert(ret); /* Extract the major number. */ r = extract_first_word(&t, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return r; if (r == 0) return -EINVAL; if (!t) return -EINVAL; r = safe_atou16_full(word, 16, &major); if (r < 0) return r; r = safe_atou16_full(t, 16, &minor); if (r < 0) return r; *ret = ((uint32_t) major << 16) | minor; return 0; }