Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <net/if.h>
4 :
5 : #include "sd-netlink.h"
6 :
7 : #include "alloc-util.h"
8 : #include "conf-parser.h"
9 : #include "extract-word.h"
10 : #include "geneve.h"
11 : #include "netlink-util.h"
12 : #include "parse-util.h"
13 : #include "string-table.h"
14 : #include "string-util.h"
15 : #include "strv.h"
16 : #include "missing.h"
17 : #include "networkd-manager.h"
18 :
19 : #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
20 : #define DEFAULT_GENEVE_DESTINATION_PORT 6081
21 :
22 : static const char* const geneve_df_table[_NETDEV_GENEVE_DF_MAX] = {
23 : [NETDEV_GENEVE_DF_NO] = "no",
24 : [NETDEV_GENEVE_DF_YES] = "yes",
25 : [NETDEV_GENEVE_DF_INHERIT] = "inherit",
26 : };
27 :
28 0 : DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(geneve_df, GeneveDF, NETDEV_GENEVE_DF_YES);
29 0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_geneve_df, geneve_df, GeneveDF, "Failed to parse Geneve IPDoNotFragment= setting");
30 :
31 : /* callback for geneve netdev's created without a backing Link */
32 0 : static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
33 : int r;
34 :
35 0 : assert(netdev);
36 0 : assert(netdev->state != _NETDEV_STATE_INVALID);
37 :
38 0 : r = sd_netlink_message_get_errno(m);
39 0 : if (r == -EEXIST)
40 0 : log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
41 0 : else if (r < 0) {
42 0 : log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
43 0 : netdev_drop(netdev);
44 :
45 0 : return 1;
46 : }
47 :
48 0 : log_netdev_debug(netdev, "Geneve created");
49 :
50 0 : return 1;
51 : }
52 :
53 0 : static int netdev_geneve_create(NetDev *netdev) {
54 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
55 : Geneve *v;
56 : int r;
57 :
58 0 : assert(netdev);
59 :
60 0 : v = GENEVE(netdev);
61 :
62 0 : r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
63 0 : if (r < 0)
64 0 : return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");
65 :
66 0 : r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
67 0 : if (r < 0)
68 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
69 :
70 0 : if (netdev->mac) {
71 0 : r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
72 0 : if (r < 0)
73 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
74 : }
75 :
76 0 : if (netdev->mtu != 0) {
77 0 : r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
78 0 : if (r < 0)
79 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
80 : }
81 :
82 0 : r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
83 0 : if (r < 0)
84 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
85 :
86 0 : r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
87 0 : if (r < 0)
88 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
89 :
90 0 : if (v->id <= GENEVE_VID_MAX) {
91 0 : r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id);
92 0 : if (r < 0)
93 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m");
94 : }
95 :
96 0 : if (in_addr_is_null(v->remote_family, &v->remote) == 0) {
97 0 : if (v->remote_family == AF_INET)
98 0 : r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in);
99 : else
100 0 : r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6);
101 0 : if (r < 0)
102 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m");
103 : }
104 :
105 0 : if (v->inherit) {
106 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL_INHERIT, 1);
107 0 : if (r < 0)
108 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL_INHERIT attribute: %m");
109 : } else {
110 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
111 0 : if (r < 0)
112 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
113 : }
114 :
115 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos);
116 0 : if (r < 0)
117 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m");
118 :
119 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum);
120 0 : if (r < 0)
121 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
122 :
123 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx);
124 0 : if (r < 0)
125 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
126 :
127 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx);
128 0 : if (r < 0)
129 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
130 :
131 0 : if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) {
132 0 : r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port));
133 0 : if (r < 0)
134 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m");
135 : }
136 :
137 0 : if (v->flow_label > 0) {
138 0 : r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label));
139 0 : if (r < 0)
140 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
141 : }
142 :
143 0 : if (v->geneve_df != _NETDEV_GENEVE_DF_INVALID) {
144 0 : r = sd_netlink_message_append_u8(m, IFLA_GENEVE_DF, v->geneve_df);
145 0 : if (r < 0)
146 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_DF attribute: %m");
147 : }
148 :
149 0 : r = sd_netlink_message_close_container(m);
150 0 : if (r < 0)
151 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
152 :
153 0 : r = sd_netlink_message_close_container(m);
154 0 : if (r < 0)
155 0 : return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
156 :
157 0 : r = netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler,
158 : netdev_destroy_callback, netdev);
159 0 : if (r < 0)
160 0 : return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
161 :
162 0 : netdev_ref(netdev);
163 0 : netdev->state = NETDEV_STATE_CREATING;
164 :
165 0 : log_netdev_debug(netdev, "Creating");
166 :
167 0 : return r;
168 : }
169 :
170 0 : int config_parse_geneve_vni(const char *unit,
171 : const char *filename,
172 : unsigned line,
173 : const char *section,
174 : unsigned section_line,
175 : const char *lvalue,
176 : int ltype,
177 : const char *rvalue,
178 : void *data,
179 : void *userdata) {
180 0 : Geneve *v = userdata;
181 : uint32_t f;
182 : int r;
183 :
184 0 : assert(filename);
185 0 : assert(lvalue);
186 0 : assert(rvalue);
187 0 : assert(data);
188 :
189 0 : r = safe_atou32(rvalue, &f);
190 0 : if (r < 0) {
191 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue);
192 0 : return 0;
193 : }
194 :
195 0 : if (f > GENEVE_VID_MAX){
196 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue);
197 0 : return 0;
198 : }
199 :
200 0 : v->id = f;
201 :
202 0 : return 0;
203 : }
204 :
205 0 : int config_parse_geneve_address(const char *unit,
206 : const char *filename,
207 : unsigned line,
208 : const char *section,
209 : unsigned section_line,
210 : const char *lvalue,
211 : int ltype,
212 : const char *rvalue,
213 : void *data,
214 : void *userdata) {
215 0 : Geneve *v = userdata;
216 0 : union in_addr_union *addr = data, buffer;
217 : int r, f;
218 :
219 0 : assert(filename);
220 0 : assert(lvalue);
221 0 : assert(rvalue);
222 0 : assert(data);
223 :
224 0 : r = in_addr_from_string_auto(rvalue, &f, &buffer);
225 0 : if (r < 0) {
226 0 : log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
227 0 : return 0;
228 : }
229 :
230 0 : r = in_addr_is_multicast(f, &buffer);
231 0 : if (r > 0) {
232 0 : log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
233 0 : return 0;
234 : }
235 :
236 0 : v->remote_family = f;
237 0 : *addr = buffer;
238 :
239 0 : return 0;
240 : }
241 :
242 0 : int config_parse_geneve_flow_label(const char *unit,
243 : const char *filename,
244 : unsigned line,
245 : const char *section,
246 : unsigned section_line,
247 : const char *lvalue,
248 : int ltype,
249 : const char *rvalue,
250 : void *data,
251 : void *userdata) {
252 0 : Geneve *v = userdata;
253 : uint32_t f;
254 : int r;
255 :
256 0 : assert(filename);
257 0 : assert(lvalue);
258 0 : assert(rvalue);
259 0 : assert(data);
260 :
261 0 : r = safe_atou32(rvalue, &f);
262 0 : if (r < 0) {
263 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue);
264 0 : return 0;
265 : }
266 :
267 0 : if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) {
268 0 : log_syntax(unit, LOG_ERR, filename, line, r,
269 : "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
270 0 : return 0;
271 : }
272 :
273 0 : v->flow_label = f;
274 :
275 0 : return 0;
276 : }
277 :
278 0 : int config_parse_geneve_ttl(const char *unit,
279 : const char *filename,
280 : unsigned line,
281 : const char *section,
282 : unsigned section_line,
283 : const char *lvalue,
284 : int ltype,
285 : const char *rvalue,
286 : void *data,
287 : void *userdata) {
288 0 : Geneve *v = userdata;
289 : unsigned f;
290 : int r;
291 :
292 0 : assert(filename);
293 0 : assert(lvalue);
294 0 : assert(rvalue);
295 0 : assert(data);
296 :
297 0 : if (streq(rvalue, "inherit"))
298 0 : v->inherit = true;
299 : else {
300 0 : r = safe_atou(rvalue, &f);
301 0 : if (r < 0) {
302 0 : log_syntax(unit, LOG_ERR, filename, line, r,
303 : "Failed to parse Geneve TTL '%s', ignoring assignment: %m", rvalue);
304 0 : return 0;
305 : }
306 :
307 0 : if (f > 255) {
308 0 : log_syntax(unit, LOG_ERR, filename, line, 0,
309 : "Invalid Geneve TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
310 0 : return 0;
311 : }
312 :
313 0 : v->ttl = f;
314 : }
315 :
316 0 : return 0;
317 : }
318 :
319 0 : static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
320 0 : Geneve *v = GENEVE(netdev);
321 :
322 0 : assert(netdev);
323 0 : assert(v);
324 0 : assert(filename);
325 :
326 0 : if (v->id > GENEVE_VID_MAX)
327 0 : return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
328 : "%s: Geneve without valid VNI (or Virtual Network Identifier) configured. Ignoring.",
329 : filename);
330 :
331 0 : return 0;
332 : }
333 :
334 0 : static void geneve_init(NetDev *netdev) {
335 : Geneve *v;
336 :
337 0 : assert(netdev);
338 :
339 0 : v = GENEVE(netdev);
340 :
341 0 : assert(v);
342 :
343 0 : v->id = GENEVE_VID_MAX + 1;
344 0 : v->geneve_df = _NETDEV_GENEVE_DF_INVALID;
345 0 : v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
346 0 : v->udpcsum = false;
347 0 : v->udp6zerocsumtx = false;
348 0 : v->udp6zerocsumrx = false;
349 0 : }
350 :
351 : const NetDevVTable geneve_vtable = {
352 : .object_size = sizeof(Geneve),
353 : .init = geneve_init,
354 : .sections = "Match\0NetDev\0GENEVE\0",
355 : .create = netdev_geneve_create,
356 : .create_type = NETDEV_CREATE_INDEPENDENT,
357 : .config_verify = netdev_geneve_verify,
358 : .generate_mac = true,
359 : };
|