summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2025-01-20 19:08:06 +0100
committerMichael Biebl <biebl@debian.org>2025-01-20 19:08:06 +0100
commit818258cf34b83fbc754633295e1052d4752d7b15 (patch)
treeaa45b6a831d6c0ee954b1a03891ad3da09349528
parente465722b908aa870bdc293b9a417d3c15294aa6d (diff)
New upstream version 1.50.2 upstream/1.50.2
-rw-r--r--.gitlab-ci.yml308
-rw-r--r--.gitlab-ci/ci.template8
-rw-r--r--.gitlab-ci/config.yml42
-rwxr-xr-x.gitlab-ci/run-test.sh24
-rw-r--r--NEWS13
-rw-r--r--configure.ac2
-rw-r--r--meson.build2
-rw-r--r--src/core/devices/nm-device.c66
-rw-r--r--src/core/devices/nm-device.h6
-rw-r--r--src/core/dhcp/nm-dhcp-client.c19
-rw-r--r--src/core/dhcp/nm-dhcp-client.h2
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c5
-rw-r--r--src/core/platform/tests/test-link.c11
-rw-r--r--src/core/vpn/nm-vpn-connection.c11
-rw-r--r--src/libnm-platform/nm-linux-platform.c4
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-connection.c6
-rw-r--r--src/n-dhcp4/src/n-dhcp4-c-probe.c8
-rw-r--r--src/n-dhcp4/src/n-dhcp4-private.h3
18 files changed, 267 insertions, 273 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d46b80d0..5d2aba95 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,7 +14,7 @@
 
 
 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
-.templates_sha: &template_sha 98b1218f146a1ec96d65e3ce0041f9a6ec5cb5e6
+.templates_sha: &template_sha 593a0a5fe35a523a646a7efae5471c9759b8fba3
 
 
 
@@ -60,11 +60,11 @@ variables:
   #
   # This is done by running `ci-fairy generate-template` and possibly bumping
   # ".default_tag".
-  ALPINE_TAG:  'tag-961e70a41177'
-  CENTOS_TAG:  'tag-fe6805b2c8f4'
-  DEBIAN_TAG:  'tag-806721d9d354'
-  FEDORA_TAG:  'tag-fe6805b2c8f4'
-  UBUNTU_TAG:  'tag-806721d9d354'
+  ALPINE_TAG:  'tag-1a1fa0d53067'
+  CENTOS_TAG:  'tag-4960ce3d0698'
+  DEBIAN_TAG:  'tag-e9c1178c8d3b'
+  FEDORA_TAG:  'tag-4960ce3d0698'
+  UBUNTU_TAG:  'tag-e9c1178c8d3b'
 
   ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
   CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
@@ -83,6 +83,7 @@ variables:
       - NetworkManager-1*.tar.xz
       - NetworkManager-1*.src.rpm
       - nm-test.log
+      - testlog.txt
 
 .nm_artifacts_debug:
   artifacts:
@@ -90,6 +91,7 @@ variables:
     when: always
     paths:
       - nm-test.log
+      - testlog.txt
 
 #################################################################
 #                                                               #
@@ -100,39 +102,39 @@ variables:
 # Build a container for each distribution + version. The ci-templates
 # will re-use the containers if the tag doesn't change.
 
-tier1:fedora:40@prep:
+tier1:fedora:41@prep:
   extends:
     - .fdo.container-build@fedora
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: '40'
+    FDO_DISTRIBUTION_VERSION: '41'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
     FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-tier2:centos:stream9@prep:
+tier2:alpine:3.21@prep:
   extends:
-    - .fdo.container-build@centos
+    - .fdo.container-build@alpine
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'stream9'
-    FDO_DISTRIBUTION_TAG: $CENTOS_TAG
-    FDO_DISTRIBUTION_EXEC: $CENTOS_EXEC
+    FDO_DISTRIBUTION_VERSION: '3.21'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
+    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier2:fedora:rawhide@prep:
+tier3:fedora:40@prep:
   extends:
     - .fdo.container-build@fedora
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'rawhide'
+    FDO_DISTRIBUTION_VERSION: '40'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
     FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
   rules:
@@ -140,41 +142,13 @@ tier2:fedora:rawhide@prep:
       when: manual
       allow_failure: true
 
-tier2:debian:sid@prep:
-  extends:
-    - .fdo.container-build@debian
-  stage: prep
-  variables:
-    GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'sid'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-    FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-      when: manual
-      allow_failure: true
-
-tier2:debian:testing@prep:
-  extends:
-    - .fdo.container-build@debian
-  stage: prep
-  variables:
-    GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'testing'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-    FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-      when: manual
-      allow_failure: true
-
-tier2:ubuntu:devel@prep:
+tier3:ubuntu:24.10@prep:
   extends:
     - .fdo.container-build@ubuntu
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'devel'
+    FDO_DISTRIBUTION_VERSION: '24.10'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
     FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
   rules:
@@ -182,41 +156,27 @@ tier2:ubuntu:devel@prep:
       when: manual
       allow_failure: true
 
-tier2:alpine:edge@prep:
-  extends:
-    - .fdo.container-build@alpine
-  stage: prep
-  variables:
-    GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'edge'
-    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
-    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-      when: manual
-      allow_failure: true
-
-tier3:fedora:39@prep:
+tier3:ubuntu:24.04@prep:
   extends:
