]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/geneve.c
firstboot: port to make_salt()
[thirdparty/systemd.git] / src / network / netdev / geneve.c
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-util.h"
14 #include "strv.h"
15 #include "missing.h"
16 #include "networkd-manager.h"
17
18 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
19 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
20
21 /* callback for geneve netdev's created without a backing Link */
22 static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
23 int r;
24
25 assert(netdev);
26 assert(netdev->state != _NETDEV_STATE_INVALID);
27
28 r = sd_netlink_message_get_errno(m);
29 if (r == -EEXIST)
30 log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
31 else if (r < 0) {
32 log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
33 netdev_drop(netdev);
34
35 return 1;
36 }
37
38 log_netdev_debug(netdev, "Geneve created");
39
40 return 1;
41 }
42
43 static int netdev_geneve_create(NetDev *netdev) {
44 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
45 Geneve *v;
46 int r;
47
48 assert(netdev);
49
50 v = GENEVE(netdev);
51
52 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
53 if (r < 0)
54 return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");
55
56 r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
57 if (r < 0)
58 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
59
60 if (netdev->mac) {
61 r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
62 if (r < 0)
63 return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
64 }
65
66 if (netdev->mtu != 0) {
67 r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
68 if (r < 0)
69 return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
70 }
71
72 r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
73 if (r < 0)
74 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
75
76 r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
77 if (r < 0)
78 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
79
80 if (v->id <= GENEVE_VID_MAX) {
81 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id);
82 if (r < 0)
83 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m");
84 }
85
86 if (in_addr_is_null(v->remote_family, &v->remote) == 0) {
87 if (v->remote_family == AF_INET)
88 r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in);
89 else
90 r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6);
91 if (r < 0)
92 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m");
93 }
94
95 if (v->ttl > 0) {
96 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
97 if (r < 0)
98 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
99 }
100
101 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos);
102 if (r < 0)
103 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m");
104
105 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum);
106 if (r < 0)
107 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
108
109 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx);
110 if (r < 0)
111 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
112
113 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx);
114 if (r < 0)
115 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
116
117 if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) {
118 r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port));
119 if (r < 0)
120 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m");
121 }
122
123 if (v->flow_label > 0) {
124 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label));
125 if (r < 0)
126 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
127 }
128
129 r = sd_netlink_message_close_container(m);
130 if (r < 0)
131 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
132
133 r = sd_netlink_message_close_container(m);
134 if (r < 0)
135 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
136
137 r = netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler,
138 netdev_destroy_callback, netdev);
139 if (r < 0)
140 return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
141
142 netdev_ref(netdev);
143 netdev->state = NETDEV_STATE_CREATING;
144
145 log_netdev_debug(netdev, "Creating");
146
147 return r;
148 }
149
150 int config_parse_geneve_vni(const char *unit,
151 const char *filename,
152 unsigned line,
153 const char *section,
154 unsigned section_line,
155 const char *lvalue,
156 int ltype,
157 const char *rvalue,
158 void *data,
159 void *userdata) {
160 Geneve *v = userdata;
161 uint32_t f;
162 int r;
163
164 assert(filename);
165 assert(lvalue);
166 assert(rvalue);
167 assert(data);
168
169 r = safe_atou32(rvalue, &f);
170 if (r < 0) {
171 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue);
172 return 0;
173 }
174
175 if (f > GENEVE_VID_MAX){
176 log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue);
177 return 0;
178 }
179
180 v->id = f;
181
182 return 0;
183 }
184
185 int config_parse_geneve_address(const char *unit,
186 const char *filename,
187 unsigned line,
188 const char *section,
189 unsigned section_line,
190 const char *lvalue,
191 int ltype,
192 const char *rvalue,
193 void *data,
194 void *userdata) {
195 Geneve *v = userdata;
196 union in_addr_union *addr = data, buffer;
197 int r, f;
198
199 assert(filename);
200 assert(lvalue);
201 assert(rvalue);
202 assert(data);
203
204 r = in_addr_from_string_auto(rvalue, &f, &buffer);
205 if (r < 0) {
206 log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
207 return 0;
208 }
209
210 r = in_addr_is_multicast(f, &buffer);
211 if (r > 0) {
212 log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
213 return 0;
214 }
215
216 v->remote_family = f;
217 *addr = buffer;
218
219 return 0;
220 }
221
222 int config_parse_geneve_flow_label(const char *unit,
223 const char *filename,
224 unsigned line,
225 const char *section,
226 unsigned section_line,
227 const char *lvalue,
228 int ltype,
229 const char *rvalue,
230 void *data,
231 void *userdata) {
232 Geneve *v = userdata;
233 uint32_t f;
234 int r;
235
236 assert(filename);
237 assert(lvalue);
238 assert(rvalue);
239 assert(data);
240
241 r = safe_atou32(rvalue, &f);
242 if (r < 0) {
243 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue);
244 return 0;
245 }
246
247 if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) {
248 log_syntax(unit, LOG_ERR, filename, line, r,
249 "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
250 return 0;
251 }
252
253 v->flow_label = f;
254
255 return 0;
256 }
257
258 static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
259 Geneve *v = GENEVE(netdev);
260
261 assert(netdev);
262 assert(v);
263 assert(filename);
264
265 if (v->ttl == 0) {
266 log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename);
267 return -EINVAL;
268 }
269
270 return 0;
271 }
272
273 static void geneve_init(NetDev *netdev) {
274 Geneve *v;
275
276 assert(netdev);
277
278 v = GENEVE(netdev);
279
280 assert(v);
281
282 v->id = GENEVE_VID_MAX + 1;
283 v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
284 v->udpcsum = false;
285 v->udp6zerocsumtx = false;
286 v->udp6zerocsumrx = false;
287 }
288
289 const NetDevVTable geneve_vtable = {
290 .object_size = sizeof(Geneve),
291 .init = geneve_init,
292 .sections = "Match\0NetDev\0GENEVE\0",
293 .create = netdev_geneve_create,
294 .create_type = NETDEV_CREATE_INDEPENDENT,
295 .config_verify = netdev_geneve_verify,
296 };