]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/tc/gred.c
tree-wide: use ASSERT_PTR more
[thirdparty/systemd.git] / src / network / tc / gred.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2 * Copyright © 2020 VMware, Inc. */
3
4 #include <linux/pkt_sched.h>
5
6 #include "alloc-util.h"
7 #include "conf-parser.h"
8 #include "netlink-util.h"
9 #include "parse-util.h"
10 #include "qdisc.h"
11 #include "string-util.h"
12
13 static int generic_random_early_detection_init(QDisc *qdisc) {
14 GenericRandomEarlyDetection *gred;
15
16 assert(qdisc);
17
18 gred = GRED(qdisc);
19
20 gred->grio = -1;
21
22 return 0;
23 }
24
25 static int generic_random_early_detection_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
26 GenericRandomEarlyDetection *gred;
27 int r;
28
29 assert(link);
30 assert(qdisc);
31 assert(req);
32
33 assert_se(gred = GRED(qdisc));
34
35 const struct tc_gred_sopt opt = {
36 .DPs = gred->virtual_queues,
37 .def_DP = gred->default_virtual_queue,
38 .grio = gred->grio,
39 };
40
41 r = sd_netlink_message_open_container_union(req, TCA_OPTIONS, "gred");
42 if (r < 0)
43 return r;
44
45 r = sd_netlink_message_append_data(req, TCA_GRED_DPS, &opt, sizeof(opt));
46 if (r < 0)
47 return r;
48
49 r = sd_netlink_message_close_container(req);
50 if (r < 0)
51 return r;
52
53 return 0;
54 }
55
56 static int generic_random_early_detection_verify(QDisc *qdisc) {
57 GenericRandomEarlyDetection *gred = GRED(qdisc);
58
59 if (gred->default_virtual_queue >= gred->virtual_queues)
60 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
61 "%s: DefaultVirtualQueue= must be less than VirtualQueues=. "
62 "Ignoring [GenericRandomEarlyDetection] section from line %u.",
63 qdisc->section->filename, qdisc->section->line);
64
65 return 0;
66 }
67
68 int config_parse_generic_random_early_detection_u32(
69 const char *unit,
70 const char *filename,
71 unsigned line,
72 const char *section,
73 unsigned section_line,
74 const char *lvalue,
75 int ltype,
76 const char *rvalue,
77 void *data,
78 void *userdata) {
79
80 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
81 GenericRandomEarlyDetection *gred;
82 Network *network = ASSERT_PTR(data);
83 uint32_t *p;
84 uint32_t v;
85 int r;
86
87 assert(filename);
88 assert(lvalue);
89 assert(rvalue);
90
91 r = qdisc_new_static(QDISC_KIND_GRED, network, filename, section_line, &qdisc);
92 if (r == -ENOMEM)
93 return log_oom();
94 if (r < 0) {
95 log_syntax(unit, LOG_WARNING, filename, line, r,
96 "More than one kind of queueing discipline, ignoring assignment: %m");
97 return 0;
98 }
99
100 gred = GRED(qdisc);
101
102 if (streq(lvalue, "VirtualQueues"))
103 p = &gred->virtual_queues;
104 else if (streq(lvalue, "DefaultVirtualQueue"))
105 p = &gred->default_virtual_queue;
106 else
107 assert_not_reached();
108
109 if (isempty(rvalue)) {
110 *p = 0;
111
112 TAKE_PTR(qdisc);
113 return 0;
114 }
115
116 r = safe_atou32(rvalue, &v);
117 if (r < 0) {
118 log_syntax(unit, LOG_WARNING, filename, line, r,
119 "Failed to parse '%s=', ignoring assignment: %s",
120 lvalue, rvalue);
121 return 0;
122 }
123
124 if (v > MAX_DPs)
125 log_syntax(unit, LOG_WARNING, filename, line, 0,
126 "Invalid '%s=', ignoring assignment: %s",
127 lvalue, rvalue);
128
129 *p = v;
130 TAKE_PTR(qdisc);
131
132 return 0;
133 }
134 int config_parse_generic_random_early_detection_bool(
135 const char *unit,
136 const char *filename,
137 unsigned line,
138 const char *section,
139 unsigned section_line,
140 const char *lvalue,
141 int ltype,
142 const char *rvalue,
143 void *data,
144 void *userdata) {
145
146 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
147 GenericRandomEarlyDetection *gred;
148 Network *network = ASSERT_PTR(data);
149 int r;
150
151 assert(filename);
152 assert(lvalue);
153 assert(rvalue);
154
155 r = qdisc_new_static(QDISC_KIND_GRED, network, filename, section_line, &qdisc);
156 if (r == -ENOMEM)
157 return log_oom();
158 if (r < 0) {
159 log_syntax(unit, LOG_WARNING, filename, line, r,
160 "More than one kind of queueing discipline, ignoring assignment: %m");
161 return 0;
162 }
163
164 gred = GRED(qdisc);
165
166 if (isempty(rvalue)) {
167 gred->grio = -1;
168
169 TAKE_PTR(qdisc);
170 return 0;
171 }
172
173 r = parse_boolean(rvalue);
174 if (r < 0) {
175 log_syntax(unit, LOG_WARNING, filename, line, r,
176 "Failed to parse '%s=', ignoring assignment: %s",
177 lvalue, rvalue);
178 return 0;
179 }
180
181 gred->grio = r;
182 TAKE_PTR(qdisc);
183
184 return 0;
185 }
186
187 const QDiscVTable gred_vtable = {
188 .object_size = sizeof(GenericRandomEarlyDetection),
189 .tca_kind = "gred",
190 .init = generic_random_early_detection_init,
191 .fill_message = generic_random_early_detection_fill_message,
192 .verify = generic_random_early_detection_verify,
193 };