]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/tc/tc-util.c
network: tc: add more settings for HTB
[thirdparty/systemd.git] / src / network / tc / tc-util.c
CommitLineData
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
11int 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
41int 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
60int 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
74int 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
78int 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
105int 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}