-    - .fdo.container-build@fedora
+    - .fdo.container-build@ubuntu
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: '39'
-    FDO_DISTRIBUTION_TAG: $FEDORA_TAG
-    FDO_DISTRIBUTION_EXEC: $FEDORA_EXEC
+    FDO_DISTRIBUTION_VERSION: '24.04'
+    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
+    FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier3:ubuntu:20.04@prep:
+tier3:ubuntu:22.04@prep:
   extends:
     - .fdo.container-build@ubuntu
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: '20.04'
+    FDO_DISTRIBUTION_VERSION: '22.04'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
     FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
   rules:
@@ -224,13 +184,13 @@ tier3:ubuntu:20.04@prep:
       when: manual
       allow_failure: true
 
-tier3:ubuntu:22.04@prep:
+tier3:ubuntu:20.04@prep:
   extends:
     - .fdo.container-build@ubuntu
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: '22.04'
+    FDO_DISTRIBUTION_VERSION: '20.04'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
     FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
   rules:
@@ -238,71 +198,71 @@ tier3:ubuntu:22.04@prep:
       when: manual
       allow_failure: true
 
-tier3:ubuntu:24.04@prep:
+tier3:debian:12@prep:
   extends:
-    - .fdo.container-build@ubuntu
+    - .fdo.container-build@debian
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: '24.04'
-    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
-    FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
+    FDO_DISTRIBUTION_VERSION: '12'
+    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
+    FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier3:ubuntu:rolling@prep:
+tier3:alpine:3.20@prep:
   extends:
-    - .fdo.container-build@ubuntu
+    - .fdo.container-build@alpine
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'rolling'
-    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
-    FDO_DISTRIBUTION_EXEC: $UBUNTU_EXEC
+    FDO_DISTRIBUTION_VERSION: '3.20'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
+    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier3:debian:stable@prep:
+tier3:alpine:3.19@prep:
   extends:
-    - .fdo.container-build@debian
+    - .fdo.container-build@alpine
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'stable'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-    FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
+    FDO_DISTRIBUTION_VERSION: '3.19'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
+    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier3:debian:oldstable@prep:
+tier3:alpine:3.18@prep:
   extends:
-    - .fdo.container-build@debian
+    - .fdo.container-build@alpine
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'oldstable'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-    FDO_DISTRIBUTION_EXEC: $DEBIAN_EXEC
+    FDO_DISTRIBUTION_VERSION: '3.18'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
+    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
       allow_failure: true
 
-tier3:alpine:latest@prep:
+tier3:centos:stream9@prep:
   extends:
-    - .fdo.container-build@alpine
+    - .fdo.container-build@centos
   stage: prep
   variables:
     GIT_STRATEGY: none
-    FDO_DISTRIBUTION_VERSION: 'latest'
-    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
-    FDO_DISTRIBUTION_EXEC: $ALPINE_EXEC
+    FDO_DISTRIBUTION_VERSION: 'stream9'
+    FDO_DISTRIBUTION_TAG: $CENTOS_TAG
+    FDO_DISTRIBUTION_EXEC: $CENTOS_EXEC
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
       when: manual
@@ -324,7 +284,7 @@ tier3:alpine:latest@prep:
   dependencies: []
 
 
-t_fedora:40:
+t_fedora:41:
   extends:
     - .build@template
     - .fdo.distribution-image@fedora
@@ -340,206 +300,164 @@ t_fedora:40:
         - tarball
         - subtree
   variables:
-    FDO_DISTRIBUTION_VERSION: '40'
+    FDO_DISTRIBUTION_VERSION: '41'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
   needs:
-    - "tier1:fedora:40@prep"
+    - "tier1:fedora:41@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_centos:stream9:
+t_alpine:3.21:
   extends:
     - .build@template
-    - .fdo.distribution-image@centos
+    - .fdo.distribution-image@alpine
     - .nm_artifacts_debug
   stage: tier2
   variables:
-    FDO_DISTRIBUTION_VERSION: 'stream9'
-    FDO_DISTRIBUTION_TAG: $CENTOS_TAG
+    FDO_DISTRIBUTION_VERSION: '3.21'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
   needs:
-    - "tier2:centos:stream9@prep"
+    - "tier2:alpine:3.21@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_fedora:rawhide:
+t_fedora:40:
   extends:
     - .build@template
     - .fdo.distribution-image@fedora
     - .nm_artifacts_debug
-  stage: tier2
+  stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'rawhide'
+    FDO_DISTRIBUTION_VERSION: '40'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
   needs:
-    - "tier2:fedora:rawhide@prep"
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-
-t_debian:sid:
-  extends:
-    - .build@template
-    - .fdo.distribution-image@debian
-    - .nm_artifacts_debug
-  stage: tier2
-  variables:
-    FDO_DISTRIBUTION_VERSION: 'sid'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-  needs:
-    - "tier2:debian:sid@prep"
+    - "tier3:fedora:40@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_debian:testing:
-  extends:
-    - .build@template
-    - .fdo.distribution-image@debian
-    - .nm_artifacts_debug
-  stage: tier2
-  variables:
-    FDO_DISTRIBUTION_VERSION: 'testing'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
-  needs:
-    - "tier2:debian:testing@prep"
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-
-t_ubuntu:devel:
+t_ubuntu:24.10:
   extends:
     - .build@template
     - .fdo.distribution-image@ubuntu
     - .nm_artifacts_debug
