summary refs log tree commit diff
path: root/src/core/platform
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2023-08-09 21:55:35 +0200
committerMichael Biebl <biebl@debian.org>2023-08-09 21:55:35 +0200
commit05e4a733f2141995181a551854d5df929f084adf (patch)
tree83bb937740a6667525ba0df046748ecaa829c269 /src/core/platform
parent14b0f3a9dc9ea90d60a3b057350fd4d637dc021a (diff)
New upstream version 1.44.0 upstream/1.44.0
Diffstat (limited to 'src/core/platform')
-rw-r--r--src/core/platform/nm-fake-platform.c99
-rw-r--r--src/core/platform/tests/test-cleanup.c4
-rw-r--r--src/core/platform/tests/test-common.c6
-rw-r--r--src/core/platform/tests/test-link.c252
-rw-r--r--src/core/platform/tests/test-route.c9
5 files changed, 259 insertions, 111 deletions
diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c
index 0c366d82..f6f377d4 100644
--- a/src/core/platform/nm-fake-platform.c
+++ b/src/core/platform/nm-fake-platform.c
@@ -102,7 +102,9 @@ static gboolean ip6_address_add(NMPlatform     *platform,
                                 struct in6_addr peer_addr,
                                 guint32         lifetime,
                                 guint32         preferred,
-                                guint           flags);
+                                guint           flags,
+                                char          **out_extack_msg);
+
 static gboolean
 ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen);
 
@@ -276,6 +278,24 @@ link_add_pre(NMPlatform *platform,
     return device;
 }
 
