+ link_unref(link);
+ return 1;
+ }
+
+ log_debug_link(link, "enslaved");
+
+ if (link->enslaving == 0)
+ link_enslaved(link);
+
+ link_unref(link);
+
+ return 1;
+}
+
+static int link_enter_enslave(Link *link) {
+ NetDev *vlan, *macvlan, *vxlan;
+ Iterator i;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(link->state == LINK_STATE_INITIALIZING);
+
+ link->state = LINK_STATE_ENSLAVING;
+
+ link_save(link);
+
+ if (!link->network->bridge &&
+ !link->network->bond &&
+ !link->network->tunnel &&
+ hashmap_isempty(link->network->vlans) &&
+ hashmap_isempty(link->network->macvlans) &&
+ hashmap_isempty(link->network->vxlans))
+ return link_enslaved(link);
+
+ if (link->network->bond) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%-*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, link->network->bond->ifname,
+ NETDEV(link->network->bond),
+ NULL);
+
+ r = netdev_enslave(link->network->bond, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%-*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, link->network->bond->ifname, strerror(-r),
+ NETDEV(link->network->bond),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;
+ }
+
+ if (link->network->bridge) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%-*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, link->network->bridge->ifname,
+ NETDEV(link->network->bridge),
+ NULL);
+
+ r = netdev_enslave(link->network->bridge, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%-*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, link->network->bridge->ifname, strerror(-r),
+ NETDEV(link->network->bridge),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;
+ }
+
+ if (link->network->tunnel) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%-*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, link->network->tunnel->ifname,
+ NETDEV(link->network->tunnel),
+ NULL);
+
+ r = netdev_enslave(link->network->tunnel, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%-*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, link->network->tunnel->ifname, strerror(-r),
+ NETDEV(link->network->tunnel),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;
+ }
+
+ HASHMAP_FOREACH(vlan, link->network->vlans, i) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%-*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, vlan->ifname, NETDEV(vlan), NULL);
+
+ r = netdev_enslave(vlan, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%-*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, vlan->ifname, strerror(-r),
+ NETDEV(vlan), NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;
+ }
+
+ HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%-*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, macvlan->ifname, NETDEV(macvlan), NULL);
+
+ r = netdev_enslave(macvlan, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%-*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, macvlan->ifname, strerror(-r),
+ NETDEV(macvlan), NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;
+ }
+
+ HASHMAP_FOREACH(vxlan, link->network->vxlans, i) {
+ log_struct_link(LOG_DEBUG, link,
+ "MESSAGE=%*s: enslaving by '%s'",
+ IFNAMSIZ,
+ link->ifname, vxlan->ifname, NETDEV(vxlan), NULL);
+
+ r = netdev_enslave(vxlan, link, &enslave_handler);
+ if (r < 0) {
+ log_struct_link(LOG_WARNING, link,
+ "MESSAGE=%*s: could not enslave by '%s': %s",
+ IFNAMSIZ,
+ link->ifname, vxlan->ifname, strerror(-r),
+ NETDEV(vxlan), NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link_ref(link);
+ link->enslaving ++;