1 /* SPDX-License-Identifier: LGPL-2.1+ */
6 #include "netlink-util.h"
7 #include "netdev/bridge.h"
8 #include "network-internal.h"
9 #include "networkd-manager.h"
10 #include "string-table.h"
11 #include "vlan-util.h"
13 static const char* const multicast_router_table
[_MULTICAST_ROUTER_MAX
] = {
14 [MULTICAST_ROUTER_NONE
] = "no",
15 [MULTICAST_ROUTER_TEMPORARY_QUERY
] = "query",
16 [MULTICAST_ROUTER_PERMANENT
] = "permanent",
17 [MULTICAST_ROUTER_TEMPORARY
] = "temporary",
20 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router
, MulticastRouter
, _MULTICAST_ROUTER_INVALID
);
21 DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router
, multicast_router
, MulticastRouter
,
22 "Failed to parse bridge multicast router setting");
24 /* callback for bridge netdev's parameter set */
25 static int netdev_bridge_set_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, NetDev
*netdev
) {
31 r
= sd_netlink_message_get_errno(m
);
33 log_netdev_warning_errno(netdev
, r
, "Bridge parameters could not be set: %m");
37 log_netdev_debug(netdev
, "Bridge parameters set success");
42 static int netdev_bridge_post_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
43 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
53 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
, RTM_NEWLINK
, netdev
->ifindex
);
55 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_SETLINK message: %m");
57 r
= sd_netlink_message_set_flags(req
, NLM_F_REQUEST
| NLM_F_ACK
);
59 return log_link_error_errno(link
, r
, "Could not set netlink flags: %m");
61 r
= sd_netlink_message_open_container(req
, IFLA_LINKINFO
);
63 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
65 r
= sd_netlink_message_open_container_union(req
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
67 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
69 /* convert to jiffes */
70 if (b
->forward_delay
!= USEC_INFINITY
) {
71 r
= sd_netlink_message_append_u32(req
, IFLA_BR_FORWARD_DELAY
, usec_to_jiffies(b
->forward_delay
));
73 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m");
76 if (b
->hello_time
> 0) {
77 r
= sd_netlink_message_append_u32(req
, IFLA_BR_HELLO_TIME
, usec_to_jiffies(b
->hello_time
));
79 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_HELLO_TIME attribute: %m");
83 r
= sd_netlink_message_append_u32(req
, IFLA_BR_MAX_AGE
, usec_to_jiffies(b
->max_age
));
85 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MAX_AGE attribute: %m");
88 if (b
->ageing_time
!= USEC_INFINITY
) {
89 r
= sd_netlink_message_append_u32(req
, IFLA_BR_AGEING_TIME
, usec_to_jiffies(b
->ageing_time
));
91 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_AGEING_TIME attribute: %m");
94 if (b
->priority
> 0) {
95 r
= sd_netlink_message_append_u16(req
, IFLA_BR_PRIORITY
, b
->priority
);
97 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_PRIORITY attribute: %m");
100 if (b
->group_fwd_mask
> 0) {
101 r
= sd_netlink_message_append_u16(req
, IFLA_BR_GROUP_FWD_MASK
, b
->group_fwd_mask
);
103 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_GROUP_FWD_MASK attribute: %m");
106 if (b
->default_pvid
!= VLANID_INVALID
) {
107 r
= sd_netlink_message_append_u16(req
, IFLA_BR_VLAN_DEFAULT_PVID
, b
->default_pvid
);
109 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m");
112 if (b
->mcast_querier
>= 0) {
113 r
= sd_netlink_message_append_u8(req
, IFLA_BR_MCAST_QUERIER
, b
->mcast_querier
);
115 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MCAST_QUERIER attribute: %m");
118 if (b
->mcast_snooping
>= 0) {
119 r
= sd_netlink_message_append_u8(req
, IFLA_BR_MCAST_SNOOPING
, b
->mcast_snooping
);
121 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m");
124 if (b
->vlan_filtering
>= 0) {
125 r
= sd_netlink_message_append_u8(req
, IFLA_BR_VLAN_FILTERING
, b
->vlan_filtering
);
127 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m");
131 r
= sd_netlink_message_append_u32(req
, IFLA_BR_STP_STATE
, b
->stp
);
133 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_BR_STP_STATE attribute: %m");
136 r
= sd_netlink_message_close_container(req
);
138 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
140 r
= sd_netlink_message_close_container(req
);
142 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
144 r
= netlink_call_async(netdev
->manager
->rtnl
, NULL
, req
, netdev_bridge_set_handler
,
145 netdev_destroy_callback
, netdev
);
147 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
154 static int link_set_bridge_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, Link
*link
) {
159 assert(link
->ifname
);
161 if (IN_SET(link
->state
, LINK_STATE_FAILED
, LINK_STATE_LINGER
))
164 r
= sd_netlink_message_get_errno(m
);
166 log_link_warning_errno(link
, r
, "Could not set bridge interface: %m");
173 int link_set_bridge(Link
*link
) {
174 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
178 assert(link
->network
);
180 r
= sd_rtnl_message_new_link(link
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
182 return log_link_error_errno(link
, r
, "Could not allocate RTM_SETLINK message: %m");
184 r
= sd_rtnl_message_link_set_family(req
, PF_BRIDGE
);
186 return log_link_error_errno(link
, r
, "Could not set message family: %m");
188 r
= sd_netlink_message_open_container(req
, IFLA_PROTINFO
);
190 return log_link_error_errno(link
, r
, "Could not append IFLA_PROTINFO attribute: %m");
192 if (link
->network
->use_bpdu
>= 0) {
193 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_GUARD
, link
->network
->use_bpdu
);
195 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_GUARD attribute: %m");
198 if (link
->network
->hairpin
>= 0) {
199 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MODE
, link
->network
->hairpin
);
201 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MODE attribute: %m");
204 if (link
->network
->fast_leave
>= 0) {
205 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_FAST_LEAVE
, link
->network
->fast_leave
);
207 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
210 if (link
->network
->allow_port_to_be_root
>= 0) {
211 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROTECT
, link
->network
->allow_port_to_be_root
);
213 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
216 if (link
->network
->unicast_flood
>= 0) {
217 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_UNICAST_FLOOD
, link
->network
->unicast_flood
);
219 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
222 if (link
->network
->multicast_flood
>= 0) {
223 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MCAST_FLOOD
, link
->network
->multicast_flood
);
225 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
228 if (link
->network
->multicast_to_unicast
>= 0) {
229 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MCAST_TO_UCAST
, link
->network
->multicast_to_unicast
);
231 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
234 if (link
->network
->neighbor_suppression
>= 0) {
235 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_NEIGH_SUPPRESS
, link
->network
->neighbor_suppression
);
237 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
240 if (link
->network
->learning
>= 0) {
241 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_LEARNING
, link
->network
->learning
);
243 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
246 if (link
->network
->bridge_proxy_arp
>= 0) {
247 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROXYARP
, link
->network
->bridge_proxy_arp
);
249 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROXYARP attribute: %m");
252 if (link
->network
->bridge_proxy_arp_wifi
>= 0) {
253 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_PROXYARP_WIFI
, link
->network
->bridge_proxy_arp_wifi
);
255 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m");
258 if (link
->network
->cost
!= 0) {
259 r
= sd_netlink_message_append_u32(req
, IFLA_BRPORT_COST
, link
->network
->cost
);
261 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_COST attribute: %m");
264 if (link
->network
->priority
!= LINK_BRIDGE_PORT_PRIORITY_INVALID
) {
265 r
= sd_netlink_message_append_u16(req
, IFLA_BRPORT_PRIORITY
, link
->network
->priority
);
267 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
270 if (link
->network
->multicast_router
!= _MULTICAST_ROUTER_INVALID
) {
271 r
= sd_netlink_message_append_u8(req
, IFLA_BRPORT_MULTICAST_ROUTER
, link
->network
->multicast_router
);
273 return log_link_error_errno(link
, r
, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
276 r
= sd_netlink_message_close_container(req
);
278 return log_link_error_errno(link
, r
, "Could not append IFLA_LINKINFO attribute: %m");
280 r
= netlink_call_async(link
->manager
->rtnl
, NULL
, req
, link_set_bridge_handler
,
281 link_netlink_destroy_callback
, link
);
283 return log_link_error_errno(link
, r
, "Could not send rtnetlink message: %m");
290 static void bridge_init(NetDev
*n
) {
297 b
->mcast_querier
= -1;
298 b
->mcast_snooping
= -1;
299 b
->vlan_filtering
= -1;
301 b
->default_pvid
= VLANID_INVALID
;
302 b
->forward_delay
= USEC_INFINITY
;
303 b
->ageing_time
= USEC_INFINITY
;
306 const NetDevVTable bridge_vtable
= {
307 .object_size
= sizeof(Bridge
),
309 .sections
= "Match\0NetDev\0Bridge\0",
310 .post_create
= netdev_bridge_post_create
,
311 .create_type
= NETDEV_CREATE_MASTER
,