+static void
+link_add_post(NMPlatform *self, NMFakePlatformLink *device)
+{
+    char path[128];
+
+    switch (device->obj->link.type) {
+    case NM_LINK_TYPE_BRIDGE:
+        nm_sprintf_buf(path, "/sys/class/net/%s/bridge/default_pvid", device->obj->link.name);
+        sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), "1");
+
+        nm_sprintf_buf(path, "/sys/class/net/%s/bridge/vlan_filtering", device->obj->link.name);
+        sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), "0");
+        break;
+    default:
+        break;
+    }
+}
+
 static int
 link_add(NMPlatform            *platform,
          NMLinkType             type,
@@ -387,6 +407,7 @@ link_add(NMPlatform            *platform,
         *out_link = NMP_OBJECT_CAST_LINK(device->obj);
 
     link_changed(platform, device, cache_op, NULL);
+    link_add_post(platform, device);
     if (veth_peer)
         link_changed(platform, device_veth, cache_op_veth, NULL);
 
@@ -439,6 +460,7 @@ link_add_one(NMPlatform *platform,
 static gboolean
 link_delete(NMPlatform *platform, int ifindex)
 {
+    NMFakePlatformPrivate          *priv     = NM_FAKE_PLATFORM_GET_PRIVATE(platform);
     NMFakePlatformLink             *device   = link_get(platform, ifindex);
     nm_auto_nmpobj const NMPObject *obj_old  = NULL;
     nm_auto_nmpobj const NMPObject *obj_old2 = NULL;
@@ -449,6 +471,17 @@ link_delete(NMPlatform *platform, int ifindex)
 
     obj_old = g_steal_pointer(&device->obj);
 
+    if (obj_old->link.type == NM_LINK_TYPE_BRIDGE) {
+        char path[128];
+
+        g_hash_table_remove(
+            priv->options,
+            nm_sprintf_buf(path, "/sys/class/net/%s/bridge/default_pvid", obj_old->link.name));
+        g_hash_table_remove(
+            priv->options,
+            nm_sprintf_buf(path, "/sys/class/net/%s/bridge/vlan_filtering", obj_old->link.name));
+    }
+
     cache_op = nmp_cache_remove(nm_platform_get_cache(platform), obj_old, FALSE, FALSE, &obj_old2);
     g_assert(cache_op == NMP_CACHE_OPS_REMOVED);
     g_assert(obj_old2);
@@ -542,7 +575,7 @@ link_changed(NMPlatform         *platform,
     nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, device->obj);
 
     if (!IN6_IS_ADDR_UNSPECIFIED(&device->ip6_lladdr)) {
-        if (device->obj->link.connected)
+        if (device->obj->link.connected) {
             ip6_address_add(platform,
                             device->obj->link.ifindex,
                             device->ip6_lladdr,
@@ -550,8 +583,9 @@ link_changed(NMPlatform         *platform,
                             in6addr_any,
                             NM_PLATFORM_LIFETIME_PERMANENT,
                             NM_PLATFORM_LIFETIME_PERMANENT,
-                            0);
-        else
+                            0,
+                            NULL);
+        } else
             ip6_address_delete(platform, device->obj->link.ifindex, device->ip6_lladdr, 64);
     }
 
@@ -669,8 +703,10 @@ link_supports_sriov(NMPlatform *platform, int ifindex)
 static gboolean
 link_change(NMPlatform                   *platform,
             int                           ifindex,
+            NMPlatformLinkProps          *props,
             NMPortKind                    port_kind,
-            const NMPlatformLinkPortData *port_data)
+            const NMPlatformLinkPortData *port_data,
+            NMPlatformLinkChangeFlags     flags)
 {
     NMFakePlatformLink       *device  = link_get(platform, ifindex);
     nm_auto_nmpobj NMPObject *obj_tmp = NULL;
@@ -747,6 +783,34 @@ link_vlan_change(NMPlatform             *platform,
     return FALSE;
 }
 
+static gboolean
+link_set_bridge_info(NMPlatform                            *self,
+                     int                                    ifindex,
+                     const NMPlatformLinkSetBridgeInfoData *bridge_info)
+{
+    NMFakePlatformLink *link;
+    char                path[128];
+    char                value[128];
+
+    link = link_get(self, ifindex);
+    if (!link)
+        return FALSE;
+
+    if (bridge_info->vlan_default_pvid_has) {
+        nm_sprintf_buf(path, "/sys/class/net/%s/bridge/default_pvid", link->obj->link.name);
+        nm_sprintf_buf(value, "%u", bridge_info->vlan_default_pvid_val);
+        sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), value);
+    }
+
+    if (bridge_info->vlan_filtering_has) {
+        nm_sprintf_buf(path, "/sys/class/net/%s/bridge/vlan_filtering", link->obj->link.name);
+        nm_sprintf_buf(value, "%u", bridge_info->vlan_filtering_val);
+        sysctl_set(self, NMP_SYSCTL_PATHID_ABSOLUTE(path), value);
+    }
+
+    return TRUE;
+}
+
 struct infiniband_add_data {
     int parent;
     int p_key;
@@ -785,7 +849,7 @@ infiniband_partition_add(NMPlatform            *platform,
     parent_device = link_get(platform, parent);
     g_return_val_if_fail(parent_device != NULL, FALSE);
 
-    nmp_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key);
+    nm_net_devname_infiniband(name, parent_device->obj->link.name, p_key);
 
     link_add_one(platform, name, NM_LINK_TYPE_INFINIBAND, _infiniband_add_prepare, &d, out_link);
     return TRUE;
@@ -800,7 +864,7 @@ infiniband_partition_delete(NMPlatform *platform, int parent, int p_key)
     parent_device = link_get(platform, parent);
     g_return_val_if_fail(parent_device != NULL, FALSE);
 
-    nmp_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key);
+    nm_net_devname_infiniband(name, parent_device->obj->link.name, p_key);
     return link_delete(platform, nm_platform_link_get_ifindex(platform, name));
 }
 
@@ -890,7 +954,10 @@ mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len)
 /*****************************************************************************/
 
 static gboolean
-ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *address)
+ipx_address_add(NMPlatform             *platform,
+                int                     addr_family,
+                const NMPlatformObject *address,
+                char                  **out_extack_msg)
 {
     nm_auto_nmpobj NMPObject       *obj = NULL;
     NMPCacheOpsType                 cache_op;
@@ -899,6 +966,7 @@ ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *a
     NMPCache                       *cache   = nm_platform_get_cache(platform);
 
     g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
+    g_assert(!out_extack_msg || !*out_extack_msg);
 
     obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ADDRESS
                                                 : NMP_OBJECT_TYPE_IP6_ADDRESS,
@@ -919,7 +987,8 @@ ip4_address_add(NMPlatform *platform,
                 guint32     lifetime,
                 guint32     preferred,
                 guint32     flags,
-                const char *label)
+                const char *label,
+                char      **out_extack_msg)
 {
     NMPlatformIP4Address address;
 
@@ -939,7 +1008,7 @@ ip4_address_add(NMPlatform *platform,
     if (label)
         g_strlcpy(address.label, label, sizeof(address.label));
 
-    return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address);
+    return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address, out_extack_msg);
 }
 
 static gboolean
