From: Yu Watanabe Date: Sun, 12 Nov 2023 17:13:03 +0000 (+0900) Subject: network/brvlan: read bridge vlan IDs through netlink and save them X-Git-Tag: v256-rc1~1569^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=11cee6efbf54aeff25a6d106f6707ce822fa72d0;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/network/networkd-bridge-vlan.c b/src/network/networkd-bridge-vlan.c index 6c8ec286fc0..c38ae16a47d 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 f6a6807be09..43d365e7457 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 2caf4ff2495..aad86eed991 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 938bbf482ec..a6c2f2d7202 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 1ca1d7abe5e..bdf6088f2f4 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); }