1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2017 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 "alloc-util.h"
24 #include "conf-parser.h"
25 #include "extract-word.h"
27 #include "parse-util.h"
28 #include "sd-netlink.h"
29 #include "string-util.h"
32 #include "networkd-manager.h"
34 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
35 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
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
;
42 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
44 r
= sd_netlink_message_get_errno(m
);
46 log_netdev_info(netdev
, "Geneve netdev exists, using existing without changing its parameters");
48 log_netdev_warning_errno(netdev
, r
, "Geneve netdev could not be created: %m");
54 log_netdev_debug(netdev
, "Geneve created");
59 static int netdev_geneve_create(NetDev
*netdev
) {
60 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
68 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &m
, RTM_NEWLINK
, 0);
70 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_NEWLINK message: %m");
72 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, netdev
->ifname
);
74 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IFNAME, attribute: %m");
77 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, netdev
->mac
);
79 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_ADDRESS attribute: %m");
83 r
= sd_netlink_message_append_u32(m
, IFLA_MTU
, netdev
->mtu
);
85 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MTU attribute: %m");
88 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
90 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
92 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
94 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
96 if (v
->id
<= GENEVE_VID_MAX
) {
97 r
= sd_netlink_message_append_u32(m
, IFLA_GENEVE_ID
, v
->id
);
99 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_ID attribute: %m");
102 if (!in_addr_is_null(v
->remote_family
, &v
->remote
)) {
104 if (v
->remote_family
== AF_INET
)
105 r
= sd_netlink_message_append_in_addr(m
, IFLA_GENEVE_REMOTE
, &v
->remote
.in
);
107 r
= sd_netlink_message_append_in6_addr(m
, IFLA_GENEVE_REMOTE6
, &v
->remote
.in6
);
110 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_GROUP attribute: %m");
115 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_TTL
, v
->ttl
);
117 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_TTL attribute: %m");
120 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_TOS
, v
->tos
);
122 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_TOS attribute: %m");
124 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_CSUM
, v
->udpcsum
);
126 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
128 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_ZERO_CSUM6_TX
, v
->udp6zerocsumtx
);
130 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
132 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_ZERO_CSUM6_RX
, v
->udp6zerocsumrx
);
134 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
136 if (v
->dest_port
!= DEFAULT_GENEVE_DESTINATION_PORT
) {
137 r
= sd_netlink_message_append_u16(m
, IFLA_GENEVE_PORT
, htobe16(v
->dest_port
));
139 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_PORT attribute: %m");
142 if (v
->flow_label
> 0) {
143 r
= sd_netlink_message_append_u32(m
, IFLA_GENEVE_LABEL
, htobe32(v
->flow_label
));
145 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_LABEL attribute: %m");
148 r
= sd_netlink_message_close_container(m
);
150 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
152 r
= sd_netlink_message_close_container(m
);
154 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
156 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, geneve_netdev_create_handler
, netdev
, 0, NULL
);
158 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
162 netdev
->state
= NETDEV_STATE_CREATING
;
164 log_netdev_debug(netdev
, "Creating");
170 int config_parse_geneve_vni(const char *unit
,
171 const char *filename
,
174 unsigned section_line
,
180 Geneve
*v
= userdata
;
189 r
= safe_atou32(rvalue
, &f
);
191 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Geneve VNI '%s'.", rvalue
);
195 if (f
> GENEVE_VID_MAX
){
196 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Geneve VNI out is of range '%s'.", rvalue
);
205 int config_parse_geneve_address(const char *unit
,
206 const char *filename
,
209 unsigned section_line
,
215 Geneve
*v
= userdata
;
216 union in_addr_union
*addr
= data
, buffer
;
224 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
226 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue
, rvalue
);
230 r
= in_addr_is_multicast(f
, &buffer
);
232 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue
, rvalue
);
236 v
->remote_family
= f
;
242 int config_parse_geneve_flow_label(const char *unit
,
243 const char *filename
,
246 unsigned section_line
,
252 Geneve
*v
= userdata
;
261 r
= safe_atou32(rvalue
, &f
);
263 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Geneve flow label '%s'.", rvalue
);
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
);
278 static int netdev_geneve_verify(NetDev
*netdev
, const char *filename
) {
279 Geneve
*v
= GENEVE(netdev
);
286 log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename
);
293 static void geneve_init(NetDev
*netdev
) {
302 v
->id
= GENEVE_VID_MAX
+ 1;
303 v
->dest_port
= DEFAULT_GENEVE_DESTINATION_PORT
;
305 v
->udp6zerocsumtx
= false;
306 v
->udp6zerocsumrx
= false;
309 const NetDevVTable geneve_vtable
= {
310 .object_size
= sizeof(Geneve
),
312 .sections
= "Match\0NetDev\0GENEVE\0",
313 .create
= netdev_geneve_create
,
314 .create_type
= NETDEV_CREATE_INDEPENDENT
,
315 .config_verify
= netdev_geneve_verify
,