@@ -950,7 +1019,8 @@ ip6_address_add(NMPlatform     *platform,
                 struct in6_addr peer_addr,
                 guint32         lifetime,
                 guint32         preferred,
-                guint32         flags)
+                guint32         flags,
+                char          **out_extack_msg)
 {
     NMPlatformIP6Address address;
 
@@ -967,7 +1037,7 @@ ip6_address_add(NMPlatform     *platform,
     address.preferred   = preferred;
     address.n_ifa_flags = flags;
 
-    return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address);
+    return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address, out_extack_msg);
 }
 
 static gboolean
@@ -1117,7 +1187,7 @@ object_delete(NMPlatform *platform, const NMPObject *obj)
 }
 
 static int
-ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
+ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack, char **out_extack_msg)
 {
     NMDedupMultiIter                iter;
     nm_auto_nmpobj NMPObject       *obj = NULL;
@@ -1139,6 +1209,7 @@ ip_route_add(NMPlatform *platform, NMPNlmFlags flags, NMPObject *obj_stack)
     g_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_stack),
                        NMP_OBJECT_TYPE_IP4_ROUTE,
                        NMP_OBJECT_TYPE_IP6_ROUTE));
+    g_assert(!out_extack_msg || !*out_extack_msg);
 
     addr_family = NMP_OBJECT_GET_ADDR_FAMILY(obj_stack);
 
@@ -1364,6 +1435,8 @@ nm_fake_platform_class_init(NMFakePlatformClass *klass)
 
     platform_class->link_vlan_change = link_vlan_change;
 
+    platform_class->link_set_bridge_info = link_set_bridge_info;
+
     platform_class->infiniband_partition_add    = infiniband_partition_add;
     platform_class->infiniband_partition_delete = infiniband_partition_delete;
 
diff --git a/src/core/platform/tests/test-cleanup.c b/src/core/platform/tests/test-cleanup.c
index 139a0280..c643e71c 100644
--- a/src/core/platform/tests/test-cleanup.c
+++ b/src/core/platform/tests/test-cleanup.c
@@ -77,6 +77,7 @@ test_cleanup_internal(void)
                                          lifetime,
                                          preferred,
                                          0,
+                                         NULL,
                                          NULL));
     g_assert(nm_platform_ip6_address_add(NM_PLATFORM_GET,
                                          ifindex,
@@ -85,7 +86,8 @@ test_cleanup_internal(void)
                                          in6addr_any,
                                          lifetime,
                                          preferred,
-                                         flags));
+                                         flags,
+                                         NULL));
     nmtstp_ip4_route_add(NM_PLATFORM_GET,
                          ifindex,
                          NM_IP_CONFIG_SOURCE_USER,
diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c
index 65bdfeae..fde7dc0d 100644
--- a/src/core/platform/tests/test-common.c
+++ b/src/core/platform/tests/test-common.c
@@ -1809,7 +1809,8 @@ _ip_address_add(NMPlatform     *platform,
                                                   lifetime,
                                                   preferred,
                                                   flags,
-                                                  label);
+                                                  label,
+                                                  NULL);
         } else {
             g_assert(label == NULL);
             success = nm_platform_ip6_address_add(platform,
@@ -1819,7 +1820,8 @@ _ip_address_add(NMPlatform     *platform,
                                                   peer_address->addr6,
                                                   lifetime,
                                                   preferred,
-                                                  flags);
+                                                  flags,
+                                                  NULL);
         }
         g_assert(success);
     }
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index 33858671..8a54ac48 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -36,6 +36,16 @@
 #define _ADD_DUMMY(platform, name) \
     g_assert(NMTST_NM_ERR_SUCCESS(nm_platform_link_dummy_add((platform), (name), NULL)))
 
