1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Susant Sahani
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.
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.
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/>.
23 #include "sd-netlink.h"
25 #include "conf-parser.h"
26 #include "alloc-util.h"
27 #include "extract-word.h"
28 #include "string-util.h"
30 #include "parse-util.h"
33 #include "networkd-link.h"
34 #include "netdev/vxlan.h"
36 static int netdev_vxlan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
48 if (v
->id
<= VXLAN_VID_MAX
) {
49 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_ID
, v
->id
);
51 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_ID attribute: %m");
54 if (!in_addr_is_null(v
->remote_family
, &v
->remote
)) {
56 if (v
->remote_family
== AF_INET
)
57 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_GROUP
, &v
->remote
.in
);
59 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_GROUP6
, &v
->remote
.in6
);
62 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GROUP attribute: %m");
66 if (!in_addr_is_null(v
->local_family
, &v
->local
)) {
68 if (v
->local_family
== AF_INET
)
69 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_LOCAL
, &v
->local
.in
);
71 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_LOCAL6
, &v
->local
.in6
);
74 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LOCAL attribute: %m");
78 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LINK
, link
->ifindex
);
80 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LINK attribute: %m");
83 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TTL
, v
->ttl
);
85 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TTL attribute: %m");
89 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TOS
, v
->tos
);
91 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TOS attribute: %m");
94 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_LEARNING
, v
->learning
);
96 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LEARNING attribute: %m");
98 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_RSC
, v
->route_short_circuit
);
100 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_RSC attribute: %m");
102 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_PROXY
, v
->arp_proxy
);
104 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PROXY attribute: %m");
106 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L2MISS
, v
->l2miss
);
108 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L2MISS attribute: %m");
110 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L3MISS
, v
->l3miss
);
112 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L3MISS attribute: %m");
115 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_AGEING
, v
->fdb_ageing
/ USEC_PER_SEC
);
117 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_AGEING attribute: %m");
121 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LIMIT
, v
->max_fdb
);
123 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LIMIT attribute: %m");
126 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_CSUM
, v
->udpcsum
);
128 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m");
130 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_TX
, v
->udp6zerocsumtx
);
132 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m");
134 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_RX
, v
->udp6zerocsumrx
);
136 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m");
138 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_TX
, v
->remote_csum_tx
);
140 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m");
142 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_RX
, v
->remote_csum_rx
);
144 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m");
146 r
= sd_netlink_message_append_u16(m
, IFLA_VXLAN_PORT
, htobe16(v
->dest_port
));
148 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT attribute: %m");
150 if (v
->port_range
.low
|| v
->port_range
.high
) {
151 struct ifla_vxlan_port_range port_range
;
153 port_range
.low
= htobe16(v
->port_range
.low
);
154 port_range
.high
= htobe16(v
->port_range
.high
);
156 r
= sd_netlink_message_append_data(m
, IFLA_VXLAN_PORT_RANGE
, &port_range
, sizeof(port_range
));
158 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m");
161 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LABEL
, htobe32(v
->flow_label
));
163 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LABEL attribute: %m");
165 if (v
->group_policy
) {
166 r
= sd_netlink_message_append_flag(m
, IFLA_VXLAN_GBP
);
168 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GBP attribute: %m");
174 int config_parse_vxlan_address(const char *unit
,
175 const char *filename
,
178 unsigned section_line
,
185 union in_addr_union
*addr
= data
, buffer
;
193 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
195 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "vxlan '%s' address is invalid, ignoring assignment: %s", lvalue
, rvalue
);
199 r
= in_addr_is_multicast(f
, &buffer
);
201 if (streq(lvalue
, "Group")) {
203 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue
, rvalue
);
207 v
->remote_family
= f
;
210 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue
, rvalue
);
214 if (streq(lvalue
, "Remote"))
215 v
->remote_family
= f
;
225 int config_parse_port_range(const char *unit
,
226 const char *filename
,
229 unsigned section_line
,
235 _cleanup_free_
char *word
= NULL
;
245 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
247 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract VXLAN port range, ignoring: %s", rvalue
);
254 r
= parse_range(word
, &low
, &high
);
256 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse VXLAN port range '%s'", word
);
260 if (low
<= 0 || low
> 65535 || high
<= 0 || high
> 65535) {
261 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
262 "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word
);
267 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
268 "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word
, low
, high
);
272 v
->port_range
.low
= low
;
273 v
->port_range
.high
= high
;
278 int config_parse_flow_label(const char *unit
,
279 const char *filename
,
282 unsigned section_line
,
297 r
= safe_atou(rvalue
, &f
);
299 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse VXLAN flow label '%s'.", rvalue
);
303 if (f
& ~VXLAN_FLOW_LABEL_MAX_MASK
) {
304 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
305 "VXLAN flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue
);
314 static int netdev_vxlan_verify(NetDev
*netdev
, const char *filename
) {
315 VxLan
*v
= VXLAN(netdev
);
321 if (v
->id
> VXLAN_VID_MAX
) {
322 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename
);
329 static void vxlan_init(NetDev
*netdev
) {
338 v
->id
= VXLAN_VID_MAX
+ 1;
341 v
->udp6zerocsumtx
= false;
342 v
->udp6zerocsumrx
= false;
345 const NetDevVTable vxlan_vtable
= {
346 .object_size
= sizeof(VxLan
),
348 .sections
= "Match\0NetDev\0VXLAN\0",
349 .fill_message_create
= netdev_vxlan_fill_message_create
,
350 .create_type
= NETDEV_CREATE_STACKED
,
351 .config_verify
= netdev_vxlan_verify
,