summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorSusant Sahani <ssahani@users.noreply.github.com>2016-12-21 23:40:36 +0530
committerLennart Poettering <lennart@poettering.net>2016-12-21 19:10:36 +0100
commiteb64b435ebb2a7cb1274d5f8d8c323905caf29bc (patch)
tree8fddf35b41f491579fba5f83d246f1f473e39911 /src/network
parent7dd6974c46859a62c0a606824bf145c2c95241a0 (diff)
networkd: bond support primary slave and active slave (#4873)
active_slave: Specifies the new active slave for modes that support it (active-backup, balance-alb and balance-tlb). primary slave: systemd-networks currently lacks the capability to set the primary slave in an active-backup bonding. This is necessary if you prefer one interface over the other. A common example is a eth0-wlan0 bonding on a laptop where you'd want to switch to the wired connection whenever it's available. Fixes: #2837
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-link.c58
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.h2
3 files changed, 62 insertions, 0 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 8d6992cee8..b993d27c2f 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1338,6 +1338,58 @@ static int link_set_bridge(Link *link) {
return r;
}
+static int link_bond_set(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(link);
+ assert(link->network);
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+ r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+ r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ if (link->network->active_slave) {
+ r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
+ }
+
+ if (link->network->primary_slave) {
+ r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
+ }
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return r;
+}
+
static int link_lldp_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -1992,6 +2044,12 @@ static int link_joined(Link *link) {
log_link_error_errno(link, r, "Could not set bridge message: %m");
}
+ if (link->network->bond) {
+ r = link_bond_set(link);
+ if (r < 0)
+ log_link_error_errno(link, r, "Could not set bond message: %m");
+ }
+
if (link->network->use_br_vlan &&
(link->network->bridge || streq_ptr("bridge", link->kind))) {
r = link_set_bridge_vlan(link);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index c9b9044a14..4fa17e8452 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -60,6 +60,8 @@ Network.IPForward, config_parse_address_family_boolean_with
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
+Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
+Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
/* legacy alias for the above */
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index d13e306add..4cf784f67c 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -167,6 +167,8 @@ struct Network {
int proxy_arp;
bool ipv6_accept_ra_use_dns;
+ bool active_slave;
+ bool primary_slave;
DHCPUseDomains ipv6_accept_ra_use_domains;
uint32_t ipv6_accept_ra_route_table;