-  stage: tier2
+  stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'devel'
+    FDO_DISTRIBUTION_VERSION: '24.10'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
   needs:
-    - "tier2:ubuntu:devel@prep"
+    - "tier3:ubuntu:24.10@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_alpine:edge:
-  extends:
-    - .build@template
-    - .fdo.distribution-image@alpine
-    - .nm_artifacts_debug
-  stage: tier2
-  variables:
-    FDO_DISTRIBUTION_VERSION: 'edge'
-    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
-  needs:
-    - "tier2:alpine:edge@prep"
-  rules:
-    - if: $CI_PIPELINE_SOURCE != 'schedule'
-
-t_fedora:39:
+t_ubuntu:24.04:
   extends:
     - .build@template
-    - .fdo.distribution-image@fedora
+    - .fdo.distribution-image@ubuntu
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: '39'
-    FDO_DISTRIBUTION_TAG: $FEDORA_TAG
+    FDO_DISTRIBUTION_VERSION: '24.04'
+    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
   needs:
-    - "tier3:fedora:39@prep"
+    - "tier3:ubuntu:24.04@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_ubuntu:20.04:
+t_ubuntu:22.04:
   extends:
     - .build@template
     - .fdo.distribution-image@ubuntu
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: '20.04'
+    FDO_DISTRIBUTION_VERSION: '22.04'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
   needs:
-    - "tier3:ubuntu:20.04@prep"
+    - "tier3:ubuntu:22.04@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_ubuntu:22.04:
+t_ubuntu:20.04:
   extends:
     - .build@template
     - .fdo.distribution-image@ubuntu
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: '22.04'
+    FDO_DISTRIBUTION_VERSION: '20.04'
     FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
   needs:
-    - "tier3:ubuntu:22.04@prep"
+    - "tier3:ubuntu:20.04@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_ubuntu:24.04:
+t_debian:12:
   extends:
     - .build@template
-    - .fdo.distribution-image@ubuntu
+    - .fdo.distribution-image@debian
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: '24.04'
-    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
+    FDO_DISTRIBUTION_VERSION: '12'
+    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
   needs:
-    - "tier3:ubuntu:24.04@prep"
+    - "tier3:debian:12@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_ubuntu:rolling:
+t_alpine:3.20:
   extends:
     - .build@template
-    - .fdo.distribution-image@ubuntu
+    - .fdo.distribution-image@alpine
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'rolling'
-    FDO_DISTRIBUTION_TAG: $UBUNTU_TAG
+    FDO_DISTRIBUTION_VERSION: '3.20'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
   needs:
-    - "tier3:ubuntu:rolling@prep"
+    - "tier3:alpine:3.20@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_debian:stable:
+t_alpine:3.19:
   extends:
     - .build@template
-    - .fdo.distribution-image@debian
+    - .fdo.distribution-image@alpine
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'stable'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
+    FDO_DISTRIBUTION_VERSION: '3.19'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
   needs:
-    - "tier3:debian:stable@prep"
+    - "tier3:alpine:3.19@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_debian:oldstable:
+t_alpine:3.18:
   extends:
     - .build@template
-    - .fdo.distribution-image@debian
+    - .fdo.distribution-image@alpine
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'oldstable'
-    FDO_DISTRIBUTION_TAG: $DEBIAN_TAG
+    FDO_DISTRIBUTION_VERSION: '3.18'
+    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
   needs:
-    - "tier3:debian:oldstable@prep"
+    - "tier3:alpine:3.18@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
-t_alpine:latest:
+t_centos:stream9:
   extends:
     - .build@template
-    - .fdo.distribution-image@alpine
+    - .fdo.distribution-image@centos
     - .nm_artifacts_debug
   stage: tier3
   variables:
-    FDO_DISTRIBUTION_VERSION: 'latest'
-    FDO_DISTRIBUTION_TAG: $ALPINE_TAG
+    FDO_DISTRIBUTION_VERSION: 'stream9'
+    FDO_DISTRIBUTION_TAG: $CENTOS_TAG
   needs:
-    - "tier3:alpine:latest@prep"
+    - "tier3:centos:stream9@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
 
@@ -553,10 +471,10 @@ check-patch:
   extends:
     - .fdo.distribution-image@fedora
   variables:
-    FDO_DISTRIBUTION_VERSION: '40'
+    FDO_DISTRIBUTION_VERSION: '41'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
   needs:
-    - "tier1:fedora:40@prep"
+    - "tier1:fedora:41@prep"
   rules:
     - if: $CI_PIPELINE_SOURCE != 'schedule'
   stage: tier1
@@ -568,11 +486,15 @@ check-tree:
   extends:
     - .fdo.distribution-image@fedora
   variables:
-    FDO_DISTRIBUTION_VERSION: '40'
+    FDO_DISTRIBUTION_VERSION: '41'
     FDO_DISTRIBUTION_TAG: $FEDORA_TAG
   needs:
-    - "tier1:fedora:40@prep"
+    - "tier1:fedora:41@prep"
   rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
+      allow_failure: true
+    - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+      allow_failure: true
     - if: $CI_PIPELINE_SOURCE != 'schedule'
   stage: tier1
   script:
