]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/geneve.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / network / netdev / geneve.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2017 Susant Sahani
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <net/if.h>
22
23 #include "alloc-util.h"
24 #include "conf-parser.h"
25 #include "extract-word.h"
26 #include "geneve.h"
27 #include "parse-util.h"
28 #include "sd-netlink.h"
29 #include "string-util.h"
30 #include "strv.h"
31 #include "missing.h"
32 #include "networkd-manager.h"
33
34 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
35 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
36
37 /* callback for geneve netdev's created without a backing Link */
38 static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
39 _cleanup_netdev_unref_ NetDev *netdev = userdata;
40 int r;
41
42 assert(netdev->state != _NETDEV_STATE_INVALID);
43
44 r = sd_netlink_message_get_errno(m);
45 if (r == -EEXIST)
46 log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
47 else if (r < 0) {
48 log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
49 netdev_drop(netdev);
50
51 return 1;
52 }
53
54 log_netdev_debug(netdev, "Geneve created");
55
56 return 1;
57 }
58
59 static int netdev_geneve_create(NetDev *netdev) {
60 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
61 Geneve *v;
62 int r;
63
64 assert(netdev);
65
66 v = GENEVE(netdev);
67
68 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
69 if (r < 0)
70 return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");
71
72 r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
73 if (r < 0)
74 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
75
76 if (netdev->mac) {
77 r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
78 if (r < 0)
79 return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
80 }
81
82 if (netdev->mtu) {
83 r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
84 if (r < 0)
85 return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
86 }
87
88 r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
89 if (r < 0)
90 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
91
92 r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
93 if (r < 0)
94 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
95
96 if (v->id <= GENEVE_VID_MAX) {
97 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id);
98 if (r < 0)
99 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m");
100 }
101
102 if (!in_addr_is_null(v->remote_family, &v->remote)) {
103
104 if (v->remote_family == AF_INET)
105 r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in);
106 else
107 r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6);
108
109 if (r < 0)
110 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_GROUP attribute: %m");
111
112 }
113
114 if (v->ttl) {
115 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
116 if (r < 0)
117 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
118 }
119
120 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos);
121 if (r < 0)
122 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m");
123
124 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum);
125 if (r < 0)
126 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
127
128 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx);
129 if (r < 0)
130 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
131
132 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx);
133 if (r < 0)
134 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
135
136 if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) {
137 r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port));
138 if (r < 0)
139 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m");
140 }
141
142 if (v->flow_label > 0) {
143 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label));
144 if (r < 0)
145 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
146 }
147
148 r = sd_netlink_message_close_container(m);
149 if (r < 0)
150 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
151
152 r = sd_netlink_message_close_container(m);
153 if (r < 0)
154 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
155
156 r = sd_netlink_call_async(netdev->manager->rtnl, m, geneve_netdev_create_handler, netdev, 0, NULL);
157 if (r < 0)
158 return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
159
160 netdev_ref(netdev);
161
162 netdev->state = NETDEV_STATE_CREATING;
163
164 log_netdev_debug(netdev, "Creating");
165
166
167 return r;
168 }
169
170 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 Geneve *v = userdata;
181 uint32_t f;
182 int r;
183
184 assert(filename);
185 assert(lvalue);
186 assert(rvalue);
187 assert(data);
188
189 r = safe_atou32(rvalue, &f);
190 if (r < 0) {
191 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue);
192 return 0;
193 }
194
195 if (f > GENEVE_VID_MAX){
196 log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue);
197 return 0;
198 }
199
200 v->id = f;
201
202 return 0;
203 }
204
205 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 Geneve *v = userdata;
216 union in_addr_union *addr = data, buffer;
217 int r, f;
218
219 assert(filename);
220 assert(lvalue);
221 assert(rvalue);
222 assert(data);
223
224 r = in_addr_from_string_auto(rvalue, &f, &buffer);
225 if (r < 0) {
226 log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
227 return 0;
228 }
229
230 r = in_addr_is_multicast(f, &buffer);
231 if (r > 0) {
232 log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
233 return 0;
234 }
235
236 v->remote_family = f;
237 *addr = buffer;
238
239 return 0;
240 }
241
242 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 Geneve *v = userdata;
253 uint32_t f;
254 int r;
255
256 assert(filename);
257 assert(lvalue);
258 assert(rvalue);
259 assert(data);
260
261 r = safe_atou32(rvalue, &f);
262 if (r < 0) {
263 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue);
264 return 0;
265 }
266
267 if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) {
268 log_syntax(unit, LOG_ERR, filename, line, r,
269 "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
270 return 0;
271 }
272
273 v->flow_label = f;
274
275 return 0;
276 }
277
278 static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
279 Geneve *v = GENEVE(netdev);
280
281 assert(netdev);
282 assert(v);
283 assert(filename);
284
285 if (v->ttl == 0) {
286 log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename);
287 return -EINVAL;
288 }
289
290 return 0;
291 }
292
293 static void geneve_init(NetDev *netdev) {
294 Geneve *v;
295
296 assert(netdev);
297
298 v = GENEVE(netdev);
299
300 assert(v);
301
302 v->id = GENEVE_VID_MAX + 1;
303 v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
304 v->udpcsum = false;
305 v->udp6zerocsumtx = false;
306 v->udp6zerocsumrx = false;
307 }
308
309 const NetDevVTable geneve_vtable = {
310 .object_size = sizeof(Geneve),
311 .init = geneve_init,
312 .sections = "Match\0NetDev\0GENEVE\0",
313 .create = netdev_geneve_create,
314 .create_type = NETDEV_CREATE_INDEPENDENT,
315 .config_verify = netdev_geneve_verify,
316 };