if (!link->network)
return false;
+ if (link->network->bond)
+ return false;
+
return link->network->dhcp & ADDRESS_FAMILY_IPV6;
}
if (!link->network)
return false;
+ if (link->network->bond)
+ return false;
+
return link->network->dhcp & ADDRESS_FAMILY_IPV4;
}
if (!link->network)
return false;
+ if (link->network->bond)
+ return false;
+
return link->network->dhcp_server;
}
if (!link->network)
return false;
- if (streq_ptr(link->kind, "wireguard"))
+ if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+ return false;
+
+ if (link->network->bond)
return false;
return link->network->link_local & ADDRESS_FAMILY_IPV4;
if (!link->network)
return false;
- if (streq_ptr(link->kind, "wireguard"))
+ if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+ return false;
+
+ if (link->network->bond)
return false;
return link->network->link_local & ADDRESS_FAMILY_IPV6;
if (!socket_ipv6_is_supported())
return false;
- if (link->network->bridge)
+ if (link->network->bridge || link->network->bond)
return false;
/* DHCPv6 client will not be started if no IPv6 link-local address is configured. */
return 0;
}
-void link_update_operstate(Link *link) {
+void link_update_operstate(Link *link, bool also_update_bond_master) {
LinkOperationalState operstate;
+
assert(link);
if (link->kernel_operstate == IF_OPER_DORMANT)
else
operstate = LINK_OPERSTATE_OFF;
+ if (IN_SET(operstate, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_CARRIER) &&
+ link->flags & IFF_SLAVE)
+ operstate = LINK_OPERSTATE_ENSLAVED;
+
+ if (IN_SET(operstate, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_ENSLAVED, LINK_OPERSTATE_ROUTABLE) &&
+ !hashmap_isempty(link->bond_slaves)) {
+ Iterator i;
+ Link *slave;
+
+ HASHMAP_FOREACH(slave, link->bond_slaves, i) {
+ link_update_operstate(slave, false);
+
+ if (IN_SET(slave->operstate,
+ LINK_OPERSTATE_OFF, LINK_OPERSTATE_NO_CARRIER, LINK_OPERSTATE_DORMANT))
+ operstate = LINK_OPERSTATE_DEGRADED;
+ }
+ }
+
if (link->operstate != operstate) {
link->operstate = operstate;
link_send_changed(link, "OperationalState", NULL);
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);
+ }
}
#define FLAG_STRING(string, flag, old, new) \
link->flags = flags;
link->kernel_operstate = operstate;
- link_update_operstate(link);
+ link_update_operstate(link, true);
return 0;
}
hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
hashmap_free(link->bound_by_links);
+ hashmap_free(link->bond_slaves);
+
return mfree(link);
}
if (!link->network->bridge) {
- if (link_ipv6ll_enabled(link))
- if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0)
- 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) ||
return r;
}
-static int link_bond_set(Link *link) {
+static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(m);
+ assert(link);
+ assert(link->ifname);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return 1;
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set bonding interface: %m");
+ return 1;
+ }
+
+ return 1;
+}
+
+static int link_set_bond(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
- r = netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler,
+ r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return r;
}
+static int link_append_bond_slave(Link *link) {
+ Link *master;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->network->bond);
+
+ r = link_get(link->manager, link->network->bond->ifindex, &master);
+ if (r < 0)
+ return r;
+
+ r = hashmap_ensure_allocated(&master->bond_slaves, NULL);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(master->bond_slaves, INT_TO_PTR(link->ifindex), link);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
static int link_lldp_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
if (r < 0)
return r;
- if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) == 0) {
+ if (!in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) {
r = link_acquire_ipv6_conf(link);
if (r < 0)
return r;
}
if (link->network->bond) {
- r = link_bond_set(link);
+ r = link_set_bond(link);
if (r < 0)
log_link_error_errno(link, r, "Could not set bond message: %m");
+
+ r = link_append_bond_slave(link);
+ if (r < 0)
+ log_link_error_errno(link, r, "Failed to add to bond master's slave list: %m");
}
if (link->network->use_br_vlan &&
assert(link);
+ if (link->network && link->network->ignore_carrier_loss)
+ return 0;
+
/* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop.
* setting_mtu keep track whether the device got reset because of setting MTU and does not drop the
* configuration and stop the clients as well. */
[LINK_OPERSTATE_DORMANT] = "dormant",
[LINK_OPERSTATE_CARRIER] = "carrier",
[LINK_OPERSTATE_DEGRADED] = "degraded",
+ [LINK_OPERSTATE_ENSLAVED] = "enslaved",
[LINK_OPERSTATE_ROUTABLE] = "routable",
};