1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "netlink-util.h"
7 #include "network-internal.h"
8 #include "networkd-manager.h"
9 #include "string-table.h"
10 #include "vlan-util.h"
12 static const char* const multicast_router_table
[_MULTICAST_ROUTER_MAX
] = {
13 [MULTICAST_ROUTER_NONE
] = "no",
14 [MULTICAST_ROUTER_TEMPORARY_QUERY
] = "query",
15 [MULTICAST_ROUTER_PERMANENT
] = "permanent",
16 [MULTICAST_ROUTER_TEMPORARY
] = "temporary",
19 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router
, MulticastRouter
, _MULTICAST_ROUTER_INVALID
);
20 DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router
, multicast_router
, MulticastRouter
,
21 "Failed to parse bridge multicast router setting");
23 /* callback for bridge netdev's parameter set */
24 static int netdev_bridge_set_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, NetDev
*netdev
) {
30 r
= sd_netlink_message_get_errno(m
);
32 log_netdev_warning_errno(netdev
, r
, "Bridge parameters could not be set: %m");
36 log_netdev_debug(netdev
, "Bridge parameters set success");
41 static int netdev_bridge_post_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
42 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
52 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
, RTM_NEWLINK
, netdev
->ifindex
);
54 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_SETLINK message: %m");
56 r
= sd_netlink_message_set_flags(req
, NLM_F_REQUEST
| NLM_F_ACK
);
58 return log_link_error_errno(link
, r
, "Could not set netlink flags: %m");
60 r
= sd_netlink_message_open_container(req
, IFLA_LINKINFO
);
62 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
64 r
= sd_netlink_message_open_container_union(req
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
66 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
68 /* convert to jiffes */
69 if (b
->forward_delay
!= USEC_INFINITY
) {
70 r
= sd_netlink_message_append_u32(req
, IFLA_BR_FORWARD_DELAY
, usec_to_jiffies(b
->forward_delay
));
72 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m");
75 if (b
->hello_time
> 0) {
76 r
= sd_netlink_message_append_u32(req
, IFLA_BR_HELLO_TIME
, usec_to_jiffies(b
->hello_time
));
78 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_HELLO_TIME attribute: %m");
82 r
= sd_netlink_message_append_u32(req
, IFLA_BR_MAX_AGE
, usec_to_jiffies(b
->max_age
));
84 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MAX_AGE attribute: %m");
87 if (b
->ageing_time
!= USEC_INFINITY
) {
88 r
= sd_netlink_message_append_u32(req
, IFLA_BR_AGEING_TIME
, usec_to_jiffies(b
->ageing_time
));
90 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_AGEING_TIME attribute: %m");
93 if (b
->priority
> 0) {
94 r
= sd_netlink_message_append_u16(req
, IFLA_BR_PRIORITY
, b
->priority
);
96 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_PRIORITY attribute: %m");
99 if (b
->group_fwd_mask
> 0) {
100 r
= sd_netlink_message_append_u16(req
, IFLA_BR_GROUP_FWD_MASK
, b
->group_fwd_mask
);
102 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_GROUP_FWD_MASK attribute: %m");
105 if (b
->default_pvid
!= VLANID_INVALID
) {
106 r
= sd_netlink_message_append_u16(req
, IFLA_BR_VLAN_DEFAULT_PVID
, b
->default_pvid
);
108 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m");
111 if (b
->mcast_querier
>= 0) {
112 r
= sd_netlink_message_append_u8(req
, IFLA_BR_MCAST_QUERIER
, b
->mcast_querier
);
114 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MCAST_QUERIER attribute: %m");
117 if (b
->mcast_snooping
>= 0) {
118 r
= sd_netlink_message_append_u8(req
, IFLA_BR_MCAST_SNOOPING
, b
->mcast_snooping
);
120 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m");
123 if (b
->vlan_filtering
>= 0) {
124 r
= sd_netlink_message_append_u8(req
, IFLA_BR_VLAN_FILTERING
, b
->vlan_filtering
);
126 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m");
129 if (b
->vlan_protocol
>= 0) {
130 r
= sd_netlink_message_append_u16(req
, IFLA_BR_VLAN_PROTOCOL
, b
->vlan_protocol
);
132 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_VLAN_PROTOCOL attribute: %m");
136 r
= sd_netlink_message_append_u32(req
, IFLA_BR_STP_STATE
, b
->stp
);
138 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_STP_STATE attribute: %m");
141 if (b
->igmp_version
> 0) {
142 r
= sd_netlink_message_append_u8(req
, IFLA_BR_MCAST_IGMP_VERSION
, b
->igmp_version
);
144 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MCAST_IGMP_VERSION attribute: %m");
147 r
= sd_netlink_message_close_container(req
);
149 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
151 r
= sd_netlink_message_close_container(req
);
153 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
155 r
= netlink_call_async(netdev
->manager
->rtnl
, NULL
, req
, netdev_bridge_set_handler
,
156 netdev_destroy_callback
, netdev
);
158 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
165 static int link_set_bridge_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
170 assert(link
->ifname
);
172 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
175 r
= sd_netlink_message_get_errno(m
);
177 log_link_warning_errno(link
, r
, "Could not set bridge interface: %m");
184 int link_set_bridge(Link
*link
) {
185 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
189 assert(link
->network
);
191 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
193 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
195 r
= sd_rtnl_message_link_set_family(req
, AF_BRIDGE
);
197 return log_link_error_errno(link
, r
, "Could not set message family: %m");
199 r
= sd_netlink_message_open_container(req
, IFLA_PROTINFO
);
201 return log_link_error_errno(link
, r
, "Could not append IFLA_PROTINFO attribute: %m");
203 if (link
->network
->use_bpdu
>= 0) {
204 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_GUARD
, link
->network
->use_bpdu
);
206 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_GUARD attribute: %m");
209 if (link
->network
->hairpin
>= 0) {
210 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MODE
, link
->network
->hairpin
);
212 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MODE attribute: %m");
215 if (link
->network
->fast_leave
>= 0) {
216 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_FAST_LEAVE
, link
->network
->fast_leave
);
218 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
221 if (link
->network
->allow_port_to_be_root
>= 0) {
222 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROTECT
, link
->network
->allow_port_to_be_root
);
224 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
227 if (link
->network
->unicast_flood
>= 0) {
228 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_UNICAST_FLOOD
, link
->network
->unicast_flood
);
230 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
233 if (link
->network
->multicast_flood
>= 0) {
234 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MCAST_FLOOD
, link
->network
->multicast_flood
);
236 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
239 if (link
->network
->multicast_to_unicast
>= 0) {
240 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MCAST_TO_UCAST
, link
->network
->multicast_to_unicast
);
242 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
245 if (link
->network
->neighbor_suppression
>= 0) {
246 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_NEIGH_SUPPRESS
, link
->network
->neighbor_suppression
);
248 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
251 if (link
->network
->learning
>= 0) {
252 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_LEARNING
, link
->network
->learning
);
254 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
257 if (link
->network
->bridge_proxy_arp
>= 0) {
258 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROXYARP
, link
->network
->bridge_proxy_arp
);
260 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROXYARP attribute: %m");
263 if (link
->network
->bridge_proxy_arp_wifi
>= 0) {
264 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROXYARP_WIFI
, link
->network
->bridge_proxy_arp_wifi
);
266 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m");
269 if (link
->network
->cost
!= 0) {
270 r
= sd_netlink_message_append_u32(req
, IFLA_BRPORT_COST
, link
->network
->cost
);
272 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_COST attribute: %m");
275 if (link
->network
->priority
!= LINK_BRIDGE_PORT_PRIORITY_INVALID
) {
276 r
= sd_netlink_message_append_u16(req
, IFLA_BRPORT_PRIORITY
, link
->network
->priority
);
278 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
281 if (link
->network
->multicast_router
!= _MULTICAST_ROUTER_INVALID
) {
282 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MULTICAST_ROUTER
, link
->network
->multicast_router
);
284 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
287 r
= sd_netlink_message_close_container(req
);
289 return log_link_error_errno(link
, r
, "Could not append IFLA_LINKINFO attribute: %m");
291 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, link_set_bridge_handler
,
292 link_netlink_destroy_callback
, link
);
294 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
301 int config_parse_bridge_igmp_version(
303 const char *filename
,
306 unsigned section_line
,
313 Bridge
*b
= userdata
;
322 if (isempty(rvalue
)) {
323 b
->igmp_version
= 0; /* 0 means unset. */
327 r
= safe_atou8(rvalue
, &u
);
329 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
330 "Failed to parse bridge's multicast IGMP version number '%s', ignoring assignment: %m",
334 if (!IN_SET(u
, 2, 3)) {
335 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
336 "Invalid bridge's multicast IGMP version number '%s', ignoring assignment.", rvalue
);
345 static void bridge_init(NetDev
*n
) {
352 b
->mcast_querier
= -1;
353 b
->mcast_snooping
= -1;
354 b
->vlan_filtering
= -1;
355 b
->vlan_protocol
= -1;
357 b
->default_pvid
= VLANID_INVALID
;
358 b
->forward_delay
= USEC_INFINITY
;
359 b
->ageing_time
= USEC_INFINITY
;
362 const NetDevVTable bridge_vtable
= {
363 .object_size
= sizeof(Bridge
),
365 .sections
= NETDEV_COMMON_SECTIONS
"Bridge\0",
366 .post_create
= netdev_bridge_post_create
,
367 .create_type
= NETDEV_CREATE_MASTER
,