Commit ba1cc6a2 authored by Thomas Haller's avatar Thomas Haller

core: refactor evaluation of device's match-spec

Previously, we would have different functions like
  - nm_match_spec_device_type()
  - nm_match_spec_hwaddr()
  - nm_match_spec_s390_subchannels()
  - nm_match_spec_interface_name()
which all would handle one type of match-spec.

So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.

Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.

The upside is:

  - the logic how to evaluate the match-spec is all at one place
    (match_device_eval()) instead of spread over multiple

  - It requires iterating the list at most twice. Twice, because
    we do a fast pre-search for "*".

One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.

(cherry picked from commit b957403e)
parent 2e8af781
......@@ -1543,19 +1543,12 @@ new_default_connection (NMDevice *self)
return connection;
static NMMatchSpecMatchType
spec_match_list (NMDevice *device, const GSList *specs)
static const char *
get_s390_subchannels (NMDevice *device)
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device);
nm_assert (NM_IS_DEVICE_ETHERNET (device));
if (priv->subchannels)
matched = nm_match_spec_s390_subchannels (specs, priv->subchannels);
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
matched = MAX (matched, m);
return matched;
return NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->subchannels;
static void
......@@ -1746,7 +1739,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
parent_class->get_configured_mtu = get_configured_mtu;
parent_class->deactivate = deactivate;
parent_class->spec_match_list = spec_match_list;
parent_class->get_s390_subchannels = get_s390_subchannels;
parent_class->update_connection = update_connection;
parent_class->carrier_changed = carrier_changed;
parent_class->link_changed = link_changed;
......@@ -12861,42 +12861,19 @@ nm_device_get_initial_hw_address (NMDevice *self)
nm_device_spec_match_list (NMDevice *self, const GSList *specs)
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (!specs)
return FALSE;
return NM_DEVICE_GET_CLASS (self)->spec_match_list (self, specs) == NM_MATCH_SPEC_MATCH;
NMDeviceClass *klass;
NMMatchSpecMatchType m;
static NMMatchSpecMatchType
spec_match_list (NMDevice *self, const GSList *specs)
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
const GSList *iter;
const char *hw_addr_perm;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
for (iter = specs; iter; iter = g_slist_next (iter)) {
if (!strcmp ((const char *) iter->data, "*")) {
klass = NM_DEVICE_GET_CLASS (self);
hw_addr_perm = nm_device_get_permanent_hw_address (self);
if (hw_addr_perm) {
m = nm_match_spec_hwaddr (specs, hw_addr_perm);
matched = MAX (matched, m);
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
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;
m = nm_match_spec_device (specs,
nm_device_get_iface (self),
nm_device_get_type_description (self),
nm_device_get_permanent_hw_address (self),
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
return m == NM_MATCH_SPEC_MATCH;
......@@ -13461,7 +13438,6 @@ nm_device_class_init (NMDeviceClass *klass)
klass->have_any_ready_slaves = have_any_ready_slaves;
klass->get_type_description = get_type_description;
klass->spec_match_list = spec_match_list;
klass->can_auto_connect = can_auto_connect;
klass->check_connection_compatible = check_connection_compatible;
klass->check_connection_available = check_connection_available;
......@@ -295,7 +295,7 @@ typedef struct {
const char *(*get_type_description) (NMDevice *self);
NMMatchSpecMatchType (* spec_match_list) (NMDevice *self, const GSList *specs);
const char *(*get_s390_subchannels) (NMDevice *self);
/* Update the connection with currently configured L2 settings */
void (* update_connection) (NMDevice *device, NMConnection *connection);
......@@ -529,9 +529,9 @@ ignore_config_snippet (GKeyFile *keyfile, gboolean is_base_config)
/* second, interpret the value as match-spec. */
match_type = nm_match_spec_match_config (specs,
match_type = nm_match_spec_config (specs,
g_slist_free_full (specs, g_free);
return match_type != NM_MATCH_SPEC_MATCH;
This diff is collapsed.
......@@ -142,11 +142,14 @@ typedef enum {
} 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);
NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
NMMatchSpecMatchType nm_match_spec_device (const GSList *specs,
const char *interface_name,
const char *device_type,
const char *hwaddr,
const char *s390_subchannels);
NMMatchSpecMatchType nm_match_spec_config (const GSList *specs,
guint nm_version,
const char *env);
GSList *nm_match_spec_split (const char *value);
char *nm_match_spec_join (GSList *specs);
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment