diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index 3de964023e..bfd857eb76 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -620,6 +620,11 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth
s390-subchannels:HWADDR
Match the device based on the subchannel address. Globbing is not supported
+
+ type:TYPE
+ Match the device type. Valid type names are as reported by "nmcli -f GENERAL.TYPE device show".
+ Globbing is not supported.
+
except:SPEC
Negative match of a device. SPEC must be explicitly qualified with
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 904b4cdc79..cc1cef4677 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -996,6 +996,7 @@ nm_utils_find_helper(const char *progname, const char *try_first, GError **error
#define MAC_TAG "mac:"
#define INTERFACE_NAME_TAG "interface-name:"
+#define DEVICE_TYPE_TAG "type:"
#define SUBCHAN_TAG "s390-subchannels:"
#define EXCEPT_TAG "except:"
@@ -1010,6 +1011,37 @@ _match_except (const char *spec_str, gboolean *out_except)
return spec_str;
}
+NMMatchSpecMatchType
+nm_match_spec_device_type (const GSList *specs, const char *device_type)
+{
+ const GSList *iter;
+ NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
+
+ if (!device_type || !*device_type)
+ return NM_MATCH_SPEC_NO_MATCH;
+
+ for (iter = specs; iter; iter = g_slist_next (iter)) {
+ const char *spec_str = iter->data;
+ gboolean except;
+
+ if (!spec_str || !*spec_str)
+ continue;
+
+ spec_str = _match_except (spec_str, &except);
+
+ if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)) != 0)
+ continue;
+
+ spec_str += STRLEN (DEVICE_TYPE_TAG);
+ if (strcmp (spec_str, device_type) == 0) {
+ if (except)
+ return NM_MATCH_SPEC_NEG_MATCH;
+ match = NM_MATCH_SPEC_MATCH;
+ }
+ }
+ return match;
+}
+
NMMatchSpecMatchType
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
{
@@ -1028,7 +1060,8 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
spec_str = _match_except (spec_str, &except);
if ( !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG))
- || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG)))
+ || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))
+ || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)))
continue;
if (!g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG)))
@@ -1064,7 +1097,8 @@ nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
spec_str = _match_except (spec_str, &except);
if ( !g_ascii_strncasecmp (spec_str, MAC_TAG, STRLEN (MAC_TAG))
- || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG)))
+ || !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, STRLEN (SUBCHAN_TAG))
+ || !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, STRLEN (DEVICE_TYPE_TAG)))
continue;
if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, STRLEN (INTERFACE_NAME_TAG))) {
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 3c14212ed8..c7b1e13627 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -93,6 +93,7 @@ typedef enum {
NM_MATCH_SPEC_NEG_MATCH = 2,
} NMMatchSpecMatchType;
+NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char *device_type);
NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 84113c86b2..3c7f060f2b 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -8531,6 +8531,10 @@ spec_match_list (NMDevice *self, const GSList *specs)
m = nm_match_spec_interface_name (specs, nm_device_get_iface (self));
matched = MAX (matched, m);
}
+ if (matched != NM_MATCH_SPEC_NEG_MATCH) {
+ m = nm_match_spec_device_type (specs, nm_device_get_type_description (self));
+ matched = MAX (matched, m);
+ }
return matched;
}