1
0
mirror of https://github.com/systemd/systemd synced 2026-03-27 09:14:51 +01:00

Compare commits

...

7 Commits

Author SHA1 Message Date
Luca Boccassi
5bf20f3a0d
Merge pull request #20626 from yuwata/network-keep-master
network: introduce KeepMaster= setting
2021-09-04 15:08:56 +01:00
Yu Watanabe
e643c3d82d network: add 80-container-vb.network 2021-09-04 08:15:34 +09:00
Yu Watanabe
b06469a66c test-network: add tests for KeepMaster= 2021-09-04 08:15:30 +09:00
Yu Watanabe
57aef9d737 network: introduce KeepMaster= setting
Closes #20624.
2021-09-04 00:23:20 +09:00
Yu Watanabe
1f024462d1 network: assume enslaved when master ifindex is positive 2021-09-04 00:20:36 +09:00
Yu Watanabe
571bf1aa31 network: use master ifindex to check if the interface is enslaved 2021-09-04 00:20:36 +09:00
Yu Watanabe
a94ed9bd62 man: drop unnecessary white space 2021-09-04 00:20:36 +09:00
11 changed files with 198 additions and 55 deletions

View File

@ -139,7 +139,7 @@
<refsect1> <refsect1>
<title>[Link] Section Options</title> <title>[Link] Section Options</title>
<para> The [Link] section accepts the following keys:</para> <para>The [Link] section accepts the following keys:</para>
<variablelist class='network-directives'> <variablelist class='network-directives'>
<varlistentry> <varlistentry>
@ -427,7 +427,8 @@
has been unsuccessful for some time. (IPv4 link-local address autoconfiguration will usually has been unsuccessful for some time. (IPv4 link-local address autoconfiguration will usually
happen in parallel with repeated attempts to acquire a DHCPv4 lease).</para> happen in parallel with repeated attempts to acquire a DHCPv4 lease).</para>
<para>Defaults to <option>no</option> when <varname>Bridge=</varname> is set or when the specified <para>Defaults to <option>no</option> when <varname>KeepMaster=</varname> or
<varname>Bridge=</varname> is set or when the specified
<varname>MACVLAN=</varname>/<varname>MACVTAP=</varname> has <varname>Mode=passthru</varname>, or <varname>MACVLAN=</varname>/<varname>MACVTAP=</varname> has <varname>Mode=passthru</varname>, or
<option>ipv6</option> otherwise.</para> <option>ipv6</option> otherwise.</para>
</listitem> </listitem>
@ -923,6 +924,20 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
An integer greater than or equal to 1280 bytes. When unset, the kernel's default will be used. An integer greater than or equal to 1280 bytes. When unset, the kernel's default will be used.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>KeepMaster=</varname></term>
<term><varname>Bond=</varname></term>
<term><varname>Bridge=</varname></term>
<term><varname>VRF=</varname></term>
<listitem>
<para>Takes a boolean value. When enabled, the current master interface index will not be
changed, and <varname>BatmanAdvanced=</varname>, <varname>Bond=</varname>,
<varname>Bridge=</varname>, and <varname>VRF=</varname> settings are ignored. This may be
useful when a netdev with a master interface is created by another program, e.g.
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
Defaults to false.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>BatmanAdvanced=</varname></term> <term><varname>BatmanAdvanced=</varname></term>
<term><varname>Bond=</varname></term> <term><varname>Bond=</varname></term>

View File

@ -0,0 +1,22 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# This network file matches the host-side of the virtual Ethernet link
# created by systemd-nspawn's --network-veth switch with --network-bridge or
# --network-zone switch. See systemd-nspawn(1) for details.
[Match]
Name=vb-*
Driver=veth
[Network]
KeepMaster=yes
LinkLocalAddressing=no
LLDP=yes
EmitLLDP=nearest-bridge

View File