@@ -597,9 +519,9 @@ pages:
       when: never
     - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'main'
   dependencies:
-    - "t_fedora:40: [meson+gcc+docs+valgrind]"
+    - "t_fedora:41: [meson+gcc+docs+valgrind]"
   needs:
-    - "t_fedora:40: [meson+gcc+docs+valgrind]"
+    - "t_fedora:41: [meson+gcc+docs+valgrind]"
 
 triage:issues:
   stage: triage
diff --git a/.gitlab-ci/ci.template b/.gitlab-ci/ci.template
index 208c3490..a804a2ee 100644
--- a/.gitlab-ci/ci.template
+++ b/.gitlab-ci/ci.template
@@ -16,7 +16,7 @@
 
 
 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
-.templates_sha: &template_sha 98b1218f146a1ec96d65e3ce0041f9a6ec5cb5e6
+.templates_sha: &template_sha 593a0a5fe35a523a646a7efae5471c9759b8fba3
 
 {# Group distros by their common (name,) tuples.#}
 {% set distro_groups = [] %}
@@ -88,6 +88,7 @@ variables:
       - NetworkManager-1*.tar.xz
       - NetworkManager-1*.src.rpm
       - nm-test.log
+      - testlog.txt
 
 .nm_artifacts_debug:
   artifacts:
@@ -95,6 +96,7 @@ variables:
     when: always
     paths:
       - nm-test.log
+      - testlog.txt
 
 #################################################################
 #                                                               #
@@ -210,6 +212,10 @@ check-tree:
   needs:
     - "tier{{default_distro.tier}}:{{default_distro.name}}:{{default_distro.versions[0]}}@prep"
   rules:
+    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH
+      allow_failure: true
+    - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+      allow_failure: true
     - if: $CI_PIPELINE_SOURCE != 'schedule'
   stage: tier1
   script:
diff --git a/.gitlab-ci/config.yml b/.gitlab-ci/config.yml
index 05b19c1c..8b9fcac3 100644
--- a/.gitlab-ci/config.yml
+++ b/.gitlab-ci/config.yml
@@ -23,51 +23,39 @@ distributions:
   - name: fedora
     tier: 1
     versions:
-      - '40'
+      - '41'
 
   # TIER 2: distribution versions that will or might use the current NM version.
   # Run when doing a release.
-  - name: centos
-    tier: 2
-    versions:
-      - 'stream9'
-  - name: fedora
-    tier: 2
-    versions:
-      - rawhide
-  - name: debian
-    tier: 2
-    versions:
-      - sid
-      - testing
-  - name: ubuntu
-    tier: 2
-    versions:
-      - devel
   - name: alpine
     tier: 2
     versions:
-      - edge
-  
+      - '3.21'
+
   # TIER 3: distribution versions not in EOL but don't use the current NM version.
   # Run when doing a release, but a failure won't be blocking for the release.
   - name: fedora
     tier: 3
     versions:
-      - '39'
+      - '40'
   - name: ubuntu
     tier: 3
     versions:
-      - '20.04'
-      - '22.04'
+      - '24.10'
       - '24.04'
-      - 'rolling' # latest non-LTS
+      - '22.04'
+      - '20.04'
   - name: debian
     tier: 3
     versions:
-      - 'stable'
-      - 'oldstable'
+      - '12'
   - name: alpine
     tier: 3
     versions:
-      - 'latest'
+      - '3.20'
+      - '3.19'
+      - '3.18'
+  - name: centos
+    tier: 3
+    versions:
+      - 'stream9'
\ No newline at end of file
diff --git a/.gitlab-ci/run-test.sh b/.gitlab-ci/run-test.sh
index 4091cdd4..2008c189 100755
--- a/.gitlab-ci/run-test.sh
+++ b/.gitlab-ci/run-test.sh
@@ -106,22 +106,36 @@ check_run_clean() {
     return 0
 }
 
+die_with_testlog() {
+    mv ./build/meson-logs/testlog.txt ./testlog.txt
+    exit 1
+}
+
 if check_run_clean meson+gcc+docs+valgrind ; then
-    BUILD_TYPE=meson CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh
+    BUILD_TYPE=meson CC=gcc WITH_DOCS=1 WITH_VALGRIND=1 contrib/scripts/nm-ci-run.sh || die_with_testlog
     mv INST/share/gtk-doc/html "$ARTIFACT_DIR/docs-html"
 fi
 
-check_run_clean meson+clang && BUILD_TYPE=meson CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh
-check_run_clean rpm+meson && test $IS_FEDORA = 1 && ./contrib/fedora/rpm/build_clean.sh -g -w crypto_gnutls -w debug -w iwd -w test -w meson
+if check_run_clean meson+clang; then
+    BUILD_TYPE=meson CC=clang WITH_DOCS=0 contrib/scripts/nm-ci-run.sh || die_with_testlog
+fi
+
+if check_run_clean rpm+meson; then
+    if [[ $IS_FEDORA = 1 ]]; then
+        ./contrib/fedora/rpm/build_clean.sh -g -w crypto_gnutls -w debug -w iwd -w test -w meson || die_with_testlog
+    fi
+fi
 
 if check_run_clean tarball && [ "$NM_BUILD_TARBALL" = 1 ]; then
-    SIGN_SOURCE=0 ./contrib/fedora/rpm/build_clean.sh -r
+    SIGN_SOURCE=0 ./contrib/fedora/rpm/build_clean.sh -r || die_with_testlog
     mv ./build/meson-dist/NetworkManager-1*.tar.xz "$ARTIFACT_DIR/"
     mv ./contrib/fedora/rpm/latest/SRPMS/NetworkManager-1*.src.rpm "$ARTIFACT_DIR/"
     do_clean
 fi
 
-check_run_clean tarball+meson && BUILD_TYPE=meson CC=gcc WITH_DOCS=1 CONFIGURE_ONLY=1 contrib/scripts/nm-ci-run.sh
+if check_run_clean tarball+meson; then
+    BUILD_TYPE=meson CC=gcc WITH_DOCS=1 CONFIGURE_ONLY=1 contrib/scripts/nm-ci-run.sh || die_with_testlog
+fi
 
 ###############################################################################
 
diff --git a/NEWS b/NEWS
index 9c9c8f44..24ca2303 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,17 @@
 ===============================================
+NetworkManager-1.50.2
+Overview of changes since NetworkManager-1.50.1
+===============================================
+
+* Fix potential crash when the property "ipv4.dhcp-send-release" is
+  enabled.
+* Support routing rules for VPN connections.
+* Place the route to the VPN gateway into the table defined by the
+  "ipv{4,6}.route-table" properties.
+* Fix error handling rp_filter when kernel don't support MPTCP.
+* Fix configuration of VLAN QoS mappings.
+
+===============================================
 NetworkManager-1.50.1
 Overview of changes since NetworkManager-1.50.0
 ===============================================
diff --git a/configure.ac b/configure.ac
index fdeee7e8..04bcc7d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,7 +8,7 @@ dnl    "shared/nm-version-macros.h.in"
 dnl  - update number in meson.build
 m4_define([nm_major_version], [1])
 m4_define([nm_minor_version], [50])
-m4_define([nm_micro_version], [1])
+m4_define([nm_micro_version], [2])
 m4_define([nm_version],
           [nm_major_version.nm_minor_version.nm_micro_version])
 
diff --git a/meson.build b/meson.build
index 10c63f9d..60782966 100644
--- a/meson.build
+++ b/meson.build
@@ -6,7 +6,7 @@ project(
 #  - add corresponding NM_VERSION_x_y_z macros in
 #    "src/libnm-core-public/nm-version-macros.h.in"
 #  - update number in configure.ac
-  version: '1.50.1',
+  version: '1.50.2',
   license: 'GPL2+',
   default_options: [
     'buildtype=debugoptimized',
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 516e13df..6c5a9b5a 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -1462,7 +1462,7 @@ _prop_get_connection_mptcp_flags(NMDevice *self)
 
     if (!NM_FLAGS_HAS(mptcp_flags, NM_MPTCP_FLAGS_DISABLED)) {
         if (!NM_FLAGS_HAS(mptcp_flags, NM_MPTCP_FLAGS_ALSO_WITHOUT_SYSCTL)) {
-            guint32 v;
+            gint32 v;
 
             /* If enabled, but without "also-without-sysctl", then MPTCP is still
              * disabled, if the sysctl says so...
@@ -10377,31 +10377,34 @@ lldp_setup(NMDevice *self, NMTernary enabled)
  *       as externally added ones. Don't restart NetworkManager if
  *       you care about that.
  */
-static void
-_routing_rules_sync(NMDevice *self, NMTernary set_mode)
+void
+nm_routing_rules_sync(NMConnection *applied_connection,
+                      NMTernary     set_mode,
+                      GPtrArray *(*get_extra_rules)(NMDevice *self),
+                      NMDevice *self,
+                      NMNetns  *netns)
 {
-    NMDevicePrivate  *priv               = NM_DEVICE_GET_PRIVATE(self);
-    NMPGlobalTracker *global_tracker     = nm_netns_get_global_tracker(nm_device_get_netns(self));
-    NMDeviceClass    *klass              = NM_DEVICE_GET_CLASS(self);
+    NMPGlobalTracker *global_tracker     = nm_netns_get_global_tracker(netns);
     gboolean          untrack_only_dirty = FALSE;
     gboolean          keep_deleted_rules;
     gpointer          user_tag_1;
     gpointer          user_tag_2;
 
-    /* take two arbitrary user-tag pointers that belong to @self. */
-    user_tag_1 = &priv->v4_route_table;
-    user_tag_2 = &priv->v6_route_table;
+    if (self) {
+        user_tag_1 = ((guint32 *) self) + 1;
+        user_tag_2 = ((guint32 *) self) + 2;
+    } else {
+        user_tag_1 = ((guint32 *) applied_connection) + 1;
+        user_tag_2 = ((guint32 *) applied_connection) + 2;
+    }
 
     if (set_mode == NM_TERNARY_TRUE) {
-        NMConnection      *applied_connection;
         NMSettingIPConfig *s_ip;
         guint              i, num;
         int                is_ipv4;
 
         untrack_only_dirty = TRUE;
 
-        applied_connection = nm_device_get_applied_connection(self);
-
         for (is_ipv4 = 0; applied_connection && is_ipv4 < 2; is_ipv4++) {
             int addr_family = is_ipv4 ? AF_INET : AF_INET6;
 
@@ -10440,10 +10443,10 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
             }
         }
 
-        if (klass->get_extra_rules) {
+        if (get_extra_rules) {
             gs_unref_ptrarray GPtrArray *extra_rules = NULL;
 
-            extra_rules = klass->get_extra_rules(self);
+            extra_rules = get_extra_rules(self);
             if (extra_rules) {
                 for (i = 0; i < extra_rules->len; i++) {
                     nmp_global_tracker_track_rule(
@@ -10458,7 +10461,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
     }
 
     nmp_global_tracker_untrack_all(global_tracker, user_tag_1, !untrack_only_dirty, TRUE);
-    if (klass->get_extra_rules)
+    if (get_extra_rules)
         nmp_global_tracker_untrack_all(global_tracker, user_tag_2, !untrack_only_dirty, TRUE);
 
     keep_deleted_rules = FALSE;
@@ -10518,8 +10521,8 @@ tc_commit(NMDevice *self)
 static void
 activate_stage2_device_config(NMDevice *self)
 {
-    NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-    NMDeviceClass   *klass;
+    NMDevicePrivate *priv  = NM_DEVICE_GET_PRIVATE(self);
+    NMDeviceClass   *klass = NM_DEVICE_GET_CLASS(self);
     NMActStageReturn ret;
     NMSettingWired  *s_wired;
     gboolean         no_firmware = FALSE;
@@ -10544,7 +10547,11 @@ activate_stage2_device_config(NMDevice *self)
         priv->tc_committed = TRUE;
     }
 
-    _routing_rules_sync(self, NM_TERNARY_TRUE);
+    nm_routing_rules_sync(nm_device_get_applied_connection(self),
+                          NM_TERNARY_TRUE,
+                          klass->get_extra_rules,
+                          self,
+                          nm_device_get_netns(self));
 
     if (!nm_device_managed_type_is_external_or_assume(self)) {
         if (!nm_device_bring_up_full(self, FALSE, TRUE, &no_firmware)) {
@@ -10556,7 +10563,6 @@ activate_stage2_device_config(NMDevice *self)
         }
     }
 
-    klass = NM_DEVICE_GET_CLASS(self);
     if (klass->act_stage2_config_also_for_external_or_assume
         || !nm_device_managed_type_is_external_or_assume(self)) {
         NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
@@ -11383,7 +11389,7 @@ _dev_ipdhcpx_start(NMDevice *self, int addr_family)
     /* Take the NML3ConfigData from the previous lease (if any) that was passed to the NMDhcpClient.
      * This may be the old lease only used during the duration of a reapply until we get the
      * new lease. */
-    previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client);
+    previous_lease = nm_dhcp_client_get_lease(priv->ipdhcp_data_x[IS_IPv4].client, TRUE);
 
     if (!priv->ipdhcp_data_x[IS_IPv4].config) {
         priv->ipdhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family, previous_lease);
@@ -13931,7 +13937,11 @@ check_and_reapply_connection(NMDevice            *self,
 
         nm_device_activate_schedule_stage3_ip_config(self, FALSE);
 
-        _routing_rules_sync(self, NM_TERNARY_TRUE);
+        nm_routing_rules_sync(nm_device_get_applied_connection(self),
+                              NM_TERNARY_TRUE,
+                              klass->get_extra_rules,
+                              self,
+                              nm_device_get_netns(self));
 
         reactivate_proxy_config(self);
 
@@ -16493,6 +16503,7 @@ static void
 nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanup_type)
 {
     NMDevicePrivate *priv;
+    NMDeviceClass   *klass = NM_DEVICE_GET_CLASS(self);
     int              ifindex;
 
     g_return_if_fail(NM_IS_DEVICE(self));
@@ -16517,8 +16528,8 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
     }
 
     /* Call device type-specific deactivation */
-    if (NM_DEVICE_GET_CLASS(self)->deactivate)
-        NM_DEVICE_GET_CLASS(self)->deactivate(self);
+    if (klass->deactivate)
+        klass->deactivate(self);
 
     ifindex = nm_device_get_ip_ifindex(self);
 
@@ -16540,8 +16551,11 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
 
     priv->tc_committed = FALSE;
 
-    _routing_rules_sync(self,
-                        cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE);
+    nm_routing_rules_sync(nm_device_get_applied_connection(self),
+                          cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE,
+                          klass->get_extra_rules,
+                          self,
+                          nm_device_get_netns(self));
 
     if (ifindex > 0)
         nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self), ifindex, NULL);
@@ -16570,7 +16584,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
             /* for other device states (UNAVAILABLE, DISCONNECTED), allow the
              * device to overwrite the reset behavior, so that Wi-Fi can set
              * a randomized MAC address used during scanning. */
-            NM_DEVICE_GET_CLASS(self)->deactivate_reset_hw_addr(self);
+            klass->deactivate_reset_hw_addr(self);
         }
     }
 
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
index b84bbb65..9b051ab4 100644
--- a/src/core/devices/nm-device.h
+++ b/src/core/devices/nm-device.h
@@ -848,4 +848,10 @@ void nm_device_clear_dns_lookup_data(NMDevice *self, const char *reason);
 
 gboolean nm_device_get_allow_autoconnect_on_external(NMDevice *self);
 
+void nm_routing_rules_sync(NMConnection *applied_connection,
+                           NMTernary     set_mode,
+                           GPtrArray *(*get_extra_rules)(NMDevice *self),
+                           NMDevice *self,
+                           NMNetns  *netns);
+
 #endif /* __NETWORKMANAGER_DEVICE_H__ */
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index 4ebc1754..cd6e67e2 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -275,10 +275,25 @@ nm_dhcp_client_create_options_dict(NMDhcpClient *self, gboolean static_keys)
     return options;
 }
 
+/**
+ * nm_dhcp_client_get_lease():
+ * @self: the client
+ * @ignore_acd_pending: FALSE means to only return the lease that already
+ * passed ACD, thus it is in use by us. TRUE means to return a new lease
+ * that might still be pending of Address Collision Detection (ACD) check,
+ * if there is one, or return the current lease that passed ACD if not.
+ *
+ * Returns the current lease that passed ACD or a pending lease still under
+ * ACD check.
+ *
+ */
 const NML3ConfigData *
-nm_dhcp_client_get_lease(NMDhcpClient *self)
+nm_dhcp_client_get_lease(NMDhcpClient *self, gboolean ignore_acd_pending)
 {
-    return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_curr;
+    if (ignore_acd_pending)
+        return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_curr;
+    else
+        return NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd_next;
 }
 
 /*****************************************************************************/
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 2b262f76..8c685faf 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -242,7 +242,7 @@ const NMDhcpClientConfig *nm_dhcp_client_get_config(NMDhcpClient *self);
 
 pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
 
-const NML3ConfigData *nm_dhcp_client_get_lease(NMDhcpClient *self);
+const NML3ConfigData *nm_dhcp_client_get_lease(NMDhcpClient *self, gboolean ignore_acd_pending);
 
 void nm_dhcp_client_stop(NMDhcpClient *self, gboolean release);
 
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index b81ce77a..f4f244c6 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -1484,7 +1484,10 @@ stop(NMDhcpClient *client, gboolean release)
     NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
 
     if (release) {
-        if (n_dhcp4_client_probe_release(priv->probe))
+        /* After we receive a lease from server, it doesn't matter if we completed ACD,
+         * we should send the release message. */
+        if (nm_dhcp_client_get_lease(client, FALSE)
+            && n_dhcp4_client_probe_release(priv->probe) < 0)
             _LOGT("dhcp-client4: failed to send request with RELEASE message");
     }
 
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index 9f63b896..bcb135d3 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -2264,7 +2264,7 @@ test_software_detect_add(const char *testpath, NMLinkType link_type, int test_mo
 }
 
 /*****************************************************************************/
-/*
+
 static void
 _assert_xgress_qos_mappings_impl(int ifindex, gboolean is_ingress_map, int n_entries, int n, ...)
 {
@@ -2344,8 +2344,7 @@ _assert_vlan_flags(int ifindex, _NMVlanFlags flags)
     g_assert(plnk);
     g_assert_cmpint(plnk->flags, ==, flags);
 }
-*/
-/*
+
 static void
 test_vlan_set_xgress(void)
 {
@@ -2361,7 +2360,6 @@ test_vlan_set_xgress(void)
     ifindex =
         nmtstp_assert_wait_for_link(NM_PLATFORM_GET, DEVICE_NAME, NM_LINK_TYPE_VLAN, 100)->ifindex;
 
-
     g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 4, 5));
     _assert_ingress_qos_mappings(ifindex, 1, 4, 5);
 
@@ -2392,7 +2390,6 @@ test_vlan_set_xgress(void)
     g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 9, 4));
     _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
 
-
     g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 7, 3));
     _assert_egress_qos_mappings(ifindex, 1, 7, 3);
 
@@ -2694,7 +2691,7 @@ test_vlan_set_xgress(void)
     nmtstp_link_delete(NULL, -1, ifindex, DEVICE_NAME, TRUE);
     nmtstp_link_delete(NULL, -1, ifindex_parent, PARENT_NAME, TRUE);
 }
-*/
+
 /*****************************************************************************/
 
 static void
@@ -4108,7 +4105,7 @@ _nmtstp_setup_tests(void)
         test_software_detect_add("/link/software/detect/wireguard/1", NM_LINK_TYPE_WIREGUARD, 1);
         test_software_detect_add("/link/software/detect/wireguard/2", NM_LINK_TYPE_WIREGUARD, 2);
 
-        //       g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress);
+        g_test_add_func("/link/software/vlan/set-xgress", test_vlan_set_xgress);
 
         g_test_add_func("/link/set-properties", test_link_set_properties);
 
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index b5a7fc4c..c14682b8 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -905,7 +905,8 @@ fw_call_cleanup(NMVpnConnection *self)
 static void
 vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev)
 {
-    const char *iface;
+    NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+    const char             *iface;
 
     /* Remove zone from firewall */
     iface = nm_vpn_connection_get_ip_iface(self, FALSE);
@@ -917,6 +918,8 @@ vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev)
     fw_call_cleanup(self);
 
     _l3cfg_l3cd_clear_all(self);
+
+    nm_routing_rules_sync(_get_applied_connection(self), NM_TERNARY_FALSE, NULL, NULL, priv->netns);
 }
 
 static void
@@ -1242,6 +1245,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
             .gateway    = parent_gw.addr4,
             .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
             .metric_any = TRUE,
+            .table_any  = TRUE,
         };
     } else {
         route.r6 = (NMPlatformIP6Route){
@@ -1251,6 +1255,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
             .gateway    = parent_gw.addr6,
             .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
             .metric_any = TRUE,
+            .table_any  = TRUE,
         };
     }
     nm_l3_config_data_add_route(l3cd, addr_family, NULL, &route.rx);
@@ -1267,6 +1272,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
                 .plen       = 32,
                 .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
                 .metric_any = TRUE,
+                .table_any  = TRUE,
             };
         } else {
             route.r6 = (NMPlatformIP6Route){
@@ -1274,6 +1280,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
                 .plen       = 128,
                 .rt_source  = NM_IP_CONFIG_SOURCE_VPN,
                 .metric_any = TRUE,
+                .table_any  = TRUE,
             };
         }
         nm_l3_config_data_add_route(l3cd, addr_family, NULL, &route.rx);