+#define _sysctl_assert_eq(plat, path, value)                                   \
+    G_STMT_START                                                               \
+    {                                                                          \
+        gs_free char *_val = NULL;                                             \
+                                                                               \
+        _val = nm_platform_sysctl_get(plat, NMP_SYSCTL_PATHID_ABSOLUTE(path)); \
+        g_assert_cmpstr(_val, ==, value);                                      \
+    }                                                                          \
+    G_STMT_END
+
 static void
 test_bogus(void)
 {
@@ -212,58 +222,58 @@ test_link_changed_signal_cb(NMPlatform               *platform,
 }
 
 static void
-test_slave(int master, int type, SignalData *master_changed)
+test_port(int controller, int port_type, SignalData *controller_changed)
 {
-    int         ifindex;
+    int         ifindex_port;
     SignalData *link_added = add_signal_ifname(NM_PLATFORM_SIGNAL_LINK_CHANGED,
                                                NM_PLATFORM_SIGNAL_ADDED,
                                                link_callback,
                                                SLAVE_NAME);
     SignalData *link_changed, *link_removed;
     char       *value;
-    NMLinkType  link_type = nm_platform_link_get_type(NM_PLATFORM_GET, master);
+    NMLinkType  controller_type = nm_platform_link_get_type(NM_PLATFORM_GET, controller);
     gboolean    test_link_changed_signal_arg1;
     gboolean    test_link_changed_signal_arg2;
 
-    g_assert(NM_IN_SET(link_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE));
+    g_assert(NM_IN_SET(controller_type, NM_LINK_TYPE_TEAM, NM_LINK_TYPE_BOND, NM_LINK_TYPE_BRIDGE));
 
-    g_assert(software_add(type, SLAVE_NAME));
-    ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, SLAVE_NAME);
-    g_assert(ifindex > 0);
+    g_assert(software_add(port_type, SLAVE_NAME));
+    ifindex_port = nm_platform_link_get_ifindex(NM_PLATFORM_GET, SLAVE_NAME);
+    g_assert(ifindex_port > 0);
     link_changed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
                                       NM_PLATFORM_SIGNAL_CHANGED,
                                       link_callback,
-                                      ifindex);
+                                      ifindex_port);
     link_removed = add_signal_ifindex(NM_PLATFORM_SIGNAL_LINK_CHANGED,
                                       NM_PLATFORM_SIGNAL_REMOVED,
                                       link_callback,
-                                      ifindex);
+                                      ifindex_port);
     accept_signal(link_added);
 
-    /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly.
+    /* Set the port up to see whether controller's IFF_LOWER_UP is set correctly.
      *
      * See https://bugzilla.redhat.com/show_bug.cgi?id=910348
      */
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, FALSE) >= 0);
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
+    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex_port));
+    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex_port, IFF_UP, FALSE) >= 0);
+    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex_port));
     ensure_no_signal(link_changed);
 
-    /* Enslave */
-    link_changed->ifindex = ifindex;
-    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex));
-    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, master);
+    /* Attach port */
+    link_changed->ifindex = ifindex_port;
+    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, controller, ifindex_port));
+    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex_port), ==, controller);
 
     accept_signals(link_changed, 1, 3);
-    accept_signals(master_changed, 0, 2);
+    accept_signals(controller_changed, 0, 2);
 
-    /* enslaveing brings put the slave */
-    if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
-        g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
+    /* Attaching ports brings up the port */
+    if (NM_IN_SET(controller_type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
+        g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, ifindex_port));
     else
-        g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
+        g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex_port));
 
-    if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND)) {
+    if (NM_IN_SET(controller_type, NM_LINK_TYPE_BOND)) {
         NMPlatformLinkBondPort   bond_port;
         gboolean                 prio_has;
         gboolean                 prio_supported;
@@ -273,7 +283,7 @@ test_slave(int master, int type, SignalData *master_changed)
         link = nmtstp_link_get_typed(NM_PLATFORM_GET, 0, SLAVE_NAME, NM_LINK_TYPE_DUMMY);
         g_assert(link);
 
-        lnk = nm_platform_link_get_lnk_bond(NM_PLATFORM_GET, master, NULL);
+        lnk = nm_platform_link_get_lnk_bond(NM_PLATFORM_GET, controller, NULL);
         g_assert(lnk);
 
         g_assert(NM_IN_SET(lnk->mode, 3, 1));
@@ -286,13 +296,24 @@ test_slave(int master, int type, SignalData *master_changed)
             .prio     = prio_has ? 6 : 0,
         };
 
-        g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, &bond_port));
+        g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex_port, NULL, &bond_port, 0));
         accept_signals(link_changed, 1, 3);
 
