Branch data 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 : : };
|