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