-        link = nmtstp_link_get(NM_PLATFORM_GET, ifindex, SLAVE_NAME);
+        link = nmtstp_link_get(NM_PLATFORM_GET, ifindex_port, SLAVE_NAME);
         g_assert(link);
         g_assert_cmpint(link->port_data.bond.queue_id, ==, 5);
         g_assert(link->port_data.bond.prio_has || link->port_data.bond.prio == 0);
+    } else if (controller_type == NM_LINK_TYPE_BRIDGE) {
+        /* Skip this part for nm-fake-platform */
+        if (nmtstp_is_root_test() && nmtstp_is_sysfs_writable()) {
+            g_assert(nm_platform_sysctl_slave_set_option(NM_PLATFORM_GET,
+                                                         ifindex_port,
+                                                         "priority",
+                                                         "614"));
+            value = nm_platform_sysctl_slave_get_option(NM_PLATFORM_GET, ifindex_port, "priority");
+            g_assert_cmpstr(value, ==, "614");
+            g_free(value);
+        }
     }
 
     test_link_changed_signal_arg1 = FALSE;
@@ -306,10 +327,10 @@ test_slave(int master, int type, SignalData *master_changed)
                      G_CALLBACK(test_link_changed_signal_cb),
                      &test_link_changed_signal_arg2);
 
-    /* Set master up */
-    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, master, IFF_UP, TRUE) >= 0);
-    g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, master));
-    accept_signals(master_changed, 1, 3);
+    /* Set controller up */
+    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, controller, IFF_UP, TRUE) >= 0);
+    g_assert(nm_platform_link_is_up(NM_PLATFORM_GET, controller));
+    accept_signals(controller_changed, 1, 3);
 
     g_signal_handlers_disconnect_by_func(NM_PLATFORM_GET,
                                          G_CALLBACK(test_link_changed_signal_cb),
@@ -320,28 +341,28 @@ test_slave(int master, int type, SignalData *master_changed)
     g_assert(test_link_changed_signal_arg1);
     g_assert(test_link_changed_signal_arg2);
 
-    /* Master with a disconnected slave is disconnected
+    /* Master with a disconnected port is disconnected
      *
-     * For some reason, bonding and teaming slaves are automatically set up. We
+     * For some reason, bonding and teaming ports are automatically set up. We
      * need to set them back down for this test.
      */
-    switch (nm_platform_link_get_type(NM_PLATFORM_GET, master)) {
+    switch (nm_platform_link_get_type(NM_PLATFORM_GET, controller)) {
     case NM_LINK_TYPE_BOND:
     case NM_LINK_TYPE_TEAM:
-        g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, FALSE) >= 0);
+        g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex_port, IFF_UP, FALSE) >= 0);
         accept_signal(link_changed);
-        accept_signals(master_changed, 0, 3);
+        accept_signals(controller_changed, 0, 3);
         break;
     default:
         break;
     }
-    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex));
-    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    if (nmtstp_is_root_test() && nm_platform_link_is_connected(NM_PLATFORM_GET, master)) {
-        if (nm_platform_link_get_type(NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) {
-            /* Older team versions (e.g. Fedora 17) have a bug that team master stays
-             * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if
-             * `ip link` also claims master to be up, accept it. */
+    g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex_port));
+    g_assert(!nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex_port));
+    if (nmtstp_is_root_test() && nm_platform_link_is_connected(NM_PLATFORM_GET, controller)) {
+        if (nm_platform_link_get_type(NM_PLATFORM_GET, controller) == NM_LINK_TYPE_TEAM) {
+            /* Older team versions (e.g. Fedora 17) have a bug that team controller stays
+             * IFF_LOWER_UP even if its port is down. Double check it with iproute2 and if
+             * `ip link` also claims controller to be up, accept it. */
             char *stdout_str = NULL;
 
             nmtst_spawn_sync(NULL,
@@ -352,7 +373,7 @@ test_slave(int master, int type, SignalData *master_changed)
                              "link",
                              "show",
                              "dev",
-                             nm_platform_link_get_name(NM_PLATFORM_GET, master));
+                             nm_platform_link_get_name(NM_PLATFORM_GET, controller));
 
             g_assert(strstr(stdout_str, "LOWER_UP"));
             g_free(stdout_str);
@@ -360,44 +381,29 @@ test_slave(int master, int type, SignalData *master_changed)
             g_assert_not_reached();
     }
 