@@ -2274,6 +2281,8 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
 
     _l3cfg_l3cd_set(self, L3CD_TYPE_IP_X(IS_IPv4), l3cd);
 
+    nm_routing_rules_sync(_get_applied_connection(self), NM_TERNARY_TRUE, NULL, NULL, priv->netns);
+
     _check_complete(self, TRUE);
 }
 
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 90a34102..f348e27c 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -5424,7 +5424,7 @@ _nl_msg_new_link_set_linkinfo_vlan(struct nl_msg          *msg,
                     if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
                         goto nla_put_failure;
                 }
-                NLA_PUT(msg, i, sizeof(ingress_qos[i]), &ingress_qos[i]);
+                NLA_PUT(msg, IFLA_VLAN_QOS_MAPPING, sizeof(ingress_qos[i]), &ingress_qos[i]);
             }
         }
 
@@ -5441,7 +5441,7 @@ _nl_msg_new_link_set_linkinfo_vlan(struct nl_msg          *msg,
                     if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
                         goto nla_put_failure;
                 }
-                NLA_PUT(msg, i, sizeof(egress_qos[i]), &egress_qos[i]);
+                NLA_PUT(msg, IFLA_VLAN_QOS_MAPPING, sizeof(egress_qos[i]), &egress_qos[i]);
             }
         }
 
