It will be used to support L2TP tunnel in later commits.
return 0;
}
+static int netdev_create_after_configured(NetDev *netdev, Link *link) {
+ assert(netdev);
+ assert(link);
+ assert(NETDEV_VTABLE(netdev)->create_after_configured);
+
+ return NETDEV_VTABLE(netdev)->create_after_configured(netdev, link);
+}
+
/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) {
int r;
return r;
break;
+ case NETDEV_CREATE_AFTER_CONFIGURED:
+ r = netdev_create_after_configured(netdev, link);
+ if (r < 0)
+ return r;
+ break;
default:
assert_not_reached("Can not join independent netdev");
}
NETDEV_CREATE_INDEPENDENT,
NETDEV_CREATE_MASTER,
NETDEV_CREATE_STACKED,
+ NETDEV_CREATE_AFTER_CONFIGURED,
_NETDEV_CREATE_MAX,
_NETDEV_CREATE_INVALID = -1,
} NetDevCreateType;
/* create netdev, if not done via rtnl */
int (*create)(NetDev *netdev);
+ /* create netdev after link is fully configured */
+ int (*create_after_configured)(NetDev *netdev, Link *link);
+
/* perform additional configuration after netdev has been createad */
int (*post_create)(NetDev *netdev, Link *link, sd_netlink_message *message);
int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink);
int netdev_get_mac(const char *ifname, struct ether_addr **ret);
int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb);
+int netdev_join_after_configured(NetDev *netdev, Link *link, link_netlink_message_handler_t callback);
const char *netdev_kind_to_string(NetDevKind d) _const_;
NetDevKind netdev_kind_from_string(const char *d) _pure_;
return NULL;
}
+static int link_join_netdevs_after_configured(Link *link) {
+ NetDev *netdev;
+ Iterator i;
+ int r;
+
+ HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
+ if (netdev->ifindex > 0)
+ /* Assume already enslaved. */
+ continue;
+
+ if (netdev_get_create_type(netdev) != NETDEV_CREATE_AFTER_CONFIGURED)
+ continue;
+
+ log_struct(LOG_DEBUG,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(netdev),
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname));
+
+ r = netdev_join(netdev, link, NULL);
+ if (r < 0)
+ return log_struct_errno(LOG_WARNING, r,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(netdev),
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname));
+ }
+
+ return 0;
+}
+
static void link_enter_configured(Link *link) {
assert(link);
assert(link->network);
link_set_state(link, LINK_STATE_CONFIGURED);
+ (void) link_join_netdevs_after_configured(link);
+
link_dirty(link);
}
/* Assume already enslaved. */
continue;
+ if (netdev_get_create_type(netdev) != NETDEV_CREATE_STACKED)
+ continue;
+
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
LOG_NETDEV_INTERFACE(netdev),