diff options
author | Jiří Klimeš <jklimes@redhat.com> | 2015-09-29 09:41:45 +0200 |
---|---|---|
committer | Jiří Klimeš <jklimes@redhat.com> | 2015-09-29 09:41:45 +0200 |
commit | edec77fba46e3e6cff8631a0796317ab765543da (patch) | |
tree | a159de531ce16367e6ea832c575eaf16dd3d322d | |
parent | 8e6a839d93380ff3f39e967d16fa90e5a4d6325a (diff) | |
parent | 82e4364480c3dc74854540ac014a3fb9e3ec67d2 (diff) | |
download | NetworkManager-edec77fba46e3e6cff8631a0796317ab765543da.tar.gz |
merge: S390 subchannels improvements (bgo #755610)
- export device's S390 subchannels on D-Bus
- update 390 subchannels comparison for connection vs.device compatibility
- support s390 subchannels in libnm and nmcli
https://bugzilla.gnome.org/show_bug.cgi?id=755610
-rw-r--r-- | clients/cli/devices.c | 10 | ||||
-rw-r--r-- | introspection/nm-device-ethernet.xml | 6 | ||||
-rw-r--r-- | libnm-glib/tests/test-nm-client.c | 29 | ||||
-rw-r--r-- | libnm/libnm.ver | 1 | ||||
-rw-r--r-- | libnm/nm-device-ethernet.c | 137 | ||||
-rw-r--r-- | libnm/nm-device-ethernet.h | 3 | ||||
-rw-r--r-- | libnm/tests/common.c | 64 | ||||
-rw-r--r-- | libnm/tests/common.h | 7 | ||||
-rw-r--r-- | libnm/tests/test-nm-client.c | 72 | ||||
-rw-r--r-- | src/devices/nm-device-ethernet.c | 55 | ||||
-rw-r--r-- | src/devices/nm-device-ethernet.h | 1 | ||||
-rwxr-xr-x | tools/test-networkmanager-service.py | 16 |
12 files changed, 357 insertions, 44 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 84c766721c..8c5fe20efd 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -108,12 +108,13 @@ static NmcOutputField nmc_fields_dev_show_cap[] = { /* Available fields for 'device show' - wired properties part */ static NmcOutputField nmc_fields_dev_show_wired_prop[] = { - {"NAME", N_("NAME")}, /* 0 */ - {"CARRIER", N_("CARRIER")}, /* 1 */ + {"NAME", N_("NAME")}, /* 0 */ + {"CARRIER", N_("CARRIER")}, /* 1 */ + {"S390-SUBCHANNELS", N_("S390-SUBCHANNELS")}, /* 2 */ {NULL, NULL} }; -#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_ALL "NAME,CARRIER" -#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_COMMON "NAME,CARRIER" +#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_ALL "NAME,CARRIER,S390-SUBCHANNELS" +#define NMC_FIELDS_DEV_SHOW_WIRED_PROP_COMMON "NAME,CARRIER,S390-SUBCHANNELS" /* Available fields for 'device show' - wireless properties part */ static NmcOutputField nmc_fields_dev_show_wifi_prop[] = { @@ -978,6 +979,7 @@ show_device_info (NMDevice *device, NmCli *nmc) set_val_strc (arr, 0, nmc_fields_dev_show_sections[4].name); /* "WIRED-PROPERTIES" */ set_val_strc (arr, 1, (nm_device_ethernet_get_carrier (NM_DEVICE_ETHERNET (device))) ? _("on") : _("off")); + set_val_arrc (arr, 2, ((const char **) nm_device_ethernet_get_s390_subchannels (NM_DEVICE_ETHERNET (device)))); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ diff --git a/introspection/nm-device-ethernet.xml b/introspection/nm-device-ethernet.xml index 2554bda17f..86d68a35ab 100644 --- a/introspection/nm-device-ethernet.xml +++ b/introspection/nm-device-ethernet.xml @@ -22,6 +22,12 @@ </tp:docstring> </property> + <property name="S390Subchannels" type="as" access="read"> + <tp:docstring> + Array of S/390 subchannels for S/390 or z/Architecture devices. + </tp:docstring> + </property> + <property name="Carrier" type="b" access="read"> <tp:docstring> Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not). diff --git a/libnm-glib/tests/test-nm-client.c b/libnm-glib/tests/test-nm-client.c index f3a581152a..3b269e0fdb 100644 --- a/libnm-glib/tests/test-nm-client.c +++ b/libnm-glib/tests/test-nm-client.c @@ -100,6 +100,29 @@ add_device (const char *method, const char *ifname, char **out_path) return TRUE; } +static gboolean +add_wired_device (const char *method, const char *ifname, char **out_path) +{ + const char *empty[] = { NULL }; + GError *error = NULL; + GVariant *ret; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + method, + g_variant_new ("(ss^as)", ifname, "/", empty), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); + if (out_path) + g_variant_get (ret, "(o)", out_path); + g_variant_unref (ret); + return TRUE; +} + /*******************************************************************/ typedef struct { @@ -168,7 +191,7 @@ test_device_added (void) g_assert (devices == NULL); /* Tell the test service to add a new device */ - add_device ("AddWiredDevice", "eth0", NULL); + add_wired_device ("AddWiredDevice", "eth0", NULL); g_signal_connect (client, "device-added", @@ -731,8 +754,8 @@ test_devices_array (void) /*************************************/ /* Add some devices */ add_device ("AddWifiDevice", "wlan0", &paths[0]); - add_device ("AddWiredDevice", "eth0", &paths[1]); - add_device ("AddWiredDevice", "eth1", &paths[2]); + add_wired_device ("AddWiredDevice", "eth0", &paths[1]); + add_wired_device ("AddWiredDevice", "eth1", &paths[2]); info.quit_count = 3; g_signal_connect (client, diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 6551bc3863..c04bfacf8d 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -858,6 +858,7 @@ libnm_1_0_6 { libnm_1_2_0 { global: nm_access_point_get_last_seen; + nm_device_ethernet_get_s390_subchannels; nm_device_get_metered; nm_device_get_nm_plugin_missing; nm_device_set_managed; diff --git a/libnm/nm-device-ethernet.c b/libnm/nm-device-ethernet.c index b0f710f8a2..537a6f4cac 100644 --- a/libnm/nm-device-ethernet.c +++ b/libnm/nm-device-ethernet.c @@ -42,6 +42,7 @@ typedef struct { char *perm_hw_address; guint32 speed; gboolean carrier; + char **s390_subchannels; } NMDeviceEthernetPrivate; enum { @@ -50,6 +51,7 @@ enum { PROP_PERM_HW_ADDRESS, PROP_SPEED, PROP_CARRIER, + PROP_S390_SUBCHANNELS, LAST_PROP }; @@ -120,18 +122,88 @@ nm_device_ethernet_get_carrier (NMDeviceEthernet *device) return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->carrier; } +/** + * nm_device_ethernet_get_s390_subchannels: + * @device: a #NMDeviceEthernet + * + * Return the list of s390 subchannels if the device supports them. + * + * Returns: (transfer none) (element-type utf8): array of strings, each specifying + * one subchannel the s390 device uses to communicate to the host. + * + * Since: 1.2 + **/ +const char * const * +nm_device_ethernet_get_s390_subchannels (NMDeviceEthernet *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL); + + return (const char * const *) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->s390_subchannels; +} + +static guint32 +_subchannels_count_num (const char * const *array) +{ + int i; + + if (!array) + return 0; + for (i = 0; array[i]; i++) + /* NOP */; + return i; +} + +static gboolean +match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + const char * const *subchans; + guint32 num1, num2; + int i, j; + + *try_mac = TRUE; + + subchans = nm_setting_wired_get_s390_subchannels (s_wired); + num1 = _subchannels_count_num (subchans); + num2 = _subchannels_count_num ((const char * const *) priv->s390_subchannels); + /* connection has no subchannels */ + if (num1 == 0) + return TRUE; + /* connection requires subchannels but the device has none */ + if (num2 == 0) + return FALSE; + /* number of subchannels differ */ + if (num1 != num2) + return FALSE; + + /* Make sure each subchannel in the connection is a subchannel of this device */ + for (i = 0; subchans[i]; i++) { + const char *candidate = subchans[i]; + gboolean found = FALSE; + + for (j = 0; priv->s390_subchannels[j]; j++) { + if (!g_strcmp0 (priv->s390_subchannels[j], candidate)) + found = TRUE; + } + if (!found) + return FALSE; /* a subchannel was not found */ + } + + *try_mac = FALSE; + return TRUE; +} + static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error) { NMSettingWired *s_wired; - gboolean is_pppoe = FALSE; if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->connection_compatible (device, connection, error)) return FALSE; - if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) - is_pppoe = TRUE; - else if (!nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { + if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) { + /* NOP */ + } else if (!nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, _("The connection was not an Ethernet or PPPoE connection.")); return FALSE; @@ -140,24 +212,49 @@ connection_compatible (NMDevice *device, NMConnection *connection, GError **erro s_wired = nm_connection_get_setting_wired (connection); /* Wired setting optional for PPPoE */ if (s_wired) { - const char *perm_addr, *setting_addr; - - /* FIXME: filter using s390 subchannels when they are exported over the bus */ + const char *perm_addr, *s_mac; + gboolean try_mac = TRUE; + const char * const *mac_blacklist; + int i; + + /* Check s390 subchannels */ + if (!match_subchans (NM_DEVICE_ETHERNET (device), s_wired, &try_mac)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection and device differ in S390 subchannels.")); + return FALSE; + } /* Check MAC address */ perm_addr = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device)); + s_mac = nm_setting_wired_get_mac_address (s_wired); if (perm_addr) { if (!nm_utils_hwaddr_valid (perm_addr, ETH_ALEN)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, _("Invalid device MAC address.")); return FALSE; } - setting_addr = nm_setting_wired_get_mac_address (s_wired); - if (setting_addr && !nm_utils_hwaddr_matches (setting_addr, -1, perm_addr, -1)) { + if (try_mac && s_mac && !nm_utils_hwaddr_matches (s_mac, -1, perm_addr, -1)) { g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, - _("The MACs of the device and the connection didn't match.")); + _("The MACs of the device and the connection do not match.")); return FALSE; } + + /* Check for MAC address blacklist */ + mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); + for (i = 0; mac_blacklist[i]; i++) { + if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) { + g_warn_if_reached (); + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("Invalid MAC in the blacklist: %s."), mac_blacklist[i]); + return FALSE; + } + + if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_addr, -1)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("Device MAC (%s) is blacklisted by the connection."), perm_addr); + return FALSE; + } + } } } @@ -193,6 +290,7 @@ init_dbus (NMObject *object) { NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, &priv->perm_hw_address }, { NM_DEVICE_ETHERNET_SPEED, &priv->speed }, { NM_DEVICE_ETHERNET_CARRIER, &priv->carrier }, + { NM_DEVICE_ETHERNET_S390_SUBCHANNELS, &priv->s390_subchannels }, { NULL }, }; @@ -210,6 +308,7 @@ finalize (GObject *object) g_free (priv->hw_address); g_free (priv->perm_hw_address); + g_strfreev (priv->s390_subchannels); G_OBJECT_CLASS (nm_device_ethernet_parent_class)->finalize (object); } @@ -221,6 +320,7 @@ get_property (GObject *object, GParamSpec *pspec) { NMDeviceEthernet *device = NM_DEVICE_ETHERNET (object); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); switch (prop_id) { case PROP_HW_ADDRESS: @@ -235,6 +335,9 @@ get_property (GObject *object, case PROP_CARRIER: g_value_set_boolean (value, nm_device_ethernet_get_carrier (device)); break; + case PROP_S390_SUBCHANNELS: + g_value_set_boxed (value, priv->s390_subchannels); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -312,4 +415,18 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMDeviceEthernet:s390-subchannels: + * + * Identifies subchannels of this network device used for + * communication with z/VM or s390 host. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_S390_SUBCHANNELS, + g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm/nm-device-ethernet.h b/libnm/nm-device-ethernet.h index 09286e73a7..07cf4c4de6 100644 --- a/libnm/nm-device-ethernet.h +++ b/libnm/nm-device-ethernet.h @@ -41,6 +41,7 @@ G_BEGIN_DECLS #define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" #define NM_DEVICE_ETHERNET_SPEED "speed" #define NM_DEVICE_ETHERNET_CARRIER "carrier" +#define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels" struct _NMDeviceEthernet { NMDevice parent; @@ -59,6 +60,8 @@ const char * nm_device_ethernet_get_hw_address (NMDeviceEthernet *device); const char * nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device); guint32 nm_device_ethernet_get_speed (NMDeviceEthernet *device); gboolean nm_device_ethernet_get_carrier (NMDeviceEthernet *device); +NM_AVAILABLE_IN_1_2 +const char * const *nm_device_ethernet_get_s390_subchannels (NMDeviceEthernet *device); G_END_DECLS diff --git a/libnm/tests/common.c b/libnm/tests/common.c index f2cdc59320..5b3f74eb27 100644 --- a/libnm/tests/common.c +++ b/libnm/tests/common.c @@ -149,22 +149,53 @@ timeout (gpointer user_data) return G_SOURCE_REMOVE; } -NMDevice * -nm_test_service_add_device (NMTestServiceInfo *sinfo, NMClient *client, - const char *method, const char *ifname) +static GVariant * +call_add_wired_device (GDBusProxy *proxy, const char *ifname, const char *hwaddr, + const char **subchannels, GError **error) { - AddDeviceInfo info; - GError *error = NULL; - GVariant *ret; - guint timeout_id; + const char *empty[] = { NULL }; + + if (!hwaddr) + hwaddr = "/"; + if (!subchannels) + subchannels = empty; + + return g_dbus_proxy_call_sync (proxy, + "AddWiredDevice", + g_variant_new ("(ss^as)", ifname, hwaddr, subchannels), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + error); +} - ret = g_dbus_proxy_call_sync (sinfo->proxy, +static GVariant * +call_add_device (GDBusProxy *proxy, const char *method, const char *ifname, GError **error) +{ + return g_dbus_proxy_call_sync (proxy, method, g_variant_new ("(s)", ifname), G_DBUS_CALL_FLAGS_NO_AUTO_START, 3000, NULL, - &error); + error); +} + +static NMDevice * +add_device_common (NMTestServiceInfo *sinfo, NMClient *client, + const char *method, const char *ifname, + const char *hwaddr, const char **subchannels) +{ + AddDeviceInfo info; + GError *error = NULL; + GVariant *ret; + guint timeout_id; + + if (g_strcmp0 (method, "AddWiredDevice") == 0) + ret = call_add_wired_device (sinfo->proxy, ifname, hwaddr, subchannels, &error); + else + ret = call_add_device (sinfo->proxy, method, ifname, &error); + g_assert_no_error (error); g_assert (ret); g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); @@ -186,3 +217,18 @@ nm_test_service_add_device (NMTestServiceInfo *sinfo, NMClient *client, return info.device; } + +NMDevice * +nm_test_service_add_device (NMTestServiceInfo *sinfo, NMClient *client, + const char *method, const char *ifname) +{ + return add_device_common (sinfo, client, method, ifname, NULL, NULL); +} + +NMDevice * +nm_test_service_add_wired_device (NMTestServiceInfo *sinfo, NMClient *client, + const char *ifname, const char *hwaddr, + const char **subchannels) +{ + return add_device_common (sinfo, client, "AddWiredDevice", ifname, hwaddr, subchannels); +} diff --git a/libnm/tests/common.h b/libnm/tests/common.h index 4919d3fda1..501ea16c4e 100644 --- a/libnm/tests/common.h +++ b/libnm/tests/common.h @@ -36,3 +36,10 @@ NMDevice *nm_test_service_add_device (NMTestServiceInfo *info, NMClient *client, const char *method, const char *ifname); + +NMDevice * nm_test_service_add_wired_device (NMTestServiceInfo *sinfo, + NMClient *client, + const char *ifname, + const char *hwaddr, + const char **subchannels); + diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c index ccd952c96f..9da5647147 100644 --- a/libnm/tests/test-nm-client.c +++ b/libnm/tests/test-nm-client.c @@ -1160,6 +1160,77 @@ test_activate_failed (void) g_clear_pointer (&sinfo, nm_test_service_cleanup); } +static void +test_device_connection_compatibility (void) +{ + NMClient *client; + NMDevice *device1, *device2; + NMConnection *conn; + NMSettingWired *s_wired; + GError *error = NULL; + const char *subchannels[] = { "0.0.8000", "0.0.8001", "0.0.8002", NULL }; + const char *subchannels_2[] = { "0.0.8000", "0.0.8001", NULL }; + const char *subchannels_x[] = { "0.0.8000", "0.0.8001", "0.0.800X", NULL }; + const char *hw_addr1 = "52:54:00:ab:db:23"; + const char *hw_addr2 = "52:54:00:ab:db:24"; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + /* Create two devices */ + device1 = nm_test_service_add_wired_device (sinfo, client, "eth0", hw_addr1, subchannels); + device2 = nm_test_service_add_wired_device (sinfo, client, "eth1", hw_addr2, NULL); + + g_assert_cmpstr (nm_device_get_hw_address (device1), ==, hw_addr1); + g_assert_cmpstr (nm_device_get_hw_address (device2), ==, hw_addr2); + + conn = nmtst_create_minimal_connection ("wired-matches", NULL, + NM_SETTING_WIRED_SETTING_NAME, NULL); + s_wired = nm_connection_get_setting_wired (conn); + nm_setting_wired_add_mac_blacklist_item (s_wired, "00:11:22:33:44:55"); + + /* device1 and conn are compatible */ + g_object_set (s_wired, + NM_SETTING_WIRED_MAC_ADDRESS, hw_addr1, + NM_SETTING_WIRED_S390_SUBCHANNELS, subchannels, + NULL); + nm_device_connection_compatible (device1, conn, &error); + g_assert_no_error (error); + + /* device2 and conn differ in subchannels */ + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, subchannels_x, NULL); + nm_device_connection_compatible (device2, conn, &error); + g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION); + g_clear_error (&error); + + /* device1 and conn differ in subchannels - 2 in connection, 3 in device */ + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, subchannels_2, NULL); + nm_device_connection_compatible (device1, conn, &error); + g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION); + g_clear_error (&error); + + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, NULL, NULL); + + /* device2 and conn differ in MAC address */ + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, "aa:bb:cc:dd:ee:ee", NULL); + nm_device_connection_compatible (device2, conn, &error); + g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION); + g_clear_error (&error); + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, NULL, NULL); + + /* device1 is blacklisted in conn */ + nm_setting_wired_add_mac_blacklist_item (s_wired, hw_addr1); + nm_device_connection_compatible (device1, conn, &error); + g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION); + g_clear_error (&error); + + g_object_unref (conn); + g_object_unref (client); + + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + /*******************************************************************/ NMTST_DEFINE (); @@ -1182,6 +1253,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/active-connections", test_active_connections); g_test_add_func ("/libnm/activate-virtual", test_activate_virtual); g_test_add_func ("/libnm/activate-failed", test_activate_failed); + g_test_add_func ("/libnm/device-connection-compatibility", test_device_connection_compatibility); return g_test_run (); } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 319ce1fc85..556569e1d6 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -104,6 +104,7 @@ typedef struct { char * subchan2; char * subchan3; char * subchannels; /* Composite used for checking unmanaged specs */ + char ** subchannels_dbus; /* Array exported on D-Bus */ char * s390_nettype; GHashTable * s390_options; @@ -123,6 +124,7 @@ enum { PROP_0, PROP_PERM_HW_ADDRESS, PROP_SPEED, + PROP_S390_SUBCHANNELS, LAST_PROP }; @@ -225,6 +227,12 @@ _update_s390_subchannels (NMDeviceEthernet *self) } else priv->subchannels = g_strdup (priv->subchan1); + priv->subchannels_dbus = g_new (char *, 3 + 1); + priv->subchannels_dbus[0] = g_strdup (priv->subchan1); + priv->subchannels_dbus[1] = g_strdup (priv->subchan2); + priv->subchannels_dbus[2] = g_strdup (priv->subchan3); + priv->subchannels_dbus[3] = NULL; + driver = nm_device_get_driver (NM_DEVICE (self)); _LOGI (LOGD_DEVICE | LOGD_HW, "found s390 '%s' subchannels [%s]", driver ? driver : "(unknown driver)", priv->subchannels); @@ -318,21 +326,39 @@ get_generic_capabilities (NMDevice *device) } } +static guint32 +_subchannels_count_num (const char * const *array) +{ + int i; + + if (!array) + return 0; + for (i = 0; array[i]; i++) + /* NOP */; + return i; +} + static gboolean match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); const char * const *subchans; + guint32 num1, num2; int i; *try_mac = TRUE; subchans = nm_setting_wired_get_s390_subchannels (s_wired); - if (!subchans) + num1 = _subchannels_count_num (subchans); + num2 = _subchannels_count_num ((const char * const *) priv->subchannels_dbus); + /* connection has no subchannels */ + if (num1 == 0) return TRUE; - /* connection requires subchannels but the device has none */ - if (!priv->subchannels) + if (num2 == 0) + return FALSE; + /* number of subchannels differ */ + if (num1 != num2) return FALSE; /* Make sure each subchannel in the connection is a subchannel of this device */ @@ -1546,16 +1572,8 @@ update_connection (NMDevice *device, NMConnection *connection) /* We don't set the MTU as we don't know whether it was set explicitly */ /* s390 */ - if (priv->subchannels) { - char **subchannels = g_new (char *, 3 + 1); - - subchannels[0] = g_strdup (priv->subchan1); - subchannels[1] = g_strdup (priv->subchan2); - subchannels[2] = g_strdup (priv->subchan3); - subchannels[3] = NULL; - g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, subchannels, NULL); - g_strfreev (subchannels); - } + if (priv->subchannels_dbus) + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, priv->subchannels_dbus, NULL); if (priv->s390_nettype) g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, priv->s390_nettype, NULL); g_hash_table_iter_init (&iter, priv->s390_options); @@ -1631,6 +1649,7 @@ finalize (GObject *object) g_free (priv->subchan2); g_free (priv->subchan3); g_free (priv->subchannels); + g_strfreev (priv->subchannels_dbus); g_free (priv->s390_nettype); g_hash_table_destroy (priv->s390_options); @@ -1651,6 +1670,9 @@ get_property (GObject *object, guint prop_id, case PROP_SPEED: g_value_set_uint (value, priv->speed); break; + case PROP_S390_SUBCHANNELS: + g_value_set_boxed (value, priv->subchannels_dbus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1718,6 +1740,13 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_S390_SUBCHANNELS, + g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_ETHERNET_SKELETON, NULL); diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h index 325225a3c8..2d284822d2 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/devices/nm-device-ethernet.h @@ -35,6 +35,7 @@ G_BEGIN_DECLS #define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" #define NM_DEVICE_ETHERNET_SPEED "speed" +#define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels" typedef NMDevice NMDeviceEthernet; typedef NMDeviceClass NMDeviceEthernetClass; diff --git a/tools/test-networkmanager-service.py b/tools/test-networkmanager-service.py index 6035fecd5c..260810019c 100755 --- a/tools/test-networkmanager-service.py +++ b/tools/test-networkmanager-service.py @@ -207,14 +207,19 @@ PE_HW_ADDRESS = "HwAddress" PE_PERM_HW_ADDRESS = "PermHwAddress" PE_SPEED = "Speed" PE_CARRIER = "Carrier" +PE_S390_SUBCHANNELS = "S390Subchannels" class WiredDevice(Device): - def __init__(self, bus, iface): + def __init__(self, bus, iface, mac, subchannels): Device.__init__(self, bus, iface, NM_DEVICE_TYPE_ETHERNET) self.add_dbus_interface(IFACE_WIRED, self.__get_props) - self.mac = random_mac() + if mac is None: + self.mac = random_mac() + else: + self.mac = mac self.carrier = False + self.s390_subchannels = subchannels # Properties interface def __get_props(self): @@ -223,6 +228,7 @@ class WiredDevice(Device): props[PE_PERM_HW_ADDRESS] = self.mac props[PE_SPEED] = dbus.UInt32(100) props[PE_CARRIER] = self.carrier + props[PE_S390_SUBCHANNELS] = self.s390_subchannels return props def __notify(self, propname): @@ -838,12 +844,12 @@ class NetworkManager(ExportedObj): def Quit(self): mainloop.quit() - @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') - def AddWiredDevice(self, ifname): + @dbus.service.method(IFACE_TEST, in_signature='ssas', out_signature='o') + def AddWiredDevice(self, ifname, mac, subchannels): for d in self.devices: if d.iface == ifname: raise PermissionDeniedException("Device already added") - dev = WiredDevice(self._bus, ifname) + dev = WiredDevice(self._bus, ifname, mac, subchannels) self.add_device(dev) return to_path(dev) |