]>
Commit | Line | Data |
---|---|---|
0f5bd7fe SS |
1 | /* SPDX-License-Identifier: LGPL-2.1+ |
2 | * Copyright © 2019 VMware, Inc. */ | |
3 | ||
4 | #include "alloc-util.h" | |
2a096331 | 5 | #include "extract-word.h" |
0f5bd7fe SS |
6 | #include "fileio.h" |
7 | #include "parse-util.h" | |
8 | #include "tc-util.h" | |
9 | #include "time-util.h" | |
10 | ||
d9eacc1c YW |
11 | int tc_init(double *ret_ticks_in_usec, uint32_t *ret_hz) { |
12 | static double ticks_in_usec = -1; | |
13 | static uint32_t hz; | |
0f5bd7fe | 14 | |
d9eacc1c YW |
15 | if (ticks_in_usec < 0) { |
16 | uint32_t clock_resolution, ticks_to_usec, usec_to_ticks; | |
17 | _cleanup_free_ char *line = NULL; | |
18 | double clock_factor; | |
19 | int r; | |
0f5bd7fe | 20 | |
d9eacc1c YW |
21 | r = read_one_line_file("/proc/net/psched", &line); |
22 | if (r < 0) | |
23 | return r; | |
0f5bd7fe | 24 | |
d9eacc1c YW |
25 | r = sscanf(line, "%08x%08x%08x%08x", &ticks_to_usec, &usec_to_ticks, &clock_resolution, &hz); |
26 | if (r < 4) | |
27 | return -EIO; | |
28 | ||
29 | clock_factor = (double) clock_resolution / USEC_PER_SEC; | |
30 | ticks_in_usec = (double) ticks_to_usec / usec_to_ticks * clock_factor; | |
31 | } | |
32 | ||
33 | if (ret_ticks_in_usec) | |
34 | *ret_ticks_in_usec = ticks_in_usec; | |
35 | if (ret_hz) | |
36 | *ret_hz = hz; | |
0f5bd7fe SS |
37 | |
38 | return 0; | |
39 | } | |
40 | ||
41 | int tc_time_to_tick(usec_t t, uint32_t *ret) { | |
d9eacc1c | 42 | double ticks_in_usec; |
0f5bd7fe SS |
43 | usec_t a; |
44 | int r; | |
45 | ||
46 | assert(ret); | |
47 | ||
d9eacc1c YW |
48 | r = tc_init(&ticks_in_usec, NULL); |
49 | if (r < 0) | |
50 | return r; | |
0f5bd7fe SS |
51 | |
52 | a = t * ticks_in_usec; | |
53 | if (a > UINT32_MAX) | |
54 | return -ERANGE; | |
55 | ||
56 | *ret = a; | |
57 | return 0; | |
58 | } | |
59 | ||
60 | int parse_tc_percent(const char *s, uint32_t *percent) { | |
61 | int r; | |
62 | ||
63 | assert(s); | |
64 | assert(percent); | |
65 | ||
66 | r = parse_permille(s); | |
67 | if (r < 0) | |
68 | return r; | |
69 | ||
70 | *percent = (double) r / 1000 * UINT32_MAX; | |
71 | return 0; | |
72 | } | |
dcfc23ae YW |
73 | |
74 | int tc_transmit_time(uint64_t rate, uint32_t size, uint32_t *ret) { | |
75 | return tc_time_to_tick(USEC_PER_SEC * ((double)size / (double)rate), ret); | |
76 | } | |
77 | ||
78 | int tc_fill_ratespec_and_table(struct tc_ratespec *rate, uint32_t *rtab, uint32_t mtu) { | |
79 | uint32_t cell_log = 0; | |
80 | int r; | |
81 | ||
82 | if (mtu == 0) | |
83 | mtu = 2047; | |
84 | ||
85 | while ((mtu >> cell_log) > 255) | |
86 | cell_log++; | |
87 | ||
88 | for (size_t i = 0; i < 256; i++) { | |
89 | uint32_t sz; | |
90 | ||
91 | sz = (i + 1) << cell_log; | |
92 | if (sz < rate->mpu) | |
93 | sz = rate->mpu; | |
94 | r = tc_transmit_time(rate->rate, sz, &rtab[i]); | |
95 | if (r < 0) | |
96 | return r; | |
97 | } | |
98 | ||
99 | rate->cell_align = -1; | |
100 | rate->cell_log = cell_log; | |
101 | rate->linklayer = TC_LINKLAYER_ETHERNET; | |
102 | return 0; | |
103 | } | |
2a096331 YW |
104 | |
105 | int parse_handle(const char *t, uint32_t *ret) { | |
106 | _cleanup_free_ char *word = NULL; | |
107 | uint16_t major, minor; | |
108 | int r; | |
109 | ||
110 | assert(t); | |
111 | assert(ret); | |
112 | ||
113 | /* Extract the major number. */ | |
114 | r = extract_first_word(&t, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); | |
115 | if (r < 0) | |
116 | return r; | |
117 | if (r == 0) | |
118 | return -EINVAL; | |
119 | if (!t) | |
120 | return -EINVAL; | |
121 | ||
122 | r = safe_atou16_full(word, 16, &major); | |
123 | if (r < 0) | |
124 | return r; | |
125 | ||
126 | r = safe_atou16_full(t, 16, &minor); | |
127 | if (r < 0) | |
128 | return r; | |
129 | ||
130 | *ret = ((uint32_t) major << 16) | minor; | |
131 | return 0; | |
132 | } |