mirror of
https://github.com/systemd/systemd.git
synced 2025-03-13 00:58:27 +03:00
networkd: add basic VLAN support
This commit is contained in:
parent
168a3f602f
commit
54abf461d6
@ -105,11 +105,24 @@
|
||||
<varlistentry>
|
||||
<term><varname>Kind</varname></term>
|
||||
<listitem>
|
||||
<para>The netdev kind. Currently, 'bridge' and 'bond' are
|
||||
supported. This option is compulsory.</para>
|
||||
<para>The netdev kind. Currently, 'bridge', 'bond' and 'vlan'
|
||||
are supported. This option is compulsory.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>The <literal>[VLAN]</literal> section only applies for netdevs of kind 'vlan',
|
||||
and accepts the following keys:</para>
|
||||
|
||||
<variablelist class='network-directives'>
|
||||
<varlistentry>
|
||||
<term><varname>Id</varname></term>
|
||||
<listitem>
|
||||
<para>The VLAN ID to use. This option is compulsory.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</refsect2>
|
||||
|
||||
<refsect2><title>Networks</title>
|
||||
|
@ -23,6 +23,7 @@ Match.Name, config_parse_ifname, 0, offsetof(Networ
|
||||
Network.Description, config_parse_string, 0, offsetof(Network, description)
|
||||
Network.Bridge, config_parse_bridge, 0, offsetof(Network, bridge)
|
||||
Network.Bond, config_parse_bond, 0, offsetof(Network, bond)
|
||||
Network.VLAN, config_parse_vlan, 0, offsetof(Network, vlan)
|
||||
Network.DHCP, config_parse_bool, 0, offsetof(Network, dhcp)
|
||||
Network.Address, config_parse_address, 0, 0
|
||||
Network.Gateway, config_parse_gateway, 0, 0
|
||||
@ -38,3 +39,4 @@ DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Networ
|
||||
Netdev.Description, config_parse_string, 0, offsetof(Netdev, description)
|
||||
Netdev.Name, config_parse_ifname, 0, offsetof(Netdev, name)
|
||||
Netdev.Kind, config_parse_netdev_kind, 0, offsetof(Netdev, kind)
|
||||
VLAN.Id, config_parse_int, 0, offsetof(Netdev, vlanid)
|
||||
|
@ -786,7 +786,7 @@ static int link_enter_enslave(Link *link) {
|
||||
|
||||
link->state = LINK_STATE_ENSLAVING;
|
||||
|
||||
if (!link->network->bridge && !link->network->bond)
|
||||
if (!link->network->bridge && !link->network->bond && !link->network->vlan)
|
||||
return link_enslaved(link);
|
||||
|
||||
if (link->network->bridge) {
|
||||
@ -810,19 +810,19 @@ static int link_enter_enslave(Link *link) {
|
||||
link->enslaving ++;
|
||||
}
|
||||
|
||||
if (link->network->bond) {
|
||||
if (link->network->vlan) {
|
||||
log_struct_link(LOG_DEBUG, link,
|
||||
"MESSAGE=%s: enslaving by '%s'",
|
||||
link->network->bond->name,
|
||||
NETDEV(link->network->bond),
|
||||
link->network->vlan->name,
|
||||
NETDEV(link->network->vlan),
|
||||
NULL);
|
||||
|
||||
r = netdev_enslave(link->network->bond, link, &enslave_handler);
|
||||
r = netdev_enslave(link->network->vlan, link, &enslave_handler);
|
||||
if (r < 0) {
|
||||
log_struct_link(LOG_WARNING, link,
|
||||
"MESSAGE=%s: could not enslave by '%s': %s",
|
||||
link->network->bond->name, strerror(-r),
|
||||
NETDEV(link->network->bond),
|
||||
link->network->vlan->name, strerror(-r),
|
||||
NETDEV(link->network->vlan),
|
||||
NULL);
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
|
@ -28,7 +28,8 @@
|
||||
|
||||
static const char* const netdev_kind_table[] = {
|
||||
[NETDEV_KIND_BRIDGE] = "bridge",
|
||||
[NETDEV_KIND_BOND] = "bond"
|
||||
[NETDEV_KIND_BOND] = "bond",
|
||||
[NETDEV_KIND_VLAN] = "vlan",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetdevKind);
|
||||
@ -154,13 +155,13 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int netdev_create(Netdev *netdev) {
|
||||
static int netdev_create(Netdev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
|
||||
_cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
|
||||
const char *kind;
|
||||
int r;
|
||||
|
||||
assert(netdev);
|
||||
assert(netdev->state == _NETDEV_STATE_INVALID);
|
||||
assert(!(netdev->kind == NETDEV_KIND_VLAN) || (link && callback && netdev->vlanid >= 0));
|
||||
assert(netdev->name);
|
||||
assert(netdev->manager);
|
||||
assert(netdev->manager->rtnl);
|
||||
@ -173,6 +174,16 @@ static int netdev_create(Netdev *netdev) {
|
||||
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->name);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
@ -203,6 +214,32 @@ static int netdev_create(Netdev *netdev) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (netdev->vlanid >= 0) {
|
||||
r = sd_rtnl_message_open_container(req, IFLA_INFO_DATA);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
"Could not open IFLA_INFO_DATA container: %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
"Could not close IFLA_INFO_DATA container %s",
|
||||
strerror(-r));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_close_container(req);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
@ -211,7 +248,10 @@ static int netdev_create(Netdev *netdev) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
|
||||
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);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
"Could not send rtnetlink message: %s", strerror(-r));
|
||||
@ -226,6 +266,9 @@ static int netdev_create(Netdev *netdev) {
|
||||
}
|
||||
|
||||
int netdev_enslave(Netdev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
|
||||
if (netdev->kind == NETDEV_KIND_VLAN)
|
||||
return netdev_create(netdev, link, callback);
|
||||
|
||||
if (netdev->state == NETDEV_STATE_READY) {
|
||||
netdev_enslave_ready(netdev, link, callback);
|
||||
} else {
|
||||
@ -289,8 +332,9 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
netdev->manager = manager;
|
||||
netdev->state = _NETDEV_STATE_INVALID;
|
||||
netdev->kind = _NETDEV_KIND_INVALID;
|
||||
netdev->vlanid = -1;
|
||||
|
||||
r = config_parse(NULL, filename, file, "Netdev\0", config_item_perf_lookup,
|
||||
r = config_parse(NULL, filename, file, "Netdev\0VLAN\0", config_item_perf_lookup,
|
||||
(void*) network_gperf_lookup, false, false, netdev);
|
||||
if (r < 0) {
|
||||
log_warning("Could not parse config file %s: %s", filename, strerror(-r));
|
||||
@ -307,6 +351,11 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (netdev->kind == NETDEV_KIND_VLAN && netdev->vlanid < 0) {
|
||||
log_warning("VLAN without Id configured in %s. Ignoring", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
netdev->filename = strdup(filename);
|
||||
if (!netdev->filename)
|
||||
return log_oom();
|
||||
@ -317,9 +366,11 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
|
||||
LIST_HEAD_INIT(netdev->callbacks);
|
||||
|
||||
r = netdev_create(netdev);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (netdev->kind != NETDEV_KIND_VLAN) {
|
||||
r = netdev_create(netdev, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
netdev = NULL;
|
||||
|
||||
|
@ -285,3 +285,40 @@ int config_parse_bond(const char *unit,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_vlan(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
Network *network = userdata;
|
||||
Netdev *netdev;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
r = netdev_get(network->manager, rvalue, &netdev);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"VLAN is invalid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (netdev->kind != NETDEV_KIND_VLAN) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"Netdev is not a VLAN, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
network->vlan = netdev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ struct netdev_enslave_callback {
|
||||
typedef enum NetdevKind {
|
||||
NETDEV_KIND_BRIDGE,
|
||||
NETDEV_KIND_BOND,
|
||||
NETDEV_KIND_VLAN,
|
||||
_NETDEV_KIND_MAX,
|
||||
_NETDEV_KIND_INVALID = -1
|
||||
} NetdevKind;
|
||||
@ -74,6 +75,8 @@ struct Netdev {
|
||||
char *name;
|
||||
NetdevKind kind;
|
||||
|
||||
int vlanid;
|
||||
|
||||
Link *link;
|
||||
NetdevState state;
|
||||
|
||||
@ -94,6 +97,7 @@ struct Network {
|
||||
char *description;
|
||||
Netdev *bridge;
|
||||
Netdev *bond;
|
||||
Netdev *vlan;
|
||||
bool dhcp;
|
||||
bool dhcp_dns;
|
||||
bool dhcp_mtu;
|
||||
@ -258,6 +262,10 @@ int config_parse_bond(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
int config_parse_vlan(const char *unit, const char *filename, unsigned line,
|
||||
const char *section, unsigned section_line, const char *lvalue,
|
||||
int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
/* gperf */
|
||||
|
||||
const struct ConfigPerfItem* network_gperf_lookup(const char *key, unsigned length);
|
||||
|
Loading…
x
Reference in New Issue
Block a user