1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "sd-netlink.h"
7 #include "conf-parser.h"
8 #include "alloc-util.h"
9 #include "extract-word.h"
10 #include "string-util.h"
12 #include "parse-util.h"
15 #include "networkd-link.h"
16 #include "netdev/vxlan.h"
18 static int netdev_vxlan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
30 if (v
->id
<= VXLAN_VID_MAX
) {
31 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_ID
, v
->id
);
33 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_ID attribute: %m");
36 if (!in_addr_is_null(v
->remote_family
, &v
->remote
)) {
38 if (v
->remote_family
== AF_INET
)
39 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_GROUP
, &v
->remote
.in
);
41 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_GROUP6
, &v
->remote
.in6
);
44 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GROUP attribute: %m");
48 if (!in_addr_is_null(v
->local_family
, &v
->local
)) {
50 if (v
->local_family
== AF_INET
)
51 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_LOCAL
, &v
->local
.in
);
53 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_LOCAL6
, &v
->local
.in6
);
56 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LOCAL attribute: %m");
60 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LINK
, link
->ifindex
);
62 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LINK attribute: %m");
65 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TTL
, v
->ttl
);
67 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TTL attribute: %m");
71 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TOS
, v
->tos
);
73 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TOS attribute: %m");
76 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_LEARNING
, v
->learning
);
78 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LEARNING attribute: %m");
80 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_RSC
, v
->route_short_circuit
);
82 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_RSC attribute: %m");
84 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_PROXY
, v
->arp_proxy
);
86 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PROXY attribute: %m");
88 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L2MISS
, v
->l2miss
);
90 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L2MISS attribute: %m");
92 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L3MISS
, v
->l3miss
);
94 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L3MISS attribute: %m");
97 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_AGEING
, v
->fdb_ageing
/ USEC_PER_SEC
);
99 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_AGEING attribute: %m");
103 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LIMIT
, v
->max_fdb
);
105 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LIMIT attribute: %m");
108 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_CSUM
, v
->udpcsum
);
110 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m");
112 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_TX
, v
->udp6zerocsumtx
);
114 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m");
116 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_RX
, v
->udp6zerocsumrx
);
118 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m");
120 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_TX
, v
->remote_csum_tx
);
122 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m");
124 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_RX
, v
->remote_csum_rx
);
126 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m");
128 r
= sd_netlink_message_append_u16(m
, IFLA_VXLAN_PORT
, htobe16(v
->dest_port
));
130 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT attribute: %m");
132 if (v
->port_range
.low
|| v
->port_range
.high
) {
133 struct ifla_vxlan_port_range port_range
;
135 port_range
.low
= htobe16(v
->port_range
.low
);
136 port_range
.high
= htobe16(v
->port_range
.high
);
138 r
= sd_netlink_message_append_data(m
, IFLA_VXLAN_PORT_RANGE
, &port_range
, sizeof(port_range
));
140 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m");
143 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LABEL
, htobe32(v
->flow_label
));
145 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LABEL attribute: %m");
147 if (v
->group_policy
) {
148 r
= sd_netlink_message_append_flag(m
, IFLA_VXLAN_GBP
);
150 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GBP attribute: %m");
156 int config_parse_vxlan_address(const char *unit
,
157 const char *filename
,
160 unsigned section_line
,
167 union in_addr_union
*addr
= data
, buffer
;
175 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
177 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "vxlan '%s' address is invalid, ignoring assignment: %s", lvalue
, rvalue
);
181 r
= in_addr_is_multicast(f
, &buffer
);
183 if (streq(lvalue
, "Group")) {
185 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue
, rvalue
);
189 v
->remote_family
= f
;
192 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue
, rvalue
);
196 if (streq(lvalue
, "Remote"))
197 v
->remote_family
= f
;
207 int config_parse_port_range(const char *unit
,
208 const char *filename
,
211 unsigned section_line
,
217 _cleanup_free_
char *word
= NULL
;
227 r
= extract_first_word(&rvalue
, &word
, NULL
, 0);
229 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to extract VXLAN port range, ignoring: %s", rvalue
);
236 r
= parse_range(word
, &low
, &high
);
238 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse VXLAN port range '%s'", word
);
242 if (low
<= 0 || low
> 65535 || high
<= 0 || high
> 65535) {
243 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
244 "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word
);
249 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
250 "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word
, low
, high
);
254 v
->port_range
.low
= low
;
255 v
->port_range
.high
= high
;
260 int config_parse_flow_label(const char *unit
,
261 const char *filename
,
264 unsigned section_line
,
279 r
= safe_atou(rvalue
, &f
);
281 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse VXLAN flow label '%s'.", rvalue
);
285 if (f
& ~VXLAN_FLOW_LABEL_MAX_MASK
) {
286 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
287 "VXLAN flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue
);
296 static int netdev_vxlan_verify(NetDev
*netdev
, const char *filename
) {
297 VxLan
*v
= VXLAN(netdev
);
303 if (v
->id
> VXLAN_VID_MAX
) {
304 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename
);
311 static void vxlan_init(NetDev
*netdev
) {
320 v
->id
= VXLAN_VID_MAX
+ 1;
323 v
->udp6zerocsumtx
= false;
324 v
->udp6zerocsumrx
= false;
327 const NetDevVTable vxlan_vtable
= {
328 .object_size
= sizeof(VxLan
),
330 .sections
= "Match\0NetDev\0VXLAN\0",
331 .fill_message_create
= netdev_vxlan_fill_message_create
,
332 .create_type
= NETDEV_CREATE_STACKED
,
333 .config_verify
= netdev_vxlan_verify
,