-    /* Set slave up and see if master gets up too */
-    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex, IFF_UP, TRUE) >= 0);
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex));
-    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, master));
+    /* Set port up and see if controller gets up too */
+    g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, ifindex_port, IFF_UP, TRUE) >= 0);
+    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, ifindex_port));
+    g_assert(nm_platform_link_is_connected(NM_PLATFORM_GET, controller));
     accept_signals(link_changed, 1, 3);
     /* NM running, can cause additional change of addrgenmode */
-    accept_signals(master_changed, 0, 3);
+    accept_signals(controller_changed, 0, 3);
 
-    /* Enslave again
+    /* Attach port again
      *
-     * Gracefully succeed if already enslaved.
+     * Gracefully succeed if already attached port.
      */
     ensure_no_signal(link_changed);
-    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, master, ifindex));
+    g_assert(nm_platform_link_enslave(NM_PLATFORM_GET, controller, ifindex_port));
     accept_signals(link_changed, 0, 2);
-    accept_signals(master_changed, 0, 2);
-
-    /* Set slave option */
-    switch (type) {
-    case NM_LINK_TYPE_BRIDGE:
-        if (nmtstp_is_sysfs_writable()) {
-            g_assert(
-                nm_platform_sysctl_slave_set_option(NM_PLATFORM_GET, ifindex, "priority", "614"));
-            value = nm_platform_sysctl_slave_get_option(NM_PLATFORM_GET, ifindex, "priority");
-            g_assert_cmpstr(value, ==, "614");
-            g_free(value);
-        }
-        break;
-    default:
-        break;
-    }
+    accept_signals(controller_changed, 0, 2);
 
     /* Release */
     ensure_no_signal(link_added);
     ensure_no_signal(link_changed);
     ensure_no_signal(link_removed);
-    g_assert(nm_platform_link_release(NM_PLATFORM_GET, master, ifindex));
-    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex), ==, 0);
+    g_assert(nm_platform_link_release(NM_PLATFORM_GET, controller, ifindex_port));
+    g_assert_cmpint(nm_platform_link_get_master(NM_PLATFORM_GET, ifindex_port), ==, 0);
     if (link_changed->received_count > 0) {
         accept_signals(link_added, 0, 1);
         accept_signals(link_changed, 1, 5);
@@ -409,22 +415,22 @@ test_slave(int master, int type, SignalData *master_changed)
         ensure_no_signal(link_changed);
         accept_signal(link_removed);
     }
-    accept_signals(master_changed, 0, 3);
+    accept_signals(controller_changed, 0, 3);
 
-    ensure_no_signal(master_changed);
+    ensure_no_signal(controller_changed);
 
     /* Release again */
     ensure_no_signal(link_changed);
-    g_assert(!nm_platform_link_release(NM_PLATFORM_GET, master, ifindex));
+    g_assert(!nm_platform_link_release(NM_PLATFORM_GET, controller, ifindex_port));
 
-    ensure_no_signal(master_changed);
+    ensure_no_signal(controller_changed);
 
     /* Remove */
     ensure_no_signal(link_added);
     ensure_no_signal(link_changed);
     ensure_no_signal(link_removed);
-    nmtstp_link_delete(NULL, -1, ifindex, NULL, TRUE);
-    accept_signals(master_changed, 0, 1);
+    nmtstp_link_delete(NULL, -1, ifindex_port, NULL, TRUE);
+    accept_signals(controller_changed, 0, 1);
     accept_signals(link_changed, 0, 1);
     accept_signal(link_removed);
 
