diff options
Diffstat (limited to 'src/network/networkd-brvlan.c')
-rw-r--r-- | src/network/networkd-brvlan.c | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c deleted file mode 100644 index 18ecd86858..0000000000 --- a/src/network/networkd-brvlan.c +++ /dev/null @@ -1,349 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2016 BISDN GmbH. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/in.h> -#include <linux/if_bridge.h> -#include <stdbool.h> - -#include "alloc-util.h" -#include "conf-parser.h" -#include "netlink-util.h" -#include "networkd-brvlan.h" -#include "networkd.h" -#include "parse-util.h" -#include "vlan-util.h" - -static bool is_bit_set(unsigned bit, uint32_t scope) { - assert(bit < sizeof(scope)*8); - return scope & (1 << bit); -} - -static inline void set_bit(unsigned nr, uint32_t *addr) { - if (nr < BRIDGE_VLAN_BITMAP_MAX) - addr[nr / 32] |= (((uint32_t) 1) << (nr % 32)); -} - -static int find_next_bit(int i, uint32_t x) { - int j; - - if (i >= 32) - return -1; - - /* find first bit */ - if (i < 0) - return BUILTIN_FFS_U32(x); - - /* mask off prior finds to get next */ - j = __builtin_ffs(x >> i); - return j ? j + i : 0; -} - -static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) { - struct bridge_vlan_info br_vlan; - int i, j, k, r, done, cnt; - uint16_t begin, end; - bool untagged = false; - - assert(link); - assert(req); - assert(br_vid_bitmap); - assert(br_untagged_bitmap); - - i = cnt = -1; - - begin = end = UINT16_MAX; - for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) { - unsigned base_bit; - uint32_t vid_map = br_vid_bitmap[k]; - uint32_t untagged_map = br_untagged_bitmap[k]; - - base_bit = k * 32; - i = -1; - done = 0; - do { - j = find_next_bit(i, vid_map); - if (j > 0) { - /* first hit of any bit */ - if (begin == UINT16_MAX && end == UINT16_MAX) { - begin = end = j - 1 + base_bit; - untagged = is_bit_set(j - 1, untagged_map); - goto next; - } - - /* this bit is a continuation of prior bits */ - if (j - 2 + base_bit == end && untagged == is_bit_set(j - 1, untagged_map) && (uint16_t)j - 1 + base_bit != pvid && (uint16_t)begin != pvid) { - end++; - goto next; - } - } else - done = 1; - - if (begin != UINT16_MAX) { - cnt++; - if (done && k < BRIDGE_VLAN_BITMAP_LEN - 1) - break; - - br_vlan.flags = 0; - if (untagged) - br_vlan.flags |= BRIDGE_VLAN_INFO_UNTAGGED; - - if (begin == end) { - br_vlan.vid = begin; - - if (begin == pvid) - br_vlan.flags |= BRIDGE_VLAN_INFO_PVID; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - } else { - br_vlan.vid = begin; - br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - - br_vlan.vid = end; - br_vlan.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN; - br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_END; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - } - - if (done) - break; - } - if (j > 0) { - begin = end = j - 1 + base_bit; - untagged = is_bit_set(j - 1, untagged_map); - } - - next: - i = j; - } while(!done); - } - if (!cnt) - return -EINVAL; - - return cnt; -} - -static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - Link *link = userdata; - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_error_errno(link, r, "Could not add VLAN to bridge port: %m"); - - return 1; -} - -int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - uint16_t flags; - sd_netlink *rtnl; - - assert(link); - assert(link->manager); - assert(br_vid_bitmap); - assert(br_untagged_bitmap); - assert(link->network); - - /* pvid might not be in br_vid_bitmap yet */ - if (pvid) - set_bit(pvid, br_vid_bitmap); - - rtnl = link->manager->rtnl; - - /* create new RTM message */ - r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); - - r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); - if (r < 0) - return log_link_error_errno(link, r, "Could not set message family: %m"); - - r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); - if (r < 0) - return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); - - /* master needs flag self */ - if (!link->network->bridge) { - flags = BRIDGE_FLAGS_SELF; - sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t)); - } - - /* add vlan info */ - r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap); - if (r < 0) - return log_link_error_errno(link, r, "Could not append VLANs: %m"); - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); - - /* send message to the kernel */ - r = sd_netlink_call_async(rtnl, req, set_brvlan_handler, link, 0, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - return 0; -} - -static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) { - int r; - char *p; - char *_rvalue = NULL; - uint16_t _vid = UINT16_MAX; - uint16_t _vid_end = UINT16_MAX; - - assert(rvalue); - assert(vid); - assert(vid_end); - - _rvalue = strdupa(rvalue); - p = strchr(_rvalue, '-'); - if (p) { - *p = '\0'; - p++; - r = parse_vlanid(_rvalue, &_vid); - if (r < 0) - return r; - - if (_vid == 0) - return -ERANGE; - - r = parse_vlanid(p, &_vid_end); - if (r < 0) - return r; - - if (_vid_end == 0) - return -ERANGE; - } else { - r = parse_vlanid(_rvalue, &_vid); - if (r < 0) - return r; - - if (_vid == 0) - return -ERANGE; - } - - *vid = _vid; - *vid_end = _vid_end; - return r; -} - -int config_parse_brvlan_pvid(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; - int r; - uint16_t pvid; - r = parse_vlanid(rvalue, &pvid); - if (r < 0) - return r; - - network->pvid = pvid; - network->use_br_vlan = true; - - return 0; -} - -int config_parse_brvlan_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; - int r; - uint16_t vid, vid_end; - - 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_ERR, filename, line, r, "Failed to parse VLAN, ignoring: %s", rvalue); - return 0; - } - - if (UINT16_MAX == vid_end) - set_bit(vid++, network->br_vid_bitmap); - else { - if (vid >= vid_end) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue); - return 0; - } - for (; vid <= vid_end; vid++) - set_bit(vid, network->br_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; - int r; - uint16_t vid, vid_end; - - 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_ERR, filename, line, r, "Could not parse VLAN: %s", rvalue); - return 0; - } - - if (UINT16_MAX == vid_end) { - set_bit(vid, network->br_vid_bitmap); - set_bit(vid, network->br_untagged_bitmap); - } else { - if (vid >= vid_end) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %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; -} |