]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/tc/fifo.c
e955223a89954b34967b2f66834bbeb54541c0f6
[thirdparty/systemd.git] / src / network / tc / fifo.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 "fifo.h"
9 #include "netlink-util.h"
10 #include "parse-util.h"
11 #include "string-util.h"
12
13 static int fifo_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req) {
14 struct tc_fifo_qopt opt = {};
15 FirstInFirstOut *fifo;
16 int r;
17
18 assert(link);
19 assert(qdisc);
20 assert(req);
21
22 switch(qdisc->kind) {
23 case QDISC_KIND_PFIFO:
24 fifo = PFIFO(qdisc);
25 break;
26 case QDISC_KIND_BFIFO:
27 fifo = BFIFO(qdisc);
28 break;
29 case QDISC_KIND_PFIFO_HEAD_DROP:
30 fifo = PFIFO_HEAD_DROP(qdisc);
31 break;
32 default:
33 assert_not_reached("Invalid QDisc kind.");
34 }
35
36 opt.limit = fifo->limit;
37
38 r = sd_netlink_message_append_data(req, TCA_OPTIONS, &opt, sizeof(struct tc_fifo_qopt));
39 if (r < 0)
40 return log_link_error_errno(link, r, "Could not append TCA_OPTIONS attribute: %m");
41
42 return 0;
43 }
44
45 int config_parse_pfifo_size(
46 const char *unit,
47 const char *filename,
48 unsigned line,
49 const char *section,
50 unsigned section_line,
51 const char *lvalue,
52 int ltype,
53 const char *rvalue,
54 void *data,
55 void *userdata) {
56
57 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
58 Network *network = data;
59 FirstInFirstOut *fifo;
60 int r;
61
62 assert(filename);
63 assert(lvalue);
64 assert(rvalue);
65 assert(data);
66
67 r = qdisc_new_static(ltype, network, filename, section_line, &qdisc);
68 if (r == -ENOMEM)
69 return log_oom();
70 if (r < 0) {
71 log_syntax(unit, LOG_WARNING, filename, line, r,
72 "More than one kind of queueing discipline, ignoring assignment: %m");
73 return 0;
74 }
75
76 switch(qdisc->kind) {
77 case QDISC_KIND_PFIFO:
78 fifo = PFIFO(qdisc);
79 break;
80 case QDISC_KIND_PFIFO_HEAD_DROP:
81 fifo = PFIFO_HEAD_DROP(qdisc);
82 break;
83 default:
84 assert_not_reached("Invalid QDisc kind.");
85 }
86
87 if (isempty(rvalue)) {
88 fifo->limit = 0;
89
90 qdisc = NULL;
91 return 0;
92 }
93
94 r = safe_atou32(rvalue, &fifo->limit);
95 if (r < 0) {
96 log_syntax(unit, LOG_WARNING, filename, line, r,
97 "Failed to parse '%s=', ignoring assignment: %s",
98 lvalue, rvalue);
99 return 0;
100 }
101
102 qdisc = NULL;
103 return 0;
104 }
105
106 int config_parse_bfifo_size(
107 const char *unit,
108 const char *filename,
109 unsigned line,
110 const char *section,
111 unsigned section_line,
112 const char *lvalue,
113 int ltype,
114 const char *rvalue,
115 void *data,
116 void *userdata) {
117
118 _cleanup_(qdisc_free_or_set_invalidp) QDisc *qdisc = NULL;
119 Network *network = data;
120 FirstInFirstOut *fifo;
121 uint64_t u;
122 int r;
123
124 assert(filename);
125 assert(lvalue);
126 assert(rvalue);
127 assert(data);
128
129 r = qdisc_new_static(QDISC_KIND_BFIFO, network, filename, section_line, &qdisc);
130 if (r == -ENOMEM)
131 return log_oom();
132 if (r < 0) {
133 log_syntax(unit, LOG_WARNING, filename, line, r,
134 "More than one kind of queueing discipline, ignoring assignment: %m");
135 return 0;
136 }
137
138 fifo = BFIFO(qdisc);
139
140 if (isempty(rvalue)) {
141 fifo->limit = 0;
142
143 qdisc = NULL;
144 return 0;
145 }
146
147 r = parse_size(rvalue, 1024, &u);
148 if (r < 0) {
149 log_syntax(unit, LOG_WARNING, filename, line, r,
150 "Failed to parse '%s=', ignoring assignment: %s",
151 lvalue, rvalue);
152 return 0;
153 }
154 if (u > UINT32_MAX) {
155 log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid '%s=', ignoring assignment: %s",
156 lvalue, rvalue);
157 return 0;
158 }
159
160 fifo->limit = (uint32_t) u;
161
162 qdisc = NULL;
163 return 0;
164 }
165
166 const QDiscVTable pfifo_vtable = {
167 .object_size = sizeof(FirstInFirstOut),
168 .tca_kind = "pfifo",
169 .fill_message = fifo_fill_message,
170 };
171
172 const QDiscVTable bfifo_vtable = {
173 .object_size = sizeof(FirstInFirstOut),
174 .tca_kind = "bfifo",
175 .fill_message = fifo_fill_message,
176 };
177
178 const QDiscVTable pfifo_head_drop_vtable = {
179 .object_size = sizeof(FirstInFirstOut),
180 .tca_kind = "pfifo_head_drop",
181 .fill_message = fifo_fill_message,
182 };
183
184 const QDiscVTable pfifo_fast_vtable = {
185 .object_size = sizeof(FirstInFirstOut),
186 .tca_kind = "pfifo_fast",
187 };