@@ -528,7 +534,7 @@ test_software(NMLinkType link_type, const char *link_typename)
     case NM_LINK_TYPE_BOND:
     case NM_LINK_TYPE_TEAM:
         link_changed->ifindex = ifindex;
-        test_slave(ifindex, NM_LINK_TYPE_DUMMY, link_changed);
+        test_port(ifindex, NM_LINK_TYPE_DUMMY, link_changed);
         link_changed->ifindex = 0;
         break;
     default:
@@ -618,10 +624,14 @@ test_vlan(void)
 static void
 test_bridge_addr(void)
 {
-    char                  addr[ETH_ALEN];
-    NMPlatformLink        link;
-    const NMPlatformLink *plink = NULL;
-    NMPLinkAddress        hw_perm_addr;
+    char                            addr[ETH_ALEN];
+    NMPlatformLink                  link;
+    const NMPlatformLink           *plink = NULL;
+    NMPLinkAddress                  hw_perm_addr;
+    gboolean                        b;
+    char                            sbuf[100];
+    gs_free char                   *str = NULL;
+    NMPlatformLinkSetBridgeInfoData info_data;
 
     nm_utils_hwaddr_aton("de:ad:be:ef:00:11", addr, sizeof(addr));
 
@@ -692,6 +702,42 @@ test_bridge_addr(void)
     g_assert_cmpint(plink->l_address.len, ==, sizeof(addr));
     g_assert(!memcmp(plink->l_address.data, addr, sizeof(addr)));
 
+    info_data = (const NMPlatformLinkSetBridgeInfoData){
+        .vlan_default_pvid_val = nmtst_rand_select(0, 5, 42, 1048),
+        .vlan_default_pvid_has = nmtst_get_rand_bool(),
+        .vlan_filtering_val    = nmtst_get_rand_bool(),
+        .vlan_filtering_has    = nmtst_get_rand_bool(),
+    };
+    b = nm_platform_link_set_bridge_info(NM_PLATFORM_GET, link.ifindex, &info_data);
+    g_assert(b);
+
+    _sysctl_assert_eq(NM_PLATFORM_GET,
+                      "/sys/class/net/" DEVICE_NAME "/bridge/default_pvid",
+                      info_data.vlan_default_pvid_has
+                          ? nm_sprintf_buf(sbuf, "%u", info_data.vlan_default_pvid_val)
+                          : "1");
+
+    _sysctl_assert_eq(NM_PLATFORM_GET,
+                      "/sys/class/net/" DEVICE_NAME "/bridge/vlan_filtering",
+                      info_data.vlan_filtering_val && info_data.vlan_filtering_has ? "1" : "0");
+
+    info_data = (const NMPlatformLinkSetBridgeInfoData){
+        .vlan_default_pvid_val = 55,
+        .vlan_default_pvid_has = TRUE,
+        .vlan_filtering_val    = !info_data.vlan_filtering_val,
+        .vlan_filtering_has    = TRUE,
+    };
+    b = nm_platform_link_set_bridge_info(NM_PLATFORM_GET, link.ifindex, &info_data);
+    g_assert(b);
+
+    _sysctl_assert_eq(NM_PLATFORM_GET,
+                      "/sys/class/net/" DEVICE_NAME "/bridge/default_pvid",
+                      nm_sprintf_buf(sbuf, "%u", info_data.vlan_default_pvid_val));
+
+    _sysctl_assert_eq(NM_PLATFORM_GET,
+                      "/sys/class/net/" DEVICE_NAME "/bridge/vlan_filtering",
+                      info_data.vlan_filtering_val ? "1" : "0");
+
     nmtstp_link_delete(NULL, -1, link.ifindex, link.name, TRUE);
 }
 
@@ -2630,6 +2676,36 @@ test_vlan_set_xgress(void)
 /*****************************************************************************/
 
 static void
