From 11cee6efbf54aeff25a6d106f6707ce822fa72d0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 13 Nov 2023 02:13:03 +0900 Subject: [PATCH] network/brvlan: read bridge vlan IDs through netlink and save them In this commit, obtained vlan IDs are not used, but they will be used in the later commits. --- src/network/networkd-bridge-vlan.c | 61 ++++++++++++++++++++++++++++++ src/network/networkd-bridge-vlan.h | 2 + src/network/networkd-link.c | 7 ++++ src/network/networkd-link.h | 6 +++ src/network/networkd-manager.c | 14 +++++++ 5 files changed, 90 insertions(+) diff --git a/src/network/networkd-bridge-vlan.c b/src/network/networkd-bridge-vlan.c index 6c8ec286fc..c38ae16a47 100644 --- a/src/network/networkd-bridge-vlan.c +++ b/src/network/networkd-bridge-vlan.c @@ -182,6 +182,67 @@ int bridge_vlan_set_message(Link *link, sd_netlink_message *m) { return 0; } +#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) + +int link_update_bridge_vlan(Link *link, sd_netlink_message *m) { + _cleanup_free_ void *data = NULL; + size_t len; + uint16_t begin = UINT16_MAX; + int r, family; + + assert(link); + assert(m); + + r = sd_rtnl_message_get_family(m, &family); + if (r < 0) + return r; + + if (family != AF_BRIDGE) + return 0; + + r = sd_netlink_message_read_data(m, IFLA_AF_SPEC, &len, &data); + if (r == -ENODATA) + return 0; + if (r < 0) + return r; + + memzero(link->bridge_vlan_bitmap, sizeof(link->bridge_vlan_bitmap)); + + for (struct rtattr *rta = data; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { + struct bridge_vlan_info *p; + + if (RTA_TYPE(rta) != IFLA_BRIDGE_VLAN_INFO) + continue; + if (RTA_PAYLOAD(rta) != sizeof(struct bridge_vlan_info)) + continue; + + p = RTA_DATA(rta); + + if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_RANGE_BEGIN)) { + begin = p->vid; + continue; + } + + if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_RANGE_END)) { + for (uint16_t k = begin; k <= p->vid; k++) + set_bit(k, link->bridge_vlan_bitmap); + + begin = UINT16_MAX; + continue; + } + + if (FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_PVID)) { + link->bridge_vlan_pvid = p->vid; + link->bridge_vlan_pvid_is_untagged = FLAGS_SET(p->flags, BRIDGE_VLAN_INFO_UNTAGGED); + } + + set_bit(p->vid, link->bridge_vlan_bitmap); + begin = UINT16_MAX; + } + + return 0; +} + void network_adjust_bridge_vlan(Network *network) { assert(network); diff --git a/src/network/networkd-bridge-vlan.h b/src/network/networkd-bridge-vlan.h index f6a6807be0..43d365e745 100644 --- a/src/network/networkd-bridge-vlan.h +++ b/src/network/networkd-bridge-vlan.h @@ -21,5 +21,7 @@ void network_adjust_bridge_vlan(Network *network); int bridge_vlan_set_message(Link *link, sd_netlink_message *m); +int link_update_bridge_vlan(Link *link, sd_netlink_message *m); + CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id); CONFIG_PARSER_PROTOTYPE(config_parse_bridge_vlan_id_range); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2caf4ff249..aad86eed99 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -35,6 +35,7 @@ #include "networkd-address.h" #include "networkd-bridge-fdb.h" #include "networkd-bridge-mdb.h" +#include "networkd-bridge-vlan.h" #include "networkd-can.h" #include "networkd-dhcp-prefix-delegation.h" #include "networkd-dhcp-server.h" @@ -2435,6 +2436,10 @@ static int link_update(Link *link, sd_netlink_message *message) { if (r < 0) return r; + r = link_update_bridge_vlan(link, message); + if (r < 0) + return r; + return needs_reconfigure; } @@ -2508,6 +2513,8 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { .ifname = TAKE_PTR(ifname), .kind = TAKE_PTR(kind), + .bridge_vlan_pvid = UINT16_MAX, + .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID, .state_file = TAKE_PTR(state_file), diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 938bbf482e..a6c2f2d720 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -21,6 +21,7 @@ #include "log-link.h" #include "netif-util.h" #include "network-util.h" +#include "networkd-bridge-vlan.h" #include "networkd-ipv6ll.h" #include "networkd-util.h" #include "ordered-set.h" @@ -72,6 +73,11 @@ typedef struct Link { sd_device *dev; char *driver; + /* bridge vlan */ + uint16_t bridge_vlan_pvid; + bool bridge_vlan_pvid_is_untagged; + uint32_t bridge_vlan_bitmap[BRIDGE_VLAN_BITMAP_LEN]; + /* to prevent multiple ethtool calls */ bool ethtool_driver_read; bool ethtool_permanent_hw_addr_read; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 1ca1d7abe5..bdf6088f2f 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -753,6 +753,20 @@ static int manager_enumerate_links(Manager *m) { if (r < 0) return r; + r = manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link); + if (r < 0) + return r; + + req = sd_netlink_message_unref(req); + + r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_rtnl_message_link_set_family(req, AF_BRIDGE); + if (r < 0) + return r; + return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link); } -- 2.25.1