networkd: VLAN - allow multiple vlans to be created on a link
Also limit the range of vlan ids. Other implementations and documentation use the ranges {0,1}-{4094,4095}, but we use the one accepted by the kernel: 0-4094. Reported-by: Oleksii Shevchuk <alxchk@gmail.com>
This commit is contained in:
parent
3831838ae7
commit
672682a6b9
|
@ -118,7 +118,8 @@
|
|||
<varlistentry>
|
||||
<term><varname>Id</varname></term>
|
||||
<listitem>
|
||||
<para>The VLAN ID to use. This option is compulsory.</para>
|
||||
<para>The VLAN ID to use. An integer in the range 0-4094.
|
||||
This option is compulsory.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -223,13 +224,20 @@
|
|||
<varlistentry>
|
||||
<term><varname>Bridge</varname></term>
|
||||
<listitem>
|
||||
<para>The name of the bridge to add the configured link to.</para>
|
||||
<para>The name of the bridge to add the link to.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Bond</varname></term>
|
||||
<listitem>
|
||||
<para>The name of the bond to add the configured link to.</para>
|
||||
<para>The name of the bond to add the link to.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>VLAN</varname></term>
|
||||
<listitem>
|
||||
<para>The name of a VLAN to create on the link. This option
|
||||
may be specified more than once.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
@ -23,7 +23,7 @@ Match.Name, config_parse_ifname, 0, offsetof(Netw
|
|||
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.VLAN, config_parse_vlan, 0, offsetof(Network, vlans)
|
||||
Network.DHCP, config_parse_bool, 0, offsetof(Network, dhcp)
|
||||
Network.Address, config_parse_address, 0, 0
|
||||
Network.Gateway, config_parse_gateway, 0, 0
|
||||
|
@ -41,4 +41,4 @@ DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Netw
|
|||
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)
|
||||
VLAN.Id, config_parse_uint64, 0, offsetof(NetDev, vlanid)
|
||||
|
|
|
@ -866,6 +866,8 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
|
|||
}
|
||||
|
||||
static int link_enter_enslave(Link *link) {
|
||||
NetDev *vlan;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
@ -874,7 +876,7 @@ static int link_enter_enslave(Link *link) {
|
|||
|
||||
link->state = LINK_STATE_ENSLAVING;
|
||||
|
||||
if (!link->network->bridge && !link->network->bond && !link->network->vlan)
|
||||
if (!link->network->bridge && !link->network->bond && !link->network->vlans)
|
||||
return link_enslaved(link);
|
||||
|
||||
if (link->network->bridge) {
|
||||
|
@ -898,20 +900,17 @@ static int link_enter_enslave(Link *link) {
|
|||
link->enslaving ++;
|
||||
}
|
||||
|
||||
if (link->network->vlan) {
|
||||
HASHMAP_FOREACH(vlan, link->network->vlans, i) {
|
||||
log_struct_link(LOG_DEBUG, link,
|
||||
"MESSAGE=%s: enslaving by '%s'",
|
||||
link->ifname, link->network->vlan->name,
|
||||
NETDEV(link->network->vlan),
|
||||
NULL);
|
||||
link->ifname, vlan->name, NETDEV(vlan), NULL);
|
||||
|
||||
r = netdev_enslave(link->network->vlan, link, &enslave_handler);
|
||||
r = netdev_enslave(vlan, link, &enslave_handler);
|
||||
if (r < 0) {
|
||||
log_struct_link(LOG_WARNING, link,
|
||||
"MESSAGE=%s: could not enslave by '%s': %s",
|
||||
link->ifname, link->network->vlan->name,
|
||||
strerror(-r), NETDEV(link->network->vlan),
|
||||
NULL);
|
||||
link->ifname, vlan->name, strerror(-r),
|
||||
NETDEV(vlan), NULL);
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "conf-parser.h"
|
||||
#include "list.h"
|
||||
|
||||
#define VLANID_MAX 4094
|
||||
|
||||
static const char* const netdev_kind_table[] = {
|
||||
[NETDEV_KIND_BRIDGE] = "bridge",
|
||||
[NETDEV_KIND_BOND] = "bond",
|
||||
|
@ -161,7 +163,7 @@ static int netdev_create(NetDev *netdev, Link *link, sd_rtnl_message_handler_t c
|
|||
int r;
|
||||
|
||||
assert(netdev);
|
||||
assert(!(netdev->kind == NETDEV_KIND_VLAN) || (link && callback && netdev->vlanid >= 0));
|
||||
assert(!(netdev->kind == NETDEV_KIND_VLAN) || (link && callback && netdev->vlanid <= VLANID_MAX));
|
||||
assert(netdev->name);
|
||||
assert(netdev->manager);
|
||||
assert(netdev->manager->rtnl);
|
||||
|
@ -214,7 +216,7 @@ static int netdev_create(NetDev *netdev, Link *link, sd_rtnl_message_handler_t c
|
|||
return r;
|
||||
}
|
||||
|
||||
if (netdev->vlanid >= 0) {
|
||||
if (netdev->vlanid <= VLANID_MAX) {
|
||||
r = sd_rtnl_message_open_container(req, IFLA_INFO_DATA);
|
||||
if (r < 0) {
|
||||
log_error_netdev(netdev,
|
||||
|
@ -329,7 +331,7 @@ 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;
|
||||
netdev->vlanid = VLANID_MAX + 1;
|
||||
|
||||
r = config_parse(NULL, filename, file, "NetDev\0VLAN\0", config_item_perf_lookup,
|
||||
(void*) network_gperf_lookup, false, false, netdev);
|
||||
|
@ -348,8 +350,8 @@ 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);
|
||||
if (netdev->kind == NETDEV_KIND_VLAN && netdev->vlanid > VLANID_MAX) {
|
||||
log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ static int network_load_one(Manager *manager, const char *filename) {
|
|||
LIST_HEAD_INIT(network->static_addresses);
|
||||
LIST_HEAD_INIT(network->static_routes);
|
||||
|
||||
network->vlans = hashmap_new(uint64_hash_func, uint64_compare_func);
|
||||
if (!network->vlans)
|
||||
return log_oom();
|
||||
|
||||
network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
|
||||
if (!network->addresses_by_section)
|
||||
return log_oom();
|
||||
|
@ -144,6 +148,8 @@ void network_free(Network *network) {
|
|||
|
||||
address_free(network->dns);
|
||||
|
||||
hashmap_free(network->vlans);
|
||||
|
||||
while ((route = network->static_routes))
|
||||
route_free(route);
|
||||
|
||||
|
@ -312,7 +318,12 @@ int config_parse_vlan(const char *unit,
|
|||
return 0;
|
||||
}
|
||||
|
||||
network->vlan = netdev;
|
||||
r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"Can not add VLAN to network: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ struct NetDev {
|
|||
char *name;
|
||||
NetDevKind kind;
|
||||
|
||||
int vlanid;
|
||||
uint64_t vlanid;
|
||||
|
||||
int ifindex;
|
||||
NetDevState state;
|
||||
|
@ -97,7 +97,7 @@ struct Network {
|
|||
char *description;
|
||||
NetDev *bridge;
|
||||
NetDev *bond;
|
||||
NetDev *vlan;
|
||||
Hashmap *vlans;
|
||||
bool dhcp;
|
||||
bool dhcp_dns;
|
||||
bool dhcp_mtu;
|
||||
|
|
Loading…
Reference in New Issue