+test_link_set_properties(void)
+{
+    const NMPlatformLink     *link;
+    NMPlatformLinkProps       props;
+    NMPlatformLinkChangeFlags flags;
+    int                       ifindex;
+
+    props = (NMPlatformLinkProps){
+        .tx_queue_length  = 599,
+        .gso_max_size     = 10001,
+        .gso_max_segments = 512,
+    };
+    flags = NM_PLATFORM_LINK_CHANGE_TX_QUEUE_LENGTH | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SIZE
+            | NM_PLATFORM_LINK_CHANGE_GSO_MAX_SEGMENTS;
+
+    ifindex = nmtstp_link_dummy_add(NM_PLATFORM_GET, FALSE, "dummy1")->ifindex;
+    g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, &props, NULL, flags));
+
+    link = nmtstp_link_get(NM_PLATFORM_GET, ifindex, "dummy1");
+    g_assert(link);
+    g_assert_cmpint(link->link_props.tx_queue_length, ==, 599);
+    g_assert_cmpint(link->link_props.gso_max_size, ==, 10001);
+    g_assert_cmpint(link->link_props.gso_max_segments, ==, 512);
+
+    nmtstp_link_delete(NULL, -1, link->ifindex, "dummy1", TRUE);
+}
+
+/*****************************************************************************/
+
+static void
 test_create_many_links_do(guint n_devices)
 {
     gint64                 time, start_time = nm_utils_get_monotonic_timestamp_nsec();
@@ -2985,16 +3061,6 @@ _check_sysctl_skip(void)
 
 /*****************************************************************************/
 
-#define _sysctl_assert_eq(plat, path, value)                                   \
-    G_STMT_START                                                               \
-    {                                                                          \
-        gs_free char *_val = NULL;                                             \
-                                                                               \
-        _val = nm_platform_sysctl_get(plat, NMP_SYSCTL_PATHID_ABSOLUTE(path)); \
-        g_assert_cmpstr(_val, ==, value);                                      \
-    }                                                                          \
-    G_STMT_END
-
 static void
 test_netns_general(gpointer fixture, gconstpointer test_data)
 {
@@ -3533,7 +3599,7 @@ test_sysctl_rename(void)
                         ==,
                         (gint32) nm_platform_sysctl_get_int32(
                             PL,
-                            NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"),
+                            NMP_SYSCTL_PATHID_NETDIR_A(dirfd, s ?: "<unknown>", "ifindex"),
                             -1));
         break;
     }
@@ -3605,7 +3671,7 @@ test_sysctl_netns_switch(void)
                     ==,
                     (gint32) nm_platform_sysctl_get_int32(
                         PL,
-                        NMP_SYSCTL_PATHID_NETDIR(dirfd, s ?: "<unknown>", "ifindex"),
+                        NMP_SYSCTL_PATHID_NETDIR_A(dirfd, s ?: "<unknown>", "ifindex"),
                         -1));
     g_assert_cmpint(
         ifindex,
@@ -4022,6 +4088,8 @@ _nmtstp_setup_tests(void)
 
         g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress);
 
+        g_test_add_func("/link/set-properties", test_link_set_properties);
+
         g_test_add_data_func("/link/create-many-links/20",
                              GUINT_TO_POINTER(20),
                              test_create_many_links);
diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c
index bd8fdc27..9aa21a9a 100644
--- a/src/core/platform/tests/test-route.c
+++ b/src/core/platform/tests/test-route.c
@@ -421,7 +421,8 @@ test_ip6_route(void)
                                          in6addr_any,
                                          NM_PLATFORM_LIFETIME_PERMANENT,
                                          NM_PLATFORM_LIFETIME_PERMANENT,
-                                         0));
+                                         0,
+                                         NULL));
     accept_signals(route_added, 0, 3);
 
     _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 200, ifindex, 1, &pref_src);
@@ -706,7 +707,8 @@ test_ip4_route_options(gconstpointer test_data)
                                              a->lifetime,
                                              a->preferred,
                                              a->n_ifa_flags,
-                                             a->label));
+                                             a->label,
+                                             NULL));
         if (a->peer_address == a->address)
             _wait_for_ipv4_addr_device_route(NM_PLATFORM_GET, 200, a->ifindex, a->address, a->plen);
     }
@@ -878,7 +880,8 @@ test_ip6_route_options(gconstpointer test_data)
                                              addr[i].peer_address,
                                              addr[i].lifetime,
                                              addr[i].preferred,
-                                             addr[i].n_ifa_flags));
+                                             addr[i].n_ifa_flags,
+                                             NULL));
     }
     _wait_for_ipv6_addr_non_tentative(NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);