]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/tc/netem.c
network: downgrade log level in conf parsers
[thirdparty/systemd.git] / src / network / tc / netem.c
1 /* SPDX-License-Identifier: LGPL-2.1+
2 * Copyright © 2019 VMware, Inc. */
3
4 #include <linux/pkt_sched.h>
5
6 #include "alloc-util.h"
7 #include "conf-parser.h"
8 #include "netem.h"
9 #include "netlink-util.h"
10 #include "networkd-manager.h"
11 #include "parse-util.h"
12 #include "qdisc.h"
13 #include "strv.h"
14 #include "tc-util.h"
15
16 static int network_emulator_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
17 struct tc_netem_qopt opt = {
18 .limit = 1000,
19 };
20 NetworkEmulator *ne;
21 int r;
22
23 assert(link);
24 assert(qdisc);
25 assert(req);
26
27 ne = NETEM(qdisc);
28
29 if (ne->limit > 0)
30 opt.limit = ne->limit;
31
32 if (ne->loss > 0)
33 opt.loss = ne->loss;
34
35 if (ne->duplicate > 0)
36 opt.duplicate = ne->duplicate;
37
38 if (ne->delay != USEC_INFINITY) {
39 r = tc_time_to_tick(ne->delay, &opt.latency);
40 if (r < 0)
41 return log_link_error_errno(link, r, "Failed to calculate latency in TCA_OPTION: %m");
42 }
43
44 if (ne->jitter != USEC_INFINITY) {
45 r = tc_time_to_tick(ne->jitter, &opt.jitter);
46 if (r < 0)
47 return log_link_error_errno(link, r, "Failed to calculate jitter in TCA_OPTION: %m");
48 }
49
50 r = sd_netlink_message_append_data(req, TCA_OPTIONS, &opt, sizeof(struct tc_netem_qopt));
51 if (r < 0)
52 return log_link_error_errno(link, r, "Could not append TCA_OPTION attribute: %m");
53
54 return 0;
55 }
56
57 int config_parse_network_emulator_delay(
58 const char *unit,
59 const char *filename,
60 unsigned line,
61 const char *section,
62 unsigned section_line,
63 const char *lvalue,
64 int ltype,
65 const char *rvalue,
66 void *data,
67 void *userdata) {
68
69 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
70 Network *network = data;
71 NetworkEmulator *ne;
72 usec_t u;
73 int r;
74
75 assert(filename);
76 assert(lvalue);
77 assert(rvalue);
78 assert(data);
79
80 r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
81 if (r == -ENOMEM)
82 return log_oom();
83 if (r < 0) {
84 log_syntax(unit, LOG_WARNING, filename, line, r,
85 "More than one kind of queueing discipline, ignoring assignment: %m");
86 return 0;
87 }
88
89 ne = NETEM(qdisc);
90
91 if (isempty(rvalue)) {
92 if (STR_IN_SET(lvalue, "DelaySec", "NetworkEmulatorDelaySec"))
93 ne->delay = USEC_INFINITY;
94 else if (STR_IN_SET(lvalue, "DelayJitterSec", "NetworkEmulatorDelayJitterSec"))
95 ne->jitter = USEC_INFINITY;
96
97 qdisc = NULL;
98 return 0;
99 }
100
101 r = parse_sec(rvalue, &u);
102 if (r < 0) {
103 log_syntax(unit, LOG_WARNING, filename, line, r,
104 "Failed to parse '%s=', ignoring assignment: %s",
105 lvalue, rvalue);
106 return 0;
107 }
108
109 if (STR_IN_SET(lvalue, "DelaySec", "NetworkEmulatorDelaySec"))
110 ne->delay = u;
111 else if (STR_IN_SET(lvalue, "DelayJitterSec", "NetworkEmulatorDelayJitterSec"))
112 ne->jitter = u;
113
114 qdisc = NULL;
115
116 return 0;
117 }
118
119 int config_parse_network_emulator_rate(
120 const char *unit,
121 const char *filename,
122 unsigned line,
123 const char *section,
124 unsigned section_line,
125 const char *lvalue,
126 int ltype,
127 const char *rvalue,
128 void *data,
129 void *userdata) {
130
131 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
132 Network *network = data;
133 NetworkEmulator *ne;
134 uint32_t rate;
135 int r;
136
137 assert(filename);
138 assert(lvalue);
139 assert(rvalue);
140 assert(data);
141
142 r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
143 if (r == -ENOMEM)
144 return log_oom();
145 if (r < 0) {
146 log_syntax(unit, LOG_WARNING, filename, line, r,
147 "More than one kind of queueing discipline, ignoring assignment: %m");
148 return 0;
149 }
150
151 ne = NETEM(qdisc);
152
153 if (isempty(rvalue)) {
154 if (STR_IN_SET(lvalue, "LossRate", "NetworkEmulatorLossRate"))
155 ne->loss = 0;
156 else if (STR_IN_SET(lvalue, "DuplicateRate", "NetworkEmulatorDuplicateRate"))
157 ne->duplicate = 0;
158
159 qdisc = NULL;
160 return 0;
161 }
162
163 r = parse_tc_percent(rvalue, &rate);
164 if (r < 0) {
165 log_syntax(unit, LOG_WARNING, filename, line, r,
166 "Failed to parse '%s=', ignoring assignment: %s",
167 lvalue, rvalue);
168 return 0;
169 }
170
171 if (STR_IN_SET(lvalue, "LossRate", "NetworkEmulatorLossRate"))
172 ne->loss = rate;
173 else if (STR_IN_SET(lvalue, "DuplicateRate", "NetworkEmulatorDuplicateRate"))
174 ne->duplicate = rate;
175
176 qdisc = NULL;
177 return 0;
178 }
179
180 int config_parse_network_emulator_packet_limit(
181 const char *unit,
182 const char *filename,
183 unsigned line,
184 const char *section,
185 unsigned section_line,
186 const char *lvalue,
187 int ltype,
188 const char *rvalue,
189 void *data,
190 void *userdata) {
191
192 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
193 Network *network = data;
194 NetworkEmulator *ne;
195 int r;
196
197 assert(filename);
198 assert(lvalue);
199 assert(rvalue);
200 assert(data);
201
202 r = qdisc_new_static(QDISC_KIND_NETEM, network, filename, section_line, &qdisc);
203 if (r == -ENOMEM)
204 return log_oom();
205 if (r < 0) {
206 log_syntax(unit, LOG_WARNING, filename, line, r,
207 "More than one kind of queueing discipline, ignoring assignment: %m");
208 return 0;
209 }
210
211 ne = NETEM(qdisc);
212
213 if (isempty(rvalue)) {
214 ne->limit = 0;
215 qdisc = NULL;
216
217 return 0;
218 }
219
220 r = safe_atou(rvalue, &ne->limit);
221 if (r < 0) {
222 log_syntax(unit, LOG_WARNING, filename, line, r,
223 "Failed to parse '%s=', ignoring assignment: %s",
224 lvalue, rvalue);
225 return 0;
226 }
227
228 qdisc = NULL;
229 return 0;
230 }
231
232 const QDiscVTable netem_vtable = {
233 .object_size = sizeof(NetworkEmulator),
234 .tca_kind = "netem",
235 .fill_message = network_emulator_fill_message,
236 };