diff options
author | Tom Gundersen <teg@jklm.no> | 2014-02-10 18:41:54 +0100 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-02-10 19:00:17 +0100 |
commit | 672682a6b9d6fb6a3722c3fea1a93b4831747b54 (patch) | |
tree | 8d7956ff4c9171faad0702afe01b9ac2656d3322 | |
parent | 3831838ae7b3ac145711bb84a71cb86cdd829975 (diff) |
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>
-rw-r--r-- | man/systemd-networkd.service.xml | 14 | ||||
-rw-r--r-- | src/network/networkd-gperf.gperf | 4 | ||||
-rw-r--r-- | src/network/networkd-link.c | 17 | ||||
-rw-r--r-- | src/network/networkd-netdev.c | 12 | ||||
-rw-r--r-- | src/network/networkd-network.c | 13 | ||||
-rw-r--r-- | src/network/networkd.h | 4 |
6 files changed, 42 insertions, 22 deletions
diff --git a/man/systemd-networkd.service.xml b/man/systemd-networkd.service.xml index e5499d66d7..1b1ea4c5fe 100644 --- a/man/systemd-networkd.service.xml +++ b/man/systemd-networkd.service.xml @@ -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> diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf index 37bb8db149..ecc5ca0bab 100644 --- a/src/network/networkd-gperf.gperf +++ b/src/network/networkd-gperf.gperf @@ -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) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6468f9cd31..5e763069f3 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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; } diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index 76f1deae58..c9b9b2bfd0 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -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; } diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5d930235b3..48131c1f09 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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; } diff --git a/src/network/networkd.h b/src/network/networkd.h index 184f631ecf..726cd83699 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -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; |