1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2017 Susant Sahani
8 #include "alloc-util.h"
9 #include "conf-parser.h"
10 #include "extract-word.h"
12 #include "parse-util.h"
13 #include "sd-netlink.h"
14 #include "string-util.h"
17 #include "networkd-manager.h"
19 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
20 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
22 /* callback for geneve netdev's created without a backing Link */
23 static int geneve_netdev_create_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
24 _cleanup_(netdev_unrefp
) NetDev
*netdev
= userdata
;
27 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
29 r
= sd_netlink_message_get_errno(m
);
31 log_netdev_info(netdev
, "Geneve netdev exists, using existing without changing its parameters");
33 log_netdev_warning_errno(netdev
, r
, "Geneve netdev could not be created: %m");
39 log_netdev_debug(netdev
, "Geneve created");
44 static int netdev_geneve_create(NetDev
*netdev
) {
45 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
53 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &m
, RTM_NEWLINK
, 0);
55 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_NEWLINK message: %m");
57 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, netdev
->ifname
);
59 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IFNAME, attribute: %m");
62 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, netdev
->mac
);
64 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_ADDRESS attribute: %m");
67 if (netdev
->mtu
!= 0) {
68 r
= sd_netlink_message_append_u32(m
, IFLA_MTU
, netdev
->mtu
);
70 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MTU attribute: %m");
73 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
75 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
77 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
79 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
81 if (v
->id
<= GENEVE_VID_MAX
) {
82 r
= sd_netlink_message_append_u32(m
, IFLA_GENEVE_ID
, v
->id
);
84 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_ID attribute: %m");
87 if (!in_addr_is_null(v
->remote_family
, &v
->remote
)) {
89 if (v
->remote_family
== AF_INET
)
90 r
= sd_netlink_message_append_in_addr(m
, IFLA_GENEVE_REMOTE
, &v
->remote
.in
);
92 r
= sd_netlink_message_append_in6_addr(m
, IFLA_GENEVE_REMOTE6
, &v
->remote
.in6
);
95 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_GROUP attribute: %m");
100 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_TTL
, v
->ttl
);
102 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_TTL attribute: %m");
105 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_TOS
, v
->tos
);
107 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_TOS attribute: %m");
109 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_CSUM
, v
->udpcsum
);
111 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
113 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_ZERO_CSUM6_TX
, v
->udp6zerocsumtx
);
115 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
117 r
= sd_netlink_message_append_u8(m
, IFLA_GENEVE_UDP_ZERO_CSUM6_RX
, v
->udp6zerocsumrx
);
119 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
121 if (v
->dest_port
!= DEFAULT_GENEVE_DESTINATION_PORT
) {
122 r
= sd_netlink_message_append_u16(m
, IFLA_GENEVE_PORT
, htobe16(v
->dest_port
));
124 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_PORT attribute: %m");
127 if (v
->flow_label
> 0) {
128 r
= sd_netlink_message_append_u32(m
, IFLA_GENEVE_LABEL
, htobe32(v
->flow_label
));
130 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_GENEVE_LABEL attribute: %m");
133 r
= sd_netlink_message_close_container(m
);
135 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
137 r
= sd_netlink_message_close_container(m
);
139 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
141 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, geneve_netdev_create_handler
, netdev
, 0, NULL
);
143 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
147 netdev
->state
= NETDEV_STATE_CREATING
;
149 log_netdev_debug(netdev
, "Creating");
154 int config_parse_geneve_vni(const char *unit
,
155 const char *filename
,
158 unsigned section_line
,
164 Geneve
*v
= userdata
;
173 r
= safe_atou32(rvalue
, &f
);
175 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Geneve VNI '%s'.", rvalue
);
179 if (f
> GENEVE_VID_MAX
){
180 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Geneve VNI out is of range '%s'.", rvalue
);
189 int config_parse_geneve_address(const char *unit
,
190 const char *filename
,
193 unsigned section_line
,
199 Geneve
*v
= userdata
;
200 union in_addr_union
*addr
= data
, buffer
;
208 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
210 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue
, rvalue
);
214 r
= in_addr_is_multicast(f
, &buffer
);
216 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue
, rvalue
);
220 v
->remote_family
= f
;
226 int config_parse_geneve_flow_label(const char *unit
,
227 const char *filename
,
230 unsigned section_line
,
236 Geneve
*v
= userdata
;
245 r
= safe_atou32(rvalue
, &f
);
247 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse Geneve flow label '%s'.", rvalue
);
251 if (f
& ~GENEVE_FLOW_LABEL_MAX_MASK
) {
252 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
253 "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue
);
262 static int netdev_geneve_verify(NetDev
*netdev
, const char *filename
) {
263 Geneve
*v
= GENEVE(netdev
);
270 log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename
);
277 static void geneve_init(NetDev
*netdev
) {
286 v
->id
= GENEVE_VID_MAX
+ 1;
287 v
->dest_port
= DEFAULT_GENEVE_DESTINATION_PORT
;
289 v
->udp6zerocsumtx
= false;
290 v
->udp6zerocsumrx
= false;
293 const NetDevVTable geneve_vtable
= {
294 .object_size
= sizeof(Geneve
),
296 .sections
= "Match\0NetDev\0GENEVE\0",
297 .create
= netdev_geneve_create
,
298 .create_type
= NETDEV_CREATE_INDEPENDENT
,
299 .config_verify
= netdev_geneve_verify
,