From c02d1c488f69ed6183cb86c80a771c902ea5e397 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 24 May 2018 17:32:37 +0200 Subject: ifcfg-rh: SR-IOV support --- Makefile.am | 2 + libnm-core/nm-setting-sriov.c | 22 +++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 67 +++++++++ .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 41 ++++++ src/settings/plugins/ifcfg-rh/shvar.c | 4 + src/settings/plugins/ifcfg-rh/shvar.h | 1 + .../tests/network-scripts/ifcfg-test-sriov | 19 +++ .../ifcfg-test-sriov-write.cexpected | 18 +++ .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 150 +++++++++++++++++++++ 9 files changed, 324 insertions(+) create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected diff --git a/Makefile.am b/Makefile.am index ab9f649a85..45074fa1e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2303,6 +2303,8 @@ EXTRA_DIST += \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov \ + src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected \ src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc \ diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c index 45608f9dc8..29161c8cd9 100644 --- a/libnm-core/nm-setting-sriov.c +++ b/libnm-core/nm-setting-sriov.c @@ -1250,6 +1250,13 @@ nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) * * Since: 1.14 **/ + /* ---ifcfg-rh--- + * property: total-vfs + * variable: SRIOV_TOTAL_VFS(+) + * description: The total number of virtual functions to create + * example: SRIOV_TOTAL_VFS=16 + * ---end--- + */ g_object_class_install_property (object_class, PROP_TOTAL_VFS, g_param_spec_uint (NM_SETTING_SRIOV_TOTAL_VFS, "", "", @@ -1286,6 +1293,13 @@ nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) * * Since: 1.14 **/ + /* ---ifcfg-rh--- + * property: vfs + * variable: SRIOV_VF1(+), SRIOV_VF2(+), ... + * description: SR-IOV virtual function descriptors + * example: SRIOV_VF10="mac=00:11:22:33:44:55", ... + * ---end--- + */ g_object_class_install_property (object_class, PROP_VFS, g_param_spec_boxed (NM_SETTING_SRIOV_VFS, "", "", @@ -1319,6 +1333,14 @@ nm_setting_sriov_class_init (NMSettingSriovClass *setting_class) * * Since: 1.14 **/ + /* ---ifcfg-rh--- + * property: autoprobe-drivers + * variable: SRIOV_AUTOPROBE_DRIVERS(+) + * default: missing variable means global default + * description: Whether to autoprobe virtual functions by a compatible driver + * example: SRIOV_AUTOPROBE_DRIVERS=0,1 + * ---end--- + */ g_object_class_install_property (object_class, PROP_AUTOPROBE_DRIVERS, g_param_spec_enum (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, "", "", diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 882932b11a..5cea628013 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -1978,6 +1978,68 @@ error: return NULL; } +static NMSetting * +make_sriov_setting (shvarFile *ifcfg) +{ + gs_unref_hashtable GHashTable *keys = NULL; + gs_unref_ptrarray GPtrArray *vfs = NULL; + NMTernary autoprobe_drivers; + NMSettingSriov *s_sriov; + int total_vfs; + + total_vfs = svGetValueInt64 (ifcfg, "SRIOV_TOTAL_VFS", 10, 0, G_MAXINT32, 0); + if (!total_vfs) + return NULL; + + autoprobe_drivers = svGetValueInt64 (ifcfg, + "SRIOV_AUTOPROBE_DRIVERS", + 10, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + NM_TERNARY_DEFAULT); + + keys = svGetKeys (ifcfg, SV_KEY_TYPE_SRIOV_VF); + if (keys) { + GHashTableIter iter; + const char *key; + + g_hash_table_iter_init (&iter, keys); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + gs_free_error GError *error = NULL; + gs_free char *value_to_free = NULL; + const char *value; + NMSriovVF *vf; + + nm_assert (g_str_has_prefix (key, "SRIOV_VF")); + + value = svGetValue (ifcfg, key, &value_to_free); + if (!value) + continue; + + key += NM_STRLEN ("SRIOV_VF"); + + vf = _nm_utils_sriov_vf_from_strparts (key, value, &error); + if (!vf) { + PARSE_WARNING ("ignoring invalid SR-IOV VF '%s %s': %s", + key, value, error->message); + continue; + } + if (!vfs) + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + g_ptr_array_add (vfs, vf); + } + } + + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + g_object_set (s_sriov, + NM_SETTING_SRIOV_TOTAL_VFS, total_vfs, + NM_SETTING_SRIOV_VFS, vfs, + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, (int) autoprobe_drivers, + NULL); + + return (NMSetting *) s_sriov; +} + static NMSetting * make_tc_setting (shvarFile *ifcfg) { @@ -5324,6 +5386,7 @@ connection_from_file_full (const char *filename, gs_free char *type = NULL; char *devtype, *bootproto; NMSetting *s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user; + NMSetting *s_sriov; const char *ifcfg_name = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; @@ -5579,6 +5642,10 @@ connection_from_file_full (const char *filename, nm_connection_add_setting (connection, s_ip4); } + s_sriov = make_sriov_setting (parsed); + if (s_sriov) + nm_connection_add_setting (connection, s_sriov); + s_tc = make_tc_setting (parsed); if (s_tc) nm_connection_add_setting (connection, s_tc); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 8921646597..ab1938f180 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -2135,6 +2135,45 @@ write_user_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } +static void +write_sriov_setting (NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingSriov *s_sriov; + guint i, num = 0; + NMTernary b; + NMSriovVF *vf; + char key[32]; + char *str; + + svUnsetAll (ifcfg, SV_KEY_TYPE_SRIOV_VF); + + s_sriov = nm_connection_get_setting_sriov (connection); + if (s_sriov) + num = nm_setting_sriov_get_total_vfs (s_sriov); + if (num == 0) { + svUnsetValue (ifcfg, "SRIOV_TOTAL_VFS"); + svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); + return; + } + + svSetValueInt64 (ifcfg, "SRIOV_TOTAL_VFS", num); + + b = nm_setting_sriov_get_autoprobe_drivers (s_sriov); + if (b != NM_TERNARY_DEFAULT) + svSetValueInt64 (ifcfg, "SRIOV_AUTOPROBE_DRIVERS", b); + else + svUnsetValue (ifcfg, "SRIOV_AUTOPROBE_DRIVERS"); + + num = nm_setting_sriov_get_num_vfs (s_sriov); + for (i = 0; i < num; i++) { + vf = nm_setting_sriov_get_vf (s_sriov, i); + nm_sprintf_buf (key, "SRIOV_VF%u", nm_sriov_vf_get_index (vf)); + str = nm_utils_sriov_vf_to_str (vf, TRUE, NULL); + svSetValueStr (ifcfg, key, str); + g_free (str); + } +} + static gboolean write_tc_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) { @@ -2921,6 +2960,8 @@ do_write_construct (NMConnection *connection, if (!write_user_setting (connection, ifcfg, error)) return FALSE; + write_sriov_setting (connection, ifcfg); + if (!write_tc_setting (connection, ifcfg, error)) return FALSE; diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index e8d028094b..f09bc2472f 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -915,6 +915,10 @@ _svKeyMatchesType (const char *key, SvKeyType match_key_type) || IS_NUMBERED_TAG (key, "FILTER")) return TRUE; } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_SRIOV_VF)) { + if (IS_NUMBERED_TAG (key, "SRIOV_VF")) + return TRUE; + } return FALSE; } diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index bef5f47743..622bb474b1 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -39,6 +39,7 @@ typedef enum { SV_KEY_TYPE_IP4_ADDRESS = (1LL << 2), SV_KEY_TYPE_TC = (1LL << 3), SV_KEY_TYPE_USER = (1LL << 4), + SV_KEY_TYPE_SRIOV_VF = (1LL << 5), } SvKeyType; const char *svFileGetName (const shvarFile *s); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov new file mode 100644 index 0000000000..142f56e434 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov @@ -0,0 +1,19 @@ +TYPE=Ethernet +DEVICE=eth0 +HWADDR=00:11:22:33:44:55 +BOOTPROTO=none +ONBOOT=yes +DNS1=4.2.2.1 +DNS2=4.2.2.2 +IPADDR=192.168.1.5 +PREFIX=24 +NETMASK=255.255.255.0 +GATEWAY=192.168.1.1 +IPV6INIT=no +NAME=ethernet-sriov +UUID=acc703b8-e751-44ce-b456-1550bdf2057e +SRIOV_TOTAL_VFS=16 +SRIOV_AUTOPROBE_DRIVERS=0 +SRIOV_VF15="max-tx-rate=200 mac=01:23:45:67:89:ab vlans=2" +SRIOV_VF12="trust=false min-tx-rate=100 vlans=1.200.ad" +SRIOV_VF3="mac=55:44:33:22:11:00 spoof-check=true" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected new file mode 100644 index 0000000000..c882c4796e --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected @@ -0,0 +1,18 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +SRIOV_TOTAL_VFS=64 +SRIOV_AUTOPROBE_DRIVERS=1 +SRIOV_VF2="mac=55:55:55:55:55:55 vlans=3.10.ad;10" +SRIOV_VF19=spoof-check=true +BOOTPROTO=none +IPADDR=1.1.1.3 +PREFIX=24 +GATEWAY=1.1.1.1 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write SR-IOV config" +UUID=${UUID} +DEVICE=eth0 +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 1331391dc2..8d4efbbfd1 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -9632,6 +9632,153 @@ test_utils_ignore (void) do_test_utils_ignored ("ignored-augtmp", "ifcfg-FooBar" AUGTMP_TAG, TRUE); } +/*****************************************************************************/ + +static void +test_sriov_read (void) +{ + gs_unref_object NMConnection *connection = NULL; + NMSettingSriov *s_sriov; + NMSriovVF *vf; + GVariant *variant; + GError *error = NULL; + char *str; + + connection = _connection_from_file (TEST_IFCFG_DIR "/ifcfg-test-sriov", + NULL, TYPE_ETHERNET,NULL); + + g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "eth0"); + + s_sriov = nm_connection_get_setting_sriov (connection); + g_assert (s_sriov); + + g_assert_cmpint (nm_setting_sriov_get_total_vfs (s_sriov), ==, 16); + g_assert_cmpint (nm_setting_sriov_get_num_vfs (s_sriov), ==, 3); + g_assert_cmpint (nm_setting_sriov_get_autoprobe_drivers (s_sriov), ==, NM_TERNARY_FALSE); + + /* VF 3 */ + vf = nm_setting_sriov_get_vf (s_sriov, 0); + g_assert (vf); + g_assert_cmpint (nm_sriov_vf_get_index (vf), ==, 3); + + variant = nm_sriov_vf_get_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_MAC); + g_assert (variant); + g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "55:44:33:22:11:00"); + + variant = nm_sriov_vf_get_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK); + g_assert (variant); + g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)); + g_assert_cmpint (g_variant_get_boolean (variant), ==, TRUE); + + /* VF 12 */ + vf = nm_setting_sriov_get_vf (s_sriov, 1); + str = nm_utils_sriov_vf_to_str (vf, FALSE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, "12 min-tx-rate=100 trust=false vlans=1.200.ad"); + g_free (str); + + /* VF 15 */ + vf = nm_setting_sriov_get_vf (s_sriov, 2); + str = nm_utils_sriov_vf_to_str (vf, FALSE, &error); + g_assert_no_error (error); + g_assert_cmpstr (str, ==, "15 mac=01:23:45:67:89:ab max-tx-rate=200 vlans=2"); + g_free (str); +} + +static void +test_sriov_write (void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingConnection *s_con; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + NMSettingWired *s_wired; + NMSettingSriov *s_sriov; + NMSriovVF *vf; + gs_unref_ptrarray GPtrArray *vfs = NULL; + NMIPAddress *addr; + GError *error = NULL; + + connection = nm_simple_connection_new (); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write SR-IOV config", + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0", + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* IP4 setting */ + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", + NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NULL); + + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); + g_assert_no_error (error); + nm_setting_ip_config_add_address (s_ip4, addr); + nm_ip_address_unref (addr); + + /* IP6 setting */ + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NULL); + + /* SRIOV setting */ + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + nm_connection_add_setting (connection, NM_SETTING (s_sriov)); + + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + + vf = nm_utils_sriov_vf_from_str ("2 mac=55:55:55:55:55:55 vlans=3.10.ad;10", &error); + nmtst_assert_success (vf, error); + g_ptr_array_add (vfs, vf); + + vf = nm_utils_sriov_vf_from_str ("19 spoof-check=true", &error); + nmtst_assert_success (vf, error); + g_ptr_array_add (vfs, vf); + + g_object_set (s_sriov, + NM_SETTING_SRIOV_TOTAL_VFS, 64, + NM_SETTING_SRIOV_VFS, vfs, + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, NM_TERNARY_TRUE, + NULL); + + nm_connection_add_setting (connection, nm_setting_proxy_new ()); + + nmtst_assert_connection_verifies_without_normalization (connection); + + _writer_new_connec_exp (connection, + TEST_SCRATCH_DIR, + TEST_IFCFG_DIR "/ifcfg-test-sriov-write.cexpected", + &testfile); + + reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); +} + +/*****************************************************************************/ + static void test_tc_read (void) { @@ -10033,6 +10180,9 @@ int main (int argc, char **argv) g_test_add_func (TPATH "utils/path", test_utils_path); g_test_add_func (TPATH "utils/ignore", test_utils_ignore); + g_test_add_func (TPATH "sriov/read", test_sriov_read); + g_test_add_func (TPATH "sriov/write", test_sriov_write); + g_test_add_func (TPATH "tc/read", test_tc_read); g_test_add_func (TPATH "tc/write", test_tc_write); -- cgit v1.2.1