@ -92,7 +92,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r == -EINVAL && streq_ptr(link->kind, "bridge") && (!link->network || !link->network->bridge)) { if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) {
/* To configure bridge MDB entries on bridge master, 1bc844ee0faa1b92e3ede00bdd948021c78d7088 (v5.4) is required. */ /* To configure bridge MDB entries on bridge master, 1bc844ee0faa1b92e3ede00bdd948021c78d7088 (v5.4) is required. */
if (!link->manager->bridge_mdb_on_master_not_supported) { if (!link->manager->bridge_mdb_on_master_not_supported) {
log_link_warning_errno(link, r, "Kernel seems not to support bridge MDB entries on bridge master, ignoring: %m"); log_link_warning_errno(link, r, "Kernel seems not to support bridge MDB entries on bridge master, ignoring: %m");
@ -112,23 +112,11 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1; return 1;
} }
static int link_get_bridge_master_ifindex(Link *link) {
assert(link);
if (link->network && link->network->bridge)
return link->network->bridge->ifindex;
if (streq_ptr(link->kind, "bridge"))
return link->ifindex;
return 0;
}
/* send a request to the kernel to add an MDB entry */ /* send a request to the kernel to add an MDB entry */
static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) { static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
struct br_mdb_entry entry; struct br_mdb_entry entry;
int master, r; int r;
assert(mdb); assert(mdb);
assert(link); assert(link);
@ -144,14 +132,10 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
strna(a), mdb->vlan_id); strna(a), mdb->vlan_id);
} }
master = link_get_bridge_master_ifindex(link);
if (master <= 0)
return log_link_error_errno(link, SYNTHETIC_ERRNO(EINVAL), "Invalid bridge master ifindex %i", master);
entry = (struct br_mdb_entry) { entry = (struct br_mdb_entry) {
/* If MDB entry is added on bridge master, then the state must be MDB_TEMPORARY. /* If MDB entry is added on bridge master, then the state must be MDB_TEMPORARY.
* See br_mdb_add_group() in net/bridge/br_mdb.c of kernel. */ * See br_mdb_add_group() in net/bridge/br_mdb.c of kernel. */
.state = master == link->ifindex ? MDB_TEMPORARY : MDB_PERMANENT, .state = link->master_ifindex <= 0 ? MDB_TEMPORARY : MDB_PERMANENT,
.ifindex = link->ifindex, .ifindex = link->ifindex,
.vid = mdb->vlan_id, .vid = mdb->vlan_id,
}; };
@ -172,7 +156,8 @@ static int bridge_mdb_configure(BridgeMDB *mdb, Link *link, link_netlink_message
} }
/* create new RTM message */ /* create new RTM message */
r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB, master); r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB,
link->master_ifindex > 0 ? link->master_ifindex : link->ifindex);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m");
@ -205,16 +190,6 @@ int link_request_static_bridge_mdb(Link *link) {
if (hashmap_isempty(link->network->bridge_mdb_entries_by_section)) if (hashmap_isempty(link->network->bridge_mdb_entries_by_section))
goto finish; goto finish;
if (!link->network->bridge) {
if (!streq_ptr(link->kind, "bridge")) {
log_link_warning(link, "Link is neither a bridge master nor a bridge port, ignoring [BridgeMDB] sections.");
goto finish;
} else if (link->manager->bridge_mdb_on_master_not_supported) {
log_link_debug(link, "Kernel seems not to support bridge MDB entries on bridge master, ignoring [BridgeMDB] sections.");
goto finish;
}
}
HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) { HASHMAP_FOREACH(mdb, link->network->bridge_mdb_entries_by_section) {
r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false, r = link_queue_request(link, REQUEST_TYPE_BRIDGE_MDB, mdb, false,
&link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL); &link->static_bridge_mdb_messages, bridge_mdb_configure_handler, NULL);
@ -240,16 +215,13 @@ static bool bridge_mdb_is_ready_to_configure(Link *link) {
if (!link_is_ready_to_configure(link, false)) if (!link_is_ready_to_configure(link, false))
return false; return false;
if (!link->network->bridge) if (!link->master_set)
return false;
if (link->master_ifindex <= 0 && streq_ptr(link->kind, "bridge"))
return true; /* The interface is bridge master. */ return true; /* The interface is bridge master. */
if (link->master_ifindex <= 0) if (link_get_master(link, &master) < 0)
return false;
if (link->master_ifindex != link->network->bridge->ifindex)
return false;
if (link_get_by_index(link->manager, link->master_ifindex, &master) < 0)
return false; return false;
if (!streq_ptr(master->kind, "bridge")) if (!streq_ptr(master->kind, "bridge"))

View File

@ -1689,17 +1689,11 @@ bool link_has_carrier(Link *link) {
static bool link_is_enslaved(Link *link) { static bool link_is_enslaved(Link *link) {
if (link->flags & IFF_SLAVE) if (link->flags & IFF_SLAVE)
/* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */
return true; return true;
if (!link->network) if (link->master_ifindex > 0)
return false;
if (link->master_ifindex > 0 && link->network->bridge)
return true; return true;
/* TODO: add conditions for other netdevs. */
return false; return false;
} }
@ -2015,6 +2009,9 @@ static int link_update_master(Link *link, sd_netlink_message *message) {
if (r < 0) if (r < 0)
return log_link_debug_errno(link, r, "rtnl: failed to read master ifindex: %m"); return log_link_debug_errno(link, r, "rtnl: failed to read master ifindex: %m");
if (master_ifindex == link->ifindex)
master_ifindex = 0;
if (master_ifindex == link->master_ifindex) if (master_ifindex == link->master_ifindex)
return 0; return 0;

View File

@ -79,6 +79,7 @@ SR-IOV.Trust, config_parse_sr_iov_boolean,
SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, 0 SR-IOV.LinkState, config_parse_sr_iov_link_state, 0, 0
SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, 0 SR-IOV.MACAddress, config_parse_sr_iov_mac, 0, 0
Network.Description, config_parse_string, 0, offsetof(Network, description) Network.Description, config_parse_string, 0, offsetof(Network, description)
Network.KeepMaster, config_parse_bool, 0, offsetof(Network, keep_master)
Network.BatmanAdvanced, config_parse_ifname, 0, offsetof(Network, batadv_name) Network.BatmanAdvanced, config_parse_ifname, 0, offsetof(Network, batadv_name)
Network.Bond, config_parse_ifname, 0, offsetof(Network, bond_name) Network.Bond, config_parse_ifname, 0, offsetof(Network, bond_name)
Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name) Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name)

View File

@ -135,6 +135,26 @@ int network_verify(Network *network) {
"%s: Conditions in the file do not match the system environment, skipping.", "%s: Conditions in the file do not match the system environment, skipping.",
network->filename); network->filename);
if (network->keep_master) {
if (network->batadv_name)
log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
network->filename);
if (network->bond_name)
log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
network->filename);
if (network->bridge_name)
log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
network->filename);
if (network->vrf_name)
log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
network->filename);
network->batadv_name = mfree(network->batadv_name);
network->bond_name = mfree(network->bond_name);
network->bridge_name = mfree(network->bridge_name);
network->vrf_name = mfree(network->vrf_name);
}
(void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv); (void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv);
(void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond); (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
(void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge); (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
@ -174,7 +194,7 @@ int network_verify(Network *network) {
if (network->link_local < 0) { if (network->link_local < 0) {
network->link_local = ADDRESS_FAMILY_IPV6; network->link_local = ADDRESS_FAMILY_IPV6;
if (network->bridge) if (network->keep_master || network->bridge)
network->link_local = ADDRESS_FAMILY_NO; network->link_local = ADDRESS_FAMILY_NO;
else { else {
NetDev *netdev; NetDev *netdev;

View File

@ -84,6 +84,7 @@ struct Network {
LIST_HEAD(Condition, conditions); LIST_HEAD(Condition, conditions);
/* Master or stacked netdevs */ /* Master or stacked netdevs */
bool keep_master;
NetDev *batadv; NetDev *batadv;
NetDev *bridge; NetDev *bridge;
NetDev *bond; NetDev *bond;

View File

@ -405,7 +405,7 @@ static int link_configure(
if (r < 0) if (r < 0)
return log_link_debug_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); return log_link_debug_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
if (!link->network->bridge) { if (link->master_ifindex <= 0) {
/* master needs BRIDGE_FLAGS_SELF flag */ /* master needs BRIDGE_FLAGS_SELF flag */
r = sd_netlink_message_append_u16(req, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF); r = sd_netlink_message_append_u16(req, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF);
if (r < 0) if (r < 0)
@ -515,9 +515,16 @@ static bool link_is_ready_to_call_set_link(Request *req) {
switch (op) { switch (op) {
case SET_LINK_BOND: case SET_LINK_BOND:
case SET_LINK_BRIDGE: case SET_LINK_BRIDGE:
if (!link->master_set)
return false;
if (link->network->keep_master && link->master_ifindex <= 0)
return false;
break;
case SET_LINK_BRIDGE_VLAN: case SET_LINK_BRIDGE_VLAN:
if (!link->master_set) if (!link->master_set)
return false; return false;
if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
return false;
break; break;
case SET_LINK_CAN: case SET_LINK_CAN:
/* Do not check link->set_flgas_messages here, as it is ok even if link->flags /* Do not check link->set_flgas_messages here, as it is ok even if link->flags
@ -672,8 +679,18 @@ int link_request_to_set_bond(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
if (!link->network->bond) if (!link->network->bond) {
return 0; Link *master;
if (!link->network->keep_master)
return 0;
if (link_get_master(link, &master) < 0)
return 0;
if (!streq_ptr(master->kind, "bond"))
return 0;
}
return link_request_set_link(link, SET_LINK_BOND, link_set_bond_handler, NULL); return link_request_set_link(link, SET_LINK_BOND, link_set_bond_handler, NULL);
} }
@ -682,8 +699,18 @@ int link_request_to_set_bridge(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
if (!link->network->bridge) if (!link->network->bridge) {
return 0; Link *master;
if (!link->network->keep_master)
return 0;
if (link_get_master(link, &master) < 0)
return 0;
if (!streq_ptr(master->kind, "bridge"))
return 0;
}
return link_request_set_link(link, SET_LINK_BRIDGE, link_set_bridge_handler, NULL); return link_request_set_link(link, SET_LINK_BRIDGE, link_set_bridge_handler, NULL);
} }
@ -695,8 +722,18 @@ int link_request_to_set_bridge_vlan(Link *link) {
if (!link->network->use_br_vlan) if (!link->network->use_br_vlan)
return 0; return 0;
if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) {
return 0; Link *master;
if (!link->network->keep_master)
return 0;
if (link_get_master(link, &master) < 0)
return 0;
if (!streq_ptr(master->kind, "bridge"))
return 0;
}
return link_request_set_link(link, SET_LINK_BRIDGE_VLAN, link_set_bridge_vlan_handler, NULL); return link_request_set_link(link, SET_LINK_BRIDGE_VLAN, link_set_bridge_vlan_handler, NULL);
} }
@ -763,6 +800,11 @@ int link_request_to_set_master(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
if (link->network->keep_master) {
link->master_set = true;
return 0;
}
link->master_set = false; link->master_set = false;
if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf)

View File

@ -178,6 +178,7 @@ MultiPathRoute=
TCPAdvertisedMaximumSegmentSize= TCPAdvertisedMaximumSegmentSize=
NextHop= NextHop=
[Network] [Network]
KeepMaster=
IPv6DuplicateAddressDetection= IPv6DuplicateAddressDetection=
IPMasquerade= IPMasquerade=
ProxyARP= ProxyARP=

View File

@ -0,0 +1,21 @@
[Match]
Name=dummy98
[Network]
LinkLocalAddressing=no
IPv6AcceptRA=no
KeepMaster=true
ActiveSlave=true
[Bridge]
Cost=400
HairPin = true
FastLeave = true
UnicastFlood = true
MulticastFlood = false
MulticastToUnicast = true
NeighborSuppression = true
Learning = false
Priority = 23
UseBPDU = true
AllowPortToBeRoot=true

View File

@ -3388,6 +3388,7 @@ class NetworkdBondTests(unittest.TestCase, Utilities):
'12-dummy.netdev', '12-dummy.netdev',
'23-active-slave.network', '23-active-slave.network',
'23-bond199.network', '23-bond199.network',
'23-keep-master.network',
'23-primary-slave.network', '23-primary-slave.network',
'25-bond-active-backup-slave.netdev', '25-bond-active-backup-slave.netdev',
'25-bond.netdev', '25-bond.netdev',
@ -3403,6 +3404,23 @@ class NetworkdBondTests(unittest.TestCase, Utilities):
remove_unit_from_networkd_path(self.units) remove_unit_from_networkd_path(self.units)
stop_networkd(show_logs=True) stop_networkd(show_logs=True)
def test_bond_keep_master(self):
check_output('ip link add bond199 type bond mode active-backup')
check_output('ip link add dummy98 type dummy')
check_output('ip link set dummy98 master bond199')
copy_unit_to_networkd_unit_path('23-keep-master.network')
start_networkd()
self.wait_online(['dummy98:enslaved'])
output = check_output('ip -d link show bond199')
print(output)
self.assertRegex(output, 'active_slave dummy98')
output = check_output('ip -d link show dummy98')
print(output)
self.assertRegex(output, 'master bond199')
def test_bond_active_slave(self): def test_bond_active_slave(self):
copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
start_networkd() start_networkd()
@ -3479,6 +3497,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
'12-dummy.netdev', '12-dummy.netdev',
'21-vlan.netdev', '21-vlan.netdev',
'21-vlan.network', '21-vlan.network',
'23-keep-master.network',
'26-bridge.netdev', '26-bridge.netdev',
'26-bridge-configure-without-carrier.network', '26-bridge-configure-without-carrier.network',
'26-bridge-issue-20373.netdev', '26-bridge-issue-20373.netdev',
@ -3562,6 +3581,38 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066') self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067') self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
def test_bridge_keep_master(self):
check_output('ip link add bridge99 type bridge')
check_output('ip link set bridge99 up')
check_output('ip link add dummy98 type dummy')
check_output('ip link set dummy98 master bridge99')
copy_unit_to_networkd_unit_path('23-keep-master.network')
start_networkd()
self.wait_online(['dummy98:enslaved'])
output = check_output('ip -d link show dummy98')
print(output)
self.assertRegex(output, 'master bridge99')
self.assertRegex(output, 'bridge')
output = check_output('bridge -d link show dummy98')
print(output)
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
# CONFIG_BRIDGE_IGMP_SNOOPING=y
if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
def test_bridge_property(self): def test_bridge_property(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
'26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',