diff --git a/src/n-dhcp4/src/n-dhcp4-c-connection.c b/src/n-dhcp4/src/n-dhcp4-c-connection.c
index 7024b71a..e76ea165 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-connection.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-connection.c
@@ -1010,9 +1010,9 @@ static const char *message_type_to_str(uint8_t type) {
         }
 }
 
-static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection,
-                                             NDhcp4Outgoing *request,
-                                             uint64_t timestamp) {
+int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection,
+                                      NDhcp4Outgoing *request,
+                                      uint64_t timestamp) {
         char server_addr[INET_ADDRSTRLEN];
         char client_addr[INET_ADDRSTRLEN];
         char error_msg[128];
diff --git a/src/n-dhcp4/src/n-dhcp4-c-probe.c b/src/n-dhcp4/src/n-dhcp4-c-probe.c
index ee3a8886..7a6def34 100644
--- a/src/n-dhcp4/src/n-dhcp4-c-probe.c
+++ b/src/n-dhcp4/src/n-dhcp4-c-probe.c
@@ -1137,7 +1137,7 @@ int n_dhcp4_client_probe_transition_decline(NDhcp4ClientProbe *probe, NDhcp4Inco
                 if (r)
                         return r;
 
-                r = n_dhcp4_c_connection_start_request(&probe->connection, request, ns_now);
+                r = n_dhcp4_c_connection_send_request(&probe->connection, request, ns_now);
                 if (r)
                         return r;
                 else
@@ -1332,11 +1332,15 @@ int n_dhcp4_client_probe_release(NDhcp4ClientProbe *probe) {
         _c_cleanup_(n_dhcp4_outgoing_freep) NDhcp4Outgoing *request_out = NULL;
         int r;
 
+        if (probe->connection.state != N_DHCP4_C_CONNECTION_STATE_DRAINING
+                && probe->connection.state != N_DHCP4_C_CONNECTION_STATE_UDP)
+                return -ENOTRECOVERABLE;
+
         r = n_dhcp4_c_connection_release_new(&probe->connection, &request_out, NULL);
         if (r)
                 return r;
 
-        r = n_dhcp4_c_connection_start_request(&probe->connection, request_out, 0);
+        r = n_dhcp4_c_connection_send_request(&probe->connection, request_out, 0);
         if (r)
                 return r;
 
diff --git a/src/n-dhcp4/src/n-dhcp4-private.h b/src/n-dhcp4/src/n-dhcp4-private.h
index 40404001..dbfe9b4a 100644
--- a/src/n-dhcp4/src/n-dhcp4-private.h
+++ b/src/n-dhcp4/src/n-dhcp4-private.h
@@ -642,6 +642,9 @@ int n_dhcp4_c_connection_release_new(NDhcp4CConnection *connection,
 int n_dhcp4_c_connection_start_request(NDhcp4CConnection *connection,
                                        NDhcp4Outgoing *request,
                                        uint64_t timestamp);
+int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection,
+                                      NDhcp4Outgoing *request,
+                                      uint64_t timestamp);
 int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection,
                                         uint64_t timestamp);
 int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection,