about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in30
-rw-r--r--NEWS10
-rwxr-xr-xconfigure28
-rw-r--r--configure.ac4
-rw-r--r--docs/api/html/NetworkManager-dispatcher.html82
-rw-r--r--docs/api/html/NetworkManager.conf.html4
-rw-r--r--docs/api/html/NetworkManager.devhelp21
-rw-r--r--docs/api/html/index.html2
-rw-r--r--docs/api/html/ix01.html20
-rw-r--r--docs/api/html/nm-dbus-types.html17
-rw-r--r--docs/api/html/nm-settings-dbus.html60
-rw-r--r--docs/api/html/nm-settings-nmcli.html152
-rw-r--r--docs/api/html/settings-connection.html4
-rw-r--r--docs/api/html/settings-generic.html11
-rw-r--r--docs/api/html/settings-macsec.html12
-rw-r--r--docs/api/html/settings-sriov.html28
-rw-r--r--docs/api/settings-spec.xml28
-rw-r--r--docs/api/version.xml2
-rw-r--r--docs/libnm/html/NMSetting.html49
-rw-r--r--docs/libnm/html/NMSettingGeneric.html56
-rw-r--r--docs/libnm/html/NMSettingMacsec.html95
-rw-r--r--docs/libnm/html/NMSettingSriov.html298
-rw-r--r--docs/libnm/html/api-index-full.html92
-rw-r--r--docs/libnm/html/index.html2
-rw-r--r--docs/libnm/html/libnm-nm-dbus-interface.html38
-rw-r--r--docs/libnm/html/libnm-nm-version-macros.html4
-rw-r--r--docs/libnm/html/libnm.devhelp237
-rw-r--r--docs/libnm/html/object-tree.html4
-rw-r--r--docs/libnm/html/usage.html2
-rw-r--r--docs/libnm/libnm-sections.txt26
-rw-r--r--docs/libnm/libnm.types4
-rw-r--r--docs/libnm/version.xml2
-rw-r--r--man/NetworkManager-dispatcher.8105
-rw-r--r--man/NetworkManager-dispatcher.xml84
-rw-r--r--man/NetworkManager-wait-online.service.84
-rw-r--r--man/NetworkManager.86
-rw-r--r--man/NetworkManager.conf.510
-rw-r--r--man/NetworkManager.conf.xml3
-rw-r--r--man/nm-cloud-setup.86
-rw-r--r--man/nm-initrd-generator.86
-rw-r--r--man/nm-online.16
-rw-r--r--man/nm-openvswitch.76
-rw-r--r--man/nm-settings-dbus.581
-rw-r--r--man/nm-settings-dbus.xml30
-rw-r--r--man/nm-settings-ifcfg-rh.56
-rw-r--r--man/nm-settings-ifcfg-rh.xml2
-rw-r--r--man/nm-settings-keyfile.56
-rw-r--r--man/nm-settings-keyfile.xml2
-rw-r--r--man/nm-settings-nmcli.574
-rw-r--r--man/nm-settings-nmcli.xml19
-rw-r--r--man/nmcli-examples.76
-rw-r--r--man/nmcli.16
-rw-r--r--man/nmtui.16
-rw-r--r--meson.build2
-rw-r--r--po/NetworkManager.pot1417
-rw-r--r--src/core/devices/nm-device-factory.c17
-rw-r--r--src/core/devices/nm-device-factory.h2
-rw-r--r--src/core/devices/nm-device-generic.c343
-rw-r--r--src/core/devices/nm-device-generic.h3
-rw-r--r--src/core/devices/nm-device-macsec.c17
-rw-r--r--src/core/devices/nm-device-utils.c4
-rw-r--r--src/core/devices/nm-device.c62
-rw-r--r--src/core/dhcp/nm-dhcp-client.c6
-rw-r--r--src/core/ndisc/nm-ndisc.c10
-rw-r--r--src/core/nm-config.c29
-rw-r--r--src/core/nm-config.h5
-rw-r--r--src/core/nm-dispatcher.c677
-rw-r--r--src/core/nm-dispatcher.h16
-rw-r--r--src/core/nm-manager.c18
-rw-r--r--src/core/platform/tests/test-link.c12
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c2
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c109
-rw-r--r--src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c2
-rw-r--r--src/core/supplicant/nm-supplicant-config.c30
-rw-r--r--src/core/supplicant/nm-supplicant-config.h7
-rw-r--r--src/core/supplicant/nm-supplicant-settings-verify.c1
-rw-r--r--src/libnm-base/nm-base.h29
-rw-r--r--src/libnm-client-impl/libnm.ver10
-rw-r--r--src/libnm-core-aux-extern/nm-dispatcher-api.h2
-rw-r--r--src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in22
-rw-r--r--src/libnm-core-impl/nm-connection.c7
-rw-r--r--src/libnm-core-impl/nm-setting-connection.c22
-rw-r--r--src/libnm-core-impl/nm-setting-generic.c128
-rw-r--r--src/libnm-core-impl/nm-setting-ip-config.c6
-rw-r--r--src/libnm-core-impl/nm-setting-ip6-config.c22
-rw-r--r--src/libnm-core-impl/nm-setting-macsec.c49
-rw-r--r--src/libnm-core-impl/nm-setting-private.h96
-rw-r--r--src/libnm-core-impl/nm-setting-sriov.c133
-rw-r--r--src/libnm-core-impl/nm-setting-wireguard.c3
-rw-r--r--src/libnm-core-impl/nm-setting.c153
-rw-r--r--src/libnm-core-impl/tests/test-setting.c37
-rw-r--r--src/libnm-core-intern/nm-core-internal.h8
-rw-r--r--src/libnm-core-public/nm-dbus-interface.h20
-rw-r--r--src/libnm-core-public/nm-dbus-types.xml5
-rw-r--r--src/libnm-core-public/nm-setting-generic.h5
-rw-r--r--src/libnm-core-public/nm-setting-macsec.h21
-rw-r--r--src/libnm-core-public/nm-setting-sriov.h64
-rw-r--r--src/libnm-core-public/nm-setting.h3
-rw-r--r--src/libnm-core-public/nm-version-macros.h4
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.c111
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h5
-rw-r--r--src/libnm-platform/devlink/nm-devlink.c365
-rw-r--r--src/libnm-platform/devlink/nm-devlink.h30
-rw-r--r--src/libnm-platform/meson.build1
-rw-r--r--src/libnm-platform/nm-linux-platform.c440
-rw-r--r--src/libnm-platform/nm-platform.c19
-rw-r--r--src/libnm-platform/nm-platform.h15
-rw-r--r--src/libnmc-base/nm-client-utils.c4
-rw-r--r--src/libnmc-base/nm-secret-agent-simple.c63
-rw-r--r--src/libnmc-base/nm-secret-agent-simple.h1
-rw-r--r--src/libnmc-setting/nm-meta-setting-desc.c86
-rw-r--r--src/libnmc-setting/settings-docs.h5
-rw-r--r--src/libnmc-setting/settings-docs.h.in5
-rw-r--r--src/nm-dispatcher/nm-dispatcher-utils.c30
-rw-r--r--src/nm-dispatcher/nm-dispatcher.c527
-rw-r--r--src/nmcli/common.c2
-rw-r--r--src/nmcli/connections.c22
-rw-r--r--src/nmcli/gen-metadata-nm-settings-nmcli.xml.in19
-rw-r--r--src/nmtui/nmt-page-bridge.c2
-rw-r--r--src/nmtui/nmt-password-dialog.c2
121 files changed, 5496 insertions, 1578 deletions
diff --git a/Makefile.am b/Makefile.am
index 833e8046..1948fcc1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -672,6 +672,8 @@ src_libnm_platform_libnm_platform_la_SOURCES = \
 	src/libnm-platform/nmp-object.h \
 	src/libnm-platform/nmp-plobj.c \
 	src/libnm-platform/nmp-plobj.h \
+	src/libnm-platform/devlink/nm-devlink.c \
+	src/libnm-platform/devlink/nm-devlink.h \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.c \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.h \
 	src/libnm-platform/wifi/nm-wifi-utils-private.h \
diff --git a/Makefile.in b/Makefile.in
index 0ac8d211..ce9b8030 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1496,6 +1496,8 @@ am__src_libnm_platform_libnm_platform_la_SOURCES_DIST =  \
 	src/libnm-platform/nmp-object.c \
 	src/libnm-platform/nmp-object.h src/libnm-platform/nmp-plobj.c \
 	src/libnm-platform/nmp-plobj.h \
+	src/libnm-platform/devlink/nm-devlink.c \
+	src/libnm-platform/devlink/nm-devlink.h \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.c \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.h \
 	src/libnm-platform/wifi/nm-wifi-utils-private.h \
@@ -1516,6 +1518,7 @@ am_src_libnm_platform_libnm_platform_la_OBJECTS =  \
 	src/libnm-platform/libnm_platform_la-nmp-netns.lo \
 	src/libnm-platform/libnm_platform_la-nmp-object.lo \
 	src/libnm-platform/libnm_platform_la-nmp-plobj.lo \
+	src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo \
 	src/libnm-platform/wifi/libnm_platform_la-nm-wifi-utils-nl80211.lo \
 	src/libnm-platform/wifi/libnm_platform_la-nm-wifi-utils.lo \
 	src/libnm-platform/wpan/libnm_platform_la-nm-wpan-utils.lo \
@@ -3159,6 +3162,7 @@ am__depfiles_remade = examples/C/glib/$(DEPDIR)/add_connection_gdbus-add-connect
 	src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-netns.Plo \
 	src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-object.Plo \
 	src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-plobj.Plo \
+	src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Plo \
 	src/libnm-platform/tests/$(DEPDIR)/test_nm_platform-test-nm-platform.Po \
 	src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Plo \
 	src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-wext.Plo \
@@ -5673,6 +5677,8 @@ src_libnm_platform_libnm_platform_la_SOURCES =  \
 	src/libnm-platform/nmp-object.c \
 	src/libnm-platform/nmp-object.h src/libnm-platform/nmp-plobj.c \
 	src/libnm-platform/nmp-plobj.h \
+	src/libnm-platform/devlink/nm-devlink.c \
+	src/libnm-platform/devlink/nm-devlink.h \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.c \
 	src/libnm-platform/wifi/nm-wifi-utils-nl80211.h \
 	src/libnm-platform/wifi/nm-wifi-utils-private.h \
@@ -10652,6 +10658,15 @@ src/libnm-platform/libnm_platform_la-nmp-object.lo:  \
 src/libnm-platform/libnm_platform_la-nmp-plobj.lo:  \
 	src/libnm-platform/$(am__dirstamp) \
 	src/libnm-platform/$(DEPDIR)/$(am__dirstamp)
+src/libnm-platform/devlink/$(am__dirstamp):
+	@$(MKDIR_P) src/libnm-platform/devlink
+	@: > src/libnm-platform/devlink/$(am__dirstamp)
+src/libnm-platform/devlink/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) src/libnm-platform/devlink/$(DEPDIR)
+	@: > src/libnm-platform/devlink/$(DEPDIR)/$(am__dirstamp)
+src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo:  \
+	src/libnm-platform/devlink/$(am__dirstamp) \
+	src/libnm-platform/devlink/$(DEPDIR)/$(am__dirstamp)
 src/libnm-platform/wifi/$(am__dirstamp):
 	@$(MKDIR_P) src/libnm-platform/wifi
 	@: > src/libnm-platform/wifi/$(am__dirstamp)
@@ -12060,6 +12075,8 @@ mostlyclean-compile:
 	-rm -f src/libnm-log-null/*.lo
 	-rm -f src/libnm-platform/*.$(OBJEXT)
 	-rm -f src/libnm-platform/*.lo
+	-rm -f src/libnm-platform/devlink/*.$(OBJEXT)
+	-rm -f src/libnm-platform/devlink/*.lo
 	-rm -f src/libnm-platform/tests/*.$(OBJEXT)
 	-rm -f src/libnm-platform/wifi/*.$(OBJEXT)
 	-rm -f src/libnm-platform/wifi/*.lo
@@ -12555,6 +12572,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-netns.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-object.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-plobj.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/tests/$(DEPDIR)/test_nm_platform-test-nm-platform.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-wext.Plo@am__quote@ # am--include-marker
@@ -15741,6 +15759,13 @@ src/libnm-platform/libnm_platform_la-nmp-plobj.lo: src/libnm-platform/nmp-plobj.
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libnm_platform_libnm_platform_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/libnm-platform/libnm_platform_la-nmp-plobj.lo `test -f 'src/libnm-platform/nmp-plobj.c' || echo '$(srcdir)/'`src/libnm-platform/nmp-plobj.c
 
+src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo: src/libnm-platform/devlink/nm-devlink.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libnm_platform_libnm_platform_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo -MD -MP -MF src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Tpo -c -o src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo `test -f 'src/libnm-platform/devlink/nm-devlink.c' || echo '$(srcdir)/'`src/libnm-platform/devlink/nm-devlink.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Tpo src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='src/libnm-platform/devlink/nm-devlink.c' object='src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libnm_platform_libnm_platform_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/libnm-platform/devlink/libnm_platform_la-nm-devlink.lo `test -f 'src/libnm-platform/devlink/nm-devlink.c' || echo '$(srcdir)/'`src/libnm-platform/devlink/nm-devlink.c
+
 src/libnm-platform/wifi/libnm_platform_la-nm-wifi-utils-nl80211.lo: src/libnm-platform/wifi/nm-wifi-utils-nl80211.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_libnm_platform_libnm_platform_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/libnm-platform/wifi/libnm_platform_la-nm-wifi-utils-nl80211.lo -MD -MP -MF src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Tpo -c -o src/libnm-platform/wifi/libnm_platform_la-nm-wifi-utils-nl80211.lo `test -f 'src/libnm-platform/wifi/nm-wifi-utils-nl80211.c' || echo '$(srcdir)/'`src/libnm-platform/wifi/nm-wifi-utils-nl80211.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Tpo src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Plo
@@ -18387,6 +18412,7 @@ clean-libtool:
 	-rm -rf src/libnm-log-core/.libs src/libnm-log-core/_libs
 	-rm -rf src/libnm-log-null/.libs src/libnm-log-null/_libs
 	-rm -rf src/libnm-platform/.libs src/libnm-platform/_libs
+	-rm -rf src/libnm-platform/devlink/.libs src/libnm-platform/devlink/_libs
 	-rm -rf src/libnm-platform/tests/.libs src/libnm-platform/tests/_libs
 	-rm -rf src/libnm-platform/wifi/.libs src/libnm-platform/wifi/_libs
 	-rm -rf src/libnm-platform/wpan/.libs src/libnm-platform/wpan/_libs
@@ -19921,6 +19947,8 @@ distclean-generic:
 	-rm -f src/libnm-log-null/$(am__dirstamp)
 	-rm -f src/libnm-platform/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/libnm-platform/$(am__dirstamp)
+	-rm -f src/libnm-platform/devlink/$(DEPDIR)/$(am__dirstamp)
+	-rm -f src/libnm-platform/devlink/$(am__dirstamp)
 	-rm -f src/libnm-platform/tests/$(DEPDIR)/$(am__dirstamp)
 	-rm -f src/libnm-platform/tests/$(am__dirstamp)
 	-rm -f src/libnm-platform/wifi/$(DEPDIR)/$(am__dirstamp)
@@ -20442,6 +20470,7 @@ distclean: distclean-recursive
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-netns.Plo
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-object.Plo
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-plobj.Plo
+	-rm -f src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Plo
 	-rm -f src/libnm-platform/tests/$(DEPDIR)/test_nm_platform-test-nm-platform.Po
 	-rm -f src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Plo
 	-rm -f src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-wext.Plo
@@ -21125,6 +21154,7 @@ maintainer-clean: maintainer-clean-recursive
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-netns.Plo
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-object.Plo
 	-rm -f src/libnm-platform/$(DEPDIR)/libnm_platform_la-nmp-plobj.Plo
+	-rm -f src/libnm-platform/devlink/$(DEPDIR)/libnm_platform_la-nm-devlink.Plo
 	-rm -f src/libnm-platform/tests/$(DEPDIR)/test_nm_platform-test-nm-platform.Po
 	-rm -f src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-nl80211.Plo
 	-rm -f src/libnm-platform/wifi/$(DEPDIR)/libnm_platform_la-nm-wifi-utils-wext.Plo
diff --git a/NEWS b/NEWS
index 01138b58..6ac3118d 100644
--- a/NEWS
+++ b/NEWS
@@ -36,8 +36,8 @@ Overview of changes since NetworkManager-1.44
 * Support Ethtool EEE (Energy Efficient Ethernet) settings.
 * Add options to prevent edns0 and trust-ad being automatically added to DNS
   configuration.
-* Implement fwmark property for IP tunnels
-* Add support to HSR/PRP interfaces
+* Implement fwmark property for IP tunnels.
+* Add support to HSR/PRP interfaces.
 * Deprecated connection.* properties master, slave-type, autoconnect-slaves
 * Allow configuring static routes also when addresses is empty.
 * VPN: accept pref-src for IPv6 routes from VPN plugins.
@@ -45,6 +45,12 @@ Overview of changes since NetworkManager-1.44
 * Support modifying the DSCP header field for DHCP packets, and change the
   default to CS0.
 * Enable IPv4 DAD (Duplicate Address Detection) by default.
+* vpn: support 2FA authentication from VPN plugins.
+* nmtui: allow adding a bond as bridge port.
+* sriov: add support to configure the NIC's eswitch settings via Devlink.
+* ndisc: fix IPv6 address lifetimes computation.
+* Support the MACsec offload mode.
+* Support creating generic devices via external "device-handler" dispatcher.
 * Documentation improvements.
 * Many internal improvements and bug fixes.
 
diff --git a/configure b/configure
index f343607d..cf24cb99 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for NetworkManager 1.45.91.
+# Generated by GNU Autoconf 2.71 for NetworkManager 1.46.0.
 #
 # Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager>.
 #
@@ -622,8 +622,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='NetworkManager'
 PACKAGE_TARNAME='NetworkManager'
-PACKAGE_VERSION='1.45.91'
-PACKAGE_STRING='NetworkManager 1.45.91'
+PACKAGE_VERSION='1.46.0'
+PACKAGE_STRING='NetworkManager 1.46.0'
 PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=NetworkManager'
 PACKAGE_URL=''
 
@@ -1744,7 +1744,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures NetworkManager 1.45.91 to adapt to many kinds of systems.
+\`configure' configures NetworkManager 1.46.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1816,7 +1816,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of NetworkManager 1.45.91:";;
+     short | recursive ) echo "Configuration of NetworkManager 1.46.0:";;
    esac
   cat <<\_ACEOF
 
@@ -2172,7 +2172,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-NetworkManager configure 1.45.91
+NetworkManager configure 1.46.0
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -2893,7 +2893,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by NetworkManager $as_me 1.45.91, which was
+It was created by NetworkManager $as_me 1.46.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4389,7 +4389,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='NetworkManager'
- VERSION='1.45.91'
+ VERSION='1.46.0'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -19297,9 +19297,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 NM_MAJOR_VERSION=1
-NM_MINOR_VERSION=45
-NM_MICRO_VERSION=91
-NM_VERSION=1.45.91
+NM_MINOR_VERSION=46
+NM_MICRO_VERSION=0
+NM_VERSION=1.46.0
 
 
 
@@ -19307,7 +19307,7 @@ NM_VERSION=1.45.91
 
 
 
-NM_GIT_SHA=87764094834398d7a3196e10a7bfb0441cdbd14b
+NM_GIT_SHA=e39f48a30a2ef7b445276a859bbd5255e4c5071d
 
 if test """" != "no-config-h" ; then
 
@@ -32687,7 +32687,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by NetworkManager $as_me 1.45.91, which was
+This file was extended by NetworkManager $as_me 1.46.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -32755,7 +32755,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-NetworkManager config.status 1.45.91
+NetworkManager config.status 1.46.0
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 9b594e41..9bc5dc51 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,8 +7,8 @@ dnl  - add corresponding NM_VERSION_x_y_z macros in
 dnl    "shared/nm-version-macros.h.in"
 dnl  - update number in meson.build
 m4_define([nm_major_version], [1])
-m4_define([nm_minor_version], [45])
-m4_define([nm_micro_version], [91])
+m4_define([nm_minor_version], [46])
+m4_define([nm_micro_version], [0])
 m4_define([nm_version],
           [nm_major_version.nm_minor_version.nm_micro_version])
 
diff --git a/docs/api/html/NetworkManager-dispatcher.html b/docs/api/html/NetworkManager-dispatcher.html
index b8ef62c3..cf1c55dd 100644
--- a/docs/api/html/NetworkManager-dispatcher.html
+++ b/docs/api/html/NetworkManager-dispatcher.html
@@ -169,6 +169,69 @@
             looking at file <code class="filename">/run/NetworkManager/resolv.conf</code>
         </p></td>
 </tr>
+<tr>
+<td><p><span class="term"><code class="varname">device-add</code></span></p></td>
+<td>
+<p>
+            This action is called when a connection of type <code class="literal">generic</code>
+            has the <code class="literal">generic.device-handler</code> property set. The property
+            indicates the name of a dispatcher script to be executed in directory
+            <code class="filename">/{etc,usr/lib}/NetworkManager/dispatcher.d/device</code>. Note
+            that differently from other actions, only one script is executed.
+          </p>
+<p>
+            The script needs to perform any action needed to create the device
+            for the generic connection. On successful termination, the script
+            returns zero. Otherwise, it returns a non-zero value to indicate an
+            error. The script can return values to NetworkManager by writing to
+            standard output; each line should contain a key name followed by the
+            equal sign '=' and a key value. The keys understood at the moment
+            are:
+            </p>
+<div class="variablelist"><table border="0" class="variablelist">
+<colgroup>
+<col align="left" valign="top">
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td><p><span class="term"><code class="varname">IFINDEX</code></span></p></td>
+<td><p> Indicates the interface index of the interface
+                created by the script. This key is required when the script
+                succeeds; if it is not set, the activation will fail. The key is
+                ignored in case of script failure. </p></td>
+</tr>
+<tr>
+<td><p><span class="term"><code class="varname">ERROR</code></span></p></td>
+<td><p> Specifies an error message indicating the cause
+                of the script failure. It is ignored when the script succeeds.
+                </p></td>
+</tr>
+</tbody>
+</table></div>
+<p>
+            Since the dispatcher service captures stdout for parsing those keys,
+            anything written to stdout will not appear in the dispatcher service
+            journal log. Use stderr if you want to print messages to the journal
+            (for example, for debugging). Only the first 8KiB of stdout are
+            considered and among those, only the first 64 lines; the rest is
+            ignored.
+          </p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><code class="varname">device-delete</code></span></p></td>
+<td><p>
+            This action is the counterpart of <code class="literal">device-add</code> and
+            is called to delete the device for a generic connection. All the
+            aspects described for <code class="literal">device-add</code> also apply to
+            this action, with the only exception that key
+            <code class="varname">IFINDEX</code> is ignored. It is not necessary to delete
+            the kernel link in the handler because NetworkManager already does
+            that; therefore the action is useful for any additional cleanup
+            needed.
+          </p></td>
+</tr>
 </tbody>
 </table></div>
 <p>
@@ -315,6 +378,25 @@
       exported too, like VPN_IP4_ADDRESS_0, VPN_IP4_NUM_ADDRESSES.
     </p>
 <p>
+      The content of the <code class="literal">user</code> setting for the connection
+      being activated is also passed via environment variables. Each key is
+      stored in a variable with name <code class="literal">CONNECTION_USER_</code>
+      concatenated with the encoding of the key name. The encoding works as
+      follows:
+      </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p>lowercase letters become uppercase</p></li>
+<li class="listitem"><p>uppercase letters are prefixed with an underscore</p></li>
+<li class="listitem"><p>numbers do not change</p></li>
+<li class="listitem"><p>a dot is replaced with a double underscore</p></li>
+<li class="listitem"><p>any other character is encoded with an underscore followed by
+          its 3-digit octal representation</p></li>
+</ul></div>
+<p>
+      For example, key <code class="literal">test.foo-Bar2</code> is stored in a variable named
+      <code class="literal">CONNECTION_USER_TEST__FOO_055_BAR2</code>.
+    </p>
+<p>
       Dispatcher scripts are run one at a time, but asynchronously from the main
       NetworkManager process, and will be killed if they run for too long. If your script
       might take arbitrarily long to complete, you should spawn a child process and have the
diff --git a/docs/api/html/NetworkManager.conf.html b/docs/api/html/NetworkManager.conf.html
index 67aa539e..aee3ac66 100644
--- a/docs/api/html/NetworkManager.conf.html
+++ b/docs/api/html/NetworkManager.conf.html
@@ -995,6 +995,10 @@ ipv6.ip6-privacy=0
 <td><p>If configured explicitly to 0, the MTU is not reconfigured during device activation unless it is required due to IPv6 constraints. If left unspecified, a DHCP/IPv6 SLAAC provided value is used or the MTU is left unspecified on activation.</p></td>
 </tr>
 <tr>
+<td><p><span class="term"><code class="varname">macsec.offload</code></span></p></td>
+<td></td>
+</tr>
+<tr>
 <td><p><span class="term"><code class="varname">sriov.autoprobe-drivers</code></span></p></td>
 <td><p>If left unspecified, drivers are autoprobed when the SR-IOV VF gets created.</p></td>
 </tr>
diff --git a/docs/api/html/NetworkManager.devhelp2 b/docs/api/html/NetworkManager.devhelp2
index 252bb748..6e0036ab 100644
--- a/docs/api/html/NetworkManager.devhelp2
+++ b/docs/api/html/NetworkManager.devhelp2
@@ -746,6 +746,7 @@
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.17.4.2.1.4.66.1.1id-1.4.17.2.17.4.2.1.4.66.1.2"/>
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.17.4.2.1.4.67.1.1id-1.4.17.2.17.4.2.1.4.67.1.2"/>
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_PEER_NOT_FOUND" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.17.4.2.1.4.68.1.1id-1.4.17.2.17.4.2.1.4.68.1.2"/>
+    <keyword type="constant" name="NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.17.4.2.1.4.69.1.1id-1.4.17.2.17.4.2.1.4.69.1.2"/>
     <keyword type="constant" name="NM_METERED_UNKNOWN" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.18.4.2.1.4.1.1.1id-1.4.17.2.18.4.2.1.4.1.1.2"/>
     <keyword type="constant" name="NM_METERED_YES" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.18.4.2.1.4.2.1.1id-1.4.17.2.18.4.2.1.4.2.1.2"/>
     <keyword type="constant" name="NM_METERED_NO" link="nm-dbus-types.htmlnm-dbus-types.html#id-1.4.17.2.18.4.2.1.4.3.1.1id-1.4.17.2.18.4.2.1.4.3.1.2"/>
diff --git a/docs/api/html/index.html b/docs/api/html/index.html
index e015aaca..f43e0514 100644
--- a/docs/api/html/index.html
+++ b/docs/api/html/index.html
@@ -16,7 +16,7 @@
 <div>
 <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">NetworkManager Reference Manual</p></th></tr></table></div>
 <div><p class="releaseinfo">
-      for NetworkManager 1.45.91
+      for NetworkManager 1.46.0
 
       The latest version of this documentation can be found on-line at
       <a class="ulink" href="https://networkmanager.dev/docs/api/latest/" target="_top">https://networkmanager.dev/docs/api/latest/</a>.
diff --git a/docs/api/html/ix01.html b/docs/api/html/ix01.html
index 04d94335..6dc24c5d 100644
--- a/docs/api/html/ix01.html
+++ b/docs/api/html/ix01.html
@@ -700,6 +700,8 @@
 </dt>
 <dt id="ientry-id-1.3.3.25.2.2.1.1.2.1.1.1.1">devargs, <a class="indexterm" href="settings-ovs-dpdk.html">ovs-dpdk</a>
 </dt>
+<dt id="ientry-id-1.3.3.14.2.2.1.1.2.1.1.1.1">device-handler, <a class="indexterm" href="settings-generic.html">generic</a>
+</dt>
 <dt id="ientry-id-1.3.3.15.2.2.1.1.2.3.1.1.1">device-id, <a class="indexterm" href="settings-gsm.html">gsm</a>
 </dt>
 <dt id="ientry-id-1.4.8.31.1.2">org.freedesktop.NetworkManager.Device.Wired, <a class="indexterm" href="gdbus-org.freedesktop.NetworkManager.Device.Wired.html#gdbus-interface-org-freedesktop-NetworkManager-Device-Wired.top_of_page">org.freedesktop.NetworkManager.Device.Wired</a>
@@ -825,6 +827,12 @@
 </dt>
 <dt id="ientry-id-1.3.3.20.2.2.1.1.2.1.1.1.1">encrypt, <a class="indexterm" href="settings-macsec.html">macsec</a>
 </dt>
+<dt id="ientry-id-1.3.3.33.2.2.1.1.2.2.1.1.1">eswitch-encap-mode, <a class="indexterm" href="settings-sriov.html">sriov</a>
+</dt>
+<dt id="ientry-id-1.3.3.33.2.2.1.1.2.3.1.1.1">eswitch-inline-mode, <a class="indexterm" href="settings-sriov.html">sriov</a>
+</dt>
+<dt id="ientry-id-1.3.3.33.2.2.1.1.2.4.1.1.1">eswitch-mode, <a class="indexterm" href="settings-sriov.html">sriov</a>
+</dt>
 </dl>
 </div>
 <div class="indexdiv">
@@ -1256,6 +1264,8 @@
 <div class="indexdiv">
 <h3>O</h3>
 <dl>
+<dt id="ientry-id-1.3.3.20.2.2.1.1.2.6.1.1.1">offload, <a class="indexterm" href="settings-macsec.html">macsec</a>
+</dt>
 <dt id="ientry-id-1.3.3.26.2.2.1.1.2.1.1.1.1">ofport-request, <a class="indexterm" href="settings-ovs-interface.html">ovs-interface</a>
 </dt>
 <dt id="ientry-id-1.3.3.51.2.2.1.1.2.3.1.1.1">only-from-default, <a class="indexterm" href="settings-hostname.html">hostname</a>
@@ -1363,7 +1373,7 @@
 </dt>
 <dt id="ientry-id-1.3.3.48.2.2.1.1.2.9.1.1.1">pmf, <a class="indexterm" href="settings-802-11-wireless-security.html">802-11-wireless-security</a>
 </dt>
-<dt id="ientry-id-1.3.3.20.2.2.1.1.2.7.1.1.1">port, <a class="indexterm" href="settings-macsec.html">macsec</a>, <a class="indexterm" href="settings-802-3-ethernet.html">802-3-ethernet</a>
+<dt id="ientry-id-1.3.3.20.2.2.1.1.2.8.1.1.1">port, <a class="indexterm" href="settings-macsec.html">macsec</a>, <a class="indexterm" href="settings-802-3-ethernet.html">802-3-ethernet</a>
 </dt>
 <dt id="ientry-id-1.3.3.2.2.2.1.1.2.21.1.1.1">port-type, <a class="indexterm" href="settings-connection.html">connection</a>
 </dt>
@@ -1522,7 +1532,7 @@
 </dt>
 <dt id="ientry-id-1.3.3.32.2.2.1.1.2.4.1.1.1">send-delay, <a class="indexterm" href="settings-serial.html">serial</a>
 </dt>
-<dt id="ientry-id-1.3.3.20.2.2.1.1.2.8.1.1.1">send-sci, <a class="indexterm" href="settings-macsec.html">macsec</a>
+<dt id="ientry-id-1.3.3.20.2.2.1.1.2.9.1.1.1">send-sci, <a class="indexterm" href="settings-macsec.html">macsec</a>
 </dt>
 <dt id="ientry-id-1.3.3.30.2.2.1.1.2.4.1.1.1">service, <a class="indexterm" href="settings-pppoe.html">pppoe</a>
 </dt>
@@ -1579,7 +1589,7 @@
 </dt>
 <dt id="ientry-id-1.3.3.19.2.2.1.1.2.13.1.1.1">tos, <a class="indexterm" href="settings-ip-tunnel.html">ip-tunnel</a>, <a class="indexterm" href="settings-vxlan.html">vxlan</a>
 </dt>
-<dt id="ientry-id-1.3.3.33.2.2.1.1.2.2.1.1.1">total-vfs, <a class="indexterm" href="settings-sriov.html">sriov</a>
+<dt id="ientry-id-1.3.3.33.2.2.1.1.2.5.1.1.1">total-vfs, <a class="indexterm" href="settings-sriov.html">sriov</a>
 </dt>
 <dt id="ientry-id-1.3.3.16.2.2.1.1.2.5.1.1.1">transport-mode, <a class="indexterm" href="settings-infiniband.html">infiniband</a>
 </dt>
@@ -1609,11 +1619,11 @@
 <div class="indexdiv">
 <h3>V</h3>
 <dl>
-<dt id="ientry-id-1.3.3.20.2.2.1.1.2.9.1.1.1">validation, <a class="indexterm" href="settings-macsec.html">macsec</a>
+<dt id="ientry-id-1.3.3.20.2.2.1.1.2.10.1.1.1">validation, <a class="indexterm" href="settings-macsec.html">macsec</a>
 </dt>
 <dt id="ientry-id-1.3.3.5.2.2.1.1.2.6.1.1.1">vci, <a class="indexterm" href="settings-adsl.html">adsl</a>
 </dt>
-<dt id="ientry-id-1.3.3.33.2.2.1.1.2.3.1.1.1">vfs, <a class="indexterm" href="settings-sriov.html">sriov</a>
+<dt id="ientry-id-1.3.3.33.2.2.1.1.2.6.1.1.1">vfs, <a class="indexterm" href="settings-sriov.html">sriov</a>
 </dt>
 <dt id="ientry-id-1.3.3.8.2.2.1.1.2.24.1.1.1">vlan-default-pvid, <a class="indexterm" href="settings-bridge.html">bridge</a>
 </dt>
diff --git a/docs/api/html/nm-dbus-types.html b/docs/api/html/nm-dbus-types.html
index c59dfbb2..96afcda9 100644
--- a/docs/api/html/nm-dbus-types.html
+++ b/docs/api/html/nm-dbus-types.html
@@ -3129,6 +3129,21 @@
 </td>
 <td class="auto-generated"> </td>
 </tr>
+<tr>
+<td class="enum_member_name">
+<p>NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED</p>
+<p></p>
+</td>
+<td class="enum_member_value">
+<p>= <code class="literal">68</code></p>
+<p></p>
+</td>
+<td class="enum_member_description">
+<p>The device handler dispatcher returned an error. Since: 1.46</p>
+<p></p>
+</td>
+<td class="auto-generated"> </td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -3136,7 +3151,7 @@
 <hr>
 <div class="refsect2">
 <a name="NMMetered"></a><h3>enum NMMetered</h3>
-<p>The NMMetered enum has two different purposes: one is to configure "connection.metered" setting of a connection profile in NMSettingConnection, and the other is to express the actual metered state of the <a href="/usr/share/gtk-doc/html/libnm/NMDevice.html#NMDevice-struct">NMDevice</a> at a given moment.</p>
+<p>The NMMetered enum has two different purposes: one is to configure "connection.metered" setting of a connection profile in NMSettingConnection, and the other is to express the actual metered state of the NMDevice at a given moment.</p>
 <p>For the connection profile only NM_METERED_UNKNOWN, NM_METERED_NO and NM_METERED_YES are allowed.</p>
 <p>The device's metered state at runtime is determined by the profile which is currently active. If the profile explicitly specifies NM_METERED_NO or NM_METERED_YES, then the device's metered state is as such. If the connection profile leaves it undecided at NM_METERED_UNKNOWN (the default), then NetworkManager tries to guess the metered state, for example based on the device type or on DHCP options (like Android devices exposing a "ANDROID_METERED" DHCP vendor option). This then leads to either NM_METERED_GUESS_NO or NM_METERED_GUESS_YES.</p>
 <p>Most applications probably should treat the runtime state NM_METERED_GUESS_YES like NM_METERED_YES, and all other states as not metered.</p>
diff --git a/docs/api/html/nm-settings-dbus.html b/docs/api/html/nm-settings-dbus.html
index 9f5c9842..52539c2e 100644
--- a/docs/api/html/nm-settings-dbus.html
+++ b/docs/api/html/nm-settings-dbus.html
@@ -137,8 +137,8 @@ Depending on "connection.multi-connect", a profile can (auto)connect only once a
 <tr>
 <td align="left">
 <a name="nm-settings-dbus.property.connection.autoconnect-ports"></a>autoconnect-ports</td>
-<td align="left">NMTernary (int32)</td>
-<td align="left"> </td>
+<td align="left">int32</td>
+<td align="left">-1</td>
 <td>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</td>
 </tr>
 <tr>
@@ -1475,7 +1475,17 @@ Since 1.34, NULL is the default and means "fabric". Before 1.34, NULL was reject
 <th>Default Value</th>
 <th>Value Description</th>
 </tr></thead>
-<tbody></tbody>
+<tbody><tr>
+<td align="left">
+<a name="nm-settings-dbus.property.generic.device-handler"></a>device-handler</td>
+<td align="left">string</td>
+<td align="left"> </td>
+<td>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.
+
+See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.
+
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</td>
+</tr></tbody>
 </table></div>
 </div>
 <hr>
@@ -2570,6 +2580,19 @@ When set, the token is used as IPv6 interface identifier instead of the hardware
 </tr>
 <tr>
 <td align="left">
+<a name="nm-settings-dbus.property.macsec.offload"></a>offload</td>
+<td align="left">int32</td>
+<td align="left">-1</td>
+<td>Specifies the MACsec offload mode.
+
+0 (off) disables MACsec offload.
+
+1 (phy) and 2 (mac) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.
+
+-1 (default) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is 0 (off).</td>
+</tr>
+<tr>
+<td align="left">
 <a name="nm-settings-dbus.property.macsec.parent"></a>parent</td>
 <td align="left">string</td>
 <td align="left"> </td>
@@ -3334,6 +3357,37 @@ When set to -1 (default), the global default is used; in case the global default
 </tr>
 <tr>
 <td align="left">
+<a name="nm-settings-dbus.property.sriov.eswitch-encap-mode"></a>eswitch-encap-mode</td>
+<td align="left">int32</td>
+<td align="left">-1</td>
+<td>Select the eswitch encapsulation support.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch encap-mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
+<td align="left">
+<a name="nm-settings-dbus.property.sriov.eswitch-inline-mode"></a>eswitch-inline-mode</td>
+<td align="left">int32</td>
+<td align="left">-1</td>
+<td>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch inline-mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
+<td align="left">
+<a name="nm-settings-dbus.property.sriov.eswitch-mode"></a>eswitch-mode</td>
+<td align="left">int32</td>
+<td align="left">-1</td>
+<td>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
+<td align="left">
 <a name="nm-settings-dbus.property.sriov.total-vfs"></a>total-vfs</td>
 <td align="left">uint32</td>
 <td align="left">0</td>
diff --git a/docs/api/html/nm-settings-nmcli.html b/docs/api/html/nm-settings-nmcli.html
index 84406d4a..9d266d92 100644
--- a/docs/api/html/nm-settings-nmcli.html
+++ b/docs/api/html/nm-settings-nmcli.html
@@ -2488,7 +2488,31 @@
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.18"></a><h3>gsm setting</h3>
+<a name="id-1.2.10.4.18"></a><h3>generic setting</h3>
+<p>Generic Link Settings.</p>
+<p>
+        Properties:
+        </p>
+<div class="variablelist"><table border="0" class="variablelist">
+<colgroup>
+<col align="left" valign="top">
+<col>
+</colgroup>
+<tbody><tr>
+<td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.generic.device-handler"></a>generic.device-handler</code></span></p></td>
+<td>
+<p>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.</p>
+<p>See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.</p>
+<p>By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</p>
+<p>
+            Format: string</p>
+</td>
+</tr></tbody>
+</table></div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="id-1.2.10.4.19"></a><h3>gsm setting</h3>
 <p>GSM-based Mobile Broadband Settings.</p>
 <p>
         Properties:
@@ -2654,7 +2678,7 @@
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.19"></a><h3>infiniband setting</h3>
+<a name="id-1.2.10.4.20"></a><h3>infiniband setting</h3>
 <p>Infiniband Settings.</p>
 <p>
         Properties:
@@ -2730,7 +2754,7 @@
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.20"></a><h3>ipv4 setting</h3>
+<a name="id-1.2.10.4.21"></a><h3>ipv4 setting</h3>
 <p>IPv4 Settings.</p>
 <p>
         Properties:
@@ -3150,7 +3174,7 @@ Example: <code class="literal">priority 5 from 192.167.4.0/24 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.21"></a><h3>ipv6 setting</h3>
+<a name="id-1.2.10.4.22"></a><h3>ipv6 setting</h3>
 <p>IPv6 Settings.</p>
 <p>
         Properties:
@@ -3563,7 +3587,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.22"></a><h3>ip-tunnel setting</h3>
+<a name="id-1.2.10.4.23"></a><h3>ip-tunnel setting</h3>
 <p>IP Tunneling Settings.</p>
 <p>
         Properties:
@@ -3717,7 +3741,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.23"></a><h3>macsec setting</h3>
+<a name="id-1.2.10.4.24"></a><h3>macsec setting</h3>
 <p>MACSec Settings.</p>
 <p>
         Properties:
@@ -3783,6 +3807,19 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </td>
 </tr>
 <tr>
+<td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.macsec.offload"></a>macsec.offload</code></span></p></td>
+<td>
+<p>Specifies the MACsec offload mode.</p>
+<p>"off" (0) disables MACsec offload.</p>
+<p>"phy" (1) and "mac" (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.</p>
+<p>"default" (-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is "off" (0).</p>
+<p>
+            Format: choice (NMSettingMacsecOffload)</p>
+<p>
+            Valid values: default (-1), off (0), phy (1), mac (2)</p>
+</td>
+</tr>
+<tr>
 <td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.macsec.parent"></a>macsec.parent</code></span></p></td>
 <td>
 <p>
@@ -3829,7 +3866,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.24"></a><h3>macvlan setting</h3>
+<a name="id-1.2.10.4.25"></a><h3>macvlan setting</h3>
 <p>MAC VLAN Settings.</p>
 <p>
         Properties:
@@ -3889,7 +3926,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.25"></a><h3>match setting</h3>
+<a name="id-1.2.10.4.26"></a><h3>match setting</h3>
 <p>Match settings.</p>
 <p>
         Properties:
@@ -3944,7 +3981,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.26"></a><h3>802-11-olpc-mesh setting</h3>
+<a name="id-1.2.10.4.27"></a><h3>802-11-olpc-mesh setting</h3>
 <p>
           Alias: olpc-mesh</p>
 <p>OLPC Wireless Mesh Settings.</p>
@@ -3995,7 +4032,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.27"></a><h3>ovs-bridge setting</h3>
+<a name="id-1.2.10.4.28"></a><h3>ovs-bridge setting</h3>
 <p>OvsBridge Link Settings.</p>
 <p>
         Properties:
@@ -4061,7 +4098,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.28"></a><h3>ovs-dpdk setting</h3>
+<a name="id-1.2.10.4.29"></a><h3>ovs-dpdk setting</h3>
 <p>OvsDpdk Link Settings.</p>
 <p>
         Properties:
@@ -4115,7 +4152,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.29"></a><h3>ovs-interface setting</h3>
+<a name="id-1.2.10.4.30"></a><h3>ovs-interface setting</h3>
 <p>Open vSwitch Interface Settings.</p>
 <p>
         Properties:
@@ -4151,7 +4188,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.30"></a><h3>ovs-patch setting</h3>
+<a name="id-1.2.10.4.31"></a><h3>ovs-patch setting</h3>
 <p>OvsPatch Link Settings.</p>
 <p>
         Properties:
@@ -4173,7 +4210,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.31"></a><h3>ovs-port setting</h3>
+<a name="id-1.2.10.4.32"></a><h3>ovs-port setting</h3>
 <p>OvsPort Link Settings.</p>
 <p>
         Properties:
@@ -4258,7 +4295,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.32"></a><h3>ppp setting</h3>
+<a name="id-1.2.10.4.33"></a><h3>ppp setting</h3>
 <p>Point-to-Point Protocol Settings.</p>
 <p>
         Properties:
@@ -4454,7 +4491,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.33"></a><h3>pppoe setting</h3>
+<a name="id-1.2.10.4.34"></a><h3>pppoe setting</h3>
 <p>PPP-over-Ethernet Settings.</p>
 <p>
         Properties:
@@ -4520,7 +4557,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.34"></a><h3>proxy setting</h3>
+<a name="id-1.2.10.4.35"></a><h3>proxy setting</h3>
 <p>WWW Proxy Settings.</p>
 <p>
         Properties:
@@ -4580,7 +4617,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.35"></a><h3>serial setting</h3>
+<a name="id-1.2.10.4.36"></a><h3>serial setting</h3>
 <p>Serial Link Settings.</p>
 <p>
         Properties:
@@ -4646,7 +4683,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.36"></a><h3>sriov setting</h3>
+<a name="id-1.2.10.4.37"></a><h3>sriov setting</h3>
 <p>SR-IOV settings.</p>
 <p>
         Properties:
@@ -4671,6 +4708,41 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </td>
 </tr>
 <tr>
+<td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.sriov.eswitch-encap-mode"></a>sriov.eswitch-encap-mode</code></span></p></td>
+<td>
+<p>Select the eswitch encapsulation support.</p>
+<p>Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</p>
+<p>If set to "preserve" (-1) (default) the eswitch encap-mode won't be modified by NetworkManager.</p>
+<p>
+            Format: choice (NMSriovEswitchEncapMode)</p>
+<p>
+            Valid values: preserve (-1), none (0), basic (1)</p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.sriov.eswitch-inline-mode"></a>sriov.eswitch-inline-mode</code></span></p></td>
+<td>
+<p>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.</p>
+<p>Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</p>
+<p>If set to "preserve" (-1) (default) the eswitch inline-mode won't be modified by NetworkManager.</p>
+<p>
+            Format: choice (NMSriovEswitchInlineMode)</p>
+<p>
+            Valid values: preserve (-1), none (0), link (1), network (2), transport (3)</p>
+</td>
+</tr>
+<tr>
+<td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.sriov.eswitch-mode"></a>sriov.eswitch-mode</code></span></p></td>
+<td>
+<p>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</p>
+<p>If set to "preserve" (-1) (default) the eswitch mode won't be modified by NetworkManager.</p>
+<p>
+            Format: choice (NMSriovEswitchMode)</p>
+<p>
+            Valid values: preserve (-1), legacy (0), switchdev (1)</p>
+</td>
+</tr>
+<tr>
 <td><p><span class="term"><code class="option"><a name="nm-settings-nmcli.property.sriov.total-vfs"></a>sriov.total-vfs</code></span></p></td>
 <td>
 <p>The total number of virtual functions to create.</p>
@@ -4703,7 +4775,7 @@ Example: <code class="literal">priority 5 from 1:2:3::5/128 table 45</code>
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.37"></a><h3>tc setting</h3>
+<a name="id-1.2.10.4.38"></a><h3>tc setting</h3>
 <p>Linux Traffic Control Settings.</p>
 <p>
         Properties:
@@ -5080,7 +5152,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.38"></a><h3>team setting</h3>
+<a name="id-1.2.10.4.39"></a><h3>team setting</h3>
 <p>Teaming Settings.</p>
 <p>
         Properties:
@@ -5268,7 +5340,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.39"></a><h3>team-port setting</h3>
+<a name="id-1.2.10.4.40"></a><h3>team-port setting</h3>
 <p>Team Port Settings.</p>
 <p>
         Properties:
@@ -5360,7 +5432,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.40"></a><h3>tun setting</h3>
+<a name="id-1.2.10.4.41"></a><h3>tun setting</h3>
 <p>Tunnel Settings.</p>
 <p>
         Properties:
@@ -5444,7 +5516,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.41"></a><h3>vlan setting</h3>
+<a name="id-1.2.10.4.42"></a><h3>vlan setting</h3>
 <p>VLAN Settings.</p>
 <p>
         Properties:
@@ -5526,7 +5598,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.42"></a><h3>vpn setting</h3>
+<a name="id-1.2.10.4.43"></a><h3>vpn setting</h3>
 <p>VPN Settings.</p>
 <p>
         Properties:
@@ -5598,7 +5670,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.43"></a><h3>vrf setting</h3>
+<a name="id-1.2.10.4.44"></a><h3>vrf setting</h3>
 <p>VRF settings.</p>
 <p>
         Properties:
@@ -5624,7 +5696,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.44"></a><h3>vxlan setting</h3>
+<a name="id-1.2.10.4.45"></a><h3>vxlan setting</h3>
 <p>VXLAN Settings.</p>
 <p>
         Properties:
@@ -5808,7 +5880,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.45"></a><h3>wifi-p2p setting</h3>
+<a name="id-1.2.10.4.46"></a><h3>wifi-p2p setting</h3>
 <p>Wi-Fi P2P Settings.</p>
 <p>
         Properties:
@@ -5854,7 +5926,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.46"></a><h3>wimax setting</h3>
+<a name="id-1.2.10.4.47"></a><h3>wimax setting</h3>
 <p>WiMax Settings.</p>
 <p>
         Properties:
@@ -5896,7 +5968,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.47"></a><h3>802-3-ethernet setting</h3>
+<a name="id-1.2.10.4.48"></a><h3>802-3-ethernet setting</h3>
 <p>
           Alias: ethernet</p>
 <p>Wired Ethernet Settings.</p>
@@ -6064,7 +6136,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.48"></a><h3>wireguard setting</h3>
+<a name="id-1.2.10.4.49"></a><h3>wireguard setting</h3>
 <p>WireGuard Settings.</p>
 <p>
         Properties:
@@ -6163,7 +6235,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.49"></a><h3>802-11-wireless setting</h3>
+<a name="id-1.2.10.4.50"></a><h3>802-11-wireless setting</h3>
 <p>
           Alias: wifi</p>
 <p>Wi-Fi Settings.</p>
@@ -6357,7 +6429,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.50"></a><h3>802-11-wireless-security setting</h3>
+<a name="id-1.2.10.4.51"></a><h3>802-11-wireless-security setting</h3>
 <p>
           Alias: wifi-sec</p>
 <p>Wi-Fi Security Settings.</p>
@@ -6564,7 +6636,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.51"></a><h3>wpan setting</h3>
+<a name="id-1.2.10.4.52"></a><h3>wpan setting</h3>
 <p>IEEE 802.15.4 (WPAN) MAC Settings.</p>
 <p>
         Properties:
@@ -6646,7 +6718,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.52"></a><h3>bond-port setting</h3>
+<a name="id-1.2.10.4.53"></a><h3>bond-port setting</h3>
 <p>Bond Port Settings.</p>
 <p>
         Properties:
@@ -6686,7 +6758,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.53"></a><h3>hostname setting</h3>
+<a name="id-1.2.10.4.54"></a><h3>hostname setting</h3>
 <p>Hostname settings.</p>
 <p>
         Properties:
@@ -6748,7 +6820,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.54"></a><h3>hsr setting</h3>
+<a name="id-1.2.10.4.55"></a><h3>hsr setting</h3>
 <p>HSR/PRP Settings.</p>
 <p>
         Properties:
@@ -6806,7 +6878,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.55"></a><h3>link setting</h3>
+<a name="id-1.2.10.4.56"></a><h3>link setting</h3>
 <p>Link settings.</p>
 <p>
         Properties:
@@ -6870,7 +6942,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.56"></a><h3>loopback setting</h3>
+<a name="id-1.2.10.4.57"></a><h3>loopback setting</h3>
 <p>Loopback Link Settings.</p>
 <p>
         Properties:
@@ -6896,7 +6968,7 @@ Linux traffic control subsystem
 </div>
 <hr>
 <div class="refsect2">
-<a name="id-1.2.10.4.57"></a><h3>veth setting</h3>
+<a name="id-1.2.10.4.58"></a><h3>veth setting</h3>
 <p>Veth Settings.</p>
 <p>
         Properties:
diff --git a/docs/api/html/settings-connection.html b/docs/api/html/settings-connection.html
index f450a596..afd9d6cc 100644
--- a/docs/api/html/settings-connection.html
+++ b/docs/api/html/settings-connection.html
@@ -77,8 +77,8 @@ Depending on "connection.multi-connect", a profile can (auto)connect only once a
 </tr>
 <tr>
 <td><pre class="screen">autoconnect-ports</pre></td>
-<td><pre class="screen">NMTernary (int32)</pre></td>
-<td><pre class="screen"></pre></td>
+<td><pre class="screen">int32</pre></td>
+<td><pre class="screen">-1</pre></td>
 <td>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</td>
 </tr>
 <tr>
diff --git a/docs/api/html/settings-generic.html b/docs/api/html/settings-generic.html
index 4beac3ac..3594cb94 100644
--- a/docs/api/html/settings-generic.html
+++ b/docs/api/html/settings-generic.html
@@ -52,7 +52,16 @@
 <th>Default Value</th>
 <th>Value Description</th>
 </tr></thead>
-<tbody></tbody>
+<tbody><tr>
+<td><pre class="screen">device-handler</pre></td>
+<td><pre class="screen">string</pre></td>
+<td><pre class="screen"></pre></td>
+<td>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.
+
+See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.
+
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</td>
+</tr></tbody>
 </table></div>
 </div>
 <p><br class="table-break"></p>
diff --git a/docs/api/html/settings-macsec.html b/docs/api/html/settings-macsec.html
index 13977556..8ae1020f 100644
--- a/docs/api/html/settings-macsec.html
+++ b/docs/api/html/settings-macsec.html
@@ -84,6 +84,18 @@
 <td>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</td>
 </tr>
 <tr>
+<td><pre class="screen">offload</pre></td>
+<td><pre class="screen">int32</pre></td>
+<td><pre class="screen">-1</pre></td>
+<td>Specifies the MACsec offload mode.
+
+0 (off) disables MACsec offload.
+
+1 (phy) and 2 (mac) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.
+
+-1 (default) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is 0 (off).</td>
+</tr>
+<tr>
 <td><pre class="screen">parent</pre></td>
 <td><pre class="screen">string</pre></td>
 <td><pre class="screen"></pre></td>
diff --git a/docs/api/html/settings-sriov.html b/docs/api/html/settings-sriov.html
index 3d3b9aa5..72aa72ef 100644
--- a/docs/api/html/settings-sriov.html
+++ b/docs/api/html/settings-sriov.html
@@ -66,6 +66,34 @@ If set to 0 (false), VFs will not be claimed and no network interfaces will be c
 When set to -1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true).</td>
 </tr>
 <tr>
+<td><pre class="screen">eswitch-encap-mode</pre></td>
+<td><pre class="screen">int32</pre></td>
+<td><pre class="screen">-1</pre></td>
+<td>Select the eswitch encapsulation support.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch encap-mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
+<td><pre class="screen">eswitch-inline-mode</pre></td>
+<td><pre class="screen">int32</pre></td>
+<td><pre class="screen">-1</pre></td>
+<td>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch inline-mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
+<td><pre class="screen">eswitch-mode</pre></td>
+<td><pre class="screen">int32</pre></td>
+<td><pre class="screen">-1</pre></td>
+<td>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch mode won't be modified by NetworkManager.</td>
+</tr>
+<tr>
 <td><pre class="screen">total-vfs</pre></td>
 <td><pre class="screen">uint32</pre></td>
 <td><pre class="screen">0</pre></td>
diff --git a/docs/api/settings-spec.xml b/docs/api/settings-spec.xml
index bdff11c1..3a1105e0 100644
--- a/docs/api/settings-spec.xml
+++ b/docs/api/settings-spec.xml
@@ -12,7 +12,7 @@ Note that autoconnect is not implemented for VPN profiles. See "secondaries" as
 
 If multiple profiles are ready to autoconnect on the same device, the one with the better "connection.autoconnect-priority" is chosen. If the priorities are equal, then the most recently connected profile is activated. If the profiles were not connected earlier or their "connection.timestamp" is identical, the choice is undefined.
 
-Depending on "connection.multi-connect", a profile can (auto)connect only once at a time or multiple times.</entry></row><row><entry><screen>autoconnect-ports<indexterm zone="settings-connection"><primary sortas="autoconnect-ports">autoconnect-ports</primary></indexterm></screen></entry><entry><screen>NMTernary (int32)</screen></entry><entry><screen/></entry><entry>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry><screen>autoconnect-priority<indexterm zone="settings-connection"><primary sortas="autoconnect-priority">autoconnect-priority</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>0</screen></entry><entry>The autoconnect priority in range -999 to 999. If the connection is set to autoconnect, connections with higher priority will be preferred. The higher number means higher priority. Defaults to 0. Note that this property only matters if there are more than one candidate profile to select for autoconnect. In case of equal priority, the profile used most recently is chosen.</entry></row><row><entry><screen>autoconnect-retries<indexterm zone="settings-connection"><primary sortas="autoconnect-retries">autoconnect-retries</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.</entry></row><row><entry><screen>autoconnect-slaves<indexterm zone="settings-connection"><primary sortas="autoconnect-slaves">autoconnect-slaves</primary></indexterm></screen></entry><entry><screen>NMSettingConnectionAutoconnectSlaves (int32)</screen></entry><entry><screen/></entry><entry>Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry><screen>controller<indexterm zone="settings-connection"><primary sortas="controller">controller</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>Interface name of the controller device or UUID of the controller connection.</entry></row><row><entry><screen>dns-over-tls<indexterm zone="settings-connection"><primary sortas="dns-over-tls">dns-over-tls</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls is a technology which uses TLS to encrypt dns traffic.
+Depending on "connection.multi-connect", a profile can (auto)connect only once at a time or multiple times.</entry></row><row><entry><screen>autoconnect-ports<indexterm zone="settings-connection"><primary sortas="autoconnect-ports">autoconnect-ports</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry><screen>autoconnect-priority<indexterm zone="settings-connection"><primary sortas="autoconnect-priority">autoconnect-priority</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>0</screen></entry><entry>The autoconnect priority in range -999 to 999. If the connection is set to autoconnect, connections with higher priority will be preferred. The higher number means higher priority. Defaults to 0. Note that this property only matters if there are more than one candidate profile to select for autoconnect. In case of equal priority, the profile used most recently is chosen.</entry></row><row><entry><screen>autoconnect-retries<indexterm zone="settings-connection"><primary sortas="autoconnect-retries">autoconnect-retries</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.</entry></row><row><entry><screen>autoconnect-slaves<indexterm zone="settings-connection"><primary sortas="autoconnect-slaves">autoconnect-slaves</primary></indexterm></screen></entry><entry><screen>NMSettingConnectionAutoconnectSlaves (int32)</screen></entry><entry><screen/></entry><entry>Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry><screen>controller<indexterm zone="settings-connection"><primary sortas="controller">controller</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>Interface name of the controller device or UUID of the controller connection.</entry></row><row><entry><screen>dns-over-tls<indexterm zone="settings-connection"><primary sortas="dns-over-tls">dns-over-tls</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls is a technology which uses TLS to encrypt dns traffic.
 
 The permitted values are: "yes" (2) use DNSOverTls and disabled fallback, "opportunistic" (1) use DNSOverTls but allow fallback to unencrypted resolution, "no" (0) don't ever use DNSOverTls. If unspecified "default" depends on the plugin used. Systemd-resolved uses global setting.
 
@@ -142,7 +142,11 @@ Since 1.34, NULL is the default and means "fabric". Before 1.34, NULL was reject
             Properties
         </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></table></para></refsect1></refentry><refentry id="settings-generic"><refnamediv><refname>generic</refname><refpurpose>Generic Link Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-generic.properties">
             Properties
-        </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></table></para></refsect1></refentry><refentry id="settings-gsm"><refnamediv><refname>gsm</refname><refpurpose>GSM-based Mobile Broadband Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-gsm.properties">
+        </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>device-handler<indexterm zone="settings-generic"><primary sortas="device-handler">device-handler</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.
+
+See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.
+
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</entry></row></tbody></tgroup></table></para></refsect1></refentry><refentry id="settings-gsm"><refnamediv><refname>gsm</refname><refpurpose>GSM-based Mobile Broadband Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-gsm.properties">
             Properties
         </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>apn<indexterm zone="settings-gsm"><primary sortas="apn">apn</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.
 
@@ -356,7 +360,13 @@ When set, the token is used as IPv6 interface identifier instead of the hardware
             Properties
         </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>encapsulation-limit<indexterm zone="settings-ip-tunnel"><primary sortas="encapsulation-limit">encapsulation-limit</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels. To disable this option, add 0x1 (ip6-ign-encap-limit) to ip-tunnel flags.</entry></row><row><entry><screen>flags<indexterm zone="settings-ip-tunnel"><primary sortas="flags">flags</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>Tunnel flags. Currently, the following values are supported: 0x1 (ip6-ign-encap-limit), 0x2 (ip6-use-orig-tclass), 0x4 (ip6-use-orig-flowlabel), 0x8 (ip6-mip6-dev), 0x10 (ip6-rcv-dscp-copy), 0x20 (ip6-use-orig-fwmark). They are valid only for IPv6 tunnels.</entry></row><row><entry><screen>flow-label<indexterm zone="settings-ip-tunnel"><primary sortas="flow-label">flow-label</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.</entry></row><row><entry><screen>fwmark<indexterm zone="settings-ip-tunnel"><primary sortas="fwmark">fwmark</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The fwmark value to assign to tunnel packets. This property can be set to a non zero value only on VTI and VTI6 tunnels.</entry></row><row><entry><screen>input-key<indexterm zone="settings-ip-tunnel"><primary sortas="input-key">input-key</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry><screen>local<indexterm zone="settings-ip-tunnel"><primary sortas="local">local</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.</entry></row><row><entry><screen>mode<indexterm zone="settings-ip-tunnel"><primary sortas="mode">mode</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The tunneling mode. Valid values: 1 (ipip), 2 (gre), 3 (sit), 4 (isatap), 5 (vti), 6 (ip6ip6), 7 (ipip6), 8 (ip6gre), 9 (vti6), 10 (gretap) and 11 (ip6gretap)</entry></row><row><entry><screen>mtu<indexterm zone="settings-ip-tunnel"><primary sortas="mtu">mtu</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.</entry></row><row><entry><screen>output-key<indexterm zone="settings-ip-tunnel"><primary sortas="output-key">output-key</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry><screen>parent<indexterm zone="settings-ip-tunnel"><primary sortas="parent">parent</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface.</entry></row><row><entry><screen>path-mtu-discovery<indexterm zone="settings-ip-tunnel"><primary sortas="path-mtu-discovery">path-mtu-discovery</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Whether to enable Path MTU Discovery on this tunnel.</entry></row><row><entry><screen>remote<indexterm zone="settings-ip-tunnel"><primary sortas="remote">remote</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address.</entry></row><row><entry><screen>tos<indexterm zone="settings-ip-tunnel"><primary sortas="tos">tos</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.</entry></row><row><entry><screen>ttl<indexterm zone="settings-ip-tunnel"><primary sortas="ttl">ttl</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.</entry></row></tbody></tgroup></table></para></refsect1></refentry><refentry id="settings-macsec"><refnamediv><refname>macsec</refname><refpurpose>MACSec Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-macsec.properties">
             Properties
-        </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>encrypt<indexterm zone="settings-macsec"><primary sortas="encrypt">encrypt</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Whether the transmitted traffic must be encrypted.</entry></row><row><entry><screen>mka-cak<indexterm zone="settings-macsec"><primary sortas="mka-cak">mka-cak</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. Must be a string of 32 hexadecimal characters.</entry></row><row><entry><screen>mka-cak-flags<indexterm zone="settings-macsec"><primary sortas="mka-cak-flags">mka-cak-flags</primary></indexterm></screen></entry><entry><screen>NMSettingSecretFlags (uint32)</screen></entry><entry><screen/></entry><entry>Flags indicating how to handle the "mka-cak" property.</entry></row><row><entry><screen>mka-ckn<indexterm zone="settings-macsec"><primary sortas="mka-ckn">mka-ckn</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.</entry></row><row><entry><screen>mode<indexterm zone="settings-macsec"><primary sortas="mode">mode</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>0</screen></entry><entry>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</entry></row><row><entry><screen>parent<indexterm zone="settings-macsec"><primary sortas="parent">parent</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry><screen>port<indexterm zone="settings-macsec"><primary sortas="port">port</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>1</screen></entry><entry>The port component of the SCI (Secure Channel Identifier), between 1 and 65534.</entry></row><row><entry><screen>send-sci<indexterm zone="settings-macsec"><primary sortas="send-sci">send-sci</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Specifies whether the SCI (Secure Channel Identifier) is included in every packet.</entry></row><row><entry><screen>validation<indexterm zone="settings-macsec"><primary sortas="validation">validation</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>2</screen></entry><entry>Specifies the validation mode for incoming frames.</entry></row></tbody></tgroup></table></para></refsect1></refentry><refentry id="settings-macvlan"><refnamediv><refname>macvlan</refname><refpurpose>MAC VLAN Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-macvlan.properties">
+        </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>encrypt<indexterm zone="settings-macsec"><primary sortas="encrypt">encrypt</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Whether the transmitted traffic must be encrypted.</entry></row><row><entry><screen>mka-cak<indexterm zone="settings-macsec"><primary sortas="mka-cak">mka-cak</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. Must be a string of 32 hexadecimal characters.</entry></row><row><entry><screen>mka-cak-flags<indexterm zone="settings-macsec"><primary sortas="mka-cak-flags">mka-cak-flags</primary></indexterm></screen></entry><entry><screen>NMSettingSecretFlags (uint32)</screen></entry><entry><screen/></entry><entry>Flags indicating how to handle the "mka-cak" property.</entry></row><row><entry><screen>mka-ckn<indexterm zone="settings-macsec"><primary sortas="mka-ckn">mka-ckn</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.</entry></row><row><entry><screen>mode<indexterm zone="settings-macsec"><primary sortas="mode">mode</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>0</screen></entry><entry>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</entry></row><row><entry><screen>offload<indexterm zone="settings-macsec"><primary sortas="offload">offload</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Specifies the MACsec offload mode.
+
+0 (off) disables MACsec offload.
+
+1 (phy) and 2 (mac) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.
+
+-1 (default) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is 0 (off).</entry></row><row><entry><screen>parent<indexterm zone="settings-macsec"><primary sortas="parent">parent</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry><screen>port<indexterm zone="settings-macsec"><primary sortas="port">port</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>1</screen></entry><entry>The port component of the SCI (Secure Channel Identifier), between 1 and 65534.</entry></row><row><entry><screen>send-sci<indexterm zone="settings-macsec"><primary sortas="send-sci">send-sci</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Specifies whether the SCI (Secure Channel Identifier) is included in every packet.</entry></row><row><entry><screen>validation<indexterm zone="settings-macsec"><primary sortas="validation">validation</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>2</screen></entry><entry>Specifies the validation mode for incoming frames.</entry></row></tbody></tgroup></table></para></refsect1></refentry><refentry id="settings-macvlan"><refnamediv><refname>macvlan</refname><refpurpose>MAC VLAN Settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-macvlan.properties">
             Properties
         </title><para><table><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry><screen>mode<indexterm zone="settings-macvlan"><primary sortas="mode">mode</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.</entry></row><row><entry><screen>parent<indexterm zone="settings-macvlan"><primary sortas="parent">parent</primary></indexterm></screen></entry><entry><screen>string</screen></entry><entry><screen/></entry><entry>If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry><screen>promiscuous<indexterm zone="settings-macvlan"><primary sortas="promiscuous">promiscuous</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>TRUE</screen></entry><entry>Whether the interface should be put in promiscuous mode.</entry></row><row><entry><screen>tap<indexterm zone="settings-macvlan"><primary sortas="tap">tap</primary></indexterm></screen></entry><entry><screen>boolean</screen></entry><entry><screen>FALSE</screen></entry><entry>Whether the interface should be a MACVTAP.</entry></row></tbody></tgroup></table></para></refsect1></refentry><refentry id="settings-match"><refnamediv><refname>match</refname><refpurpose>Match settings</refpurpose></refnamediv><refsect1 role="properties"><title id="settings-match.properties">
             Properties
@@ -406,7 +416,17 @@ If set to 1 (true), the kernel will try to bind VFs to a compatible driver and i
 
 If set to 0 (false), VFs will not be claimed and no network interfaces will be created for them.
 
-When set to -1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true).</entry></row><row><entry><screen>total-vfs<indexterm zone="settings-sriov"><primary sortas="total-vfs">total-vfs</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The total number of virtual functions to create.
+When set to -1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true).</entry></row><row><entry><screen>eswitch-encap-mode<indexterm zone="settings-sriov"><primary sortas="eswitch-encap-mode">eswitch-encap-mode</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Select the eswitch encapsulation support.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch encap-mode won't be modified by NetworkManager.</entry></row><row><entry><screen>eswitch-inline-mode<indexterm zone="settings-sriov"><primary sortas="eswitch-inline-mode">eswitch-inline-mode</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch inline-mode won't be modified by NetworkManager.</entry></row><row><entry><screen>eswitch-mode<indexterm zone="settings-sriov"><primary sortas="eswitch-mode">eswitch-mode</primary></indexterm></screen></entry><entry><screen>int32</screen></entry><entry><screen>-1</screen></entry><entry>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch mode won't be modified by NetworkManager.</entry></row><row><entry><screen>total-vfs<indexterm zone="settings-sriov"><primary sortas="total-vfs">total-vfs</primary></indexterm></screen></entry><entry><screen>uint32</screen></entry><entry><screen>0</screen></entry><entry>The total number of virtual functions to create.
 
 Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.</entry></row><row><entry><screen>vfs<indexterm zone="settings-sriov"><primary sortas="vfs">vfs</primary></indexterm></screen></entry><entry><screen>array of vardict</screen></entry><entry><screen/></entry><entry>Array of virtual function descriptors.
 
diff --git a/docs/api/version.xml b/docs/api/version.xml
index 24a58e09..0a3db35b 100644
--- a/docs/api/version.xml
+++ b/docs/api/version.xml
@@ -1 +1 @@
-1.45.91
+1.46.0
diff --git a/docs/libnm/html/NMSetting.html b/docs/libnm/html/NMSetting.html
index a921dc81..b35c6b74 100644
--- a/docs/libnm/html/NMSetting.html
+++ b/docs/libnm/html/NMSetting.html
@@ -215,6 +215,14 @@
 </tr>
 <tr>
 <td class="function_type">
+<a href="https://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#GType"><span class="returnvalue">GType</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NMSetting.html#nm-setting-get-enum-property-type" title="nm_setting_get_enum_property_type ()">nm_setting_get_enum_property_type</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
 <a class="link" href="NMSetting.html#NMRange"><span class="returnvalue">NMRange</span></a> *
 </td>
 <td class="function_name">
@@ -1218,6 +1226,47 @@ on <em class="parameter"><code>setting</code></em>
 </div>
 <hr>
 <div class="refsect2">
+<a name="nm-setting-get-enum-property-type"></a><h3>nm_setting_get_enum_property_type ()</h3>
+<pre class="programlisting"><a href="https://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#GType"><span class="returnvalue">GType</span></a>
+nm_setting_get_enum_property_type (<em class="parameter"><code><a href="https://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#GType"><span class="type">GType</span></a> setting_type</code></em>,
+                                   <em class="parameter"><code>const <span class="type">char</span> *property_name</code></em>);</pre>
+<p>Get the type of the enum that defines the values that the property accepts. It is only
+useful for properties configured to accept values from certain enum type, otherwise
+it will return <a href="https://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#G-TYPE-INVALID:CAPS"><code class="literal">G_TYPE_INVALID</code></a>. Note that flags (children of G_TYPE_FLAGS) are also
+considered enums.</p>
+<p>Note that the GObject property might be implemented as an integer, actually, and not
+as enum. Find out what underlying type is used, checking the <a href="https://developer.gnome.org/gobject/unstable/gobject-GParamSpec.html#GParamSpec"><span class="type">GParamSpec</span></a>, before
+setting the GObject property.</p>
+<div class="refsect3">
+<a name="nm-setting-get-enum-property-type.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>setting_type</p></td>
+<td class="parameter_description"><p>the GType of the NMSetting instance</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>property_name</p></td>
+<td class="parameter_description"><p>the name of the property</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-get-enum-property-type.returns"></a><h4>Returns</h4>
+<p> the enum's GType, or <a href="https://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#G-TYPE-INVALID:CAPS"><code class="literal">G_TYPE_INVALID</code></a> if the property is not of enum type</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="nm-range-new"></a><h3>nm_range_new ()</h3>
 <pre class="programlisting"><a class="link" href="NMSetting.html#NMRange"><span class="returnvalue">NMRange</span></a> *
 nm_range_new (<em class="parameter"><code><a href="https://developer.gnome.org/glib/unstable/glib-Basic-Types.html#guint64"><span class="type">guint64</span></a> start</code></em>,
diff --git a/docs/libnm/html/NMSettingGeneric.html b/docs/libnm/html/NMSettingGeneric.html
index 4a10561c..fae31e4e 100644
--- a/docs/libnm/html/NMSettingGeneric.html
+++ b/docs/libnm/html/NMSettingGeneric.html
@@ -38,14 +38,23 @@
 <col width="150px" class="functions_proto_type">
 <col class="functions_proto_name">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="function_type">
 <a class="link" href="NMSetting.html" title="NMSetting"><span class="returnvalue">NMSetting</span></a> *
 </td>
 <td class="function_name">
 <a class="link" href="NMSettingGeneric.html#nm-setting-generic-new" title="nm_setting_generic_new ()">nm_setting_generic_new</a> <span class="c_punctuation">()</span>
 </td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">char</span> *
+</td>
+<td class="function_name">
+<a class="link" href="NMSettingGeneric.html#nm-setting-generic-get-device-handler" title="nm_setting_generic_get_device_handler ()">nm_setting_generic_get_device_handler</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
 </table></div>
 </div>
 <div class="refsect1">
@@ -55,10 +64,16 @@
 <col width="150px" class="other_proto_type">
 <col class="other_proto_name">
 </colgroup>
-<tbody><tr>
+<tbody>
+<tr>
 <td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="NMSettingGeneric.html#NM-SETTING-GENERIC-SETTING-NAME:CAPS" title="NM_SETTING_GENERIC_SETTING_NAME">NM_SETTING_GENERIC_SETTING_NAME</a></td>
-</tr></tbody>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NMSettingGeneric.html#NM-SETTING-GENERIC-DEVICE-HANDLER:CAPS" title="NM_SETTING_GENERIC_DEVICE_HANDLER">NM_SETTING_GENERIC_DEVICE_HANDLER</a></td>
+</tr>
+</tbody>
 </table></div>
 </div>
 <div class="refsect1">
@@ -82,6 +97,33 @@ nm_setting_generic_new (<em class="parameter"><code><span class="type">void</spa
 <p><span class="annotation">[<acronym title="The caller owns the data, and is responsible for free it."><span class="acronym">transfer full</span></acronym>]</span></p>
 </div>
 </div>
+<hr>
+<div class="refsect2">
+<a name="nm-setting-generic-get-device-handler"></a><h3>nm_setting_generic_get_device_handler ()</h3>
+<pre class="programlisting">const <span class="returnvalue">char</span> *
+nm_setting_generic_get_device_handler (<em class="parameter"><code><a class="link" href="NMSettingGeneric.html" title="NMSettingGeneric"><span class="type">NMSettingGeneric</span></a> *setting</code></em>);</pre>
+<p>Returns the <span class="type">“device-handler”</span> property of the connection.</p>
+<div class="refsect3">
+<a name="nm-setting-generic-get-device-handler.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>setting</p></td>
+<td class="parameter_description"><p>the <a class="link" href="NMSettingGeneric.html" title="NMSettingGeneric"><span class="type">NMSettingGeneric</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-generic-get-device-handler.returns"></a><h4>Returns</h4>
+<p> the device handler name, or <a href="https://developer.gnome.org/glib/unstable/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> if no device handler is set</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
 </div>
 <div class="refsect1">
 <a name="NMSettingGeneric.other_details"></a><h2>Types and Values</h2>
@@ -90,6 +132,12 @@ nm_setting_generic_new (<em class="parameter"><code><span class="type">void</spa
 <pre class="programlisting">#define NM_SETTING_GENERIC_SETTING_NAME "generic"
 </pre>
 </div>
+<hr>
+<div class="refsect2">
+<a name="NM-SETTING-GENERIC-DEVICE-HANDLER:CAPS"></a><h3>NM_SETTING_GENERIC_DEVICE_HANDLER</h3>
+<pre class="programlisting">#define NM_SETTING_GENERIC_DEVICE_HANDLER "device-handler"
+</pre>
+</div>
 </div>
 </div>
 <div class="footer">
diff --git a/docs/libnm/html/NMSettingMacsec.html b/docs/libnm/html/NMSettingMacsec.html
index 87ab2340..4bb383d3 100644
--- a/docs/libnm/html/NMSettingMacsec.html
+++ b/docs/libnm/html/NMSettingMacsec.html
@@ -117,6 +117,14 @@
 <a class="link" href="NMSettingMacsec.html#nm-setting-macsec-get-send-sci" title="nm_setting_macsec_get_send_sci ()">nm_setting_macsec_get_send_sci</a> <span class="c_punctuation">()</span>
 </td>
 </tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NMSettingMacsec.html#NMSettingMacsecOffload" title="enum NMSettingMacsecOffload"><span class="returnvalue">NMSettingMacsecOffload</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NMSettingMacsec.html#nm-setting-macsec-get-offload" title="nm_setting_macsec_get_offload ()">nm_setting_macsec_get_offload</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -169,6 +177,10 @@
 <td class="function_name"><a class="link" href="NMSettingMacsec.html#NM-SETTING-MACSEC-SEND-SCI:CAPS" title="NM_SETTING_MACSEC_SEND_SCI">NM_SETTING_MACSEC_SEND_SCI</a></td>
 </tr>
 <tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD:CAPS" title="NM_SETTING_MACSEC_OFFLOAD">NM_SETTING_MACSEC_OFFLOAD</a></td>
+</tr>
+<tr>
 <td class="datatype_keyword">enum</td>
 <td class="function_name"><a class="link" href="NMSettingMacsec.html#NMSettingMacsecMode" title="enum NMSettingMacsecMode">NMSettingMacsecMode</a></td>
 </tr>
@@ -184,6 +196,10 @@
 <td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="NMSettingMacsec.html#NM-SETTING-MACSEC-MKA-CKN-LENGTH:CAPS" title="NM_SETTING_MACSEC_MKA_CKN_LENGTH">NM_SETTING_MACSEC_MKA_CKN_LENGTH</a></td>
 </tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NMSettingMacsec.html#NMSettingMacsecOffload" title="enum NMSettingMacsecOffload">NMSettingMacsecOffload</a></td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -191,6 +207,7 @@
 <a name="NMSettingMacsec.object-hierarchy"></a><h2>Object Hierarchy</h2>
 <pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
     <span class="lineart">├──</span> NMSettingMacsecMode
+    <span class="lineart">├──</span> NMSettingMacsecOffload
     <span class="lineart">╰──</span> NMSettingMacsecValidation
 </pre>
 </div>
@@ -447,6 +464,32 @@ nm_setting_macsec_get_send_sci (<em class="parameter"><code><a class="link" href
 </div>
 <p class="since">Since: 1.12</p>
 </div>
+<hr>
+<div class="refsect2">
+<a name="nm-setting-macsec-get-offload"></a><h3>nm_setting_macsec_get_offload ()</h3>
+<pre class="programlisting"><a class="link" href="NMSettingMacsec.html#NMSettingMacsecOffload" title="enum NMSettingMacsecOffload"><span class="returnvalue">NMSettingMacsecOffload</span></a>
+nm_setting_macsec_get_offload (<em class="parameter"><code><a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec"><span class="type">NMSettingMacsec</span></a> *setting</code></em>);</pre>
+<div class="refsect3">
+<a name="nm-setting-macsec-get-offload.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>setting</p></td>
+<td class="parameter_description"><p>the <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec"><span class="type">NMSettingMacsec</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-macsec-get-offload.returns"></a><h4>Returns</h4>
+<p> the <span class="type">“offload”</span> property of the setting</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
 </div>
 <div class="refsect1">
 <a name="NMSettingMacsec.other_details"></a><h2>Types and Values</h2>
@@ -511,6 +554,12 @@ nm_setting_macsec_get_send_sci (<em class="parameter"><code><a class="link" href
 </div>
 <hr>
 <div class="refsect2">
+<a name="NM-SETTING-MACSEC-OFFLOAD:CAPS"></a><h3>NM_SETTING_MACSEC_OFFLOAD</h3>
+<pre class="programlisting">#define NM_SETTING_MACSEC_OFFLOAD       "offload"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
 <a name="NMSettingMacsecMode"></a><h3>enum NMSettingMacsecMode</h3>
 <p><a class="link" href="NMSettingMacsec.html#NMSettingMacsecMode" title="enum NMSettingMacsecMode"><span class="type">NMSettingMacsecMode</span></a> controls how the CAK (Connectivity Association Key) used
 in MKA (MACsec Key Agreement) is obtained.</p>
@@ -596,6 +645,52 @@ verify frames are dropped</p>
 <pre class="programlisting">#define NM_SETTING_MACSEC_MKA_CKN_LENGTH 64
 </pre>
 </div>
+<hr>
+<div class="refsect2">
+<a name="NMSettingMacsecOffload"></a><h3>enum NMSettingMacsecOffload</h3>
+<p>These flags control the MACsec offload mode.</p>
+<div class="refsect3">
+<a name="NMSettingMacsecOffload.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SETTING-MACSEC-OFFLOAD-DEFAULT:CAPS"></a>NM_SETTING_MACSEC_OFFLOAD_DEFAULT</p></td>
+<td class="enum_member_description">
+<p>use the global default; disable if not defined</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SETTING-MACSEC-OFFLOAD-OFF:CAPS"></a>NM_SETTING_MACSEC_OFFLOAD_OFF</p></td>
+<td class="enum_member_description">
+<p>disable offload</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SETTING-MACSEC-OFFLOAD-PHY:CAPS"></a>NM_SETTING_MACSEC_OFFLOAD_PHY</p></td>
+<td class="enum_member_description">
+<p>request offload to the PHY</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SETTING-MACSEC-OFFLOAD-MAC:CAPS"></a>NM_SETTING_MACSEC_OFFLOAD_MAC</p></td>
+<td class="enum_member_description">
+<p>request offload to the MAC</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
 </div>
 </div>
 <div class="footer">
diff --git a/docs/libnm/html/NMSettingSriov.html b/docs/libnm/html/NMSettingSriov.html
index 4d24ab1e..d7386945 100644
--- a/docs/libnm/html/NMSettingSriov.html
+++ b/docs/libnm/html/NMSettingSriov.html
@@ -114,6 +114,30 @@
 </tr>
 <tr>
 <td class="function_type">
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchMode" title="enum NMSriovEswitchMode"><span class="returnvalue">NMSriovEswitchMode</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-mode" title="nm_setting_sriov_get_eswitch_mode ()">nm_setting_sriov_get_eswitch_mode</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchInlineMode" title="enum NMSriovEswitchInlineMode"><span class="returnvalue">NMSriovEswitchInlineMode</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-inline-mode" title="nm_setting_sriov_get_eswitch_inline_mode ()">nm_setting_sriov_get_eswitch_inline_mode</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchEncapMode" title="enum NMSriovEswitchEncapMode"><span class="returnvalue">NMSriovEswitchEncapMode</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-encap-mode" title="nm_setting_sriov_get_eswitch_encap_mode ()">nm_setting_sriov_get_eswitch_encap_mode</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
 <a href="https://developer.gnome.org/glib/unstable/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
 </td>
 <td class="function_name">
@@ -275,6 +299,18 @@
 </tr>
 <tr>
 <td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_MODE">NM_SETTING_SRIOV_ESWITCH_MODE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-INLINE-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_INLINE_MODE">NM_SETTING_SRIOV_ESWITCH_INLINE_MODE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-ENCAP-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE">NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
 <td class="function_name"><a class="link" href="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-MAC:CAPS" title="NM_SRIOV_VF_ATTRIBUTE_MAC">NM_SRIOV_VF_ATTRIBUTE_MAC</a></td>
 </tr>
 <tr>
@@ -297,6 +333,18 @@
 <td class="datatype_keyword">enum</td>
 <td class="function_name"><a class="link" href="NMSettingSriov.html#NMSriovVFVlanProtocol" title="enum NMSriovVFVlanProtocol">NMSriovVFVlanProtocol</a></td>
 </tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NMSriovEswitchMode" title="enum NMSriovEswitchMode">NMSriovEswitchMode</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NMSriovEswitchInlineMode" title="enum NMSriovEswitchInlineMode">NMSriovEswitchInlineMode</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NMSettingSriov.html#NMSriovEswitchEncapMode" title="enum NMSriovEswitchEncapMode">NMSriovEswitchEncapMode</a></td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -305,6 +353,9 @@
 <pre class="screen">    <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
     <span class="lineart">╰──</span> NMSriovVF
     <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+    <span class="lineart">├──</span> NMSriovEswitchEncapMode
+    <span class="lineart">├──</span> NMSriovEswitchInlineMode
+    <span class="lineart">├──</span> NMSriovEswitchMode
     <span class="lineart">╰──</span> NMSriovVFVlanProtocol
 </pre>
 </div>
@@ -574,6 +625,86 @@ property.</p>
 </div>
 <hr>
 <div class="refsect2">
+<a name="nm-setting-sriov-get-eswitch-mode"></a><h3>nm_setting_sriov_get_eswitch_mode ()</h3>
+<pre class="programlisting"><a class="link" href="NMSettingSriov.html#NMSriovEswitchMode" title="enum NMSriovEswitchMode"><span class="returnvalue">NMSriovEswitchMode</span></a>
+nm_setting_sriov_get_eswitch_mode (<em class="parameter"><code><a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a> *setting</code></em>);</pre>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-mode.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>setting</p></td>
+<td class="parameter_description"><p>the <a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-mode.returns"></a><h4>Returns</h4>
+<p> the value contained in the <span class="type">“eswitch-mode”</span> property.</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nm-setting-sriov-get-eswitch-inline-mode"></a><h3>nm_setting_sriov_get_eswitch_inline_mode ()</h3>
+<pre class="programlisting"><a class="link" href="NMSettingSriov.html#NMSriovEswitchInlineMode" title="enum NMSriovEswitchInlineMode"><span class="returnvalue">NMSriovEswitchInlineMode</span></a>
+nm_setting_sriov_get_eswitch_inline_mode
+                               (<em class="parameter"><code><a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a> *setting</code></em>);</pre>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-inline-mode.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>setting</p></td>
+<td class="parameter_description"><p>the <a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-inline-mode.returns"></a><h4>Returns</h4>
+<p> the value contained in the <span class="type">“eswitch-inline-mode”</span> property.</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nm-setting-sriov-get-eswitch-encap-mode"></a><h3>nm_setting_sriov_get_eswitch_encap_mode ()</h3>
+<pre class="programlisting"><a class="link" href="NMSettingSriov.html#NMSriovEswitchEncapMode" title="enum NMSriovEswitchEncapMode"><span class="returnvalue">NMSriovEswitchEncapMode</span></a>
+nm_setting_sriov_get_eswitch_encap_mode
+                               (<em class="parameter"><code><a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a> *setting</code></em>);</pre>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-encap-mode.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>setting</p></td>
+<td class="parameter_description"><p>the <a class="link" href="NMSettingSriov.html" title="NMSettingSriov"><span class="type">NMSettingSriov</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nm-setting-sriov-get-eswitch-encap-mode.returns"></a><h4>Returns</h4>
+<p> the value contained in the <span class="type">“eswitch-encap-mode”</span> property.</p>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
 <a name="nm-sriov-vf-add-vlan"></a><h3>nm_sriov_vf_add_vlan ()</h3>
 <pre class="programlisting"><a href="https://developer.gnome.org/glib/unstable/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
 nm_sriov_vf_add_vlan (<em class="parameter"><code><a class="link" href="NMSettingSriov.html#NMSriovVF"><span class="type">NMSriovVF</span></a> *vf</code></em>,
@@ -1162,19 +1293,37 @@ the value is of the correct type and well-formed.</p>
 <hr>
 <div class="refsect2">
 <a name="NM-SETTING-SRIOV-TOTAL-VFS:CAPS"></a><h3>NM_SETTING_SRIOV_TOTAL_VFS</h3>
-<pre class="programlisting">#define NM_SETTING_SRIOV_TOTAL_VFS         "total-vfs"
+<pre class="programlisting">#define NM_SETTING_SRIOV_TOTAL_VFS           "total-vfs"
 </pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="NM-SETTING-SRIOV-VFS:CAPS"></a><h3>NM_SETTING_SRIOV_VFS</h3>
-<pre class="programlisting">#define NM_SETTING_SRIOV_VFS               "vfs"
+<pre class="programlisting">#define NM_SETTING_SRIOV_VFS                 "vfs"
 </pre>
 </div>
 <hr>
 <div class="refsect2">
 <a name="NM-SETTING-SRIOV-AUTOPROBE-DRIVERS:CAPS"></a><h3>NM_SETTING_SRIOV_AUTOPROBE_DRIVERS</h3>
-<pre class="programlisting">#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers"
+<pre class="programlisting">#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS   "autoprobe-drivers"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NM-SETTING-SRIOV-ESWITCH-MODE:CAPS"></a><h3>NM_SETTING_SRIOV_ESWITCH_MODE</h3>
+<pre class="programlisting">#define NM_SETTING_SRIOV_ESWITCH_MODE        "eswitch-mode"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NM-SETTING-SRIOV-ESWITCH-INLINE-MODE:CAPS"></a><h3>NM_SETTING_SRIOV_ESWITCH_INLINE_MODE</h3>
+<pre class="programlisting">#define NM_SETTING_SRIOV_ESWITCH_INLINE_MODE "eswitch-inline-mode"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NM-SETTING-SRIOV-ESWITCH-ENCAP-MODE:CAPS"></a><h3>NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE</h3>
+<pre class="programlisting">#define NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE  "eswitch-encap-mode"
 </pre>
 </div>
 <hr>
@@ -1239,6 +1388,149 @@ the value is of the correct type and well-formed.</p>
 </div>
 <p class="since">Since: 1.14</p>
 </div>
+<hr>
+<div class="refsect2">
+<a name="NMSriovEswitchMode"></a><h3>enum NMSriovEswitchMode</h3>
+<div class="refsect3">
+<a name="NMSriovEswitchMode.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-MODE-PRESERVE:CAPS"></a>NM_SRIOV_ESWITCH_MODE_PRESERVE</p></td>
+<td class="enum_member_description">
+<p>don't modify current eswitch mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-MODE-UNKNOWN:CAPS"></a>NM_SRIOV_ESWITCH_MODE_UNKNOWN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-MODE-LEGACY:CAPS"></a>NM_SRIOV_ESWITCH_MODE_LEGACY</p></td>
+<td class="enum_member_description">
+<p>use legacy SRIOV</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-MODE-SWITCHDEV:CAPS"></a>NM_SRIOV_ESWITCH_MODE_SWITCHDEV</p></td>
+<td class="enum_member_description">
+<p>use switchdev mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NMSriovEswitchInlineMode"></a><h3>enum NMSriovEswitchInlineMode</h3>
+<div class="refsect3">
+<a name="NMSriovEswitchInlineMode.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-PRESERVE:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE</p></td>
+<td class="enum_member_description">
+<p>don't modify current inline-mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-UNKNOWN:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_UNKNOWN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-NONE:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_NONE</p></td>
+<td class="enum_member_description">
+<p>don't use inline mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-LINK:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_LINK</p></td>
+<td class="enum_member_description">
+<p>L2 mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-NETWORK:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_NETWORK</p></td>
+<td class="enum_member_description">
+<p>L3 mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-INLINE-MODE-TRANSPORT:CAPS"></a>NM_SRIOV_ESWITCH_INLINE_MODE_TRANSPORT</p></td>
+<td class="enum_member_description">
+<p>L4 mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NMSriovEswitchEncapMode"></a><h3>enum NMSriovEswitchEncapMode</h3>
+<div class="refsect3">
+<a name="NMSriovEswitchEncapMode.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-ENCAP-MODE-PRESERVE:CAPS"></a>NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE</p></td>
+<td class="enum_member_description">
+<p>don't modify current encap-mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-ENCAP-MODE-UNKNOWN:CAPS"></a>NM_SRIOV_ESWITCH_ENCAP_MODE_UNKNOWN</p></td>
+<td> </td>
+<td> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-ENCAP-MODE-NONE:CAPS"></a>NM_SRIOV_ESWITCH_ENCAP_MODE_NONE</p></td>
+<td class="enum_member_description">
+<p>disable encapsulation mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-SRIOV-ESWITCH-ENCAP-MODE-BASIC:CAPS"></a>NM_SRIOV_ESWITCH_ENCAP_MODE_BASIC</p></td>
+<td class="enum_member_description">
+<p>enable encapsulation mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: 1.46</p>
+</div>
 </div>
 </div>
 <div class="footer">
diff --git a/docs/libnm/html/api-index-full.html b/docs/libnm/html/api-index-full.html
index 19fac919..809b5920 100644
--- a/docs/libnm/html/api-index-full.html
+++ b/docs/libnm/html/api-index-full.html
@@ -6060,6 +6060,18 @@ NMConnection::secrets-updated, object signal in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE:CAPS" title="NM_SECRET_TAG_DYNAMIC_CHALLENGE">NM_SECRET_TAG_DYNAMIC_CHALLENGE</a>, macro in <a class="link" href="libnm-nm-dbus-interface.html" title="nm-dbus-interface">nm-dbus-interface</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE-ECHO:CAPS" title="NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO">NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO</a>, macro in <a class="link" href="libnm-nm-dbus-interface.html" title="nm-dbus-interface">nm-dbus-interface</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-VPN-MSG:CAPS" title="NM_SECRET_TAG_VPN_MSG">NM_SECRET_TAG_VPN_MSG</a>, macro in <a class="link" href="libnm-nm-dbus-interface.html" title="nm-dbus-interface">nm-dbus-interface</a>
+</dt>
+<dd></dd>
+<dt>
 NMSetting, struct in NMSettingOvs
 </dt>
 <dd></dd>
@@ -6740,6 +6752,10 @@ NMSettingGeneric, struct in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+NMSettingGeneric:device-handler, object property in NMSettingOvs
+</dt>
+<dd></dd>
+<dt>
 NMSettingGsm, struct in NMSettingOvs
 </dt>
 <dd></dd>
@@ -7156,6 +7172,10 @@ NMSettingMacsec:mode, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+NMSettingMacsec:offload, object property in NMSettingOvs
+</dt>
+<dd></dd>
+<dt>
 NMSettingMacsec:parent, object property in NMSettingOvs
 </dt>
 <dd></dd>
@@ -7176,6 +7196,10 @@ NMSettingMacsec:validation, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingMacsec.html#NMSettingMacsecOffload" title="enum NMSettingMacsecOffload">NMSettingMacsecOffload</a>, enum in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingMacsec.html#NMSettingMacsecValidation" title="enum NMSettingMacsecValidation">NMSettingMacsecValidation</a>, enum in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
 </dt>
 <dd></dd>
@@ -7528,6 +7552,18 @@ NMSettingSriov:autoprobe-drivers, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+NMSettingSriov:eswitch-encap-mode, object property in NMSettingOvs
+</dt>
+<dd></dd>
+<dt>
+NMSettingSriov:eswitch-inline-mode, object property in NMSettingOvs
+</dt>
+<dd></dd>
+<dt>
+NMSettingSriov:eswitch-mode, object property in NMSettingOvs
+</dt>
+<dd></dd>
+<dt>
 NMSettingSriov:total-vfs, object property in NMSettingOvs
 </dt>
 <dd></dd>
@@ -10024,6 +10060,14 @@ NMSettingWpan:short-address, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingGeneric.html#NM-SETTING-GENERIC-DEVICE-HANDLER:CAPS" title="NM_SETTING_GENERIC_DEVICE_HANDLER">NM_SETTING_GENERIC_DEVICE_HANDLER</a>, macro in <a class="link" href="NMSettingGeneric.html" title="NMSettingGeneric">NMSettingGeneric</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingGeneric.html#nm-setting-generic-get-device-handler" title="nm_setting_generic_get_device_handler ()">nm_setting_generic_get_device_handler</a>, function in <a class="link" href="NMSettingGeneric.html" title="NMSettingGeneric">NMSettingGeneric</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingGeneric.html#nm-setting-generic-new" title="nm_setting_generic_new ()">nm_setting_generic_new</a>, function in <a class="link" href="NMSettingGeneric.html" title="NMSettingGeneric">NMSettingGeneric</a>
 </dt>
 <dd></dd>
@@ -10036,6 +10080,10 @@ NMSettingWpan:short-address, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSetting.html#nm-setting-get-enum-property-type" title="nm_setting_get_enum_property_type ()">nm_setting_get_enum_property_type</a>, function in <a class="link" href="NMSetting.html" title="NMSetting">NMSetting</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSetting.html#nm-setting-get-name" title="nm_setting_get_name ()">nm_setting_get_name</a>, function in <a class="link" href="NMSetting.html" title="NMSetting">NMSetting</a>
 </dt>
 <dd></dd>
@@ -11012,6 +11060,10 @@ NMSettingWpan:short-address, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingMacsec.html#nm-setting-macsec-get-offload" title="nm_setting_macsec_get_offload ()">nm_setting_macsec_get_offload</a>, function in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingMacsec.html#nm-setting-macsec-get-parent" title="nm_setting_macsec_get_parent ()">nm_setting_macsec_get_parent</a>, function in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
 </dt>
 <dd></dd>
@@ -11056,6 +11108,10 @@ NMSettingWpan:short-address, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD:CAPS" title="NM_SETTING_MACSEC_OFFLOAD">NM_SETTING_MACSEC_OFFLOAD</a>, macro in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingMacsec.html#NM-SETTING-MACSEC-PARENT:CAPS" title="NM_SETTING_MACSEC_PARENT">NM_SETTING_MACSEC_PARENT</a>, macro in <a class="link" href="NMSettingMacsec.html" title="NMSettingMacsec">NMSettingMacsec</a>
 </dt>
 <dd></dd>
@@ -11904,10 +11960,34 @@ NMSettingWpan:short-address, object property in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-ENCAP-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE">NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE</a>, macro in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-INLINE-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_INLINE_MODE">NM_SETTING_SRIOV_ESWITCH_INLINE_MODE</a>, macro in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-MODE:CAPS" title="NM_SETTING_SRIOV_ESWITCH_MODE">NM_SETTING_SRIOV_ESWITCH_MODE</a>, macro in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-autoprobe-drivers" title="nm_setting_sriov_get_autoprobe_drivers ()">nm_setting_sriov_get_autoprobe_drivers</a>, function in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-encap-mode" title="nm_setting_sriov_get_eswitch_encap_mode ()">nm_setting_sriov_get_eswitch_encap_mode</a>, function in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-inline-mode" title="nm_setting_sriov_get_eswitch_inline_mode ()">nm_setting_sriov_get_eswitch_inline_mode</a>, function in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-eswitch-mode" title="nm_setting_sriov_get_eswitch_mode ()">nm_setting_sriov_get_eswitch_mode</a>, function in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingSriov.html#nm-setting-sriov-get-num-vfs" title="nm_setting_sriov_get_num_vfs ()">nm_setting_sriov_get_num_vfs</a>, function in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
 </dt>
 <dd></dd>
@@ -13628,6 +13708,18 @@ NMSimpleConnection, struct in NMSettingOvs
 </dt>
 <dd></dd>
 <dt>
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchEncapMode" title="enum NMSriovEswitchEncapMode">NMSriovEswitchEncapMode</a>, enum in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchInlineMode" title="enum NMSriovEswitchInlineMode">NMSriovEswitchInlineMode</a>, enum in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NMSettingSriov.html#NMSriovEswitchMode" title="enum NMSriovEswitchMode">NMSriovEswitchMode</a>, enum in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
+</dt>
+<dd></dd>
+<dt>
 <a class="link" href="NMSettingSriov.html#NMSriovVFVlanProtocol" title="enum NMSriovVFVlanProtocol">NMSriovVFVlanProtocol</a>, enum in <a class="link" href="NMSettingSriov.html" title="NMSettingSriov">NMSettingSriov</a>
 </dt>
 <dd></dd>
diff --git a/docs/libnm/html/index.html b/docs/libnm/html/index.html
index 5cbf323e..395c777c 100644
--- a/docs/libnm/html/index.html
+++ b/docs/libnm/html/index.html
@@ -15,7 +15,7 @@
 <div>
 <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">libnm Reference Manual</p></th></tr></table></div>
 <div><p class="releaseinfo">
-      for libnm 1.45.91
+      for libnm 1.46.0
 
       The latest version of this documentation can be found on-line at
       <a class="ulink" href="https://networkmanager.dev/docs/libnm/latest/" target="_top">https://networkmanager.dev/docs/libnm/latest/</a>.
diff --git a/docs/libnm/html/libnm-nm-dbus-interface.html b/docs/libnm/html/libnm-nm-dbus-interface.html
index ddb782bc..a275d9f0 100644
--- a/docs/libnm/html/libnm-nm-dbus-interface.html
+++ b/docs/libnm/html/libnm-nm-dbus-interface.html
@@ -532,6 +532,18 @@
 <td class="datatype_keyword">enum</td>
 <td class="function_name"><a class="link" href="libnm-nm-dbus-interface.html#NMMptcpFlags" title="enum NMMptcpFlags">NMMptcpFlags</a></td>
 </tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-VPN-MSG:CAPS" title="NM_SECRET_TAG_VPN_MSG">NM_SECRET_TAG_VPN_MSG</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE:CAPS" title="NM_SECRET_TAG_DYNAMIC_CHALLENGE">NM_SECRET_TAG_DYNAMIC_CHALLENGE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE-ECHO:CAPS" title="NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO">NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO</a></td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -2614,6 +2626,14 @@ network and is cleaning up the connection request</p>
 </td>
 <td class="enum_member_annotations"> </td>
 </tr>
+<tr>
+<td class="enum_member_name"><p><a name="NM-DEVICE-STATE-REASON-DEVICE-HANDLER-FAILED:CAPS"></a>NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED</p></td>
+<td class="enum_member_description">
+<p>The device handler dispatcher returned an
+error. Since: 1.46</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
 </tbody>
 </table></div>
 </div>
@@ -4308,6 +4328,24 @@ sub-option will trigger creation of an additional subflow to generate a full mes
 </div>
 <p class="since">Since: 1.40</p>
 </div>
+<hr>
+<div class="refsect2">
+<a name="NM-SECRET-TAG-VPN-MSG:CAPS"></a><h3>NM_SECRET_TAG_VPN_MSG</h3>
+<pre class="programlisting">#define NM_SECRET_TAG_VPN_MSG "x-vpn-message:"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NM-SECRET-TAG-DYNAMIC-CHALLENGE:CAPS"></a><h3>NM_SECRET_TAG_DYNAMIC_CHALLENGE</h3>
+<pre class="programlisting">#define NM_SECRET_TAG_DYNAMIC_CHALLENGE      "x-dynamic-challenge:"
+</pre>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NM-SECRET-TAG-DYNAMIC-CHALLENGE-ECHO:CAPS"></a><h3>NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO</h3>
+<pre class="programlisting">#define NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO "x-dynamic-challenge-echo:"
+</pre>
+</div>
 </div>
 </div>
 <div class="footer">
diff --git a/docs/libnm/html/libnm-nm-version-macros.html b/docs/libnm/html/libnm-nm-version-macros.html
index e0b0311e..84d453aa 100644
--- a/docs/libnm/html/libnm-nm-version-macros.html
+++ b/docs/libnm/html/libnm-nm-version-macros.html
@@ -257,7 +257,7 @@ is compiled against.</p>
 <hr>
 <div class="refsect2">
 <a name="NM-MINOR-VERSION:CAPS"></a><h3>NM_MINOR_VERSION</h3>
-<pre class="programlisting">#define NM_MINOR_VERSION (45)
+<pre class="programlisting">#define NM_MINOR_VERSION (46)
 </pre>
 <p>Evaluates to the minor version number of NetworkManager which this source
 is compiled against.</p>
@@ -265,7 +265,7 @@ is compiled against.</p>
 <hr>
 <div class="refsect2">
 <a name="NM-MICRO-VERSION:CAPS"></a><h3>NM_MICRO_VERSION</h3>
-<pre class="programlisting">#define NM_MICRO_VERSION (91)
+<pre class="programlisting">#define NM_MICRO_VERSION (0)
 </pre>
 <p>Evaluates to the micro version number of NetworkManager which this source
 compiled against.</p>
diff --git a/docs/libnm/html/libnm.devhelp2 b/docs/libnm/html/libnm.devhelp2
index 4f12cb2b..b021c174 100644
--- a/docs/libnm/html/libnm.devhelp2
+++ b/docs/libnm/html/libnm.devhelp2
@@ -520,6 +520,9 @@
     <keyword type="enum" name="enum NMClientPermissionResult" link="libnm-nm-dbus-interface.html#NMClientPermissionResult"/>
     <keyword type="enum" name="enum NMRadioFlags" link="libnm-nm-dbus-interface.html#NMRadioFlags" since="1.38"/>
     <keyword type="enum" name="enum NMMptcpFlags" link="libnm-nm-dbus-interface.html#NMMptcpFlags" since="1.40"/>
+    <keyword type="macro" name="NM_SECRET_TAG_VPN_MSG" link="libnm-nm-dbus-interface.html#NM-SECRET-TAG-VPN-MSG:CAPS"/>
+    <keyword type="macro" name="NM_SECRET_TAG_DYNAMIC_CHALLENGE" link="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE:CAPS"/>
+    <keyword type="macro" name="NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO" link="libnm-nm-dbus-interface.html#NM-SECRET-TAG-DYNAMIC-CHALLENGE-ECHO:CAPS"/>
     <keyword type="macro" name="NM_DEPRECATED_IN_1_8_FOR()" link="libnm-nm-vpn-dbus-interface.html#NM-DEPRECATED-IN-1-8-FOR:CAPS"/>
     <keyword type="macro" name="NM_DBUS_PATH_VPN" link="libnm-nm-vpn-dbus-interface.html#NM-DBUS-PATH-VPN:CAPS"/>
     <keyword type="macro" name="NM_DBUS_INTERFACE_VPN" link="libnm-nm-vpn-dbus-interface.html#NM-DBUS-INTERFACE-VPN:CAPS"/>
@@ -718,6 +721,7 @@
     <keyword type="function" name="nm_setting_option_get_all_names ()" link="NMSetting.html#nm-setting-option-get-all-names" since="1.26"/>
     <keyword type="function" name="nm_setting_option_clear_by_name ()" link="NMSetting.html#nm-setting-option-clear-by-name" since="1.26"/>
     <keyword type="function" name="nm_setting_get_dbus_property_type ()" link="NMSetting.html#nm-setting-get-dbus-property-type"/>
+    <keyword type="function" name="nm_setting_get_enum_property_type ()" link="NMSetting.html#nm-setting-get-enum-property-type" since="1.46"/>
     <keyword type="function" name="nm_range_new ()" link="NMSetting.html#nm-range-new" since="1.42"/>
     <keyword type="function" name="nm_range_ref ()" link="NMSetting.html#nm-range-ref" since="1.42"/>
     <keyword type="function" name="nm_range_unref ()" link="NMSetting.html#nm-range-unref" since="1.42"/>
@@ -1202,7 +1206,9 @@
     <keyword type="function" name="nm_setting_ethtool_clear_features ()" link="NMSettingEthtool.html#nm-setting-ethtool-clear-features" deprecated="1.26: use nm_setting_option_clear_by_name() with nm_ethtool_optname_is_feature() predicate instead." since="1.14"/>
     <keyword type="macro" name="NM_SETTING_ETHTOOL_SETTING_NAME" link="NMSettingEthtool.html#NM-SETTING-ETHTOOL-SETTING-NAME:CAPS"/>
     <keyword type="function" name="nm_setting_generic_new ()" link="NMSettingGeneric.html#nm-setting-generic-new"/>
+    <keyword type="function" name="nm_setting_generic_get_device_handler ()" link="NMSettingGeneric.html#nm-setting-generic-get-device-handler" since="1.46"/>
     <keyword type="macro" name="NM_SETTING_GENERIC_SETTING_NAME" link="NMSettingGeneric.html#NM-SETTING-GENERIC-SETTING-NAME:CAPS"/>
+    <keyword type="macro" name="NM_SETTING_GENERIC_DEVICE_HANDLER" link="NMSettingGeneric.html#NM-SETTING-GENERIC-DEVICE-HANDLER:CAPS"/>
     <keyword type="function" name="nm_setting_gsm_new ()" link="NMSettingGsm.html#nm-setting-gsm-new"/>
     <keyword type="function" name="nm_setting_gsm_get_auto_config ()" link="NMSettingGsm.html#nm-setting-gsm-get-auto-config" since="1.22"/>
     <keyword type="function" name="nm_setting_gsm_get_username ()" link="NMSettingGsm.html#nm-setting-gsm-get-username"/>
@@ -1586,6 +1592,7 @@
     <keyword type="function" name="nm_setting_macsec_get_port ()" link="NMSettingMacsec.html#nm-setting-macsec-get-port" since="1.6"/>
     <keyword type="function" name="nm_setting_macsec_get_validation ()" link="NMSettingMacsec.html#nm-setting-macsec-get-validation" since="1.6"/>
     <keyword type="function" name="nm_setting_macsec_get_send_sci ()" link="NMSettingMacsec.html#nm-setting-macsec-get-send-sci" since="1.12"/>
+    <keyword type="function" name="nm_setting_macsec_get_offload ()" link="NMSettingMacsec.html#nm-setting-macsec-get-offload" since="1.46"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_SETTING_NAME" link="NMSettingMacsec.html#NM-SETTING-MACSEC-SETTING-NAME:CAPS"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_PARENT" link="NMSettingMacsec.html#NM-SETTING-MACSEC-PARENT:CAPS"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_MODE" link="NMSettingMacsec.html#NM-SETTING-MACSEC-MODE:CAPS"/>
@@ -1596,10 +1603,12 @@
     <keyword type="macro" name="NM_SETTING_MACSEC_PORT" link="NMSettingMacsec.html#NM-SETTING-MACSEC-PORT:CAPS"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_VALIDATION" link="NMSettingMacsec.html#NM-SETTING-MACSEC-VALIDATION:CAPS"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_SEND_SCI" link="NMSettingMacsec.html#NM-SETTING-MACSEC-SEND-SCI:CAPS"/>
+    <keyword type="macro" name="NM_SETTING_MACSEC_OFFLOAD" link="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD:CAPS"/>
     <keyword type="enum" name="enum NMSettingMacsecMode" link="NMSettingMacsec.html#NMSettingMacsecMode" since="1.6"/>
     <keyword type="enum" name="enum NMSettingMacsecValidation" link="NMSettingMacsec.html#NMSettingMacsecValidation" since="1.6"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_MKA_CAK_LENGTH" link="NMSettingMacsec.html#NM-SETTING-MACSEC-MKA-CAK-LENGTH:CAPS"/>
     <keyword type="macro" name="NM_SETTING_MACSEC_MKA_CKN_LENGTH" link="NMSettingMacsec.html#NM-SETTING-MACSEC-MKA-CKN-LENGTH:CAPS"/>
+    <keyword type="enum" name="enum NMSettingMacsecOffload" link="NMSettingMacsec.html#NMSettingMacsecOffload" since="1.46"/>
     <keyword type="function" name="nm_setting_macvlan_new ()" link="NMSettingMacvlan.html#nm-setting-macvlan-new" since="1.2"/>
     <keyword type="function" name="nm_setting_macvlan_get_parent ()" link="NMSettingMacvlan.html#nm-setting-macvlan-get-parent" since="1.2"/>
     <keyword type="function" name="nm_setting_macvlan_get_mode ()" link="NMSettingMacvlan.html#nm-setting-macvlan-get-mode" since="1.2"/>
@@ -1803,6 +1812,9 @@
     <keyword type="function" name="nm_setting_sriov_remove_vf_by_index ()" link="NMSettingSriov.html#nm-setting-sriov-remove-vf-by-index" since="1.14"/>
     <keyword type="function" name="nm_setting_sriov_clear_vfs ()" link="NMSettingSriov.html#nm-setting-sriov-clear-vfs" since="1.14"/>
     <keyword type="function" name="nm_setting_sriov_get_autoprobe_drivers ()" link="NMSettingSriov.html#nm-setting-sriov-get-autoprobe-drivers" since="1.14"/>
+    <keyword type="function" name="nm_setting_sriov_get_eswitch_mode ()" link="NMSettingSriov.html#nm-setting-sriov-get-eswitch-mode" since="1.46"/>
+    <keyword type="function" name="nm_setting_sriov_get_eswitch_inline_mode ()" link="NMSettingSriov.html#nm-setting-sriov-get-eswitch-inline-mode" since="1.46"/>
+    <keyword type="function" name="nm_setting_sriov_get_eswitch_encap_mode ()" link="NMSettingSriov.html#nm-setting-sriov-get-eswitch-encap-mode" since="1.46"/>
     <keyword type="function" name="nm_sriov_vf_add_vlan ()" link="NMSettingSriov.html#nm-sriov-vf-add-vlan" since="1.14"/>
     <keyword type="function" name="nm_sriov_vf_remove_vlan ()" link="NMSettingSriov.html#nm-sriov-vf-remove-vlan" since="1.14"/>
     <keyword type="function" name="nm_sriov_vf_get_vlan_ids ()" link="NMSettingSriov.html#nm-sriov-vf-get-vlan-ids" since="1.14"/>
@@ -1824,12 +1836,18 @@
     <keyword type="macro" name="NM_SETTING_SRIOV_TOTAL_VFS" link="NMSettingSriov.html#NM-SETTING-SRIOV-TOTAL-VFS:CAPS"/>
     <keyword type="macro" name="NM_SETTING_SRIOV_VFS" link="NMSettingSriov.html#NM-SETTING-SRIOV-VFS:CAPS"/>
     <keyword type="macro" name="NM_SETTING_SRIOV_AUTOPROBE_DRIVERS" link="NMSettingSriov.html#NM-SETTING-SRIOV-AUTOPROBE-DRIVERS:CAPS"/>
+    <keyword type="macro" name="NM_SETTING_SRIOV_ESWITCH_MODE" link="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-MODE:CAPS"/>
+    <keyword type="macro" name="NM_SETTING_SRIOV_ESWITCH_INLINE_MODE" link="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-INLINE-MODE:CAPS"/>
+    <keyword type="macro" name="NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE" link="NMSettingSriov.html#NM-SETTING-SRIOV-ESWITCH-ENCAP-MODE:CAPS"/>
     <keyword type="macro" name="NM_SRIOV_VF_ATTRIBUTE_MAC" link="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-MAC:CAPS"/>
     <keyword type="macro" name="NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK" link="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-SPOOF-CHECK:CAPS"/>
     <keyword type="macro" name="NM_SRIOV_VF_ATTRIBUTE_TRUST" link="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-TRUST:CAPS"/>
     <keyword type="macro" name="NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE" link="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-MIN-TX-RATE:CAPS"/>
     <keyword type="macro" name="NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE" link="NMSettingSriov.html#NM-SRIOV-VF-ATTRIBUTE-MAX-TX-RATE:CAPS"/>
     <keyword type="enum" name="enum NMSriovVFVlanProtocol" link="NMSettingSriov.html#NMSriovVFVlanProtocol" since="1.14"/>
+    <keyword type="enum" name="enum NMSriovEswitchMode" link="NMSettingSriov.html#NMSriovEswitchMode" since="1.46"/>
+    <keyword type="enum" name="enum NMSriovEswitchInlineMode" link="NMSettingSriov.html#NMSriovEswitchInlineMode" since="1.46"/>
+    <keyword type="enum" name="enum NMSriovEswitchEncapMode" link="NMSettingSriov.html#NMSriovEswitchEncapMode" since="1.46"/>
     <keyword type="function" name="nm_tc_qdisc_new ()" link="NMSettingTCConfig.html#nm-tc-qdisc-new" since="1.12"/>
     <keyword type="function" name="nm_tc_qdisc_ref ()" link="NMSettingTCConfig.html#nm-tc-qdisc-ref" since="1.12"/>
     <keyword type="function" name="nm_tc_qdisc_unref ()" link="NMSettingTCConfig.html#nm-tc-qdisc-unref" since="1.12"/>
@@ -3740,6 +3758,7 @@
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED" link="libnm-nm-dbus-interface.html#NM-DEVICE-STATE-REASON-IP-METHOD-UNSUPPORTED:CAPS"/>
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED" link="libnm-nm-dbus-interface.html#NM-DEVICE-STATE-REASON-SRIOV-CONFIGURATION-FAILED:CAPS"/>
     <keyword type="constant" name="NM_DEVICE_STATE_REASON_PEER_NOT_FOUND" link="libnm-nm-dbus-interface.html#NM-DEVICE-STATE-REASON-PEER-NOT-FOUND:CAPS"/>
+    <keyword type="constant" name="NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED" link="libnm-nm-dbus-interface.html#NM-DEVICE-STATE-REASON-DEVICE-HANDLER-FAILED:CAPS"/>
     <keyword type="constant" name="NM_METERED_UNKNOWN" link="libnm-nm-dbus-interface.html#NM-METERED-UNKNOWN:CAPS"/>
     <keyword type="constant" name="NM_METERED_YES" link="libnm-nm-dbus-interface.html#NM-METERED-YES:CAPS"/>
     <keyword type="constant" name="NM_METERED_NO" link="libnm-nm-dbus-interface.html#NM-METERED-NO:CAPS"/>
@@ -4013,6 +4032,10 @@
     <keyword type="constant" name="NM_SETTING_MACSEC_VALIDATION_DISABLE" link="NMSettingMacsec.html#NM-SETTING-MACSEC-VALIDATION-DISABLE:CAPS"/>
     <keyword type="constant" name="NM_SETTING_MACSEC_VALIDATION_CHECK" link="NMSettingMacsec.html#NM-SETTING-MACSEC-VALIDATION-CHECK:CAPS"/>
     <keyword type="constant" name="NM_SETTING_MACSEC_VALIDATION_STRICT" link="NMSettingMacsec.html#NM-SETTING-MACSEC-VALIDATION-STRICT:CAPS"/>
+    <keyword type="constant" name="NM_SETTING_MACSEC_OFFLOAD_DEFAULT" link="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD-DEFAULT:CAPS"/>
+    <keyword type="constant" name="NM_SETTING_MACSEC_OFFLOAD_OFF" link="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD-OFF:CAPS"/>
+    <keyword type="constant" name="NM_SETTING_MACSEC_OFFLOAD_PHY" link="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD-PHY:CAPS"/>
+    <keyword type="constant" name="NM_SETTING_MACSEC_OFFLOAD_MAC" link="NMSettingMacsec.html#NM-SETTING-MACSEC-OFFLOAD-MAC:CAPS"/>
     <keyword type="constant" name="NM_SETTING_MACVLAN_MODE_UNKNOWN" link="NMSettingMacvlan.html#NM-SETTING-MACVLAN-MODE-UNKNOWN:CAPS"/>
     <keyword type="constant" name="NM_SETTING_MACVLAN_MODE_VEPA" link="NMSettingMacvlan.html#NM-SETTING-MACVLAN-MODE-VEPA:CAPS"/>
     <keyword type="constant" name="NM_SETTING_MACVLAN_MODE_BRIDGE" link="NMSettingMacvlan.html#NM-SETTING-MACVLAN-MODE-BRIDGE:CAPS"/>
@@ -4028,6 +4051,20 @@
     <keyword type="constant" name="NM_SETTING_SERIAL_PARITY_ODD" link="NMSettingSerial.html#NM-SETTING-SERIAL-PARITY-ODD:CAPS"/>
     <keyword type="constant" name="NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q" link="NMSettingSriov.html#NM-SRIOV-VF-VLAN-PROTOCOL-802-1Q:CAPS"/>
     <keyword type="constant" name="NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD" link="NMSettingSriov.html#NM-SRIOV-VF-VLAN-PROTOCOL-802-1AD:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_MODE_PRESERVE" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-MODE-PRESERVE:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_MODE_UNKNOWN" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-MODE-UNKNOWN:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_MODE_LEGACY" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-MODE-LEGACY:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_MODE_SWITCHDEV" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-MODE-SWITCHDEV:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-PRESERVE:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_UNKNOWN" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-UNKNOWN:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_NONE" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-NONE:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_LINK" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-LINK:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_NETWORK" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-NETWORK:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_INLINE_MODE_TRANSPORT" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-INLINE-MODE-TRANSPORT:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-ENCAP-MODE-PRESERVE:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_ENCAP_MODE_UNKNOWN" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-ENCAP-MODE-UNKNOWN:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_ENCAP_MODE_NONE" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-ENCAP-MODE-NONE:CAPS"/>
+    <keyword type="constant" name="NM_SRIOV_ESWITCH_ENCAP_MODE_BASIC" link="NMSettingSriov.html#NM-SRIOV-ESWITCH-ENCAP-MODE-BASIC:CAPS"/>
     <keyword type="constant" name="NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_NONE" link="NMSettingTeam.html#NM-TEAM-LINK-WATCHER-ARP-PING-FLAG-NONE:CAPS"/>
     <keyword type="constant" name="NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_ACTIVE" link="NMSettingTeam.html#NM-TEAM-LINK-WATCHER-ARP-PING-FLAG-VALIDATE-ACTIVE:CAPS"/>
     <keyword type="constant" name="NM_TEAM_LINK_WATCHER_ARP_PING_FLAG_VALIDATE_INACTIVE" link="NMSettingTeam.html#NM-TEAM-LINK-WATCHER-ARP-PING-FLAG-VALIDATE-INACTIVE:CAPS"/>
diff --git a/docs/libnm/html/object-tree.html b/docs/libnm/html/object-tree.html
index 60ccc96c..8fc9acd3 100644
--- a/docs/libnm/html/object-tree.html
+++ b/docs/libnm/html/object-tree.html
@@ -208,6 +208,7 @@
     <span class="lineart">├──</span> <a class="link" href="NMSettingIP6Config.html#NMSettingIP6ConfigPrivacy" title="enum NMSettingIP6ConfigPrivacy">NMSettingIP6ConfigPrivacy</a>
     <span class="lineart">├──</span> <a class="link" href="NMSetting.html#NMSettingMacRandomization" title="enum NMSettingMacRandomization">NMSettingMacRandomization</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingMacsec.html#NMSettingMacsecMode" title="enum NMSettingMacsecMode">NMSettingMacsecMode</a>
+    <span class="lineart">├──</span> <a class="link" href="NMSettingMacsec.html#NMSettingMacsecOffload" title="enum NMSettingMacsecOffload">NMSettingMacsecOffload</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingMacsec.html#NMSettingMacsecValidation" title="enum NMSettingMacsecValidation">NMSettingMacsecValidation</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingMacvlan.html#NMSettingMacvlanMode" title="enum NMSettingMacvlanMode">NMSettingMacvlanMode</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingProxy.html#NMSettingProxyMethod" title="enum NMSettingProxyMethod">NMSettingProxyMethod</a>
@@ -216,6 +217,9 @@
     <span class="lineart">├──</span> <a class="link" href="NMSettingWireless.html#NMSettingWirelessPowersave" title="enum NMSettingWirelessPowersave">NMSettingWirelessPowersave</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingWirelessSecurity.html#NMSettingWirelessSecurityFils" title="enum NMSettingWirelessSecurityFils">NMSettingWirelessSecurityFils</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingWirelessSecurity.html#NMSettingWirelessSecurityPmf" title="enum NMSettingWirelessSecurityPmf">NMSettingWirelessSecurityPmf</a>
+    <span class="lineart">├──</span> <a class="link" href="NMSettingSriov.html#NMSriovEswitchEncapMode" title="enum NMSriovEswitchEncapMode">NMSriovEswitchEncapMode</a>
+    <span class="lineart">├──</span> <a class="link" href="NMSettingSriov.html#NMSriovEswitchInlineMode" title="enum NMSriovEswitchInlineMode">NMSriovEswitchInlineMode</a>
+    <span class="lineart">├──</span> <a class="link" href="NMSettingSriov.html#NMSriovEswitchMode" title="enum NMSriovEswitchMode">NMSriovEswitchMode</a>
     <span class="lineart">├──</span> <a class="link" href="NMSettingSriov.html#NMSriovVFVlanProtocol" title="enum NMSriovVFVlanProtocol">NMSriovVFVlanProtocol</a>
     <span class="lineart">├──</span> <a class="link" href="libnm-nm-dbus-interface.html#NMState" title="enum NMState">NMState</a>
     <span class="lineart">├──</span> <a class="link" href="libnm-nm-dbus-interface.html#NMTernary" title="enum NMTernary">NMTernary</a>
diff --git a/docs/libnm/html/usage.html b/docs/libnm/html/usage.html
index 56b9df61..cc9db2ab 100644
--- a/docs/libnm/html/usage.html
+++ b/docs/libnm/html/usage.html
@@ -96,7 +96,7 @@
         </p>
 <pre class="screen"><code class="prompt">$ </code><strong class="userinput"><code>cc $(pkg-config --libs --cflags libnm) -o hello-nm hello-nm.c</code></strong>
   <code class="prompt">$ </code><strong class="userinput"><code>./hello-nm</code></strong>
-  NetworkManager version: 1.45.91
+  NetworkManager version: 1.46.0
 
   <code class="prompt">$ </code></pre>
 <p>
diff --git a/docs/libnm/libnm-sections.txt b/docs/libnm/libnm-sections.txt
index 492f35f6..de2998e0 100644
--- a/docs/libnm/libnm-sections.txt
+++ b/docs/libnm/libnm-sections.txt
@@ -440,6 +440,7 @@ NM_TYPE_SETTING_IP4_LINK_LOCAL
 NM_TYPE_SETTING_IP6_CONFIG_ADDR_GEN_MODE
 NM_TYPE_SETTING_IP6_CONFIG_PRIVACY
 NM_TYPE_SETTING_MACSEC_MODE
+NM_TYPE_SETTING_MACSEC_OFFLOAD
 NM_TYPE_SETTING_MACSEC_VALIDATION
 NM_TYPE_SETTING_MACVLAN_MODE
 NM_TYPE_SETTING_MAC_RANDOMIZATION
@@ -453,6 +454,9 @@ NM_TYPE_SETTING_WIRELESS_SECURITY_FILS
 NM_TYPE_SETTING_WIRELESS_SECURITY_PMF
 NM_TYPE_SETTING_WIRELESS_SECURITY_WPS_METHOD
 NM_TYPE_SETTING_WIRELESS_WAKE_ON_WLAN
+NM_TYPE_SRIOV_ESWITCH_ENCAP_MODE
+NM_TYPE_SRIOV_ESWITCH_INLINE_MODE
+NM_TYPE_SRIOV_ESWITCH_MODE
 NM_TYPE_SRIOV_VF_VLAN_PROTOCOL
 NM_TYPE_STATE
 NM_TYPE_TEAM_LINK_WATCHER_ARP_PING_FLAGS
@@ -522,6 +526,7 @@ nm_setting_ip6_config_addr_gen_mode_get_type
 nm_setting_ip6_config_privacy_get_type
 nm_setting_mac_randomization_get_type
 nm_setting_macsec_mode_get_type
+nm_setting_macsec_offload_get_type
 nm_setting_macsec_validation_get_type
 nm_setting_macvlan_mode_get_type
 nm_setting_proxy_method_get_type
@@ -538,6 +543,9 @@ nm_settings_add_connection2_flags_get_type
 nm_settings_connection_flags_get_type
 nm_settings_error_get_type
 nm_settings_update2_flags_get_type
+nm_sriov_eswitch_encap_mode_get_type
+nm_sriov_eswitch_inline_mode_get_type
+nm_sriov_eswitch_mode_get_type
 nm_sriov_vf_vlan_protocol_get_type
 nm_state_get_type
 nm_team_link_watcher_arp_ping_flags_get_type
@@ -744,6 +752,9 @@ NMClientPermission
 NMClientPermissionResult
 NMRadioFlags
 NMMptcpFlags
+NM_SECRET_TAG_VPN_MSG
+NM_SECRET_TAG_DYNAMIC_CHALLENGE
+NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO
 </SECTION>
 
 <SECTION>
@@ -1915,6 +1926,7 @@ nm_setting_option_set_boolean
 nm_setting_option_get_all_names
 nm_setting_option_clear_by_name
 nm_setting_get_dbus_property_type
+nm_setting_get_enum_property_type
 nm_range_new
 nm_range_ref
 nm_range_unref
@@ -2591,7 +2603,9 @@ nm_setting_ethtool_get_type
 <FILE>nm-setting-generic</FILE>
 <TITLE>NMSettingGeneric</TITLE>
 NM_SETTING_GENERIC_SETTING_NAME
+NM_SETTING_GENERIC_DEVICE_HANDLER
 nm_setting_generic_new
+nm_setting_generic_get_device_handler
 <SUBSECTION Standard>
 NMSettingGenericClass
 NM_IS_SETTING_GENERIC
@@ -3134,10 +3148,12 @@ NM_SETTING_MACSEC_MKA_CKN
 NM_SETTING_MACSEC_PORT
 NM_SETTING_MACSEC_VALIDATION
 NM_SETTING_MACSEC_SEND_SCI
+NM_SETTING_MACSEC_OFFLOAD
 NMSettingMacsecMode
 NMSettingMacsecValidation
 NM_SETTING_MACSEC_MKA_CAK_LENGTH
 NM_SETTING_MACSEC_MKA_CKN_LENGTH
+NMSettingMacsecOffload
 nm_setting_macsec_new
 nm_setting_macsec_get_parent
 nm_setting_macsec_get_mode
@@ -3148,6 +3164,7 @@ nm_setting_macsec_get_mka_ckn
 nm_setting_macsec_get_port
 nm_setting_macsec_get_validation
 nm_setting_macsec_get_send_sci
+nm_setting_macsec_get_offload
 <SUBSECTION Standard>
 NMSettingMacsecClass
 NM_IS_SETTING_MACSEC
@@ -3556,12 +3573,18 @@ NM_SETTING_SRIOV_SETTING_NAME
 NM_SETTING_SRIOV_TOTAL_VFS
 NM_SETTING_SRIOV_VFS
 NM_SETTING_SRIOV_AUTOPROBE_DRIVERS
+NM_SETTING_SRIOV_ESWITCH_MODE
+NM_SETTING_SRIOV_ESWITCH_INLINE_MODE
+NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE
 NM_SRIOV_VF_ATTRIBUTE_MAC
 NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK
 NM_SRIOV_VF_ATTRIBUTE_TRUST
 NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE
 NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE
 NMSriovVFVlanProtocol
+NMSriovEswitchMode
+NMSriovEswitchInlineMode
+NMSriovEswitchEncapMode
 nm_setting_sriov_new
 nm_setting_sriov_get_total_vfs
 nm_setting_sriov_get_num_vfs
@@ -3571,6 +3594,9 @@ nm_setting_sriov_remove_vf
 nm_setting_sriov_remove_vf_by_index
 nm_setting_sriov_clear_vfs
 nm_setting_sriov_get_autoprobe_drivers
+nm_setting_sriov_get_eswitch_mode
+nm_setting_sriov_get_eswitch_inline_mode
+nm_setting_sriov_get_eswitch_encap_mode
 nm_sriov_vf_add_vlan
 nm_sriov_vf_remove_vlan
 nm_sriov_vf_get_vlan_ids
diff --git a/docs/libnm/libnm.types b/docs/libnm/libnm.types
index f7e744c8..a20412f2 100644
--- a/docs/libnm/libnm.types
+++ b/docs/libnm/libnm.types
@@ -133,6 +133,7 @@ nm_setting_loopback_get_type
 nm_setting_mac_randomization_get_type
 nm_setting_macsec_get_type
 nm_setting_macsec_mode_get_type
+nm_setting_macsec_offload_get_type
 nm_setting_macsec_validation_get_type
 nm_setting_macvlan_get_type
 nm_setting_macvlan_mode_get_type
@@ -182,6 +183,9 @@ nm_settings_connection_flags_get_type
 nm_settings_error_get_type
 nm_settings_update2_flags_get_type
 nm_simple_connection_get_type
+nm_sriov_eswitch_encap_mode_get_type
+nm_sriov_eswitch_inline_mode_get_type
+nm_sriov_eswitch_mode_get_type
 nm_sriov_vf_get_type
 nm_sriov_vf_vlan_protocol_get_type
 nm_state_get_type
diff --git a/docs/libnm/version.xml b/docs/libnm/version.xml
index 24a58e09..0a3db35b 100644
--- a/docs/libnm/version.xml
+++ b/docs/libnm/version.xml
@@ -1 +1 @@
-1.45.91
+1.46.0
diff --git a/man/NetworkManager-dispatcher.8 b/man/NetworkManager-dispatcher.8
index 803f807b..4e263d62 100644
--- a/man/NetworkManager-dispatcher.8
+++ b/man/NetworkManager-dispatcher.8
@@ -2,9 +2,9 @@
 .\"     Title: NetworkManager-dispatcher
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Network management daemons
-.\"    Source: NetworkManager-dispatcher 1.45.91
+.\"    Source: NetworkManager-dispatcher 1.46.0
 .\"  Language: English
 .\"
 .TH "NETWORKMANAGER\-DISPATCHER" "8" "" "NetworkManager\-dispatcher 1\&" "Network management daemons"
@@ -130,6 +130,41 @@ The DNS configuration has changed\&. This action is raised even if NetworkManage
 /run/NetworkManager/resolv\&.conf
 .RE
 .PP
+\fIdevice\-add\fR
+.RS 4
+This action is called when a connection of type
+generic
+has the
+generic\&.device\-handler
+property set\&. The property indicates the name of a dispatcher script to be executed in directory
+/{etc,usr/lib}/NetworkManager/dispatcher\&.d/device\&. Note that differently from other actions, only one script is executed\&.
+.sp
+The script needs to perform any action needed to create the device for the generic connection\&. On successful termination, the script returns zero\&. Otherwise, it returns a non\-zero value to indicate an error\&. The script can return values to NetworkManager by writing to standard output; each line should contain a key name followed by the equal sign \*(Aq=\*(Aq and a key value\&. The keys understood at the moment are:
+.PP
+\fIIFINDEX\fR
+.RS 4
+Indicates the interface index of the interface created by the script\&. This key is required when the script succeeds; if it is not set, the activation will fail\&. The key is ignored in case of script failure\&.
+.RE
+.PP
+\fIERROR\fR
+.RS 4
+Specifies an error message indicating the cause of the script failure\&. It is ignored when the script succeeds\&.
+.RE
+.sp
+Since the dispatcher service captures stdout for parsing those keys, anything written to stdout will not appear in the dispatcher service journal log\&. Use stderr if you want to print messages to the journal (for example, for debugging)\&. Only the first 8KiB of stdout are considered and among those, only the first 64 lines; the rest is ignored\&.
+.RE
+.PP
+\fIdevice\-delete\fR
+.RS 4
+This action is the counterpart of
+device\-add
+and is called to delete the device for a generic connection\&. All the aspects described for
+device\-add
+also apply to this action, with the only exception that key
+\fIIFINDEX\fR
+is ignored\&. It is not necessary to delete the kernel link in the handler because NetworkManager already does that; therefore the action is useful for any additional cleanup needed\&.
+.RE
+.PP
 The environment contains more information about the interface and the connection\&. The following variables are available for the use in the dispatcher scripts:
 .PP
 \fINM_DISPATCHER_ACTION\fR
@@ -231,6 +266,72 @@ FULL\&. Note: this variable will only be set for connectivity\-change actions\&.
 .PP
 In case of VPN, VPN_IP_IFACE is set, and IP4_*, IP6_* variables with VPN prefix are exported too, like VPN_IP4_ADDRESS_0, VPN_IP4_NUM_ADDRESSES\&.
 .PP
+The content of the
+user
+setting for the connection being activated is also passed via environment variables\&. Each key is stored in a variable with name
+CONNECTION_USER_
+concatenated with the encoding of the key name\&. The encoding works as follows:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+lowercase letters become uppercase
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+uppercase letters are prefixed with an underscore
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+numbers do not change
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+a dot is replaced with a double underscore
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+any other character is encoded with an underscore followed by its 3\-digit octal representation
+.RE
+.sp
+For example, key
+test\&.foo\-Bar2
+is stored in a variable named
+CONNECTION_USER_TEST__FOO_055_BAR2\&.
+.PP
 Dispatcher scripts are run one at a time, but asynchronously from the main NetworkManager process, and will be killed if they run for too long\&. If your script might take arbitrarily long to complete, you should spawn a child process and have the parent return immediately\&. Scripts that are symbolic links pointing inside the
 /etc/NetworkManager/dispatcher\&.d/no\-wait\&.d/
 directory are run immediately, without waiting for the termination of previous scripts, and in parallel\&. Also beware that once a script is queued, it will always be run, even if a later event renders it obsolete\&. (Eg, if an interface goes up, and then back down again quickly, it is possible that one or more "up" scripts will be run after the interface has gone down\&.)
diff --git a/man/NetworkManager-dispatcher.xml b/man/NetworkManager-dispatcher.xml
index f6e1d22d..f85a495a 100644
--- a/man/NetworkManager-dispatcher.xml
+++ b/man/NetworkManager-dispatcher.xml
@@ -172,6 +172,63 @@
             looking at file <filename>/run/NetworkManager/resolv.conf</filename>
         </para></listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>device-add</varname></term>
+        <listitem>
+          <para>
+            This action is called when a connection of type <literal>generic</literal>
+            has the <literal>generic.device-handler</literal> property set. The property
+            indicates the name of a dispatcher script to be executed in directory
+            <filename>/{etc,usr/lib}/NetworkManager/dispatcher.d/device</filename>. Note
+            that differently from other actions, only one script is executed.
+          </para>
+          <para>
+            The script needs to perform any action needed to create the device
+            for the generic connection. On successful termination, the script
+            returns zero. Otherwise, it returns a non-zero value to indicate an
+            error. The script can return values to NetworkManager by writing to
+            standard output; each line should contain a key name followed by the
+            equal sign '=' and a key value. The keys understood at the moment
+            are:
+            <variablelist>
+              <varlistentry>
+                <term><varname>IFINDEX</varname></term>
+                <listitem><para> Indicates the interface index of the interface
+                created by the script. This key is required when the script
+                succeeds; if it is not set, the activation will fail. The key is
+                ignored in case of script failure. </para></listitem>
+              </varlistentry>
+              <varlistentry>
+                <term><varname>ERROR</varname></term>
+                <listitem><para> Specifies an error message indicating the cause
+                of the script failure. It is ignored when the script succeeds.
+                </para></listitem>
+              </varlistentry>
+            </variablelist>
+            Since the dispatcher service captures stdout for parsing those keys,
+            anything written to stdout will not appear in the dispatcher service
+            journal log. Use stderr if you want to print messages to the journal
+            (for example, for debugging). Only the first 8KiB of stdout are
+            considered and among those, only the first 64 lines; the rest is
+            ignored.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>device-delete</varname></term>
+        <listitem>
+          <para>
+            This action is the counterpart of <literal>device-add</literal> and
+            is called to delete the device for a generic connection. All the
+            aspects described for <literal>device-add</literal> also apply to
+            this action, with the only exception that key
+            <varname>IFINDEX</varname> is ignored. It is not necessary to delete
+            the kernel link in the handler because NetworkManager already does
+            that; therefore the action is useful for any additional cleanup
+            needed.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
     <para>
       The environment contains more information about the interface and the connection.
@@ -309,6 +366,33 @@
       exported too, like VPN_IP4_ADDRESS_0, VPN_IP4_NUM_ADDRESSES.
     </para>
     <para>
+      The content of the <literal>user</literal> setting for the connection
+      being activated is also passed via environment variables. Each key is
+      stored in a variable with name <literal>CONNECTION_USER_</literal>
+      concatenated with the encoding of the key name. The encoding works as
+      follows:
+      <itemizedlist>
+        <listitem>
+          <para>lowercase letters become uppercase</para>
+        </listitem>
+        <listitem>
+          <para>uppercase letters are prefixed with an underscore</para>
+        </listitem>
+        <listitem>
+          <para>numbers do not change</para>
+        </listitem>
+        <listitem>
+          <para>a dot is replaced with a double underscore</para>
+        </listitem>
+        <listitem>
+          <para>any other character is encoded with an underscore followed by
+          its 3-digit octal representation</para>
+        </listitem>
+      </itemizedlist>
+      For example, key <literal>test.foo-Bar2</literal> is stored in a variable named
+      <literal>CONNECTION_USER_TEST__FOO_055_BAR2</literal>.
+    </para>
+    <para>
       Dispatcher scripts are run one at a time, but asynchronously from the main
       NetworkManager process, and will be killed if they run for too long. If your script
       might take arbitrarily long to complete, you should spawn a child process and have the
diff --git a/man/NetworkManager-wait-online.service.8 b/man/NetworkManager-wait-online.service.8
index 971644cb..17f61261 100644
--- a/man/NetworkManager-wait-online.service.8
+++ b/man/NetworkManager-wait-online.service.8
@@ -2,9 +2,9 @@
 .\"     Title: NetworkManager-wait-online.service
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Network management daemons
-.\"    Source: NetworkManager-wait-online.service 1.45.91
+.\"    Source: NetworkManager-wait-online.service 1.46.0
 .\"  Language: English
 .\"
 .TH "NETWORKMANAGER\-WAIT\-ONLINE\&" "8" "" "NetworkManager\-wait\-online\&" "Network management daemons"
diff --git a/man/NetworkManager.8 b/man/NetworkManager.8
index 829e88c9..4233c56e 100644
--- a/man/NetworkManager.8
+++ b/man/NetworkManager.8
@@ -2,12 +2,12 @@
 .\"     Title: NetworkManager
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Network management daemons
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NETWORKMANAGER" "8" "" "NetworkManager 1\&.45\&.91" "Network management daemons"
+.TH "NETWORKMANAGER" "8" "" "NetworkManager 1\&.46\&.0" "Network management daemons"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/NetworkManager.conf.5 b/man/NetworkManager.conf.5
index 357da0c0..1fa1b2de 100644
--- a/man/NetworkManager.conf.5
+++ b/man/NetworkManager.conf.5
@@ -2,12 +2,12 @@
 .\"     Title: NetworkManager.conf
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Configuration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NETWORKMANAGER\&.CONF" "5" "" "NetworkManager 1\&.45\&.91" "Configuration"
+.TH "NETWORKMANAGER\&.CONF" "5" "" "NetworkManager 1\&.46\&.0" "Configuration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -985,6 +985,10 @@ If left unspecified, routes are only added to the main table\&. Note that this i
 If configured explicitly to 0, the MTU is not reconfigured during device activation unless it is required due to IPv6 constraints\&. If left unspecified, a DHCP/IPv6 SLAAC provided value is used or the MTU is left unspecified on activation\&.
 .RE
 .PP
+\fImacsec\&.offload\fR
+.RS 4
+.RE
+.PP
 \fIsriov\&.autoprobe\-drivers\fR
 .RS 4
 If left unspecified, drivers are autoprobed when the SR\-IOV VF gets created\&.
diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml
index 442c7140..69cfdb07 100644
--- a/man/NetworkManager.conf.xml
+++ b/man/NetworkManager.conf.xml
@@ -1022,6 +1022,9 @@ ipv6.ip6-privacy=0
           <listitem><para>If configured explicitly to 0, the MTU is not reconfigured during device activation unless it is required due to IPv6 constraints. If left unspecified, a DHCP/IPv6 SLAAC provided value is used or the MTU is left unspecified on activation.</para></listitem>
         </varlistentry>
         <varlistentry>
+          <term><varname>macsec.offload</varname></term>
+        </varlistentry>
+        <varlistentry>
           <term><varname>sriov.autoprobe-drivers</varname></term>
           <listitem><para>If left unspecified, drivers are autoprobed when the SR-IOV VF gets created.</para></listitem>
         </varlistentry>
diff --git a/man/nm-cloud-setup.8 b/man/nm-cloud-setup.8
index decfcc4b..43a72c57 100644
--- a/man/nm-cloud-setup.8
+++ b/man/nm-cloud-setup.8
@@ -2,12 +2,12 @@
 .\"     Title: nm-cloud-setup
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Automatic Network Configuration in Cloud with NetworkManager
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-CLOUD\-SETUP" "8" "" "NetworkManager 1\&.45\&.91" "Automatic Network Configuratio"
+.TH "NM\-CLOUD\-SETUP" "8" "" "NetworkManager 1\&.46\&.0" "Automatic Network Configuratio"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-initrd-generator.8 b/man/nm-initrd-generator.8
index aafa7992..b3b6ca3f 100644
--- a/man/nm-initrd-generator.8
+++ b/man/nm-initrd-generator.8
@@ -2,12 +2,12 @@
 .\"     Title: nm-initrd-generator
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: System Administration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-INITRD\-GENERATOR" "8" "" "NetworkManager 1\&.45\&.91" "System Administration"
+.TH "NM\-INITRD\-GENERATOR" "8" "" "NetworkManager 1\&.46\&.0" "System Administration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-online.1 b/man/nm-online.1
index 54ec05b8..cd739472 100644
--- a/man/nm-online.1
+++ b/man/nm-online.1
@@ -2,12 +2,12 @@
 .\"     Title: nm-online
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: General Commands Manual
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-ONLINE" "1" "" "NetworkManager 1\&.45\&.91" "General Commands Manual"
+.TH "NM\-ONLINE" "1" "" "NetworkManager 1\&.46\&.0" "General Commands Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-openvswitch.7 b/man/nm-openvswitch.7
index fda3ef9d..35f5589b 100644
--- a/man/nm-openvswitch.7
+++ b/man/nm-openvswitch.7
@@ -2,12 +2,12 @@
 .\"     Title: nm-openvswitch
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Open vSwitch support overview
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-OPENVSWITCH" "7" "" "NetworkManager 1\&.45\&.91" "Open vSwitch support overview"
+.TH "NM\-OPENVSWITCH" "7" "" "NetworkManager 1\&.46\&.0" "Open vSwitch support overview"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-settings-dbus.5 b/man/nm-settings-dbus.5
index 480ccc0e..f586b00d 100644
--- a/man/nm-settings-dbus.5
+++ b/man/nm-settings-dbus.5
@@ -2,12 +2,12 @@
 .\"     Title: nm-settings-dbus
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Configuration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-SETTINGS\-DBUS" "5" "" "NetworkManager 1\&.45\&.91" "Configuration"
+.TH "NM\-SETTINGS\-DBUS" "5" "" "NetworkManager 1\&.46\&.0" "Configuration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -136,9 +136,9 @@ T}
 T{
 autoconnect\-ports
 T}:T{
-NMTernary (int32)
+int32
 T}:T{
-\ \&
+\-1
 T}:T{
 Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection\&. This only has a real effect for controller connections\&. The properties "autoconnect", "autoconnect\-priority" and "autoconnect\-retries" are unrelated to this setting\&. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, \-1: default\&. If \-1 (default) is set, global connection\&.autoconnect\-ports is read to determine the real value\&. If it is default as well, this fallbacks to 0\&.
 T}
@@ -1836,7 +1836,20 @@ T}:T{
 Value Description
 T}
 .T&
-.
+l l l l.
+T{
+device\-handler
+T}:T{
+string
+T}:T{
+\ \&
+T}:T{
+Name of the device handler that will be invoked to add and delete the device for this connection\&. The name can only contain ASCII alphanumeric characters and \*(Aq\-\*(Aq, \*(Aq_\*(Aq, \*(Aq\&.\*(Aq\&. It cannot start with \*(Aq\&.\*(Aq\&.
+
+See the NetworkManager\-dispatcher(8) man page for more details about how to write the device handler\&.
+
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device\-handler\&.
+T}
 .TE
 .sp 1
 .SS "gsm setting"
@@ -3197,6 +3210,7 @@ l l l l
 l l l l
 l l l l
 l l l l
+l l l l
 l l l l.
 T{
 encrypt
@@ -3244,6 +3258,21 @@ T}:T{
 Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained\&.
 T}
 T{
+offload
+T}:T{
+int32
+T}:T{
+\-1
+T}:T{
+Specifies the MACsec offload mode\&.
+
+0 (off) disables MACsec offload\&.
+
+1 (phy) and 2 (mac) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail\&.
+
+\-1 (default) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built\-in default is 0 (off)\&.
+T}
+T{
 parent
 T}:T{
 string
@@ -4153,6 +4182,9 @@ T}
 .T&
 l l l l
 l l l l
+l l l l
+l l l l
+l l l l
 l l l l.
 T{
 autoprobe\-drivers
@@ -4170,6 +4202,43 @@ If set to 0 (false), VFs will not be claimed and no network interfaces will be c
 When set to \-1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true)\&.
 T}
 T{
+eswitch\-encap\-mode
+T}:T{
+int32
+T}:T{
+\-1
+T}:T{
+Select the eswitch encapsulation support\&.
+
+Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+
+If set to \-1 (preserve) (default) the eswitch encap\-mode won\*(Aqt be modified by NetworkManager\&.
+T}
+T{
+eswitch\-inline\-mode
+T}:T{
+int32
+T}:T{
+\-1
+T}:T{
+Select the eswitch inline\-mode of the device\&. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e\-switch can do proper matching and steering\&.
+
+Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+
+If set to \-1 (preserve) (default) the eswitch inline\-mode won\*(Aqt be modified by NetworkManager\&.
+T}
+T{
+eswitch\-mode
+T}:T{
+int32
+T}:T{
+\-1
+T}:T{
+Select the eswitch mode of the device\&. Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+
+If set to \-1 (preserve) (default) the eswitch mode won\*(Aqt be modified by NetworkManager\&.
+T}
+T{
 total\-vfs
 T}:T{
 uint32
diff --git a/man/nm-settings-dbus.xml b/man/nm-settings-dbus.xml
index 11001e71..ec9bd0ec 100644
--- a/man/nm-settings-dbus.xml
+++ b/man/nm-settings-dbus.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-<refentry id="nm-settings-dbus"><refentryinfo><title>nm-settings-dbus</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-dbus</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.45.91</refmiscinfo></refmeta><refnamediv><refname>nm-settings-dbus</refname><refpurpose>Description of settings and properties of NetworkManager connection profiles on the D-Bus API</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
+<refentry id="nm-settings-dbus"><refentryinfo><title>nm-settings-dbus</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-dbus</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.46.0</refmiscinfo></refmeta><refnamediv><refname>nm-settings-dbus</refname><refpurpose>Description of settings and properties of NetworkManager connection profiles on the D-Bus API</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
           NetworkManager is based on a concept of connection profiles, sometimes referred to as
           connections only. These connection profiles contain a network configuration. When
           NetworkManager activates a connection profile on a network device the configuration will
@@ -42,7 +42,7 @@ Note that autoconnect is not implemented for VPN profiles. See "secondaries" as
 
 If multiple profiles are ready to autoconnect on the same device, the one with the better "connection.autoconnect-priority" is chosen. If the priorities are equal, then the most recently connected profile is activated. If the profiles were not connected earlier or their "connection.timestamp" is identical, the choice is undefined.
 
-Depending on "connection.multi-connect", a profile can (auto)connect only once at a time or multiple times.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-ports">autoconnect-ports</entry><entry align="left">NMTernary (int32)</entry><entry align="left"/><entry>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-priority">autoconnect-priority</entry><entry align="left">int32</entry><entry align="left">0</entry><entry>The autoconnect priority in range -999 to 999. If the connection is set to autoconnect, connections with higher priority will be preferred. The higher number means higher priority. Defaults to 0. Note that this property only matters if there are more than one candidate profile to select for autoconnect. In case of equal priority, the profile used most recently is chosen.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-retries">autoconnect-retries</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-slaves">autoconnect-slaves</entry><entry align="left">NMSettingConnectionAutoconnectSlaves (int32)</entry><entry align="left"/><entry>Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.controller">controller</entry><entry align="left">string</entry><entry align="left"/><entry>Interface name of the controller device or UUID of the controller connection.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.dns-over-tls">dns-over-tls</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls is a technology which uses TLS to encrypt dns traffic.
+Depending on "connection.multi-connect", a profile can (auto)connect only once at a time or multiple times.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-ports">autoconnect-ports</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Whether or not ports of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for controller connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave port connections untouched, 1: activate all the port connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-ports is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-priority">autoconnect-priority</entry><entry align="left">int32</entry><entry align="left">0</entry><entry>The autoconnect priority in range -999 to 999. If the connection is set to autoconnect, connections with higher priority will be preferred. The higher number means higher priority. Defaults to 0. Note that this property only matters if there are more than one candidate profile to select for autoconnect. In case of equal priority, the profile used most recently is chosen.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-retries">autoconnect-retries</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The number of times a connection should be tried when autoactivating before giving up. Zero means forever, -1 means the global default (4 times if not overridden). Setting this to 1 means to try activation only once before blocking autoconnect. Note that after a timeout, NetworkManager will try to autoconnect again.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.autoconnect-slaves">autoconnect-slaves</entry><entry align="left">NMSettingConnectionAutoconnectSlaves (int32)</entry><entry align="left"/><entry>Whether or not slaves of this connection should be automatically brought up when NetworkManager activates this connection. This only has a real effect for master connections. The properties "autoconnect", "autoconnect-priority" and "autoconnect-retries" are unrelated to this setting. The permitted values are: 0: leave slave connections untouched, 1: activate all the slave connections with this connection, -1: default. If -1 (default) is set, global connection.autoconnect-slaves is read to determine the real value. If it is default as well, this fallbacks to 0.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.controller">controller</entry><entry align="left">string</entry><entry align="left"/><entry>Interface name of the controller device or UUID of the controller connection.</entry></row><row><entry align="left" id="nm-settings-dbus.property.connection.dns-over-tls">dns-over-tls</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls is a technology which uses TLS to encrypt dns traffic.
 
 The permitted values are: "yes" (2) use DNSOverTls and disabled fallback, "opportunistic" (1) use DNSOverTls but allow fallback to unencrypted resolution, "no" (0) don't ever use DNSOverTls. If unspecified "default" depends on the plugin used. Systemd-resolved uses global setting.
 
@@ -156,7 +156,11 @@ $vid [pvid] [untagged] [, $vid [pvid] [untagged]]...
 
 where $vid is either a single id between 1 and 4094 or a range, represented as a couple of ids separated by a dash.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>cdma setting</title><para>CDMA-based Mobile Broadband Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.cdma.mtu">mtu</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.</entry></row><row><entry align="left" id="nm-settings-dbus.property.cdma.number">number</entry><entry align="left">string</entry><entry align="left"/><entry>The number to dial to establish the connection to the CDMA-based mobile broadband network, if any.  If not specified, the default number (#777) is used when required.</entry></row><row><entry align="left" id="nm-settings-dbus.property.cdma.password">password</entry><entry align="left">string</entry><entry align="left"/><entry>The password used to authenticate with the network, if required.  Many providers do not require a password, or accept any password.  But if a password is required, it is specified here.</entry></row><row><entry align="left" id="nm-settings-dbus.property.cdma.password-flags">password-flags</entry><entry align="left">NMSettingSecretFlags (uint32)</entry><entry align="left"/><entry>Flags indicating how to handle the "password" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.cdma.username">username</entry><entry align="left">string</entry><entry align="left"/><entry>The username used to authenticate with the network, if required.  Many providers do not require a username, or accept any username.  But if a username is required, it is specified here.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>dcb setting</title><para>Data Center Bridging Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fcoe-flags">app-fcoe-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for the DCB FCoE application.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fcoe-mode">app-fcoe-mode</entry><entry align="left">string</entry><entry align="left"/><entry>The FCoE controller mode; either "fabric" or "vn2vn".
 
-Since 1.34, NULL is the default and means "fabric". Before 1.34, NULL was rejected as invalid and the default was "fabric".</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fcoe-priority">app-fcoe-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority.  Only used when the "app-fcoe-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fip-flags">app-fip-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for the DCB FIP application.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fip-priority">app-fip-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority.  Only used when the "app-fip-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-iscsi-flags">app-iscsi-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for the DCB iSCSI application.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-iscsi-priority">app-iscsi-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the "app-iscsi-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-bandwidth">priority-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use.  The sum of all percentages for priorities which belong to the same group must total 100 percents.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-flow-control">priority-flow-control</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-flow-control-flags">priority-flow-control-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-bandwidth">priority-group-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group.  Allowed values are 0 - 100, and the sum of all values must total 100 percents.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-flags">priority-group-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for DCB Priority Groups.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-id">priority-group-id</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-strict-bandwidth">priority-strict-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-traffic-class">priority-traffic-class</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>dummy setting</title><para>Dummy Link Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></informaltable></refsect2><refsect2><title>ethtool setting</title><para>Ethtool Ethernet Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></informaltable></refsect2><refsect2><title>generic setting</title><para>Generic Link Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></informaltable></refsect2><refsect2><title>gsm setting</title><para>GSM-based Mobile Broadband Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.gsm.apn">apn</entry><entry align="left">string</entry><entry align="left"/><entry>The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.
+Since 1.34, NULL is the default and means "fabric". Before 1.34, NULL was rejected as invalid and the default was "fabric".</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fcoe-priority">app-fcoe-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority.  Only used when the "app-fcoe-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fip-flags">app-fip-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for the DCB FIP application.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-fip-priority">app-fip-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority.  Only used when the "app-fip-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-iscsi-flags">app-iscsi-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for the DCB iSCSI application.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.app-iscsi-priority">app-iscsi-priority</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the "app-iscsi-flags" property includes the 0x1 (enable) flag.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-bandwidth">priority-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use.  The sum of all percentages for priorities which belong to the same group must total 100 percents.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-flow-control">priority-flow-control</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-flow-control-flags">priority-flow-control-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-bandwidth">priority-group-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group.  Allowed values are 0 - 100, and the sum of all values must total 100 percents.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-flags">priority-group-flags</entry><entry align="left">NMSettingDcbFlags (uint32)</entry><entry align="left"/><entry>Specifies the NMSettingDcbFlags for DCB Priority Groups.  Flags may be any combination of 0x1 (enable), 0x2 (advertise), and 0x4 (willing).</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-group-id">priority-group-id</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-strict-bandwidth">priority-strict-bandwidth</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.</entry></row><row><entry align="left" id="nm-settings-dbus.property.dcb.priority-traffic-class">priority-traffic-class</entry><entry align="left">array of uint32</entry><entry align="left"/><entry>An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>dummy setting</title><para>Dummy Link Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></informaltable></refsect2><refsect2><title>ethtool setting</title><para>Ethtool Ethernet Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody/></tgroup></informaltable></refsect2><refsect2><title>generic setting</title><para>Generic Link Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.generic.device-handler">device-handler</entry><entry align="left">string</entry><entry align="left"/><entry>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.
+
+See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.
+
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>gsm setting</title><para>GSM-based Mobile Broadband Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.gsm.apn">apn</entry><entry align="left">string</entry><entry align="left"/><entry>The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.
 
 If the APN is unset (the default) then it may be detected based on "auto-config" setting. The property can be explicitly set to the empty string to prevent that and use no APN.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.auto-config">auto-config</entry><entry align="left">boolean</entry><entry align="left">FALSE</entry><entry>When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.device-id">device-id</entry><entry align="left">string</entry><entry align="left"/><entry>The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.home-only">home-only</entry><entry align="left">boolean</entry><entry align="left">FALSE</entry><entry>When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.initial-eps-bearer-apn">initial-eps-bearer-apn</entry><entry align="left">string</entry><entry align="left"/><entry>For LTE modems, this sets the APN for the initial EPS bearer that is set up when attaching to the network.  Setting this parameter implies initial-eps-bearer-configure to be TRUE.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.initial-eps-bearer-configure">initial-eps-bearer-configure</entry><entry align="left">boolean</entry><entry align="left">FALSE</entry><entry>For LTE modems, this setting determines whether the initial EPS bearer shall be configured when bringing up the connection.  It is inferred TRUE if initial-eps-bearer-apn is set.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.mtu">mtu</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.network-id">network-id</entry><entry align="left">string</entry><entry align="left"/><entry>The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration.  If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible.</entry></row><row><entry align="left" id="nm-settings-dbus.property.gsm.number">number</entry><entry align="left">string</entry><entry align="left"/><entry>Legacy setting that used to help establishing PPP data sessions for GSM-based modems.
 
@@ -360,7 +364,13 @@ If the table setting is left at zero, it is eligible to be overwritten via globa
 Policy routing disabled means that NetworkManager will add all routes to the main table (except static routes that explicitly configure a different table). Additionally, NetworkManager will not delete any extraneous routes from tables except the main table. This is to preserve backward compatibility for users who manage routing tables outside of NetworkManager.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ipv6.routes">routes</entry><entry align="left">array of legacy IPv6 route struct (a(ayuayu))</entry><entry align="left"/><entry>Deprecated in favor of the 'route-data' property, but this can be used for backward-compatibility with older daemons. Note that if you send this property the daemon will ignore 'route-data'.
 Array of IPv6 route structures.  Each IPv6 route structure is composed of an IPv6 address, a prefix length (0 - 128), an IPv6 next hop address (which may be zeroed out if there is no next hop), and a metric. If the metric is 0, NM will choose an appropriate default metric for the device.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ipv6.routing-rules">routing-rules</entry><entry align="left">array of 'a{sv}'</entry><entry align="left"/><entry>Array of dictionaries for routing rules. Each routing rule supports the following options: action (y), dport-end (q), dport-start (q), family (i), from (s), from-len (y), fwmark (u), fwmask (u), iifname (s), invert (b), ipproto (s), oifname (s), priority (u), sport-end (q), sport-start (q), supress-prefixlength (i), table (u), to (s), tos (y), to-len (y), range-end (u), range-start (u).</entry></row><row><entry align="left" id="nm-settings-dbus.property.ipv6.token">token</entry><entry align="left">string</entry><entry align="left"/><entry>Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode.
 
-When set, the token is used as IPv6 interface identifier instead of the hardware address. This only applies to addresses from stateless autoconfiguration, not to IPv6 link local addresses.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>ip-tunnel setting</title><para>IP Tunneling Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.encapsulation-limit">encapsulation-limit</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels. To disable this option, add 0x1 (ip6-ign-encap-limit) to ip-tunnel flags.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.flags">flags</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>Tunnel flags. Currently, the following values are supported: 0x1 (ip6-ign-encap-limit), 0x2 (ip6-use-orig-tclass), 0x4 (ip6-use-orig-flowlabel), 0x8 (ip6-mip6-dev), 0x10 (ip6-rcv-dscp-copy), 0x20 (ip6-use-orig-fwmark). They are valid only for IPv6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.flow-label">flow-label</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.fwmark">fwmark</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The fwmark value to assign to tunnel packets. This property can be set to a non zero value only on VTI and VTI6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.input-key">input-key</entry><entry align="left">string</entry><entry align="left"/><entry>The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.local">local</entry><entry align="left">string</entry><entry align="left"/><entry>The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.mode">mode</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The tunneling mode. Valid values: 1 (ipip), 2 (gre), 3 (sit), 4 (isatap), 5 (vti), 6 (ip6ip6), 7 (ipip6), 8 (ip6gre), 9 (vti6), 10 (gretap) and 11 (ip6gretap)</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.mtu">mtu</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.output-key">output-key</entry><entry align="left">string</entry><entry align="left"/><entry>The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.path-mtu-discovery">path-mtu-discovery</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether to enable Path MTU Discovery on this tunnel.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.remote">remote</entry><entry align="left">string</entry><entry align="left"/><entry>The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.tos">tos</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.ttl">ttl</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>macsec setting</title><para>MACSec Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.macsec.encrypt">encrypt</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether the transmitted traffic must be encrypted.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-cak">mka-cak</entry><entry align="left">string</entry><entry align="left"/><entry>The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. Must be a string of 32 hexadecimal characters.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-cak-flags">mka-cak-flags</entry><entry align="left">NMSettingSecretFlags (uint32)</entry><entry align="left"/><entry>Flags indicating how to handle the "mka-cak" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-ckn">mka-ckn</entry><entry align="left">string</entry><entry align="left"/><entry>The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mode">mode</entry><entry align="left">int32</entry><entry align="left">0</entry><entry>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.port">port</entry><entry align="left">int32</entry><entry align="left">1</entry><entry>The port component of the SCI (Secure Channel Identifier), between 1 and 65534.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.send-sci">send-sci</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Specifies whether the SCI (Secure Channel Identifier) is included in every packet.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.validation">validation</entry><entry align="left">int32</entry><entry align="left">2</entry><entry>Specifies the validation mode for incoming frames.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>macvlan setting</title><para>MAC VLAN Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.macvlan.mode">mode</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.promiscuous">promiscuous</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether the interface should be put in promiscuous mode.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.tap">tap</entry><entry align="left">boolean</entry><entry align="left">FALSE</entry><entry>Whether the interface should be a MACVTAP.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>match setting</title><para>Match settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.match.driver">driver</entry><entry align="left">array of string</entry><entry align="left"/><entry>A list of driver names to match. Each element is a shell wildcard pattern.
+When set, the token is used as IPv6 interface identifier instead of the hardware address. This only applies to addresses from stateless autoconfiguration, not to IPv6 link local addresses.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>ip-tunnel setting</title><para>IP Tunneling Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.encapsulation-limit">encapsulation-limit</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels. To disable this option, add 0x1 (ip6-ign-encap-limit) to ip-tunnel flags.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.flags">flags</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>Tunnel flags. Currently, the following values are supported: 0x1 (ip6-ign-encap-limit), 0x2 (ip6-use-orig-tclass), 0x4 (ip6-use-orig-flowlabel), 0x8 (ip6-mip6-dev), 0x10 (ip6-rcv-dscp-copy), 0x20 (ip6-use-orig-fwmark). They are valid only for IPv6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.flow-label">flow-label</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.fwmark">fwmark</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The fwmark value to assign to tunnel packets. This property can be set to a non zero value only on VTI and VTI6 tunnels.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.input-key">input-key</entry><entry align="left">string</entry><entry align="left"/><entry>The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.local">local</entry><entry align="left">string</entry><entry align="left"/><entry>The local endpoint of the tunnel; the value can be empty, otherwise it must contain an IPv4 or IPv6 address.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.mode">mode</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The tunneling mode. Valid values: 1 (ipip), 2 (gre), 3 (sit), 4 (isatap), 5 (vti), 6 (ip6ip6), 7 (ipip6), 8 (ip6gre), 9 (vti6), 10 (gretap) and 11 (ip6gretap)</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.mtu">mtu</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.output-key">output-key</entry><entry align="left">string</entry><entry align="left"/><entry>The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID the new device will be bound to so that tunneled packets will only be routed via that interface.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.path-mtu-discovery">path-mtu-discovery</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether to enable Path MTU Discovery on this tunnel.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.remote">remote</entry><entry align="left">string</entry><entry align="left"/><entry>The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 address.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.tos">tos</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.</entry></row><row><entry align="left" id="nm-settings-dbus.property.ip-tunnel.ttl">ttl</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The TTL to assign to tunneled packets. 0 is a special value meaning that packets inherit the TTL value.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>macsec setting</title><para>MACSec Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.macsec.encrypt">encrypt</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether the transmitted traffic must be encrypted.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-cak">mka-cak</entry><entry align="left">string</entry><entry align="left"/><entry>The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. Must be a string of 32 hexadecimal characters.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-cak-flags">mka-cak-flags</entry><entry align="left">NMSettingSecretFlags (uint32)</entry><entry align="left"/><entry>Flags indicating how to handle the "mka-cak" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mka-ckn">mka-ckn</entry><entry align="left">string</entry><entry align="left"/><entry>The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.mode">mode</entry><entry align="left">int32</entry><entry align="left">0</entry><entry>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.offload">offload</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Specifies the MACsec offload mode.
+
+0 (off) disables MACsec offload.
+
+1 (phy) and 2 (mac) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.
+
+-1 (default) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is 0 (off).</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.port">port</entry><entry align="left">int32</entry><entry align="left">1</entry><entry>The port component of the SCI (Secure Channel Identifier), between 1 and 65534.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.send-sci">send-sci</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Specifies whether the SCI (Secure Channel Identifier) is included in every packet.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macsec.validation">validation</entry><entry align="left">int32</entry><entry align="left">2</entry><entry>Specifies the validation mode for incoming frames.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>macvlan setting</title><para>MAC VLAN Settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.macvlan.mode">mode</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.parent">parent</entry><entry align="left">string</entry><entry align="left"/><entry>If given, specifies the parent interface name or parent connection UUID from which this MAC-VLAN interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.promiscuous">promiscuous</entry><entry align="left">boolean</entry><entry align="left">TRUE</entry><entry>Whether the interface should be put in promiscuous mode.</entry></row><row><entry align="left" id="nm-settings-dbus.property.macvlan.tap">tap</entry><entry align="left">boolean</entry><entry align="left">FALSE</entry><entry>Whether the interface should be a MACVTAP.</entry></row></tbody></tgroup></informaltable></refsect2><refsect2><title>match setting</title><para>Match settings.</para><informaltable><tgroup cols="4"><thead><row><entry>Key Name</entry><entry>Value Type</entry><entry>Default Value</entry><entry>Value Description</entry></row></thead><tbody><row><entry align="left" id="nm-settings-dbus.property.match.driver">driver</entry><entry align="left">array of string</entry><entry align="left"/><entry>A list of driver names to match. Each element is a shell wildcard pattern.
 
 See NMSettingMatch:interface-name for how special characters '|', '&amp;', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.</entry></row><row><entry align="left" id="nm-settings-dbus.property.match.interface-name">interface-name</entry><entry align="left">array of string</entry><entry align="left"/><entry>A list of interface names to match. Each element is a shell wildcard pattern.
 
@@ -384,7 +394,17 @@ If set to 1 (true), the kernel will try to bind VFs to a compatible driver and i
 
 If set to 0 (false), VFs will not be claimed and no network interfaces will be created for them.
 
-When set to -1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true).</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.total-vfs">total-vfs</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The total number of virtual functions to create.
+When set to -1 (default), the global default is used; in case the global default is unspecified it is assumed to be 1 (true).</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.eswitch-encap-mode">eswitch-encap-mode</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Select the eswitch encapsulation support.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch encap-mode won't be modified by NetworkManager.</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.eswitch-inline-mode">eswitch-inline-mode</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.
+
+Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch inline-mode won't be modified by NetworkManager.</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.eswitch-mode">eswitch-mode</entry><entry align="left">int32</entry><entry align="left">-1</entry><entry>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.
+
+If set to -1 (preserve) (default) the eswitch mode won't be modified by NetworkManager.</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.total-vfs">total-vfs</entry><entry align="left">uint32</entry><entry align="left">0</entry><entry>The total number of virtual functions to create.
 
 Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.</entry></row><row><entry align="left" id="nm-settings-dbus.property.sriov.vfs">vfs</entry><entry align="left">array of vardict</entry><entry align="left"/><entry>Array of virtual function descriptors.
 
diff --git a/man/nm-settings-ifcfg-rh.5 b/man/nm-settings-ifcfg-rh.5
index 40af6afb..9685f866 100644
--- a/man/nm-settings-ifcfg-rh.5
+++ b/man/nm-settings-ifcfg-rh.5
@@ -2,12 +2,12 @@
 .\"     Title: nm-settings-ifcfg-rh
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Configuration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-SETTINGS\-IFCFG\-RH" "5" "" "NetworkManager 1\&.45\&.91" "Configuration"
+.TH "NM\-SETTINGS\-IFCFG\-RH" "5" "" "NetworkManager 1\&.46\&.0" "Configuration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-settings-ifcfg-rh.xml b/man/nm-settings-ifcfg-rh.xml
index 2d583774..a7f99eb8 100644
--- a/man/nm-settings-ifcfg-rh.xml
+++ b/man/nm-settings-ifcfg-rh.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-<refentry id="nm-settings-ifcfg-rh"><refentryinfo><title>nm-settings-ifcfg-rh</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-ifcfg-rh</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.45.91</refmiscinfo></refmeta><refnamediv><refname>nm-settings-ifcfg-rh</refname><refpurpose>Description of <emphasis>ifcfg-rh</emphasis> settings plugin</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
+<refentry id="nm-settings-ifcfg-rh"><refentryinfo><title>nm-settings-ifcfg-rh</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-ifcfg-rh</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.46.0</refmiscinfo></refmeta><refnamediv><refname>nm-settings-ifcfg-rh</refname><refpurpose>Description of <emphasis>ifcfg-rh</emphasis> settings plugin</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
           NetworkManager is based on the concept of connection profiles that contain
           network configuration (see <citerefentry><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details). The profiles can be
           stored in various formats. NetworkManager uses plugins for reading and writing
diff --git a/man/nm-settings-keyfile.5 b/man/nm-settings-keyfile.5
index 40ec1a65..1b2bf22f 100644
--- a/man/nm-settings-keyfile.5
+++ b/man/nm-settings-keyfile.5
@@ -2,12 +2,12 @@
 .\"     Title: nm-settings-keyfile
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Configuration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-SETTINGS\-KEYFILE" "5" "" "NetworkManager 1\&.45\&.91" "Configuration"
+.TH "NM\-SETTINGS\-KEYFILE" "5" "" "NetworkManager 1\&.46\&.0" "Configuration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nm-settings-keyfile.xml b/man/nm-settings-keyfile.xml
index 2eb8d48c..ac4d9375 100644
--- a/man/nm-settings-keyfile.xml
+++ b/man/nm-settings-keyfile.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-<refentry id="nm-settings-keyfile"><refentryinfo><title>nm-settings-keyfile</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-keyfile</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.45.91</refmiscinfo></refmeta><refnamediv><refname>nm-settings-keyfile</refname><refpurpose>Description of <emphasis>keyfile</emphasis> settings plugin</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
+<refentry id="nm-settings-keyfile"><refentryinfo><title>nm-settings-keyfile</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-keyfile</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.46.0</refmiscinfo></refmeta><refnamediv><refname>nm-settings-keyfile</refname><refpurpose>Description of <emphasis>keyfile</emphasis> settings plugin</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
           NetworkManager is based on the concept of connection profiles that contain
           network configuration (see <citerefentry><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details). The profiles can be
           stored in various formats. NetworkManager uses plugins for reading and writing
diff --git a/man/nm-settings-nmcli.5 b/man/nm-settings-nmcli.5
index 8285c2df..d33da534 100644
--- a/man/nm-settings-nmcli.5
+++ b/man/nm-settings-nmcli.5
@@ -2,12 +2,12 @@
 .\"     Title: nm-settings-nmcli
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Configuration
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NM\-SETTINGS\-NMCLI" "5" "" "NetworkManager 1\&.45\&.91" "Configuration"
+.TH "NM\-SETTINGS\-NMCLI" "5" "" "NetworkManager 1\&.46\&.0" "Configuration"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -2098,6 +2098,22 @@ Format: integer
 .sp
 Valid values: 0 \- 4294967295
 .RE
+.SS "generic setting"
+.PP
+Generic Link Settings\&.
+.PP
+Properties:
+.PP
+\fBgeneric\&.device\-handler\fR
+.RS 4
+Name of the device handler that will be invoked to add and delete the device for this connection\&. The name can only contain ASCII alphanumeric characters and \*(Aq\-\*(Aq, \*(Aq_\*(Aq, \*(Aq\&.\*(Aq\&. It cannot start with \*(Aq\&.\*(Aq\&.
+.sp
+See the NetworkManager\-dispatcher(8) man page for more details about how to write the device handler\&.
+.sp
+By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device\-handler\&.
+.sp
+Format: string
+.RE
 .SS "gsm setting"
 .PP
 GSM\-based Mobile Broadband Settings\&.
@@ -3842,6 +3858,21 @@ Format: choice (NMSettingMacsecMode)
 Valid values: psk (0), eap (1)
 .RE
 .PP
+\fBmacsec\&.offload\fR
+.RS 4
+Specifies the MACsec offload mode\&.
+.sp
+"off" (0) disables MACsec offload\&.
+.sp
+"phy" (1) and "mac" (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail\&.
+.sp
+"default" (\-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built\-in default is "off" (0)\&.
+.sp
+Format: choice (NMSettingMacsecOffload)
+.sp
+Valid values: default (\-1), off (0), phy (1), mac (2)
+.RE
+.PP
 \fBmacsec\&.parent\fR
 .RS 4
 Alias: dev
@@ -4534,6 +4565,43 @@ Format: ternary
 Valid values: true/yes/on, false/no/off, default/unknown
 .RE
 .PP
+\fBsriov\&.eswitch\-encap\-mode\fR
+.RS 4
+Select the eswitch encapsulation support\&.
+.sp
+Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+.sp
+If set to "preserve" (\-1) (default) the eswitch encap\-mode won\*(Aqt be modified by NetworkManager\&.
+.sp
+Format: choice (NMSriovEswitchEncapMode)
+.sp
+Valid values: preserve (\-1), none (0), basic (1)
+.RE
+.PP
+\fBsriov\&.eswitch\-inline\-mode\fR
+.RS 4
+Select the eswitch inline\-mode of the device\&. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e\-switch can do proper matching and steering\&.
+.sp
+Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+.sp
+If set to "preserve" (\-1) (default) the eswitch inline\-mode won\*(Aqt be modified by NetworkManager\&.
+.sp
+Format: choice (NMSriovEswitchInlineMode)
+.sp
+Valid values: preserve (\-1), none (0), link (1), network (2), transport (3)
+.RE
+.PP
+\fBsriov\&.eswitch\-mode\fR
+.RS 4
+Select the eswitch mode of the device\&. Currently it\*(Aqs only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF\&.
+.sp
+If set to "preserve" (\-1) (default) the eswitch mode won\*(Aqt be modified by NetworkManager\&.
+.sp
+Format: choice (NMSriovEswitchMode)
+.sp
+Valid values: preserve (\-1), legacy (0), switchdev (1)
+.RE
+.PP
 \fBsriov\&.total\-vfs\fR
 .RS 4
 The total number of virtual functions to create\&.
diff --git a/man/nm-settings-nmcli.xml b/man/nm-settings-nmcli.xml
index 1a18a20c..89130b99 100644
--- a/man/nm-settings-nmcli.xml
+++ b/man/nm-settings-nmcli.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-<refentry id="nm-settings-nmcli"><refentryinfo><title>nm-settings-nmcli</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.45.91</refmiscinfo></refmeta><refnamediv><refname>nm-settings-nmcli</refname><refpurpose>Description of settings and properties of NetworkManager connection profiles for nmcli</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
+<refentry id="nm-settings-nmcli"><refentryinfo><title>nm-settings-nmcli</title><author>NetworkManager developers</author></refentryinfo><refmeta><refentrytitle>nm-settings-nmcli</refentrytitle><manvolnum>5</manvolnum><refmiscinfo class="source">NetworkManager</refmiscinfo><refmiscinfo class="manual">Configuration</refmiscinfo><refmiscinfo class="version">1.46.0</refmiscinfo></refmeta><refnamediv><refname>nm-settings-nmcli</refname><refpurpose>Description of settings and properties of NetworkManager connection profiles for nmcli</refpurpose></refnamediv><refsect1 id="description"><title>Description</title><para>
           NetworkManager is based on a concept of connection profiles, sometimes referred to as
           connections only. These connection profiles contain a network configuration. When
           NetworkManager activates a connection profile on a network device the configuration will
@@ -503,7 +503,10 @@
             Format: integer</para><para>
             Valid values: 0 - 4294967295</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.ethtool.ring-tx">ethtool.ring-tx</option></term><listitem><para>
             Format: integer</para><para>
-            Valid values: 0 - 4294967295</para></listitem></varlistentry></variablelist></para></refsect2><refsect2><title>gsm setting</title><para>GSM-based Mobile Broadband Settings.</para><para>
+            Valid values: 0 - 4294967295</para></listitem></varlistentry></variablelist></para></refsect2><refsect2><title>generic setting</title><para>Generic Link Settings.</para><para>
+        Properties:
+        <variablelist><varlistentry><term><option id="nm-settings-nmcli.property.generic.device-handler">generic.device-handler</option></term><listitem><para>Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'.</para><para>See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler.</para><para>By setting this property the generic connection becomes "virtual", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.</para><para>
+            Format: string</para></listitem></varlistentry></variablelist></para></refsect2><refsect2><title>gsm setting</title><para>GSM-based Mobile Broadband Settings.</para><para>
         Properties:
         <variablelist><varlistentry><term><option id="nm-settings-nmcli.property.gsm.apn">gsm.apn</option></term><listitem><para>
             Alias: apn</para><para>The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.</para><para>If the APN is unset (the default) then it may be detected based on "auto-config" setting. The property can be explicitly set to the empty string to prevent that and use no APN.</para><para>
@@ -925,7 +928,9 @@ Example: <literal>priority 5 from 1:2:3::5/128 table 45</literal>
             Format: string</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.macsec.mode">macsec.mode</option></term><listitem><para>
             Alias: mode</para><para>Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.</para><para>
             Format: choice (NMSettingMacsecMode)</para><para>
-            Valid values: psk (0), eap (1)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.macsec.parent">macsec.parent</option></term><listitem><para>
+            Valid values: psk (0), eap (1)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.macsec.offload">macsec.offload</option></term><listitem><para>Specifies the MACsec offload mode.</para><para>"off" (0) disables MACsec offload.</para><para>"phy" (1) and "mac" (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail.</para><para>"default" (-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is "off" (0).</para><para>
+            Format: choice (NMSettingMacsecOffload)</para><para>
+            Valid values: default (-1), off (0), phy (1), mac (2)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.macsec.parent">macsec.parent</option></term><listitem><para>
             Alias: dev</para><para>If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property.</para><para>
             Format: string</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.macsec.port">macsec.port</option></term><listitem><para>
             Alias: port</para><para>The port component of the SCI (Secure Channel Identifier), between 1 and 65534.</para><para>
@@ -1085,7 +1090,13 @@ Example: <literal>priority 5 from 1:2:3::5/128 table 45</literal>
         Properties:
         <variablelist><varlistentry><term><option id="nm-settings-nmcli.property.sriov.autoprobe-drivers">sriov.autoprobe-drivers</option></term><listitem><para>Whether to autoprobe virtual functions by a compatible driver.</para><para>If set to "true" (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF.</para><para>If set to "false" (0), VFs will not be claimed and no network interfaces will be created for them.</para><para>When set to "default" (-1), the global default is used; in case the global default is unspecified it is assumed to be "true" (1).</para><para>
             Format: ternary</para><para>
-            Valid values: true/yes/on, false/no/off, default/unknown</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.total-vfs">sriov.total-vfs</option></term><listitem><para>The total number of virtual functions to create.</para><para>Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.</para><para>
+            Valid values: true/yes/on, false/no/off, default/unknown</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.eswitch-encap-mode">sriov.eswitch-encap-mode</option></term><listitem><para>Select the eswitch encapsulation support.</para><para>Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</para><para>If set to "preserve" (-1) (default) the eswitch encap-mode won't be modified by NetworkManager.</para><para>
+            Format: choice (NMSriovEswitchEncapMode)</para><para>
+            Valid values: preserve (-1), none (0), basic (1)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.eswitch-inline-mode">sriov.eswitch-inline-mode</option></term><listitem><para>Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering.</para><para>Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</para><para>If set to "preserve" (-1) (default) the eswitch inline-mode won't be modified by NetworkManager.</para><para>
+            Format: choice (NMSriovEswitchInlineMode)</para><para>
+            Valid values: preserve (-1), none (0), link (1), network (2), transport (3)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.eswitch-mode">sriov.eswitch-mode</option></term><listitem><para>Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF.</para><para>If set to "preserve" (-1) (default) the eswitch mode won't be modified by NetworkManager.</para><para>
+            Format: choice (NMSriovEswitchMode)</para><para>
+            Valid values: preserve (-1), legacy (0), switchdev (1)</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.total-vfs">sriov.total-vfs</option></term><listitem><para>The total number of virtual functions to create.</para><para>Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.</para><para>
             Format: integer</para><para>
             Valid values: 0 - 4294967295</para></listitem></varlistentry><varlistentry><term><option id="nm-settings-nmcli.property.sriov.vfs">sriov.vfs</option></term><listitem><para>Array of virtual function descriptors.</para><para>Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF.</para><para>When represented as string a VF is in the form:</para><para>"INDEX [ATTR=VALUE[ ATTR=VALUE]...]".</para><para>for example:</para><para>"2 mac=00:11:22:33:44:55 spoof-check=true".</para><para>Multiple VFs can be specified using a comma as separator. Currently, the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans.</para><para>The "vlans" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form</para><para>"ID[.PRIORITY[.PROTO]]".</para><para>PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.</para><para>
             Format: list of sriov.vfs objects</para></listitem></varlistentry></variablelist></para></refsect2><refsect2><title>tc setting</title><para>Linux Traffic Control Settings.</para><para>
diff --git a/man/nmcli-examples.7 b/man/nmcli-examples.7
index 783c0166..68b24fa3 100644
--- a/man/nmcli-examples.7
+++ b/man/nmcli-examples.7
@@ -2,12 +2,12 @@
 .\"     Title: nmcli-examples
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: Examples
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NMCLI\-EXAMPLES" "7" "" "NetworkManager 1\&.45\&.91" "Examples"
+.TH "NMCLI\-EXAMPLES" "7" "" "NetworkManager 1\&.46\&.0" "Examples"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nmcli.1 b/man/nmcli.1
index 12793187..5bd86fb3 100644
--- a/man/nmcli.1
+++ b/man/nmcli.1
@@ -2,12 +2,12 @@
 .\"     Title: nmcli
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: General Commands Manual
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NMCLI" "1" "" "NetworkManager 1\&.45\&.91" "General Commands Manual"
+.TH "NMCLI" "1" "" "NetworkManager 1\&.46\&.0" "General Commands Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/man/nmtui.1 b/man/nmtui.1
index f7c479dc..4d58cadc 100644
--- a/man/nmtui.1
+++ b/man/nmtui.1
@@ -2,12 +2,12 @@
 .\"     Title: nmtui
 .\"    Author: 
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 02/09/2024
+.\"      Date: 02/22/2024
 .\"    Manual: General Commands Manual
-.\"    Source: NetworkManager 1.45.91
+.\"    Source: NetworkManager 1.46.0
 .\"  Language: English
 .\"
-.TH "NMTUI" "1" "" "NetworkManager 1\&.45\&.91" "General Commands Manual"
+.TH "NMTUI" "1" "" "NetworkManager 1\&.46\&.0" "General Commands Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
diff --git a/meson.build b/meson.build
index 61c025b9..1cc11d0d 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.45.91',
+  version: '1.46.0',
   license: 'GPL2+',
   default_options: [
     'buildtype=debugoptimized',
diff --git a/po/NetworkManager.pot b/po/NetworkManager.pot
index 150fdb74..47cf54d3 100644
--- a/po/NetworkManager.pot
+++ b/po/NetworkManager.pot
@@ -6,10 +6,10 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: NetworkManager 1.45.91\n"
+"Project-Id-Version: NetworkManager 1.46.0\n"
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/NetworkManager/"
 "NetworkManager/issues\n"
-"POT-Creation-Date: 2024-02-09 15:43+0100\n"
+"POT-Creation-Date: 2024-02-22 16:09+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -172,7 +172,7 @@ msgid "%s %u"
 msgstr ""
 
 #: src/core/devices/adsl/nm-device-adsl.c:118
-#: src/libnmc-setting/nm-meta-setting-desc.c:8656
+#: src/libnmc-setting/nm-meta-setting-desc.c:8652
 msgid "ADSL connection"
 msgstr ""
 
@@ -249,7 +249,7 @@ msgid "Wired connection %d"
 msgstr ""
 
 #: src/core/devices/nm-device-ethernet.c:1641
-#: src/libnmc-setting/nm-meta-setting-desc.c:8698
+#: src/libnmc-setting/nm-meta-setting-desc.c:8694
 msgid "Veth connection"
 msgstr ""
 
@@ -262,7 +262,7 @@ msgid "Wired connection"
 msgstr ""
 
 #: src/core/devices/nm-device-infiniband.c:160
-#: src/libnmc-setting/nm-meta-setting-desc.c:8671
+#: src/libnmc-setting/nm-meta-setting-desc.c:8667
 msgid "InfiniBand connection"
 msgstr ""
 
@@ -283,17 +283,17 @@ msgid "TUN connection"
 msgstr ""
 
 #: src/core/devices/nm-device-vlan.c:380
-#: src/libnmc-setting/nm-meta-setting-desc.c:8699
+#: src/libnmc-setting/nm-meta-setting-desc.c:8695
 msgid "VLAN connection"
 msgstr ""
 
 #: src/core/devices/nm-device-vrf.c:185
-#: src/libnmc-setting/nm-meta-setting-desc.c:8701
+#: src/libnmc-setting/nm-meta-setting-desc.c:8697
 msgid "VRF connection"
 msgstr ""
 
 #: src/core/devices/nm-device-vxlan.c:385
-#: src/libnmc-setting/nm-meta-setting-desc.c:8702
+#: src/libnmc-setting/nm-meta-setting-desc.c:8698
 msgid "VXLAN connection"
 msgstr ""
 
@@ -531,8 +531,8 @@ msgid "Could not daemonize: %s [error %u]\n"
 msgstr ""
 
 #: src/core/nm-config.c:544 src/libnm-core-impl/nm-setting-ovs-bridge.c:187
-#: src/libnmc-setting/nm-meta-setting-desc.c:2188
-#: src/libnmc-setting/nm-meta-setting-desc.c:4334
+#: src/libnmc-setting/nm-meta-setting-desc.c:2163
+#: src/libnmc-setting/nm-meta-setting-desc.c:4309
 #, c-format
 msgid "'%s' is not valid"
 msgstr ""
@@ -598,25 +598,25 @@ msgstr ""
 msgid "Show NetworkManager options"
 msgstr ""
 
-#: src/core/nm-manager.c:6886 src/libnmc-setting/nm-meta-setting-desc.c:8700
+#: src/core/nm-manager.c:6893 src/libnmc-setting/nm-meta-setting-desc.c:8696
 msgid "VPN connection"
 msgstr ""
 
 #: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5650
 #: src/libnm-client-impl/nm-device.c:1781
-#: src/libnm-core-impl/nm-connection.c:3237 src/nmtui/nm-editor-utils.c:196
+#: src/libnm-core-impl/nm-connection.c:3244 src/nmtui/nm-editor-utils.c:196
 msgid "Bond"
 msgstr ""
 
 #: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:5721
 #: src/libnm-client-impl/nm-device.c:1783
-#: src/libnm-core-impl/nm-connection.c:3239 src/nmtui/nm-editor-utils.c:214
+#: src/libnm-core-impl/nm-connection.c:3246 src/nmtui/nm-editor-utils.c:214
 msgid "Team"
 msgstr ""
 
 #: src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c:6058
 #: src/libnm-client-impl/nm-device.c:1785
-#: src/libnm-core-impl/nm-connection.c:3241 src/nmtui/nm-editor-utils.c:205
+#: src/libnm-core-impl/nm-connection.c:3248 src/nmtui/nm-editor-utils.c:205
 msgid "Bridge"
 msgstr ""
 
@@ -895,12 +895,12 @@ msgid "Mobile Broadband"
 msgstr ""
 
 #: src/libnm-client-impl/nm-device.c:1779
-#: src/libnm-core-impl/nm-connection.c:3245 src/nmtui/nm-editor-utils.c:169
+#: src/libnm-core-impl/nm-connection.c:3252 src/nmtui/nm-editor-utils.c:169
 msgid "InfiniBand"
 msgstr ""
 
 #: src/libnm-client-impl/nm-device.c:1787
-#: src/libnm-core-impl/nm-connection.c:3243 src/nmtui/nm-editor-utils.c:223
+#: src/libnm-core-impl/nm-connection.c:3250 src/nmtui/nm-editor-utils.c:223
 #: src/nmtui/nmt-page-vlan.c:57
 msgid "VLAN"
 msgstr ""
@@ -951,7 +951,7 @@ msgid "6LoWPAN"
 msgstr ""
 
 #: src/libnm-client-impl/nm-device.c:1811
-#: src/libnm-core-impl/nm-connection.c:3251 src/nmtui/nm-editor-utils.c:271
+#: src/libnm-core-impl/nm-connection.c:3258 src/nmtui/nm-editor-utils.c:271
 #: src/nmtui/nmt-page-wireguard.c:57
 msgid "WireGuard"
 msgstr ""
@@ -975,7 +975,7 @@ msgstr ""
 #. TRANSLATORS: Unknown reason for a device state change (NMDeviceStateReason)
 #. TRANSLATORS: Unknown reason for a connection state change (NMActiveConnectionStateReason)
 #: src/libnm-client-impl/nm-device.c:1826 src/libnmc-base/nm-client-utils.c:352
-#: src/libnmc-base/nm-client-utils.c:473 src/nmcli/utils.c:1841
+#: src/libnmc-base/nm-client-utils.c:475 src/nmcli/utils.c:1841
 msgid "Unknown"
 msgstr ""
 
@@ -1203,11 +1203,11 @@ msgstr ""
 msgid "property is missing"
 msgstr ""
 
-#: src/libnm-core-impl/nm-connection.c:3249
+#: src/libnm-core-impl/nm-connection.c:3256
 msgid "IP Tunnel"
 msgstr ""
 
-#: src/libnm-core-impl/nm-connection.c:3253
+#: src/libnm-core-impl/nm-connection.c:3260
 msgid "TUN/TAP"
 msgstr ""
 
@@ -1293,7 +1293,7 @@ msgid "ignoring invalid DNS server IPv%c address '%s'"
 msgstr ""
 
 #: src/libnm-core-impl/nm-keyfile.c:1177
-#: src/libnmc-setting/nm-meta-setting-desc.c:1678
+#: src/libnmc-setting/nm-meta-setting-desc.c:1653
 #, c-format
 msgid "invalid option '%s', use one of [%s]"
 msgstr ""
@@ -1456,7 +1456,7 @@ msgid "property is not specified"
 msgstr ""
 
 #: src/libnm-core-impl/nm-setting-6lowpan.c:104
-#: src/libnm-core-impl/nm-setting-macsec.c:315
+#: src/libnm-core-impl/nm-setting-macsec.c:333
 #: src/libnm-core-impl/nm-setting-vlan.c:625
 #, c-format
 msgid "'%s' value doesn't match '%s=%s'"
@@ -1464,7 +1464,7 @@ msgstr ""
 
 #: src/libnm-core-impl/nm-setting-6lowpan.c:120
 #: src/libnm-core-impl/nm-setting-ip-tunnel.c:378
-#: src/libnm-core-impl/nm-setting-macsec.c:331
+#: src/libnm-core-impl/nm-setting-macsec.c:349
 #: src/libnm-core-impl/nm-setting-macvlan.c:138
 #: src/libnm-core-impl/nm-setting-vlan.c:641
 #: src/libnm-core-impl/nm-setting-vxlan.c:377
@@ -1543,7 +1543,7 @@ msgstr ""
 #: src/libnm-core-impl/nm-setting-wimax.c:107
 #: src/libnm-core-impl/nm-setting-wireless-security.c:968
 #: src/libnm-core-impl/nm-setting-wireless-security.c:996
-#: src/libnm-core-impl/nm-setting.c:2531
+#: src/libnm-core-impl/nm-setting.c:2603
 msgid "property is empty"
 msgstr ""
 
@@ -2041,12 +2041,12 @@ msgid "Invalid routing metric '%s'"
 msgstr ""
 
 #: src/libnm-core-impl/nm-setting-ip-config.c:1339
-#: src/libnm-core-impl/nm-setting-sriov.c:400
+#: src/libnm-core-impl/nm-setting-sriov.c:410
 msgid "unknown attribute"
 msgstr ""
 
 #: src/libnm-core-impl/nm-setting-ip-config.c:1349
-#: src/libnm-core-impl/nm-setting-sriov.c:410
+#: src/libnm-core-impl/nm-setting-sriov.c:420
 #, c-format
 msgid "invalid attribute type '%s'"
 msgstr ""
@@ -2456,40 +2456,40 @@ msgstr ""
 msgid "a loopback profile cannot be a port"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:249
+#: src/libnm-core-impl/nm-setting-macsec.c:267
 msgid "the key is empty"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:259
+#: src/libnm-core-impl/nm-setting-macsec.c:277
 #, c-format
 msgid "the key must be %d characters"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:269
+#: src/libnm-core-impl/nm-setting-macsec.c:287
 msgid "the key must have an even number of characters between 2 and 64"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:278
+#: src/libnm-core-impl/nm-setting-macsec.c:296
 msgid "the key contains non-hexadecimal characters"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:347
+#: src/libnm-core-impl/nm-setting-macsec.c:365
 #: src/libnm-core-impl/nm-setting-macvlan.c:154
 #: src/libnm-core-impl/nm-setting-vlan.c:654
 #, c-format
 msgid "property is not specified and neither is '%s:%s'"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:378
+#: src/libnm-core-impl/nm-setting-macsec.c:396
 #, c-format
 msgid "EAP key management requires '%s' setting presence"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:387
+#: src/libnm-core-impl/nm-setting-macsec.c:405
 msgid "must be either psk (0) or eap (1)"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-macsec.c:398
+#: src/libnm-core-impl/nm-setting-macsec.c:416
 msgid "only valid for psk mode"
 msgstr ""
 
@@ -2687,34 +2687,34 @@ msgstr ""
 msgid "the script lacks FindProxyForURL function"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-sriov.c:422
+#: src/libnm-core-impl/nm-setting-sriov.c:432
 #: src/libnm-core-impl/nm-setting-wired.c:809
 #: src/libnm-core-impl/nm-setting-wired.c:825
 #: src/libnm-core-impl/nm-setting-wired.c:899
 #: src/libnm-core-impl/nm-setting-wired.c:958
 #: src/libnm-core-impl/nm-setting-wireless.c:1051
 #: src/libnm-core-impl/nm-setting-wireless.c:1070
-#: src/libnmc-setting/nm-meta-setting-desc.c:4283
+#: src/libnmc-setting/nm-meta-setting-desc.c:4258
 #, c-format
 msgid "'%s' is not a valid MAC address"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-sriov.c:1045
+#: src/libnm-core-impl/nm-setting-sriov.c:1103
 #, c-format
 msgid "VF with index %u, but the total number of VFs is %u"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-sriov.c:1059
+#: src/libnm-core-impl/nm-setting-sriov.c:1117
 #, c-format
 msgid "invalid VF %u: %s"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-sriov.c:1073
+#: src/libnm-core-impl/nm-setting-sriov.c:1131
 #, c-format
 msgid "duplicate VF index %u"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting-sriov.c:1097
+#: src/libnm-core-impl/nm-setting-sriov.c:1155
 #, c-format
 msgid "VFs %d and %d are not sorted by ascending index"
 msgstr ""
@@ -2835,7 +2835,7 @@ msgid "setting contained a secret with an empty name"
 msgstr ""
 
 #: src/libnm-core-impl/nm-setting-vpn.c:651
-#: src/libnm-core-impl/nm-setting.c:3482
+#: src/libnm-core-impl/nm-setting.c:3554
 msgid "not a secret property"
 msgstr ""
 
@@ -3069,40 +3069,45 @@ msgstr ""
 msgid "channel must not be between %d and %d"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:1709 src/libnm-core-impl/nm-setting.c:1749
-#: src/libnm-core-impl/nm-setting.c:2060
+#: src/libnm-core-impl/nm-setting.c:1751 src/libnm-core-impl/nm-setting.c:1791
+#: src/libnm-core-impl/nm-setting.c:2102
 #, c-format
 msgid "can't set property of type '%s' from value of type '%s'"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:1725
+#: src/libnm-core-impl/nm-setting.c:1767
 #, c-format
 msgid "value of type '%s' is invalid or out of range for property '%s'"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:1770
+#: src/libnm-core-impl/nm-setting.c:1812
 #, c-format
 msgid "can not set property: %s"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:1999
+#: src/libnm-core-impl/nm-setting.c:2041
 msgid "duplicate property"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:2019
+#: src/libnm-core-impl/nm-setting.c:2061
 msgid "unknown property"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:2093 src/libnm-core-impl/nm-setting.c:2175
+#: src/libnm-core-impl/nm-setting.c:2135 src/libnm-core-impl/nm-setting.c:2217
 #, c-format
 msgid "failed to set property: %s"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:2444
+#: src/libnm-core-impl/nm-setting.c:2492
+#, c-format
+msgid "invalid value %d, expected %d-%d"
+msgstr ""
+
+#: src/libnm-core-impl/nm-setting.c:2516
 msgid "cannot be empty"
 msgstr ""
 
-#: src/libnm-core-impl/nm-setting.c:3379
+#: src/libnm-core-impl/nm-setting.c:3451
 msgid "secret not found"
 msgstr ""
 
@@ -3975,10 +3980,10 @@ msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:291 src/libnmc-base/nm-client-utils.c:305
 #: src/libnmc-base/nm-client-utils.c:341 src/libnmc-base/nm-client-utils.c:346
-#: src/libnmc-setting/nm-meta-setting-desc.c:1842
-#: src/libnmc-setting/nm-meta-setting-desc.c:1873
-#: src/libnmc-setting/nm-meta-setting-desc.c:2882
-#: src/libnmc-setting/nm-meta-setting-desc.c:2940 src/nmcli/common.c:1611
+#: src/libnmc-setting/nm-meta-setting-desc.c:1817
+#: src/libnmc-setting/nm-meta-setting-desc.c:1848
+#: src/libnmc-setting/nm-meta-setting-desc.c:2857
+#: src/libnmc-setting/nm-meta-setting-desc.c:2915 src/nmcli/common.c:1611
 #: src/nmcli/connections.c:79 src/nmcli/connections.c:89
 #: src/nmcli/devices.c:485 src/nmcli/devices.c:592 src/nmcli/devices.c:598
 #: src/nmcli/devices.c:604 src/nmcli/general.c:30 src/nmcli/general.c:85
@@ -4050,7 +4055,7 @@ msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:342
 #: src/libnmc-setting/nm-meta-setting-desc.c:875
-#: src/libnmc-setting/nm-meta-setting-desc.c:2874 src/nmcli/connections.c:5576
+#: src/libnmc-setting/nm-meta-setting-desc.c:2849 src/nmcli/connections.c:5576
 #: src/nmcli/connections.c:7554 src/nmcli/connections.c:7555
 #: src/nmcli/devices.c:591 src/nmcli/devices.c:597 src/nmcli/devices.c:603
 #: src/nmcli/devices.c:1427 src/nmcli/general.c:92 src/nmcli/utils.h:316
@@ -4059,7 +4064,7 @@ msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:343
 #: src/libnmc-setting/nm-meta-setting-desc.c:875
-#: src/libnmc-setting/nm-meta-setting-desc.c:2877 src/nmcli/connections.c:5575
+#: src/libnmc-setting/nm-meta-setting-desc.c:2852 src/nmcli/connections.c:5575
 #: src/nmcli/connections.c:7554 src/nmcli/connections.c:7555
 #: src/nmcli/devices.c:591 src/nmcli/devices.c:597 src/nmcli/devices.c:603
 #: src/nmcli/devices.c:1427 src/nmcli/general.c:93 src/nmcli/utils.h:316
@@ -4349,91 +4354,95 @@ msgstr ""
 msgid "The Wi-Fi P2P peer could not be found"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:474
-msgid "Unknown reason"
+#: src/libnmc-base/nm-client-utils.c:469
+msgid "The device handler dispatcher returned an error"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:476
-msgid "The connection was disconnected"
+msgid "Unknown reason"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:478
-msgid "Disconnected by user"
+msgid "The connection was disconnected"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:480
-msgid "The base network connection was interrupted"
+msgid "Disconnected by user"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:482
-msgid "The VPN service stopped unexpectedly"
+msgid "The base network connection was interrupted"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:484
-msgid "The VPN service returned invalid configuration"
+msgid "The VPN service stopped unexpectedly"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:486
-msgid "The connection attempt timed out"
+msgid "The VPN service returned invalid configuration"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:488
-msgid "The VPN service did not start in time"
+msgid "The connection attempt timed out"
 msgstr ""
 
 #: src/libnmc-base/nm-client-utils.c:490
+msgid "The VPN service did not start in time"
+msgstr ""
+
+#: src/libnmc-base/nm-client-utils.c:492
 msgid "The VPN service failed to start"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:491
+#: src/libnmc-base/nm-client-utils.c:493
 msgid "No valid secrets"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:492
+#: src/libnmc-base/nm-client-utils.c:494
 msgid "Invalid secrets"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:494
+#: src/libnmc-base/nm-client-utils.c:496
 msgid "The connection was removed"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:496
+#: src/libnmc-base/nm-client-utils.c:498
 msgid "Master connection failed"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:498
+#: src/libnmc-base/nm-client-utils.c:500
 msgid "Could not create a software link"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:500
+#: src/libnmc-base/nm-client-utils.c:502
 msgid "The device disappeared"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:826
+#: src/libnmc-base/nm-client-utils.c:828
 msgid "missing colon for \"<setting>.<property>:<secret>\" format"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:843
+#: src/libnmc-base/nm-client-utils.c:845
 msgid "missing dot for \"<setting>.<property>:<secret>\" format"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:849
+#: src/libnmc-base/nm-client-utils.c:851
 msgid "missing setting for \"<setting>.<property>:<secret>\" format"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:860
+#: src/libnmc-base/nm-client-utils.c:862
 msgid "missing property for \"<setting>.<property>:<secret>\" format"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:870
+#: src/libnmc-base/nm-client-utils.c:872
 msgid "invalid setting name"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:884
+#: src/libnmc-base/nm-client-utils.c:886
 msgid "property name is not UTF-8"
 msgstr ""
 
-#: src/libnmc-base/nm-client-utils.c:901 src/libnmc-base/nm-client-utils.c:907
+#: src/libnmc-base/nm-client-utils.c:903 src/libnmc-base/nm-client-utils.c:909
 msgid "secret is not UTF-8"
 msgstr ""
 
@@ -4447,27 +4456,27 @@ msgstr ""
 msgid "Could not retrieve session id: %s"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:222
+#: src/libnmc-base/nm-secret-agent-simple.c:225
 #, c-format
 msgid "Preshared-key for %s"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:270
-#: src/libnmc-base/nm-secret-agent-simple.c:357
-#: src/libnmc-setting/nm-meta-setting-desc.c:5200
+#: src/libnmc-base/nm-secret-agent-simple.c:274
+#: src/libnmc-base/nm-secret-agent-simple.c:361
+#: src/libnmc-setting/nm-meta-setting-desc.c:5175
 #: src/nmtui/nmt-8021x-fields.c:182 src/nmtui/nmt-8021x-fields.c:353
 #: src/nmtui/nmt-8021x-fields.c:457 src/nmtui/nmt-page-dsl.c:51
 #: src/nmtui/nmt-page-wifi.c:345
 msgid "Username"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:275
-#: src/libnmc-base/nm-secret-agent-simple.c:312
-#: src/libnmc-base/nm-secret-agent-simple.c:335
-#: src/libnmc-base/nm-secret-agent-simple.c:367
-#: src/libnmc-base/nm-secret-agent-simple.c:917
-#: src/libnmc-base/nm-secret-agent-simple.c:952
-#: src/libnmc-base/nm-secret-agent-simple.c:979
+#: src/libnmc-base/nm-secret-agent-simple.c:279
+#: src/libnmc-base/nm-secret-agent-simple.c:316
+#: src/libnmc-base/nm-secret-agent-simple.c:339
+#: src/libnmc-base/nm-secret-agent-simple.c:371
+#: src/libnmc-base/nm-secret-agent-simple.c:948
+#: src/libnmc-base/nm-secret-agent-simple.c:983
+#: src/libnmc-base/nm-secret-agent-simple.c:1010
 #: src/libnmc-base/nm-vpn-helpers.c:144 src/libnmc-base/nm-vpn-helpers.c:148
 #: src/libnmc-base/nm-vpn-helpers.c:154 src/libnmc-base/nm-vpn-helpers.c:159
 #: src/nmcli/devices.c:4736 src/nmtui/nmt-8021x-fields.c:195
@@ -4477,111 +4486,111 @@ msgstr ""
 msgid "Password"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:284
+#: src/libnmc-base/nm-secret-agent-simple.c:288
 #: src/nmtui/nmt-8021x-fields.c:204
 msgid "Identity"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:289
+#: src/libnmc-base/nm-secret-agent-simple.c:293
 msgid "Private key password"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:325 src/nmtui/nmt-page-wifi.c:298
+#: src/libnmc-base/nm-secret-agent-simple.c:329 src/nmtui/nmt-page-wifi.c:298
 msgid "Key"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:362 src/nmtui/nmt-page-dsl.c:67
+#: src/libnmc-base/nm-secret-agent-simple.c:366 src/nmtui/nmt-page-dsl.c:67
 msgid "Service"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:473
+#: src/libnmc-base/nm-secret-agent-simple.c:500
 msgid "WireGuard private-key"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:512
+#: src/libnmc-base/nm-secret-agent-simple.c:539
 #, c-format
 msgid "Secrets are required to connect WireGuard VPN '%s'"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:620
-#: src/libnmc-base/nm-secret-agent-simple.c:913
-#: src/libnmc-base/nm-secret-agent-simple.c:948
-#: src/libnmc-base/nm-secret-agent-simple.c:975
-#: src/libnmc-base/nm-secret-agent-simple.c:994
+#: src/libnmc-base/nm-secret-agent-simple.c:651
+#: src/libnmc-base/nm-secret-agent-simple.c:944
+#: src/libnmc-base/nm-secret-agent-simple.c:979
+#: src/libnmc-base/nm-secret-agent-simple.c:1006
+#: src/libnmc-base/nm-secret-agent-simple.c:1025
 #, c-format
 msgid "A password is required to connect to '%s'."
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:878
+#: src/libnmc-base/nm-secret-agent-simple.c:909
 msgid "Authentication required by wireless network"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:880
+#: src/libnmc-base/nm-secret-agent-simple.c:911
 #, c-format
 msgid ""
 "Passwords or encryption keys are required to access the wireless network "
 "'%s'."
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:886
+#: src/libnmc-base/nm-secret-agent-simple.c:917
 msgid "Wired 802.1X authentication"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:887
+#: src/libnmc-base/nm-secret-agent-simple.c:918
 #, c-format
 msgid "Secrets are required to access the wired network '%s'"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:893
+#: src/libnmc-base/nm-secret-agent-simple.c:924
 msgid "DSL authentication"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:894
+#: src/libnmc-base/nm-secret-agent-simple.c:925
 #, c-format
 msgid "Secrets are required for the DSL connection '%s'"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:903
+#: src/libnmc-base/nm-secret-agent-simple.c:934
 msgid "PIN code required"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:904
+#: src/libnmc-base/nm-secret-agent-simple.c:935
 msgid "PIN code is needed for the mobile broadband device"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:907
+#: src/libnmc-base/nm-secret-agent-simple.c:938
 msgid "PIN"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:912
-#: src/libnmc-base/nm-secret-agent-simple.c:947
-#: src/libnmc-base/nm-secret-agent-simple.c:974
+#: src/libnmc-base/nm-secret-agent-simple.c:943
+#: src/libnmc-base/nm-secret-agent-simple.c:978
+#: src/libnmc-base/nm-secret-agent-simple.c:1005
 msgid "Mobile broadband network password"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:925
+#: src/libnmc-base/nm-secret-agent-simple.c:956
 #, c-format
 msgid "Secrets are required to access the MACsec network '%s'"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:929
+#: src/libnmc-base/nm-secret-agent-simple.c:960
 msgid "MACsec PSK authentication"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:931
-#: src/libnmc-setting/nm-meta-setting-desc.c:6905
+#: src/libnmc-base/nm-secret-agent-simple.c:962
+#: src/libnmc-setting/nm-meta-setting-desc.c:6889
 msgid "MKA CAK"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:936
+#: src/libnmc-base/nm-secret-agent-simple.c:967
 msgid "MACsec EAP authentication"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:941
+#: src/libnmc-base/nm-secret-agent-simple.c:972
 msgid "WireGuard VPN secret"
 msgstr ""
 
-#: src/libnmc-base/nm-secret-agent-simple.c:984
+#: src/libnmc-base/nm-secret-agent-simple.c:1015
 msgid "VPN password required"
 msgstr ""
 
@@ -4727,134 +4736,134 @@ msgstr ""
 msgid "auto"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1193
+#: src/libnmc-setting/nm-meta-setting-desc.c:1179
 #, c-format
 msgid "%s (%s)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1447
-#: src/libnmc-setting/nm-meta-setting-desc.c:1455
-#: src/libnmc-setting/nm-meta-setting-desc.c:4513
+#: src/libnmc-setting/nm-meta-setting-desc.c:1435
+#: src/libnmc-setting/nm-meta-setting-desc.c:1443
+#: src/libnmc-setting/nm-meta-setting-desc.c:4488
 msgid "'%s' is out of range [%"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1463
+#: src/libnmc-setting/nm-meta-setting-desc.c:1451
 #, c-format
 msgid "'%s' is not a valid number"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1519
+#: src/libnmc-setting/nm-meta-setting-desc.c:1507
 #, c-format
 msgid "'%s' is out of range [0, %u]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1570
+#: src/libnmc-setting/nm-meta-setting-desc.c:1558
 #, c-format
 msgid "'%s' is not a valid Ethernet MAC"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1672
+#: src/libnmc-setting/nm-meta-setting-desc.c:1647
 #, c-format
 msgid "invalid option '%s', use a combination of [%s]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1809
+#: src/libnmc-setting/nm-meta-setting-desc.c:1784
 #, c-format
 msgid "%d (key)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1811
+#: src/libnmc-setting/nm-meta-setting-desc.c:1786
 #, c-format
 msgid "%d (passphrase)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1814
+#: src/libnmc-setting/nm-meta-setting-desc.c:1789
 #, c-format
 msgid "%d (unknown)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1827
+#: src/libnmc-setting/nm-meta-setting-desc.c:1802
 msgid "0 (NONE)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1833
+#: src/libnmc-setting/nm-meta-setting-desc.c:1808
 msgid "REORDER_HEADERS, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1835
+#: src/libnmc-setting/nm-meta-setting-desc.c:1810
 msgid "GVRP, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1837
+#: src/libnmc-setting/nm-meta-setting-desc.c:1812
 msgid "LOOSE_BINDING, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1839
+#: src/libnmc-setting/nm-meta-setting-desc.c:1814
 msgid "MVRP, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1860
+#: src/libnmc-setting/nm-meta-setting-desc.c:1835
 msgid "0 (none)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1866
+#: src/libnmc-setting/nm-meta-setting-desc.c:1841
 msgid "agent-owned, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1868
+#: src/libnmc-setting/nm-meta-setting-desc.c:1843
 msgid "not saved, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:1870
+#: src/libnmc-setting/nm-meta-setting-desc.c:1845
 msgid "not required, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2075
+#: src/libnmc-setting/nm-meta-setting-desc.c:2050
 #, c-format
 msgid "'%s' is not valid; use <option>=<value>"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2085
+#: src/libnmc-setting/nm-meta-setting-desc.c:2060
 #, c-format
 msgid "cannot set empty \"%s\" option"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2146
+#: src/libnmc-setting/nm-meta-setting-desc.c:2121
 #, c-format
 msgid "'%u' flags are not valid; use combination of %s"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2166
+#: src/libnmc-setting/nm-meta-setting-desc.c:2141
 #, c-format
 msgid "'%s' is not a valid number (or out of range)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2266
+#: src/libnmc-setting/nm-meta-setting-desc.c:2241
 #, c-format
 msgid "invalid IPv4 or subnet \"%s\""
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2297
+#: src/libnmc-setting/nm-meta-setting-desc.c:2272
 msgid "not a valid hex-string"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2315
+#: src/libnmc-setting/nm-meta-setting-desc.c:2290
 #, c-format
 msgid "'%s' is not a valid hex character"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2403
+#: src/libnmc-setting/nm-meta-setting-desc.c:2378
 msgid ""
 "too many arguments. Please only specify a private key file and optionally a "
 "password"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2520
+#: src/libnmc-setting/nm-meta-setting-desc.c:2495
 #, c-format
 msgid "failed to set bond option \"%s\""
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2568
+#: src/libnmc-setting/nm-meta-setting-desc.c:2543
 #, c-format
 msgid ""
 "Enter a list of bonding options formatted as:\n"
@@ -4872,118 +4881,118 @@ msgid ""
 "Example: mode=2,miimon=120\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2675
+#: src/libnmc-setting/nm-meta-setting-desc.c:2650
 msgid "Can not change the connection type"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2756
+#: src/libnmc-setting/nm-meta-setting-desc.c:2731
 #, c-format
 msgid "invalid permission \"%s\""
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2856
+#: src/libnmc-setting/nm-meta-setting-desc.c:2831
 #, c-format
 msgid "the value '%s' is not a valid UUID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2927
+#: src/libnmc-setting/nm-meta-setting-desc.c:2902
 msgid "0 (disabled)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2933
+#: src/libnmc-setting/nm-meta-setting-desc.c:2908
 msgid "enabled, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2935
+#: src/libnmc-setting/nm-meta-setting-desc.c:2910
 msgid "advertise, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:2937
+#: src/libnmc-setting/nm-meta-setting-desc.c:2912
 msgid "willing, "
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3026
+#: src/libnmc-setting/nm-meta-setting-desc.c:3001
 #, c-format
 msgid "'%s' is not a valid DCB flag"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3054
+#: src/libnmc-setting/nm-meta-setting-desc.c:3029
 msgid "must contain 8 comma-separated numbers"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3069
+#: src/libnmc-setting/nm-meta-setting-desc.c:3044
 #, c-format
 msgid "'%s' not a number between 0 and %u (inclusive) or %u"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3076
+#: src/libnmc-setting/nm-meta-setting-desc.c:3051
 #, c-format
 msgid "'%s' not a number between 0 and %u (inclusive)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3102
+#: src/libnmc-setting/nm-meta-setting-desc.c:3077
 #, c-format
 msgid "changes will have no effect until '%s' includes 1 (enabled)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3134
+#: src/libnmc-setting/nm-meta-setting-desc.c:3109
 #, c-format
 msgid "bandwidth percentages must total 100%%"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3234
-#: src/libnmc-setting/nm-meta-setting-desc.c:3243
+#: src/libnmc-setting/nm-meta-setting-desc.c:3209
+#: src/libnmc-setting/nm-meta-setting-desc.c:3218
 msgid "SIM operator ID must be a 5 or 6 number MCCMNC code"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3266
+#: src/libnmc-setting/nm-meta-setting-desc.c:3241
 #, c-format
 msgid "'%s' is not a valid IBoIP P_Key"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3290
+#: src/libnmc-setting/nm-meta-setting-desc.c:3265
 msgid "default"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3561
+#: src/libnmc-setting/nm-meta-setting-desc.c:3536
 #, c-format
 msgid "invalid gateway address '%s'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3713
+#: src/libnmc-setting/nm-meta-setting-desc.c:3688
 #, c-format
 msgid "'%s' is not a valid channel; use <1-13>"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3807
+#: src/libnmc-setting/nm-meta-setting-desc.c:3782
 msgid "The valid syntax is: vf [attribute=value]... [,vf [attribute=value]...]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3833
-#: src/libnmc-setting/nm-meta-setting-desc.c:3946
+#: src/libnmc-setting/nm-meta-setting-desc.c:3808
+#: src/libnmc-setting/nm-meta-setting-desc.c:3921
 msgid ""
 "The valid syntax is: '[root | parent <handle>] [handle <handle>] <kind>'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3860
+#: src/libnmc-setting/nm-meta-setting-desc.c:3835
 msgid "The valid syntax is: '<value>' or '<start>-<end>"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:3890
+#: src/libnmc-setting/nm-meta-setting-desc.c:3865
 msgid "The valid syntax is: '<vid>[-<vid>] [pvid] [untagged]'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4092
+#: src/libnmc-setting/nm-meta-setting-desc.c:4067
 #, c-format
 msgid "invalid priority map '%s'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4185
+#: src/libnmc-setting/nm-meta-setting-desc.c:4160
 #, c-format
 msgid "'%s' is not valid; 2 or 3 strings should be provided"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4224
+#: src/libnmc-setting/nm-meta-setting-desc.c:4199
 #, c-format
 msgid ""
 "Enter a list of S/390 options formatted as:\n"
@@ -4991,87 +5000,87 @@ msgid ""
 "Valid options are: %s\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4258
+#: src/libnmc-setting/nm-meta-setting-desc.c:4233
 #, c-format
 msgid "'%s' is not a valid channel"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4266
+#: src/libnmc-setting/nm-meta-setting-desc.c:4241
 #, c-format
 msgid "'%ld' is not a valid channel"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4347
+#: src/libnmc-setting/nm-meta-setting-desc.c:4322
 #, c-format
 msgid ""
 "'%s' not compatible with %s '%s', please change the key or set the right %s "
 "first."
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4363
+#: src/libnmc-setting/nm-meta-setting-desc.c:4338
 #, c-format
 msgid "WEP key is guessed to be of %s"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4370
+#: src/libnmc-setting/nm-meta-setting-desc.c:4345
 #, c-format
 msgid "WEP key index set to '%d'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4446
+#: src/libnmc-setting/nm-meta-setting-desc.c:4421
 #, c-format
 msgid "'%s' is not compatible with '%s' type, please change or delete the key."
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4483 src/nmcli/utils.h:322
+#: src/libnmc-setting/nm-meta-setting-desc.c:4458 src/nmcli/utils.h:322
 msgid "on"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4483 src/nmcli/utils.h:322
+#: src/libnmc-setting/nm-meta-setting-desc.c:4458 src/nmcli/utils.h:322
 msgid "off"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4531
+#: src/libnmc-setting/nm-meta-setting-desc.c:4506
 #, c-format
 msgid "'%s' is not valid; use 'on', 'off', or 'ignore'"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4604
+#: src/libnmc-setting/nm-meta-setting-desc.c:4579
 msgid "Bonding primary interface"
 msgstr ""
 
 #. this is a virtual property, only needed during "ask" mode.
-#: src/libnmc-setting/nm-meta-setting-desc.c:4612
+#: src/libnmc-setting/nm-meta-setting-desc.c:4587
 msgid "Bonding monitoring mode"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4621
+#: src/libnmc-setting/nm-meta-setting-desc.c:4596
 msgid "Bonding miimon"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4630
+#: src/libnmc-setting/nm-meta-setting-desc.c:4605
 msgid "Bonding downdelay"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4639
+#: src/libnmc-setting/nm-meta-setting-desc.c:4614
 msgid "Bonding updelay"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4648
+#: src/libnmc-setting/nm-meta-setting-desc.c:4623
 msgid "Bonding arp-interval"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4657
+#: src/libnmc-setting/nm-meta-setting-desc.c:4632
 msgid "Bonding arp-ip-target"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4666
+#: src/libnmc-setting/nm-meta-setting-desc.c:4641
 msgid "LACP rate (slow/fast)"
 msgstr ""
 
 #. macro that returns @func as const (guint32(*)(NMSetting*)) type, but checks
 #. * that the actual type is (guint32(*)(type *)).
-#: src/libnmc-setting/nm-meta-setting-desc.c:4857
+#: src/libnmc-setting/nm-meta-setting-desc.c:4832
 msgid ""
 "nmcli can accepts both direct JSON configuration data and a file name "
 "containing the configuration. In the latter case the file is read and the "
@@ -5082,7 +5091,7 @@ msgid ""
 "          set team.config /etc/my-team.conf\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4865
+#: src/libnmc-setting/nm-meta-setting-desc.c:4840
 msgid ""
 "Enter a list of link watchers formatted as dictionaries where the keys are "
 "teamd properties. Dictionary pairs are in the form: key=value and pairs are "
@@ -5108,11 +5117,11 @@ msgid ""
 "name=ethtool delay-up=3\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4914
+#: src/libnmc-setting/nm-meta-setting-desc.c:4889
 msgid "IEEE 802.15.4 (WPAN) parent device or connection UUID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4951
+#: src/libnmc-setting/nm-meta-setting-desc.c:4926
 msgid ""
 "Enter file path to CA certificate (optionally prefixed with file://).\n"
 "  [file://]<file path>\n"
@@ -5120,7 +5129,7 @@ msgid ""
 "Example: /home/cimrman/cacert.crt\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:4994
+#: src/libnmc-setting/nm-meta-setting-desc.c:4969
 msgid ""
 "Enter file path to client certificate (optionally prefixed with file://).\n"
 "  [file://]<file path>\n"
@@ -5128,7 +5137,7 @@ msgid ""
 "Example: /home/cimrman/jara.crt\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5051
+#: src/libnmc-setting/nm-meta-setting-desc.c:5026
 msgid ""
 "Enter file path to CA certificate for inner authentication (optionally "
 "prefixed\n"
@@ -5138,7 +5147,7 @@ msgid ""
 "Example: /home/cimrman/ca-zweite-phase.crt\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5099
+#: src/libnmc-setting/nm-meta-setting-desc.c:5074
 msgid ""
 "Enter file path to client certificate for inner authentication (optionally "
 "prefixed\n"
@@ -5148,7 +5157,7 @@ msgid ""
 "Example: /home/cimrman/jara-zweite-phase.crt\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5126
+#: src/libnmc-setting/nm-meta-setting-desc.c:5101
 msgid ""
 "Enter bytes as a list of hexadecimal values.\n"
 "Two formats are accepted:\n"
@@ -5161,8 +5170,8 @@ msgid ""
 "          ab 4 55 0xa6 ea 3a 74 C2\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5143
-#: src/libnmc-setting/nm-meta-setting-desc.c:5161
+#: src/libnmc-setting/nm-meta-setting-desc.c:5118
+#: src/libnmc-setting/nm-meta-setting-desc.c:5136
 msgid ""
 "Enter path to a private key and the key password (if not set yet):\n"
 "  [file://]<file path> [<password>]\n"
@@ -5170,91 +5179,91 @@ msgid ""
 "Example: /home/cimrman/jara-priv-key Dardanely\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5206
-#: src/libnmc-setting/nm-meta-setting-desc.c:5509
-#: src/libnmc-setting/nm-meta-setting-desc.c:6036
-#: src/libnmc-setting/nm-meta-setting-desc.c:7266
+#: src/libnmc-setting/nm-meta-setting-desc.c:5181
+#: src/libnmc-setting/nm-meta-setting-desc.c:5484
+#: src/libnmc-setting/nm-meta-setting-desc.c:6020
+#: src/libnmc-setting/nm-meta-setting-desc.c:7253
 msgid "Password [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5252
+#: src/libnmc-setting/nm-meta-setting-desc.c:5227
 msgid "Bluetooth device address"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5301
+#: src/libnmc-setting/nm-meta-setting-desc.c:5276
 #: src/nmtui/nmt-page-bond-port.c:51
 msgid "Queue ID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5307
+#: src/libnmc-setting/nm-meta-setting-desc.c:5282
 msgid "Port Priority"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5319
-#: src/libnmc-setting/nm-meta-setting-desc.c:6147
-#: src/libnmc-setting/nm-meta-setting-desc.c:7999
-#: src/libnmc-setting/nm-meta-setting-desc.c:8037
-#: src/libnmc-setting/nm-meta-setting-desc.c:8219
-#: src/libnmc-setting/nm-meta-setting-desc.c:8466
+#: src/libnmc-setting/nm-meta-setting-desc.c:5294
+#: src/libnmc-setting/nm-meta-setting-desc.c:6131
+#: src/libnmc-setting/nm-meta-setting-desc.c:7995
+#: src/libnmc-setting/nm-meta-setting-desc.c:8033
+#: src/libnmc-setting/nm-meta-setting-desc.c:8215
+#: src/libnmc-setting/nm-meta-setting-desc.c:8462
 msgid "MAC [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5325
+#: src/libnmc-setting/nm-meta-setting-desc.c:5300
 msgid "Enable STP"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5331
+#: src/libnmc-setting/nm-meta-setting-desc.c:5306
 msgid "STP priority"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5337
+#: src/libnmc-setting/nm-meta-setting-desc.c:5312
 #: src/nmtui/nmt-page-bridge.c:120
 msgid "Forward delay"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5343
+#: src/libnmc-setting/nm-meta-setting-desc.c:5318
 #: src/nmtui/nmt-page-bridge.c:134
 msgid "Hello time"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5349
+#: src/libnmc-setting/nm-meta-setting-desc.c:5324
 #: src/nmtui/nmt-page-bridge.c:148
 msgid "Max age"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5355
+#: src/libnmc-setting/nm-meta-setting-desc.c:5330
 msgid "MAC address ageing time"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5365
+#: src/libnmc-setting/nm-meta-setting-desc.c:5340
 #: src/nmtui/nmt-page-bridge.c:156
 msgid "Group forward mask"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5407
+#: src/libnmc-setting/nm-meta-setting-desc.c:5382
 #: src/nmtui/nmt-page-bridge.c:79
 msgid "Enable IGMP snooping"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5465
+#: src/libnmc-setting/nm-meta-setting-desc.c:5440
 msgid "Bridge port priority"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5471
+#: src/libnmc-setting/nm-meta-setting-desc.c:5446
 msgid "Bridge port STP path cost"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5477
+#: src/libnmc-setting/nm-meta-setting-desc.c:5452
 msgid "Hairpin"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5503
-#: src/libnmc-setting/nm-meta-setting-desc.c:6030
-#: src/libnmc-setting/nm-meta-setting-desc.c:7844
+#: src/libnmc-setting/nm-meta-setting-desc.c:5478
+#: src/libnmc-setting/nm-meta-setting-desc.c:6014
+#: src/libnmc-setting/nm-meta-setting-desc.c:7840
 msgid "Username [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5608
+#: src/libnmc-setting/nm-meta-setting-desc.c:5583
 msgid ""
 "Enter a list of user permissions. This is a list of user names formatted "
 "as:\n"
@@ -5264,11 +5273,11 @@ msgid ""
 "Example: alice bob charlie\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5637
+#: src/libnmc-setting/nm-meta-setting-desc.c:5612
 msgid "Controller"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5693
+#: src/libnmc-setting/nm-meta-setting-desc.c:5668
 msgid ""
 "Enter secondary connections that should be activated when this connection "
 "is\n"
@@ -5281,7 +5290,7 @@ msgid ""
 "Example: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:5717
+#: src/libnmc-setting/nm-meta-setting-desc.c:5692
 msgid ""
 "Enter a value which indicates whether the connection is subject to a data\n"
 "quota, usage costs or other limitations. Accepted options are:\n"
@@ -5290,52 +5299,52 @@ msgid ""
 "'unknown' to let NetworkManager choose a value using some heuristics\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6046
+#: src/libnmc-setting/nm-meta-setting-desc.c:6030
 msgid "APN"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6100
+#: src/libnmc-setting/nm-meta-setting-desc.c:6084
 msgid "hsr port1"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6107
+#: src/libnmc-setting/nm-meta-setting-desc.c:6091
 msgid "hsr port2"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6113
+#: src/libnmc-setting/nm-meta-setting-desc.c:6097
 msgid "hsr multicast spec"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6156
-#: src/libnmc-setting/nm-meta-setting-desc.c:6812
-#: src/libnmc-setting/nm-meta-setting-desc.c:8069
-#: src/libnmc-setting/nm-meta-setting-desc.c:8266
+#: src/libnmc-setting/nm-meta-setting-desc.c:6140
+#: src/libnmc-setting/nm-meta-setting-desc.c:6796
+#: src/libnmc-setting/nm-meta-setting-desc.c:8065
+#: src/libnmc-setting/nm-meta-setting-desc.c:8262
 #: src/nmtui/nmt-page-ethernet.c:124 src/nmtui/nmt-page-infiniband.c:81
 #: src/nmtui/nmt-page-ip-tunnel.c:178 src/nmtui/nmt-page-vlan.c:100
 #: src/nmtui/nmt-page-wifi.c:395 src/nmtui/nmt-page-wireguard.c:85
 msgid "MTU"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6175
+#: src/libnmc-setting/nm-meta-setting-desc.c:6159
 msgid "P_KEY [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6193
+#: src/libnmc-setting/nm-meta-setting-desc.c:6177
 msgid "Parent interface [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6222
+#: src/libnmc-setting/nm-meta-setting-desc.c:6206
 msgid ""
 "Enter a list of IPv4 addresses of DNS servers.\n"
 "\n"
 "Example: 8.8.8.8, 8.8.4.4\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6272
+#: src/libnmc-setting/nm-meta-setting-desc.c:6256
 msgid "IPv4 address (IP[/plen]) [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6274
+#: src/libnmc-setting/nm-meta-setting-desc.c:6258
 msgid ""
 "Enter a list of IPv4 addresses formatted as:\n"
 "  ip[/prefix], ip[/prefix],...\n"
@@ -5344,11 +5353,11 @@ msgid ""
 "Example: 192.168.1.5/24, 10.0.0.11/24\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6293
+#: src/libnmc-setting/nm-meta-setting-desc.c:6277
 msgid "IPv4 gateway [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6302
+#: src/libnmc-setting/nm-meta-setting-desc.c:6286
 msgid ""
 "Enter a list of IPv4 routes formatted as:\n"
 "  ip[/prefix] [next-hop] [metric],...\n"
@@ -5361,14 +5370,14 @@ msgid ""
 "          10.1.2.0/24\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6342
+#: src/libnmc-setting/nm-meta-setting-desc.c:6326
 msgid ""
 "Enter a list of IPv4 routing rules formatted as:\n"
 "  priority [prio] [from [src]] [to [dst]], ,...\n"
 "\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6486
+#: src/libnmc-setting/nm-meta-setting-desc.c:6470
 msgid ""
 "Enter a list of IPv6 addresses of DNS servers.  If the IPv6 configuration "
 "method is 'auto' these DNS servers are appended to those (if any) returned "
@@ -5380,11 +5389,11 @@ msgid ""
 "Example: 2607:f0d0:1002:51::4, 2607:f0d0:1002:51::1\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6542
+#: src/libnmc-setting/nm-meta-setting-desc.c:6526
 msgid "IPv6 address (IP[/plen]) [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6544
+#: src/libnmc-setting/nm-meta-setting-desc.c:6528
 msgid ""
 "Enter a list of IPv6 addresses formatted as:\n"
 "  ip[/prefix], ip[/prefix],...\n"
@@ -5393,11 +5402,11 @@ msgid ""
 "Example: 2607:f0d0:1002:51::4/64, 1050:0:0:0:5:600:300c:326b\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6563
+#: src/libnmc-setting/nm-meta-setting-desc.c:6547
 msgid "IPv6 gateway [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6572
+#: src/libnmc-setting/nm-meta-setting-desc.c:6556
 msgid ""
 "Enter a list of IPv6 routes formatted as:\n"
 "  ip[/prefix] [next-hop] [metric],...\n"
@@ -5411,403 +5420,403 @@ msgid ""
 "          abbe::/64 55\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6612
+#: src/libnmc-setting/nm-meta-setting-desc.c:6596
 msgid ""
 "Enter a list of IPv6 routing rules formatted as:\n"
 "  priority [prio] [from [src]] [to [dst]], ,...\n"
 "\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6749
-#: src/libnmc-setting/nm-meta-setting-desc.c:7899
+#: src/libnmc-setting/nm-meta-setting-desc.c:6733
+#: src/libnmc-setting/nm-meta-setting-desc.c:7895
 msgid "Parent device [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6755
+#: src/libnmc-setting/nm-meta-setting-desc.c:6739
 msgid "Local endpoint [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6762
-#: src/libnmc-setting/nm-meta-setting-desc.c:7918
+#: src/libnmc-setting/nm-meta-setting-desc.c:6746
+#: src/libnmc-setting/nm-meta-setting-desc.c:7914
 msgid "Remote"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6878
+#: src/libnmc-setting/nm-meta-setting-desc.c:6862
 msgid "MACsec parent device or connection UUID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6899
+#: src/libnmc-setting/nm-meta-setting-desc.c:6883
 msgid "Enable encryption"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6915
+#: src/libnmc-setting/nm-meta-setting-desc.c:6899
 msgid "MKA_CKN"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6921
+#: src/libnmc-setting/nm-meta-setting-desc.c:6905
 #: src/nmtui/nmt-page-macsec.c:170
 msgid "SCI port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6947
+#: src/libnmc-setting/nm-meta-setting-desc.c:6934
 msgid "MACVLAN parent device or connection UUID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:6968
+#: src/libnmc-setting/nm-meta-setting-desc.c:6955
 msgid "Tap"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7039
-#: src/libnmc-setting/nm-meta-setting-desc.c:8179 src/nmtui/nmt-page-wifi.c:216
+#: src/libnmc-setting/nm-meta-setting-desc.c:7026
+#: src/libnmc-setting/nm-meta-setting-desc.c:8175 src/nmtui/nmt-page-wifi.c:216
 msgid "SSID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7049
+#: src/libnmc-setting/nm-meta-setting-desc.c:7036
 msgid "OLPC Mesh channel"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7059
+#: src/libnmc-setting/nm-meta-setting-desc.c:7046
 msgid "DHCP anycast MAC address [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7247
+#: src/libnmc-setting/nm-meta-setting-desc.c:7234
 msgid "PPPoE parent device"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7253
+#: src/libnmc-setting/nm-meta-setting-desc.c:7240
 msgid "Service [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7260
+#: src/libnmc-setting/nm-meta-setting-desc.c:7247
 msgid "PPPoE username"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7296
+#: src/libnmc-setting/nm-meta-setting-desc.c:7283
 msgid "Browser only"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7302
+#: src/libnmc-setting/nm-meta-setting-desc.c:7289
 msgid "PAC URL"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7308
+#: src/libnmc-setting/nm-meta-setting-desc.c:7295
 msgid "PAC script"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7432
-#: src/libnmc-setting/nm-meta-setting-desc.c:7621
+#: src/libnmc-setting/nm-meta-setting-desc.c:7428
+#: src/libnmc-setting/nm-meta-setting-desc.c:7617
 msgid "Team JSON configuration [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7724
+#: src/libnmc-setting/nm-meta-setting-desc.c:7720
 msgid "User ID [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7730
+#: src/libnmc-setting/nm-meta-setting-desc.c:7726
 msgid "Group ID [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7736
+#: src/libnmc-setting/nm-meta-setting-desc.c:7732
 msgid "Enable PI"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7742
+#: src/libnmc-setting/nm-meta-setting-desc.c:7738
 msgid "Enable VNET header"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7748
+#: src/libnmc-setting/nm-meta-setting-desc.c:7744
 msgid "Enable multi queue"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7761
+#: src/libnmc-setting/nm-meta-setting-desc.c:7757
 msgid "veth peer"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7774
+#: src/libnmc-setting/nm-meta-setting-desc.c:7770
 msgid "VLAN parent device or connection UUID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7781
+#: src/libnmc-setting/nm-meta-setting-desc.c:7777
 msgid "VLAN ID (<0-4094>)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7787
+#: src/libnmc-setting/nm-meta-setting-desc.c:7783
 msgid "VLAN flags (<0-7>) [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7803
+#: src/libnmc-setting/nm-meta-setting-desc.c:7799
 msgid "Ingress priority maps [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7814
+#: src/libnmc-setting/nm-meta-setting-desc.c:7810
 msgid "Egress priority maps [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7886
+#: src/libnmc-setting/nm-meta-setting-desc.c:7882
 msgid "Table"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7906
+#: src/libnmc-setting/nm-meta-setting-desc.c:7902
 msgid "VXLAN ID"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7912
+#: src/libnmc-setting/nm-meta-setting-desc.c:7908
 msgid "Local address [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7924
+#: src/libnmc-setting/nm-meta-setting-desc.c:7920
 msgid "Minimum source port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7930
+#: src/libnmc-setting/nm-meta-setting-desc.c:7926
 msgid "Maximum source port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7936
+#: src/libnmc-setting/nm-meta-setting-desc.c:7932
 msgid "Destination port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:7976
+#: src/libnmc-setting/nm-meta-setting-desc.c:7972
 #: src/nmtui/nmt-wireguard-peer-editor.c:78
 msgid "Peer"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8006
+#: src/libnmc-setting/nm-meta-setting-desc.c:8002
 msgid "WiMAX NSP name"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8043
-#: src/libnmc-setting/nm-meta-setting-desc.c:8224
+#: src/libnmc-setting/nm-meta-setting-desc.c:8039
+#: src/libnmc-setting/nm-meta-setting-desc.c:8220
 msgid "Cloned MAC [none]"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8077
+#: src/libnmc-setting/nm-meta-setting-desc.c:8073
 msgid ""
 "Enter a list of subchannels (comma or space separated).\n"
 "\n"
 "Example: 0.0.0e20 0.0.0e21 0.0.0e22\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8415
+#: src/libnmc-setting/nm-meta-setting-desc.c:8411
 msgid ""
 "Enter the type of WEP keys. The accepted values are: 0 or unknown, 1 or key, "
 "and 2 or passphrase.\n"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8474
+#: src/libnmc-setting/nm-meta-setting-desc.c:8470
 msgid "Short address (<0x0000-0xffff>)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8490
+#: src/libnmc-setting/nm-meta-setting-desc.c:8486
 msgid "PAN Identifier (<0x0000-0xffff>)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8505
+#: src/libnmc-setting/nm-meta-setting-desc.c:8501
 msgid "Page (<default|0-31>)"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8519
+#: src/libnmc-setting/nm-meta-setting-desc.c:8515
 msgid "Channel (<default|0-26>)"
 msgstr ""
 
 #. ***************************************************************************
-#: src/libnmc-setting/nm-meta-setting-desc.c:8654
+#: src/libnmc-setting/nm-meta-setting-desc.c:8650
 msgid "6LOWPAN settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8655
+#: src/libnmc-setting/nm-meta-setting-desc.c:8651
 msgid "802-1x settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8657
+#: src/libnmc-setting/nm-meta-setting-desc.c:8653
 msgid "bluetooth connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8658
+#: src/libnmc-setting/nm-meta-setting-desc.c:8654
 msgid "Bond device"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8659
+#: src/libnmc-setting/nm-meta-setting-desc.c:8655
 msgid "Bond port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8660
+#: src/libnmc-setting/nm-meta-setting-desc.c:8656
 msgid "Bridge device"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8661
+#: src/libnmc-setting/nm-meta-setting-desc.c:8657
 msgid "Bridge port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8662
+#: src/libnmc-setting/nm-meta-setting-desc.c:8658
 msgid "CDMA mobile broadband connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8663
+#: src/libnmc-setting/nm-meta-setting-desc.c:8659
 msgid "General settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8664
+#: src/libnmc-setting/nm-meta-setting-desc.c:8660
 msgid "DCB settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8665
+#: src/libnmc-setting/nm-meta-setting-desc.c:8661
 msgid "Dummy settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8666
+#: src/libnmc-setting/nm-meta-setting-desc.c:8662
 msgid "Ethtool settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8667
+#: src/libnmc-setting/nm-meta-setting-desc.c:8663
 msgid "Generic settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8668
+#: src/libnmc-setting/nm-meta-setting-desc.c:8664
 msgid "GSM mobile broadband connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8669
+#: src/libnmc-setting/nm-meta-setting-desc.c:8665
 msgid "Hostname settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8670
+#: src/libnmc-setting/nm-meta-setting-desc.c:8666
 msgid "HSR settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8672
+#: src/libnmc-setting/nm-meta-setting-desc.c:8668
 msgid "IPv4 protocol"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8673
+#: src/libnmc-setting/nm-meta-setting-desc.c:8669
 msgid "IPv6 protocol"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8674
+#: src/libnmc-setting/nm-meta-setting-desc.c:8670
 msgid "IP-tunnel settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8675
+#: src/libnmc-setting/nm-meta-setting-desc.c:8671
 msgid "Link settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8676
+#: src/libnmc-setting/nm-meta-setting-desc.c:8672
 msgid "Loopback settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8677
+#: src/libnmc-setting/nm-meta-setting-desc.c:8673
 msgid "MACsec connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8678
+#: src/libnmc-setting/nm-meta-setting-desc.c:8674
 msgid "macvlan connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8679
+#: src/libnmc-setting/nm-meta-setting-desc.c:8675
 msgid "Match"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8680
+#: src/libnmc-setting/nm-meta-setting-desc.c:8676
 msgid "OLPC Mesh connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8681
+#: src/libnmc-setting/nm-meta-setting-desc.c:8677
 msgid "Open vSwitch bridge settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8682
+#: src/libnmc-setting/nm-meta-setting-desc.c:8678
 msgid "Open vSwitch DPDK interface settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8683
+#: src/libnmc-setting/nm-meta-setting-desc.c:8679
 msgid "OVS Other Config"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8684
+#: src/libnmc-setting/nm-meta-setting-desc.c:8680
 msgid "OVS External IDs"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8685
+#: src/libnmc-setting/nm-meta-setting-desc.c:8681
 msgid "Open vSwitch interface settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8686
+#: src/libnmc-setting/nm-meta-setting-desc.c:8682
 msgid "Open vSwitch patch interface settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8687
+#: src/libnmc-setting/nm-meta-setting-desc.c:8683
 msgid "Open vSwitch port settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8688
+#: src/libnmc-setting/nm-meta-setting-desc.c:8684
 msgid "PPP settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8689
+#: src/libnmc-setting/nm-meta-setting-desc.c:8685
 msgid "PPPoE"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8690
+#: src/libnmc-setting/nm-meta-setting-desc.c:8686
 msgid "Proxy"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8691
+#: src/libnmc-setting/nm-meta-setting-desc.c:8687
 msgid "Serial settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8692
+#: src/libnmc-setting/nm-meta-setting-desc.c:8688
 msgid "SR-IOV settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8693
+#: src/libnmc-setting/nm-meta-setting-desc.c:8689
 msgid "Traffic controls"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8694
+#: src/libnmc-setting/nm-meta-setting-desc.c:8690
 msgid "Team device"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8695
+#: src/libnmc-setting/nm-meta-setting-desc.c:8691
 msgid "Team port"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8696
+#: src/libnmc-setting/nm-meta-setting-desc.c:8692
 msgid "Tun device"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8697
+#: src/libnmc-setting/nm-meta-setting-desc.c:8693
 msgid "User settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8703
+#: src/libnmc-setting/nm-meta-setting-desc.c:8699
 msgid "Wi-Fi P2P connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8704
+#: src/libnmc-setting/nm-meta-setting-desc.c:8700
 msgid "WiMAX connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8705
+#: src/libnmc-setting/nm-meta-setting-desc.c:8701
 msgid "Wired Ethernet"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8706
+#: src/libnmc-setting/nm-meta-setting-desc.c:8702
 msgid "WireGuard VPN settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8707
+#: src/libnmc-setting/nm-meta-setting-desc.c:8703
 msgid "Wi-Fi connection"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8708
+#: src/libnmc-setting/nm-meta-setting-desc.c:8704
 msgid "Wi-Fi security settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:8709
+#: src/libnmc-setting/nm-meta-setting-desc.c:8705
 msgid "WPAN settings"
 msgstr ""
 
-#: src/libnmc-setting/nm-meta-setting-desc.c:9138
+#: src/libnmc-setting/nm-meta-setting-desc.c:9134
 msgid "name"
 msgstr ""
 
@@ -6288,8 +6297,8 @@ msgstr ""
 #: src/libnmc-setting/settings-docs.h.in:52
 #: src/libnmc-setting/settings-docs.h.in:84
 #: src/libnmc-setting/settings-docs.h.in:126
-#: src/libnmc-setting/settings-docs.h.in:153
-#: src/libnmc-setting/settings-docs.h.in:300
+#: src/libnmc-setting/settings-docs.h.in:154
+#: src/libnmc-setting/settings-docs.h.in:302
 msgid "Flags indicating how to handle the \"password\" property."
 msgstr ""
 
@@ -6500,7 +6509,7 @@ msgid "PIN used for EAP authentication methods."
 msgstr ""
 
 #: src/libnmc-setting/settings-docs.h.in:76
-#: src/libnmc-setting/settings-docs.h.in:155
+#: src/libnmc-setting/settings-docs.h.in:156
 msgid "Flags indicating how to handle the \"pin\" property."
 msgstr ""
 
@@ -6785,8 +6794,8 @@ msgid ""
 msgstr ""
 
 #: src/libnmc-setting/settings-docs.h.in:123
-#: src/libnmc-setting/settings-docs.h.in:149
-#: src/libnmc-setting/settings-docs.h.in:160
+#: src/libnmc-setting/settings-docs.h.in:150
+#: src/libnmc-setting/settings-docs.h.in:161
 msgid ""
 "If non-zero, only transmit packets of the specified size or smaller, "
 "breaking larger packets up into multiple frames."
@@ -6800,7 +6809,7 @@ msgid ""
 msgstr ""
 
 #: src/libnmc-setting/settings-docs.h.in:125
-#: src/libnmc-setting/settings-docs.h.in:152
+#: src/libnmc-setting/settings-docs.h.in:153
 msgid ""
 "The password used to authenticate with the network, if required.  Many "
 "providers do not require a password, or accept any password.  But if a "
@@ -6808,7 +6817,7 @@ msgid ""
 msgstr ""
 
 #: src/libnmc-setting/settings-docs.h.in:127
-#: src/libnmc-setting/settings-docs.h.in:158
+#: src/libnmc-setting/settings-docs.h.in:159
 msgid ""
 "The username used to authenticate with the network, if required.  Many "
 "providers do not require a username, or accept any username.  But if a "
@@ -6924,6 +6933,18 @@ msgstr ""
 
 #: src/libnmc-setting/settings-docs.h.in:143
 msgid ""
+"Name of the device handler that will be invoked to add and delete the device "
+"for this connection. The name can only contain ASCII alphanumeric characters "
+"and '-', '_', '.'. It cannot start with '.'. See the NetworkManager-"
+"dispatcher(8) man page for more details about how to write the device "
+"handler. By setting this property the generic connection becomes "
+"\"virtual\", meaning that it can be activated without an existing device; "
+"the device will be created at the time the connection is started by invoking "
+"the device-handler."
+msgstr ""
+
+#: src/libnmc-setting/settings-docs.h.in:144
+msgid ""
 "The GPRS Access Point Name specifying the APN used when establishing a data "
 "session with the GSM-based network.  The APN often determines how the user "
 "will be billed for their network usage and whether the user has access to "
@@ -6935,41 +6956,41 @@ msgid ""
 "string to prevent that and use no APN."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:144
+#: src/libnmc-setting/settings-docs.h.in:145
 msgid ""
 "When TRUE, the settings such as APN, username, or password will default to "
 "values that match the network the modem will register to in the Mobile "
 "Broadband Provider database."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:145
+#: src/libnmc-setting/settings-docs.h.in:146
 msgid ""
 "The device unique identifier (as given by the WWAN management service) which "
 "this connection applies to.  If given, the connection will only apply to the "
 "specified device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:146
+#: src/libnmc-setting/settings-docs.h.in:147
 msgid ""
 "When TRUE, only connections to the home network will be allowed. Connections "
 "to roaming networks will not be made."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:147
+#: src/libnmc-setting/settings-docs.h.in:148
 msgid ""
 "For LTE modems, this sets the APN for the initial EPS bearer that is set up "
 "when attaching to the network.  Setting this parameter implies initial-eps-"
 "bearer-configure to be TRUE."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:148
+#: src/libnmc-setting/settings-docs.h.in:149
 msgid ""
 "For LTE modems, this setting determines whether the initial EPS bearer shall "
 "be configured when bringing up the connection.  It is inferred TRUE if "
 "initial-eps-bearer-apn is set."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:150
+#: src/libnmc-setting/settings-docs.h.in:151
 msgid ""
 "The Network ID (GSM LAI format, ie MCC-MNC) to force specific network "
 "registration.  If the Network ID is specified, NetworkManager will attempt "
@@ -6978,20 +6999,20 @@ msgid ""
 "the device is not otherwise possible."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:151
+#: src/libnmc-setting/settings-docs.h.in:152
 msgid ""
 "Legacy setting that used to help establishing PPP data sessions for GSM-"
 "based modems."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:154
+#: src/libnmc-setting/settings-docs.h.in:155
 msgid ""
 "If the SIM is locked with a PIN it must be unlocked before any other "
 "operations are requested.  Specify the PIN here to allow operation of the "
 "device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:156
+#: src/libnmc-setting/settings-docs.h.in:157
 msgid ""
 "The SIM card unique identifier (as given by the WWAN management service) "
 "which this connection applies to.  If given, the connection will apply to "
@@ -6999,7 +7020,7 @@ msgid ""
 "the given identifier."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:157
+#: src/libnmc-setting/settings-docs.h.in:158
 msgid ""
 "A MCC/MNC string like \"310260\" or \"21601\" identifying the specific "
 "mobile network operator which this connection applies to.  If given, the "
@@ -7007,14 +7028,14 @@ msgid ""
 "id\" which contains a SIM card provisioned by the given operator."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:159
+#: src/libnmc-setting/settings-docs.h.in:160
 msgid ""
 "If specified, this connection will only apply to the IPoIB device whose "
 "permanent MAC address matches. This property does not change the MAC address "
 "of the device (i.e. MAC spoofing)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:161
+#: src/libnmc-setting/settings-docs.h.in:162
 msgid ""
 "The InfiniBand p-key to use for this device. A value of -1 means to use the "
 "default p-key (aka \"the p-key at index 0\"). Otherwise, it is a 16-bit "
@@ -7027,19 +7048,19 @@ msgid ""
 "membership p-key with 0x8000 flag set."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:162
+#: src/libnmc-setting/settings-docs.h.in:163
 msgid ""
 "The interface name of the parent device of this device. Normally NULL, but "
 "if the \"p_key\" property is set, then you must specify the base device by "
 "setting either this property or \"mac-address\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:163
+#: src/libnmc-setting/settings-docs.h.in:164
 msgid ""
 "The IP-over-InfiniBand transport mode. Either \"datagram\" or \"connected\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:164
+#: src/libnmc-setting/settings-docs.h.in:165
 msgid ""
 "A list of IPv4 addresses and their prefix length. Multiple addresses can be "
 "separated by comma. For example \"192.168.1.5/24, 10.1.0.5/24\". The "
@@ -7047,8 +7068,8 @@ msgid ""
 "be the primary address."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:165
-#: src/libnmc-setting/settings-docs.h.in:196
+#: src/libnmc-setting/settings-docs.h.in:166
+#: src/libnmc-setting/settings-docs.h.in:197
 msgid ""
 "VPN connections will default to add the route automatically unless this "
 "setting is set to FALSE. For other connection types, adding such an "
@@ -7056,8 +7077,8 @@ msgid ""
 "effect."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:166
-#: src/libnmc-setting/settings-docs.h.in:197
+#: src/libnmc-setting/settings-docs.h.in:167
+#: src/libnmc-setting/settings-docs.h.in:198
 msgid ""
 "Maximum timeout in milliseconds used to check for the presence of duplicate "
 "IP addresses on the network.  If an address conflict is detected, the "
@@ -7070,7 +7091,7 @@ msgid ""
 "in this property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:167
+#: src/libnmc-setting/settings-docs.h.in:168
 msgid ""
 "A string sent to the DHCP server to identify the local machine which the "
 "DHCP server may use to customize the DHCP lease and options. When the "
@@ -7100,8 +7121,8 @@ msgid ""
 "otherwise."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:168
-#: src/libnmc-setting/settings-docs.h.in:198
+#: src/libnmc-setting/settings-docs.h.in:169
+#: src/libnmc-setting/settings-docs.h.in:199
 msgid ""
 "Specifies the value for the DSCP field (traffic class) of the IP header. "
 "When empty, the global default value is used; if no global default is "
@@ -7110,23 +7131,23 @@ msgid ""
 "supported only by the \"internal\" DHCP plugin."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:169
+#: src/libnmc-setting/settings-docs.h.in:170
 msgid ""
 "If the \"dhcp-send-hostname\" property is TRUE, then the specified FQDN will "
 "be sent to the DHCP server when acquiring a lease. This property and \"dhcp-"
 "hostname\" are mutually exclusive and cannot be set at the same time."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:170
-#: src/libnmc-setting/settings-docs.h.in:200
+#: src/libnmc-setting/settings-docs.h.in:171
+#: src/libnmc-setting/settings-docs.h.in:201
 msgid ""
 "If the \"dhcp-send-hostname\" property is TRUE, then the specified name will "
 "be sent to the DHCP server when acquiring a lease. This property and \"dhcp-"
 "fqdn\" are mutually exclusive and cannot be set at the same time."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:171
-#: src/libnmc-setting/settings-docs.h.in:201
+#: src/libnmc-setting/settings-docs.h.in:172
+#: src/libnmc-setting/settings-docs.h.in:202
 msgid ""
 "Flags for the DHCP hostname and FQDN. Currently, this property only includes "
 "flags to control the FQDN flags set in the DHCP FQDN option. Supported FQDN "
@@ -7141,8 +7162,8 @@ msgid ""
 "then the standard FQDN flags described above are sent in the DHCP requests."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:172
-#: src/libnmc-setting/settings-docs.h.in:202
+#: src/libnmc-setting/settings-docs.h.in:173
+#: src/libnmc-setting/settings-docs.h.in:203
 msgid ""
 "A string containing the \"Identity Association Identifier\" (IAID) used by "
 "the DHCP client. The string can be a 32-bit number (either decimal, "
@@ -7163,8 +7184,8 @@ msgid ""
 "the lease information of the device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:173
-#: src/libnmc-setting/settings-docs.h.in:204
+#: src/libnmc-setting/settings-docs.h.in:174
+#: src/libnmc-setting/settings-docs.h.in:205
 msgid ""
 "Array of servers from which DHCP offers must be rejected. This property is "
 "useful to avoid getting a lease from misconfigured or rogue servers. For "
@@ -7173,8 +7194,8 @@ msgid ""
 "not implemented for DHCPv6."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:174
-#: src/libnmc-setting/settings-docs.h.in:205
+#: src/libnmc-setting/settings-docs.h.in:175
+#: src/libnmc-setting/settings-docs.h.in:206
 msgid ""
 "If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some "
 "DHCP servers use this hostname to update DNS databases, essentially "
@@ -7183,8 +7204,8 @@ msgid ""
 "of the computer is sent."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:175
-#: src/libnmc-setting/settings-docs.h.in:206
+#: src/libnmc-setting/settings-docs.h.in:176
+#: src/libnmc-setting/settings-docs.h.in:207
 msgid ""
 "A timeout for a DHCP transaction in seconds. If zero (the default), a "
 "globally configured default is used. If still unspecified, a device specific "
@@ -7192,7 +7213,7 @@ msgid ""
 "infinity."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:176
+#: src/libnmc-setting/settings-docs.h.in:177
 msgid ""
 "The Vendor Class Identifier DHCP option (60). Special characters in the data "
 "string may be escaped using C-style escapes, nevertheless this property "
@@ -7201,15 +7222,15 @@ msgid ""
 "the DHCP option is not sent to the server."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:177
-#: src/libnmc-setting/settings-docs.h.in:207
+#: src/libnmc-setting/settings-docs.h.in:178
+#: src/libnmc-setting/settings-docs.h.in:208
 msgid ""
 "Array of IP addresses of DNS servers. For DoT (DNS over TLS), the SNI server "
 "name can be specified by appending \"#example.com\" to the IP address of the "
 "DNS server. This currently only has effect when using systemd-resolved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:178
+#: src/libnmc-setting/settings-docs.h.in:179
 msgid ""
 "DNS options for /etc/resolv.conf as described in resolv.conf(5) manual. The "
 "currently supported options are \"attempts\", \"debug\", \"edns0\", "
@@ -7227,8 +7248,8 @@ msgid ""
 "options\" get merged together."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:179
-#: src/libnmc-setting/settings-docs.h.in:209
+#: src/libnmc-setting/settings-docs.h.in:180
+#: src/libnmc-setting/settings-docs.h.in:210
 msgid ""
 "DNS servers priority. The relative priority for DNS servers specified by "
 "this setting.  A lower numerical value is better (higher priority). Negative "
@@ -7268,8 +7289,8 @@ msgid ""
 "of the desired interface are configured."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:180
-#: src/libnmc-setting/settings-docs.h.in:210
+#: src/libnmc-setting/settings-docs.h.in:181
+#: src/libnmc-setting/settings-docs.h.in:211
 msgid ""
 "List of DNS search domains. Domains starting with a tilde ('~') are "
 "considered 'routing' domains and are used only to decide the interface over "
@@ -7285,8 +7306,8 @@ msgid ""
 "DHCP (option 15)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:181
-#: src/libnmc-setting/settings-docs.h.in:211
+#: src/libnmc-setting/settings-docs.h.in:182
+#: src/libnmc-setting/settings-docs.h.in:212
 msgid ""
 "The gateway associated with this configuration. This is only meaningful if "
 "\"addresses\" is also set. Setting the gateway causes NetworkManager to "
@@ -7298,8 +7319,8 @@ msgid ""
 "case. See \"ip4-auto-default-route\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:182
-#: src/libnmc-setting/settings-docs.h.in:212
+#: src/libnmc-setting/settings-docs.h.in:183
+#: src/libnmc-setting/settings-docs.h.in:213
 msgid ""
 "When \"method\" is set to \"auto\" and this property to TRUE, automatically "
 "configured name servers and search domains are ignored and only name servers "
@@ -7307,15 +7328,15 @@ msgid ""
 "if any, are used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:183
-#: src/libnmc-setting/settings-docs.h.in:213
+#: src/libnmc-setting/settings-docs.h.in:184
+#: src/libnmc-setting/settings-docs.h.in:214
 msgid ""
 "When \"method\" is set to \"auto\" and this property to TRUE, automatically "
 "configured routes are ignored and only routes specified in the \"routes\" "
 "property, if any, are used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:184
+#: src/libnmc-setting/settings-docs.h.in:185
 msgid ""
 "Enable and disable the IPv4 link-local configuration independently of the "
 "ipv4.method configuration. This allows a link-local address (169.254.x.y/16) "
@@ -7327,8 +7348,8 @@ msgid ""
 "disabled too. The default is \"default\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:185
-#: src/libnmc-setting/settings-docs.h.in:215
+#: src/libnmc-setting/settings-docs.h.in:186
+#: src/libnmc-setting/settings-docs.h.in:216
 msgid ""
 "If TRUE, allow overall network configuration to proceed even if the "
 "configuration specified by this property times out.  Note that at least one "
@@ -7338,26 +7359,26 @@ msgid ""
 "if IPv4 configuration fails but IPv6 configuration completes successfully."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:186
+#: src/libnmc-setting/settings-docs.h.in:187
 msgid "The IPv4 connection method."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:187
-#: src/libnmc-setting/settings-docs.h.in:218
+#: src/libnmc-setting/settings-docs.h.in:188
+#: src/libnmc-setting/settings-docs.h.in:219
 msgid ""
 "If TRUE, this connection will never be the default connection for this IP "
 "type, meaning it will never be assigned the default route by NetworkManager."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:188
-#: src/libnmc-setting/settings-docs.h.in:220
+#: src/libnmc-setting/settings-docs.h.in:189
+#: src/libnmc-setting/settings-docs.h.in:221
 msgid ""
 "Connections will default to keep the autogenerated priority 0 local rule "
 "unless this setting is set to TRUE."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:189
-#: src/libnmc-setting/settings-docs.h.in:221
+#: src/libnmc-setting/settings-docs.h.in:190
+#: src/libnmc-setting/settings-docs.h.in:222
 msgid ""
 "The minimum time interval in milliseconds for which dynamic IP configuration "
 "should be tried before the connection succeeds. This property is useful for "
@@ -7372,8 +7393,8 @@ msgid ""
 "configuration ipvx.required-timeout override or zero)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:190
-#: src/libnmc-setting/settings-docs.h.in:222
+#: src/libnmc-setting/settings-docs.h.in:191
+#: src/libnmc-setting/settings-docs.h.in:223
 msgid ""
 "The default metric for routes that don't explicitly specify a metric. The "
 "default value -1 means that the metric is chosen automatically based on the "
@@ -7384,8 +7405,8 @@ msgid ""
 "mean setting it to 1024. For IPv4, zero is a regular value for the metric."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:191
-#: src/libnmc-setting/settings-docs.h.in:223
+#: src/libnmc-setting/settings-docs.h.in:192
+#: src/libnmc-setting/settings-docs.h.in:224
 msgid ""
 "Enable policy routing (source routing) and set the routing table used when "
 "adding routes. This affects all routes, including device-routes, IPv4LL, "
@@ -7402,7 +7423,7 @@ msgid ""
 "tables outside of NetworkManager."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:192
+#: src/libnmc-setting/settings-docs.h.in:193
 msgid ""
 "A list of IPv4 destination addresses, prefix length, optional IPv4 next hop "
 "addresses, optional route metric, optional attribute. The valid syntax is: "
@@ -7410,12 +7431,12 @@ msgid ""
 "example \"192.0.2.0/24 10.1.1.1 77, 198.51.100.0/24\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:193
-#: src/libnmc-setting/settings-docs.h.in:225
+#: src/libnmc-setting/settings-docs.h.in:194
+#: src/libnmc-setting/settings-docs.h.in:226
 msgid "A comma separated list of routing rules for policy routing."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:194
+#: src/libnmc-setting/settings-docs.h.in:195
 msgid ""
 "Configure method for creating the IPv6 interface identifer of addresses with "
 "RFC4862 IPv6 Stateless Address Autoconfiguration and Link Local addresses. "
@@ -7444,7 +7465,7 @@ msgid ""
 "option."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:195
+#: src/libnmc-setting/settings-docs.h.in:196
 msgid ""
 "A list of IPv6 addresses and their prefix length. Multiple addresses can be "
 "separated by comma. For example \"2001:db8:85a3::8a2e:370:7334/64, 2001:"
@@ -7453,7 +7474,7 @@ msgid ""
 "with IPv6 source address selection (RFC 6724, section 5)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:199
+#: src/libnmc-setting/settings-docs.h.in:200
 msgid ""
 "A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp "
 "client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried "
@@ -7482,7 +7503,7 @@ msgid ""
 "assumed."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:203
+#: src/libnmc-setting/settings-docs.h.in:204
 msgid ""
 "A IPv6 address followed by a slash and a prefix length. If set, the value is "
 "sent to the DHCPv6 server as hint indicating the prefix delegation (IA_PD) "
@@ -7490,7 +7511,7 @@ msgid ""
 "address part to the zero address (for example \"::/60\")."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:208
+#: src/libnmc-setting/settings-docs.h.in:209
 msgid ""
 "DNS options for /etc/resolv.conf as described in resolv.conf(5) manual. The "
 "currently supported options are \"attempts\", \"debug\", \"edns0\", "
@@ -7509,7 +7530,7 @@ msgid ""
 "options\" get merged together."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:214
+#: src/libnmc-setting/settings-docs.h.in:215
 msgid ""
 "Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If "
 "enabled, it makes the kernel generate a temporary IPv6 address in addition "
@@ -7526,11 +7547,11 @@ msgid ""
 "IPv6 addresses."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:216
+#: src/libnmc-setting/settings-docs.h.in:217
 msgid "The IPv6 connection method."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:217
+#: src/libnmc-setting/settings-docs.h.in:218
 msgid ""
 "Maximum transmission unit size, in bytes. If zero (the default), the MTU is "
 "set automatically from router advertisements or is left equal to the link-"
@@ -7538,7 +7559,7 @@ msgid ""
 "than the minimum IPv6 MTU of 1280, this value has no effect."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:219
+#: src/libnmc-setting/settings-docs.h.in:220
 msgid ""
 "A timeout for waiting Router Advertisements in seconds. If zero (the "
 "default), a globally configured default is used. If still unspecified, the "
@@ -7546,11 +7567,11 @@ msgid ""
 "(MAXINT32) for infinity."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:224
+#: src/libnmc-setting/settings-docs.h.in:225
 msgid "Array of IP routes."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:226
+#: src/libnmc-setting/settings-docs.h.in:227
 msgid ""
 "Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 "
 "tokenized interface identifiers. Useful with eui64 addr-gen-mode. When set, "
@@ -7559,14 +7580,14 @@ msgid ""
 "not to IPv6 link local addresses."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:227
+#: src/libnmc-setting/settings-docs.h.in:228
 msgid ""
 "How many additional levels of encapsulation are permitted to be prepended to "
 "packets. This property applies only to IPv6 tunnels. To disable this option, "
 "add 0x1 (ip6-ign-encap-limit) to ip-tunnel flags."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:228
+#: src/libnmc-setting/settings-docs.h.in:229
 msgid ""
 "Tunnel flags. Currently, the following values are supported: 0x1 (ip6-ign-"
 "encap-limit), 0x2 (ip6-use-orig-tclass), 0x4 (ip6-use-orig-flowlabel), 0x8 "
@@ -7574,106 +7595,116 @@ msgid ""
 "They are valid only for IPv6 tunnels."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:229
+#: src/libnmc-setting/settings-docs.h.in:230
 msgid ""
 "The flow label to assign to tunnel packets. This property applies only to "
 "IPv6 tunnels."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:230
+#: src/libnmc-setting/settings-docs.h.in:231
 msgid ""
 "The fwmark value to assign to tunnel packets. This property can be set to a "
 "non zero value only on VTI and VTI6 tunnels."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:231
+#: src/libnmc-setting/settings-docs.h.in:232
 msgid ""
 "The key used for tunnel input packets; the property is valid only for "
 "certain tunnel modes (GRE, IP6GRE). If empty, no key is used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:232
+#: src/libnmc-setting/settings-docs.h.in:233
 msgid ""
 "The local endpoint of the tunnel; the value can be empty, otherwise it must "
 "contain an IPv4 or IPv6 address."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:233
+#: src/libnmc-setting/settings-docs.h.in:234
 msgid ""
 "The tunneling mode. Valid values: ipip (1), gre (2), sit (3), isatap (4), "
 "vti (5), ip6ip6 (6), ipip6 (7), ip6gre (8), vti6 (9), gretap (10) and "
 "ip6gretap (11)"
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:234
+#: src/libnmc-setting/settings-docs.h.in:235
 msgid ""
 "If non-zero, only transmit packets of the specified size or smaller, "
 "breaking larger packets up into multiple fragments."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:235
+#: src/libnmc-setting/settings-docs.h.in:236
 msgid ""
 "The key used for tunnel output packets; the property is valid only for "
 "certain tunnel modes (GRE, IP6GRE). If empty, no key is used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:236
+#: src/libnmc-setting/settings-docs.h.in:237
 msgid ""
 "If given, specifies the parent interface name or parent connection UUID the "
 "new device will be bound to so that tunneled packets will only be routed via "
 "that interface."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:237
+#: src/libnmc-setting/settings-docs.h.in:238
 msgid "Whether to enable Path MTU Discovery on this tunnel."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:238
+#: src/libnmc-setting/settings-docs.h.in:239
 msgid ""
 "The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 "
 "address."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:239
+#: src/libnmc-setting/settings-docs.h.in:240
 msgid ""
 "The type of service (IPv4) or traffic class (IPv6) field to be set on "
 "tunneled packets."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:240
+#: src/libnmc-setting/settings-docs.h.in:241
 msgid ""
 "The TTL to assign to tunneled packets. 0 is a special value meaning that "
 "packets inherit the TTL value."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:241
+#: src/libnmc-setting/settings-docs.h.in:242
 msgid "Whether the transmitted traffic must be encrypted."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:242
+#: src/libnmc-setting/settings-docs.h.in:243
 msgid ""
 "The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement. "
 "Must be a string of 32 hexadecimal characters."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:243
+#: src/libnmc-setting/settings-docs.h.in:244
 msgid "Flags indicating how to handle the \"mka-cak\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:244
+#: src/libnmc-setting/settings-docs.h.in:245
 msgid ""
 "The pre-shared CKN (Connectivity-association Key Name) for MACsec Key "
 "Agreement. Must be a string of hexadecimal characters with a even length "
 "between 2 and 64."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:245
+#: src/libnmc-setting/settings-docs.h.in:246
 msgid ""
 "Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key "
 "Agreement) is obtained."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:246
+#: src/libnmc-setting/settings-docs.h.in:247
+msgid ""
+"Specifies the MACsec offload mode. \"off\" (0) disables MACsec offload. "
+"\"phy\" (1) and \"mac\" (2) request offload respectively to the PHY or to "
+"the MAC; if the selected mode is not available, the connection will fail. "
+"\"default\" (-1) uses the global default value specified in NetworkManager "
+"configuration; if no global default is defined, the built-in default is "
+"\"off\" (0)."
+msgstr ""
+
+#: src/libnmc-setting/settings-docs.h.in:248
 msgid ""
 "If given, specifies the parent interface name or parent connection UUID from "
 "which this MACSEC interface should be created.  If this property is not "
@@ -7681,29 +7712,29 @@ msgid ""
 "\"mac-address\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:247
+#: src/libnmc-setting/settings-docs.h.in:249
 msgid ""
 "The port component of the SCI (Secure Channel Identifier), between 1 and "
 "65534."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:248
+#: src/libnmc-setting/settings-docs.h.in:250
 msgid ""
 "Specifies whether the SCI (Secure Channel Identifier) is included in every "
 "packet."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:249
+#: src/libnmc-setting/settings-docs.h.in:251
 msgid "Specifies the validation mode for incoming frames."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:250
+#: src/libnmc-setting/settings-docs.h.in:252
 msgid ""
 "The macvlan mode, which specifies the communication mechanism between "
 "multiple macvlans on the same lower device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:251
+#: src/libnmc-setting/settings-docs.h.in:253
 msgid ""
 "If given, specifies the parent interface name or parent connection UUID from "
 "which this MAC-VLAN interface should be created.  If this property is not "
@@ -7711,15 +7742,15 @@ msgid ""
 "\"mac-address\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:252
+#: src/libnmc-setting/settings-docs.h.in:254
 msgid "Whether the interface should be put in promiscuous mode."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:253
+#: src/libnmc-setting/settings-docs.h.in:255
 msgid "Whether the interface should be a MACVTAP."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:254
+#: src/libnmc-setting/settings-docs.h.in:256
 msgid ""
 "A list of driver names to match. Each element is a shell wildcard pattern. "
 "See NMSettingMatch:interface-name for how special characters '|', '&', '!' "
@@ -7727,7 +7758,7 @@ msgid ""
 "pattern."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:255
+#: src/libnmc-setting/settings-docs.h.in:257
 msgid ""
 "A list of interface names to match. Each element is a shell wildcard "
 "pattern. An element can be prefixed with a pipe symbol (|) or an ampersand "
@@ -7744,7 +7775,7 @@ msgid ""
 "For example, \"&\\!a\" is an mandatory match for literally \"!a\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:256
+#: src/libnmc-setting/settings-docs.h.in:258
 msgid ""
 "A list of kernel command line arguments to match. This may be used to check "
 "whether a specific kernel command line option is set (or unset, if prefixed "
@@ -7757,7 +7788,7 @@ msgid ""
 "and '\\' are used for optional and mandatory matches and inverting the match."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:257
+#: src/libnmc-setting/settings-docs.h.in:259
 msgid ""
 "A list of paths to match against the ID_PATH udev property of devices. "
 "ID_PATH represents the topological persistent path of a device. It typically "
@@ -7772,52 +7803,52 @@ msgid ""
 "'\\' are used for optional and mandatory matches and inverting the pattern."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:258
+#: src/libnmc-setting/settings-docs.h.in:260
 msgid "Channel on which the mesh network to join is located."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:259
+#: src/libnmc-setting/settings-docs.h.in:261
 msgid ""
 "Anycast DHCP MAC address used when requesting an IP address via DHCP. The "
 "specific anycast address used determines which DHCP server class answers the "
 "request. This is currently only implemented by dhclient DHCP plugin."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:260
+#: src/libnmc-setting/settings-docs.h.in:262
 msgid "SSID of the mesh network to join."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:261
+#: src/libnmc-setting/settings-docs.h.in:263
 msgid "The data path type. One of \"system\", \"netdev\" or empty."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:262
+#: src/libnmc-setting/settings-docs.h.in:264
 msgid "The bridge failure mode. One of \"secure\", \"standalone\" or empty."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:263
+#: src/libnmc-setting/settings-docs.h.in:265
 msgid "Enable or disable multicast snooping."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:264
+#: src/libnmc-setting/settings-docs.h.in:266
 msgid "Enable or disable RSTP."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:265
+#: src/libnmc-setting/settings-docs.h.in:267
 msgid "Enable or disable STP."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:266
+#: src/libnmc-setting/settings-docs.h.in:268
 msgid "Open vSwitch DPDK device arguments."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:267
+#: src/libnmc-setting/settings-docs.h.in:269
 msgid ""
 "Open vSwitch DPDK number of rx queues. Defaults to zero which means to leave "
 "the parameter in OVS unspecified and effectively configures one queue."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:268
+#: src/libnmc-setting/settings-docs.h.in:270
 msgid ""
 "The rx queue size (number of rx descriptors) for DPDK ports. Must be zero or "
 "a power of 2 between 1 and 4096, and supported by the hardware. Defaults to "
@@ -7825,7 +7856,7 @@ msgid ""
 "configures 2048 descriptors."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:269
+#: src/libnmc-setting/settings-docs.h.in:271
 msgid ""
 "The tx queue size (number of tx descriptors) for DPDK ports. Must be zero or "
 "a power of 2 between 1 and 4096, and supported by the hardware. Defaults to "
@@ -7833,7 +7864,7 @@ msgid ""
 "configures 2048 descriptors."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:270
+#: src/libnmc-setting/settings-docs.h.in:272
 msgid ""
 "Open vSwitch openflow port number. Defaults to zero which means that port "
 "number will not be specified and it will be chosen randomly by ovs. OpenFlow "
@@ -7842,67 +7873,67 @@ msgid ""
 "to each other via their OpenFlow ports."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:271
+#: src/libnmc-setting/settings-docs.h.in:273
 msgid ""
 "The interface type. Either \"internal\", \"system\", \"patch\", \"dpdk\", or "
 "empty."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:272
+#: src/libnmc-setting/settings-docs.h.in:274
 msgid ""
 "Specifies the name of the interface for the other side of the patch. The "
 "patch on the other side must also set this interface as peer."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:273
+#: src/libnmc-setting/settings-docs.h.in:275
 msgid "The time port must be inactive in order to be considered down."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:274
+#: src/libnmc-setting/settings-docs.h.in:276
 msgid ""
 "Bonding mode. One of \"active-backup\", \"balance-slb\", or \"balance-tcp\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:275
+#: src/libnmc-setting/settings-docs.h.in:277
 msgid "The time port must be active before it starts forwarding traffic."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:276
+#: src/libnmc-setting/settings-docs.h.in:278
 msgid "LACP mode. One of \"active\", \"off\", or \"passive\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:277
+#: src/libnmc-setting/settings-docs.h.in:279
 msgid "The VLAN tag in the range 0-4095."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:278
+#: src/libnmc-setting/settings-docs.h.in:280
 msgid ""
 "A list of VLAN ranges that this port trunks. The property is valid only for "
 "ports with mode \"trunk\", \"native-tagged\", or \"native-untagged port\". "
 "If it is empty, the port trunks all VLANs."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:279
+#: src/libnmc-setting/settings-docs.h.in:281
 msgid ""
 "The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", "
 "\"trunk\", \"dot1q-tunnel\" or unset."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:280
+#: src/libnmc-setting/settings-docs.h.in:282
 msgid ""
 "If non-zero, instruct pppd to set the serial port to the specified "
 "baudrate.  This value should normally be left as 0 to automatically choose "
 "the speed."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:281
+#: src/libnmc-setting/settings-docs.h.in:283
 msgid ""
 "If TRUE, specify that pppd should set the serial port to use hardware flow "
 "control with RTS and CTS signals.  This value should normally be set to "
 "FALSE."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:282
+#: src/libnmc-setting/settings-docs.h.in:284
 msgid ""
 "If non-zero, instruct pppd to presume the connection to the peer has failed "
 "if the specified number of LCP echo-requests go unanswered by the peer.  The "
@@ -7910,7 +7941,7 @@ msgid ""
 "property is used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:283
+#: src/libnmc-setting/settings-docs.h.in:285
 msgid ""
 "If non-zero, instruct pppd to send an LCP echo-request frame to the peer "
 "every n seconds (where n is the specified value).  Note that some PPP peers "
@@ -7918,78 +7949,78 @@ msgid ""
 "autodetect this."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:284
+#: src/libnmc-setting/settings-docs.h.in:286
 msgid ""
 "If TRUE, stateful MPPE is used.  See pppd documentation for more information "
 "on stateful MPPE."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:285
+#: src/libnmc-setting/settings-docs.h.in:287
 msgid ""
 "If non-zero, instruct pppd to request that the peer send packets no larger "
 "than the specified size.  If non-zero, the MRU should be between 128 and "
 "16384."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:286
+#: src/libnmc-setting/settings-docs.h.in:288
 msgid ""
 "If non-zero, instruct pppd to send packets no larger than the specified size."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:287
+#: src/libnmc-setting/settings-docs.h.in:289
 msgid "If TRUE, Van Jacobsen TCP header compression will not be requested."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:288
+#: src/libnmc-setting/settings-docs.h.in:290
 msgid ""
 "If TRUE, do not require the other side (usually the PPP server) to "
 "authenticate itself to the client.  If FALSE, require authentication from "
 "the remote side.  In almost all cases, this should be TRUE."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:289
+#: src/libnmc-setting/settings-docs.h.in:291
 msgid "If TRUE, BSD compression will not be requested."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:290
+#: src/libnmc-setting/settings-docs.h.in:292
 msgid "If TRUE, \"deflate\" compression will not be requested."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:291
+#: src/libnmc-setting/settings-docs.h.in:293
 msgid "If TRUE, the CHAP authentication method will not be used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:292
+#: src/libnmc-setting/settings-docs.h.in:294
 msgid "If TRUE, the EAP authentication method will not be used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:293
+#: src/libnmc-setting/settings-docs.h.in:295
 msgid "If TRUE, the MSCHAP authentication method will not be used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:294
+#: src/libnmc-setting/settings-docs.h.in:296
 msgid "If TRUE, the MSCHAPv2 authentication method will not be used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:295
+#: src/libnmc-setting/settings-docs.h.in:297
 msgid "If TRUE, the PAP authentication method will not be used."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:296
+#: src/libnmc-setting/settings-docs.h.in:298
 msgid ""
 "If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for the "
 "PPP session.  If either 64-bit or 128-bit MPPE is not available the session "
 "will fail.  Note that MPPE is not used on mobile broadband connections."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:297
+#: src/libnmc-setting/settings-docs.h.in:299
 msgid ""
 "If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be required "
 "for the PPP session, and the \"require-mppe\" property must also be set to "
 "TRUE.  If 128-bit MPPE is not available the session will fail."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:298
+#: src/libnmc-setting/settings-docs.h.in:300
 msgid ""
 "If given, specifies the parent interface name on which this PPPoE connection "
 "should be created.  If this property is not specified, the connection is "
@@ -7997,11 +8028,11 @@ msgid ""
 "NMSettingConnection."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:299
+#: src/libnmc-setting/settings-docs.h.in:301
 msgid "Password used to authenticate with the PPPoE service."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:301
+#: src/libnmc-setting/settings-docs.h.in:303
 msgid ""
 "If specified, instruct PPPoE to only initiate sessions with access "
 "concentrators that provide the specified service.  For most providers, this "
@@ -8009,19 +8040,19 @@ msgid ""
 "concentrators or a specific service is known to be required."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:302
+#: src/libnmc-setting/settings-docs.h.in:304
 msgid "Username used to authenticate with the PPPoE service."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:303
+#: src/libnmc-setting/settings-docs.h.in:305
 msgid "Whether the proxy configuration is for browser only."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:304
+#: src/libnmc-setting/settings-docs.h.in:306
 msgid "Method for proxy configuration, Default is \"none\" (0)"
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:305
+#: src/libnmc-setting/settings-docs.h.in:307
 msgid ""
 "The PAC script. In the profile this must be an UTF-8 encoded javascript code "
 "that defines a FindProxyForURL() function. When setting the property in "
@@ -8030,36 +8061,36 @@ msgid ""
 "supported to explicitly differentiate between the two."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:306
+#: src/libnmc-setting/settings-docs.h.in:308
 msgid "PAC URL for obtaining PAC file."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:307
+#: src/libnmc-setting/settings-docs.h.in:309
 msgid ""
 "Speed to use for communication over the serial port.  Note that this value "
 "usually has no effect for mobile broadband modems as they generally ignore "
 "speed settings and use the highest available speed."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:308
+#: src/libnmc-setting/settings-docs.h.in:310
 msgid "Byte-width of the serial communication. The 8 in \"8n1\" for example."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:309
+#: src/libnmc-setting/settings-docs.h.in:311
 msgid "Parity setting of the serial port."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:310
+#: src/libnmc-setting/settings-docs.h.in:312
 msgid "Time to delay between each byte sent to the modem, in microseconds."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:311
+#: src/libnmc-setting/settings-docs.h.in:313
 msgid ""
 "Number of stop bits for communication on the serial port.  Either 1 or 2. "
 "The 1 in \"8n1\" for example."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:312
+#: src/libnmc-setting/settings-docs.h.in:314
 msgid ""
 "Whether to autoprobe virtual functions by a compatible driver. If set to "
 "\"true\" (1), the kernel will try to bind VFs to a compatible driver and if "
@@ -8070,7 +8101,33 @@ msgid ""
 "\"true\" (1)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:313
+#: src/libnmc-setting/settings-docs.h.in:315
+msgid ""
+"Select the eswitch encapsulation support. Currently it's only supported for "
+"PCI PF devices, and only if the eswitch device is managed from the same PCI "
+"address than the PF. If set to \"preserve\" (-1) (default) the eswitch encap-"
+"mode won't be modified by NetworkManager."
+msgstr ""
+
+#: src/libnmc-setting/settings-docs.h.in:316
+msgid ""
+"Select the eswitch inline-mode of the device. Some HWs need the VF driver to "
+"put part of the packet headers on the TX descriptor so the e-switch can do "
+"proper matching and steering. Currently it's only supported for PCI PF "
+"devices, and only if the eswitch device is managed from the same PCI address "
+"than the PF. If set to \"preserve\" (-1) (default) the eswitch inline-mode "
+"won't be modified by NetworkManager."
+msgstr ""
+
+#: src/libnmc-setting/settings-docs.h.in:317
+msgid ""
+"Select the eswitch mode of the device. Currently it's only supported for PCI "
+"PF devices, and only if the eswitch device is managed from the same PCI "
+"address than the PF. If set to \"preserve\" (-1) (default) the eswitch mode "
+"won't be modified by NetworkManager."
+msgstr ""
+
+#: src/libnmc-setting/settings-docs.h.in:318
 msgid ""
 "The total number of virtual functions to create. Note that when the sriov "
 "setting is present NetworkManager enforces the number of virtual functions "
@@ -8079,7 +8136,7 @@ msgid ""
 "setting to the connection."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:314
+#: src/libnmc-setting/settings-docs.h.in:319
 msgid ""
 "Array of virtual function descriptors. Each VF descriptor is a dictionary "
 "mapping attribute names to GVariant values. The 'index' entry is mandatory "
@@ -8093,7 +8150,7 @@ msgid ""
 "default) or 'ad' for 802.1ad."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:315
+#: src/libnmc-setting/settings-docs.h.in:320
 msgid ""
 "Array of TC queueing disciplines. When the \"tc\" setting is present, qdiscs "
 "from this property are applied upon activation. If the property is empty, "
@@ -8103,7 +8160,7 @@ msgid ""
 "present on the interface."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:316
+#: src/libnmc-setting/settings-docs.h.in:321
 msgid ""
 "Array of TC traffic filters. When the \"tc\" setting is present, filters "
 "from this property are applied upon activation. If the property is empty, "
@@ -8111,7 +8168,7 @@ msgid ""
 "present, NetworkManager doesn't touch the filters present on the interface."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:317
+#: src/libnmc-setting/settings-docs.h.in:322
 msgid ""
 "The JSON configuration for the team network interface.  The property should "
 "contain raw JSON configuration data suitable for teamd, because the value is "
@@ -8119,8 +8176,8 @@ msgid ""
 "used.  See man teamd.conf for the format details."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:318
-#: src/libnmc-setting/settings-docs.h.in:336
+#: src/libnmc-setting/settings-docs.h.in:323
+#: src/libnmc-setting/settings-docs.h.in:341
 msgid ""
 "Link watchers configuration for the connection: each link watcher is defined "
 "by a dictionary, whose keys depend upon the selected link watcher. Available "
@@ -8132,65 +8189,65 @@ msgid ""
 "for more details."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:319
+#: src/libnmc-setting/settings-docs.h.in:324
 msgid "Corresponds to the teamd mcast_rejoin.count."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:320
+#: src/libnmc-setting/settings-docs.h.in:325
 msgid "Corresponds to the teamd mcast_rejoin.interval."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:321
+#: src/libnmc-setting/settings-docs.h.in:326
 msgid "Corresponds to the teamd notify_peers.count."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:322
+#: src/libnmc-setting/settings-docs.h.in:327
 msgid "Corresponds to the teamd notify_peers.interval."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:323
+#: src/libnmc-setting/settings-docs.h.in:328
 msgid ""
 "Corresponds to the teamd runner.name. Permitted values are: \"roundrobin\", "
 "\"broadcast\", \"activebackup\", \"loadbalance\", \"lacp\", \"random\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:324
+#: src/libnmc-setting/settings-docs.h.in:329
 msgid "Corresponds to the teamd runner.active."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:325
+#: src/libnmc-setting/settings-docs.h.in:330
 msgid "Corresponds to the teamd runner.agg_select_policy."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:326
+#: src/libnmc-setting/settings-docs.h.in:331
 msgid "Corresponds to the teamd runner.fast_rate."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:327
+#: src/libnmc-setting/settings-docs.h.in:332
 msgid "Corresponds to the teamd runner.hwaddr_policy."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:328
+#: src/libnmc-setting/settings-docs.h.in:333
 msgid "Corresponds to the teamd runner.min_ports."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:329
+#: src/libnmc-setting/settings-docs.h.in:334
 msgid "Corresponds to the teamd runner.sys_prio."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:330
+#: src/libnmc-setting/settings-docs.h.in:335
 msgid "Corresponds to the teamd runner.tx_balancer.name."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:331
+#: src/libnmc-setting/settings-docs.h.in:336
 msgid "Corresponds to the teamd runner.tx_balancer.interval."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:332
+#: src/libnmc-setting/settings-docs.h.in:337
 msgid "Corresponds to the teamd runner.tx_hash."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:333
+#: src/libnmc-setting/settings-docs.h.in:338
 msgid ""
 "The JSON configuration for the team port. The property should contain raw "
 "JSON configuration data suitable for teamd, because the value is passed "
@@ -8198,67 +8255,67 @@ msgid ""
 "man teamd.conf for the format details."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:334
+#: src/libnmc-setting/settings-docs.h.in:339
 msgid "Corresponds to the teamd ports.PORTIFNAME.lacp_key."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:335
+#: src/libnmc-setting/settings-docs.h.in:340
 msgid "Corresponds to the teamd ports.PORTIFNAME.lacp_prio."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:337
+#: src/libnmc-setting/settings-docs.h.in:342
 msgid "Corresponds to the teamd ports.PORTIFNAME.prio."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:338
+#: src/libnmc-setting/settings-docs.h.in:343
 msgid ""
 "Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the "
 "parameter is skipped from the json config."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:339
+#: src/libnmc-setting/settings-docs.h.in:344
 msgid "Corresponds to the teamd ports.PORTIFNAME.sticky."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:340
+#: src/libnmc-setting/settings-docs.h.in:345
 msgid ""
 "The group ID which will own the device. If set to NULL everyone will be able "
 "to use the device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:341
+#: src/libnmc-setting/settings-docs.h.in:346
 msgid ""
 "The operating mode of the virtual device. Allowed values are \"tun\" (1) to "
 "create a layer 3 device and \"tap\" (2) to create an Ethernet-like layer 2 "
 "one."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:342
+#: src/libnmc-setting/settings-docs.h.in:347
 msgid ""
 "If the property is set to TRUE, the interface will support multiple file "
 "descriptors (queues) to parallelize packet sending or receiving. Otherwise, "
 "the interface will only support a single queue."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:343
+#: src/libnmc-setting/settings-docs.h.in:348
 msgid ""
 "The user ID which will own the device. If set to NULL everyone will be able "
 "to use the device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:344
+#: src/libnmc-setting/settings-docs.h.in:349
 msgid ""
 "If TRUE the interface will prepend a 4 byte header describing the physical "
 "interface to the packets."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:345
+#: src/libnmc-setting/settings-docs.h.in:350
 msgid ""
 "If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network "
 "header."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:346
+#: src/libnmc-setting/settings-docs.h.in:351
 msgid ""
 "A dictionary of key/value pairs with user data. This data is ignored by "
 "NetworkManager and can be used at the users discretion. The keys only "
@@ -8266,14 +8323,14 @@ msgid ""
 "up to a certain length."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:347
+#: src/libnmc-setting/settings-docs.h.in:352
 msgid ""
 "For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p "
 "priorities.  The mapping is given in the format \"from:to\" where both "
 "\"from\" and \"to\" are unsigned integers, ie \"7:3\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:348
+#: src/libnmc-setting/settings-docs.h.in:353
 msgid ""
 "One or more flags which control the behavior and features of the VLAN "
 "interface.  Flags include \"reorder-headers\" (0x1) (reordering of output "
@@ -8285,20 +8342,20 @@ msgid ""
 "continues to be 0 and a missing property on D-Bus is still considered as 0."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:349
+#: src/libnmc-setting/settings-docs.h.in:354
 msgid ""
 "The VLAN identifier that the interface created by this connection should be "
 "assigned. The valid range is from 0 to 4094, without the reserved id 4095."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:350
+#: src/libnmc-setting/settings-docs.h.in:355
 msgid ""
 "For incoming packets, a list of mappings from 802.1p priorities to Linux SKB "
 "priorities.  The mapping is given in the format \"from:to\" where both "
 "\"from\" and \"to\" are unsigned integers, ie \"7:3\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:351
+#: src/libnmc-setting/settings-docs.h.in:356
 msgid ""
 "If given, specifies the parent interface name or parent connection UUID from "
 "which this VLAN interface should be created.  If this property is not "
@@ -8306,38 +8363,38 @@ msgid ""
 "\"mac-address\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:352
+#: src/libnmc-setting/settings-docs.h.in:357
 msgid ""
 "Specifies the VLAN protocol to use for encapsulation. Supported values are: "
 "'802.1Q', '802.1ad'. If not specified the default value is '802.1Q'."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:353
+#: src/libnmc-setting/settings-docs.h.in:358
 msgid ""
 "Dictionary of key/value pairs of VPN plugin specific data.  Both keys and "
 "values must be strings."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:354
+#: src/libnmc-setting/settings-docs.h.in:359
 msgid ""
 "If the VPN service supports persistence, and this property is TRUE, the VPN "
 "will attempt to stay connected across link changes and outages, until "
 "explicitly disconnected."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:355
+#: src/libnmc-setting/settings-docs.h.in:360
 msgid ""
 "Dictionary of key/value pairs of VPN plugin specific secrets like passwords "
 "or private keys.  Both keys and values must be strings."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:356
+#: src/libnmc-setting/settings-docs.h.in:361
 msgid ""
 "D-Bus service name of the VPN plugin that this setting uses to connect to "
 "its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:357
+#: src/libnmc-setting/settings-docs.h.in:362
 msgid ""
 "Timeout for the VPN service to establish the connection. Some services may "
 "take quite a long time to connect. Value of 0 means a default timeout, which "
@@ -8345,7 +8402,7 @@ msgid ""
 "Values greater than zero mean timeout in seconds."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:358
+#: src/libnmc-setting/settings-docs.h.in:363
 msgid ""
 "If the VPN connection requires a user name for authentication, that name "
 "should be provided here.  If the connection is available to more than one "
@@ -8355,96 +8412,96 @@ msgid ""
 "connection."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:359
+#: src/libnmc-setting/settings-docs.h.in:364
 msgid "The routing table for this VRF."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:360
+#: src/libnmc-setting/settings-docs.h.in:365
 msgid "Specifies the lifetime in seconds of FDB entries learnt by the kernel."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:361
+#: src/libnmc-setting/settings-docs.h.in:366
 msgid ""
 "Specifies the UDP destination port to communicate to the remote VXLAN tunnel "
 "endpoint."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:362
+#: src/libnmc-setting/settings-docs.h.in:367
 msgid ""
 "Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:363
+#: src/libnmc-setting/settings-docs.h.in:368
 msgid "Specifies whether netlink LL ADDR miss notifications are generated."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:364
+#: src/libnmc-setting/settings-docs.h.in:369
 msgid "Specifies whether netlink IP ADDR miss notifications are generated."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:365
+#: src/libnmc-setting/settings-docs.h.in:370
 msgid ""
 "Specifies whether unknown source link layer addresses and IP addresses are "
 "entered into the VXLAN device forwarding database."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:366
+#: src/libnmc-setting/settings-docs.h.in:371
 msgid ""
 "Specifies the maximum number of FDB entries. A value of zero means that the "
 "kernel will store unlimited entries."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:367
+#: src/libnmc-setting/settings-docs.h.in:372
 msgid "If given, specifies the source IP address to use in outgoing packets."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:368
+#: src/libnmc-setting/settings-docs.h.in:373
 msgid ""
 "If given, specifies the parent interface name or parent connection UUID."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:369
+#: src/libnmc-setting/settings-docs.h.in:374
 msgid "Specifies whether ARP proxy is turned on."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:370
+#: src/libnmc-setting/settings-docs.h.in:375
 msgid ""
 "Specifies the unicast destination IP address to use in outgoing packets when "
 "the destination link layer address is not known in the VXLAN device "
 "forwarding database, or the multicast IP address to join."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:371
+#: src/libnmc-setting/settings-docs.h.in:376
 msgid "Specifies whether route short circuit is turned on."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:372
+#: src/libnmc-setting/settings-docs.h.in:377
 msgid ""
 "Specifies the maximum UDP source port to communicate to the remote VXLAN "
 "tunnel endpoint."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:373
+#: src/libnmc-setting/settings-docs.h.in:378
 msgid ""
 "Specifies the minimum UDP source port to communicate to the remote VXLAN "
 "tunnel endpoint."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:374
+#: src/libnmc-setting/settings-docs.h.in:379
 msgid "Specifies the TOS value to use in outgoing packets."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:375
+#: src/libnmc-setting/settings-docs.h.in:380
 msgid "Specifies the time-to-live value to use in outgoing packets."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:376
+#: src/libnmc-setting/settings-docs.h.in:381
 msgid ""
 "The P2P device that should be connected to. Currently, this is the only way "
 "to create or join a group."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:377
+#: src/libnmc-setting/settings-docs.h.in:382
 msgid ""
 "The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display "
 "requires a protocol specific information element to be set in certain Wi-Fi "
@@ -8453,27 +8510,27 @@ msgid ""
 "client."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:378
+#: src/libnmc-setting/settings-docs.h.in:383
 msgid ""
 "Flags indicating which mode of WPS is to be used. There's little point in "
 "changing the default setting as NetworkManager will automatically determine "
 "the best method to use."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:379
+#: src/libnmc-setting/settings-docs.h.in:384
 msgid ""
 "If specified, this connection will only apply to the WiMAX device whose MAC "
 "address matches. This property does not change the MAC address of the device "
 "(known as MAC spoofing)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:380
+#: src/libnmc-setting/settings-docs.h.in:385
 msgid ""
 "Network Service Provider (NSP) name of the WiMAX network this connection "
 "should use."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:381
+#: src/libnmc-setting/settings-docs.h.in:386
 msgid ""
 "When TRUE, setup the interface to accept packets for all MAC addresses. This "
 "is enabling the kernel interface flag IFF_PROMISC. When FALSE, the interface "
@@ -8481,7 +8538,7 @@ msgid ""
 "broadcast."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:382
+#: src/libnmc-setting/settings-docs.h.in:387
 msgid ""
 "When TRUE, enforce auto-negotiation of speed and duplex mode. If \"speed\" "
 "and \"duplex\" properties are both specified, only that single mode will be "
@@ -8492,7 +8549,7 @@ msgid ""
 "will be skipped."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:383
+#: src/libnmc-setting/settings-docs.h.in:388
 msgid ""
 "If specified, request that the device use this MAC address instead. This is "
 "known as MAC cloning or spoofing. Beside explicitly specifying a MAC "
@@ -8509,7 +8566,7 @@ msgid ""
 "deprecated \"cloned-mac-address\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:384
+#: src/libnmc-setting/settings-docs.h.in:389
 msgid ""
 "When a value is set, either \"half\" or \"full\", configures the device to "
 "use the specified duplex mode. If \"auto-negotiate\" is \"yes\" the "
@@ -8524,8 +8581,8 @@ msgid ""
 "your device supports it."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:385
-#: src/libnmc-setting/settings-docs.h.in:409
+#: src/libnmc-setting/settings-docs.h.in:390
+#: src/libnmc-setting/settings-docs.h.in:414
 msgid ""
 "With \"cloned-mac-address\" setting \"random\" or \"stable\", by default all "
 "bits of the MAC address are scrambled and a locally-administered, unicast "
@@ -8552,29 +8609,29 @@ msgid ""
 "administered."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:386
+#: src/libnmc-setting/settings-docs.h.in:391
 msgid ""
 "If specified, this connection will only apply to the Ethernet device whose "
 "permanent MAC address matches. This property does not change the MAC address "
 "of the device (i.e. MAC spoofing)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:387
+#: src/libnmc-setting/settings-docs.h.in:392
 msgid ""
 "If specified, this connection will never apply to the Ethernet device whose "
 "permanent MAC address matches an address in the list.  Each MAC address is "
 "in the standard hex-digits-and-colons notation (00:11:22:33:44:55)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:388
-#: src/libnmc-setting/settings-docs.h.in:415
-#: src/libnmc-setting/settings-docs.h.in:461
+#: src/libnmc-setting/settings-docs.h.in:393
+#: src/libnmc-setting/settings-docs.h.in:420
+#: src/libnmc-setting/settings-docs.h.in:466
 msgid ""
 "If non-zero, only transmit packets of the specified size or smaller, "
 "breaking larger packets up into multiple Ethernet frames."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:389
+#: src/libnmc-setting/settings-docs.h.in:394
 msgid ""
 "Specific port type to use if the device supports multiple attachment "
 "methods.  One of \"tp\" (Twisted Pair), \"aui\" (Attachment Unit Interface), "
@@ -8582,13 +8639,13 @@ msgid ""
 "device supports only one port type, this setting is ignored."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:390
+#: src/libnmc-setting/settings-docs.h.in:395
 msgid ""
 "s390 network device type; one of \"qeth\", \"lcs\", or \"ctc\", representing "
 "the different types of virtual network devices available on s390 systems."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:391
+#: src/libnmc-setting/settings-docs.h.in:396
 msgid ""
 "Dictionary of key/value pairs of s390-specific device options.  Both keys "
 "and values must be strings.  Allowed keys include \"portno\", \"layer2\", "
@@ -8598,7 +8655,7 @@ msgid ""
 "which parses this information and applies it to the interface."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:392
+#: src/libnmc-setting/settings-docs.h.in:397
 msgid ""
 "Identifies specific subchannels that this network device uses for "
 "communication with z/VM or s390 host.  Like the \"mac-address\" property for "
@@ -8608,7 +8665,7 @@ msgid ""
 "hexadecimal characters and the period (.) character."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:393
+#: src/libnmc-setting/settings-docs.h.in:398
 msgid ""
 "When a value greater than 0 is set, configures the device to use the "
 "specified speed. If \"auto-negotiate\" is \"yes\" the specified speed will "
@@ -8623,7 +8680,7 @@ msgid ""
 "sure your device supports it."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:394
+#: src/libnmc-setting/settings-docs.h.in:399
 msgid ""
 "The NMSettingWiredWakeOnLan options to enable. Not all devices support all "
 "options. May be any combination of \"phy\" (0x2), \"unicast\" (0x4), "
@@ -8632,14 +8689,14 @@ msgid ""
 "\"ignore\" (0x8000) (to disable management of Wake-on-LAN in NetworkManager)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:395
+#: src/libnmc-setting/settings-docs.h.in:400
 msgid ""
 "If specified, the password used with magic-packet-based Wake-on-LAN, "
 "represented as an Ethernet MAC address.  If NULL, no password will be "
 "required."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:396
+#: src/libnmc-setting/settings-docs.h.in:401
 msgid ""
 "The use of fwmark is optional and is by default off. Setting it to 0 "
 "disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. Note "
@@ -8647,7 +8704,7 @@ msgid ""
 "implies to automatically choose a fwmark."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:397
+#: src/libnmc-setting/settings-docs.h.in:402
 msgid ""
 "Whether to enable special handling of the IPv4 default route. If enabled, "
 "the IPv4 default route from wireguard.peer-routes will be placed to a "
@@ -8665,17 +8722,17 @@ msgid ""
 "want to configure your own routing and rules."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:398
+#: src/libnmc-setting/settings-docs.h.in:403
 msgid "Like ip4-auto-default-route, but for the IPv6 default route."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:399
+#: src/libnmc-setting/settings-docs.h.in:404
 msgid ""
 "The listen-port. If listen-port is not specified, the port will be chosen "
 "randomly when the interface comes up."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:400
+#: src/libnmc-setting/settings-docs.h.in:405
 msgid ""
 "If non-zero, only transmit packets of the specified size or smaller, "
 "breaking larger packets up into multiple fragments. If zero a default MTU is "
@@ -8683,7 +8740,7 @@ msgid ""
 "account the current routes at the time of activation."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:401
+#: src/libnmc-setting/settings-docs.h.in:406
 msgid ""
 "Whether to automatically add routes for the AllowedIPs ranges of the peers. "
 "If TRUE (the default), NetworkManager will automatically add routes in the "
@@ -8696,15 +8753,15 @@ msgid ""
 "be added automatically."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:402
+#: src/libnmc-setting/settings-docs.h.in:407
 msgid "The 256 bit private-key in base64 encoding."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:403
+#: src/libnmc-setting/settings-docs.h.in:408
 msgid "Flags indicating how to handle the \"private-key\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:404
+#: src/libnmc-setting/settings-docs.h.in:409
 msgid ""
 "Configures AP isolation, which prevents communication between wireless "
 "devices connected to this AP. This property can be set to a value different "
@@ -8718,7 +8775,7 @@ msgid ""
 "unspecified it is assumed to be \"false\" (0)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:405
+#: src/libnmc-setting/settings-docs.h.in:410
 msgid ""
 "802.11 frequency band of the network.  One of \"a\" for 5GHz 802.11a or "
 "\"bg\" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network "
@@ -8728,7 +8785,7 @@ msgid ""
 "and may not work with all drivers."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:406
+#: src/libnmc-setting/settings-docs.h.in:411
 msgid ""
 "If specified, directs the device to only associate with the given access "
 "point.  This capability is highly driver dependent and not supported by all "
@@ -8738,7 +8795,7 @@ msgid ""
 "scanning. That can be useful, if there is only one access point for the SSID."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:407
+#: src/libnmc-setting/settings-docs.h.in:412
 msgid ""
 "Wireless channel to use for the Wi-Fi connection.  The device will only join "
 "(or create for Ad-Hoc networks) a Wi-Fi network on the specified channel.  "
@@ -8746,7 +8803,7 @@ msgid ""
 "the \"band\" property to be set."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:408
+#: src/libnmc-setting/settings-docs.h.in:413
 msgid ""
 "If specified, request that the device use this MAC address instead. This is "
 "known as MAC cloning or spoofing. Beside explicitly specifying a MAC "
@@ -8764,7 +8821,7 @@ msgid ""
 "mac-address\" or the deprecated \"cloned-mac-address\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:410
+#: src/libnmc-setting/settings-docs.h.in:415
 msgid ""
 "If TRUE, indicates that the network is a non-broadcasting network that hides "
 "its SSID. This works both in infrastructure and AP mode. In infrastructure "
@@ -8777,21 +8834,21 @@ msgid ""
 "mode), as the explicit probe-scans are distinctly recognizable on the air."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:411
+#: src/libnmc-setting/settings-docs.h.in:416
 msgid ""
 "If specified, this connection will only apply to the Wi-Fi device whose "
 "permanent MAC address matches. This property does not change the MAC address "
 "of the device (i.e. MAC spoofing)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:412
+#: src/libnmc-setting/settings-docs.h.in:417
 msgid ""
 "A list of permanent MAC addresses of Wi-Fi devices to which this connection "
 "should never apply.  Each MAC address should be given in the standard hex-"
 "digits-and-colons notation (eg \"00:11:22:33:44:55\")."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:413
+#: src/libnmc-setting/settings-docs.h.in:418
 msgid ""
 "One of \"default\" (0) (never randomize unless the user has set a global "
 "default to randomize and the supplicant supports randomization),  "
@@ -8799,13 +8856,13 @@ msgid ""
 "randomize the MAC address)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:414
+#: src/libnmc-setting/settings-docs.h.in:419
 msgid ""
 "Wi-Fi network mode; one of \"infrastructure\", \"mesh\", \"adhoc\" or "
 "\"ap\".  If blank, infrastructure is assumed."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:416
+#: src/libnmc-setting/settings-docs.h.in:421
 msgid ""
 "One of \"disable\" (2) (disable Wi-Fi power saving), \"enable\" (3) (enable "
 "Wi-Fi power saving), \"ignore\" (1) (don't touch currently configure "
@@ -8813,12 +8870,12 @@ msgid ""
 "values are reserved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:417
-#: src/libnmc-setting/settings-docs.h.in:420
+#: src/libnmc-setting/settings-docs.h.in:422
+#: src/libnmc-setting/settings-docs.h.in:425
 msgid "This property is not implemented and has no effect."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:418
+#: src/libnmc-setting/settings-docs.h.in:423
 msgid ""
 "A list of BSSIDs (each BSSID formatted as a MAC address like "
 "\"00:11:22:33:44:55\") that have been detected as part of the Wi-Fi "
@@ -8830,11 +8887,11 @@ msgid ""
 "in \"/var/lib/NetworkManager/seen-bssids\" file."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:419
+#: src/libnmc-setting/settings-docs.h.in:424
 msgid "SSID of the Wi-Fi network. Must be specified."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:421
+#: src/libnmc-setting/settings-docs.h.in:426
 msgid ""
 "The NMSettingWirelessWakeOnWLan options to enable. Not all devices support "
 "all options. May be any combination of \"any\" (0x2), \"disconnect\" (0x4), "
@@ -8845,7 +8902,7 @@ msgid ""
 "NetworkManager)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:422
+#: src/libnmc-setting/settings-docs.h.in:427
 msgid ""
 "When WEP is used (ie, key-mgmt = \"none\" or \"ieee8021x\") indicate the "
 "802.11 authentication algorithm required by the AP here.  One of \"open\" "
@@ -8854,7 +8911,7 @@ msgid ""
 "the \"leap-username\" and \"leap-password\" properties must be specified."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:423
+#: src/libnmc-setting/settings-docs.h.in:428
 msgid ""
 "Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the "
 "connection.  One of \"default\" (0) (use global default value), "
@@ -8864,7 +8921,7 @@ msgid ""
 "default is set, FILS will be optionally enabled."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:424
+#: src/libnmc-setting/settings-docs.h.in:429
 msgid ""
 "A list of group/broadcast encryption algorithms which prevents connections "
 "to Wi-Fi networks that do not utilize one of the algorithms in the list.  "
@@ -8872,7 +8929,7 @@ msgid ""
 "be one of \"wep40\", \"wep104\", \"tkip\", or \"ccmp\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:425
+#: src/libnmc-setting/settings-docs.h.in:430
 msgid ""
 "Key management used for the connection. One of \"none\" (WEP or no password "
 "protection), \"ieee8021x\" (Dynamic WEP), \"owe\" (Opportunistic Wireless "
@@ -8882,23 +8939,23 @@ msgid ""
 "uses security."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:426
+#: src/libnmc-setting/settings-docs.h.in:431
 msgid ""
 "The login password for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" "
 "and auth-alg = \"leap\")."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:427
+#: src/libnmc-setting/settings-docs.h.in:432
 msgid "Flags indicating how to handle the \"leap-password\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:428
+#: src/libnmc-setting/settings-docs.h.in:433
 msgid ""
 "The login username for legacy LEAP connections (ie, key-mgmt = \"ieee8021x\" "
 "and auth-alg = \"leap\")."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:429
+#: src/libnmc-setting/settings-docs.h.in:434
 msgid ""
 "A list of pairwise encryption algorithms which prevents connections to Wi-Fi "
 "networks that do not utilize one of the algorithms in the list. For maximum "
@@ -8906,7 +8963,7 @@ msgid ""
 "\"tkip\" or \"ccmp\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:430
+#: src/libnmc-setting/settings-docs.h.in:435
 msgid ""
 "Indicates whether Protected Management Frames (802.11w) must be enabled for "
 "the connection.  One of \"default\" (0) (use global default value), "
@@ -8916,14 +8973,14 @@ msgid ""
 "default is set, PMF will be optionally enabled."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:431
+#: src/libnmc-setting/settings-docs.h.in:436
 msgid ""
 "List of strings specifying the allowed WPA protocol versions to use. Each "
 "element may be one \"wpa\" (allow WPA) or \"rsn\" (allow WPA2/RSN).  If not "
 "specified, both WPA and RSN connections are allowed."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:432
+#: src/libnmc-setting/settings-docs.h.in:437
 msgid ""
 "Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII "
 "passphrase of 8 to 63 characters that is (as specified in the 802.11i "
@@ -8932,17 +8989,17 @@ msgid ""
 "length for SAE authentication."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:433
+#: src/libnmc-setting/settings-docs.h.in:438
 msgid "Flags indicating how to handle the \"psk\" property."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:434
+#: src/libnmc-setting/settings-docs.h.in:439
 msgid ""
 "Flags indicating how to handle the \"wep-key0\", \"wep-key1\", \"wep-key2\", "
 "and \"wep-key3\" properties."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:435
+#: src/libnmc-setting/settings-docs.h.in:440
 msgid ""
 "Controls the interpretation of WEP keys.  Allowed values are \"key\" (1), in "
 "which case the key is either a 10- or 26-character hexadecimal string, or a "
@@ -8951,31 +9008,31 @@ msgid ""
 "method to derive the actual WEP key."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:436
+#: src/libnmc-setting/settings-docs.h.in:441
 msgid ""
 "Index 0 WEP key.  This is the WEP key used in most networks.  See the \"wep-"
 "key-type\" property for a description of how this key is interpreted."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:437
+#: src/libnmc-setting/settings-docs.h.in:442
 msgid ""
 "Index 1 WEP key.  This WEP index is not used by most networks.  See the "
 "\"wep-key-type\" property for a description of how this key is interpreted."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:438
+#: src/libnmc-setting/settings-docs.h.in:443
 msgid ""
 "Index 2 WEP key.  This WEP index is not used by most networks.  See the "
 "\"wep-key-type\" property for a description of how this key is interpreted."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:439
+#: src/libnmc-setting/settings-docs.h.in:444
 msgid ""
 "Index 3 WEP key.  This WEP index is not used by most networks.  See the "
 "\"wep-key-type\" property for a description of how this key is interpreted."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:440
+#: src/libnmc-setting/settings-docs.h.in:445
 msgid ""
 "When static WEP is used (ie, key-mgmt = \"none\") and a non-default WEP key "
 "index is used by the AP, put that WEP key index here.  Valid values are 0 "
@@ -8983,7 +9040,7 @@ msgid ""
 "Linksys WRT54G) number the keys 1 - 4."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:441
+#: src/libnmc-setting/settings-docs.h.in:446
 msgid ""
 "Flags indicating which mode of WPS is to be used if any. There's little "
 "point in changing the default setting as NetworkManager will automatically "
@@ -8992,33 +9049,33 @@ msgid ""
 "of 1."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:442
+#: src/libnmc-setting/settings-docs.h.in:447
 msgid ""
 "IEEE 802.15.4 channel. A positive integer or -1, meaning \"do not set, use "
 "whatever the device is already set to\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:443
+#: src/libnmc-setting/settings-docs.h.in:448
 msgid ""
 "If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) "
 "MAC layer device whose permanent MAC address matches."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:444
+#: src/libnmc-setting/settings-docs.h.in:449
 msgid ""
 "IEEE 802.15.4 channel page. A positive integer or -1, meaning \"do not set, "
 "use whatever the device is already set to\"."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:445
+#: src/libnmc-setting/settings-docs.h.in:450
 msgid "IEEE 802.15.4 Personal Area Network (PAN) identifier."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:446
+#: src/libnmc-setting/settings-docs.h.in:451
 msgid "Short IEEE 802.15.4 address to be used within a restricted environment."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:447
+#: src/libnmc-setting/settings-docs.h.in:452
 msgid ""
 "The port priority for bond active port re-selection during failover. A "
 "higher number means a higher priority in selection. The primary port has the "
@@ -9026,13 +9083,13 @@ msgid ""
 "tlb and balance-alb modes."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:448
+#: src/libnmc-setting/settings-docs.h.in:453
 msgid ""
 "The queue ID of this bond port. The maximum value of queue ID is the number "
 "of TX queues currently active in device."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:449
+#: src/libnmc-setting/settings-docs.h.in:454
 msgid ""
 "Whether the system hostname can be determined from DHCP on this connection. "
 "When set to \"default\" (-1), the value from global configuration is used. "
@@ -9040,7 +9097,7 @@ msgid ""
 "NetworkManager assumes the value to be \"true\" (1)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:450
+#: src/libnmc-setting/settings-docs.h.in:455
 msgid ""
 "Whether the system hostname can be determined from reverse DNS lookup of "
 "addresses on this device. When set to \"default\" (-1), the value from "
@@ -9048,7 +9105,7 @@ msgid ""
 "global configuration, NetworkManager assumes the value to be \"true\" (1)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:451
+#: src/libnmc-setting/settings-docs.h.in:456
 msgid ""
 "If set to \"true\" (1), NetworkManager attempts to get the hostname via "
 "DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has "
@@ -9059,7 +9116,7 @@ msgid ""
 "configuration, NetworkManager assumes the value to be \"false\" (0)."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:452
+#: src/libnmc-setting/settings-docs.h.in:457
 msgid ""
 "The relative priority of this connection to determine the system hostname. A "
 "lower numerical value is better (higher priority).  A connection with higher "
@@ -9073,62 +9130,62 @@ msgid ""
 "hostname."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:453
+#: src/libnmc-setting/settings-docs.h.in:458
 msgid "The last byte of supervision address."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:454
+#: src/libnmc-setting/settings-docs.h.in:459
 msgid "The port1 interface name of the HSR. This property is mandatory."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:455
+#: src/libnmc-setting/settings-docs.h.in:460
 msgid "The port2 interface name of the HSR. This property is mandatory."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:456
+#: src/libnmc-setting/settings-docs.h.in:461
 msgid "The protocol used by the interface, whether it is PRP or HSR."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:457
+#: src/libnmc-setting/settings-docs.h.in:462
 msgid ""
 "The maximum size of a packet built by the Generic Receive Offload stack for "
 "this device. The value must be between 0 and 4294967295. When set to -1, the "
 "existing value is preserved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:458
+#: src/libnmc-setting/settings-docs.h.in:463
 msgid ""
 "The maximum segments of a Generic Segment Offload packet the device should "
 "accept. The value must be between 0 and 4294967295. When set to -1, the "
 "existing value is preserved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:459
+#: src/libnmc-setting/settings-docs.h.in:464
 msgid ""
 "The maximum size of a Generic Segment Offload packet the device should "
 "accept. The value must be between 0 and 4294967295. When set to -1, the "
 "existing value is preserved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:460
+#: src/libnmc-setting/settings-docs.h.in:465
 msgid ""
 "The size of the transmit queue for the device, in number of packets. The "
 "value must be between 0 and 4294967295. When set to -1, the existing value "
 "is preserved."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:462
+#: src/libnmc-setting/settings-docs.h.in:467
 msgid "A dictionary of key/value pairs with external-ids for OVS."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:463
+#: src/libnmc-setting/settings-docs.h.in:468
 msgid ""
 "A dictionary of key/value pairs with other_config settings for OVS. See also "
 "\"other_config\" in the \"ovs-vswitchd.conf.db\" manual for the keys that "
 "OVS supports."
 msgstr ""
 
-#: src/libnmc-setting/settings-docs.h.in:464
+#: src/libnmc-setting/settings-docs.h.in:469
 msgid ""
 "This property specifies the peer interface name of the veth. This property "
 "is mandatory."
@@ -9389,15 +9446,15 @@ msgstr ""
 msgid "Error: Error writing connection: %s"
 msgstr ""
 
-#: src/nmcli/connections.c:677
+#: src/nmcli/connections.c:676
 msgid "WiMax is no longer supported"
 msgstr ""
 
-#: src/nmcli/connections.c:683
+#: src/nmcli/connections.c:682
 msgid "WEP encryption is known to be insecure"
 msgstr ""
 
-#: src/nmcli/connections.c:765
+#: src/nmcli/connections.c:764
 msgid "never"
 msgstr ""
 
diff --git a/src/core/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c
index c97fbb57..69c2a38f 100644
--- a/src/core/devices/nm-device-factory.c
+++ b/src/core/devices/nm-device-factory.c
@@ -28,6 +28,10 @@ G_DEFINE_ABSTRACT_TYPE(NMDeviceFactory, nm_device_factory, G_TYPE_OBJECT)
 
 /*****************************************************************************/
 
+static NMDeviceFactory *generic_factory;
+
+/*****************************************************************************/
+
 static void
 nm_device_factory_get_supported_types(NMDeviceFactory    *factory,
                                       const NMLinkType  **out_link_types,
@@ -66,7 +70,8 @@ nm_device_factory_create_device(NMDeviceFactory      *factory,
     if (plink) {
         g_return_val_if_fail(!connection, NULL);
         g_return_val_if_fail(strcmp(iface, plink->name) == 0, NULL);
-        nm_assert(factory == nm_device_factory_manager_find_factory_for_link_type(plink->type));
+        nm_assert(factory == nm_device_factory_manager_find_factory_for_link_type(plink->type)
+                  || factory == generic_factory);
     } else if (connection)
         nm_assert(factory == nm_device_factory_manager_find_factory_for_connection(connection));
     else
@@ -185,6 +190,12 @@ static void __attribute__((destructor)) _cleanup(void)
 }
 
 NMDeviceFactory *
+nm_device_factory_get_generic_factory(void)
+{
+    return generic_factory;
+}
+
+NMDeviceFactory *
 nm_device_factory_manager_find_factory_for_link_type(NMLinkType link_type)
 {
     g_return_val_if_fail(factories_by_link, NULL);
@@ -300,9 +311,12 @@ _load_internal_factory(GType                             factory_gtype,
                        gpointer                          user_data)
 {
     gs_unref_object NMDeviceFactory *factory = NULL;
+    GType                            nm_generic_device_factory_get_type(void);
 
     factory = g_object_new(factory_gtype, NULL);
     _add_factory(factory, NULL, callback, user_data);
+    if (factory_gtype == nm_generic_device_factory_get_type())
+        generic_factory = factory;
 }
 
 static void
@@ -396,6 +410,7 @@ nm_device_factory_manager_load_factories(NMDeviceFactoryManagerFactoryFunc callb
     _ADD_INTERNAL(nm_bridge_device_factory_get_type);
     _ADD_INTERNAL(nm_dummy_device_factory_get_type);
     _ADD_INTERNAL(nm_ethernet_device_factory_get_type);
+    _ADD_INTERNAL(nm_generic_device_factory_get_type);
     _ADD_INTERNAL(nm_hsr_device_factory_get_type);
     _ADD_INTERNAL(nm_infiniband_device_factory_get_type);
     _ADD_INTERNAL(nm_ip_tunnel_device_factory_get_type);
diff --git a/src/core/devices/nm-device-factory.h b/src/core/devices/nm-device-factory.h
index fc3d9dd4..004ae9b1 100644
--- a/src/core/devices/nm-device-factory.h
+++ b/src/core/devices/nm-device-factory.h
@@ -234,4 +234,6 @@ NMDeviceFactory *nm_device_factory_manager_find_factory_for_connection(NMConnect
 void nm_device_factory_manager_for_each_factory(NMDeviceFactoryManagerFactoryFunc callback,
                                                 gpointer                          user_data);
 
+NMDeviceFactory *nm_device_factory_get_generic_factory(void);
+
 #endif /* __NETWORKMANAGER_DEVICE_FACTORY_H__ */
diff --git a/src/core/devices/nm-device-generic.c b/src/core/devices/nm-device-generic.c
index ead671d4..85f65246 100644
--- a/src/core/devices/nm-device-generic.c
+++ b/src/core/devices/nm-device-generic.c
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
- * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2013-2023 Red Hat, Inc.
  */
 
 #include "src/core/nm-default-daemon.h"
@@ -10,13 +10,27 @@
 #include "nm-device-private.h"
 #include "libnm-platform/nm-platform.h"
 #include "libnm-core-intern/nm-core-internal.h"
+#include "nm-dispatcher.h"
+#include "nm-device-factory.h"
+
+#define _NMLOG_DEVICE_TYPE NMDeviceGeneric
+#include "devices/nm-device-logging.h"
 
 /*****************************************************************************/
 
-NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_TYPE_DESCRIPTION, );
+NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceGeneric, PROP_TYPE_DESCRIPTION, PROP_HAS_DEVICE_HANDLER, );
 
 typedef struct {
-    const char *type_description;
+    const char         *type_description;
+    bool                prepare_done : 1;
+    bool                has_device_handler : 1;
+    NMDispatcherCallId *dispatcher_call_id;
+    struct {
+        NMDeviceDeactivateCallback callback;
+        gpointer                   callback_data;
+        GCancellable              *cancellable;
+        gulong                     cancellable_id;
+    } deactivate;
 } NMDeviceGenericPrivate;
 
 struct _NMDeviceGeneric {
@@ -38,13 +52,151 @@ G_DEFINE_TYPE(NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE)
 static NMDeviceCapabilities
 get_generic_capabilities(NMDevice *device)
 {
-    int ifindex = nm_device_get_ifindex(device);
+    NMDeviceGenericPrivate *priv    = NM_DEVICE_GENERIC_GET_PRIVATE(device);
+    int                     ifindex = nm_device_get_ifindex(device);
+    NMDeviceCapabilities    cap     = NM_DEVICE_CAP_NONE;
+
+    if (priv->has_device_handler)
+        cap |= NM_DEVICE_CAP_IS_SOFTWARE;
 
     if (ifindex > 0
         && nm_platform_link_supports_carrier_detect(nm_device_get_platform(device), ifindex))
-        return NM_DEVICE_CAP_CARRIER_DETECT;
-    else
-        return NM_DEVICE_CAP_NONE;
+        cap |= NM_DEVICE_CAP_CARRIER_DETECT;
+
+    return cap;
+}
+
+static void
+device_add_dispatcher_cb(NMDispatcherCallId *call_id,
+                         gpointer            user_data,
+                         gboolean            success,
+                         const char         *error,
+                         GHashTable         *dict)
+{
+    nm_auto_unref_object NMDeviceGeneric *self     = NM_DEVICE_GENERIC(user_data);
+    NMDeviceGenericPrivate               *priv     = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+    NMDevice                             *device   = NM_DEVICE(self);
+    NMPlatform                           *platform = nm_device_get_platform(device);
+    const NMPlatformLink                 *link;
+    int                                   ifindex = -1;
+    const char                           *ifindex_str;
+    NMSettingConnection                  *s_con;
+
+    nm_assert(call_id == priv->dispatcher_call_id);
+    priv->dispatcher_call_id = NULL;
+
+    if (!success) {
+        _LOGW(LOGD_CORE, "device handler 'device-add' failed: %s", error);
+        nm_device_state_changed(device,
+                                NM_DEVICE_STATE_FAILED,
+                                NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return;
+    }
+
+    ifindex_str = g_hash_table_lookup(dict, "IFINDEX");
+    if (!ifindex_str) {
+        _LOGW(LOGD_CORE, "device handler 'device-add' didn't return a IFINDEX key");
+        nm_device_state_changed(device,
+                                NM_DEVICE_STATE_FAILED,
+                                NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return;
+    }
+
+    ifindex = _nm_utils_ascii_str_to_int64(ifindex_str, 10, 1, G_MAXINT32, -1);
+    if (ifindex < 0) {
+        _LOGW(LOGD_CORE, "device handler 'device-add' returned invalid ifindex '%s'", ifindex_str);
+        nm_device_state_changed(device,
+                                NM_DEVICE_STATE_FAILED,
+                                NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return;
+    }
+
+    _LOGD(LOGD_DEVICE, "device handler 'device-add' returned ifindex %d", ifindex);
+
+    /* Check that the ifindex is valid and matches the interface name. */
+    nm_platform_process_events(platform);
+    link = nm_platform_link_get(platform, ifindex);
+    if (!link) {
+        _LOGW(LOGD_DEVICE,
+              "device handler 'device-add' didn't create link with ifindex %d",
+              ifindex);
+        nm_device_state_changed(device,
+                                NM_DEVICE_STATE_FAILED,
+                                NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return;
+    }
+
+    s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION);
+    nm_assert(s_con);
+
+    if (!nm_streq(link->name, nm_setting_connection_get_interface_name(s_con))) {
+        _LOGW(LOGD_DEVICE,
+              "device handler 'device-add' created a kernel link with name '%s' instead of '%s'",
+              link->name,
+              nm_setting_connection_get_interface_name(s_con));
+        nm_device_state_changed(device,
+                                NM_DEVICE_STATE_FAILED,
+                                NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return;
+    }
+
+    priv->prepare_done = TRUE;
+    nm_device_activate_schedule_stage1_device_prepare(device, FALSE);
+}
+
+static NMActStageReturn
+act_stage1_prepare(NMDevice *self, NMDeviceStateReason *out_failure_reason)
+{
+    NMDevice               *device = NM_DEVICE(self);
+    NMDeviceGenericPrivate *priv   = NM_DEVICE_GENERIC_GET_PRIVATE(device);
+    NMSettingGeneric       *s_generic;
+    const char             *type_desc;
+    int                     ifindex;
+
+    s_generic = nm_device_get_applied_setting(device, NM_TYPE_SETTING_GENERIC);
+    g_return_val_if_fail(s_generic, NM_ACT_STAGE_RETURN_FAILURE);
+
+    if (!nm_setting_generic_get_device_handler(s_generic))
+        return NM_ACT_STAGE_RETURN_SUCCESS;
+
+    if (priv->prepare_done) {
+        /* after we create a new interface via a device-handler, update the
+         * type description */
+        ifindex = nm_device_get_ip_ifindex(NM_DEVICE(self));
+        if (ifindex > 0) {
+            type_desc = nm_platform_link_get_type_name(nm_device_get_platform(device), ifindex);
+            if (!nm_streq0(priv->type_description, type_desc)) {
+                priv->type_description = type_desc;
+                _notify(NM_DEVICE_GENERIC(self), PROP_TYPE_DESCRIPTION);
+            }
+        }
+        return NM_ACT_STAGE_RETURN_SUCCESS;
+    }
+
+    if (priv->dispatcher_call_id) {
+        nm_dispatcher_call_cancel(priv->dispatcher_call_id);
+        priv->dispatcher_call_id = NULL;
+    }
+
+    _LOGD(LOGD_CORE, "calling device handler 'device-add'");
+    if (!nm_dispatcher_call_device_handler(NM_DISPATCHER_ACTION_DEVICE_ADD,
+                                           device,
+                                           NULL,
+                                           device_add_dispatcher_cb,
+                                           g_object_ref(self),
+                                           &priv->dispatcher_call_id)) {
+        _LOGW(LOGD_DEVICE, "failed to call device handler 'device-add'");
+        NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED);
+        return NM_ACT_STAGE_RETURN_FAILURE;
+    }
+
+    return NM_ACT_STAGE_RETURN_POSTPONE;
+}
+
+static void
+act_stage3_ip_config(NMDevice *device, int addr_family)
+{
+    nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL);
 }
 
 static const char *
@@ -110,6 +262,111 @@ update_connection(NMDevice *device, NMConnection *connection)
                  NULL);
 }
 
+static gboolean
+create_and_realize(NMDevice              *device,
+                   NMConnection          *connection,
+                   NMDevice              *parent,
+                   const NMPlatformLink **out_plink,
+                   GError               **error)
+{
+    /* The actual interface is created during stage1 once the device
+     * starts activating, as we need to call the dispatcher service
+     * which returns asynchronously */
+    return TRUE;
+}
+
+static void
+deactivate_clear_data(NMDeviceGeneric *self)
+{
+    NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+
+    if (priv->dispatcher_call_id) {
+        nm_dispatcher_call_cancel(priv->dispatcher_call_id);
+        priv->dispatcher_call_id = NULL;
+    }
+
+    priv->deactivate.callback      = NULL;
+    priv->deactivate.callback_data = NULL;
+    g_clear_object(&priv->deactivate.cancellable);
+}
+
+static void
+device_delete_dispatcher_cb(NMDispatcherCallId *call_id,
+                            gpointer            user_data,
+                            gboolean            success,
+                            const char         *error,
+                            GHashTable         *dict)
+{
+    NMDeviceGeneric        *self  = user_data;
+    NMDeviceGenericPrivate *priv  = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+    gs_free_error GError   *local = NULL;
+
+    nm_assert(call_id == priv->dispatcher_call_id);
+    priv->dispatcher_call_id = NULL;
+
+    if (success)
+        _LOGT(LOGD_DEVICE, "deactivate: async callback");
+    else {
+        local = g_error_new(NM_DEVICE_ERROR,
+                            NM_DEVICE_ERROR_FAILED,
+                            "device handler 'device-delete' failed with error: %s",
+                            error);
+    }
+
+    priv->deactivate.callback(NM_DEVICE(self), local, priv->deactivate.callback_data);
+    nm_clear_g_cancellable_disconnect(priv->deactivate.cancellable,
+                                      &priv->deactivate.cancellable_id);
+    deactivate_clear_data(self);
+}
+
+static void
+deactivate_cancellable_cancelled(GCancellable *cancellable, NMDeviceGeneric *self)
+{
+    NMDeviceGenericPrivate *priv  = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+    gs_free_error GError   *error = NULL;
+
+    error = nm_utils_error_new_cancelled(FALSE, NULL);
+    priv->deactivate.callback(NM_DEVICE(self), error, priv->deactivate.callback_data);
+
+    deactivate_clear_data(self);
+}
+
+static void
+deactivate_async(NMDevice                  *device,
+                 GCancellable              *cancellable,
+                 NMDeviceDeactivateCallback callback,
+                 gpointer                   callback_user_data)
+{
+    NMDeviceGeneric        *self = NM_DEVICE_GENERIC(device);
+    NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+
+    _LOGT(LOGD_CORE, "deactivate: start async");
+
+    priv->prepare_done = FALSE;
+
+    if (priv->dispatcher_call_id) {
+        nm_dispatcher_call_cancel(priv->dispatcher_call_id);
+        priv->dispatcher_call_id = NULL;
+    }
+
+    g_object_ref(self);
+    priv->deactivate.callback      = callback;
+    priv->deactivate.callback_data = callback_user_data;
+    priv->deactivate.cancellable   = g_object_ref(cancellable);
+    priv->deactivate.cancellable_id =
+        g_cancellable_connect(cancellable,
+                              G_CALLBACK(deactivate_cancellable_cancelled),
+                              self,
+                              NULL);
+
+    nm_dispatcher_call_device_handler(NM_DISPATCHER_ACTION_DEVICE_DELETE,
+                                      device,
+                                      NULL,
+                                      device_delete_dispatcher_cb,
+                                      self,
+                                      &priv->dispatcher_call_id);
+}
+
 /*****************************************************************************/
 
 static void
@@ -122,6 +379,26 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
     case PROP_TYPE_DESCRIPTION:
         g_value_set_string(value, priv->type_description);
         break;
+    case PROP_HAS_DEVICE_HANDLER:
+        g_value_set_boolean(value, priv->has_device_handler);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    NMDeviceGeneric        *self = (NMDeviceGeneric *) object;
+    NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE(self);
+
+    switch (prop_id) {
+    case PROP_HAS_DEVICE_HANDLER:
+        /* construct-only */
+        priv->has_device_handler = g_value_get_boolean(value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -137,16 +414,41 @@ nm_device_generic_init(NMDeviceGeneric *self)
 static GObject *
 constructor(GType type, guint n_construct_params, GObjectConstructParam *construct_params)
 {
-    GObject *object;
+    GObject                *object;
+    NMDeviceGenericPrivate *priv;
 
     object = G_OBJECT_CLASS(nm_device_generic_parent_class)
                  ->constructor(type, n_construct_params, construct_params);
 
-    nm_device_set_unmanaged_flags((NMDevice *) object, NM_UNMANAGED_BY_DEFAULT, TRUE);
+    priv = NM_DEVICE_GENERIC_GET_PRIVATE(object);
+    /* If the device is software (has a device-handler), don't set
+     * unmanaged-by-default so that the device can autoconnect if
+     * necessary. */
+    if (!priv->has_device_handler)
+        nm_device_set_unmanaged_flags((NMDevice *) object, NM_UNMANAGED_BY_DEFAULT, TRUE);
 
     return object;
 }
 
+static NMDevice *
+create_device(NMDeviceFactory      *factory,
+              const char           *iface,
+              const NMPlatformLink *plink,
+              NMConnection         *connection,
+              gboolean             *out_ignore)
+{
+    return g_object_new(NM_TYPE_DEVICE_GENERIC,
+                        NM_DEVICE_IFACE,
+                        iface,
+                        NM_DEVICE_TYPE_DESC,
+                        "Generic",
+                        NM_DEVICE_DEVICE_TYPE,
+                        NM_DEVICE_TYPE_GENERIC,
+                        NM_DEVICE_GENERIC_HAS_DEVICE_HANDLER,
+                        TRUE,
+                        NULL);
+}
+
 NMDevice *
 nm_device_generic_new(const NMPlatformLink *plink, gboolean nm_plugin_missing)
 {
@@ -188,6 +490,7 @@ nm_device_generic_class_init(NMDeviceGenericClass *klass)
 
     object_class->constructor  = constructor;
     object_class->get_property = get_property;
+    object_class->set_property = set_property;
 
     dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_generic);
 
@@ -195,10 +498,14 @@ nm_device_generic_class_init(NMDeviceGenericClass *klass)
     device_class->connection_type_check_compatible = NM_SETTING_GENERIC_SETTING_NAME;
     device_class->link_types                       = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_ANY);
 
-    device_class->realize_start_notify        = realize_start_notify;
+    device_class->act_stage1_prepare          = act_stage1_prepare;
+    device_class->act_stage3_ip_config        = act_stage3_ip_config;
+    device_class->check_connection_compatible = check_connection_compatible;
+    device_class->create_and_realize          = create_and_realize;
+    device_class->deactivate_async            = deactivate_async;
     device_class->get_generic_capabilities    = get_generic_capabilities;
     device_class->get_type_description        = get_type_description;
-    device_class->check_connection_compatible = check_connection_compatible;
+    device_class->realize_start_notify        = realize_start_notify;
     device_class->update_connection           = update_connection;
 
     obj_properties[PROP_TYPE_DESCRIPTION] =
@@ -207,6 +514,18 @@ nm_device_generic_class_init(NMDeviceGenericClass *klass)
                             "",
                             NULL,
                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
+    obj_properties[PROP_HAS_DEVICE_HANDLER] = g_param_spec_boolean(
+        NM_DEVICE_GENERIC_HAS_DEVICE_HANDLER,
+        "",
+        "",
+        FALSE,
+        G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
     g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }
+
+NM_DEVICE_FACTORY_DEFINE_INTERNAL(
+    GENERIC,
+    Generic,
+    generic,
+    NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_GENERIC_SETTING_NAME),
+    factory_class->create_device = create_device;);
diff --git a/src/core/devices/nm-device-generic.h b/src/core/devices/nm-device-generic.h
index f06a5bdc..07cb5447 100644
--- a/src/core/devices/nm-device-generic.h
+++ b/src/core/devices/nm-device-generic.h
@@ -18,7 +18,8 @@
 #define NM_DEVICE_GENERIC_GET_CLASS(obj) \
     (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass))
 
-#define NM_DEVICE_GENERIC_TYPE_DESCRIPTION "type-description"
+#define NM_DEVICE_GENERIC_TYPE_DESCRIPTION   "type-description"
+#define NM_DEVICE_GENERIC_HAS_DEVICE_HANDLER "has-device-handler"
 
 typedef struct _NMDeviceGeneric      NMDeviceGeneric;
 typedef struct _NMDeviceGenericClass NMDeviceGenericClass;
diff --git a/src/core/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c
index 130708bb..32fab5be 100644
--- a/src/core/devices/nm-device-macsec.c
+++ b/src/core/devices/nm-device-macsec.c
@@ -10,6 +10,7 @@
 #include <linux/if_ether.h>
 
 #include "nm-act-request.h"
+#include "nm-config.h"
 #include "nm-device-private.h"
 #include "libnm-platform/nm-platform.h"
 #include "nm-device-factory.h"
@@ -190,6 +191,7 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
     NMConnection                       *connection;
     const char                         *con_uuid;
     guint32                             mtu;
+    int                                 offload;
 
     connection = nm_device_get_applied_connection(NM_DEVICE(self));
 
@@ -205,7 +207,20 @@ build_supplicant_config(NMDeviceMacsec *self, GError **error)
 
     g_return_val_if_fail(s_macsec, NULL);
 
-    if (!nm_supplicant_config_add_setting_macsec(config, s_macsec, error)) {
+    offload = nm_setting_macsec_get_offload(s_macsec);
+    if (offload == NM_SETTING_MACSEC_OFFLOAD_DEFAULT) {
+        offload = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
+                                                              NM_CON_DEFAULT("macsec.offload"),
+                                                              NM_DEVICE(self),
+                                                              NM_SETTING_MACSEC_OFFLOAD_OFF,
+                                                              NM_SETTING_MACSEC_OFFLOAD_MAC,
+                                                              NM_SETTING_MACSEC_OFFLOAD_OFF);
+    }
+
+    if (!nm_supplicant_config_add_setting_macsec(config,
+                                                 s_macsec,
+                                                 (NMSettingMacsecOffload) offload,
+                                                 error)) {
         g_prefix_error(error, "macsec-setting: ");
         return NULL;
     }
diff --git a/src/core/devices/nm-device-utils.c b/src/core/devices/nm-device-utils.c
index 2bf24ae6..ed0a2738 100644
--- a/src/core/devices/nm-device-utils.c
+++ b/src/core/devices/nm-device-utils.c
@@ -127,7 +127,9 @@ NM_UTILS_LOOKUP_STR_DEFINE(
     NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"),
     NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED,
                              "sriov-configuration-failed"),
-    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), );
+    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"),
+    NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED,
+                             "device-handler-failed"), );
 
 NM_UTILS_LOOKUP_STR_DEFINE(nm_device_mtu_source_to_string,
                            NMDeviceMtuSource,
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index a9e8c085..34022efb 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -137,8 +137,7 @@ typedef struct {
     GCancellable           *cancellable;
     NMPlatformAsyncCallback callback;
     gpointer                callback_data;
-    guint                   num_vfs;
-    NMOptionBool            autoprobe;
+    NMPlatformSriovParams   sriov_params;
 } SriovOp;
 
 typedef enum {
@@ -7706,8 +7705,7 @@ sriov_op_start(NMDevice *self, SriovOp *op)
 
     nm_platform_link_set_sriov_params_async(nm_device_get_platform(self),
                                             priv->ifindex,
-                                            op->num_vfs,
-                                            op->autoprobe,
+                                            op->sriov_params,
                                             sriov_op_cb,
                                             op,
                                             op->cancellable);
@@ -7768,11 +7766,14 @@ sriov_op_queue_op(NMDevice *self, SriovOp *op)
 }
 
 static void
-sriov_op_queue(NMDevice               *self,
-               guint                   num_vfs,
-               NMOptionBool            autoprobe,
-               NMPlatformAsyncCallback callback,
-               gpointer                callback_data)
+sriov_op_queue(NMDevice                *self,
+               guint                    num_vfs,
+               NMOptionBool             autoprobe,
+               NMSriovEswitchMode       eswitch_mode,
+               NMSriovEswitchInlineMode eswitch_inline_mode,
+               NMSriovEswitchEncapMode  eswitch_encap_mode,
+               NMPlatformAsyncCallback  callback,
+               gpointer                 callback_data)
 {
     SriovOp *op;
 
@@ -7797,8 +7798,14 @@ sriov_op_queue(NMDevice               *self,
 
     op  = g_slice_new(SriovOp);
     *op = (SriovOp){
-        .num_vfs       = num_vfs,
-        .autoprobe     = autoprobe,
+        .sriov_params =
+            (NMPlatformSriovParams){
+                .num_vfs             = num_vfs,
+                .autoprobe           = autoprobe,
+                .eswitch_mode        = (_NMSriovEswitchMode) eswitch_mode,
+                .eswitch_inline_mode = (_NMSriovEswitchInlineMode) eswitch_inline_mode,
+                .eswitch_encap_mode  = (_NMSriovEswitchEncapMode) eswitch_encap_mode,
+            },
         .callback      = callback,
         .callback_data = callback_data,
     };
@@ -7823,7 +7830,14 @@ device_init_static_sriov_num_vfs(NMDevice *self)
             -1,
             -1);
         if (num_vfs >= 0)
-            sriov_op_queue(self, num_vfs, NM_OPTION_BOOL_DEFAULT, NULL, NULL);
+            sriov_op_queue(self,
+                           num_vfs,
+                           NM_OPTION_BOOL_DEFAULT,
+                           NM_SRIOV_ESWITCH_MODE_PRESERVE,
+                           NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE,
+                           NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE,
+                           NULL,
+                           NULL);
     }
 }
 
@@ -10004,6 +10018,9 @@ activate_stage1_device_prepare(NMDevice *self)
             sriov_op_queue(self,
                            nm_setting_sriov_get_total_vfs(s_sriov),
                            NM_TERNARY_TO_OPTION_BOOL(autoprobe),
+                           nm_setting_sriov_get_eswitch_mode(s_sriov),
+                           nm_setting_sriov_get_eswitch_inline_mode(s_sriov),
+                           nm_setting_sriov_get_eswitch_encap_mode(s_sriov),
                            sriov_params_cb,
                            nm_utils_user_data_pack(self, g_steal_pointer(&plat_vfs)));
             priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING;
@@ -10880,7 +10897,16 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d
     case NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE:
 
         if (!notify_data->lease_update.l3cd) {
+            const NML3ConfigData *dhcp_l3cd = priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)].d;
+
             _LOGT_ipdhcp(addr_family, "lease lost");
+            if (dhcp_l3cd
+                && nm_l3cfg_remove_config(
+                    priv->l3cfg,
+                    _dev_l3_config_data_tag_get(priv, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4)),
+                    dhcp_l3cd)) {
+                _dev_l3_cfg_commit(self, FALSE);
+            }
             goto lease_update_out;
         }
 
@@ -16711,6 +16737,9 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
                 sriov_op_queue(self,
                                0,
                                NM_OPTION_BOOL_TRUE,
+                               NM_SRIOV_ESWITCH_MODE_PRESERVE,
+                               NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE,
+                               NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE,
                                sriov_reset_on_deactivate_cb,
                                nm_utils_user_data_pack(self, GINT_TO_POINTER(reason)));
             }
@@ -16760,7 +16789,14 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
         if (priv->ifindex > 0
             && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) {
             priv->sriov_reset_pending++;
-            sriov_op_queue(self, 0, NM_OPTION_BOOL_TRUE, sriov_reset_on_failure_cb, self);
+            sriov_op_queue(self,
+                           0,
+                           NM_OPTION_BOOL_TRUE,
+                           NM_SRIOV_ESWITCH_MODE_PRESERVE,
+                           NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE,
+                           NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE,
+                           sriov_reset_on_failure_cb,
+                           self);
             break;
         }
         /* Schedule the transition to DISCONNECTED.  The device can't transition
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index 4be03f4b..8770656b 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -899,6 +899,12 @@ _nm_dhcp_client_notify(NMDhcpClient         *self,
 
     l3_cfg_notify_check_connected(self);
 
+    if (!priv->l3cd_curr) {
+        /* When the lease is lost, any cached ACD information is no longer relevant.
+         * Remove it so that it doesn't interfere with a new lease we might get. */
+        _acd_state_reset(self, TRUE, TRUE);
+    }
+
     _emit_notify(self,
                  NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
                  .lease_update = {
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index c8f7ed0c..e6b1a94e 100644
--- a/src/core/ndisc/nm-ndisc.c
+++ b/src/core/ndisc/nm-ndisc.c
@@ -114,7 +114,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex        *multi_idx,
     nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
     guint32                                 ifa_flags;
     guint                                   i;
-    const gint32                            now_sec = nm_utils_get_monotonic_timestamp_sec();
+    const gint64                            now_msec = nm_utils_get_monotonic_timestamp_msec();
 
     l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_NDISC);
 
@@ -134,12 +134,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex        *multi_idx,
             .ifindex   = ifindex,
             .address   = ndisc_addr->address,
             .plen      = 64,
-            .timestamp = now_sec,
-            .lifetime  = _nm_ndisc_lifetime_from_expiry(((gint64) now_sec) * 1000,
-                                                       ndisc_addr->expiry_msec,
-                                                       TRUE),
+            .timestamp = now_msec / 1000,
+            .lifetime  = _nm_ndisc_lifetime_from_expiry(now_msec, ndisc_addr->expiry_msec, TRUE),
             .preferred = _nm_ndisc_lifetime_from_expiry(
-                ((gint64) now_sec) * 1000,
+                now_msec,
                 NM_MIN(ndisc_addr->expiry_msec, ndisc_addr->expiry_preferred_msec),
                 TRUE),
             .addr_source = NM_IP_CONFIG_SOURCE_NDISC,
diff --git a/src/core/nm-config.c b/src/core/nm-config.c
index 5db4a92a..43eb3646 100644
--- a/src/core/nm-config.c
+++ b/src/core/nm-config.c
@@ -2354,9 +2354,10 @@ _nm_config_state_set(NMConfig *self, gboolean allow_persist, gboolean force_pers
     "route-metric-default-aspired"
 #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE \
     "route-metric-default-effective"
-#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH     "root-path"
-#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER   "next-server"
-#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_DHCP_BOOTFILE "dhcp-bootfile"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH        "root-path"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER      "next-server"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_DHCP_BOOTFILE    "dhcp-bootfile"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_GENERIC_SOFTWARE "generic-software"
 
 static NM_UTILS_LOOKUP_STR_DEFINE(
     _device_state_managed_type_to_str,
@@ -2457,6 +2458,12 @@ _config_device_state_data_new(int ifindex, GKeyFile *kf)
     device_state->route_metric_default_aspired   = route_metric_default_aspired;
     device_state->route_metric_default_effective = route_metric_default_effective;
 
+    device_state->generic_sw =
+        nm_config_keyfile_get_boolean(kf,
+                                      DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+                                      DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_GENERIC_SOFTWARE,
+                                      FALSE);
+
     p = (char *) (&device_state[1]);
     if (connection_uuid) {
         memcpy(p, connection_uuid, connection_uuid_len);
@@ -2502,7 +2509,7 @@ nm_config_device_state_load(int ifindex)
                        ? ", nm-owned=1"
                        : (device_state->nm_owned == NM_TERNARY_FALSE ? ", nm-owned=0" : "");
 
-    _LOGT("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s, "
+    _LOGT("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s%s, "
           "route-metric-default=%" G_GUINT32_FORMAT "-%" G_GUINT32_FORMAT "",
           kf ? "read" : "miss",
           ifindex,
@@ -2519,6 +2526,7 @@ nm_config_device_state_load(int ifindex)
                               "",
                               ""),
           nm_owned_str,
+          device_state->generic_sw ? ", generic-software" : "",
           device_state->route_metric_default_aspired,
           device_state->route_metric_default_effective);
 
@@ -2577,7 +2585,8 @@ nm_config_device_state_write(int                            ifindex,
                              guint32                        route_metric_default_aspired,
                              guint32                        route_metric_default_effective,
                              NMDhcpConfig                  *dhcp4_config,
-                             NMDhcpConfig                  *dhcp6_config)
+                             NMDhcpConfig                  *dhcp6_config,
+                             gboolean                       generic_sw)
 {
     char    path[NM_STRLEN(NM_CONFIG_DEVICE_STATE_DIR "/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
     GError *local                                 = NULL;
@@ -2664,6 +2673,13 @@ nm_config_device_state_write(int                            ifindex,
                               dhcp_bootfile);
     }
 
+    if (generic_sw) {
+        g_key_file_set_boolean(kf,
+                               DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+                               DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_GENERIC_SOFTWARE,
+                               TRUE);
+    }
+
     for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
         NMDhcpConfig              *dhcp_config = IS_IPv4 ? dhcp4_config : dhcp6_config;
         gs_free NMUtilsNamedValue *values      = NULL;
@@ -2691,7 +2707,7 @@ nm_config_device_state_write(int                            ifindex,
         g_error_free(local);
         return FALSE;
     }
-    _LOGT("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, "
+    _LOGT("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s%s, "
           "route-metric-default=%" G_GUINT32_FORMAT "-%" G_GUINT32_FORMAT "%s%s%s"
           "%s%s%s"
           "%s%s%s",
@@ -2700,6 +2716,7 @@ nm_config_device_state_write(int                            ifindex,
           _device_state_managed_type_to_str(managed),
           NM_PRINT_FMT_QUOTED(connection_uuid, ", connection-uuid=", connection_uuid, "", ""),
           NM_PRINT_FMT_QUOTED(perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""),
+          generic_sw ? ", generic-software" : "",
           route_metric_default_aspired,
           route_metric_default_effective,
           NM_PRINT_FMT_QUOTED(next_server, ", next-server=", next_server, "", ""),
diff --git a/src/core/nm-config.h b/src/core/nm-config.h
index acec8d05..e65582c3 100644
--- a/src/core/nm-config.h
+++ b/src/core/nm-config.h
@@ -176,6 +176,8 @@ struct _NMConfigDeviceStateData {
     /* whether the device was nm-owned (0/1) or -1 for
      * non-software devices. */
     NMTernary nm_owned : 3;
+    /* whether the device is a generic one created by NM */
+    bool generic_sw : 1;
 };
 
 NMConfigDeviceStateData *nm_config_device_state_load(int ifindex);
@@ -188,7 +190,8 @@ gboolean                 nm_config_device_state_write(int
                                                       guint32                        route_metric_default_aspired,
                                                       guint32                        route_metric_default_effective,
                                                       NMDhcpConfig                  *dhcp4_config,
-                                                      NMDhcpConfig                  *dhcp6_config);
+                                                      NMDhcpConfig                  *dhcp6_config,
+                                                      gboolean                       generic);
 
 void nm_config_device_state_prune_stale(GHashTable *preserve_ifindexes,
                                         NMPlatform *preserve_in_platform);
diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c
index 9aa4194e..4f442c68 100644
--- a/src/core/nm-dispatcher.c
+++ b/src/core/nm-dispatcher.c
@@ -50,20 +50,24 @@
     }                                                         \
     G_STMT_END
 
-static gboolean nm_dispatcher_need_device(NMDispatcherAction action);
-
 /*****************************************************************************/
 
+/* Type for generic callback function; must be cast to either
+ * NMDispatcherFunc or NMDispatcherFuncDH before using. */
+typedef void (*NMDispatcherCallback)(void);
+
 struct NMDispatcherCallId {
-    NMDispatcherFunc   callback;
-    gpointer           user_data;
-    const char        *log_ifname;
-    const char        *log_con_uuid;
-    gint64             start_at_msec;
-    NMDispatcherAction action;
-    guint              idle_id;
-    guint32            request_id;
-    char               extra_strings[];
+    NMDispatcherCallback callback;
+    gpointer             user_data;
+    const char          *log_ifname;
+    const char          *log_con_uuid;
+    GVariant            *action_params;
+    gint64               start_at_msec;
+    NMDispatcherAction   action;
+    guint                idle_id;
+    guint32              request_id;
+    bool                 is_action2 : 1;
+    char                 extra_strings[];
 };
 
 /*****************************************************************************/
@@ -84,14 +88,34 @@ static struct {
 
 /*****************************************************************************/
 
+/* All actions except 'hostname', 'connectivity-change' and 'dns-change' require
+ * a device */
+static gboolean
+action_need_device(NMDispatcherAction action)
+{
+    if (NM_IN_SET(action,
+                  NM_DISPATCHER_ACTION_HOSTNAME,
+                  NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE,
+                  NM_DISPATCHER_ACTION_DNS_CHANGE)) {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+action_is_device_handler(NMDispatcherAction action)
+{
+    return NM_IN_SET(action, NM_DISPATCHER_ACTION_DEVICE_ADD, NM_DISPATCHER_ACTION_DEVICE_DELETE);
+}
+
 static NMDispatcherCallId *
-dispatcher_call_id_new(guint32            request_id,
-                       gint64             start_at_msec,
-                       NMDispatcherAction action,
-                       NMDispatcherFunc   callback,
-                       gpointer           user_data,
-                       const char        *log_ifname,
-                       const char        *log_con_uuid)
+dispatcher_call_id_new(guint32              request_id,
+                       gint64               start_at_msec,
+                       NMDispatcherAction   action,
+                       NMDispatcherCallback callback,
+                       gpointer             user_data,
+                       const char          *log_ifname,
+                       const char          *log_con_uuid)
 {
     NMDispatcherCallId *call_id;
     gsize               l_log_ifname;
@@ -109,6 +133,7 @@ dispatcher_call_id_new(guint32            request_id,
     call_id->callback      = callback;
     call_id->user_data     = user_data;
     call_id->idle_id       = 0;
+    call_id->is_action2    = TRUE;
 
     extra_strings = &call_id->extra_strings[0];
 
@@ -131,6 +156,7 @@ dispatcher_call_id_new(guint32            request_id,
 static void
 dispatcher_call_id_free(NMDispatcherCallId *call_id)
 {
+    nm_clear_pointer(&call_id->action_params, g_variant_unref);
     nm_clear_g_source(&call_id->idle_id);
     g_free(call_id);
 }
@@ -372,20 +398,50 @@ dispatch_result_to_string(DispatchResult result)
     g_assert_not_reached();
 }
 
+/*
+ * dispatcher_results_process:
+ * @action: the dispatcher action
+ * @request_id: request id
+ * @start_at_msec: the timestamp at which the dispatcher call was started
+ * @now_msec: the current timestamp in milliseconds
+ * @log_ifname: the interface name for logging
+ * @log_con_uuid: the connection UUID for logging
+ * @out_success: (out): for device-handler actions, the result of the script
+ * @out_error_msg: (out)(transfer full): for device-handler actions, the
+ *   error message in case of failure
+ * @out_dict: (out)(transfer full): for device-handler actions, the output
+ *   dictionary in case of success
+ * @v_results: the GVariant containing the results to parse
+ * @is_action2: whether the D-Bus method is "Action2()" (or "Action()")
+ *
+ * Process the results of the dispatcher call.
+ *
+ */
 static void
-dispatcher_results_process(guint32     request_id,
-                           gint64      start_at_msec,
-                           gint64      now_msec,
-                           const char *log_ifname,
-                           const char *log_con_uuid,
-                           GVariant   *v_results)
+dispatcher_results_process(NMDispatcherAction action,
+                           guint32            request_id,
+                           gint64             start_at_msec,
+                           gint64             now_msec,
+                           const char        *log_ifname,
+                           const char        *log_con_uuid,
+                           gboolean          *out_success,
+                           char             **out_error_msg,
+                           GHashTable       **out_dict,
+                           GVariant          *v_results,
+                           gboolean           is_action2)
 {
     nm_auto_free_variant_iter GVariantIter *results = NULL;
     const char                             *script, *err;
     guint32                                 result;
     gsize                                   n_children;
+    gboolean                                action_is_dh = action_is_device_handler(action);
 
-    g_variant_get(v_results, "(a(sus))", &results);
+    nm_assert(!action_is_dh || is_action2);
+
+    if (is_action2)
+        g_variant_get(v_results, "(a(susa{sv}))", &results);
+    else
+        g_variant_get(v_results, "(a(sus))", &results);
 
     n_children = g_variant_iter_n_children(results);
 
@@ -397,10 +453,26 @@ dispatcher_results_process(guint32     request_id,
            (int) ((now_msec - start_at_msec) % 1000),
            n_children);
 
-    if (n_children == 0)
+    if (n_children == 0) {
+        if (action_is_dh) {
+            NM_SET_OUT(out_success, FALSE);
+            NM_SET_OUT(out_error_msg, g_strdup("no result returned from dispatcher service"));
+            NM_SET_OUT(out_dict, NULL);
+        }
         return;
+    }
+
+    while (TRUE) {
+        gs_unref_variant GVariant *options = NULL;
+
+        if (is_action2) {
+            if (!g_variant_iter_next(results, "(&su&s@a{sv})", &script, &result, &err, &options))
+                break;
+        } else {
+            if (!g_variant_iter_next(results, "(&su&s)", &script, &result, &err))
+                break;
+        }
 
-    while (g_variant_iter_next(results, "(&su&s)", &script, &result, &err)) {
         if (result == DISPATCH_RESULT_SUCCESS) {
             _LOG2D(request_id, log_ifname, log_con_uuid, "%s succeeded", script);
         } else {
@@ -412,22 +484,96 @@ dispatcher_results_process(guint32     request_id,
                    dispatch_result_to_string(result),
                    err);
         }
+
+        if (action_is_dh) {
+            if (result == DISPATCH_RESULT_SUCCESS) {
+                gs_unref_variant GVariant     *output_dict = NULL;
+                gs_unref_hashtable GHashTable *hash        = NULL;
+                GVariantIter                   iter;
+                const char                    *value;
+                const char                    *key;
+
+                hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
+                output_dict =
+                    g_variant_lookup_value(options, "output_dict", G_VARIANT_TYPE("a{ss}"));
+                if (output_dict) {
+                    g_variant_iter_init(&iter, output_dict);
+                    while (g_variant_iter_next(&iter, "{&s&s}", &key, &value)) {
+                        const char *unescaped;
+                        gpointer    to_free;
+                        gsize       len;
+
+                        unescaped = nm_utils_buf_utf8safe_unescape(value,
+                                                                   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE,
+                                                                   &len,
+                                                                   &to_free);
+                        g_hash_table_insert(hash,
+                                            g_strdup(key),
+                                            ((char *) to_free) ?: g_strdup(unescaped));
+                    }
+                }
+
+                NM_SET_OUT(out_success, TRUE);
+                NM_SET_OUT(out_dict, g_steal_pointer(&hash));
+                NM_SET_OUT(out_error_msg, NULL);
+            } else {
+                gs_unref_variant GVariant *output_dict = NULL;
+                const char                *err2        = NULL;
+
+                output_dict =
+                    g_variant_lookup_value(options, "output_dict", G_VARIANT_TYPE("a{ss}"));
+                if (output_dict) {
+                    g_variant_lookup(output_dict, "ERROR", "&s", &err2);
+                }
+
+                NM_SET_OUT(out_success, FALSE);
+                NM_SET_OUT(out_dict, NULL);
+                NM_SET_OUT(out_error_msg,
+                           err2 ? g_strdup_printf("%s (Error: %s)", err, err2) : g_strdup(err));
+            }
+            break;
+        }
     }
 }
 
 static void
 dispatcher_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
 {
-    gs_unref_variant GVariant *ret     = NULL;
-    gs_free_error GError      *error   = NULL;
-    NMDispatcherCallId        *call_id = user_data;
-    gint64                     now_msec;
+    gs_unref_variant GVariant     *ret     = NULL;
+    gs_free_error GError          *error   = NULL;
+    NMDispatcherCallId            *call_id = user_data;
+    gint64                         now_msec;
+    gboolean                       action_is_dh;
+    gboolean                       success   = TRUE;
+    gs_free char                  *error_msg = NULL;
+    gs_unref_hashtable GHashTable *hash      = NULL;
 
     nm_assert((gpointer) source == gl.dbus_connection);
 
     now_msec = nm_utils_get_monotonic_timestamp_msec();
 
     ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
+
+    if (!ret && call_id->is_action2 && !action_is_device_handler(call_id->action)
+        && g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
+        _LOG3D(call_id,
+               "dispatcher service does not implement Action2() method, falling back to Action()");
+        call_id->is_action2 = FALSE;
+        g_dbus_connection_call(gl.dbus_connection,
+                               NM_DISPATCHER_DBUS_SERVICE,
+                               NM_DISPATCHER_DBUS_PATH,
+                               NM_DISPATCHER_DBUS_INTERFACE,
+                               "Action",
+                               g_steal_pointer(&call_id->action_params),
+                               G_VARIANT_TYPE("(a(sus))"),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               CALL_TIMEOUT,
+                               NULL,
+                               dispatcher_done_cb,
+                               call_id);
+        return;
+    }
+
     if (!ret) {
         NMLogLevel log_level = LOGL_DEBUG;
 
@@ -442,37 +588,55 @@ dispatcher_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
                 (int) ((now_msec - call_id->start_at_msec) % 1000),
                 error->message);
     } else {
-        dispatcher_results_process(call_id->request_id,
+        dispatcher_results_process(call_id->action,
+                                   call_id->request_id,
                                    call_id->start_at_msec,
                                    now_msec,
                                    call_id->log_ifname,
                                    call_id->log_con_uuid,
-                                   ret);
+                                   &success,
+                                   &error_msg,
+                                   &hash,
+                                   ret,
+                                   call_id->is_action2);
     }
 
     g_hash_table_remove(gl.requests, call_id);
+    action_is_dh = action_is_device_handler(call_id->action);
+
+    if (call_id->callback) {
+        if (action_is_dh) {
+            NMDispatcherFuncDH cb = (NMDispatcherFuncDH) call_id->callback;
+
+            cb(call_id, call_id->user_data, success, error_msg, hash);
+        } else {
+            NMDispatcherFunc cb = (NMDispatcherFunc) call_id->callback;
 
-    if (call_id->callback)
-        call_id->callback(call_id, call_id->user_data);
+            cb(call_id, call_id->user_data);
+        }
+    }
 
     dispatcher_call_id_free(call_id);
 }
 
-static const char *action_table[] = {[NM_DISPATCHER_ACTION_HOSTNAME]      = NMD_ACTION_HOSTNAME,
-                                     [NM_DISPATCHER_ACTION_PRE_UP]        = NMD_ACTION_PRE_UP,
-                                     [NM_DISPATCHER_ACTION_UP]            = NMD_ACTION_UP,
-                                     [NM_DISPATCHER_ACTION_PRE_DOWN]      = NMD_ACTION_PRE_DOWN,
-                                     [NM_DISPATCHER_ACTION_DOWN]          = NMD_ACTION_DOWN,
-                                     [NM_DISPATCHER_ACTION_VPN_PRE_UP]    = NMD_ACTION_VPN_PRE_UP,
-                                     [NM_DISPATCHER_ACTION_VPN_UP]        = NMD_ACTION_VPN_UP,
-                                     [NM_DISPATCHER_ACTION_VPN_PRE_DOWN]  = NMD_ACTION_VPN_PRE_DOWN,
-                                     [NM_DISPATCHER_ACTION_VPN_DOWN]      = NMD_ACTION_VPN_DOWN,
-                                     [NM_DISPATCHER_ACTION_DHCP_CHANGE_4] = NMD_ACTION_DHCP4_CHANGE,
-                                     [NM_DISPATCHER_ACTION_DHCP_CHANGE_6] = NMD_ACTION_DHCP6_CHANGE,
-                                     [NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE] =
-                                         NMD_ACTION_CONNECTIVITY_CHANGE,
-                                     [NM_DISPATCHER_ACTION_REAPPLY]    = NMD_ACTION_REAPPLY,
-                                     [NM_DISPATCHER_ACTION_DNS_CHANGE] = NMD_ACTION_DNS_CHANGE};
+static const char *action_table[] = {
+    [NM_DISPATCHER_ACTION_HOSTNAME]            = NMD_ACTION_HOSTNAME,
+    [NM_DISPATCHER_ACTION_PRE_UP]              = NMD_ACTION_PRE_UP,
+    [NM_DISPATCHER_ACTION_UP]                  = NMD_ACTION_UP,
+    [NM_DISPATCHER_ACTION_PRE_DOWN]            = NMD_ACTION_PRE_DOWN,
+    [NM_DISPATCHER_ACTION_DOWN]                = NMD_ACTION_DOWN,
+    [NM_DISPATCHER_ACTION_VPN_PRE_UP]          = NMD_ACTION_VPN_PRE_UP,
+    [NM_DISPATCHER_ACTION_VPN_UP]              = NMD_ACTION_VPN_UP,
+    [NM_DISPATCHER_ACTION_VPN_PRE_DOWN]        = NMD_ACTION_VPN_PRE_DOWN,
+    [NM_DISPATCHER_ACTION_VPN_DOWN]            = NMD_ACTION_VPN_DOWN,
+    [NM_DISPATCHER_ACTION_DHCP_CHANGE_4]       = NMD_ACTION_DHCP4_CHANGE,
+    [NM_DISPATCHER_ACTION_DHCP_CHANGE_6]       = NMD_ACTION_DHCP6_CHANGE,
+    [NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE] = NMD_ACTION_CONNECTIVITY_CHANGE,
+    [NM_DISPATCHER_ACTION_REAPPLY]             = NMD_ACTION_REAPPLY,
+    [NM_DISPATCHER_ACTION_DNS_CHANGE]          = NMD_ACTION_DNS_CHANGE,
+    [NM_DISPATCHER_ACTION_DEVICE_ADD]          = NMD_ACTION_DEVICE_ADD,
+    [NM_DISPATCHER_ACTION_DEVICE_DELETE]       = NMD_ACTION_DEVICE_DELETE,
+};
 
 static const char *
 action_to_string(NMDispatcherAction action)
@@ -482,75 +646,29 @@ action_to_string(NMDispatcherAction action)
     return action_table[(gsize) action];
 }
 
-static gboolean
-_dispatcher_call(NMDispatcherAction    action,
-                 gboolean              blocking,
-                 NMDevice             *device,
-                 NMSettingsConnection *settings_connection,
-                 NMConnection         *applied_connection,
-                 gboolean              activation_type_external,
-                 NMConnectivityState   connectivity_state,
-                 const char           *vpn_iface,
-                 const NML3ConfigData *l3cd,
-                 NMDispatcherFunc      callback,
-                 gpointer              user_data,
-                 NMDispatcherCallId  **out_call_id)
+static GVariant *
+build_call_parameters(NMDispatcherAction    action,
+                      NMDevice             *device,
+                      NMSettingsConnection *settings_connection,
+                      NMConnection         *applied_connection,
+                      gboolean              activation_type_external,
+                      NMConnectivityState   connectivity_state,
+                      const char           *vpn_iface,
+                      const NML3ConfigData *l3cd,
+                      gboolean              is_action2)
 {
+    const char                *connectivity_state_string = "UNKNOWN";
     GVariant                  *connection_dict;
     GVariantBuilder            connection_props;
     GVariantBuilder            device_props;
     GVariantBuilder            device_proxy_props;
     GVariantBuilder            device_ip4_props;
     GVariantBuilder            device_ip6_props;
-    gs_unref_variant GVariant *parameters_floating = NULL;
-    gs_unref_variant GVariant *device_dhcp4_props  = NULL;
-    gs_unref_variant GVariant *device_dhcp6_props  = NULL;
+    gs_unref_variant GVariant *device_dhcp4_props = NULL;
+    gs_unref_variant GVariant *device_dhcp6_props = NULL;
     GVariantBuilder            vpn_proxy_props;
     GVariantBuilder            vpn_ip4_props;
     GVariantBuilder            vpn_ip6_props;
-    NMDispatcherCallId        *call_id;
-    guint                      request_id;
-    const char                *connectivity_state_string = "UNKNOWN";
-    const char                *log_ifname;
-    const char                *log_con_uuid;
-    gint64                     start_at_msec;
-    gint64                     now_msec;
-
-    g_return_val_if_fail(!blocking || (!callback && !user_data), FALSE);
-
-    NM_SET_OUT(out_call_id, NULL);
-
-    _init_dispatcher();
-
-    if (!gl.dbus_connection)
-        return FALSE;
-
-    log_ifname = device ? nm_device_get_iface(device) : NULL;
-    log_con_uuid =
-        settings_connection ? nm_settings_connection_get_uuid(settings_connection) : NULL;
-
-    request_id = ++gl.request_id_counter;
-    if (G_UNLIKELY(!request_id))
-        request_id = ++gl.request_id_counter;
-
-    if (!nm_dispatcher_need_device(action)) {
-        _LOG2D(request_id,
-               log_ifname,
-               log_con_uuid,
-               "dispatching action '%s'%s",
-               action_to_string(action),
-               blocking ? " (blocking)" : (callback ? " (with callback)" : ""));
-    } else {
-        g_return_val_if_fail(NM_IS_DEVICE(device), FALSE);
-
-        _LOG2D(request_id,
-               log_ifname,
-               log_con_uuid,
-               "(%s) dispatching action '%s'%s",
-               vpn_iface ?: nm_device_get_iface(device),
-               action_to_string(action),
-               blocking ? " (blocking)" : (callback ? " (with callback)" : ""));
-    }
 
     if (applied_connection)
         connection_dict =
@@ -594,7 +712,7 @@ _dispatcher_call(NMDispatcherAction    action,
     g_variant_builder_init(&vpn_ip6_props, G_VARIANT_TYPE_VARDICT);
 
     /* hostname, DNS and connectivity-change actions don't send device data */
-    if (nm_dispatcher_need_device(action)) {
+    if (action_need_device(action)) {
         fill_device_props(device,
                           &device_props,
                           &device_proxy_props,
@@ -609,25 +727,114 @@ _dispatcher_call(NMDispatcherAction    action,
 
     connectivity_state_string = nm_connectivity_state_to_string(connectivity_state);
 
-    parameters_floating =
-        g_variant_new("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
-                      action_to_string(action),
-                      connection_dict,
-                      &connection_props,
-                      &device_props,
-                      &device_proxy_props,
-                      &device_ip4_props,
-                      &device_ip6_props,
-                      device_dhcp4_props ?: nm_g_variant_singleton_aLsvI(),
-                      device_dhcp6_props ?: nm_g_variant_singleton_aLsvI(),
-                      connectivity_state_string,
-                      vpn_iface ?: "",
-                      &vpn_proxy_props,
-                      &vpn_ip4_props,
-                      &vpn_ip6_props,
-                      nm_logging_enabled(LOGL_DEBUG, LOGD_DISPATCH));
-
-    start_at_msec = nm_utils_get_monotonic_timestamp_msec();
+    if (is_action2) {
+        return g_variant_new(
+            "(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b@a{sv})",
+            action_to_string(action),
+            connection_dict,
+            &connection_props,
+            &device_props,
+            &device_proxy_props,
+            &device_ip4_props,
+            &device_ip6_props,
+            device_dhcp4_props ?: nm_g_variant_singleton_aLsvI(),
+            device_dhcp6_props ?: nm_g_variant_singleton_aLsvI(),
+            connectivity_state_string,
+            vpn_iface ?: "",
+            &vpn_proxy_props,
+            &vpn_ip4_props,
+            &vpn_ip6_props,
+            nm_logging_enabled(LOGL_DEBUG, LOGD_DISPATCH),
+            nm_g_variant_singleton_aLsvI());
+    }
+
+    return g_variant_new("(s@a{sa{sv}}a{sv}a{sv}a{sv}a{sv}a{sv}@a{sv}@a{sv}ssa{sv}a{sv}a{sv}b)",
+                         action_to_string(action),
+                         connection_dict,
+                         &connection_props,
+                         &device_props,
+                         &device_proxy_props,
+                         &device_ip4_props,
+                         &device_ip6_props,
+                         device_dhcp4_props ?: nm_g_variant_singleton_aLsvI(),
+                         device_dhcp6_props ?: nm_g_variant_singleton_aLsvI(),
+                         connectivity_state_string,
+                         vpn_iface ?: "",
+                         &vpn_proxy_props,
+                         &vpn_ip4_props,
+                         &vpn_ip6_props,
+                         nm_logging_enabled(LOGL_DEBUG, LOGD_DISPATCH));
+}
+
+static gboolean
+_dispatcher_call(NMDispatcherAction    action,
+                 gboolean              blocking,
+                 NMDevice             *device,
+                 NMSettingsConnection *settings_connection,
+                 NMConnection         *applied_connection,
+                 gboolean              activation_type_external,
+                 NMConnectivityState   connectivity_state,
+                 const char           *vpn_iface,
+                 const NML3ConfigData *l3cd,
+                 NMDispatcherCallback  callback,
+                 gpointer              user_data,
+                 NMDispatcherCallId  **out_call_id)
+{
+    NMDispatcherCallId        *call_id;
+    guint                      request_id;
+    const char                *log_ifname;
+    const char                *log_con_uuid;
+    gint64                     start_at_msec;
+    gint64                     now_msec;
+    gs_unref_variant GVariant *parameters_floating = NULL;
+    gboolean                   is_action2          = TRUE;
+
+    g_return_val_if_fail(!blocking || (!callback && !user_data), FALSE);
+
+    NM_SET_OUT(out_call_id, NULL);
+
+    _init_dispatcher();
+
+    if (!gl.dbus_connection)
+        return FALSE;
+
+    log_ifname = device ? nm_device_get_iface(device) : NULL;
+    log_con_uuid =
+        settings_connection ? nm_settings_connection_get_uuid(settings_connection) : NULL;
+
+    request_id = ++gl.request_id_counter;
+    if (G_UNLIKELY(!request_id))
+        request_id = ++gl.request_id_counter;
+
+    if (!action_need_device(action)) {
+        _LOG2D(request_id,
+               log_ifname,
+               log_con_uuid,
+               "dispatching action '%s'%s",
+               action_to_string(action),
+               blocking ? " (blocking)" : (callback ? " (with callback)" : ""));
+    } else {
+        g_return_val_if_fail(NM_IS_DEVICE(device), FALSE);
+
+        _LOG2D(request_id,
+               log_ifname,
+               log_con_uuid,
+               "(%s) dispatching action '%s'%s",
+               vpn_iface ?: nm_device_get_iface(device),
+               action_to_string(action),
+               blocking ? " (blocking)" : (callback ? " (with callback)" : ""));
+    }
+
+    parameters_floating = build_call_parameters(action,
+                                                device,
+                                                settings_connection,
+                                                applied_connection,
+                                                activation_type_external,
+                                                connectivity_state,
+                                                vpn_iface,
+                                                l3cd,
+                                                TRUE);
+    start_at_msec       = nm_utils_get_monotonic_timestamp_msec();
 
     /* Send the action to the dispatcher */
     if (blocking) {
@@ -638,14 +845,44 @@ _dispatcher_call(NMDispatcherAction    action,
                                           NM_DISPATCHER_DBUS_SERVICE,
                                           NM_DISPATCHER_DBUS_PATH,
                                           NM_DISPATCHER_DBUS_INTERFACE,
-                                          "Action",
+                                          "Action2",
                                           g_steal_pointer(&parameters_floating),
-                                          G_VARIANT_TYPE("(a(sus))"),
+                                          G_VARIANT_TYPE("(a(susa{sv}))"),
                                           G_DBUS_CALL_FLAGS_NONE,
                                           CALL_TIMEOUT,
                                           NULL,
                                           &error);
 
+        if (!ret && g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) {
+            _LOG2D(
+                request_id,
+                log_ifname,
+                log_con_uuid,
+                "dispatcher service does not implement Action2() method, falling back to Action()");
+            g_clear_error(&error);
+            parameters_floating = build_call_parameters(action,
+                                                        device,
+                                                        settings_connection,
+                                                        applied_connection,
+                                                        activation_type_external,
+                                                        connectivity_state,
+                                                        vpn_iface,
+                                                        l3cd,
+                                                        FALSE);
+            ret                 = g_dbus_connection_call_sync(gl.dbus_connection,
+                                              NM_DISPATCHER_DBUS_SERVICE,
+                                              NM_DISPATCHER_DBUS_PATH,
+                                              NM_DISPATCHER_DBUS_INTERFACE,
+                                              "Action",
+                                              g_steal_pointer(&parameters_floating),
+                                              G_VARIANT_TYPE("(a(sus))"),
+                                              G_DBUS_CALL_FLAGS_NONE,
+                                              CALL_TIMEOUT,
+                                              NULL,
+                                              &error);
+            is_action2          = FALSE;
+        }
+
         now_msec = nm_utils_get_monotonic_timestamp_msec();
 
         if (!ret) {
@@ -659,12 +896,17 @@ _dispatcher_call(NMDispatcherAction    action,
                    error->message);
             return FALSE;
         }
-        dispatcher_results_process(request_id,
+        dispatcher_results_process(action,
+                                   request_id,
                                    start_at_msec,
                                    now_msec,
                                    log_ifname,
                                    log_con_uuid,
-                                   ret);
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   ret,
+                                   is_action2);
         return TRUE;
     }
 
@@ -676,13 +918,25 @@ _dispatcher_call(NMDispatcherAction    action,
                                      log_ifname,
                                      log_con_uuid);
 
+    /* Since we don't want to cache all the input parameters, already build
+     * and cache the argument for the Action() method in case Action2() fails. */
+    call_id->action_params = build_call_parameters(action,
+                                                   device,
+                                                   settings_connection,
+                                                   applied_connection,
+                                                   activation_type_external,
+                                                   connectivity_state,
+                                                   vpn_iface,
+                                                   l3cd,
+                                                   FALSE);
+
     g_dbus_connection_call(gl.dbus_connection,
                            NM_DISPATCHER_DBUS_SERVICE,
                            NM_DISPATCHER_DBUS_PATH,
                            NM_DISPATCHER_DBUS_INTERFACE,
-                           "Action",
+                           "Action2",
                            g_steal_pointer(&parameters_floating),
-                           G_VARIANT_TYPE("(a(sus))"),
+                           G_VARIANT_TYPE("(a(susa{sv}))"),
                            G_DBUS_CALL_FLAGS_NONE,
                            CALL_TIMEOUT,
                            NULL,
@@ -718,11 +972,45 @@ nm_dispatcher_call_hostname(NMDispatcherFunc     callback,
                             NM_CONNECTIVITY_UNKNOWN,
                             NULL,
                             NULL,
-                            callback,
+                            (NMDispatcherCallback) callback,
                             user_data,
                             out_call_id);
 }
 
+static gboolean
+_dispatcher_call_device(NMDispatcherAction   action,
+                        NMDevice            *device,
+                        gboolean             blocking,
+                        NMActRequest        *act_request,
+                        NMDispatcherCallback callback,
+                        gpointer             user_data,
+                        NMDispatcherCallId **out_call_id)
+{
+    nm_assert(NM_IS_DEVICE(device));
+    if (!act_request) {
+        act_request = nm_device_get_act_request(device);
+        if (!act_request)
+            return FALSE;
+    }
+    nm_assert(NM_IN_SET(nm_active_connection_get_device(NM_ACTIVE_CONNECTION(act_request)),
+                        NULL,
+                        device));
+    return _dispatcher_call(
+        action,
+        blocking,
+        device,
+        nm_act_request_get_settings_connection(act_request),
+        nm_act_request_get_applied_connection(act_request),
+        nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(act_request))
+            == NM_ACTIVATION_TYPE_EXTERNAL,
+        NM_CONNECTIVITY_UNKNOWN,
+        NULL,
+        NULL,
+        callback,
+        user_data,
+        out_call_id);
+}
+
 /**
  * nm_dispatcher_call_device:
  * @action: the %NMDispatcherAction
@@ -747,29 +1035,50 @@ nm_dispatcher_call_device(NMDispatcherAction   action,
                           gpointer             user_data,
                           NMDispatcherCallId **out_call_id)
 {
-    nm_assert(NM_IS_DEVICE(device));
-    if (!act_request) {
-        act_request = nm_device_get_act_request(device);
-        if (!act_request)
-            return FALSE;
-    }
-    nm_assert(NM_IN_SET(nm_active_connection_get_device(NM_ACTIVE_CONNECTION(act_request)),
-                        NULL,
-                        device));
-    return _dispatcher_call(
-        action,
-        FALSE,
-        device,
-        nm_act_request_get_settings_connection(act_request),
-        nm_act_request_get_applied_connection(act_request),
-        nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(act_request))
-            == NM_ACTIVATION_TYPE_EXTERNAL,
-        NM_CONNECTIVITY_UNKNOWN,
-        NULL,
-        NULL,
-        callback,
-        user_data,
-        out_call_id);
+    g_return_val_if_fail(!action_is_device_handler(action), FALSE);
+
+    return _dispatcher_call_device(action,
+                                   device,
+                                   FALSE,
+                                   act_request,
+                                   (NMDispatcherCallback) callback,
+                                   user_data,
+                                   out_call_id);
+}
+
+/**
+ * nm_dispatcher_call_device_handler:
+ * @action: the %NMDispatcherAction, must be device-add or device-remove
+ * @device: the #NMDevice the action applies to
+ * @act_request: the #NMActRequest for the action. If %NULL, use the
+ *   current request of the device.
+ * @callback: a caller-supplied device-handler callback to execute when done
+ * @user_data: caller-supplied pointer passed to @callback
+ * @out_call_id: on success, a call identifier which can be passed to
+ *   nm_dispatcher_call_cancel()
+ *
+ * This method always invokes the device dispatcher action asynchronously.  To ignore
+ * the result, pass %NULL to @callback.
+ *
+ * Returns: %TRUE if the action was dispatched, %FALSE on failure
+ */
+gboolean
+nm_dispatcher_call_device_handler(NMDispatcherAction   action,
+                                  NMDevice            *device,
+                                  NMActRequest        *act_request,
+                                  NMDispatcherFuncDH   callback,
+                                  gpointer             user_data,
+                                  NMDispatcherCallId **out_call_id)
+{
+    g_return_val_if_fail(action_is_device_handler(action), FALSE);
+
+    return _dispatcher_call_device(action,
+                                   device,
+                                   FALSE,
+                                   act_request,
+                                   (NMDispatcherCallback) callback,
+                                   user_data,
+                                   out_call_id);
 }
 
 /**
@@ -789,29 +1098,9 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
                                NMDevice          *device,
                                NMActRequest      *act_request)
 {
-    nm_assert(NM_IS_DEVICE(device));
-    if (!act_request) {
-        act_request = nm_device_get_act_request(device);
-        if (!act_request)
-            return FALSE;
-    }
-    nm_assert(NM_IN_SET(nm_active_connection_get_device(NM_ACTIVE_CONNECTION(act_request)),
-                        NULL,
-                        device));
-    return _dispatcher_call(
-        action,
-        TRUE,
-        device,
-        nm_act_request_get_settings_connection(act_request),
-        nm_act_request_get_applied_connection(act_request),
-        nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(act_request))
-            == NM_ACTIVATION_TYPE_EXTERNAL,
-        NM_CONNECTIVITY_UNKNOWN,
-        NULL,
-        NULL,
-        NULL,
-        NULL,
-        NULL);
+    g_return_val_if_fail(!action_is_device_handler(action), FALSE);
+
+    return _dispatcher_call_device(action, device, TRUE, act_request, NULL, NULL, NULL);
 }
 
 /**
@@ -852,7 +1141,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction    action,
                             NM_CONNECTIVITY_UNKNOWN,
                             vpn_iface,
                             l3cd,
-                            callback,
+                            (NMDispatcherCallback) callback,
                             user_data,
                             out_call_id);
 }
@@ -879,6 +1168,8 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction    action,
                             const char           *vpn_iface,
                             const NML3ConfigData *l3cd)
 {
+    g_return_val_if_fail(!action_is_device_handler(action), FALSE);
+
     return _dispatcher_call(action,
                             TRUE,
                             parent_device,
@@ -920,7 +1211,7 @@ nm_dispatcher_call_connectivity(NMConnectivityState  connectivity_state,
                             connectivity_state,
                             NULL,
                             NULL,
-                            callback,
+                            (NMDispatcherCallback) callback,
                             user_data,
                             out_call_id);
 }
@@ -952,7 +1243,10 @@ nm_dispatcher_call_dns_change(void)
 void
 nm_dispatcher_call_cancel(NMDispatcherCallId *call_id)
 {
-    if (!call_id || g_hash_table_lookup(gl.requests, call_id) != call_id || !call_id->callback)
+    if (!call_id || g_hash_table_lookup(gl.requests, call_id) != call_id)
+        g_return_if_reached();
+
+    if (!call_id->callback)
         g_return_if_reached();
 
     /* Canceling just means the callback doesn't get called, so set the
@@ -961,16 +1255,3 @@ nm_dispatcher_call_cancel(NMDispatcherCallId *call_id)
     _LOG3D(call_id, "cancelling dispatcher callback action");
     call_id->callback = NULL;
 }
-
-/* All actions except 'hostname', 'connectivity-change' and 'dns-change' require
- * a device */
-static gboolean
-nm_dispatcher_need_device(NMDispatcherAction action)
-{
-    if (action == NM_DISPATCHER_ACTION_HOSTNAME
-        || action == NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE
-        || action == NM_DISPATCHER_ACTION_DNS_CHANGE) {
-        return FALSE;
-    }
-    return TRUE;
-}
diff --git a/src/core/nm-dispatcher.h b/src/core/nm-dispatcher.h
index a1cb96b7..2882503b 100644
--- a/src/core/nm-dispatcher.h
+++ b/src/core/nm-dispatcher.h
@@ -24,6 +24,8 @@ typedef enum {
     NM_DISPATCHER_ACTION_CONNECTIVITY_CHANGE,
     NM_DISPATCHER_ACTION_REAPPLY,
     NM_DISPATCHER_ACTION_DNS_CHANGE,
+    NM_DISPATCHER_ACTION_DEVICE_ADD,
+    NM_DISPATCHER_ACTION_DEVICE_DELETE,
 } NMDispatcherAction;
 
 #define NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4) \
@@ -31,7 +33,14 @@ typedef enum {
 
 typedef struct NMDispatcherCallId NMDispatcherCallId;
 
+/* Callback function for regular dispatcher calls */
 typedef void (*NMDispatcherFunc)(NMDispatcherCallId *call_id, gpointer user_data);
+/* Callback function for device-handler dispatcher calls */
+typedef void (*NMDispatcherFuncDH)(NMDispatcherCallId *call_id,
+                                   gpointer            user_data,
+                                   gboolean            success,
+                                   const char         *error_msg,
+                                   GHashTable         *dict);
 
 gboolean nm_dispatcher_call_hostname(NMDispatcherFunc     callback,
                                      gpointer             user_data,
@@ -44,6 +53,13 @@ gboolean nm_dispatcher_call_device(NMDispatcherAction   action,
                                    gpointer             user_data,
                                    NMDispatcherCallId **out_call_id);
 
+gboolean nm_dispatcher_call_device_handler(NMDispatcherAction   action,
+                                           NMDevice            *device,
+                                           NMActRequest        *act_request,
+                                           NMDispatcherFuncDH   callback_dh,
+                                           gpointer             user_data,
+                                           NMDispatcherCallId **out_call_id);
+
 gboolean nm_dispatcher_call_device_sync(NMDispatcherAction action,
                                         NMDevice          *device,
                                         NMActRequest      *act_request);
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 2cf9cb1d..730ba476 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -4168,8 +4168,11 @@ platform_link_added(NMManager                     *self,
         gboolean              compatible = TRUE;
         gs_free_error GError *error      = NULL;
 
-        if (nm_device_get_link_type(candidate) != plink->type)
+        if (nm_device_get_device_type(candidate) == NM_DEVICE_TYPE_GENERIC) {
+            /* generic devices are compatible with all link types */
+        } else if (nm_device_get_link_type(candidate) != plink->type) {
             continue;
+        }
 
         if (!nm_streq(nm_device_get_iface(candidate), plink->name))
             continue;
@@ -4213,8 +4216,12 @@ platform_link_added(NMManager                     *self,
     }
 
 add:
-    /* Try registered device factories */
-    factory = nm_device_factory_manager_find_factory_for_link_type(plink->type);
+    if (dev_state && dev_state->generic_sw) {
+        factory = nm_device_factory_get_generic_factory();
+    } else {
+        /* Try registered device factories */
+        factory = nm_device_factory_manager_find_factory_for_link_type(plink->type);
+    }
     if (factory) {
         gboolean              ignore = FALSE;
         gs_free_error GError *error  = NULL;
@@ -7860,7 +7867,10 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
                                       route_metric_default_aspired,
                                       route_metric_default_effective,
                                       nm_device_get_dhcp_config(device, AF_INET),
-                                      nm_device_get_dhcp_config(device, AF_INET6)))
+                                      nm_device_get_dhcp_config(device, AF_INET6),
+                                      nm_device_is_software(device)
+                                          && nm_device_get_device_type(device)
+                                                 == NM_DEVICE_TYPE_GENERIC))
         return FALSE;
 
     NM_SET_OUT(out_ifindex, ifindex);
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
index 205559ce..1d0bfdbe 100644
--- a/src/core/platform/tests/test-link.c
+++ b/src/core/platform/tests/test-link.c
@@ -2263,7 +2263,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, ...)
 {
@@ -2343,7 +2343,8 @@ _assert_vlan_flags(int ifindex, _NMVlanFlags flags)
     g_assert(plnk);
     g_assert_cmpint(plnk->flags, ==, flags);
 }
-
+*/
+/*
 static void
 test_vlan_set_xgress(void)
 {
@@ -2359,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;
 
-    /* ingress-qos-map */
 
     g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 4, 5));
     _assert_ingress_qos_mappings(ifindex, 1, 4, 5);
@@ -2385,14 +2385,12 @@ test_vlan_set_xgress(void)
     g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 0, 5));
     _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
 
-    /* Set invalid values: */
     g_assert(nm_platform_link_vlan_set_ingress_map(NM_PLATFORM_GET, ifindex, 8, 3));
     _assert_ingress_qos_mappings(ifindex, 3, 0, 5, 3, 8, 4, 5);
 
     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);
 
-    /* egress-qos-map */
 
     g_assert(nm_platform_link_vlan_set_egress_map(NM_PLATFORM_GET, ifindex, 7, 3));
     _assert_egress_qos_mappings(ifindex, 1, 7, 3);
@@ -2695,7 +2693,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
@@ -4109,7 +4107,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/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index 04e79725..3bcbb71b 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -1723,7 +1723,7 @@ make_user_setting(shvarFile *ifcfg)
         else
             g_string_set_size(str, 0);
 
-        if (!nms_ifcfg_rh_utils_user_key_decode(key + NM_STRLEN("NM_USER_"), str))
+        if (!nm_utils_env_var_decode_name(key + NM_STRLEN("NM_USER_"), str))
             continue;
 
         if (!s_user)
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
index 50e352d3..b4edefbb 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c
@@ -398,115 +398,6 @@ utils_detect_ifcfg_path(const char *path, gboolean only_ifcfg)
     return utils_get_ifcfg_path(path);
 }
 
-void
-nms_ifcfg_rh_utils_user_key_encode(const char *key, GString *str_buffer)
-{
-    gsize i;
-
-    nm_assert(key);
-    nm_assert(str_buffer);
-
-    for (i = 0; key[i]; i++) {
-        char ch = key[i];
-
-        /* we encode the key in only upper case letters, digits, and underscore.
-         * As we expect lower-case letters to be more common, we encode lower-case
-         * letters as upper case, and upper-case letters with a leading underscore. */
-
-        if (ch >= '0' && ch <= '9') {
-            g_string_append_c(str_buffer, ch);
-            continue;
-        }
-        if (ch >= 'a' && ch <= 'z') {
-            g_string_append_c(str_buffer, ch - 'a' + 'A');
-            continue;
-        }
-        if (ch == '.') {
-            g_string_append(str_buffer, "__");
-            continue;
-        }
-        if (ch >= 'A' && ch <= 'Z') {
-            g_string_append_c(str_buffer, '_');
-            g_string_append_c(str_buffer, ch);
-            continue;
-        }
-        g_string_append_printf(str_buffer, "_%03o", (unsigned) ch);
-    }
-}
-
-gboolean
-nms_ifcfg_rh_utils_user_key_decode(const char *name, GString *str_buffer)
-{
-    gsize i;
-
-    nm_assert(name);
-    nm_assert(str_buffer);
-
-    if (!name[0])
-        return FALSE;
-
-    for (i = 0; name[i];) {
-        char ch = name[i];
-
-        if (ch >= '0' && ch <= '9') {
-            g_string_append_c(str_buffer, ch);
-            i++;
-            continue;
-        }
-        if (ch >= 'A' && ch <= 'Z') {
-            g_string_append_c(str_buffer, ch - 'A' + 'a');
-            i++;
-            continue;
-        }
-
-        if (ch == '_') {
-            ch = name[i + 1];
-            if (ch == '_') {
-                g_string_append_c(str_buffer, '.');
-                i += 2;
-                continue;
-            }
-            if (ch >= 'A' && ch <= 'Z') {
-                g_string_append_c(str_buffer, ch);
-                i += 2;
-                continue;
-            }
-            if (ch >= '0' && ch <= '7') {
-                char     ch2, ch3;
-                unsigned v;
-
-                ch2 = name[i + 2];
-                if (!(ch2 >= '0' && ch2 <= '7'))
-                    return FALSE;
-
-                ch3 = name[i + 3];
-                if (!(ch3 >= '0' && ch3 <= '7'))
-                    return FALSE;
-
-#define OCTAL_VALUE(ch) ((unsigned) ((ch) - '0'))
-                v = (OCTAL_VALUE(ch) << 6) + (OCTAL_VALUE(ch2) << 3) + OCTAL_VALUE(ch3);
-                if (v > 0xFF || v == 0)
-                    return FALSE;
-                ch = (char) v;
-                if ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '.')
-                    || (ch >= 'a' && ch <= 'z')) {
-                    /* such characters are not expected to be encoded via
-                     * octal representation. The encoding is invalid. */
-                    return FALSE;
-                }
-                g_string_append_c(str_buffer, ch);
-                i += 4;
-                continue;
-            }
-            return FALSE;
-        }
-
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
 /*****************************************************************************/
 
 const char *const _nm_ethtool_ifcfg_names[] = {
diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 07e5e64d..617c5ef6 100644
--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -2604,7 +2604,7 @@ write_user_setting(NMConnection *connection, shvarFile *ifcfg, GError **error)
 
             g_string_set_size(str, 0);
             g_string_append(str, "NM_USER_");
-            nms_ifcfg_rh_utils_user_key_encode(key, str);
+            nm_utils_env_var_encode_name(key, str);
             svSetValue(ifcfg, str->str, nm_setting_user_get_data(s_user, key));
         }
     }
diff --git a/src/core/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c
index 1d9372e0..9ad4a8f9 100644
--- a/src/core/supplicant/nm-supplicant-config.c
+++ b/src/core/supplicant/nm-supplicant-config.c
@@ -396,14 +396,16 @@ again:
 }
 
 gboolean
-nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
-                                        NMSettingMacsec    *setting,
-                                        GError            **error)
+nm_supplicant_config_add_setting_macsec(NMSupplicantConfig    *self,
+                                        NMSettingMacsec       *setting,
+                                        NMSettingMacsecOffload offload,
+                                        GError               **error)
 {
     const char *value;
     char        buf[32];
     int         port;
     gsize       key_len;
+    const char *offload_str = NULL;
 
     g_return_val_if_fail(NM_IS_SUPPLICANT_CONFIG(self), FALSE);
     g_return_val_if_fail(setting != NULL, FALSE);
@@ -472,6 +474,28 @@ nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
             return FALSE;
     }
 
+    switch (offload) {
+    case NM_SETTING_MACSEC_OFFLOAD_OFF:
+        /* This is the default in wpa_supplicant. Don't set the option,
+         * so that if user doesn't enable offload, the connection still
+         * works with previous versions of the supplicant.
+         */
+        break;
+    case NM_SETTING_MACSEC_OFFLOAD_PHY:
+        offload_str = "1";
+        break;
+    case NM_SETTING_MACSEC_OFFLOAD_MAC:
+        offload_str = "2";
+        break;
+    case NM_SETTING_MACSEC_OFFLOAD_DEFAULT:
+        nm_assert_not_reached();
+        break;
+    }
+    if (offload_str
+        && !nm_supplicant_config_add_option(self, "macsec_offload", offload_str, -1, NULL, error)) {
+        return FALSE;
+    }
+
     return TRUE;
 }
 
diff --git a/src/core/supplicant/nm-supplicant-config.h b/src/core/supplicant/nm-supplicant-config.h
index 585cf958..c52b756e 100644
--- a/src/core/supplicant/nm-supplicant-config.h
+++ b/src/core/supplicant/nm-supplicant-config.h
@@ -68,9 +68,10 @@ gboolean nm_supplicant_config_add_setting_8021x(NMSupplicantConfig *self,
                                                 gboolean            wired,
                                                 GError            **error);
 
-gboolean nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self,
-                                                 NMSettingMacsec    *setting,
-                                                 GError            **error);
+gboolean nm_supplicant_config_add_setting_macsec(NMSupplicantConfig    *self,
+                                                 NMSettingMacsec       *setting,
+                                                 NMSettingMacsecOffload offload,
+                                                 GError               **error);
 
 gboolean nm_supplicant_config_enable_pmf_akm(NMSupplicantConfig *self, GError **error);
 
diff --git a/src/core/supplicant/nm-supplicant-settings-verify.c b/src/core/supplicant/nm-supplicant-settings-verify.c
index 8f2561a6..7842365c 100644
--- a/src/core/supplicant/nm-supplicant-settings-verify.c
+++ b/src/core/supplicant/nm-supplicant-settings-verify.c
@@ -87,6 +87,7 @@ static const struct Opt opt_table[] = {
                              "OWE",
                              "NONE", )),
     OPT_INT("macsec_integ_only", 0, 1),
+    OPT_INT("macsec_offload", 0, 2),
     OPT_INT("macsec_policy", 0, 1),
     OPT_INT("macsec_port", 1, 65534),
     OPT_BYTES("mka_cak", 65536),
diff --git a/src/libnm-base/nm-base.h b/src/libnm-base/nm-base.h
index 34944408..e1cc2733 100644
--- a/src/libnm-base/nm-base.h
+++ b/src/libnm-base/nm-base.h
@@ -277,6 +277,35 @@ typedef enum {
                          | _NM_VLAN_FLAG_LOOSE_BINDING | _NM_VLAN_FLAG_MVRP,
 } _NMVlanFlags;
 
+typedef enum {
+    /* Mirrors libnm's NMSriovEswitchMode.
+     * Values >= 0 mirror kernel's enum devlink_eswitch_mode. */
+    _NM_SRIOV_ESWITCH_MODE_PRESERVE  = -1,
+    _NM_SRIOV_ESWITCH_MODE_UNKNOWN   = -1, /*< skip >*/
+    _NM_SRIOV_ESWITCH_MODE_LEGACY    = 0,
+    _NM_SRIOV_ESWITCH_MODE_SWITCHDEV = 1,
+} _NMSriovEswitchMode;
+
+typedef enum {
+    /* Mirrors libnm's NMSriovEswitchInlineMode.
+     * Values >= 0 mirror kernel's enum devlink_eswitch_inline_mode. */
+    _NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE  = -1,
+    _NM_SRIOV_ESWITCH_INLINE_MODE_UNKNOWN   = -1, /*< skip >*/
+    _NM_SRIOV_ESWITCH_INLINE_MODE_NONE      = 0,
+    _NM_SRIOV_ESWITCH_INLINE_MODE_LINK      = 1,
+    _NM_SRIOV_ESWITCH_INLINE_MODE_NETWORK   = 2,
+    _NM_SRIOV_ESWITCH_INLINE_MODE_TRANSPORT = 3,
+} _NMSriovEswitchInlineMode;
+
+typedef enum {
+    /* Mirrors libnm's NMSriovEswitchEncapMode.
+     * Values >= 0 mirror kernel's enum devlink_eswitch_encap_mode. */
+    _NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE = -1,
+    _NM_SRIOV_ESWITCH_ENCAP_MODE_UNKNOWN  = -1, /*< skip >*/
+    _NM_SRIOV_ESWITCH_ENCAP_MODE_NONE     = 0,
+    _NM_SRIOV_ESWITCH_ENCAP_MODE_BASIC    = 1,
+} _NMSriovEswitchEncapMode;
+
 /*****************************************************************************/
 
 typedef enum {
diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver
index f4c92401..5442377a 100644
--- a/src/libnm-client-impl/libnm.ver
+++ b/src/libnm-client-impl/libnm.ver
@@ -1959,6 +1959,8 @@ global:
 	nm_setting_connection_get_autoconnect_ports;
 	nm_setting_connection_get_controller;
 	nm_setting_connection_get_port_type;
+	nm_setting_generic_get_device_handler;
+	nm_setting_get_enum_property_type;
 	nm_setting_hsr_get_multicast_spec;
 	nm_setting_hsr_get_port1;
 	nm_setting_hsr_get_port2;
@@ -1966,4 +1968,12 @@ global:
 	nm_setting_hsr_get_type;
 	nm_setting_hsr_new;
 	nm_setting_ip_config_get_dhcp_dscp;
+	nm_setting_macsec_get_offload;
+	nm_setting_macsec_offload_get_type;
+	nm_setting_sriov_get_eswitch_encap_mode;
+	nm_setting_sriov_get_eswitch_inline_mode;
+	nm_setting_sriov_get_eswitch_mode;
+	nm_sriov_eswitch_encap_mode_get_type;
+	nm_sriov_eswitch_inline_mode_get_type;
+	nm_sriov_eswitch_mode_get_type;
 } libnm_1_44_0;
diff --git a/src/libnm-core-aux-extern/nm-dispatcher-api.h b/src/libnm-core-aux-extern/nm-dispatcher-api.h
index 7cb370a9..635b4fb3 100644
--- a/src/libnm-core-aux-extern/nm-dispatcher-api.h
+++ b/src/libnm-core-aux-extern/nm-dispatcher-api.h
@@ -35,6 +35,8 @@
 #define NMD_ACTION_CONNECTIVITY_CHANGE "connectivity-change"
 #define NMD_ACTION_REAPPLY             "reapply"
 #define NMD_ACTION_DNS_CHANGE          "dns-change"
+#define NMD_ACTION_DEVICE_ADD          "device-add"
+#define NMD_ACTION_DEVICE_DELETE       "device-delete"
 
 typedef enum {
     DISPATCH_RESULT_UNKNOWN     = 0,
diff --git a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
index 84220043..146f9282 100644
--- a/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
+++ b/src/libnm-core-impl/gen-metadata-nm-settings-libnm-core.xml.in
@@ -769,7 +769,7 @@
                   />
         <property name="autoconnect-ports"
                   dbus-type="i"
-                  gprop-type="NMTernary"
+                  gprop-type="gint"
                   />
         <property name="autoconnect-priority"
                   dbus-type="i"
@@ -1331,6 +1331,10 @@
     <setting name="generic"
              gtype="NMSettingGeneric"
              >
+        <property name="device-handler"
+                  dbus-type="s"
+                  gprop-type="gchararray"
+                  />
     </setting>
     <setting name="gsm"
              gtype="NMSettingGsm"
@@ -1876,6 +1880,10 @@
                   dbus-type="i"
                   gprop-type="gint"
                   />
+        <property name="offload"
+                  dbus-type="i"
+                  gprop-type="gint"
+                  />
         <property name="parent"
                   dbus-type="s"
                   gprop-type="gchararray"
@@ -2198,6 +2206,18 @@
                   dbus-type="i"
                   gprop-type="NMTernary"
                   />
+        <property name="eswitch-encap-mode"
+                  dbus-type="i"
+                  gprop-type="gint"
+                  />
+        <property name="eswitch-inline-mode"
+                  dbus-type="i"
+                  gprop-type="gint"
+                  />
+        <property name="eswitch-mode"
+                  dbus-type="i"
+                  gprop-type="gint"
+                  />
         <property name="total-vfs"
                   dbus-type="u"
                   gprop-type="guint"
diff --git a/src/libnm-core-impl/nm-connection.c b/src/libnm-core-impl/nm-connection.c
index a23dc113..33360d04 100644
--- a/src/libnm-core-impl/nm-connection.c
+++ b/src/libnm-core-impl/nm-connection.c
@@ -3207,6 +3207,13 @@ nm_connection_is_virtual(NMConnection *connection)
         return !!nm_setting_pppoe_get_parent(s_pppoe);
     }
 
+    if (nm_streq(type, NM_SETTING_GENERIC_SETTING_NAME)) {
+        NMSettingGeneric *s_generic;
+
+        s_generic = nm_connection_get_setting_generic(connection);
+        return !!nm_setting_generic_get_device_handler(s_generic);
+    }
+
     return FALSE;
 }
 
diff --git a/src/libnm-core-impl/nm-setting-connection.c b/src/libnm-core-impl/nm-setting-connection.c
index 616a3e5e..7c58c84f 100644
--- a/src/libnm-core-impl/nm-setting-connection.c
+++ b/src/libnm-core-impl/nm-setting-connection.c
@@ -2655,7 +2655,7 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
      *   when this connection is activated.
      * ---end---
      */
-    prop_idx = _nm_setting_property_define_direct_enum(
+    prop_idx = _nm_setting_property_define_direct_real_enum(
         properties_override,
         obj_properties,
         NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES,
@@ -2776,16 +2776,16 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
      * example: CONNECTION_METERED=yes
      * ---end---
      */
-    _nm_setting_property_define_direct_enum(properties_override,
-                                            obj_properties,
-                                            NM_SETTING_CONNECTION_METERED,
-                                            PROP_METERED,
-                                            NM_TYPE_METERED,
-                                            NM_METERED_UNKNOWN,
-                                            NM_SETTING_PARAM_REAPPLY_IMMEDIATELY,
-                                            NULL,
-                                            NMSettingConnectionPrivate,
-                                            metered);
+    _nm_setting_property_define_direct_real_enum(properties_override,
+                                                 obj_properties,
+                                                 NM_SETTING_CONNECTION_METERED,
+                                                 PROP_METERED,
+                                                 NM_TYPE_METERED,
+                                                 NM_METERED_UNKNOWN,
+                                                 NM_SETTING_PARAM_REAPPLY_IMMEDIATELY,
+                                                 NULL,
+                                                 NMSettingConnectionPrivate,
+                                                 metered);
 
     /**
      * NMSettingConnection:lldp:
diff --git a/src/libnm-core-impl/nm-setting-generic.c b/src/libnm-core-impl/nm-setting-generic.c
index 6623e71f..8a38118a 100644
--- a/src/libnm-core-impl/nm-setting-generic.c
+++ b/src/libnm-core-impl/nm-setting-generic.c
@@ -23,13 +23,20 @@
 
 /*****************************************************************************/
 
+NM_GOBJECT_PROPERTIES_DEFINE(NMSettingGeneric, PROP_DEVICE_HANDLER, );
+
+typedef struct {
+    char *device_handler;
+} NMSettingGenericPrivate;
+
 /**
  * NMSettingGeneric:
  *
  * Generic Link Settings
  */
 struct _NMSettingGeneric {
-    NMSetting parent;
+    NMSetting               parent;
+    NMSettingGenericPrivate _priv;
 };
 
 struct _NMSettingGenericClass {
@@ -38,6 +45,82 @@ struct _NMSettingGenericClass {
 
 G_DEFINE_TYPE(NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING)
 
+#define NM_SETTING_GENERIC_GET_PRIVATE(self) \
+    _NM_GET_PRIVATE(self, NMSettingGeneric, NM_IS_SETTING_GENERIC, NMSetting)
+
+/*****************************************************************************/
+
+/**
+ * nm_setting_generic_get_device_handler:
+ * @setting: the #NMSettingGeneric
+ *
+ * Returns the #NMSettingGeneric:device-handler property of the connection.
+ *
+ * Returns: the device handler name, or %NULL if no device handler is set
+ *
+ * Since: 1.46
+ **/
+const char *
+nm_setting_generic_get_device_handler(NMSettingGeneric *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_GENERIC(setting), NULL);
+
+    return NM_SETTING_GENERIC_GET_PRIVATE(setting)->device_handler;
+}
+
+static gboolean
+verify(NMSetting *setting, NMConnection *connection, GError **error)
+{
+    NMSettingGenericPrivate *priv = NM_SETTING_GENERIC_GET_PRIVATE(setting);
+
+    if (priv->device_handler) {
+        if (NM_IN_SET(priv->device_handler[0], '\0', '.')
+            || !NM_STRCHAR_ALL(priv->device_handler,
+                               ch,
+                               g_ascii_isalnum(ch) || NM_IN_SET(ch, '-', '_', '.'))) {
+            g_set_error_literal(error,
+                                NM_CONNECTION_ERROR,
+                                NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                                _("property is invalid"));
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_GENERIC_SETTING_NAME,
+                           NM_SETTING_GENERIC_DEVICE_HANDLER);
+            return FALSE;
+        }
+
+        if (connection) {
+            NMSettingConnection *s_con;
+
+            s_con = nm_connection_get_setting_connection(connection);
+            if (!s_con) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_MISSING_SETTING,
+                            _("missing setting"));
+                g_prefix_error(error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME);
+                return FALSE;
+            }
+
+            if (!nm_setting_connection_get_interface_name(s_con)) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                            _("the property is required when %s.%s is set"),
+                            NM_SETTING_GENERIC_SETTING_NAME,
+                            NM_SETTING_GENERIC_DEVICE_HANDLER);
+                g_prefix_error(error,
+                               "%s.%s: ",
+                               NM_SETTING_CONNECTION_SETTING_NAME,
+                               NM_SETTING_CONNECTION_INTERFACE_NAME);
+                return FALSE;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
 /*****************************************************************************/
 
 static void
@@ -60,7 +143,46 @@ nm_setting_generic_new(void)
 static void
 nm_setting_generic_class_init(NMSettingGenericClass *klass)
 {
-    NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
+    GObjectClass   *object_class        = G_OBJECT_CLASS(klass);
+    NMSettingClass *setting_class       = NM_SETTING_CLASS(klass);
+    GArray         *properties_override = _nm_sett_info_property_override_create_array();
+
+    object_class->get_property = _nm_setting_property_get_property_direct;
+    object_class->set_property = _nm_setting_property_set_property_direct;
+
+    setting_class->verify = verify;
+
+    /**
+     * NMSettingGeneric:device-handler:
+     *
+     * Name of the device handler that will be invoked to add and delete
+     * the device for this connection. The name can only contain ASCII
+     * alphanumeric characters and '-', '_', '.'. It cannot start with '.'.
+     *
+     * See the NetworkManager-dispatcher(8) man page for more details
+     * about how to write the device handler.
+     *
+     * By setting this property the generic connection becomes "virtual",
+     * meaning that it can be activated without an existing device; the device
+     * will be created at the time the connection is started by invoking the
+     * device-handler.
+     *
+     * Since: 1.46
+     **/
+    _nm_setting_property_define_direct_string(properties_override,
+                                              obj_properties,
+                                              NM_SETTING_GENERIC_DEVICE_HANDLER,
+                                              PROP_DEVICE_HANDLER,
+                                              NM_SETTING_PARAM_FUZZY_IGNORE
+                                                  | NM_SETTING_PARAM_INFERRABLE,
+                                              NMSettingGeneric,
+                                              _priv.device_handler);
+
+    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
-    _nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_GENERIC, NULL, NULL, 0);
+    _nm_setting_class_commit(setting_class,
+                             NM_META_SETTING_TYPE_GENERIC,
+                             NULL,
+                             properties_override,
+                             0);
 }
diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c
index 8165cb2f..02334b54 100644
--- a/src/libnm-core-impl/nm-setting-ip-config.c
+++ b/src/libnm-core-impl/nm-setting-ip-config.c
@@ -6139,14 +6139,16 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family)
         obj_properties[PROP_AUTO_ROUTE_EXT_GW],
         &nm_sett_info_propert_type_direct_enum,
         .direct_offset =
-            NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw));
+            NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw),
+        .direct_data.enum_gtype = NM_TYPE_TERNARY);
 
     _nm_properties_override_gobj(
         properties_override,
         obj_properties[PROP_REPLACE_LOCAL_RULE],
         &nm_sett_info_propert_type_direct_enum,
         .direct_offset =
-            NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule));
+            NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule),
+        .direct_data.enum_gtype = NM_TYPE_TERNARY);
 
     _nm_properties_override_gobj(
         properties_override,
diff --git a/src/libnm-core-impl/nm-setting-ip6-config.c b/src/libnm-core-impl/nm-setting-ip6-config.c
index fc0744ad..42bb2571 100644
--- a/src/libnm-core-impl/nm-setting-ip6-config.c
+++ b/src/libnm-core-impl/nm-setting-ip6-config.c
@@ -941,16 +941,16 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass)
      * example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes
      * ---end---
      */
-    _nm_setting_property_define_direct_enum(properties_override,
-                                            obj_properties,
-                                            NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
-                                            PROP_IP6_PRIVACY,
-                                            NM_TYPE_SETTING_IP6_CONFIG_PRIVACY,
-                                            NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
-                                            NM_SETTING_PARAM_NONE,
-                                            NULL,
-                                            NMSettingIP6ConfigPrivate,
-                                            ip6_privacy);
+    _nm_setting_property_define_direct_real_enum(properties_override,
+                                                 obj_properties,
+                                                 NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
+                                                 PROP_IP6_PRIVACY,
+                                                 NM_TYPE_SETTING_IP6_CONFIG_PRIVACY,
+                                                 NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+                                                 NM_SETTING_PARAM_NONE,
+                                                 NULL,
+                                                 NMSettingIP6ConfigPrivate,
+                                                 ip6_privacy);
 
     /**
      * NMSettingIP6Config:addr-gen-mode:
@@ -1215,7 +1215,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass)
                                               NM_SETTING_PARAM_NONE,
                                               NMSettingIP6ConfigPrivate,
                                               dhcp_pd_hint,
-                                              .direct_set_fcn.set_string =
+                                              .direct_data.set_string =
                                                   _set_string_fcn_dhcp_pd_hint,
                                               .direct_string_allow_empty = TRUE);
 
diff --git a/src/libnm-core-impl/nm-setting-macsec.c b/src/libnm-core-impl/nm-setting-macsec.c
index f66fc52a..763d306b 100644
--- a/src/libnm-core-impl/nm-setting-macsec.c
+++ b/src/libnm-core-impl/nm-setting-macsec.c
@@ -35,7 +35,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PARENT,
                                   PROP_MKA_CKN,
                                   PROP_PORT,
                                   PROP_VALIDATION,
-                                  PROP_SEND_SCI, );
+                                  PROP_SEND_SCI,
+                                  PROP_OFFLOAD, );
 
 typedef struct {
     char  *parent;
@@ -47,6 +48,7 @@ typedef struct {
     gint32 port;
     bool   encrypt;
     bool   send_sci;
+    gint32 offload;
 } NMSettingMacsecPrivate;
 
 /**
@@ -212,6 +214,22 @@ nm_setting_macsec_get_send_sci(NMSettingMacsec *setting)
     return NM_SETTING_MACSEC_GET_PRIVATE(setting)->send_sci;
 }
 
+/**
+ * nm_setting_macsec_get_offload:
+ * @setting: the #NMSettingMacsec
+ *
+ * Returns: the #NMSettingMacsec:offload property of the setting
+ *
+ * Since: 1.46
+ **/
+NMSettingMacsecOffload
+nm_setting_macsec_get_offload(NMSettingMacsec *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_MACSEC(setting), NM_SETTING_MACSEC_OFFLOAD_DEFAULT);
+
+    return NM_SETTING_MACSEC_GET_PRIVATE(setting)->offload;
+}
+
 static GPtrArray *
 need_secrets(NMSetting *setting, gboolean check_rerequest)
 {
@@ -597,6 +615,35 @@ nm_setting_macsec_class_init(NMSettingMacsecClass *klass)
                                                NMSettingMacsecPrivate,
                                                send_sci);
 
+    /**
+     * NMSettingMacsec:offload:
+     *
+     * Specifies the MACsec offload mode.
+     *
+     * %NM_SETTING_MACSEC_OFFLOAD_OFF disables MACsec offload.
+     *
+     * %NM_SETTING_MACSEC_OFFLOAD_PHY and %NM_SETTING_MACSEC_OFFLOAD_MAC request offload
+     * respectively to the PHY or to the MAC; if the selected mode is not available, the
+     * connection will fail.
+     *
+     * %NM_SETTING_MACSEC_OFFLOAD_DEFAULT uses the global default value specified in
+     * NetworkManager configuration; if no global default is defined, the built-in
+     * default is %NM_SETTING_MACSEC_OFFLOAD_OFF.
+     *
+     * Since: 1.46
+     **/
+    _nm_setting_property_define_direct_enum(properties_override,
+                                            obj_properties,
+                                            NM_SETTING_MACSEC_OFFLOAD,
+                                            PROP_OFFLOAD,
+                                            NM_TYPE_SETTING_MACSEC_OFFLOAD,
+                                            NM_SETTING_MACSEC_OFFLOAD_DEFAULT,
+                                            NM_SETTING_PARAM_INFERRABLE
+                                                | NM_SETTING_PARAM_FUZZY_IGNORE,
+                                            NULL,
+                                            NMSettingMacsecPrivate,
+                                            offload);
+
     g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
     _nm_setting_class_commit(setting_class,
diff --git a/src/libnm-core-impl/nm-setting-private.h b/src/libnm-core-impl/nm-setting-private.h
index 6bad516e..1276c903 100644
--- a/src/libnm-core-impl/nm-setting-private.h
+++ b/src/libnm-core-impl/nm-setting-private.h
@@ -904,6 +904,13 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
 
 /*****************************************************************************/
 
+/* Define a direct property of type enum, but using `int` as type in the underlying
+ * GObject property. This is the preferred way to define enum properties because using
+ * real enums it is not possible to maintain backwards compatibility with clients
+ * using an old libnm (glib asserts against new values of the enum not being valid).
+ * The main difference from define_direct_real_enum is that this will accept any
+ * integer value, and we'll check that it's valid in #NMSetting::verify, as doing
+ * 'verify' is optional for clients. */
 #define _nm_setting_property_define_direct_enum(properties_override,                             \
                                                 obj_properties,                                  \
                                                 prop_name,                                       \
@@ -924,6 +931,58 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
                           ~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \
                             | NM_SETTING_PARAM_INFERRABLE)));                                    \
                                                                                                  \
+        nm_assert(G_TYPE_IS_ENUM(gtype_enum));                                                   \
+                                                                                                 \
+        _param_spec = g_param_spec_int("" prop_name "",                                          \
+                                       "",                                                       \
+                                       "",                                                       \
+                                       G_MININT32,                                               \
+                                       G_MAXINT32,                                               \
+                                       (default_value),                                          \
+                                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY               \
+                                           | G_PARAM_STATIC_STRINGS | (param_flags));            \
+                                                                                                 \
+        (obj_properties)[(prop_id)] = _param_spec;                                               \
+        _property_type              = (property_type) ?: &nm_sett_info_propert_type_direct_enum; \
+                                                                                                 \
+        _nm_properties_override_gobj(                                                            \
+            (properties_override),                                                               \
+            _param_spec,                                                                         \
+            _property_type,                                                                      \
+            .direct_offset =                                                                     \
+                NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field),    \
+            .direct_data.enum_gtype = (gtype_enum),                                              \
+            __VA_ARGS__);                                                                        \
+    })
+
+/*****************************************************************************/
+
+/* Define an enum property using real enums in the GObject, not integers. Note that
+ * this is not backwards compatible because clients with old libnm will reject
+ * newer values of the enum. Generally you want to use define_direct_enum and use this
+ * one only for properties that already existed as real enums */
+#define _nm_setting_property_define_direct_real_enum(properties_override,                        \
+                                                     obj_properties,                             \
+                                                     prop_name,                                  \
+                                                     prop_id,                                    \
+                                                     gtype_enum,                                 \
+                                                     default_value,                              \
+                                                     param_flags,                                \
+                                                     property_type,                              \
+                                                     private_struct_type,                        \
+                                                     private_struct_field,                       \
+                                                     ... /* extra NMSettInfoProperty fields */)  \
+    ({                                                                                           \
+        GParamSpec                  *_param_spec;                                                \
+        const NMSettInfoPropertType *_property_type;                                             \
+                                                                                                 \
+        G_STATIC_ASSERT(                                                                         \
+            !NM_FLAGS_ANY((param_flags),                                                         \
+                          ~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \
+                            | NM_SETTING_PARAM_INFERRABLE)));                                    \
+                                                                                                 \
+        nm_assert(G_TYPE_IS_ENUM(gtype_enum));                                                   \
+                                                                                                 \
         _param_spec = g_param_spec_enum("" prop_name "",                                         \
                                         "",                                                      \
                                         "",                                                      \
@@ -941,11 +1000,26 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
             _property_type,                                                                      \
             .direct_offset =                                                                     \
                 NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field),    \
+            .direct_data.enum_gtype = (gtype_enum),                                              \
             __VA_ARGS__);                                                                        \
     })
 
 /*****************************************************************************/
 
+#define _nm_setting_property_is_valid_direct_enum(property_info)                               \
+    ({                                                                                         \
+        const NMSettInfoProperty *_property_info = (property_info);                            \
+        NMValueType               direct_nmtype  = _property_info->property_type->direct_type; \
+        GType                     direct_gtype   = _property_info->direct_data.enum_gtype;     \
+        GParamSpec               *spec           = _property_info->param_spec;                 \
+        GType                     spec_gtype     = spec ? spec->value_type : G_TYPE_INVALID;   \
+                                                                                               \
+        direct_nmtype == NM_VALUE_TYPE_ENUM &&direct_gtype &&G_TYPE_IS_ENUM(direct_gtype)      \
+            && NM_IN_SET(spec_gtype, G_TYPE_INT, direct_gtype);                                \
+    })
+
+/*****************************************************************************/
+
 #define _nm_setting_property_define_direct_ternary_enum(properties_override,  \
                                                         obj_properties,       \
                                                         prop_name,            \
@@ -954,17 +1028,17 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
                                                         private_struct_type,  \
                                                         private_struct_field, \
                                                         ...)                  \
-    _nm_setting_property_define_direct_enum((properties_override),            \
-                                            (obj_properties),                 \
-                                            prop_name,                        \
-                                            (prop_id),                        \
-                                            NM_TYPE_TERNARY,                  \
-                                            NM_TERNARY_DEFAULT,               \
-                                            (param_flags),                    \
-                                            NULL,                             \
-                                            private_struct_type,              \
-                                            private_struct_field,             \
-                                            __VA_ARGS__)
+    _nm_setting_property_define_direct_real_enum((properties_override),       \
+                                                 (obj_properties),            \
+                                                 prop_name,                   \
+                                                 (prop_id),                   \
+                                                 NM_TYPE_TERNARY,             \
+                                                 NM_TERNARY_DEFAULT,          \
+                                                 (param_flags),               \
+                                                 NULL,                        \
+                                                 private_struct_type,         \
+                                                 private_struct_field,        \
+                                                 __VA_ARGS__)
 
 /*****************************************************************************/
 
diff --git a/src/libnm-core-impl/nm-setting-sriov.c b/src/libnm-core-impl/nm-setting-sriov.c
index b9faad56..145c2b14 100644
--- a/src/libnm-core-impl/nm-setting-sriov.c
+++ b/src/libnm-core-impl/nm-setting-sriov.c
@@ -9,6 +9,7 @@
 
 #include "nm-setting-private.h"
 #include "nm-utils-private.h"
+#include "nm-core-enum-types.h"
 
 /**
  * SECTION:nm-setting-sriov
@@ -18,7 +19,13 @@
 
 /*****************************************************************************/
 
-NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov, PROP_TOTAL_VFS, PROP_VFS, PROP_AUTOPROBE_DRIVERS, );
+NM_GOBJECT_PROPERTIES_DEFINE(NMSettingSriov,
+                             PROP_TOTAL_VFS,
+                             PROP_VFS,
+                             PROP_AUTOPROBE_DRIVERS,
+                             PROP_ESWITCH_MODE,
+                             PROP_ESWITCH_INLINE_MODE,
+                             PROP_ESWITCH_ENCAP_MODE, );
 
 /**
  * NMSettingSriov:
@@ -32,6 +39,9 @@ struct _NMSettingSriov {
     GPtrArray *vfs;
     int        autoprobe_drivers;
     guint32    total_vfs;
+    int        eswitch_mode;
+    int        eswitch_inline_mode;
+    int        eswitch_encap_mode;
 };
 
 struct _NMSettingSriovClass {
@@ -835,6 +845,54 @@ nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting)
     return setting->autoprobe_drivers;
 }
 
+/**
+ * nm_setting_sriov_get_eswitch_mode:
+ * @setting: the #NMSettingSriov
+ *
+ * Returns: the value contained in the #NMSettingSriov:eswitch-mode property.
+ *
+ * Since: 1.46
+ */
+NMSriovEswitchMode
+nm_setting_sriov_get_eswitch_mode(NMSettingSriov *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_MODE_PRESERVE);
+
+    return setting->eswitch_mode;
+}
+
+/**
+ * nm_setting_sriov_get_eswitch_inline_mode:
+ * @setting: the #NMSettingSriov
+ *
+ * Returns: the value contained in the #NMSettingSriov:eswitch-inline-mode property.
+ *
+ * Since: 1.46
+ */
+NMSriovEswitchInlineMode
+nm_setting_sriov_get_eswitch_inline_mode(NMSettingSriov *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE);
+
+    return setting->eswitch_inline_mode;
+}
+
+/**
+ * nm_setting_sriov_get_eswitch_encap_mode:
+ * @setting: the #NMSettingSriov
+ *
+ * Returns: the value contained in the #NMSettingSriov:eswitch-encap-mode property.
+ *
+ * Since: 1.46
+ */
+NMSriovEswitchEncapMode
+nm_setting_sriov_get_eswitch_encap_mode(NMSettingSriov *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_SRIOV(setting), NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE);
+
+    return setting->eswitch_encap_mode;
+}
+
 static int
 vf_index_compare(gconstpointer a, gconstpointer b)
 {
@@ -1331,6 +1389,79 @@ nm_setting_sriov_class_init(NMSettingSriovClass *klass)
                                                     NMSettingSriov,
                                                     autoprobe_drivers);
 
+    /**
+     * NMSettingSriov:eswitch-mode
+     *
+     * Select the eswitch mode of the device. Currently it's only supported for
+     * PCI PF devices, and only if the eswitch device is managed from the same
+     * PCI address than the PF.
+     *
+     * If set to %NM_SRIOV_ESWITCH_MODE_PRESERVE (default) the eswitch mode won't be
+     * modified by NetworkManager.
+     *
+     * Since: 1.46
+     */
+    _nm_setting_property_define_direct_enum(properties_override,
+                                            obj_properties,
+                                            NM_SETTING_SRIOV_ESWITCH_MODE,
+                                            PROP_ESWITCH_MODE,
+                                            NM_TYPE_SRIOV_ESWITCH_MODE,
+                                            NM_SRIOV_ESWITCH_MODE_PRESERVE,
+                                            NM_SETTING_PARAM_FUZZY_IGNORE,
+                                            NULL,
+                                            NMSettingSriov,
+                                            eswitch_mode);
+
+    /**
+     * NMSettingSriov:eswitch-inline-mode
+     *
+     * Select the eswitch inline-mode of the device. Some HWs need the VF driver to put
+     * part of the packet headers on the TX descriptor so the e-switch can do proper
+     * matching and steering.
+     *
+     * Currently it's only supported for PCI PF devices, and only if the eswitch device
+     * is managed from the same PCI address than the PF.
+     *
+     * If set to %NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE (default) the eswitch inline-mode
+     * won't be modified by NetworkManager.
+     *
+     * Since: 1.46
+     */
+    _nm_setting_property_define_direct_enum(properties_override,
+                                            obj_properties,
+                                            NM_SETTING_SRIOV_ESWITCH_INLINE_MODE,
+                                            PROP_ESWITCH_INLINE_MODE,
+                                            NM_TYPE_SRIOV_ESWITCH_INLINE_MODE,
+                                            NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE,
+                                            NM_SETTING_PARAM_FUZZY_IGNORE,
+                                            NULL,
+                                            NMSettingSriov,
+                                            eswitch_inline_mode);
+
+    /**
+     * NMSettingSriov:eswitch-encap-mode
+     *
+     * Select the eswitch encapsulation support.
+     *
+     * Currently it's only supported for PCI PF devices, and only if the eswitch device
+     * is managed from the same PCI address than the PF.
+     *
+     * If set to %NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE (default) the eswitch encap-mode
+     * won't be modified by NetworkManager.
+     *
+     * Since: 1.46
+     */
+    _nm_setting_property_define_direct_enum(properties_override,
+                                            obj_properties,
+                                            NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE,
+                                            PROP_ESWITCH_ENCAP_MODE,
+                                            NM_TYPE_SRIOV_ESWITCH_ENCAP_MODE,
+                                            NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE,
+                                            NM_SETTING_PARAM_FUZZY_IGNORE,
+                                            NULL,
+                                            NMSettingSriov,
+                                            eswitch_encap_mode);
+
     g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
     _nm_setting_class_commit(setting_class,
diff --git a/src/libnm-core-impl/nm-setting-wireguard.c b/src/libnm-core-impl/nm-setting-wireguard.c
index c313d22c..4f96f742 100644
--- a/src/libnm-core-impl/nm-setting-wireguard.c
+++ b/src/libnm-core-impl/nm-setting-wireguard.c
@@ -2361,8 +2361,7 @@ nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass)
                                               NM_SETTING_PARAM_SECRET,
                                               NMSettingWireGuard,
                                               _priv.private_key,
-                                              .direct_set_fcn.set_string =
-                                                  _set_string_fcn_public_key,
+                                              .direct_data.set_string = _set_string_fcn_public_key,
                                               .direct_string_allow_empty = TRUE);
 
     /**
diff --git a/src/libnm-core-impl/nm-setting.c b/src/libnm-core-impl/nm-setting.c
index e6e4d23b..8bc7b4bf 100644
--- a/src/libnm-core-impl/nm-setting.c
+++ b/src/libnm-core-impl/nm-setting.c
@@ -682,10 +682,10 @@ _property_direct_set_string(const NMSettInfoSetting  *sett_info,
                + (!!property_info->direct_string_is_refstr)
                + (property_info->direct_set_string_mac_address_len > 0)
                + (property_info->direct_set_string_ip_address_addr_family != 0))
-              <= (property_info->direct_set_fcn.set_string ? 0 : 1));
+              <= (property_info->direct_data.set_string ? 0 : 1));
 
-    if (property_info->direct_set_fcn.set_string) {
-        return property_info->direct_set_fcn.set_string(sett_info, property_info, setting, src);
+    if (property_info->direct_data.set_string) {
+        return property_info->direct_data.set_string(sett_info, property_info, setting, src);
     }
 
     dst = _nm_setting_get_private_field(setting, sett_info, property_info);
@@ -805,7 +805,13 @@ _nm_setting_property_get_property_direct(GObject    *object,
     {
         const int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
 
-        g_value_set_enum(value, *p_val);
+        nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
+
+        if (G_TYPE_IS_ENUM(pspec->value_type))
+            g_value_set_enum(value, *p_val);
+        else
+            g_value_set_int(value, *p_val);
+
         return;
     }
     case NM_VALUE_TYPE_FLAGS:
@@ -940,7 +946,13 @@ _nm_setting_property_set_property_direct(GObject      *object,
         int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
         int  v;
 
-        v = g_value_get_enum(value);
+        nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
+
+        if (G_TYPE_IS_ENUM(pspec->value_type))
+            v = g_value_get_enum(value);
+        else
+            v = g_value_get_int(value);
+
         if (*p_val == v)
             return;
         *p_val = v;
@@ -1076,7 +1088,13 @@ _init_direct(NMSetting *setting)
             int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
             int  def_val;
 
-            def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
+            nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
+
+            if (G_TYPE_IS_ENUM(property_info->param_spec->value_type))
+                def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
+            else
+                def_val = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec);
+
             nm_assert(NM_IN_SET(*p_val, 0, property_info->direct_is_aliased_field ? def_val : 0));
             *p_val = def_val;
             break;
@@ -1234,10 +1252,22 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_
     {
         int val;
 
+        nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
+
         val = *((int *) _nm_setting_get_private_field(setting, sett_info, property_info));
-        if (!property_info->to_dbus_including_default
-            && val == NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec))
-            return NULL;
+
+        if (!property_info->to_dbus_including_default) {
+            int default_value;
+
+            if (G_TYPE_IS_ENUM(property_info->param_spec->value_type))
+                default_value = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
+            else
+                default_value = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec);
+
+            if (val == default_value)
+                return NULL;
+        }
+
         return nm_g_variant_maybe_singleton_i(val);
     }
     case NM_VALUE_TYPE_FLAGS:
@@ -1413,7 +1443,10 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
         GVariant                       *_value         = (value);                      \
         gboolean                        _success       = FALSE;                        \
                                                                                        \
-        nm_assert(_property_info->param_spec->value_type == _gtype);                   \
+        nm_assert(_property_info->param_spec->value_type == _gtype                     \
+                  || (_property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM \
+                      && _property_info->direct_data.enum_gtype == _gtype));           \
+                                                                                       \
         if (_property_info->property_type->from_dbus_direct_allow_transform) {         \
             nm_auto_unset_gvalue GValue _gvalue = G_VALUE_INIT;                        \
                                                                                        \
@@ -1564,21 +1597,20 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
     }
     case NM_VALUE_TYPE_ENUM:
     {
-        const GParamSpecEnum *param_spec;
-        int                  *p_val;
-        int                   v;
+        int *p_val;
+        int  v;
 
-        param_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec);
+        nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
 
         if (g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
             G_STATIC_ASSERT(sizeof(int) >= sizeof(gint32));
             v = g_variant_get_int32(value);
         } else {
-            if (!_variant_get_value_transform(property_info,
-                                              value,
-                                              G_TYPE_FROM_CLASS(param_spec->enum_class),
-                                              g_value_get_flags,
-                                              &v))
+            GType gtype = G_TYPE_IS_ENUM(property_info->param_spec->value_type)
+                              ? property_info->param_spec->value_type
+                              : G_TYPE_INT;
+
+            if (!_variant_get_value_transform(property_info, value, gtype, g_value_get_flags, &v))
                 goto out_error_wrong_dbus_type;
         }
 
@@ -1586,8 +1618,18 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
         if (*p_val == v)
             goto out_unchanged;
 
-        if (!g_enum_get_value(param_spec->enum_class, v))
-            goto out_error_param_spec_validation;
+        /* To avoid that clients with old libnm fails setting a newer value received
+         * from the daemon, do not validate here if the value is within range or not.
+         * Instead, do it in 'verify' that the client can ignore.
+         * However, some properties are implemented as real enums, mostly those that
+         * were originally implemented as such. Maintain the old behaviour on them. */
+        if (G_TYPE_IS_ENUM(property_info->param_spec->value_type)) {
+            const GParamSpecEnum *enum_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec);
+
+            if (!g_enum_get_value(enum_spec->enum_class, v))
+                goto out_error_param_spec_validation;
+        }
+
         *p_val = v;
         goto out_notify;
     }
@@ -2422,7 +2464,6 @@ _verify_properties(NMSetting *setting, GError **error)
         case NM_VALUE_TYPE_BOOL:
         case NM_VALUE_TYPE_BYTES:
         case NM_VALUE_TYPE_STRV:
-        case NM_VALUE_TYPE_ENUM:
         case NM_VALUE_TYPE_FLAGS:
         case NM_VALUE_TYPE_INT32:
         case NM_VALUE_TYPE_INT64:
@@ -2430,6 +2471,37 @@ _verify_properties(NMSetting *setting, GError **error)
         case NM_VALUE_TYPE_UINT32:
         case NM_VALUE_TYPE_UINT64:
             break;
+        case NM_VALUE_TYPE_ENUM:
+        {
+            nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL;
+            int                                 *val;
+
+            nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
+
+            enum_class = g_type_class_ref(property_info->direct_data.enum_gtype);
+            val        = _nm_setting_get_private_field(setting, sett_info, property_info);
+
+            /* We validate here that the value is within the range of the enum, and not
+             * in the GObject property and/or DBus setters. This way, clients using an
+             * old libnm can accept new values added later to the enum, because clients
+             * are not required to 'verify' */
+            if (!g_enum_get_value(enum_class, *val)) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("invalid value %d, expected %d-%d"),
+                            *val,
+                            enum_class->minimum,
+                            enum_class->maximum);
+                g_prefix_error(error,
+                               "%s.%s: ",
+                               klass->setting_info->setting_name,
+                               property_info->name);
+                return FALSE;
+            }
+
+            return TRUE;
+        }
         case NM_VALUE_TYPE_STRING:
         {
             const char *val;
@@ -4444,6 +4516,43 @@ nm_range_from_str(const char *str, GError **error)
     return nm_range_new(start, end);
 }
 
+/**
+ * nm_setting_get_enum_property_type:
+ * @setting_type: the GType of the NMSetting instance
+ * @property_name: the name of the property
+ *
+ * Get the type of the enum that defines the values that the property accepts. It is only
+ * useful for properties configured to accept values from certain enum type, otherwise
+ * it will return %G_TYPE_INVALID. Note that flags (children of G_TYPE_FLAGS) are also
+ * considered enums.
+ *
+ * Note that the GObject property might be implemented as an integer, actually, and not
+ * as enum. Find out what underlying type is used, checking the #GParamSpec, before
+ * setting the GObject property.
+ *
+ * Returns: the enum's GType, or %G_TYPE_INVALID if the property is not of enum type
+ *
+ * Since: 1.46
+ */
+GType
+nm_setting_get_enum_property_type(GType setting_type, const char *property_name)
+{
+    nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref(setting_type);
+    const NMSettInfoProperty                *property_info;
+    GParamSpec                              *spec;
+
+    g_return_val_if_fail(NM_IS_SETTING_CLASS(setting_class), G_TYPE_INVALID);
+
+    property_info = _nm_setting_class_get_property_info(setting_class, property_name);
+    spec          = property_info->param_spec;
+
+    if (spec && (G_TYPE_IS_ENUM(spec->value_type) || G_TYPE_IS_FLAGS(spec->value_type)))
+        return property_info->param_spec->value_type;
+    if (property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM)
+        return property_info->direct_data.enum_gtype;
+    return G_TYPE_INVALID;
+}
+
 /*****************************************************************************/
 
 static void
diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c
index 72b855a5..4b5a0b6f 100644
--- a/src/libnm-core-impl/tests/test-setting.c
+++ b/src/libnm-core-impl/tests/test-setting.c
@@ -4565,7 +4565,7 @@ test_setting_metadata(void)
             GArray                   *property_types_data;
             guint                     prop_idx_val;
             gboolean                  can_set_including_default = FALSE;
-            gboolean                  can_have_direct_set_fcn   = FALSE;
+            gboolean                  can_have_direct_data      = FALSE;
             int                       n_special_options;
 
             g_assert(sip->name);
@@ -4662,18 +4662,35 @@ test_setting_metadata(void)
 
                 can_set_including_default = TRUE;
             } else if (sip->property_type->direct_type == NM_VALUE_TYPE_ENUM) {
-                const GParamSpecEnum *pspec;
+                nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL;
+                int                                  default_value;
 
+                g_assert(_nm_setting_property_is_valid_direct_enum(sip));
+                g_assert(G_TYPE_IS_ENUM(sip->direct_data.enum_gtype));
                 g_assert(g_variant_type_equal(sip->property_type->dbus_type, "i"));
                 g_assert(sip->param_spec);
-                g_assert(g_type_is_a(sip->param_spec->value_type, G_TYPE_ENUM));
-                g_assert(sip->param_spec->value_type != G_TYPE_ENUM);
 
-                pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec);
-                g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type);
-                g_assert(g_enum_get_value(pspec->enum_class, pspec->default_value));
+                if (G_TYPE_IS_ENUM(sip->param_spec->value_type)) {
+                    const GParamSpecEnum *pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec);
+
+                    g_assert(sip->param_spec->value_type != G_TYPE_ENUM);
+                    g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type);
+                    g_assert(sip->param_spec->value_type == sip->direct_data.enum_gtype);
+
+                    default_value = pspec->default_value;
+                } else if (sip->param_spec->value_type == G_TYPE_INT) {
+                    const GParamSpecInt *pspec = NM_G_PARAM_SPEC_CAST_INT(sip->param_spec);
+
+                    default_value = pspec->default_value;
+                } else {
+                    g_assert_not_reached();
+                }
+
+                enum_class = g_type_class_ref(sip->direct_data.enum_gtype);
+                g_assert(g_enum_get_value(enum_class, default_value));
 
                 can_set_including_default = TRUE;
+                can_have_direct_data      = TRUE;
             } else if (sip->property_type->direct_type == NM_VALUE_TYPE_FLAGS) {
                 const GParamSpecFlags *pspec;
 
@@ -4703,7 +4720,7 @@ test_setting_metadata(void)
                                        INFINIBAND_ALEN));
                 } else {
                     g_assert(g_variant_type_equal(sip->property_type->dbus_type, "s"));
-                    can_have_direct_set_fcn = TRUE;
+                    can_have_direct_data = TRUE;
                 }
                 g_assert(sip->param_spec);
                 g_assert(sip->param_spec->value_type == G_TYPE_STRING);
@@ -4744,8 +4761,8 @@ test_setting_metadata(void)
                 g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRING);
             }
 
-            if (!can_have_direct_set_fcn)
-                g_assert(!sip->direct_set_fcn.set_string);
+            if (!can_have_direct_data)
+                g_assert(!sip->direct_data.set_string);
 
             if (sip->property_type->direct_type == NM_VALUE_TYPE_NONE)
                 g_assert(!sip->direct_also_notify);
diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h
index dedc90b2..3903467d 100644
--- a/src/libnm-core-intern/nm-core-internal.h
+++ b/src/libnm-core-intern/nm-core-internal.h
@@ -800,7 +800,13 @@ struct _NMSettInfoProperty {
                                const NMSettInfoProperty *property_info,
                                NMSetting                *setting,
                                const char               *src);
-    } direct_set_fcn;
+
+        /* We implement %NM_VALUE_TYPE_ENUM properties as integer GObject properties
+        * because using real enum triggers glib assertions when passing newer values to
+        * clients with old libnm. This defines the enum type that the direct_property of
+        * type %NM_VALUE_TYPE_ENUM will use. */
+        GType enum_gtype;
+    } direct_data;
 
     /* For direct properties, this is the param_spec that also should be
      * notified on changes. */
diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h
index 5acbf467..66cd590d 100644
--- a/src/libnm-core-public/nm-dbus-interface.h
+++ b/src/libnm-core-public/nm-dbus-interface.h
@@ -610,6 +610,8 @@ typedef enum {
  * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported
  * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed
  * @NM_DEVICE_STATE_REASON_PEER_NOT_FOUND: The Wi-Fi P2P peer could not be found
+ * @NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED: The device handler dispatcher returned an
+ *   error. Since: 1.46
  *
  * Device state change reason codes
  */
@@ -682,6 +684,7 @@ typedef enum {
     NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED          = 65,
     NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED     = 66,
     NM_DEVICE_STATE_REASON_PEER_NOT_FOUND                 = 67,
+    NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED          = 68,
 } NMDeviceStateReason;
 
 /**
@@ -1415,4 +1418,21 @@ typedef enum /*< flags >*/ {
     NM_MPTCP_FLAGS_FULLMESH = 0x80,
 } NMMptcpFlags;
 
+/* For secrets requests, hints starting with "x-vpn-message:" are a message to show, not
+ * a secret to request
+ */
+#define NM_SECRET_TAG_VPN_MSG "x-vpn-message:"
+
+/* For secrets requests, hints starting with "x-dynamic-challenge(-echo):" are dynamic
+ * 2FA challenges that are requested in a second authentication step, after the password
+ * (or whatever auth method is used) was already successfully validated. Because of
+ * that, the default secrets of the service mustn't be requested (again).
+ * When using the "-echo" variant, the user input doesn't need to be hidden even
+ * without --show-secrets
+ *
+ * Note: currently only implemented for VPN, but can be extended.
+ */
+#define NM_SECRET_TAG_DYNAMIC_CHALLENGE      "x-dynamic-challenge:"
+#define NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO "x-dynamic-challenge-echo:"
+
 #endif /* __NM_DBUS_INTERFACE_H__ */
diff --git a/src/libnm-core-public/nm-dbus-types.xml b/src/libnm-core-public/nm-dbus-types.xml
index 18417169..d294453d 100644
--- a/src/libnm-core-public/nm-dbus-types.xml
+++ b/src/libnm-core-public/nm-dbus-types.xml
@@ -1247,6 +1247,11 @@
               <entry role="enum_member_value"><para>= <literal>67</literal></para><para></para></entry>
               <entry role="enum_member_description"><para>The Wi-Fi P2P peer could not be found</para><para></para></entry>
             </row>
+            <row role="constant">
+              <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED</para><para></para></entry>
+              <entry role="enum_member_value"><para>= <literal>68</literal></para><para></para></entry>
+              <entry role="enum_member_description"><para>The device handler dispatcher returned an error. Since: 1.46</para><para></para></entry>
+            </row>
           </tbody>
         </tgroup>
       </informaltable>
diff --git a/src/libnm-core-public/nm-setting-generic.h b/src/libnm-core-public/nm-setting-generic.h
index 9bdcd11d..d735513f 100644
--- a/src/libnm-core-public/nm-setting-generic.h
+++ b/src/libnm-core-public/nm-setting-generic.h
@@ -27,12 +27,17 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_GENERIC_SETTING_NAME "generic"
 
+#define NM_SETTING_GENERIC_DEVICE_HANDLER "device-handler"
+
 typedef struct _NMSettingGenericClass NMSettingGenericClass;
 
 GType nm_setting_generic_get_type(void);
 
 NMSetting *nm_setting_generic_new(void);
 
+NM_AVAILABLE_IN_1_46
+const char *nm_setting_generic_get_device_handler(NMSettingGeneric *setting);
+
 G_END_DECLS
 
 #endif /* __NM_SETTING_GENERIC_H__ */
diff --git a/src/libnm-core-public/nm-setting-macsec.h b/src/libnm-core-public/nm-setting-macsec.h
index c2662b1f..27b7311e 100644
--- a/src/libnm-core-public/nm-setting-macsec.h
+++ b/src/libnm-core-public/nm-setting-macsec.h
@@ -35,6 +35,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_MACSEC_PORT          "port"
 #define NM_SETTING_MACSEC_VALIDATION    "validation"
 #define NM_SETTING_MACSEC_SEND_SCI      "send-sci"
+#define NM_SETTING_MACSEC_OFFLOAD       "offload"
 
 typedef struct _NMSettingMacsecClass NMSettingMacsecClass;
 
@@ -77,6 +78,24 @@ typedef enum {
 /* Deprecated. The CKN can be between 2 and 64 characters. */
 #define NM_SETTING_MACSEC_MKA_CKN_LENGTH 64
 
+/**
+ * NMSettingMacsecOffload:
+ * @NM_SETTING_MACSEC_OFFLOAD_DEFAULT: use the global default; disable if not defined
+ * @NM_SETTING_MACSEC_OFFLOAD_OFF: disable offload
+ * @NM_SETTING_MACSEC_OFFLOAD_PHY: request offload to the PHY
+ * @NM_SETTING_MACSEC_OFFLOAD_MAC: request offload to the MAC
+ *
+ * These flags control the MACsec offload mode.
+ *
+ * Since: 1.46
+ **/
+typedef enum {
+    NM_SETTING_MACSEC_OFFLOAD_DEFAULT = -1,
+    NM_SETTING_MACSEC_OFFLOAD_OFF     = 0,
+    NM_SETTING_MACSEC_OFFLOAD_PHY     = 1,
+    NM_SETTING_MACSEC_OFFLOAD_MAC     = 2,
+} NMSettingMacsecOffload;
+
 NM_AVAILABLE_IN_1_6
 GType nm_setting_macsec_get_type(void);
 NM_AVAILABLE_IN_1_6
@@ -100,6 +119,8 @@ NM_AVAILABLE_IN_1_6
 NMSettingMacsecValidation nm_setting_macsec_get_validation(NMSettingMacsec *setting);
 NM_AVAILABLE_IN_1_12
 gboolean nm_setting_macsec_get_send_sci(NMSettingMacsec *setting);
+NM_AVAILABLE_IN_1_46
+NMSettingMacsecOffload nm_setting_macsec_get_offload(NMSettingMacsec *setting);
 
 G_END_DECLS
 
diff --git a/src/libnm-core-public/nm-setting-sriov.h b/src/libnm-core-public/nm-setting-sriov.h
index 071b9837..affccc48 100644
--- a/src/libnm-core-public/nm-setting-sriov.h
+++ b/src/libnm-core-public/nm-setting-sriov.h
@@ -26,9 +26,12 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_SRIOV_SETTING_NAME "sriov"
 
-#define NM_SETTING_SRIOV_TOTAL_VFS         "total-vfs"
-#define NM_SETTING_SRIOV_VFS               "vfs"
-#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS "autoprobe-drivers"
+#define NM_SETTING_SRIOV_TOTAL_VFS           "total-vfs"
+#define NM_SETTING_SRIOV_VFS                 "vfs"
+#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS   "autoprobe-drivers"
+#define NM_SETTING_SRIOV_ESWITCH_MODE        "eswitch-mode"
+#define NM_SETTING_SRIOV_ESWITCH_INLINE_MODE "eswitch-inline-mode"
+#define NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE  "eswitch-encap-mode"
 
 #define NM_SRIOV_VF_ATTRIBUTE_MAC         "mac"
 #define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK "spoof-check"
@@ -53,6 +56,55 @@ typedef enum {
     NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1,
 } NMSriovVFVlanProtocol;
 
+/**
+ * NMSriovEswitchMode:
+ * @NM_SRIOV_ESWITCH_MODE_PRESERVE:  don't modify current eswitch mode
+ * @NM_SRIOV_ESWITCH_MODE_LEGACY:    use legacy SRIOV
+ * @NM_SRIOV_ESWITCH_MODE_SWITCHDEV: use switchdev mode
+ *
+ * Since: 1.46
+ */
+typedef enum {
+    NM_SRIOV_ESWITCH_MODE_PRESERVE  = -1,
+    NM_SRIOV_ESWITCH_MODE_UNKNOWN   = -1, /*< skip >*/
+    NM_SRIOV_ESWITCH_MODE_LEGACY    = 0,
+    NM_SRIOV_ESWITCH_MODE_SWITCHDEV = 1,
+} NMSriovEswitchMode;
+
+/**
+ * NMSriovEswitchInlineMode:
+ * @NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE:  don't modify current inline-mode
+ * @NM_SRIOV_ESWITCH_INLINE_MODE_NONE:      don't use inline mode
+ * @NM_SRIOV_ESWITCH_INLINE_MODE_LINK:      L2 mode
+ * @NM_SRIOV_ESWITCH_INLINE_MODE_NETWORK:   L3 mode
+ * @NM_SRIOV_ESWITCH_INLINE_MODE_TRANSPORT: L4 mode
+ *
+ * Since: 1.46
+ */
+typedef enum {
+    NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE  = -1,
+    NM_SRIOV_ESWITCH_INLINE_MODE_UNKNOWN   = -1, /*< skip >*/
+    NM_SRIOV_ESWITCH_INLINE_MODE_NONE      = 0,
+    NM_SRIOV_ESWITCH_INLINE_MODE_LINK      = 1,
+    NM_SRIOV_ESWITCH_INLINE_MODE_NETWORK   = 2,
+    NM_SRIOV_ESWITCH_INLINE_MODE_TRANSPORT = 3,
+} NMSriovEswitchInlineMode;
+
+/**
+ * NMSriovEswitchEncapMode:
+ * @NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE: don't modify current encap-mode
+ * @NM_SRIOV_ESWITCH_ENCAP_MODE_NONE: disable encapsulation mode
+ * @NM_SRIOV_ESWITCH_ENCAP_MODE_BASIC: enable encapsulation mode
+ *
+ * Since: 1.46
+ */
+typedef enum {
+    NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE = -1,
+    NM_SRIOV_ESWITCH_ENCAP_MODE_UNKNOWN  = -1, /*< skip >*/
+    NM_SRIOV_ESWITCH_ENCAP_MODE_NONE     = 0,
+    NM_SRIOV_ESWITCH_ENCAP_MODE_BASIC    = 1,
+} NMSriovEswitchEncapMode;
+
 NM_AVAILABLE_IN_1_14
 GType nm_setting_sriov_get_type(void);
 NM_AVAILABLE_IN_1_14
@@ -73,6 +125,12 @@ NM_AVAILABLE_IN_1_14
 void nm_setting_sriov_clear_vfs(NMSettingSriov *setting);
 NM_AVAILABLE_IN_1_14
 NMTernary nm_setting_sriov_get_autoprobe_drivers(NMSettingSriov *setting);
+NM_AVAILABLE_IN_1_46
+NMSriovEswitchMode nm_setting_sriov_get_eswitch_mode(NMSettingSriov *setting);
+NM_AVAILABLE_IN_1_46
+NMSriovEswitchInlineMode nm_setting_sriov_get_eswitch_inline_mode(NMSettingSriov *setting);
+NM_AVAILABLE_IN_1_46
+NMSriovEswitchEncapMode nm_setting_sriov_get_eswitch_encap_mode(NMSettingSriov *setting);
 
 NM_AVAILABLE_IN_1_14
 gboolean nm_sriov_vf_add_vlan(NMSriovVF *vf, guint vlan_id);
diff --git a/src/libnm-core-public/nm-setting.h b/src/libnm-core-public/nm-setting.h
index d525a6ad..6c6fe2bf 100644
--- a/src/libnm-core-public/nm-setting.h
+++ b/src/libnm-core-public/nm-setting.h
@@ -255,6 +255,9 @@ void nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr pre
 const GVariantType *nm_setting_get_dbus_property_type(NMSetting  *setting,
                                                       const char *property_name);
 
+NM_AVAILABLE_IN_1_46
+GType nm_setting_get_enum_property_type(GType setting_type, const char *property_name);
+
 /*****************************************************************************/
 
 typedef struct _NMRange NMRange;
diff --git a/src/libnm-core-public/nm-version-macros.h b/src/libnm-core-public/nm-version-macros.h
index 4582e9b7..7e0b4a36 100644
--- a/src/libnm-core-public/nm-version-macros.h
+++ b/src/libnm-core-public/nm-version-macros.h
@@ -22,7 +22,7 @@
  * Evaluates to the minor version number of NetworkManager which this source
  * is compiled against.
  */
-#define NM_MINOR_VERSION (45)
+#define NM_MINOR_VERSION (46)
 
 /**
  * NM_MICRO_VERSION:
@@ -30,7 +30,7 @@
  * Evaluates to the micro version number of NetworkManager which this source
  * compiled against.
  */
-#define NM_MICRO_VERSION (91)
+#define NM_MICRO_VERSION (0)
 
 /**
  * NM_CHECK_VERSION:
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c
index 7d623bd9..421e4d1b 100644
--- a/src/libnm-glib-aux/nm-shared-utils.c
+++ b/src/libnm-glib-aux/nm-shared-utils.c
@@ -7330,3 +7330,114 @@ nm_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **e
 
     return g_task_propagate_boolean(task, error);
 }
+
+/*****************************************************************************/
+
+void
+nm_utils_env_var_encode_name(const char *key, GString *str_buffer)
+{
+    gsize i;
+
+    nm_assert(key);
+    nm_assert(str_buffer);
+
+    for (i = 0; key[i]; i++) {
+        char ch = key[i];
+
+        /* we encode the key in only upper case letters, digits, and underscore.
+         * As we expect lower-case letters to be more common, we encode lower-case
+         * letters as upper case, and upper-case letters with a leading underscore. */
+
+        if (ch >= '0' && ch <= '9') {
+            g_string_append_c(str_buffer, ch);
+            continue;
+        }
+        if (ch >= 'a' && ch <= 'z') {
+            g_string_append_c(str_buffer, ch - 'a' + 'A');
+            continue;
+        }
+        if (ch == '.') {
+            g_string_append(str_buffer, "__");
+            continue;
+        }
+        if (ch >= 'A' && ch <= 'Z') {
+            g_string_append_c(str_buffer, '_');
+            g_string_append_c(str_buffer, ch);
+            continue;
+        }
+        g_string_append_printf(str_buffer, "_%03o", (unsigned) ch);
+    }
+}
+
+gboolean
+nm_utils_env_var_decode_name(const char *name, GString *str_buffer)
+{
+    gsize i;
+
+    nm_assert(name);
+    nm_assert(str_buffer);
+
+    if (!name[0])
+        return FALSE;
+
+    for (i = 0; name[i];) {
+        char ch = name[i];
+
+        if (ch >= '0' && ch <= '9') {
+            g_string_append_c(str_buffer, ch);
+            i++;
+            continue;
+        }
+        if (ch >= 'A' && ch <= 'Z') {
+            g_string_append_c(str_buffer, ch - 'A' + 'a');
+            i++;
+            continue;
+        }
+
+        if (ch == '_') {
+            ch = name[i + 1];
+            if (ch == '_') {
+                g_string_append_c(str_buffer, '.');
+                i += 2;
+                continue;
+            }
+            if (ch >= 'A' && ch <= 'Z') {
+                g_string_append_c(str_buffer, ch);
+                i += 2;
+                continue;
+            }
+            if (ch >= '0' && ch <= '7') {
+                char     ch2, ch3;
+                unsigned v;
+
+                ch2 = name[i + 2];
+                if (!(ch2 >= '0' && ch2 <= '7'))
+                    return FALSE;
+
+                ch3 = name[i + 3];
+                if (!(ch3 >= '0' && ch3 <= '7'))
+                    return FALSE;
+
+#define OCTAL_VALUE(ch) ((unsigned) ((ch) - '0'))
+                v = (OCTAL_VALUE(ch) << 6) + (OCTAL_VALUE(ch2) << 3) + OCTAL_VALUE(ch3);
+                if (v > 0xFF || v == 0)
+                    return FALSE;
+                ch = (char) v;
+                if ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '.')
+                    || (ch >= 'a' && ch <= 'z')) {
+                    /* such characters are not expected to be encoded via
+                     * octal representation. The encoding is invalid. */
+                    return FALSE;
+                }
+                g_string_append_c(str_buffer, ch);
+                i += 4;
+                continue;
+            }
+            return FALSE;
+        }
+
+        return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index ea38e083..804034d2 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -3551,4 +3551,9 @@ void nm_utils_poll(int                               poll_timeout_ms,
 
 gboolean nm_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **error);
 
+/*****************************************************************************/
+
+void     nm_utils_env_var_encode_name(const char *key, GString *str_buffer);
+gboolean nm_utils_env_var_decode_name(const char *name, GString *str_buffer);
+
 #endif /* __NM_SHARED_UTILS_H__ */
diff --git a/src/libnm-platform/devlink/nm-devlink.c b/src/libnm-platform/devlink/nm-devlink.c
new file mode 100644
index 00000000..f06697cf
--- /dev/null
+++ b/src/libnm-platform/devlink/nm-devlink.c
@@ -0,0 +1,365 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024 Red Hat, Inc.
+ */
+
+#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
+
+#include "nm-devlink.h"
+
+#include <linux/if.h>
+#include <linux/devlink.h>
+
+#include "libnm-log-core/nm-logging.h"
+#include "libnm-platform/nm-netlink.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nm-platform-utils.h"
+
+#define _NMLOG_PREFIX_NAME "devlink"
+#define _NMLOG_DOMAIN      LOGD_PLATFORM | LOGD_DEVICE
+#define _NMLOG(level, ...)                                                                        \
+    G_STMT_START                                                                                  \
+    {                                                                                             \
+        char        _ifname_buf[IFNAMSIZ];                                                        \
+        const char *_ifname = self ? nmp_utils_if_indextoname(self->ifindex, _ifname_buf) : NULL; \
+                                                                                                  \
+        nm_log((level),                                                                           \
+               _NMLOG_DOMAIN,                                                                     \
+               _ifname ?: NULL,                                                                   \
+               NULL,                                                                              \
+               "%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),                                   \
+               _NMLOG_PREFIX_NAME,                                                                \
+               NM_PRINT_FMT_QUOTED(_ifname, " (", _ifname, ")", "")                               \
+                   _NM_UTILS_MACRO_REST(__VA_ARGS__));                                            \
+    }                                                                                             \
+    G_STMT_END
+
+#define CB_RESULT_PENDING 0
+#define CB_RESULT_OK      1
+
+struct _NMDevlink {
+    NMPlatform     *plat;
+    struct nl_sock *genl_sock_sync;
+    guint16         genl_family_id;
+    int             ifindex;
+};
+
+/**
+ * nm_devlink_new:
+ * @platform: the #NMPlatform that will use this #NMDevlink instance
+ * @genl_sock_sync: the netlink socket (will be used synchronously)
+ * @ifindex: the kernel's netdev ifindex corresponding to the devlink device
+ *
+ * Create a new #NMDevlink instance to make devlink queries regarding a specific
+ * device.
+ *
+ * Returns: (transfer full): the allocated new #NMDevlink
+ */
+NMDevlink *
+nm_devlink_new(NMPlatform *platform, struct nl_sock *genl_sock_sync, int ifindex)
+{
+    NMDevlink *self = g_new(NMDevlink, 1);
+
+    self->plat           = platform;
+    self->genl_sock_sync = genl_sock_sync;
+    self->genl_family_id = nm_platform_genl_get_family_id(platform, NMP_GENL_FAMILY_TYPE_DEVLINK);
+    self->ifindex        = ifindex;
+    return self;
+}
+
+/**
+ * nm_devlink_get_dev_identifier:
+ * @self: the #NMDevlink
+ * @out_bus: (out): the "bus_name" part of the devlink device identifier
+ * @out_addr: (out): the "bus_addr" part of the devlink device identifier
+ * @error: (optional): the error location
+ *
+ * Get the devlink device identifier of the device for which the #NMDevlink was
+ * created (with the @ifindex argument of nm_devlink_get_new()). A devlink device
+ * is identified as "bus_name/bus_addr" (i.e. "pci/0000:65:00.0"). This function
+ * provides both parts separately.
+ *
+ * Note that here we only get the potential devlink device identifier. The real devlink
+ * device might not even exist if the hw doesn't implement devlink or the netdev
+ * doesn't have a 1-1 corresponding devlink device (i.e. because it's a VF or
+ * because the hw uses a "one eswitch for many ports" model).
+ *
+ * Also note that currently only PCI devices are supported, an error will be
+ * returned for other kind of devices.
+ *
+ * Returns: FALSE in case of error, TRUE otherwise
+ */
+gboolean
+nm_devlink_get_dev_identifier(NMDevlink *self, char **out_bus, char **out_addr, GError **error)
+{
+    const char               *bus;
+    char                      sbuf[IFNAMSIZ];
+    NMPUtilsEthtoolDriverInfo ethtool_driver_info;
+
+    nm_assert(out_bus != NULL && out_addr != NULL);
+    nm_assert(!error || !*error);
+
+    if (!nm_platform_link_get_udev_property(self->plat, self->ifindex, "ID_BUS", &bus)) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "Can't get udev info for device '%s'",
+                    nmp_utils_if_indextoname(self->ifindex, sbuf));
+        return FALSE;
+    }
+
+    if (!nm_streq0(bus, "pci")) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "Devlink is only supported for PCI but device '%s' has bus name '%s'",
+                    nmp_utils_if_indextoname(self->ifindex, sbuf),
+                    bus);
+        return FALSE;
+    }
+
+    if (!nmp_utils_ethtool_get_driver_info(self->ifindex, &ethtool_driver_info)) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "Can't get ethtool driver info for device '%s'",
+                    nmp_utils_if_indextoname(self->ifindex, sbuf));
+        return FALSE;
+    }
+
+    *out_bus  = g_strdup("pci");
+    *out_addr = g_strdup(ethtool_driver_info._private_bus_info);
+    return TRUE;
+}
+
+static struct nl_msg *
+devlink_alloc_msg(NMDevlink *self, uint8_t cmd, uint16_t flags)
+{
+    nm_auto_nlmsg struct nl_msg *msg = nlmsg_alloc(0);
+    if (!msg)
+        return NULL;
+
+    genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, self->genl_family_id, 0, flags, cmd, 0);
+    return g_steal_pointer(&msg);
+}
+
+static int
+ack_cb_handler(const struct nl_msg *msg, void *data)
+{
+    int *result = data;
+    *result     = CB_RESULT_OK;
+    return NL_STOP;
+}
+
+static int
+finish_cb_handler(const struct nl_msg *msg, void *data)
+{
+    int *result = data;
+    *result     = CB_RESULT_OK;
+    return NL_SKIP;
+}
+
+static int
+err_cb_handler(const struct sockaddr_nl *nla, const struct nlmsgerr *err, void *data)
+{
+    void      **args       = data;
+    NMDevlink  *self       = args[0];
+    int        *result     = args[1];
+    char      **err_msg    = args[2];
+    const char *extack_msg = NULL;
+
+    *result = err->error;
+    nlmsg_parse_error(nlmsg_undata(err), &extack_msg);
+
+    _LOGT("error response (%d - %s)", err->error, extack_msg ?: nm_strerror(err->error));
+
+    if (err_msg)
+        *err_msg = g_strdup(extack_msg ?: nm_strerror(err->error));
+
+    return NL_SKIP;
+}
+
+static int
+devlink_send_and_recv(NMDevlink     *self,
+                      struct nl_msg *msg,
+                      int (*valid_handler)(const struct nl_msg *, void *),
+                      void  *valid_data,
+                      char **err_msg)
+{
+    int                nle;
+    int                cb_result = CB_RESULT_PENDING;
+    void              *err_arg[] = {self, &cb_result, err_msg};
+    const struct nl_cb cb        = {
+               .err_cb     = err_cb_handler,
+               .err_arg    = err_arg,
+               .finish_cb  = finish_cb_handler,
+               .finish_arg = &cb_result,
+               .ack_cb     = ack_cb_handler,
+               .ack_arg    = &cb_result,
+               .valid_cb   = valid_handler,
+               .valid_arg  = valid_data,
+    };
+
+    g_return_val_if_fail(msg != NULL, -ENOMEM);
+
+    if (err_msg)
+        *err_msg = NULL;
+
+    nle = nl_send_auto(self->genl_sock_sync, msg);
+    if (nle < 0)
+        goto out;
+
+    while (cb_result == CB_RESULT_PENDING) {
+        nle = nl_recvmsgs(self->genl_sock_sync, &cb);
+        if (nle < 0 && nle != -EAGAIN) {
+            _LOGW("nl_recvmsgs() error (%d - %s)", nle, nm_strerror(nle));
+            break;
+        }
+    }
+
+out:
+    if (nle < 0 && err_msg && *err_msg == NULL)
+        *err_msg = strdup(nm_strerror(nle));
+
+    if (nle >= 0 && cb_result < 0)
+        nle = cb_result;
+    return nle;
+}
+
+static int
+devlink_parse_eswitch_mode(const struct nl_msg *msg, void *data)
+{
+    static const struct nla_policy eswitch_policy[] = {
+        [DEVLINK_ATTR_ESWITCH_MODE]        = {.type = NLA_U16},
+        [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = {.type = NLA_U8},
+        [DEVLINK_ATTR_ESWITCH_ENCAP_MODE]  = {.type = NLA_U8},
+    };
+    NMDevlinkEswitchParams *params = data;
+    struct genlmsghdr      *gnlh   = nlmsg_data(nlmsg_hdr(msg));
+    struct nlattr          *tb[G_N_ELEMENTS(eswitch_policy)];
+    struct nlattr          *nla;
+
+    if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), eswitch_policy) < 0)
+        return NL_SKIP;
+
+    nla          = tb[DEVLINK_ATTR_ESWITCH_MODE];
+    params->mode = nla ? (_NMSriovEswitchMode) nla_get_u16(nla) : _NM_SRIOV_ESWITCH_MODE_UNKNOWN;
+
+    nla = tb[DEVLINK_ATTR_ESWITCH_INLINE_MODE];
+    params->inline_mode =
+        nla ? (_NMSriovEswitchInlineMode) nla_get_u8(nla) : _NM_SRIOV_ESWITCH_INLINE_MODE_UNKNOWN;
+
+    nla = tb[DEVLINK_ATTR_ESWITCH_ENCAP_MODE];
+    params->encap_mode =
+        nla ? (_NMSriovEswitchEncapMode) nla_get_u8(nla) : _NM_SRIOV_ESWITCH_ENCAP_MODE_UNKNOWN;
+
+    return NL_OK;
+}
+
+/*
+ * nm_devlink_get_eswitch_params:
+ * @self: the #NMDevlink
+ * @out_params: the eswitch parameters read via Devlink
+ * @error: the error location
+ *
+ * Get the eswitch configuration of the device related to the #NMDevlink instance. Note
+ * that this might be unsupported by the device (see nm_devlink_get_dev()).
+ *
+ * Returns: FALSE in case of error, TRUE otherwise
+ */
+gboolean
+nm_devlink_get_eswitch_params(NMDevlink *self, NMDevlinkEswitchParams *out_params, GError **error)
+{
+    nm_auto_nlmsg struct nl_msg *msg     = NULL;
+    gs_free char                *bus     = NULL;
+    gs_free char                *addr    = NULL;
+    gs_free char                *err_msg = NULL;
+    int                          rc;
+
+    nm_assert(out_params);
+
+    if (!nm_devlink_get_dev_identifier(self, &bus, &addr, error))
+        return FALSE;
+
+    msg = devlink_alloc_msg(self, DEVLINK_CMD_ESWITCH_GET, 0);
+    NLA_PUT_STRING(msg, DEVLINK_ATTR_BUS_NAME, bus);
+    NLA_PUT_STRING(msg, DEVLINK_ATTR_DEV_NAME, addr);
+
+    rc = devlink_send_and_recv(self, msg, devlink_parse_eswitch_mode, out_params, &err_msg);
+    if (rc < 0) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "devlink: eswitch get failed (%d - %s)",
+                    rc,
+                    err_msg);
+        return FALSE;
+    }
+
+    _LOGD("eswitch get success");
+
+    return TRUE;
+
+nla_put_failure:
+    g_return_val_if_reached(FALSE);
+}
+
+/*
+ * nm_devlink_set_eswitch_params:
+ * @self: the #NMDevlink
+ * @params: the eswitch parameters to set
+ * @error: the error location
+ *
+ * Set the eswitch configuration of the device related to the #NMDevlink instance. Note
+ * that this might be unsupported by the device (see nm_devlink_get_dev()).
+ *
+ * If any of the eswitch parameters is set to "preserve" it won't be modified.
+ *
+ * Returns: FALSE in case of error, TRUE otherwise
+ */
+gboolean
+nm_devlink_set_eswitch_params(NMDevlink *self, NMDevlinkEswitchParams params, GError **error)
+{
+    nm_auto_nlmsg struct nl_msg *msg     = NULL;
+    gs_free char                *bus     = NULL;
+    gs_free char                *addr    = NULL;
+    gs_free char                *err_msg = NULL;
+    int                          rc;
+
+    if (params.mode == _NM_SRIOV_ESWITCH_MODE_PRESERVE
+        && params.inline_mode == _NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE
+        && params.encap_mode == _NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE)
+        return TRUE;
+
+    if (!nm_devlink_get_dev_identifier(self, &bus, &addr, error))
+        return FALSE;
+
+    msg = devlink_alloc_msg(self, DEVLINK_CMD_ESWITCH_SET, 0);
+    NLA_PUT_STRING(msg, DEVLINK_ATTR_BUS_NAME, bus);
+    NLA_PUT_STRING(msg, DEVLINK_ATTR_DEV_NAME, addr);
+
+    if (params.mode != _NM_SRIOV_ESWITCH_MODE_PRESERVE)
+        NLA_PUT_U16(msg, DEVLINK_ATTR_ESWITCH_MODE, params.mode);
+    if (params.inline_mode != _NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE)
+        NLA_PUT_U8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, params.inline_mode);
+    if (params.encap_mode != _NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE)
+        NLA_PUT_U8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, params.encap_mode);
+
+    rc = devlink_send_and_recv(self, msg, NULL, NULL, &err_msg);
+    if (rc < 0) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "devlink: eswitch set failed (%d - %s)",
+                    rc,
+                    err_msg);
+        return FALSE;
+    }
+
+    _LOGD("eswitch set success");
+
+    return TRUE;
+
+nla_put_failure:
+    g_return_val_if_reached(FALSE);
+}
diff --git a/src/libnm-platform/devlink/nm-devlink.h b/src/libnm-platform/devlink/nm-devlink.h
new file mode 100644
index 00000000..c626a120
--- /dev/null
+++ b/src/libnm-platform/devlink/nm-devlink.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024 Red Hat, Inc.
+ */
+
+#ifndef __NMP_DEVLINK_H__
+#define __NMP_DEVLINK_H__
+
+#include "libnm-base/nm-base.h"
+#include <linux/devlink.h>
+
+struct nl_sock;
+typedef struct _NMPlatform NMPlatform;
+typedef struct _NMDevlink  NMDevlink;
+
+typedef struct {
+    _NMSriovEswitchMode       mode;
+    _NMSriovEswitchInlineMode inline_mode;
+    _NMSriovEswitchEncapMode  encap_mode;
+} NMDevlinkEswitchParams;
+
+NMDevlink *nm_devlink_new(NMPlatform *platform, struct nl_sock *genl_sock_sync, int ifindex);
+gboolean
+nm_devlink_get_dev_identifier(NMDevlink *self, char **out_bus, char **out_addr, GError **error);
+gboolean
+nm_devlink_get_eswitch_params(NMDevlink *self, NMDevlinkEswitchParams *out_params, GError **error);
+gboolean
+nm_devlink_set_eswitch_params(NMDevlink *self, NMDevlinkEswitchParams params, GError **error);
+
+#endif /* __NMP_DEVLINK_H__ */
\ No newline at end of file
diff --git a/src/libnm-platform/meson.build b/src/libnm-platform/meson.build
index 696ca1a6..7b6ad042 100644
--- a/src/libnm-platform/meson.build
+++ b/src/libnm-platform/meson.build
@@ -12,6 +12,7 @@ libnm_platform = static_library(
     'nmp-netns.c',
     'nmp-object.c',
     'nmp-plobj.c',
+    'devlink/nm-devlink.c',
     'wifi/nm-wifi-utils-nl80211.c',
     'wifi/nm-wifi-utils.c',
     'wpan/nm-wpan-utils.c',
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index a7078280..9ecac2d9 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -41,6 +41,7 @@
 #include "libnm-platform/nm-netlink.h"
 #include "libnm-platform/nm-platform-utils.h"
 #include "libnm-platform/nmp-netns.h"
+#include "libnm-platform/devlink/nm-devlink.h"
 #include "libnm-platform/wifi/nm-wifi-utils-wext.h"
 #include "libnm-platform/wifi/nm-wifi-utils.h"
 #include "libnm-platform/wpan/nm-wpan-utils.h"
@@ -8881,141 +8882,394 @@ nla_put_failure:
     g_return_val_if_reached(FALSE);
 }
 
+static gint64
+sriov_read_sysctl_uint(NMPlatform *platform,
+                       int         dirfd,
+                       const char *ifname,
+                       const char *dev_file,
+                       GError    **error)
+{
+    const char *path;
+    gint64      val;
+
+    nm_assert(NM_STRLEN("device/%s") + strlen(dev_file));
+
+    path = nm_sprintf_bufa(256, "device/%s", dev_file);
+    val  = nm_platform_sysctl_get_int_checked(platform,
+                                             NMP_SYSCTL_PATHID_NETDIR_UNSAFE_A(dirfd, ifname, path),
+                                             10,
+                                             0,
+                                             G_MAXUINT,
+                                             -1);
+
+    if (val < 0) {
+        g_set_error(error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "couldn't read %s: %s",
+                    dev_file,
+                    nm_strerror_native(errno));
+        return -errno;
+    }
+
+    return val;
+}
+
+static gboolean
+sriov_set_autoprobe(NMPlatform  *platform,
+                    int          dirfd,
+                    const char  *ifname,
+                    NMOptionBool autoprobe,
+                    GError     **error)
+{
+    int current_autoprobe =
+        (int) sriov_read_sysctl_uint(platform, dirfd, ifname, "sriov_drivers_autoprobe", error);
+
+    if (current_autoprobe == -ENOENT) {
+        /* older kernel versions don't have this sysctl. Assume the value is "1". */
+        current_autoprobe = 1;
+        g_clear_error(error);
+    }
+
+    if (current_autoprobe < 0)
+        return FALSE;
+
+    if (autoprobe != NM_OPTION_BOOL_DEFAULT && current_autoprobe != autoprobe) {
+        if (!nm_platform_sysctl_set(
+                platform,
+                NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"),
+                autoprobe == 1 ? "1" : "0")) {
+            g_set_error(error,
+                        NM_UTILS_ERROR,
+                        NM_UTILS_ERROR_UNKNOWN,
+                        "couldn't set SR-IOV drivers-autoprobe to %d: %s",
+                        (int) autoprobe,
+                        nm_strerror_native(errno));
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+#define _SRIOV_ASYNC_MAX_STEPS 4
+
+typedef struct _SriovAsyncState {
+    NMPlatform           *platform;
+    int                   ifindex;
+    NMPlatformSriovParams sriov_params;
+    void (*steps[_SRIOV_ASYNC_MAX_STEPS])(struct _SriovAsyncState *);
+    int                     current_step;
+    NMPlatformAsyncCallback callback;
+    gpointer                data;
+    GCancellable           *cancellable;
+} SriovAsyncState;
+
 static void
-sriov_idle_cb(gpointer user_data, GCancellable *cancellable)
+sriov_async_invoke_callback(gpointer user_data, GCancellable *cancellable)
 {
-    gs_unref_object NMPlatform *platform        = NULL;
-    gs_free_error GError       *cancelled_error = NULL;
-    gs_free_error GError       *error           = NULL;
-    NMPlatformAsyncCallback     callback;
-    gpointer                    callback_data;
+    gs_free_error GError   *cancelled_error = NULL;
+    gs_free_error GError   *error           = NULL;
+    NMPlatformAsyncCallback callback;
+    gpointer                callback_data;
 
     g_cancellable_set_error_if_cancelled(cancellable, &cancelled_error);
-    nm_utils_user_data_unpack(user_data, &platform, &error, &callback, &callback_data);
+    nm_utils_user_data_unpack(user_data, &error, &callback, &callback_data);
     callback(cancelled_error ?: error, callback_data);
 }
 
 static void
+sriov_async_finish_err(SriovAsyncState *async_state, GError *error)
+{
+    NMPlatform *platform = async_state->platform;
+
+    _LOGD("finished configuring SR-IOV, error: %s", error ? error->message : "none");
+
+    if (async_state->callback) {
+        /* nm_platform_link_set_sriov_params() promises to always call the callback,
+         * and always asynchronously. We might have reached here without doing
+         * any asynchronous task, so invoke the user's callback in the idle task
+         * to make it asynchronous. Actually, let's make it simple and do it
+         * always in this way, even if asynchronous tasks were made.
+         */
+        gpointer packed = nm_utils_user_data_pack(g_steal_pointer(&error),
+                                                  async_state->callback,
+                                                  async_state->data);
+        nm_utils_invoke_on_idle(async_state->cancellable, sriov_async_invoke_callback, packed);
+    }
+
+    g_object_unref(async_state->platform);
+    g_object_unref(async_state->cancellable);
+    g_free(async_state);
+    g_free(error);
+}
+
+static void
+sriov_async_call_next_step(SriovAsyncState *async_state)
+{
+    if (g_cancellable_is_cancelled(async_state->cancellable)) {
+        sriov_async_finish_err(async_state, NULL); /* The error will be set later */
+        return;
+    }
+
+    async_state->current_step++;
+
+    nm_assert(async_state->current_step >= 0);
+    nm_assert(async_state->current_step < _SRIOV_ASYNC_MAX_STEPS);
+    nm_assert(async_state->steps[async_state->current_step] != NULL);
+
+    async_state->steps[async_state->current_step](async_state);
+}
+
+static void
+sriov_async_sysctl_done_cb(GError *error, gpointer data)
+{
+    SriovAsyncState *async_state = data;
+
+    if (error)
+        sriov_async_finish_err(async_state, g_error_copy(error));
+    else
+        sriov_async_call_next_step(async_state);
+}
+
+static void
+sriov_async_set_num_vfs(SriovAsyncState *async_state, const char *val)
+{
+    NMPlatform           *platform = async_state->platform;
+    const char           *values[] = {val, NULL};
+    nm_auto_close int     dirfd    = -1;
+    char                  ifname[IFNAMSIZ];
+    gs_free_error GError *error = NULL;
+
+    dirfd = nm_platform_sysctl_open_netdir(platform, async_state->ifindex, ifname);
+    if (!dirfd) {
+        g_set_error(&error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "couldn't open netdir for device with ifindex %d",
+                    async_state->ifindex);
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
+    }
+
+    sysctl_set_async(platform,
+                     NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_numvfs"),
+                     values,
+                     sriov_async_sysctl_done_cb,
+                     async_state,
+                     async_state->cancellable);
+}
+
+static void
+sriov_async_step1_destroy_vfs(SriovAsyncState *async_state)
+{
+    NMPlatform *platform = async_state->platform;
+
+    _LOGD("destroying VFs before configuring SR-IOV");
+
+    sriov_async_set_num_vfs(async_state, "0");
+}
+
+static void
+sriov_async_step2_set_eswitch_mode(SriovAsyncState *async_state)
+{
+    NMPlatform             *platform       = async_state->platform;
+    NMLinuxPlatformPrivate *priv           = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
+    gs_free NMDevlink      *devlink        = NULL;
+    gs_free_error GError   *error          = NULL;
+    NMDevlinkEswitchParams  eswitch_params = {
+         .mode        = async_state->sriov_params.eswitch_mode,
+         .inline_mode = async_state->sriov_params.eswitch_inline_mode,
+         .encap_mode  = async_state->sriov_params.eswitch_encap_mode,
+    };
+
+    _LOGD("setting eswitch params (mode=%d, inline-mode=%d, encap-mode=%d)",
+          (int) eswitch_params.mode,
+          (int) eswitch_params.inline_mode,
+          (int) eswitch_params.encap_mode);
+
+    /* We set eswitch mode as a sriov_async step because it's in the middle of
+     * other steps that are async. However, this step itself is synchronous. */
+    devlink = nm_devlink_new(platform, priv->sk_genl_sync, async_state->ifindex);
+    if (!nm_devlink_set_eswitch_params(devlink, eswitch_params, &error)) {
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
+    }
+
+    sriov_async_call_next_step(async_state);
+}
+
+static void
+sriov_async_step3_create_vfs(SriovAsyncState *async_state)
+{
+    NMPlatform *platform = async_state->platform;
+    const char *val      = nm_sprintf_bufa(32, "%u", async_state->sriov_params.num_vfs);
+
+    _LOGD("setting sriov_numvfs to %u", async_state->sriov_params.num_vfs);
+
+    sriov_async_set_num_vfs(async_state, val);
+}
+
+static void
+sriov_async_step_finish_ok(SriovAsyncState *async_state)
+{
+    sriov_async_finish_err(async_state, NULL);
+}
+
+static int
+sriov_eswitch_get_needs_change(SriovAsyncState *async_state,
+                               gboolean        *out_needs_change,
+                               GError         **error)
+{
+    NMPlatform               *platform    = async_state->platform;
+    NMLinuxPlatformPrivate   *priv        = NM_LINUX_PLATFORM_GET_PRIVATE(platform);
+    _NMSriovEswitchMode       mode        = async_state->sriov_params.eswitch_mode;
+    _NMSriovEswitchInlineMode inline_mode = async_state->sriov_params.eswitch_inline_mode;
+    _NMSriovEswitchEncapMode  encap_mode  = async_state->sriov_params.eswitch_encap_mode;
+    NMDevlinkEswitchParams    current_params;
+    gs_free NMDevlink        *devlink = NULL;
+
+    nm_assert(out_needs_change);
+
+    if (mode == _NM_SRIOV_ESWITCH_MODE_PRESERVE
+        && inline_mode == _NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE
+        && encap_mode == _NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE) {
+        *out_needs_change = FALSE;
+        return 0;
+    }
+
+    devlink = nm_devlink_new(platform, priv->sk_genl_sync, async_state->ifindex);
+
+    if (!nm_devlink_get_eswitch_params(devlink, &current_params, error))
+        return -1;
+
+    *out_needs_change = (mode != _NM_SRIOV_ESWITCH_MODE_PRESERVE && mode != current_params.mode)
+                        || (inline_mode != _NM_SRIOV_ESWITCH_INLINE_MODE_PRESERVE
+                            && inline_mode != current_params.inline_mode)
+                        || (encap_mode != _NM_SRIOV_ESWITCH_ENCAP_MODE_PRESERVE
+                            && encap_mode != current_params.encap_mode);
+    return 0;
+}
+
+/*
+ * Take special care when setting new values:
+ *  - don't touch anything if the right values are already set
+ *  - to change the number of VFs, eswitch mode or autoprobe we need to destroy existing VFs
+ *  - the autoprobe setting is irrelevant when numvfs is zero
+ */
+static void
 link_set_sriov_params_async(NMPlatform             *platform,
                             int                     ifindex,
-                            guint                   num_vfs,
-                            NMOptionBool            autoprobe,
+                            NMPlatformSriovParams   sriov_params,
                             NMPlatformAsyncCallback callback,
                             gpointer                data,
                             GCancellable           *cancellable)
 {
+    SriovAsyncState            *async_state;
     nm_auto_pop_netns NMPNetns *netns = NULL;
     gs_free_error GError       *error = NULL;
     nm_auto_close int           dirfd = -1;
-    int                         current_autoprobe;
-    guint                       i, total;
-    gint64                      current_num;
     char                        ifname[IFNAMSIZ];
-    gpointer                    packed;
-    const char                 *values[3];
-    char                        buf[64];
+    int                         max_vfs;
+    int                         current_num_vfs;
+    gboolean                    need_change_eswitch_params;
+    gboolean                    need_change_vfs;
+    gboolean                    need_destroy_vfs;
+    gboolean                    need_create_vfs;
+    int                         i;
 
     g_return_if_fail(callback || !data);
     g_return_if_fail(cancellable);
 
+    async_state               = g_new0(SriovAsyncState, 1);
+    async_state->platform     = g_object_ref(platform);
+    async_state->ifindex      = ifindex;
+    async_state->sriov_params = sriov_params;
+    async_state->current_step = -1;
+    async_state->callback     = callback;
+    async_state->data         = data;
+    async_state->cancellable  = g_object_ref(cancellable);
+
     if (!nm_platform_netns_push(platform, &netns)) {
         g_set_error_literal(&error,
                             NM_UTILS_ERROR,
                             NM_UTILS_ERROR_UNKNOWN,
-                            "couldn't change namespace");
-        goto out_idle;
+                            "couldn't change network namespace");
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
     }
 
     dirfd = nm_platform_sysctl_open_netdir(platform, ifindex, ifname);
     if (!dirfd) {
-        g_set_error_literal(&error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "couldn't open netdir");
-        goto out_idle;
+        g_set_error(&error,
+                    NM_UTILS_ERROR,
+                    NM_UTILS_ERROR_UNKNOWN,
+                    "couldn't open netdir for device with ifindex %d",
+                    ifindex);
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
     }
 
-    total = nm_platform_sysctl_get_int_checked(
-        platform,
-        NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_totalvfs"),
-        10,
-        0,
-        G_MAXUINT,
-        0);
-    if (!errno && num_vfs > total) {
-        _LOGW("link: %d only supports %u VFs (requested %u)", ifindex, total, num_vfs);
-        num_vfs = total;
+    current_num_vfs = sriov_read_sysctl_uint(platform, dirfd, ifname, "sriov_numvfs", &error);
+    if (current_num_vfs < 0) {
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
     }
 
-    /*
-     * Take special care when setting new values:
-     *  - don't touch anything if the right values are already set
-     *  - to change the number of VFs or autoprobe we need to destroy existing VFs
-     *  - the autoprobe setting is irrelevant when numvfs is zero
-     */
-    current_num = nm_platform_sysctl_get_int_checked(
-        platform,
-        NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_numvfs"),
-        10,
-        0,
-        G_MAXUINT,
-        -1);
-    current_autoprobe = nm_platform_sysctl_get_int_checked(
-        platform,
-        NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"),
-        10,
-        0,
-        1,
-        -1);
-
-    if (current_autoprobe == -1 && errno == ENOENT) {
-        /* older kernel versions don't have this sysctl. Assume the value is
-         * "1". */
-        current_autoprobe = 1;
+    max_vfs = sriov_read_sysctl_uint(platform, dirfd, ifname, "sriov_totalvfs", &error);
+    if (max_vfs < 0) {
+        _LOGD("link: can't read max VFs (%s)", error->message);
+        g_clear_error(&error);
+        max_vfs = sriov_params.num_vfs; /* Try to create all */
     }
 
-    if (current_num == num_vfs
-        && (autoprobe == NM_OPTION_BOOL_DEFAULT || current_autoprobe == autoprobe))
-        goto out_idle;
+    if (sriov_params.num_vfs > max_vfs) {
+        _LOGW("link: device %d only supports %u VFs (requested %u)",
+              ifindex,
+              max_vfs,
+              sriov_params.num_vfs);
+        _LOGW("link: reducing num_vfs to %u for device %d", max_vfs, ifindex);
+        sriov_params.num_vfs              = max_vfs;
+        async_state->sriov_params.num_vfs = max_vfs;
+    }
 
-    if (NM_IN_SET(autoprobe, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE)
-        && current_autoprobe != autoprobe
-        && !nm_platform_sysctl_set(
-            platform,
-            NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_drivers_autoprobe"),
-            nm_sprintf_buf(buf, "%d", (int) autoprobe))) {
-        g_set_error(&error,
-                    NM_UTILS_ERROR,
-                    NM_UTILS_ERROR_UNKNOWN,
-                    "couldn't set SR-IOV drivers-autoprobe to %d: %s",
-                    (int) autoprobe,
-                    nm_strerror_native(errno));
-        goto out_idle;
+    /* Setting autoprobe goes first, we can do it synchronously */
+    if (sriov_params.num_vfs > 0
+        && !sriov_set_autoprobe(platform, dirfd, ifname, sriov_params.autoprobe, &error)) {
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
     }
 
-    if (current_num == 0 && num_vfs == 0)
-        goto out_idle;
+    /* Decide what actions we must do. Note that we might need to destroy the VFs even
+     * if num_vfs == current_num_vfs, for example to change the eswitch mode. Because of
+     * that, we might need to create VFs even if num_vfs == current_num_vfs.
+     * Steps in order (unnecessary steps are skipped):
+     *   1. Destroy VFs
+     *   2. Set eswitch mode
+     *   3. Create VFs
+     *   4. Invoke caller's callback
+     */
+    if (sriov_eswitch_get_needs_change(async_state, &need_change_eswitch_params, &error) < 0) {
+        sriov_async_finish_err(async_state, g_steal_pointer(&error));
+        return;
+    }
+    need_change_vfs  = sriov_params.num_vfs != current_num_vfs;
+    need_destroy_vfs = current_num_vfs > 0 && (need_change_eswitch_params || need_change_vfs);
+    need_create_vfs  = (current_num_vfs == 0 || need_destroy_vfs) && sriov_params.num_vfs > 0;
 
     i = 0;
-    if (current_num != 0)
-        values[i++] = "0";
-    if (num_vfs != 0)
-        values[i++] = nm_sprintf_bufa(32, "%u", num_vfs);
-    values[i++] = NULL;
+    if (need_destroy_vfs)
+        async_state->steps[i++] = sriov_async_step1_destroy_vfs;
+    if (need_change_eswitch_params)
+        async_state->steps[i++] = sriov_async_step2_set_eswitch_mode;
+    if (need_create_vfs)
+        async_state->steps[i++] = sriov_async_step3_create_vfs;
 
-    sysctl_set_async(platform,
-                     NMP_SYSCTL_PATHID_NETDIR_A(dirfd, ifname, "device/sriov_numvfs"),
-                     values,
-                     callback,
-                     data,
-                     cancellable);
-    return;
-
-out_idle:
-    if (callback) {
-        packed = nm_utils_user_data_pack(g_object_ref(platform),
-                                         g_steal_pointer(&error),
-                                         callback,
-                                         data);
-        nm_utils_invoke_on_idle(cancellable, sriov_idle_cb, packed);
-    }
+    nm_assert(i < _SRIOV_ASYNC_MAX_STEPS);
+
+    async_state->steps[i] = sriov_async_step_finish_ok;
+
+    sriov_async_call_next_step(async_state);
 }
 
 static gboolean
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 1411fe9e..b89b0359 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -452,6 +452,10 @@ _nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value)
 /*****************************************************************************/
 
 const NMPGenlFamilyInfo nmp_genl_family_infos[_NMP_GENL_FAMILY_TYPE_NUM] = {
+    [NMP_GENL_FAMILY_TYPE_DEVLINK] =
+        {
+            .name = "devlink",
+        },
     [NMP_GENL_FAMILY_TYPE_ETHTOOL] =
         {
             .name = "ethtool",
@@ -2018,8 +2022,7 @@ nm_platform_link_supports_sriov(NMPlatform *self, int ifindex)
 void
 nm_platform_link_set_sriov_params_async(NMPlatform             *self,
                                         int                     ifindex,
-                                        guint                   num_vfs,
-                                        NMOptionBool            autoprobe,
+                                        NMPlatformSriovParams   sriov_params,
                                         NMPlatformAsyncCallback callback,
                                         gpointer                callback_data,
                                         GCancellable           *cancellable)
@@ -2028,11 +2031,17 @@ nm_platform_link_set_sriov_params_async(NMPlatform             *self,
 
     g_return_if_fail(ifindex > 0);
 
-    _LOG3D("link: setting %u total VFs and autoprobe %d", num_vfs, (int) autoprobe);
+    _LOG3D("link: setting SR-IOV params (numvfs=%u, autoprobe=%d, eswitch mode=%d inline-mode=%d "
+           "encap-mode=%d)",
+           sriov_params.num_vfs,
+           (int) sriov_params.autoprobe,
+           (int) sriov_params.eswitch_mode,
+           (int) sriov_params.eswitch_inline_mode,
+           (int) sriov_params.eswitch_encap_mode);
+
     klass->link_set_sriov_params_async(self,
                                        ifindex,
-                                       num_vfs,
-                                       autoprobe,
+                                       sriov_params,
                                        callback,
                                        callback_data,
                                        cancellable);
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index a6e60bd4..f6a6ba08 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -993,6 +993,14 @@ typedef struct {
     guint8  public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
 } _nm_alignas(NMPlatformObject) NMPlatformLnkWireGuard;
 
+typedef struct {
+    guint                     num_vfs;
+    NMOptionBool              autoprobe;
+    _NMSriovEswitchMode       eswitch_mode;
+    _NMSriovEswitchInlineMode eswitch_inline_mode;
+    _NMSriovEswitchEncapMode  eswitch_encap_mode;
+} NMPlatformSriovParams;
+
 typedef enum {
     NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE            = 0,
     NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS   = (1LL << 0),
@@ -1084,6 +1092,7 @@ nm_platform_kernel_support_get(NMPlatformKernelSupportType type)
 }
 
 typedef enum {
+    NMP_GENL_FAMILY_TYPE_DEVLINK,
     NMP_GENL_FAMILY_TYPE_ETHTOOL,
     NMP_GENL_FAMILY_TYPE_MPTCP_PM,
     NMP_GENL_FAMILY_TYPE_NL80211,
@@ -1171,8 +1180,7 @@ typedef struct {
     gboolean (*link_set_name)(NMPlatform *self, int ifindex, const char *name);
     void (*link_set_sriov_params_async)(NMPlatform             *self,
                                         int                     ifindex,
-                                        guint                   num_vfs,
-                                        NMOptionBool            autoprobe,
+                                        NMPlatformSriovParams   sriov_params,
                                         NMPlatformAsyncCallback callback,
                                         gpointer                callback_data,
                                         GCancellable           *cancellable);
@@ -2034,8 +2042,7 @@ gboolean nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *na
 
 void nm_platform_link_set_sriov_params_async(NMPlatform             *self,
                                              int                     ifindex,
-                                             guint                   num_vfs,
-                                             NMOptionBool            autoprobe,
+                                             NMPlatformSriovParams   sriov_params,
                                              NMPlatformAsyncCallback callback,
                                              gpointer                callback_data,
                                              GCancellable           *cancellable);
diff --git a/src/libnmc-base/nm-client-utils.c b/src/libnmc-base/nm-client-utils.c
index b052a307..30213e41 100644
--- a/src/libnmc-base/nm-client-utils.c
+++ b/src/libnmc-base/nm-client-utils.c
@@ -464,7 +464,9 @@ NM_UTILS_LOOKUP_STR_DEFINE(
     NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED,
                          N_("Failed to configure SR-IOV parameters")),
     NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_PEER_NOT_FOUND,
-                         N_("The Wi-Fi P2P peer could not be found")), );
+                         N_("The Wi-Fi P2P peer could not be found")),
+    NM_UTILS_LOOKUP_ITEM(NM_DEVICE_STATE_REASON_DEVICE_HANDLER_FAILED,
+                         N_("The device handler dispatcher returned an error")), );
 
 NM_UTILS_LOOKUP_STR_DEFINE(
     nm_active_connection_state_reason_to_string,
diff --git a/src/libnmc-base/nm-secret-agent-simple.c b/src/libnmc-base/nm-secret-agent-simple.c
index 1b9aa571..4bb77c98 100644
--- a/src/libnmc-base/nm-secret-agent-simple.c
+++ b/src/libnmc-base/nm-secret-agent-simple.c
@@ -170,6 +170,7 @@ _secret_real_new_plain(NMSecretAgentSecretType secret_type,
         .base.entry_id    = g_strdup_printf("%s.%s", nm_setting_get_name(setting), property),
         .base.value       = g_steal_pointer(&value),
         .base.is_secret   = (secret_type != NM_SECRET_AGENT_SECRET_TYPE_PROPERTY),
+        .base.force_echo  = FALSE,
         .setting          = g_object_ref(setting),
         .property         = g_strdup(property),
     };
@@ -180,7 +181,8 @@ static NMSecretAgentSimpleSecret *
 _secret_real_new_vpn_secret(const char *pretty_name,
                             NMSetting  *setting,
                             const char *property,
-                            const char *vpn_type)
+                            const char *vpn_type,
+                            gboolean    force_echo)
 {
     SecretReal *real;
     const char *value;
@@ -197,11 +199,12 @@ _secret_real_new_vpn_secret(const char *pretty_name,
         .base.pretty_name = g_strdup(pretty_name),
         .base.entry_id =
             g_strdup_printf("%s%s", NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS, property),
-        .base.value     = g_strdup(value),
-        .base.is_secret = TRUE,
-        .base.vpn_type  = g_strdup(vpn_type),
-        .setting        = g_object_ref(setting),
-        .property       = g_strdup(property),
+        .base.value      = g_strdup(value),
+        .base.is_secret  = TRUE,
+        .base.force_echo = force_echo,
+        .base.vpn_type   = g_strdup(vpn_type),
+        .setting         = g_object_ref(setting),
+        .property        = g_strdup(property),
     };
     return &real->base;
 }
@@ -227,6 +230,7 @@ _secret_real_new_wireguard_peer_psk(NMSettingWireGuard *s_wg,
         .base.value              = g_strdup(preshared_key),
         .base.is_secret          = TRUE,
         .base.no_prompt_entry_id = TRUE,
+        .base.force_echo         = FALSE,
         .setting                 = NM_SETTING(g_object_ref(s_wg)),
         .property                = g_strdup(public_key),
     };
@@ -388,7 +392,8 @@ static void
 add_vpn_secret_helper(GPtrArray    *secrets,
                       NMSettingVpn *s_vpn,
                       const char   *name,
-                      const char   *ui_name)
+                      const char   *ui_name,
+                      gboolean      force_echo)
 {
     NMSecretAgentSimpleSecret *secret;
     NMSettingSecretFlags       flags;
@@ -399,7 +404,8 @@ add_vpn_secret_helper(GPtrArray    *secrets,
         secret = _secret_real_new_vpn_secret(ui_name,
                                              NM_SETTING(s_vpn),
                                              name,
-                                             nm_setting_vpn_get_service_type(s_vpn));
+                                             nm_setting_vpn_get_service_type(s_vpn),
+                                             force_echo);
 
         /* Check for duplicates */
         for (i = 0; i < secrets->len; i++) {
@@ -408,6 +414,8 @@ add_vpn_secret_helper(GPtrArray    *secrets,
             if (s->secret_type == secret->secret_type && nm_streq0(s->vpn_type, secret->vpn_type)
                 && nm_streq0(s->entry_id, secret->entry_id)) {
                 _secret_real_free(secret);
+                if (!force_echo)
+                    s->force_echo = FALSE;
                 return;
             }
         }
@@ -416,8 +424,6 @@ add_vpn_secret_helper(GPtrArray    *secrets,
     }
 }
 
-#define VPN_MSG_TAG "x-vpn-message:"
-
 static gboolean
 add_vpn_secrets(RequestData *request, GPtrArray *secrets, char **msg)
 {
@@ -425,23 +431,44 @@ add_vpn_secrets(RequestData *request, GPtrArray *secrets, char **msg)
     const NmcVpnPasswordName *p;
     const char               *vpn_msg = NULL;
     char                    **iter;
+    char                     *secret_name;
+    bool                      is_challenge = FALSE;
+    bool                      force_echo;
 
     /* If hints are given, then always ask for what the hints require */
     if (request->hints) {
         for (iter = request->hints; *iter; iter++) {
-            if (!vpn_msg && g_str_has_prefix(*iter, VPN_MSG_TAG))
-                vpn_msg = &(*iter)[NM_STRLEN(VPN_MSG_TAG)];
-            else
-                add_vpn_secret_helper(secrets, s_vpn, *iter, *iter);
+            if (!vpn_msg && NM_STR_HAS_PREFIX(*iter, NM_SECRET_TAG_VPN_MSG)) {
+                vpn_msg = &(*iter)[NM_STRLEN(NM_SECRET_TAG_VPN_MSG)];
+            } else {
+                if (NM_STR_HAS_PREFIX(*iter, NM_SECRET_TAG_DYNAMIC_CHALLENGE)) {
+                    secret_name  = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE)];
+                    is_challenge = TRUE;
+                    force_echo   = FALSE;
+                } else if (NM_STR_HAS_PREFIX(*iter, NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)) {
+                    secret_name  = &(*iter)[NM_STRLEN(NM_SECRET_TAG_DYNAMIC_CHALLENGE_ECHO)];
+                    is_challenge = TRUE;
+                    force_echo   = TRUE;
+                } else {
+                    secret_name = *iter;
+                    force_echo  = FALSE;
+                }
+
+                add_vpn_secret_helper(secrets, s_vpn, secret_name, secret_name, force_echo);
+            }
         }
     }
 
     NM_SET_OUT(msg, g_strdup(vpn_msg));
 
+    /* If we are in the 2nd step of a 2FA authentication, don't ask again for the default secrets */
+    if (is_challenge)
+        return TRUE;
+
     /* Now add what client thinks might be required, because hints may be empty or incomplete */
     p = nm_vpn_get_secret_names(nm_setting_vpn_get_service_type(s_vpn));
     while (p && p->name) {
-        add_vpn_secret_helper(secrets, s_vpn, p->name, _(p->ui_name));
+        add_vpn_secret_helper(secrets, s_vpn, p->name, _(p->ui_name), FALSE);
         p++;
     }
 
@@ -596,6 +623,7 @@ _auth_dialog_exited(GPid pid, int status, gpointer user_data)
 
     for (i = 1; groups[i]; i++) {
         gs_free char *pretty_name = NULL;
+        gboolean      force_echo;
 
         if (!g_key_file_get_boolean(keyfile, groups[i], "IsSecret", NULL))
             continue;
@@ -603,11 +631,14 @@ _auth_dialog_exited(GPid pid, int status, gpointer user_data)
             continue;
 
         pretty_name = g_key_file_get_string(keyfile, groups[i], "Label", NULL);
+        force_echo  = g_key_file_get_boolean(keyfile, groups[i], "ForceEcho", NULL);
+
         g_ptr_array_add(secrets,
                         _secret_real_new_vpn_secret(pretty_name,
                                                     NM_SETTING(s_vpn),
                                                     groups[i],
-                                                    nm_setting_vpn_get_service_type(s_vpn)));
+                                                    nm_setting_vpn_get_service_type(s_vpn),
+                                                    force_echo));
     }
 
 out:
diff --git a/src/libnmc-base/nm-secret-agent-simple.h b/src/libnmc-base/nm-secret-agent-simple.h
index a1d15881..94197957 100644
--- a/src/libnmc-base/nm-secret-agent-simple.h
+++ b/src/libnmc-base/nm-secret-agent-simple.h
@@ -23,6 +23,7 @@ typedef struct {
     const char             *vpn_type;
     bool                    is_secret : 1;
     bool                    no_prompt_entry_id : 1;
+    bool                    force_echo : 1;
 } NMSecretAgentSimpleSecret;
 
 #define NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRETS "vpn.secrets."
diff --git a/src/libnmc-setting/nm-meta-setting-desc.c b/src/libnmc-setting/nm-meta-setting-desc.c
index 103b844e..2871ccb6 100644
--- a/src/libnmc-setting/nm-meta-setting-desc.c
+++ b/src/libnmc-setting/nm-meta-setting-desc.c
@@ -1073,7 +1073,6 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
 {
     GType                       gtype       = 0;
     const NMUtilsEnumValueInfo *value_infos = NULL;
-    gboolean                    has_gtype   = FALSE;
     nm_auto_unset_gvalue GValue gval        = G_VALUE_INIT;
     gint64                      v;
     gboolean                    format_numeric             = FALSE;
@@ -1087,13 +1086,6 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
 
     RETURN_UNSUPPORTED_GET_TYPE();
 
-    if (property_info->property_typ_data) {
-        if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
-            gtype     = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
-            has_gtype = TRUE;
-        }
-    }
-
     if (property_info->property_typ_data && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY
         && NM_FLAGS_ANY(property_info->property_typ_data->typ_flags,
                         NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC
@@ -1136,18 +1128,12 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
 
     nm_assert(format_text || format_numeric);
 
+    gtype = nm_meta_property_enum_get_type(property_info);
+    g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
+
     pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(setting), property_info->property_name);
     g_return_val_if_fail(pspec, NULL);
 
-    if (has_gtype) {
-        /* if the property is already enum, don't set get_gtype: it's redundant and error prone */
-        g_return_val_if_fail(NM_IN_SET(pspec->value_type, G_TYPE_INT, G_TYPE_UINT), FALSE);
-    } else {
-        gtype = pspec->value_type;
-    }
-
-    g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), NULL);
-
     g_value_init(&gval, pspec->value_type);
     g_object_get_property(G_OBJECT(setting), property_info->property_name, &gval);
     NM_SET_OUT(out_is_default, g_param_value_defaults(pspec, &gval));
@@ -1255,17 +1241,19 @@ nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
 GType
 nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info)
 {
-    GType gtype = _property_get_spec(property_info)->value_type;
+    GType setting_gtype = property_info->setting_info->general->get_setting_gtype();
+    GType prop_gtype =
+        nm_setting_get_enum_property_type(setting_gtype, property_info->property_name);
 
     if (property_info->property_typ_data
         && property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
         /* if the property is already enum, don't set get_gtype: it's redundant and error prone */
-        g_return_val_if_fail(NM_IN_SET(gtype, G_TYPE_INT, G_TYPE_UINT), G_TYPE_INVALID);
+        g_return_val_if_fail(prop_gtype == G_TYPE_INVALID, G_TYPE_INVALID);
         return property_info->property_typ_data->subtype.gobject_enum.get_gtype();
     }
 
-    g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), G_TYPE_INVALID);
-    return gtype;
+    g_return_val_if_fail(G_TYPE_IS_ENUM(prop_gtype) || G_TYPE_IS_FLAGS(prop_gtype), G_TYPE_INVALID);
+    return prop_gtype;
 }
 
 /**
@@ -1579,33 +1567,18 @@ _set_fcn_gobject_mac(ARGS_SET_FCN)
 static gboolean
 _set_fcn_gobject_enum(ARGS_SET_FCN)
 {
-    GType                       gtype = 0;
-    GType                       gtype_prop;
-    gboolean                    has_gtype = FALSE;
-    nm_auto_unset_gvalue GValue gval      = G_VALUE_INIT;
+    GType                       gtype;
+    GType                       gtype_gobj;
+    nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
     gboolean                    is_flags;
     int                         v;
 
     if (_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE(property_info, modifier, value))
         return _gobject_property_reset_default(setting, property_info->property_name);
 
-    if (property_info->property_typ_data) {
-        if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
-            gtype     = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
-            has_gtype = TRUE;
-        }
-    }
-
-    gtype_prop = _gobject_property_get_gtype(G_OBJECT(setting), property_info->property_name);
-
-    if (has_gtype) {
-        /* if the property is already enum, don't set get_gtype: it's redundant and error prone */
-        g_return_val_if_fail(NM_IN_SET(gtype_prop, G_TYPE_INT, G_TYPE_UINT), FALSE);
-    } else {
-        gtype = gtype_prop;
-    }
+    gtype = nm_meta_property_enum_get_type(property_info);
+    g_return_val_if_fail(gtype != G_TYPE_INVALID, FALSE);
 
-    g_return_val_if_fail(G_TYPE_IS_FLAGS(gtype) || G_TYPE_IS_ENUM(gtype), FALSE);
     is_flags = G_TYPE_IS_FLAGS(gtype);
 
     if (!_nm_utils_enum_from_str_full(
@@ -1641,10 +1614,12 @@ _set_fcn_gobject_enum(ARGS_SET_FCN)
             v = (int) (v_flag | ((guint) v));
     }
 
-    g_value_init(&gval, gtype_prop);
-    if (gtype_prop == G_TYPE_INT)
+    gtype_gobj = _gobject_property_get_gtype(G_OBJECT(setting), property_info->property_name);
+
+    g_value_init(&gval, gtype_gobj);
+    if (gtype_gobj == G_TYPE_INT)
         g_value_set_int(&gval, v);
-    else if (gtype_prop == G_TYPE_UINT)
+    else if (gtype_gobj == G_TYPE_UINT)
         g_value_set_uint(&gval, v);
     else if (is_flags)
         g_value_set_flags(&gval, v);
@@ -6011,6 +5986,15 @@ static const NMMetaPropertyInfo *const property_infos_ETHTOOL[] = {
 };
 
 #undef  _CURRENT_NM_META_SETTING_TYPE
+#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GENERIC
+static const NMMetaPropertyInfo *const property_infos_GENERIC[] = {
+    PROPERTY_INFO_WITH_DESC (NM_SETTING_GENERIC_DEVICE_HANDLER,
+        .property_type =                &_pt_gobject_string,
+    ),
+    NULL
+};
+
+#undef  _CURRENT_NM_META_SETTING_TYPE
 #define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GSM
 static const NMMetaPropertyInfo *const property_infos_GSM[] = {
     PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_AUTO_CONFIG,
@@ -6934,6 +6918,9 @@ static const NMMetaPropertyInfo *const property_infos_MACSEC[] = {
     PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_SEND_SCI,
         .property_type =                &_pt_gobject_bool,
     ),
+    PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_OFFLOAD,
+        .property_type =                &_pt_gobject_enum,
+    ),
     NULL
 };
 
@@ -7388,6 +7375,15 @@ static const NMMetaPropertyInfo *const property_infos_SRIOV[] = {
     PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS,
         .property_type =                &_pt_gobject_ternary,
     ),
+    PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_ESWITCH_MODE,
+        .property_type =                &_pt_gobject_enum,
+    ),
+    PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_ESWITCH_INLINE_MODE,
+        .property_type =                &_pt_gobject_enum,
+    ),
+    PROPERTY_INFO_WITH_DESC (NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE,
+        .property_type =                &_pt_gobject_enum,
+    ),
     NULL
 };
 
@@ -8795,7 +8791,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
             NM_META_SETTING_VALID_PART_ITEM (ETHTOOL,               FALSE),
         ),
     ),
-    SETTING_INFO_EMPTY (GENERIC,
+    SETTING_INFO (GENERIC,
         .valid_parts = NM_META_SETTING_VALID_PARTS (
             NM_META_SETTING_VALID_PART_ITEM (CONNECTION,            TRUE),
             NM_META_SETTING_VALID_PART_ITEM (GENERIC,               TRUE),
diff --git a/src/libnmc-setting/settings-docs.h b/src/libnmc-setting/settings-docs.h
index 854e925a..c4014166 100644
--- a/src/libnmc-setting/settings-docs.h
+++ b/src/libnmc-setting/settings-docs.h
@@ -140,6 +140,7 @@
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_ID N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.")
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.")
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.")
+#define DESCRIBE_DOC_NM_SETTING_GENERIC_DEVICE_HANDLER N_("Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'. See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler. By setting this property the generic connection becomes \"virtual\", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_APN N_("The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9. If the APN is unset (the default) then it may be detected based on \"auto-config\" setting. The property can be explicitly set to the empty string to prevent that and use no APN.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_AUTO_CONFIG N_("When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_DEVICE_ID N_("The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device.")
@@ -243,6 +244,7 @@
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK_FLAGS N_("Flags indicating how to handle the \"mka-cak\" property.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CKN N_("The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MODE N_("Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_OFFLOAD N_("Specifies the MACsec offload mode. \"off\" (0) disables MACsec offload. \"phy\" (1) and \"mac\" (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail. \"default\" (-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is \"off\" (0).")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_PORT N_("The port component of the SCI (Secure Channel Identifier), between 1 and 65534.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_SEND_SCI N_("Specifies whether the SCI (Secure Channel Identifier) is included in every packet.")
@@ -310,6 +312,9 @@
 #define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
 #define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port.  Either 1 or 2. The 1 in \"8n1\" for example.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to \"true\" (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to \"false\" (0), VFs will not be claimed and no network interfaces will be created for them. When set to \"default\" (-1), the global default is used; in case the global default is unspecified it is assumed to be \"true\" (1).")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE N_("Select the eswitch encapsulation support. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch encap-mode won't be modified by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_INLINE_MODE N_("Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch inline-mode won't be modified by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_MODE N_("Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch mode won't be modified by NetworkManager.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently, the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.")
 #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines. When the \"tc\" setting is present, qdiscs from this property are applied upon activation. If the property is empty, all qdiscs are removed and the device will only have the default qdisc assigned by kernel according to the \"net.core.default_qdisc\" sysctl. If the \"tc\" setting is not present, NetworkManager doesn't touch the qdiscs present on the interface.")
diff --git a/src/libnmc-setting/settings-docs.h.in b/src/libnmc-setting/settings-docs.h.in
index 854e925a..c4014166 100644
--- a/src/libnmc-setting/settings-docs.h.in
+++ b/src/libnmc-setting/settings-docs.h.in
@@ -140,6 +140,7 @@
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_GROUP_ID N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group.")
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH N_("An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group.")
 #define DESCRIBE_DOC_NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS N_("An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped.")
+#define DESCRIBE_DOC_NM_SETTING_GENERIC_DEVICE_HANDLER N_("Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and '-', '_', '.'. It cannot start with '.'. See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler. By setting this property the generic connection becomes \"virtual\", meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_APN N_("The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network.  The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9. If the APN is unset (the default) then it may be detected based on \"auto-config\" setting. The property can be explicitly set to the empty string to prevent that and use no APN.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_AUTO_CONFIG N_("When TRUE, the settings such as APN, username, or password will default to values that match the network the modem will register to in the Mobile Broadband Provider database.")
 #define DESCRIBE_DOC_NM_SETTING_GSM_DEVICE_ID N_("The device unique identifier (as given by the WWAN management service) which this connection applies to.  If given, the connection will only apply to the specified device.")
@@ -243,6 +244,7 @@
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CAK_FLAGS N_("Flags indicating how to handle the \"mka-cak\" property.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MKA_CKN N_("The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement. Must be a string of hexadecimal characters with a even length between 2 and 64.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_MODE N_("Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.")
+#define DESCRIBE_DOC_NM_SETTING_MACSEC_OFFLOAD N_("Specifies the MACsec offload mode. \"off\" (0) disables MACsec offload. \"phy\" (1) and \"mac\" (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail. \"default\" (-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is \"off\" (0).")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_PARENT N_("If given, specifies the parent interface name or parent connection UUID from which this MACSEC interface should be created.  If this property is not specified, the connection must contain an \"802-3-ethernet\" setting with a \"mac-address\" property.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_PORT N_("The port component of the SCI (Secure Channel Identifier), between 1 and 65534.")
 #define DESCRIBE_DOC_NM_SETTING_MACSEC_SEND_SCI N_("Specifies whether the SCI (Secure Channel Identifier) is included in every packet.")
@@ -310,6 +312,9 @@
 #define DESCRIBE_DOC_NM_SETTING_SERIAL_SEND_DELAY N_("Time to delay between each byte sent to the modem, in microseconds.")
 #define DESCRIBE_DOC_NM_SETTING_SERIAL_STOPBITS N_("Number of stop bits for communication on the serial port.  Either 1 or 2. The 1 in \"8n1\" for example.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_AUTOPROBE_DRIVERS N_("Whether to autoprobe virtual functions by a compatible driver. If set to \"true\" (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to \"false\" (0), VFs will not be claimed and no network interfaces will be created for them. When set to \"default\" (-1), the global default is used; in case the global default is unspecified it is assumed to be \"true\" (1).")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_ENCAP_MODE N_("Select the eswitch encapsulation support. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch encap-mode won't be modified by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_INLINE_MODE N_("Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch inline-mode won't be modified by NetworkManager.")
+#define DESCRIBE_DOC_NM_SETTING_SRIOV_ESWITCH_MODE N_("Select the eswitch mode of the device. Currently it's only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to \"preserve\" (-1) (default) the eswitch mode won't be modified by NetworkManager.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_TOTAL_VFS N_("The total number of virtual functions to create. Note that when the sriov setting is present NetworkManager enforces the number of virtual functions on the interface (also when it is zero) during activation and resets it upon deactivation. To prevent any changes to SR-IOV parameters don't add a sriov setting to the connection.")
 #define DESCRIBE_DOC_NM_SETTING_SRIOV_VFS N_("Array of virtual function descriptors. Each VF descriptor is a dictionary mapping attribute names to GVariant values. The 'index' entry is mandatory for each VF. When represented as string a VF is in the form: \"INDEX [ATTR=VALUE[ ATTR=VALUE]...]\". for example: \"2 mac=00:11:22:33:44:55 spoof-check=true\". Multiple VFs can be specified using a comma as separator. Currently, the following attributes are supported: mac, spoof-check, trust, min-tx-rate, max-tx-rate, vlans. The \"vlans\" attribute is represented as a semicolon-separated list of VLAN descriptors, where each descriptor has the form \"ID[.PRIORITY[.PROTO]]\". PROTO can be either 'q' for 802.1Q (the default) or 'ad' for 802.1ad.")
 #define DESCRIBE_DOC_NM_SETTING_TC_CONFIG_QDISCS N_("Array of TC queueing disciplines. When the \"tc\" setting is present, qdiscs from this property are applied upon activation. If the property is empty, all qdiscs are removed and the device will only have the default qdisc assigned by kernel according to the \"net.core.default_qdisc\" sysctl. If the \"tc\" setting is not present, NetworkManager doesn't touch the qdiscs present on the interface.")
diff --git a/src/nm-dispatcher/nm-dispatcher-utils.c b/src/nm-dispatcher/nm-dispatcher-utils.c
index f8a4c280..6659936f 100644
--- a/src/nm-dispatcher/nm-dispatcher-utils.c
+++ b/src/nm-dispatcher/nm-dispatcher-utils.c
@@ -540,6 +540,36 @@ nm_dispatcher_utils_construct_envp(const char  *action,
         _items_add_key0(items, NULL, "DEVICE_IP_IFACE", ip_iface);
     }
 
+    {
+        gs_unref_variant GVariant *user_setting = NULL;
+
+        user_setting = g_variant_lookup_value(connection_dict,
+                                              NM_SETTING_USER_SETTING_NAME,
+                                              NM_VARIANT_TYPE_SETTING);
+        if (user_setting) {
+            gs_unref_variant GVariant    *data   = NULL;
+            nm_auto_free_gstring GString *string = NULL;
+            GVariantIter                  iter;
+            const char                   *key;
+            const char                   *val;
+
+            data =
+                g_variant_lookup_value(user_setting, NM_SETTING_USER_DATA, G_VARIANT_TYPE("a{ss}"));
+            if (data) {
+                g_variant_iter_init(&iter, data);
+                while (g_variant_iter_next(&iter, "{&s&s}", &key, &val)) {
+                    if (key) {
+                        if (!string)
+                            string = g_string_sized_new(64);
+                        g_string_assign(string, "CONNECTION_USER_");
+                        nm_utils_env_var_encode_name(key, string);
+                        _items_add_key0(items, NULL, string->str, val);
+                    }
+                }
+            }
+        }
+    }
+
     /* Device items aren't valid if the device isn't activated */
     if (iface && dev_state == NM_DEVICE_STATE_ACTIVATED) {
         construct_proxy_items(items, device_proxy_props, NULL);
diff --git a/src/nm-dispatcher/nm-dispatcher.c b/src/nm-dispatcher/nm-dispatcher.c
index 97b85813..efb4ec00 100644
--- a/src/nm-dispatcher/nm-dispatcher.c
+++ b/src/nm-dispatcher/nm-dispatcher.c
@@ -20,6 +20,7 @@
 #include "libnm-core-aux-extern/nm-dispatcher-api.h"
 #include "libnm-glib-aux/nm-dbus-aux.h"
 #include "libnm-glib-aux/nm-io-utils.h"
+#include "libnm-glib-aux/nm-str-buf.h"
 #include "libnm-glib-aux/nm-time-utils.h"
 #include "nm-dispatcher-utils.h"
 
@@ -75,6 +76,10 @@ typedef struct {
     gboolean       dispatched;
     GSource       *watch_source;
     GSource       *timeout_source;
+
+    int      stdout_fd;
+    GSource *stdout_source;
+    NMStrBuf stdout_buffer;
 } ScriptInfo;
 
 struct Request {
@@ -85,6 +90,8 @@ struct Request {
     char                  *iface;
     char                 **envp;
     gboolean               debug;
+    gboolean               is_action2;
+    gboolean               is_device_handler;
 
     GPtrArray *scripts; /* list of ScriptInfo */
     guint      idx;
@@ -192,6 +199,12 @@ script_info_free(gpointer ptr)
 {
     ScriptInfo *info = ptr;
 
+    nm_assert(info->pid == -1);
+    nm_assert(info->stdout_fd == -1);
+    nm_assert(!info->stdout_source);
+    nm_assert(!info->timeout_source);
+    nm_assert(!info->watch_source);
+
     g_free(info->script);
     g_free(info->error);
     g_slice_free(ScriptInfo, info);
@@ -280,6 +293,108 @@ next_request(Request *request)
     return TRUE;
 }
 
+static GVariant *
+build_result_options(char *stdout)
+{
+    gs_unref_hashtable GHashTable *hash = NULL;
+    GHashTableIter                 iter;
+    gs_strfreev char             **lines = NULL;
+    GVariantBuilder                builder_opts;
+    GVariantBuilder                builder_out_dict;
+    guint                          i;
+    char                          *eq;
+    char                          *key;
+    char                          *value;
+
+    lines = g_strsplit(stdout, "\n", 65);
+
+    for (i = 0; lines[i] && i < 64; i++) {
+        eq = strchr(lines[i], '=');
+        if (!eq)
+            continue;
+        *eq = '\0';
+
+        if (!NM_STRCHAR_ALL(lines[i],
+                            ch,
+                            (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_'))
+            continue;
+
+        if (!hash) {
+            hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
+        }
+
+        g_hash_table_insert(hash, g_strdup(lines[i]), g_strdup(eq + 1));
+    }
+
+    g_variant_builder_init(&builder_out_dict, G_VARIANT_TYPE("a{ss}"));
+    if (hash) {
+        g_hash_table_iter_init(&iter, hash);
+        while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &value)) {
+            gs_free char *to_free = NULL;
+
+            g_variant_builder_add(&builder_out_dict,
+                                  "{ss}",
+                                  key,
+                                  nm_utils_buf_utf8safe_escape(value,
+                                                               -1,
+                                                               NM_UTILS_STR_UTF8_SAFE_FLAG_NONE,
+                                                               &to_free));
+        }
+    }
+
+    g_variant_builder_init(&builder_opts, G_VARIANT_TYPE("a{sv}"));
+    g_variant_builder_add(&builder_opts,
+                          "{sv}",
+                          "output_dict",
+                          g_variant_builder_end(&builder_out_dict));
+
+    return g_variant_builder_end(&builder_opts);
+}
+
+static void
+request_dbus_method_return(Request *request)
+{
+    GVariantBuilder results;
+    guint           i;
+
+    if (request->is_action2) {
+        g_variant_builder_init(&results, G_VARIANT_TYPE("a(susa{sv})"));
+    } else {
+        g_variant_builder_init(&results, G_VARIANT_TYPE("a(sus)"));
+    }
+
+    for (i = 0; i < request->scripts->len; i++) {
+        ScriptInfo   *script  = g_ptr_array_index(request->scripts, i);
+        GVariant     *options = NULL;
+        gs_free char *stdout  = NULL;
+
+        if (request->is_device_handler) {
+            stdout  = nm_str_buf_finalize(&script->stdout_buffer, NULL);
+            options = build_result_options(stdout);
+        }
+
+        if (request->is_action2) {
+            g_variant_builder_add(&results,
+                                  "(sus@a{sv})",
+                                  script->script,
+                                  script->result,
+                                  script->error ?: "",
+                                  options ?: nm_g_variant_singleton_aLsvI());
+        } else {
+            g_variant_builder_add(&results,
+                                  "(sus)",
+                                  script->script,
+                                  script->result,
+                                  script->error ?: "");
+        }
+    }
+
+    g_dbus_method_invocation_return_value(request->context,
+                                          request->is_action2
+                                              ? g_variant_new("(a(susa{sv}))", &results)
+                                              : g_variant_new("(a(sus))", &results));
+}
+
 /**
  * complete_request:
  * @request: the request
@@ -292,29 +407,13 @@ next_request(Request *request)
 static void
 complete_request(Request *request)
 {
-    GVariantBuilder results;
-    GVariant       *ret;
-    guint           i;
-
     nm_assert(request);
 
     /* Are there still pending scripts? Then do nothing (for now). */
     if (request->num_scripts_done < request->scripts->len)
         return;
 
-    g_variant_builder_init(&results, G_VARIANT_TYPE("a(sus)"));
-    for (i = 0; i < request->scripts->len; i++) {
-        ScriptInfo *script = g_ptr_array_index(request->scripts, i);
-
-        g_variant_builder_add(&results,
-                              "(sus)",
-                              script->script,
-                              script->result,
-                              script->error ?: "");
-    }
-
-    ret = g_variant_new("(a(sus))", &results);
-    g_dbus_method_invocation_return_value(request->context, ret);
+    request_dbus_method_return(request);
 
     _LOG_R_T(request, "completed (%u scripts)", request->scripts->len);
 
@@ -333,10 +432,17 @@ complete_request(Request *request)
 static void
 complete_script(ScriptInfo *script)
 {
-    Request *request;
-    gboolean wait = script->wait;
+    Request *request = script->request;
+    gboolean wait    = script->wait;
 
-    request = script->request;
+    if (script->pid != -1 || script->stdout_fd != -1) {
+        /* Wait that process has terminated and stdout is closed */
+        return;
+    }
+
+    script->request->num_scripts_done++;
+    if (!script->wait)
+        script->request->num_scripts_nowait--;
 
     if (wait) {
         /* for "wait" scripts, try to schedule the next blocking script.
@@ -404,26 +510,23 @@ script_watch_cb(GPid pid, int status, gpointer user_data)
 
     nm_clear_g_source_inst(&script->watch_source);
     nm_clear_g_source_inst(&script->timeout_source);
-    script->request->num_scripts_done++;
-    if (!script->wait)
-        script->request->num_scripts_nowait--;
 
     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
         script->result = DISPATCH_RESULT_SUCCESS;
     } else {
-        status_desc   = nm_utils_get_process_exit_status_desc(status);
-        script->error = g_strdup_printf("Script '%s' %s.", script->script, status_desc);
+        status_desc = nm_utils_get_process_exit_status_desc(status);
+        nm_clear_g_free(&script->error);
+        script->error = g_strdup_printf("Script '%s' %s", script->script, status_desc);
     }
 
     if (script->result == DISPATCH_RESULT_SUCCESS) {
-        _LOG_S_T(script, "complete");
+        _LOG_S_T(script, "complete: process succeeded");
     } else {
         script->result = DISPATCH_RESULT_FAILED;
-        _LOG_S_W(script, "complete: failed with %s", script->error);
+        _LOG_S_W(script, "complete: process failed with %s", script->error);
     }
 
-    g_spawn_close_pid(script->pid);
-
+    script->pid = -1;
     complete_script(script);
 }
 
@@ -434,9 +537,8 @@ script_timeout_cb(gpointer user_data)
 
     nm_clear_g_source_inst(&script->timeout_source);
     nm_clear_g_source_inst(&script->watch_source);
-    script->request->num_scripts_done++;
-    if (!script->wait)
-        script->request->num_scripts_nowait--;
+    nm_clear_g_source_inst(&script->stdout_source);
+    nm_clear_fd(&script->stdout_fd);
 
     _LOG_S_W(script, "complete: timeout (kill script)");
 
@@ -447,11 +549,10 @@ again:
             goto again;
     }
 
-    script->error  = g_strdup_printf("Script '%s' timed out.", script->script);
+    script->error  = g_strdup_printf("Script '%s' timed out", script->script);
     script->result = DISPATCH_RESULT_TIMEOUT;
 
-    g_spawn_close_pid(script->pid);
-
+    script->pid = -1;
     complete_script(script);
 
     return G_SOURCE_CONTINUE;
@@ -466,19 +567,19 @@ check_permissions(struct stat *s, const char **out_error_msg)
 
     /* Only accept files owned by root */
     if (s->st_uid != 0) {
-        *out_error_msg = "not owned by root.";
+        *out_error_msg = "not owned by root";
         return FALSE;
     }
 
     /* Only accept files not writable by group or other, and not SUID */
     if (s->st_mode & (S_IWGRP | S_IWOTH | S_ISUID)) {
-        *out_error_msg = "writable by group or other, or set-UID.";
+        *out_error_msg = "writable by group or other, or set-UID";
         return FALSE;
     }
 
     /* Only accept files executable by the owner */
     if (!(s->st_mode & S_IXUSR)) {
-        *out_error_msg = "not executable by owner.";
+        *out_error_msg = "not executable by owner";
         return FALSE;
     }
 
@@ -515,11 +616,45 @@ check_filename(const char *file_name)
 #define SCRIPT_TIMEOUT 600 /* 10 minutes */
 
 static gboolean
+script_have_data(int fd, GIOCondition condition, gpointer user_data)
+{
+    ScriptInfo *script = user_data;
+    gssize      n_read;
+
+    n_read = nm_utils_fd_read(fd, &script->stdout_buffer);
+
+    if (n_read == -EAGAIN) {
+        return G_SOURCE_CONTINUE;
+    } else if (n_read > 0) {
+        if (script->stdout_buffer.len < 8 * 1024)
+            return G_SOURCE_CONTINUE;
+        /* Don't allow the buffer to grow indefinitely. */
+        _LOG_S_W(script, "complete: ignoring script stdout exceeding 8KiB");
+        nm_str_buf_set_size(&script->stdout_buffer, 8 * 1024, FALSE, FALSE);
+    } else if (n_read == 0) {
+        _LOG_S_T(script, "complete: stdout closed");
+    } else {
+        _LOG_S_T(script,
+                 "complete: reading stdout failed with %d (%s)",
+                 (int) n_read,
+                 nm_strerror_native((int) -n_read));
+    }
+
+    nm_clear_g_source_inst(&script->stdout_source);
+    nm_clear_fd(&script->stdout_fd);
+
+    complete_script(script);
+
+    return G_SOURCE_CONTINUE;
+}
+
+static gboolean
 script_dispatch(ScriptInfo *script)
 {
     gs_free_error GError *error = NULL;
     char                 *argv[4];
-    Request              *request = script->request;
+    Request              *request           = script->request;
+    gboolean              is_device_handler = script->request->is_device_handler;
 
     if (script->dispatched)
         return FALSE;
@@ -536,14 +671,17 @@ script_dispatch(ScriptInfo *script)
 
     _LOG_S_T(script, "run script%s", script->wait ? "" : " (no-wait)");
 
-    if (!g_spawn_async("/",
-                       argv,
-                       request->envp,
-                       G_SPAWN_DO_NOT_REAP_CHILD,
-                       NULL,
-                       NULL,
-                       &script->pid,
-                       &error)) {
+    if (!g_spawn_async_with_pipes("/",
+                                  argv,
+                                  request->envp,
+                                  G_SPAWN_CLOEXEC_PIPES | G_SPAWN_DO_NOT_REAP_CHILD,
+                                  NULL,
+                                  NULL,
+                                  &script->pid,
+                                  NULL,
+                                  is_device_handler ? &script->stdout_fd : NULL,
+                                  NULL,
+                                  &error)) {
         _LOG_S_W(script, "complete: failed to execute script: %s", error->message);
         script->result = DISPATCH_RESULT_EXEC_FAILED;
         script->error  = g_strdup(error->message);
@@ -556,6 +694,19 @@ script_dispatch(ScriptInfo *script)
         nm_g_timeout_add_seconds_source(SCRIPT_TIMEOUT, script_timeout_cb, script);
     if (!script->wait)
         request->num_scripts_nowait++;
+
+    if (is_device_handler) {
+        /* Watch process stdout */
+        nm_io_fcntl_setfl_update_nonblock(script->stdout_fd);
+        script->stdout_source = nm_g_unix_fd_source_new(script->stdout_fd,
+                                                        G_IO_IN | G_IO_ERR | G_IO_HUP,
+                                                        G_PRIORITY_DEFAULT,
+                                                        script_have_data,
+                                                        script,
+                                                        NULL);
+        g_source_attach(script->stdout_source, NULL);
+    }
+
     return TRUE;
 }
 
@@ -593,6 +744,31 @@ _compare_basenames(gconstpointer a, gconstpointer b)
     return 0;
 }
 
+static gboolean
+check_file(Request *request, const char *path)
+{
+    gs_free char *link_target = NULL;
+    const char   *err_msg     = NULL;
+    struct stat   st;
+    int           err;
+
+    link_target = g_file_read_link(path, NULL);
+    if (nm_streq0(link_target, "/dev/null"))
+        return FALSE;
+
+    err = stat(path, &st);
+    if (err) {
+        return FALSE;
+    } else if (!S_ISREG(st.st_mode) || st.st_size == 0) {
+        /* silently skip. */
+        return FALSE;
+    } else if (!check_permissions(&st, &err_msg)) {
+        _LOG_R_W(request, "find-scripts: Cannot execute '%s': %s", path, err_msg);
+        return FALSE;
+    }
+    return TRUE;
+}
+
 static void
 _find_scripts(Request *request, GHashTable *scripts, const char *base, const char *subdir)
 {
@@ -625,7 +801,7 @@ _find_scripts(Request *request, GHashTable *scripts, const char *base, const cha
 }
 
 static GSList *
-find_scripts(Request *request)
+find_scripts(Request *request, const char *device_handler)
 {
     gs_unref_hashtable GHashTable *scripts     = NULL;
     GSList                        *script_list = NULL;
@@ -634,6 +810,33 @@ find_scripts(Request *request)
     char                          *path;
     char                          *filename;
 
+    if (request->is_device_handler) {
+        const char *const dirs[] = {NMCONFDIR, NMLIBDIR};
+        guint             i;
+
+        nm_assert(device_handler);
+
+        for (i = 0; i < G_N_ELEMENTS(dirs); i++) {
+            gs_free char *full_name = NULL;
+
+            full_name = g_build_filename(dirs[i], "dispatcher.d", "device", device_handler, NULL);
+            if (check_file(request, full_name)) {
+                script_list = g_slist_prepend(script_list, g_steal_pointer(&full_name));
+                return script_list;
+            }
+        }
+
+        _LOG_R_W(request,
+                 "find-scripts: no device-handler script found with name \"%s\"",
+                 device_handler);
+        return NULL;
+    }
+
+    nm_assert(!device_handler);
+
+    /* Use a hash-table to deduplicate scripts with same name from /etc and /usr */
+    scripts = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
+
     if (NM_IN_STRSET(request->action, NMD_ACTION_PRE_UP, NMD_ACTION_VPN_PRE_UP))
         subdir = "pre-up.d";
     else if (NM_IN_STRSET(request->action, NMD_ACTION_PRE_DOWN, NMD_ACTION_VPN_PRE_DOWN))
@@ -641,33 +844,13 @@ find_scripts(Request *request)
     else
         subdir = NULL;
 
-    scripts = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
-
     _find_scripts(request, scripts, NMLIBDIR, subdir);
     _find_scripts(request, scripts, NMCONFDIR, subdir);
 
     g_hash_table_iter_init(&iter, scripts);
     while (g_hash_table_iter_next(&iter, (gpointer *) &filename, (gpointer *) &path)) {
-        gs_free char *link_target = NULL;
-        const char   *err_msg     = NULL;
-        struct stat   st;
-        int           err;
-
-        link_target = g_file_read_link(path, NULL);
-        if (nm_streq0(link_target, "/dev/null"))
-            continue;
-
-        err = stat(path, &st);
-        if (err)
-            _LOG_R_W(request, "find-scripts: Failed to stat '%s': %d", path, err);
-        else if (!S_ISREG(st.st_mode) || st.st_size == 0) {
-            /* silently skip. */
-        } else if (!check_permissions(&st, &err_msg))
-            _LOG_R_W(request, "find-scripts: Cannot execute '%s': %s", path, err_msg);
-        else {
-            /* success */
+        if (check_file(request, path)) {
             script_list = g_slist_prepend(script_list, g_strdup(path));
-            continue;
         }
     }
 
@@ -703,8 +886,29 @@ script_must_wait(const char *path)
     return TRUE;
 }
 
+static char *
+get_device_handler(GVariant *connection)
+{
+    gs_unref_variant GVariant *generic_setting = NULL;
+    const char                *device_handler  = NULL;
+
+    generic_setting = g_variant_lookup_value(connection,
+                                             NM_SETTING_GENERIC_SETTING_NAME,
+                                             NM_VARIANT_TYPE_SETTING);
+    if (generic_setting) {
+        if (g_variant_lookup(generic_setting,
+                             NM_SETTING_GENERIC_DEVICE_HANDLER,
+                             "&s",
+                             &device_handler)) {
+            return g_strdup(device_handler);
+        }
+    }
+
+    return NULL;
+}
+
 static void
-_handle_action(GDBusMethodInvocation *invocation, GVariant *parameters)
+_handle_action(GDBusMethodInvocation *invocation, GVariant *parameters, gboolean is_action2)
 {
     const char                *action;
     gs_unref_variant GVariant *connection              = NULL;
@@ -717,9 +921,11 @@ _handle_action(GDBusMethodInvocation *invocation, GVariant *parameters)
     gs_unref_variant GVariant *device_dhcp6_config     = NULL;
     const char                *connectivity_state;
     const char                *vpn_ip_iface;
+    gs_free char              *device_handler       = NULL;
     gs_unref_variant GVariant *vpn_proxy_properties = NULL;
     gs_unref_variant GVariant *vpn_ip4_config       = NULL;
     gs_unref_variant GVariant *vpn_ip6_config       = NULL;
+    gs_unref_variant GVariant *options              = NULL;
     gboolean                   debug;
     GSList                    *sorted_scripts = NULL;
     GSList                    *iter;
@@ -728,45 +934,86 @@ _handle_action(GDBusMethodInvocation *invocation, GVariant *parameters)
     guint                      i, num_nowait = 0;
     const char                *error_message = NULL;
 
-    g_variant_get(parameters,
-                  "("
-                  "&s"         /* action */
-                  "@a{sa{sv}}" /* connection */
-                  "@a{sv}"     /* connection_properties */
-                  "@a{sv}"     /* device_properties */
-                  "@a{sv}"     /* device_proxy_properties */
-                  "@a{sv}"     /* device_ip4_config */
-                  "@a{sv}"     /* device_ip6_config */
-                  "@a{sv}"     /* device_dhcp4_config */
-                  "@a{sv}"     /* device_dhcp6_config */
-                  "&s"         /* connectivity_state */
-                  "&s"         /* vpn_ip_iface */
-                  "@a{sv}"     /* vpn_proxy_properties */
-                  "@a{sv}"     /* vpn_ip4_config */
-                  "@a{sv}"     /* vpn_ip6_config */
-                  "b"          /* debug */
-                  ")",
-                  &action,
-                  &connection,
-                  &connection_properties,
-                  &device_properties,
-                  &device_proxy_properties,
-                  &device_ip4_config,
-                  &device_ip6_config,
-                  &device_dhcp4_config,
-                  &device_dhcp6_config,
-                  &connectivity_state,
-                  &vpn_ip_iface,
-                  &vpn_proxy_properties,
-                  &vpn_ip4_config,
-                  &vpn_ip6_config,
-                  &debug);
+    if (is_action2) {
+        g_variant_get(parameters,
+                      "("
+                      "&s"         /* action */
+                      "@a{sa{sv}}" /* connection */
+                      "@a{sv}"     /* connection_properties */
+                      "@a{sv}"     /* device_properties */
+                      "@a{sv}"     /* device_proxy_properties */
+                      "@a{sv}"     /* device_ip4_config */
+                      "@a{sv}"     /* device_ip6_config */
+                      "@a{sv}"     /* device_dhcp4_config */
+                      "@a{sv}"     /* device_dhcp6_config */
+                      "&s"         /* connectivity_state */
+                      "&s"         /* vpn_ip_iface */
+                      "@a{sv}"     /* vpn_proxy_properties */
+                      "@a{sv}"     /* vpn_ip4_config */
+                      "@a{sv}"     /* vpn_ip6_config */
+                      "b"          /* debug */
+                      "@a{sv}"     /* options */
+                      ")",
+                      &action,
+                      &connection,
+                      &connection_properties,
+                      &device_properties,
+                      &device_proxy_properties,
+                      &device_ip4_config,
+                      &device_ip6_config,
+                      &device_dhcp4_config,
+                      &device_dhcp6_config,
+                      &connectivity_state,
+                      &vpn_ip_iface,
+                      &vpn_proxy_properties,
+                      &vpn_ip4_config,
+                      &vpn_ip6_config,
+                      &debug,
+                      &options);
+    } else {
+        g_variant_get(parameters,
+                      "("
+                      "&s"         /* action */
+                      "@a{sa{sv}}" /* connection */
+                      "@a{sv}"     /* connection_properties */
+                      "@a{sv}"     /* device_properties */
+                      "@a{sv}"     /* device_proxy_properties */
+                      "@a{sv}"     /* device_ip4_config */
+                      "@a{sv}"     /* device_ip6_config */
+                      "@a{sv}"     /* device_dhcp4_config */
+                      "@a{sv}"     /* device_dhcp6_config */
+                      "&s"         /* connectivity_state */
+                      "&s"         /* vpn_ip_iface */
+                      "@a{sv}"     /* vpn_proxy_properties */
+                      "@a{sv}"     /* vpn_ip4_config */
+                      "@a{sv}"     /* vpn_ip6_config */
+                      "b"          /* debug */
+                      ")",
+                      &action,
+                      &connection,
+                      &connection_properties,
+                      &device_properties,
+                      &device_proxy_properties,
+                      &device_ip4_config,
+                      &device_ip6_config,
+                      &device_dhcp4_config,
+                      &device_dhcp6_config,
+                      &connectivity_state,
+                      &vpn_ip_iface,
+                      &vpn_proxy_properties,
+                      &vpn_ip4_config,
+                      &vpn_ip6_config,
+                      &debug);
+    }
 
     request             = g_slice_new0(Request);
     request->request_id = ++gl.request_id_counter;
     request->debug      = debug || gl.log_verbose;
     request->context    = invocation;
     request->action     = g_strdup(action);
+    request->is_action2 = is_action2;
+    request->is_device_handler =
+        NM_IN_STRSET(action, NMD_ACTION_DEVICE_ADD, NMD_ACTION_DEVICE_DELETE);
 
     request->envp = nm_dispatcher_utils_construct_envp(action,
                                                        connection,
@@ -784,37 +1031,42 @@ _handle_action(GDBusMethodInvocation *invocation, GVariant *parameters)
                                                        vpn_ip6_config,
                                                        &request->iface,
                                                        &error_message);
+    if (!error_message) {
+        if (request->is_device_handler) {
+            device_handler = get_device_handler(connection);
+        }
 
-    request->scripts = g_ptr_array_new_full(5, script_info_free);
+        request->scripts = g_ptr_array_new_full(5, script_info_free);
 
-    sorted_scripts = find_scripts(request);
-    for (iter = sorted_scripts; iter; iter = g_slist_next(iter)) {
-        ScriptInfo *s;
+        sorted_scripts = find_scripts(request, device_handler);
+        for (iter = sorted_scripts; iter; iter = g_slist_next(iter)) {
+            ScriptInfo *s;
 
-        s          = g_slice_new0(ScriptInfo);
-        s->request = request;
-        s->script  = iter->data;
-        s->wait    = script_must_wait(s->script);
-        g_ptr_array_add(request->scripts, s);
-    }
-    g_slist_free(sorted_scripts);
+            s                = g_slice_new0(ScriptInfo);
+            s->request       = request;
+            s->script        = iter->data;
+            s->wait          = script_must_wait(s->script);
+            s->stdout_fd     = -1;
+            s->pid           = -1;
+            s->stdout_buffer = NM_STR_BUF_INIT(0, FALSE);
+            g_ptr_array_add(request->scripts, s);
+        }
+        g_slist_free(sorted_scripts);
 
-    _LOG_R_D(request, "new request (%u scripts)", request->scripts->len);
-    if (_LOG_R_T_enabled(request) && request->envp) {
-        for (p = request->envp; *p; p++)
-            _LOG_R_T(request, "environment: %s", *p);
+        _LOG_R_D(request, "new request (%u scripts)", request->scripts->len);
+        if (_LOG_R_T_enabled(request) && request->envp) {
+            for (p = request->envp; *p; p++)
+                _LOG_R_T(request, "environment: %s", *p);
+        }
     }
 
-    if (error_message || request->scripts->len == 0) {
-        GVariant *results;
-
+    if (request->scripts->len == 0) {
         if (error_message)
             _LOG_R_W(request, "completed: invalid request: %s", error_message);
         else
             _LOG_R_D(request, "completed: no scripts");
 
-        results = g_variant_new_array(G_VARIANT_TYPE("(sus)"), NULL, 0);
-        g_dbus_method_invocation_return_value(invocation, g_variant_new("(@a(sus))", results));
+        request_dbus_method_return(request);
         request->num_scripts_done = request->scripts->len;
         request_free(request);
         return;
@@ -905,8 +1157,12 @@ _bus_method_call(GDBusConnection       *connection,
         return;
     }
     if (nm_streq(interface_name, NM_DISPATCHER_DBUS_INTERFACE)) {
+        if (nm_streq(method_name, "Action2")) {
+            _handle_action(invocation, parameters, TRUE);
+            return;
+        }
         if (nm_streq(method_name, "Action")) {
-            _handle_action(invocation, parameters);
+            _handle_action(invocation, parameters, FALSE);
             return;
         }
         if (nm_streq(method_name, "Ping")) {
@@ -947,7 +1203,28 @@ static GDBusInterfaceInfo *const interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO
                 NM_DEFINE_GDBUS_ARG_INFO("vpn_ip6_config", "a{sv}"),
                 NM_DEFINE_GDBUS_ARG_INFO("debug", "b"), ),
             .out_args =
-                NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("results", "a(sus)"), ), ), ), );
+                NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("results", "a(sus)"), ), ),
+        NM_DEFINE_GDBUS_METHOD_INFO(
+            "Action2",
+            .in_args = NM_DEFINE_GDBUS_ARG_INFOS(
+                NM_DEFINE_GDBUS_ARG_INFO("action", "s"),
+                NM_DEFINE_GDBUS_ARG_INFO("connection", "a{sa{sv}}"),
+                NM_DEFINE_GDBUS_ARG_INFO("connection_properties", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_properties", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_proxy_properties", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_ip4_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_ip6_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_dhcp4_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("device_dhcp6_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("connectivity_state", "s"),
+                NM_DEFINE_GDBUS_ARG_INFO("vpn_ip_iface", "s"),
+                NM_DEFINE_GDBUS_ARG_INFO("vpn_proxy_properties", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("vpn_ip4_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("vpn_ip6_config", "a{sv}"),
+                NM_DEFINE_GDBUS_ARG_INFO("debug", "b"),
+                NM_DEFINE_GDBUS_ARG_INFO("options", "a{sv}"), ),
+            .out_args = NM_DEFINE_GDBUS_ARG_INFOS(
+                NM_DEFINE_GDBUS_ARG_INFO("results", "a(susa{sv})"), ), ), ), );
 
 static gboolean
 _bus_register_service(void)
diff --git a/src/nmcli/common.c b/src/nmcli/common.c
index 04d2ebf9..2f205e50 100644
--- a/src/nmcli/common.c
+++ b/src/nmcli/common.c
@@ -700,7 +700,7 @@ get_secrets_from_user(const NmcConfig *nmc_config,
                 if (msg)
                     nmc_print("%s\n", msg);
 
-                echo_on = secret->is_secret ? nmc_config->show_secrets : TRUE;
+                echo_on = secret->is_secret ? secret->force_echo || nmc_config->show_secrets : TRUE;
 
                 if (secret->no_prompt_entry_id)
                     pwd = nmc_readline_echo(nmc_config, echo_on, "%s: ", secret->pretty_name);
diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c
index 0ab11e3e..72a1fc18 100644
--- a/src/nmcli/connections.c
+++ b/src/nmcli/connections.c
@@ -672,8 +672,7 @@ nmc_connection_check_deprecated(NMConnection *c)
     const char                *type;
 
     type = nm_connection_get_connection_type(c);
-
-    if (strcmp(type, NM_SETTING_WIMAX_SETTING_NAME) == 0)
+    if (nm_streq0(type, NM_SETTING_WIMAX_SETTING_NAME))
         return _("WiMax is no longer supported");
 
     s_wsec = nm_connection_get_setting_wireless_security(c);
@@ -1067,15 +1066,16 @@ const NmcMetaGenericInfo
     "," NM_SETTING_TEAM_SETTING_NAME "," NM_SETTING_TEAM_PORT_SETTING_NAME             \
     "," NM_SETTING_OVS_BRIDGE_SETTING_NAME "," NM_SETTING_OVS_INTERFACE_SETTING_NAME   \
     "," NM_SETTING_OVS_PATCH_SETTING_NAME "," NM_SETTING_OVS_PORT_SETTING_NAME         \
-    "," NM_SETTING_DCB_SETTING_NAME "," NM_SETTING_TUN_SETTING_NAME                    \
-    "," NM_SETTING_IP_TUNNEL_SETTING_NAME "," NM_SETTING_MACSEC_SETTING_NAME           \
-    "," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME              \
-    "," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME                   \
-    "," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME          \
-    "," NM_SETTING_LINK_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME                 \
-    "," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME            \
-    "," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME           \
-    "," NM_SETTING_HOSTNAME_SETTING_NAME "," NM_SETTING_HSR_SETTING_NAME
+    "," NM_SETTING_GENERIC_SETTING_NAME "," NM_SETTING_DCB_SETTING_NAME                \
+    "," NM_SETTING_TUN_SETTING_NAME "," NM_SETTING_IP_TUNNEL_SETTING_NAME              \
+    "," NM_SETTING_MACSEC_SETTING_NAME "," NM_SETTING_MACVLAN_SETTING_NAME             \
+    "," NM_SETTING_VXLAN_SETTING_NAME "," NM_SETTING_VRF_SETTING_NAME                  \
+    "," NM_SETTING_WPAN_SETTING_NAME "," NM_SETTING_6LOWPAN_SETTING_NAME               \
+    "," NM_SETTING_WIREGUARD_SETTING_NAME "," NM_SETTING_LINK_SETTING_NAME             \
+    "," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME            \
+    "," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME              \
+    "," NM_SETTING_OVS_DPDK_SETTING_NAME "," NM_SETTING_HOSTNAME_SETTING_NAME          \
+    "," NM_SETTING_HSR_SETTING_NAME
 /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
 
 const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
diff --git a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
index 40ef214f..160ae32f 100644
--- a/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
+++ b/src/nmcli/gen-metadata-nm-settings-nmcli.xml.in
@@ -1070,6 +1070,9 @@
                   values="0 - 4294967295" />
     </setting>
     <setting name="generic" >
+        <property name="device-handler"
+                  nmcli-description="Name of the device handler that will be invoked to add and delete the device for this connection. The name can only contain ASCII alphanumeric characters and &apos;-&apos;, &apos;_&apos;, &apos;.&apos;. It cannot start with &apos;.&apos;. See the NetworkManager-dispatcher(8) man page for more details about how to write the device handler. By setting this property the generic connection becomes &quot;virtual&quot;, meaning that it can be activated without an existing device; the device will be created at the time the connection is started by invoking the device-handler."
+                  format="string" />
     </setting>
     <setting name="gsm" >
         <property name="auto-config"
@@ -1548,6 +1551,10 @@
                   nmcli-description="Specifies whether the SCI (Secure Channel Identifier) is included in every packet."
                   format="boolean"
                   values="true/yes/on, false/no/off" />
+        <property name="offload"
+                  nmcli-description="Specifies the MACsec offload mode. &quot;off&quot; (0) disables MACsec offload. &quot;phy&quot; (1) and &quot;mac&quot; (2) request offload respectively to the PHY or to the MAC; if the selected mode is not available, the connection will fail. &quot;default&quot; (-1) uses the global default value specified in NetworkManager configuration; if no global default is defined, the built-in default is &quot;off&quot; (0)."
+                  format="choice (NMSettingMacsecOffload)"
+                  values="default (-1), off (0), phy (1), mac (2)" />
     </setting>
     <setting name="macvlan" >
         <property name="parent"
@@ -1820,6 +1827,18 @@
                   nmcli-description="Whether to autoprobe virtual functions by a compatible driver. If set to &quot;true&quot; (1), the kernel will try to bind VFs to a compatible driver and if this succeeds a new network interface will be instantiated for each VF. If set to &quot;false&quot; (0), VFs will not be claimed and no network interfaces will be created for them. When set to &quot;default&quot; (-1), the global default is used; in case the global default is unspecified it is assumed to be &quot;true&quot; (1)."
                   format="ternary"
                   values="true/yes/on, false/no/off, default/unknown" />
+        <property name="eswitch-mode"
+                  nmcli-description="Select the eswitch mode of the device. Currently it&apos;s only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to &quot;preserve&quot; (-1) (default) the eswitch mode won&apos;t be modified by NetworkManager."
+                  format="choice (NMSriovEswitchMode)"
+                  values="preserve (-1), legacy (0), switchdev (1)" />
+        <property name="eswitch-inline-mode"
+                  nmcli-description="Select the eswitch inline-mode of the device. Some HWs need the VF driver to put part of the packet headers on the TX descriptor so the e-switch can do proper matching and steering. Currently it&apos;s only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to &quot;preserve&quot; (-1) (default) the eswitch inline-mode won&apos;t be modified by NetworkManager."
+                  format="choice (NMSriovEswitchInlineMode)"
+                  values="preserve (-1), none (0), link (1), network (2), transport (3)" />
+        <property name="eswitch-encap-mode"
+                  nmcli-description="Select the eswitch encapsulation support. Currently it&apos;s only supported for PCI PF devices, and only if the eswitch device is managed from the same PCI address than the PF. If set to &quot;preserve&quot; (-1) (default) the eswitch encap-mode won&apos;t be modified by NetworkManager."
+                  format="choice (NMSriovEswitchEncapMode)"
+                  values="preserve (-1), none (0), basic (1)" />
     </setting>
     <setting name="tc" >
         <property name="qdiscs"
diff --git a/src/nmtui/nmt-page-bridge.c b/src/nmtui/nmt-page-bridge.c
index e84af1d8..61bc4d06 100644
--- a/src/nmtui/nmt-page-bridge.c
+++ b/src/nmtui/nmt-page-bridge.c
@@ -39,7 +39,7 @@ static gboolean
 bridge_connection_type_filter(GType connection_type, gpointer user_data)
 {
     return (connection_type == NM_TYPE_SETTING_WIRED || connection_type == NM_TYPE_SETTING_WIRELESS
-            || connection_type == NM_TYPE_SETTING_VLAN);
+            || connection_type == NM_TYPE_SETTING_VLAN || connection_type == NM_TYPE_SETTING_BOND);
 }
 
 static void
diff --git a/src/nmtui/nmt-password-dialog.c b/src/nmtui/nmt-password-dialog.c
index 75194d7b..6f1a5f03 100644
--- a/src/nmtui/nmt-password-dialog.c
+++ b/src/nmtui/nmt-password-dialog.c
@@ -139,7 +139,7 @@ nmt_password_dialog_constructed(GObject *object)
         nmt_newt_widget_set_padding(widget, 4, 0, 1, 0);
 
         flags = NMT_NEWT_ENTRY_NONEMPTY;
-        if (secret->is_secret)
+        if (secret->is_secret && !secret->force_echo)
             flags |= NMT_NEWT_ENTRY_PASSWORD;
         widget = nmt_newt_entry_new(30, flags);
         if (secret->value)