Merge pull request #11767 from yuwata/network-bridge-enslaved
network: extend 'enslaved' state to bridge slave
This commit is contained in:
+5
-4
@@ -118,21 +118,22 @@
|
||||
<varlistentry>
|
||||
<term>carrier</term>
|
||||
<listitem>
|
||||
<para>the link has a carrier, or for bond master, all bonding slave network interfaces are
|
||||
enslaved to the master.</para>
|
||||
<para>the link has a carrier, or for bond or bridge master, all bonding or bridge slave
|
||||
network interfaces are enslaved to the master.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>degraded</term>
|
||||
<listitem>
|
||||
<para>the link has carrier and addresses valid on the local link configured, or for bond
|
||||
master, one of the bonding slave network interfaces is in off, no-carrier, or dormant</para>
|
||||
or bridge master, one of the bonding or bridge slave network interfaces is in off,
|
||||
no-carrier, or dormant</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>enslaved</term>
|
||||
<listitem>
|
||||
<para>the link has carrier and is enslaved to other network interfaces</para>
|
||||
<para>the link has carrier and is enslaved to bond or bridge master network interface</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
@@ -318,10 +318,10 @@
|
||||
<varlistentry>
|
||||
<term><varname>LinkLocalAddressing=</varname></term>
|
||||
<listitem>
|
||||
<para>Enables link-local address autoconfiguration. Accepts
|
||||
<literal>yes</literal>, <literal>no</literal>,
|
||||
<literal>ipv4</literal>, or <literal>ipv6</literal>. Defaults to
|
||||
<literal>ipv6</literal>.</para>
|
||||
<para>Enables link-local address autoconfiguration. Accepts <literal>yes</literal>,
|
||||
<literal>no</literal>, <literal>ipv4</literal>, or <literal>ipv6</literal>. If
|
||||
<varname>Bridge=</varname> is set, defaults to <literal>no</literal>, and if not,
|
||||
defaults to <literal>ipv6</literal>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
+92
-55
@@ -158,7 +158,7 @@ static bool link_ipv6_enabled(Link *link) {
|
||||
if (!socket_ipv6_is_supported())
|
||||
return false;
|
||||
|
||||
if (link->network->bridge || link->network->bond)
|
||||
if (link->network->bond)
|
||||
return false;
|
||||
|
||||
if (manager_sysctl_ipv6_enabled(link->manager) == 0)
|
||||
@@ -328,8 +328,39 @@ static int link_enable_ipv6(Link *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void link_update_operstate(Link *link, bool also_update_bond_master) {
|
||||
static bool link_is_enslaved(Link *link) {
|
||||
if (link->flags & IFF_SLAVE)
|
||||
/* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */
|
||||
return true;
|
||||
|
||||
if (!link->enslaved_raw)
|
||||
return false;
|
||||
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
if (link->network->bridge)
|
||||
/* TODO: support the case when link is not managed by networkd. */
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void link_update_master_operstate(Link *link, NetDev *netdev) {
|
||||
Link *master;
|
||||
|
||||
if (!netdev)
|
||||
return;
|
||||
|
||||
if (link_get(link->manager, netdev->ifindex, &master) < 0)
|
||||
return;
|
||||
|
||||
link_update_operstate(master, true);
|
||||
}
|
||||
|
||||
void link_update_operstate(Link *link, bool also_update_master) {
|
||||
LinkOperationalState operstate;
|
||||
Iterator i;
|
||||
|
||||
assert(link);
|
||||
|
||||
@@ -338,7 +369,6 @@ void link_update_operstate(Link *link, bool also_update_bond_master) {
|
||||
else if (link_has_carrier(link)) {
|
||||
Address *address;
|
||||
uint8_t scope = RT_SCOPE_NOWHERE;
|
||||
Iterator i;
|
||||
|
||||
/* if we have carrier, check what addresses we have */
|
||||
SET_FOREACH(address, link->addresses, i) {
|
||||
@@ -373,15 +403,13 @@ void link_update_operstate(Link *link, bool also_update_bond_master) {
|
||||
operstate = LINK_OPERSTATE_OFF;
|
||||
|
||||
if (IN_SET(operstate, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_CARRIER) &&
|
||||
link->flags & IFF_SLAVE)
|
||||
link_is_enslaved(link))
|
||||
operstate = LINK_OPERSTATE_ENSLAVED;
|
||||
|
||||
if (IN_SET(operstate, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_ENSLAVED, LINK_OPERSTATE_ROUTABLE) &&
|
||||
!hashmap_isempty(link->bond_slaves)) {
|
||||
Iterator i;
|
||||
if (IN_SET(operstate, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_ENSLAVED, LINK_OPERSTATE_ROUTABLE)) {
|
||||
Link *slave;
|
||||
|
||||
HASHMAP_FOREACH(slave, link->bond_slaves, i) {
|
||||
HASHMAP_FOREACH(slave, link->slaves, i) {
|
||||
link_update_operstate(slave, false);
|
||||
|
||||
if (IN_SET(slave->operstate,
|
||||
@@ -396,13 +424,9 @@ void link_update_operstate(Link *link, bool also_update_bond_master) {
|
||||
link_dirty(link);
|
||||
}
|
||||
|
||||
if (also_update_bond_master && link->network && link->network->bond) {
|
||||
Link *master;
|
||||
|
||||
if (link_get(link->manager, link->network->bond->ifindex, &master) < 0)
|
||||
return;
|
||||
|
||||
link_update_operstate(master, true);
|
||||
if (also_update_master && link->network) {
|
||||
link_update_master_operstate(link, link->network->bond);
|
||||
link_update_master_operstate(link, link->network->bridge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,8 +616,8 @@ static void link_detach_from_manager(Link *link) {
|
||||
}
|
||||
|
||||
static Link *link_free(Link *link) {
|
||||
Link *carrier, *master;
|
||||
Address *address;
|
||||
Link *carrier;
|
||||
Route *route;
|
||||
Iterator i;
|
||||
|
||||
@@ -659,7 +683,17 @@ static Link *link_free(Link *link) {
|
||||
hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
|
||||
hashmap_free(link->bound_by_links);
|
||||
|
||||
hashmap_free(link->bond_slaves);
|
||||
hashmap_free(link->slaves);
|
||||
|
||||
if (link->network) {
|
||||
if (link->network->bond &&
|
||||
link_get(link->manager, link->network->bond->ifindex, &master) >= 0)
|
||||
(void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
|
||||
|
||||
if (link->network->bridge &&
|
||||
link_get(link->manager, link->network->bridge->ifindex, &master) >= 0)
|
||||
(void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
|
||||
}
|
||||
|
||||
return mfree(link);
|
||||
}
|
||||
@@ -953,23 +987,20 @@ void link_check_ready(Link *link) {
|
||||
!link->ipv4ll_route)
|
||||
return;
|
||||
|
||||
if (!link->network->bridge) {
|
||||
if (link_ipv6ll_enabled(link) &&
|
||||
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
|
||||
return;
|
||||
|
||||
if (link_ipv6ll_enabled(link) &&
|
||||
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
|
||||
return;
|
||||
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
|
||||
!link->dhcp4_configured) ||
|
||||
(link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
|
||||
!link->dhcp6_configured) ||
|
||||
(link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
|
||||
!link->dhcp4_configured && !link->dhcp6_configured))
|
||||
return;
|
||||
|
||||
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
|
||||
!link->dhcp4_configured) ||
|
||||
(link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
|
||||
!link->dhcp6_configured) ||
|
||||
(link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
|
||||
!link->dhcp4_configured && !link->dhcp6_configured))
|
||||
return;
|
||||
|
||||
if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
|
||||
return;
|
||||
}
|
||||
if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
|
||||
return;
|
||||
|
||||
if (link->state != LINK_STATE_CONFIGURED)
|
||||
link_enter_configured(link);
|
||||
@@ -1414,7 +1445,7 @@ int link_set_mtu(Link *link, uint32_t mtu) {
|
||||
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
|
||||
|
||||
/* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled)
|
||||
* for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */
|
||||
* for this interface, then disable IPv6 else enable it. */
|
||||
(void) link_enable_ipv6(link);
|
||||
|
||||
/* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
|
||||
@@ -1665,23 +1696,22 @@ static int link_set_bond(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int link_append_bond_slave(Link *link) {
|
||||
static int link_append_to_master(Link *link, NetDev *netdev) {
|
||||
Link *master;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->network->bond);
|
||||
assert(netdev);
|
||||
|
||||
r = link_get(link->manager, link->network->bond->ifindex, &master);
|
||||
r = link_get(link->manager, netdev->ifindex, &master);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_allocated(&master->bond_slaves, NULL);
|
||||
r = hashmap_ensure_allocated(&master->slaves, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_put(master->bond_slaves, INT_TO_PTR(link->ifindex), link);
|
||||
r = hashmap_put(master->slaves, INT_TO_PTR(link->ifindex), link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2478,6 +2508,10 @@ static int link_joined(Link *link) {
|
||||
r = link_set_bridge(link);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Could not set bridge message: %m");
|
||||
|
||||
r = link_append_to_master(link, link->network->bridge);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Failed to add to bridge master's slave list: %m");
|
||||
}
|
||||
|
||||
if (link->network->bond) {
|
||||
@@ -2485,7 +2519,7 @@ static int link_joined(Link *link) {
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Could not set bond message: %m");
|
||||
|
||||
r = link_append_bond_slave(link);
|
||||
r = link_append_to_master(link, link->network->bond);
|
||||
if (r < 0)
|
||||
log_link_error_errno(link, r, "Failed to add to bond master's slave list: %m");
|
||||
}
|
||||
@@ -2511,6 +2545,8 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->enslaving > 0);
|
||||
assert(!link->enslaved_raw);
|
||||
|
||||
link->enslaving--;
|
||||
|
||||
@@ -2525,8 +2561,10 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
|
||||
} else
|
||||
log_link_debug(link, "Joined netdev");
|
||||
|
||||
if (link->enslaving <= 0)
|
||||
if (link->enslaving == 0) {
|
||||
link->enslaved_raw = true;
|
||||
link_joined(link);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2543,12 +2581,8 @@ static int link_enter_join_netdev(Link *link) {
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
|
||||
link_dirty(link);
|
||||
|
||||
if (!link->network->bridge &&
|
||||
!link->network->bond &&
|
||||
!link->network->vrf &&
|
||||
hashmap_isempty(link->network->stacked_netdevs))
|
||||
return link_joined(link);
|
||||
link->enslaving = 0;
|
||||
link->enslaved_raw = false;
|
||||
|
||||
if (link->network->bond) {
|
||||
if (link->network->bond->state == NETDEV_STATE_READY &&
|
||||
@@ -2560,6 +2594,8 @@ static int link_enter_join_netdev(Link *link) {
|
||||
LOG_NETDEV_INTERFACE(link->network->bond),
|
||||
LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname));
|
||||
|
||||
link->enslaving++;
|
||||
|
||||
r = netdev_join(link->network->bond, link, netdev_join_handler);
|
||||
if (r < 0) {
|
||||
log_struct_errno(LOG_WARNING, r,
|
||||
@@ -2569,8 +2605,6 @@ static int link_enter_join_netdev(Link *link) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
link->enslaving++;
|
||||
}
|
||||
|
||||
if (link->network->bridge) {
|
||||
@@ -2579,6 +2613,8 @@ static int link_enter_join_netdev(Link *link) {
|
||||
LOG_NETDEV_INTERFACE(link->network->bridge),
|
||||
LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname));
|
||||
|
||||
link->enslaving++;
|
||||
|
||||
r = netdev_join(link->network->bridge, link, netdev_join_handler);
|
||||
if (r < 0) {
|
||||
log_struct_errno(LOG_WARNING, r,
|
||||
@@ -2588,8 +2624,6 @@ static int link_enter_join_netdev(Link *link) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
link->enslaving++;
|
||||
}
|
||||
|
||||
if (link->network->vrf) {
|
||||
@@ -2598,6 +2632,8 @@ static int link_enter_join_netdev(Link *link) {
|
||||
LOG_NETDEV_INTERFACE(link->network->vrf),
|
||||
LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname));
|
||||
|
||||
link->enslaving++;
|
||||
|
||||
r = netdev_join(link->network->vrf, link, netdev_join_handler);
|
||||
if (r < 0) {
|
||||
log_struct_errno(LOG_WARNING, r,
|
||||
@@ -2607,8 +2643,6 @@ static int link_enter_join_netdev(Link *link) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
link->enslaving++;
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
|
||||
@@ -2623,6 +2657,8 @@ static int link_enter_join_netdev(Link *link) {
|
||||
LOG_NETDEV_INTERFACE(netdev),
|
||||
LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname));
|
||||
|
||||
link->enslaving++;
|
||||
|
||||
r = netdev_join(netdev, link, netdev_join_handler);
|
||||
if (r < 0) {
|
||||
log_struct_errno(LOG_WARNING, r,
|
||||
@@ -2632,10 +2668,11 @@ static int link_enter_join_netdev(Link *link) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
link->enslaving++;
|
||||
}
|
||||
|
||||
if (link->enslaving == 0)
|
||||
return link_joined(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ typedef struct Link {
|
||||
unsigned routing_policy_rule_messages;
|
||||
unsigned routing_policy_rule_remove_messages;
|
||||
unsigned enslaving;
|
||||
/* link_is_enslaved() has additional checks. So, it is named _raw. */
|
||||
bool enslaved_raw;
|
||||
|
||||
Set *addresses;
|
||||
Set *addresses_foreign;
|
||||
@@ -129,7 +131,7 @@ typedef struct Link {
|
||||
|
||||
Hashmap *bound_by_links;
|
||||
Hashmap *bound_to_links;
|
||||
Hashmap *bond_slaves;
|
||||
Hashmap *slaves;
|
||||
} Link;
|
||||
|
||||
typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
|
||||
|
||||
@@ -1427,9 +1427,6 @@ void manager_free(Manager *m) {
|
||||
sd_netlink_unref(m->genl);
|
||||
sd_resolve_unref(m->resolve);
|
||||
|
||||
while ((network = m->networks))
|
||||
network_free(network);
|
||||
|
||||
while ((link = hashmap_first(m->dhcp6_prefixes)))
|
||||
manager_dhcp6_prefix_remove_all(m, link);
|
||||
hashmap_free(m->dhcp6_prefixes);
|
||||
@@ -1445,6 +1442,9 @@ void manager_free(Manager *m) {
|
||||
m->links_requesting_uuid = set_free(m->links_requesting_uuid);
|
||||
set_free(m->duids_requesting_uuid);
|
||||
|
||||
while ((network = m->networks))
|
||||
network_free(network);
|
||||
|
||||
hashmap_free(m->networks_by_name);
|
||||
|
||||
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
|
||||
|
||||
@@ -141,7 +141,10 @@ static int network_verify(Network *network) {
|
||||
}
|
||||
|
||||
if (network->link_local < 0)
|
||||
network->link_local = ADDRESS_FAMILY_IPV6;
|
||||
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
|
||||
|
||||
if (network->ipv6_accept_ra < 0 && network->bridge)
|
||||
network->ipv6_accept_ra = false;
|
||||
|
||||
/* IPMasquerade=yes implies IPForward=yes */
|
||||
if (network->ip_masquerade)
|
||||
|
||||
@@ -4,4 +4,9 @@ Name=bridge99
|
||||
[Network]
|
||||
Address=192.168.0.15/24
|
||||
Gateway=192.168.0.1
|
||||
IPv6AcceptRA=no
|
||||
IgnoreCarrierLoss=true
|
||||
|
||||
[RoutingPolicyRule]
|
||||
To=8.8.8.8
|
||||
Table=100
|
||||
|
||||
@@ -4,3 +4,4 @@ Name=bridge99
|
||||
[Network]
|
||||
Address=192.168.0.15/24
|
||||
Gateway=192.168.0.1
|
||||
IPv6AcceptRA=no
|
||||
|
||||
@@ -1198,8 +1198,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
|
||||
|
||||
output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertRegex(output, '192.168.0.15')
|
||||
self.assertRegex(output, '192.168.0.1')
|
||||
self.assertRegex(output, '192.168.0.15/24')
|
||||
|
||||
output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
@@ -1212,13 +1211,37 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
|
||||
if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
|
||||
self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: enslaved \(configured\)')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: enslaved \(configured\)')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: routable \(configured\)')
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
|
||||
time.sleep(1)
|
||||
|
||||
output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertRegex(output, '192.168.0.16/24')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: routable \(configured\)')
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
|
||||
time.sleep(3)
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: degraded \(configured\)')
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
|
||||
time.sleep(3)
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: no-carrier \(configured\)')
|
||||
|
||||
output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertRegex(output, 'NO-CARRIER')
|
||||
@@ -1248,6 +1271,48 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
|
||||
self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
|
||||
self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
|
||||
|
||||
subprocess.call(['ip', 'rule', 'del', 'table', '100'])
|
||||
|
||||
def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
|
||||
self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
|
||||
'bridge99-ignore-carrier-loss.network')
|
||||
self.start_networkd()
|
||||
|
||||
self.assertTrue(self.link_exits('bridge99'))
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
|
||||
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
|
||||
self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: routable \(configured\)')
|
||||
|
||||
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
|
||||
self.assertRegex(output, 'State: enslaved \(configured\)')
|
||||
|
||||
output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
|
||||
print(output)
|
||||
self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
|
||||
|
||||
subprocess.call(['ip', 'rule', 'del', 'table', '100'])
|
||||
|
||||
class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
|
||||
links = ['veth99']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user