diff --git a/man/systemd.network.xml b/man/systemd.network.xml index fe8c8a14c6a..886258fbd04 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -5858,8 +5858,9 @@ ServerAddress=192.168.0.1/24 VLAN= - The VLAN ID allowed on the port. This can be either a single ID or a range M-N. Takes - an integer in the range 1…4094. + The VLAN ID allowed on the port. This can be either a single ID or a range M-N. Takes an + integer in the range 1…4094. This setting can be specified multiple times. If an empty string is + assigned, then the all previous assignments are cleared. @@ -5868,8 +5869,10 @@ ServerAddress=192.168.0.1/24 EgressUntagged= The VLAN ID specified here will be used to untag frames on egress. Configuring - EgressUntagged= implicates the use of VLAN= above and will enable the - VLAN ID for ingress as well. This can be either a single ID or a range M-N. + EgressUntagged= implicates the use of VLAN= above and will + enable the VLAN ID for ingress as well. This can be either a single ID or a range M-N. This + setting can be specified multiple times. If an empty string is assigned, then the all previous + assignments are cleared. diff --git a/src/network/networkd-bridge-vlan.c b/src/network/networkd-bridge-vlan.c index a3d90651e5b..6c8ec286fc0 100644 --- a/src/network/networkd-bridge-vlan.c +++ b/src/network/networkd-bridge-vlan.c @@ -83,7 +83,7 @@ static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) { for (uint16_t k = 0; k < BRIDGE_VLAN_BITMAP_MAX; k++) { - if (k == link->network->pvid) { + if (k == link->network->bridge_vlan_pvid) { /* PVID needs to be sent alone. Finish previous bits. */ if (begin != UINT16_MAX) { assert(begin < k); @@ -95,7 +95,7 @@ static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) { begin = UINT16_MAX; } - untagged = is_bit_set(k, link->network->br_untagged_bitmap); + untagged = is_bit_set(k, link->network->bridge_vlan_untagged_bitmap); r = add_single(m, k, untagged, /* is_pvid = */ true); if (r < 0) return r; @@ -103,7 +103,7 @@ static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) { continue; } - if (!is_bit_set(k, link->network->br_vid_bitmap)) { + if (!is_bit_set(k, link->network->bridge_vlan_bitmap)) { /* This bit is not set. Finish previous bits. */ if (begin != UINT16_MAX) { assert(begin < k); @@ -123,7 +123,7 @@ static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) { assert(begin < k); - u = is_bit_set(k, link->network->br_untagged_bitmap); + u = is_bit_set(k, link->network->bridge_vlan_untagged_bitmap); if (untagged == u) continue; @@ -139,7 +139,7 @@ static int bridge_vlan_append_set_info(Link *link, sd_netlink_message *m) { /* This is the starting point of a new bit sequence. Save the position and the tagging flag. */ begin = k; - untagged = is_bit_set(k, link->network->br_untagged_bitmap); + untagged = is_bit_set(k, link->network->bridge_vlan_untagged_bitmap); } /* No pending bit sequence. @@ -185,15 +185,15 @@ int bridge_vlan_set_message(Link *link, sd_netlink_message *m) { void network_adjust_bridge_vlan(Network *network) { assert(network); - if (!network->use_br_vlan) - return; + for (uint16_t k = 0; k < BRIDGE_VLAN_BITMAP_MAX; k++) + if (is_bit_set(k, network->bridge_vlan_untagged_bitmap)) + set_bit(k, network->bridge_vlan_bitmap); - /* pvid might not be in br_vid_bitmap yet */ - if (vlanid_is_valid(network->pvid)) - set_bit(network->pvid, network->br_vid_bitmap); + if (vlanid_is_valid(network->bridge_vlan_pvid)) + set_bit(network->bridge_vlan_pvid, network->bridge_vlan_bitmap); } -int config_parse_brvlan_pvid( +int config_parse_bridge_vlan_id( const char *unit, const char *filename, unsigned line, @@ -205,21 +205,32 @@ int config_parse_brvlan_pvid( void *data, void *userdata) { - Network *network = userdata; - uint16_t pvid; + uint16_t v, *id = ASSERT_PTR(data); int r; - r = parse_vlanid(rvalue, &pvid); - if (r < 0) - return r; + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); - network->pvid = pvid; - network->use_br_vlan = true; + if (isempty(rvalue)) { + *id = UINT16_MAX; + return 0; + } + r = parse_vlanid(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring: %s", + lvalue, rvalue); + return 0; + } + + *id = v; return 0; } -int config_parse_brvlan_vlan( +int config_parse_bridge_vlan_id_range( const char *unit, const char *filename, unsigned line, @@ -231,7 +242,7 @@ int config_parse_brvlan_vlan( void *data, void *userdata) { - Network *network = userdata; + uint32_t *bitmap = ASSERT_PTR(data); uint16_t vid, vid_end; int r; @@ -239,54 +250,22 @@ int config_parse_brvlan_vlan( assert(section); assert(lvalue); assert(rvalue); - assert(data); + + if (isempty(rvalue)) { + memzero(bitmap, BRIDGE_VLAN_BITMAP_LEN * sizeof(uint32_t)); + return 0; + } r = parse_vid_range(rvalue, &vid, &vid_end); if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse VLAN, ignoring: %s", rvalue); + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse %s=, ignoring: %s", + lvalue, rvalue); return 0; } for (; vid <= vid_end; vid++) - set_bit(vid, network->br_vid_bitmap); + set_bit(vid, bitmap); - network->use_br_vlan = true; - return 0; -} - -int config_parse_brvlan_untagged( - 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; - uint16_t vid, vid_end; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = parse_vid_range(rvalue, &vid, &vid_end); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Could not parse VLAN: %s", rvalue); - return 0; - } - - for (; vid <= vid_end; vid++) { - set_bit(vid, network->br_vid_bitmap); - set_bit(vid, network->br_untagged_bitmap); - } - - network->use_br_vlan = true; return 0; } diff --git a/src/network/networkd-bridge-vlan.h b/src/network/networkd-bridge-vlan.h index af159e06c0e..f6a6807be09 100644 --- a/src/network/networkd-bridge-vlan.h +++ b/src/network/networkd-bridge-vlan.h @@ -21,6 +21,5 @@ void network_adjust_bridge_vlan(Network *network); int bridge_vlan_set_message(Link *link, sd_netlink_message *m); -CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid); -CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan); -CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_untagged); +CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id); +CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id_range); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 628b1ad19f5..e101d2811b9 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -368,9 +368,9 @@ BridgeFDB.AssociatedWith, config_parse_fdb_ntf_flags, BridgeFDB.OutgoingInterface, config_parse_fdb_interface, 0, 0 BridgeMDB.MulticastGroupAddress, config_parse_mdb_group_address, 0, 0 BridgeMDB.VLANId, config_parse_mdb_vlan_id, 0, 0 -BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 -BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 -BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 +BridgeVLAN.PVID, config_parse_bridge_vlan_id, 0, offsetof(Network, bridge_vlan_pvid) +BridgeVLAN.VLAN, config_parse_bridge_vlan_id_range, 0, offsetof(Network, bridge_vlan_bitmap) +BridgeVLAN.EgressUntagged, config_parse_bridge_vlan_id_range, 0, offsetof(Network, bridge_vlan_untagged_bitmap) DHCPPrefixDelegation.UplinkInterface, config_parse_uplink, 0, 0 DHCPPrefixDelegation.SubnetId, config_parse_dhcp_pd_subnet_id, 0, offsetof(Network, dhcp_pd_subnet_id) DHCPPrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp_pd_announce) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e3735842e26..654fd7bb9ee 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -450,7 +450,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID, .multicast_router = _MULTICAST_ROUTER_INVALID, - .pvid = UINT16_MAX, + .bridge_vlan_pvid = UINT16_MAX, .lldp_mode = LLDP_MODE_ROUTERS_ONLY, .lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 4995e55b531..80a46c488ec 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -289,10 +289,9 @@ struct Network { MulticastRouter multicast_router; /* Bridge VLAN */ - bool use_br_vlan; - uint16_t pvid; - uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN]; - uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN]; + uint16_t bridge_vlan_pvid; + uint32_t bridge_vlan_bitmap[BRIDGE_VLAN_BITMAP_LEN]; + uint32_t bridge_vlan_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN]; /* CAN support */ uint32_t can_bitrate; diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index ae8db4d8c8a..3e1d904836f 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -687,7 +687,8 @@ int link_request_to_set_bridge_vlan(Link *link) { assert(link); assert(link->network); - if (!link->network->use_br_vlan) + /* If nothing configured, use the default vlan ID. */ + if (memeqzero(link->network->bridge_vlan_bitmap, BRIDGE_VLAN_BITMAP_LEN * sizeof(uint32_t))) return 0; if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) {