#include "list.h"
#include "siphash24.h"
-#define VLANID_MAX 4094
-
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_BRIDGE] = "bridge",
[NETDEV_KIND_BOND] = "bond",
[NETDEV_KIND_GRE] = "gre",
[NETDEV_KIND_SIT] = "sit",
[NETDEV_KIND_VETH] = "veth",
- [NETDEV_KIND_VTI] = "vti"
+ [NETDEV_KIND_VTI] = "vti",
+ [NETDEV_KIND_DUMMY] = "dummy",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
-static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
- [NETDEV_MACVLAN_MODE_PRIVATE] = "private",
- [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
- [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
- [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
-
static void netdev_cancel_callbacks(NetDev *netdev) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
netdev_enslave_callback *callback;
return r;
}
+ link_ref(link);
+
log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
return 0;
return 0;
}
+
+/* callback for netdev's created without a backing Link */
static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
- NetDev *netdev = userdata;
+ _cleanup_netdev_unref_ NetDev *netdev = userdata;
int r;
assert(netdev->state != _NETDEV_STATE_INVALID);
return 0;
}
-static int netdev_create(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
+static int netdev_create(NetDev *netdev) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
const char *kind;
int r;
assert(netdev);
- assert(!(netdev->kind == NETDEV_KIND_VLAN || netdev->kind == NETDEV_KIND_MACVLAN) ||
- (link && callback));
assert(netdev->ifname);
assert(netdev->manager);
assert(netdev->manager->rtnl);
return r;
}
- if (link) {
- r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
- if (r < 0) {
- log_error_netdev(netdev,
- "Could not append IFLA_LINK attribute: %s",
- strerror(-r));
- return r;
- }
- }
-
r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
if (r < 0) {
log_error_netdev(netdev,
return r;
}
- if (netdev->vlanid <= VLANID_MAX) {
- r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
- if (r < 0) {
- log_error_netdev(netdev,
- "Could not append IFLA_VLAN_ID attribute: %s",
- strerror(-r));
- return r;
- }
- }
-
- if (netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
- r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, netdev->macvlan_mode);
- if (r < 0) {
- log_error_netdev(netdev,
- "Could not append IFLA_MACVLAN_MODE attribute: %s",
- strerror(-r));
- return r;
- }
- }
-
r = sd_rtnl_message_close_container(req);
if (r < 0) {
log_error_netdev(netdev,
return r;
}
- if (link)
- r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
- else
- r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
+ r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
if (r < 0) {
log_error_netdev(netdev,
"Could not send rtnetlink message: %s", strerror(-r));
return r;
}
+ netdev_ref(netdev);
+
log_debug_netdev(netdev, "creating netdev");
netdev->state = NETDEV_STATE_CREATING;
return 0;
}
+/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
int r;
switch(netdev->kind) {
case NETDEV_KIND_VLAN:
+ return netdev_create_vlan(netdev, link, callback);
case NETDEV_KIND_MACVLAN:
- return netdev_create(netdev, link, callback);
+ return netdev_create_macvlan(netdev, link, callback);
case NETDEV_KIND_VXLAN:
return netdev_create_vxlan(netdev, link, callback);
case NETDEV_KIND_IPIP:
case NETDEV_KIND_GRE:
case NETDEV_KIND_SIT:
case NETDEV_KIND_VTI:
- return netdev_create_tunnel(link, netdev_create_handler);
+ return netdev_create_tunnel(netdev, link, callback);
default:
break;
}
cb->callback = callback;
cb->link = link;
+ link_ref(link);
LIST_PREPEND(callbacks, netdev->callbacks, cb);
}
LIST_HEAD_INIT(netdev->callbacks);
- if(netdev->kind == NETDEV_KIND_VETH) {
- if (netdev->ifname_peer) {
- log_warning("Veth NetDev without Peer Name configured "
+ switch (netdev->kind) {
+ case NETDEV_KIND_VETH:
+ if (!netdev->ifname_peer) {
+ log_warning("Veth NetDev without peer name configured "
"in %s. Ignoring", filename);
return 0;
}
}
}
- return netdev_create_veth(netdev, netdev_create_handler);
- }
+ r = netdev_create_veth(netdev, netdev_create_handler);
+ if (r < 0)
+ return r;
- if (netdev->kind != NETDEV_KIND_VLAN &&
- netdev->kind != NETDEV_KIND_MACVLAN &&
- netdev->kind != NETDEV_KIND_VXLAN &&
- netdev->kind != NETDEV_KIND_IPIP &&
- netdev->kind != NETDEV_KIND_GRE &&
- netdev->kind != NETDEV_KIND_SIT &&
- netdev->kind != NETDEV_KIND_VTI) {
- r = netdev_create(netdev, NULL, NULL);
+ break;
+ case NETDEV_KIND_DUMMY:
+ r = netdev_create_dummy(netdev, netdev_create_handler);
if (r < 0)
return r;
+
+ break;
+ case NETDEV_KIND_BRIDGE:
+ case NETDEV_KIND_BOND:
+ r = netdev_create(netdev);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ break;
}
log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));