1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "conf-parser.h"
6 #include "alloc-util.h"
7 #include "extract-word.h"
8 #include "string-table.h"
9 #include "string-util.h"
11 #include "parse-util.h"
14 static const char* const df_table
[_NETDEV_VXLAN_DF_MAX
] = {
15 [NETDEV_VXLAN_DF_NO
] = "no",
16 [NETDEV_VXLAN_DF_YES
] = "yes",
17 [NETDEV_VXLAN_DF_INHERIT
] = "inherit",
20 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(df
, VxLanDF
, NETDEV_VXLAN_DF_YES
);
21 DEFINE_CONFIG_PARSE_ENUM(config_parse_df
, df
, VxLanDF
, "Failed to parse VXLAN IPDoNotFragment= setting");
23 static int netdev_vxlan_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
34 if (v
->vni
<= VXLAN_VID_MAX
) {
35 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_ID
, v
->vni
);
37 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_ID attribute: %m");
40 if (in_addr_is_null(v
->group_family
, &v
->group
) == 0) {
41 if (v
->group_family
== AF_INET
)
42 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_GROUP
, &v
->group
.in
);
44 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_GROUP6
, &v
->group
.in6
);
46 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GROUP attribute: %m");
47 } else if (in_addr_is_null(v
->remote_family
, &v
->remote
) == 0) {
48 if (v
->remote_family
== AF_INET
)
49 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_GROUP
, &v
->remote
.in
);
51 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_GROUP6
, &v
->remote
.in6
);
53 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GROUP attribute: %m");
56 if (in_addr_is_null(v
->local_family
, &v
->local
) == 0) {
57 if (v
->local_family
== AF_INET
)
58 r
= sd_netlink_message_append_in_addr(m
, IFLA_VXLAN_LOCAL
, &v
->local
.in
);
60 r
= sd_netlink_message_append_in6_addr(m
, IFLA_VXLAN_LOCAL6
, &v
->local
.in6
);
62 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LOCAL attribute: %m");
65 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LINK
, link
? link
->ifindex
: 0);
67 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LINK attribute: %m");
70 r
= sd_netlink_message_append_flag(m
, IFLA_VXLAN_TTL_INHERIT
);
72 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TTL_INHERIT attribute: %m");
74 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TTL
, v
->ttl
);
76 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TTL attribute: %m");
80 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_TOS
, v
->tos
);
82 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_TOS attribute: %m");
85 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_LEARNING
, v
->learning
);
87 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LEARNING attribute: %m");
89 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_RSC
, v
->route_short_circuit
);
91 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_RSC attribute: %m");
93 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_PROXY
, v
->arp_proxy
);
95 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PROXY attribute: %m");
97 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L2MISS
, v
->l2miss
);
99 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L2MISS attribute: %m");
101 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_L3MISS
, v
->l3miss
);
103 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_L3MISS attribute: %m");
105 if (v
->fdb_ageing
!= 0) {
106 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_AGEING
, v
->fdb_ageing
/ USEC_PER_SEC
);
108 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_AGEING attribute: %m");
111 if (v
->max_fdb
!= 0) {
112 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LIMIT
, v
->max_fdb
);
114 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LIMIT attribute: %m");
117 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_CSUM
, v
->udpcsum
);
119 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m");
121 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_TX
, v
->udp6zerocsumtx
);
123 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m");
125 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_UDP_ZERO_CSUM6_RX
, v
->udp6zerocsumrx
);
127 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m");
129 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_TX
, v
->remote_csum_tx
);
131 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m");
133 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_REMCSUM_RX
, v
->remote_csum_rx
);
135 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m");
137 r
= sd_netlink_message_append_u16(m
, IFLA_VXLAN_PORT
, htobe16(v
->dest_port
));
139 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT attribute: %m");
141 if (v
->port_range
.low
!= 0 || v
->port_range
.high
!= 0) {
142 struct ifla_vxlan_port_range port_range
;
144 port_range
.low
= htobe16(v
->port_range
.low
);
145 port_range
.high
= htobe16(v
->port_range
.high
);
147 r
= sd_netlink_message_append_data(m
, IFLA_VXLAN_PORT_RANGE
, &port_range
, sizeof(port_range
));
149 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m");
152 r
= sd_netlink_message_append_u32(m
, IFLA_VXLAN_LABEL
, htobe32(v
->flow_label
));
154 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_LABEL attribute: %m");
156 if (v
->group_policy
) {
157 r
= sd_netlink_message_append_flag(m
, IFLA_VXLAN_GBP
);
159 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GBP attribute: %m");
162 if (v
->generic_protocol_extension
) {
163 r
= sd_netlink_message_append_flag(m
, IFLA_VXLAN_GPE
);
165 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_GPE attribute: %m");
168 if (v
->df
!= _NETDEV_VXLAN_DF_INVALID
) {
169 r
= sd_netlink_message_append_u8(m
, IFLA_VXLAN_DF
, v
->df
);
171 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_VXLAN_DF attribute: %m");
177 int config_parse_vxlan_address(const char *unit
,
178 const char *filename
,
181 unsigned section_line
,
188 union in_addr_union
*addr
= data
, buffer
;
196 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
198 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
, "vxlan '%s' address is invalid, ignoring assignment: %s", lvalue
, rvalue
);
202 r
= in_addr_is_multicast(f
, &buffer
);
204 if (streq(lvalue
, "Group")) {
206 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue
, rvalue
);
213 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue
, rvalue
);
217 if (streq(lvalue
, "Remote"))
218 v
->remote_family
= f
;
228 int config_parse_port_range(const char *unit
,
229 const char *filename
,
232 unsigned section_line
,
247 r
= parse_ip_port_range(rvalue
, &low
, &high
);
249 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
250 "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", rvalue
);
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_WARNING
, filename
, line
, r
, "Failed to parse VXLAN flow label '%s'.", rvalue
);
285 if (f
& ~VXLAN_FLOW_LABEL_MAX_MASK
) {
286 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
287 "VXLAN flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue
);
296 int config_parse_vxlan_ttl(const char *unit
,
297 const char *filename
,
300 unsigned section_line
,
315 if (streq(rvalue
, "inherit"))
318 r
= safe_atou(rvalue
, &f
);
320 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
321 "Failed to parse VXLAN TTL '%s', ignoring assignment: %m", rvalue
);
326 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
327 "Invalid VXLAN TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue
);
337 static int netdev_vxlan_verify(NetDev
*netdev
, const char *filename
) {
338 VxLan
*v
= VXLAN(netdev
);
344 if (v
->vni
> VXLAN_VID_MAX
)
345 return log_netdev_warning_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
346 "%s: VXLAN without valid VNI (or VXLAN Segment ID) configured. Ignoring.",
350 return log_netdev_warning_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
351 "%s: VXLAN TTL must be <= 255. Ignoring.",
354 if (!v
->dest_port
&& v
->generic_protocol_extension
)
357 if (in_addr_is_null(v
->group_family
, &v
->group
) == 0 && in_addr_is_null(v
->remote_family
, &v
->remote
) == 0)
358 return log_netdev_warning_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
359 "%s: VXLAN both 'Group=' and 'Remote=' cannot be specified. Ignoring.",
365 static void vxlan_init(NetDev
*netdev
) {
374 v
->vni
= VXLAN_VID_MAX
+ 1;
375 v
->df
= _NETDEV_VXLAN_DF_INVALID
;
378 v
->udp6zerocsumtx
= false;
379 v
->udp6zerocsumrx
= false;
382 const NetDevVTable vxlan_vtable
= {
383 .object_size
= sizeof(VxLan
),
385 .sections
= NETDEV_COMMON_SECTIONS
"VXLAN\0",
386 .fill_message_create
= netdev_vxlan_fill_message_create
,
387 .create_type
= NETDEV_CREATE_STACKED
,
388 .config_verify
= netdev_vxlan_verify
,
389 .generate_mac
= true,