]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/brvlan: read bridge vlan IDs through netlink and save them
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 12 Nov 2023 17:13:03 +0000 (02:13 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 12 Nov 2023 18:58:46 +0000 (03:58 +0900)
In this commit, obtained vlan IDs are not used, but they will be used in
the later commits.

src/network/networkd-bridge-vlan.c
src/network/networkd-bridge-vlan.h
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c

index 6c8ec286fc0ac5e18bb6a85d8ab353f27c8ab71a..c38ae16a47ddcee45d684e39ea50b060184cb309 100644 (file)
@@ -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);
 
index f6a6807be0992e488dac5135f2309161628f16b8..43d365e7457e3dfdcbd0b748b3b9b58e94a017e2 100644 (file)
@@ -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);
index 2caf4ff24956f6a923eb78801b69eea18dea6651..aad86eed9911281ef97de3bf4f5332fef742d7db 100644 (file)
@@ -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),
index 938bbf482eca8292ca95e524d27680f7b47a93a2..a6c2f2d72026c1db7250dcdac925e6a1d9c7e525 100644 (file)
@@ -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;
index 1ca1d7abe5eaa2dffc4ba248be53889b3cd7c777..bdf6088f2f42fdc4dd9a537dce83e906c6cb7960 100644 (file)
@@ -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);
 }