mirror of
https://github.com/systemd/systemd
synced 2026-03-27 01:04:53 +01:00
Compare commits
7 Commits
c29537f39e
...
5bf20f3a0d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bf20f3a0d | ||
|
|
e643c3d82d | ||
|
|
b06469a66c | ||
|
|
57aef9d737 | ||
|
|
1f024462d1 | ||
|
|
571bf1aa31 | ||
|
|
a94ed9bd62 |
@ -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>
|
||||||
|
|||||||
22
network/80-container-vb.network
Normal file
22
network/80-container-vb.network
Normal 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
|
||||||
@ -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"))
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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,9 +679,19 @@ 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) {
|
||||||
|
Link *master;
|
||||||
|
|
||||||
|
if (!link->network->keep_master)
|
||||||
return 0;
|
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,9 +699,19 @@ 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) {
|
||||||
|
Link *master;
|
||||||
|
|
||||||
|
if (!link->network->keep_master)
|
||||||
return 0;
|
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,9 +722,19 @@ 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")) {
|
||||||
|
Link *master;
|
||||||
|
|
||||||
|
if (!link->network->keep_master)
|
||||||
return 0;
|
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)
|
||||||
|
|||||||
@ -178,6 +178,7 @@ MultiPathRoute=
|
|||||||
TCPAdvertisedMaximumSegmentSize=
|
TCPAdvertisedMaximumSegmentSize=
|
||||||
NextHop=
|
NextHop=
|
||||||
[Network]
|
[Network]
|
||||||
|
KeepMaster=
|
||||||
IPv6DuplicateAddressDetection=
|
IPv6DuplicateAddressDetection=
|
||||||
IPMasquerade=
|
IPMasquerade=
|
||||||
ProxyARP=
|
ProxyARP=
|
||||||
|
|||||||
21
test/test-network/conf/23-keep-master.network
Normal file
21
test/test-network/conf/23-keep-master.network
Normal 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
|
||||||
@ -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',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user