From 3a09a7e991e7f09a0b453a372e1f79ad3ed68c96 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 14:40:39 +0100 Subject: [PATCH 1/9] nmtst: add nmtst_assert_variant_*() helper macros --- shared/nm-test-utils.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h index 694e84ccd0..b11b310733 100644 --- a/shared/nm-test-utils.h +++ b/shared/nm-test-utils.h @@ -1774,6 +1774,34 @@ nmtst_create_connection_from_keyfile (const char *keyfile_str, const char *keyfi #ifdef __NM_CONNECTION_H__ +#define nmtst_assert_variant_is_of_type(variant, type) \ + G_STMT_START { \ + GVariant *_variantx = (variant); \ + \ + g_assert (_variantx); \ + g_assert (g_variant_is_of_type (_variantx, (type))); \ + } G_STMT_END + +#define nmtst_assert_variant_uint32(variant, val) \ + G_STMT_START { \ + GVariant *_variant = (variant); \ + \ + nmtst_assert_variant_is_of_type (_variant, G_VARIANT_TYPE_UINT32); \ + g_assert_cmpint (g_variant_get_uint32 (_variant), ==, (val)); \ + } G_STMT_END + +#define nmtst_assert_variant_string(variant, str) \ + G_STMT_START { \ + gsize _l; \ + GVariant *_variant = (variant); \ + const char *_str = (str); \ + \ + nmtst_assert_variant_is_of_type (_variant, G_VARIANT_TYPE_STRING); \ + g_assert (_str); \ + g_assert_cmpstr (g_variant_get_string (_variant, &_l), ==, _str); \ + g_assert_cmpint (_l, ==, strlen (_str)); \ + } G_STMT_END + typedef enum { NMTST_VARIANT_EDITOR_CONNECTION, NMTST_VARIANT_EDITOR_SETTING, From 0cee9ef7b534ee63ffcf4b4a41e9de12cde50b38 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 16:46:30 +0100 Subject: [PATCH 2/9] nmtst: add nmtst_main_loop_quit_on_notify function --- shared/nm-test-utils.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h index b11b310733..6e705dce5c 100644 --- a/shared/nm-test-utils.h +++ b/shared/nm-test-utils.h @@ -853,6 +853,18 @@ nmtst_main_loop_run (GMainLoop *loop, int timeout_ms) return loopx != NULL; } +inline static void +_nmtst_main_loop_quit_on_notify (GObject *object, GParamSpec *pspec, gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_assert (G_IS_OBJECT (object)); + g_assert (loop); + + g_main_loop_quit (loop); +} +#define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify) + /*****************************************************************************/ inline static const char * From 3802fd46dd6a5f6fc057e35dd92270f316de6a8c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 16:24:48 +0100 Subject: [PATCH 3/9] lldp: fix name of NM_LLDP_ATTR_IEEE_802_1_VID string Fixes: 07a9364d9c151bc3086a863759d31d0857ae011e --- libnm-core/nm-dbus-interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 1b16cce527..d76c564061 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -669,7 +669,7 @@ typedef enum /*< flags >*/ { #define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid" #define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid" #define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags" -#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-pvid" +#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-vid" #define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name" #define NM_LLDP_DEST_NEAREST_BRIDGE "nearest-bridge" From 57af1d6e2af09c6548459ff10fd1ca7a0d2e23e6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 12:26:02 +0100 Subject: [PATCH 4/9] lldp/tests/trivial: some renaming and moving of code --- src/devices/tests/test-lldp.c | 125 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 978821a686..96dd4dda8a 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -32,62 +32,7 @@ #include "nm-test-utils.h" -typedef struct { - int ifindex; - int fd; - guint8 mac[ETH_ALEN]; -} test_fixture; - -#define TEST_IFNAME "nm-tap-test0" - -static void -fixture_setup (test_fixture *fixture, gconstpointer user_data) -{ - const NMPlatformLink *link; - struct ifreq ifr = { }; - int fd, s; - - fd = open ("/dev/net/tun", O_RDWR); - g_assert (fd >= 0); - - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); - g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); - - /* Bring the interface up */ - s = socket (AF_INET, SOCK_DGRAM, 0); - g_assert (s >= 0); - ifr.ifr_flags |= IFF_UP; - g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); - close (s); - - nm_platform_process_events (NM_PLATFORM_GET); - link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); - g_assert (link); - fixture->ifindex = link->ifindex; - fixture->fd = fd; - memcpy (fixture->mac, link->addr.data, ETH_ALEN); -} - -typedef struct { - int num_called; -} TestInfo; - -static gboolean -loop_quit (gpointer user_data) -{ - g_main_loop_quit ((GMainLoop *) user_data); - return G_SOURCE_REMOVE; -} - -static void -lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, - gpointer user_data) -{ - TestInfo *info = user_data; - - info->num_called++; -} +/*****************************************************************************/ static GVariant * get_lldp_neighbor_attribute (GVariant *neighbors, @@ -138,12 +83,69 @@ get_lldp_neighbor_attribute (GVariant *neighbors, return NULL; } +typedef struct { + int ifindex; + int fd; + guint8 mac[ETH_ALEN]; +} TestRecvFixture; + +#define TEST_IFNAME "nm-tap-test0" + static void -test_receive_frame (test_fixture *fixture, gconstpointer user_data) +_test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) +{ + const NMPlatformLink *link; + struct ifreq ifr = { }; + int fd, s; + + fd = open ("/dev/net/tun", O_RDWR); + g_assert (fd >= 0); + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + nm_utils_ifname_cpy (ifr.ifr_name, TEST_IFNAME); + g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); + + /* Bring the interface up */ + s = socket (AF_INET, SOCK_DGRAM, 0); + g_assert (s >= 0); + ifr.ifr_flags |= IFF_UP; + g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); + close (s); + + nm_platform_process_events (NM_PLATFORM_GET); + link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); + g_assert (link); + fixture->ifindex = link->ifindex; + fixture->fd = fd; + memcpy (fixture->mac, link->addr.data, ETH_ALEN); +} + +typedef struct { + int num_called; +} TestRecvCallbackInfo; + +static gboolean +loop_quit (gpointer user_data) +{ + g_main_loop_quit ((GMainLoop *) user_data); + return G_SOURCE_REMOVE; +} + +static void +lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, + gpointer user_data) +{ + TestRecvCallbackInfo *info = user_data; + + info->num_called++; +} + +static void +test_recv (TestRecvFixture *fixture, gconstpointer user_data) { gs_unref_object NMLldpListener *listener = NULL; GMainLoop *loop; - TestInfo info = { }; + TestRecvCallbackInfo info = { }; GVariant *neighbors, *attr; uint8_t frame[] = { /* Ethernet header */ @@ -209,11 +211,13 @@ test_receive_frame (test_fixture *fixture, gconstpointer user_data) } static void -fixture_teardown (test_fixture *fixture, gconstpointer user_data) +_test_recv_fixture_teardown (TestRecvFixture *fixture, gconstpointer user_data) { nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); } +/*****************************************************************************/ + void init_tests (int *argc, char ***argv) { @@ -223,6 +227,5 @@ init_tests (int *argc, char ***argv) void setup_tests (void) { - g_test_add ("/lldp/receive_frame", test_fixture, NULL, fixture_setup, - test_receive_frame, fixture_teardown); + g_test_add ("/lldp/recv", TestRecvFixture, NULL, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown); } From c44261789900fc7e92eceb35d9437347bdcc9039 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 12:33:28 +0100 Subject: [PATCH 5/9] lldp/tests: refactor tests to run receive different frames --- src/devices/nm-lldp-listener.c | 2 + src/devices/tests/test-lldp.c | 146 +++++++++++++++++++++------------ 2 files changed, 97 insertions(+), 51 deletions(-) diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 8182781766..c9202c4323 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -538,6 +538,8 @@ nm_lldp_listener_get_neighbors (NMLldpListener *self) LLDPNeighbor *neigh; char *dest_str = NULL; + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); if (priv->variant) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 96dd4dda8a..7f4fd1176d 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -89,8 +89,88 @@ typedef struct { guint8 mac[ETH_ALEN]; } TestRecvFixture; +typedef struct { + gsize frame_len; + const uint8_t *frame; +} TestRecvFrame; +#define TEST_RECV_FRAME_DEFINE(name, ...) \ + static const guint8 _##name##_v[] = { __VA_ARGS__ }; \ + static const TestRecvFrame name = { \ + .frame_len = sizeof (_##name##_v), \ + .frame = _##name##_v, \ + } + +typedef struct { + guint expected_num_called; + gsize frames_len; + const TestRecvFrame *frames[10]; + void (*check) (NMLldpListener *listener); +} TestRecvData; +#define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ + static const TestRecvData name = { \ + .expected_num_called = _expected_num_called, \ + .check = _check, \ + .frames_len = NM_NARG (__VA_ARGS__), \ + .frames = { __VA_ARGS__ }, \ + } + #define TEST_IFNAME "nm-tap-test0" +TEST_RECV_FRAME_DEFINE (_test_recv_data0_frame0, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data0_check (NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + /* Check port description */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_PORT_DESCRIPTION); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); + nm_clear_g_variant (&attr); + + /* Check system name */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_SYSTEM_NAME); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); + nm_clear_g_variant (&attr); + + /* Check destination */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_DESTINATION); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, + NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + nm_clear_g_variant (&attr); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data0, 1, _test_recv_data0_check, &_test_recv_data0_frame0); +TEST_RECV_DATA_DEFINE (_test_recv_data0_twice, 1, _test_recv_data0_check, &_test_recv_data0_frame0, &_test_recv_data0_frame0); + static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { @@ -112,9 +192,7 @@ _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); close (s); - nm_platform_process_events (NM_PLATFORM_GET); - link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); - g_assert (link); + link = nmtstp_assert_wait_for_link (TEST_IFNAME, NM_LINK_TYPE_TAP, 100); fixture->ifindex = link->ifindex; fixture->fd = fd; memcpy (fixture->mac, link->addr.data, ETH_ALEN); @@ -143,26 +221,11 @@ lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, static void test_recv (TestRecvFixture *fixture, gconstpointer user_data) { + const TestRecvData *data = user_data; gs_unref_object NMLldpListener *listener = NULL; GMainLoop *loop; TestRecvCallbackInfo info = { }; - GVariant *neighbors, *attr; - uint8_t frame[] = { - /* Ethernet header */ - 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ - 0x88, 0xcc, /* Ethertype */ - /* LLDP mandatory TLVs */ - 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ - 0x03, 0x04, 0x05, - 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ - 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ - /* LLDP optional TLVs */ - 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ - 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ - 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ - 0x00, 0x00 /* End Of LLDPDU */ - }; + gsize i_frames; listener = nm_lldp_listener_new (); g_assert (listener != NULL); @@ -171,41 +234,19 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, (GCallback) lldp_neighbors_changed, &info); loop = g_main_loop_new (NULL, FALSE); - g_timeout_add_seconds (1, loop_quit, loop); + g_timeout_add (500, loop_quit, loop); - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); - g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); + for (i_frames = 0; i_frames < data->frames_len; i_frames++) { + const TestRecvFrame *f = data->frames[i_frames]; + + g_assert (write (fixture->fd, f->frame, f->frame_len) == f->frame_len); + } g_main_loop_run (loop); - g_assert_cmpint (info.num_called, ==, 1); - neighbors = nm_lldp_listener_get_neighbors (listener); - g_assert (neighbors != NULL); + g_assert_cmpint (info.num_called, ==, data->expected_num_called); - /* Check port description */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_PORT_DESCRIPTION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); - nm_clear_g_variant (&attr); - - /* Check system name */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_SYSTEM_NAME); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); - nm_clear_g_variant (&attr); - - /* Check destination */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_DESTINATION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, - NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); - nm_clear_g_variant (&attr); + data->check (listener); g_clear_pointer (&loop, g_main_loop_unref); } @@ -227,5 +268,8 @@ init_tests (int *argc, char ***argv) void setup_tests (void) { - g_test_add ("/lldp/recv", TestRecvFixture, NULL, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown); +#define _TEST_ADD_RECV(testpath, testdata) \ + g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown) + _TEST_ADD_RECV ("/lldp/recv/0", &_test_recv_data0); + _TEST_ADD_RECV ("/lldp/recv/0_twice", &_test_recv_data0_twice); } From 8cafd4d39d3df0c580e02449b9be03a1aff5260e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 14:31:04 +0100 Subject: [PATCH 6/9] lldp/tests: refactor checking for lldp neighbors Also assert against the number of properties in the attributes and explicitly assert against the values of chassis-id-type, port-id-type, and system-description. --- src/devices/tests/test-lldp.c | 111 +++++++++++++++++----------------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 7f4fd1176d..6c51f3a912 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -28,6 +28,8 @@ #include "nm-lldp-listener.h" +#include "lldp.h" + #include "test-common.h" #include "nm-test-utils.h" @@ -35,52 +37,51 @@ /*****************************************************************************/ static GVariant * -get_lldp_neighbor_attribute (GVariant *neighbors, - const char *chassis, const char *port, - const char *name) +get_lldp_neighbor (GVariant *neighbors, + int chassis_id_type, + const char *chassis_id, + int port_id_type, + const char *port_id) { - GVariantIter iter, attrs_iter; - GVariant *variant, *attr_variant; - const char *attr_name; + GVariantIter iter; + GVariant *variant; + GVariant *result = NULL; + + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + + g_assert (chassis_id_type >= -1 && chassis_id_type <= G_MAXUINT8); + g_assert (port_id_type >= -1 && port_id_type <= G_MAXUINT8); - g_return_val_if_fail (g_variant_is_of_type (neighbors, - G_VARIANT_TYPE ("aa{sv}")), - NULL); g_variant_iter_init (&iter, neighbors); - while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { - gs_unref_variant GVariant *chassis_v = NULL; - gs_unref_variant GVariant *port_v = NULL; - gs_unref_variant GVariant *attr_v = NULL; + gs_unref_variant GVariant *v_chassis_id_type = NULL; + gs_unref_variant GVariant *v_chassis_id = NULL; + gs_unref_variant GVariant *v_port_id_type = NULL; + gs_unref_variant GVariant *v_port_id = NULL; - g_variant_iter_init (&attrs_iter, variant); - while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) { - if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) { - g_assert (!chassis_v); - chassis_v = attr_variant; - } else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) { - g_assert (!port_v); - port_v = attr_variant; - } else if (!g_strcmp0 (attr_name, name)) { - g_assert (!attr_v); - attr_v = attr_variant; - } else - g_variant_unref (attr_variant); - } + v_chassis_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_chassis_id_type); - g_variant_unref (variant); + v_chassis_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID, G_VARIANT_TYPE_STRING); + g_assert (v_chassis_id); - if ( chassis_v - && port_v - && g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) - && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING) - && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL)) - && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) - return g_variant_ref (attr_v); + v_port_id_type = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID_TYPE, G_VARIANT_TYPE_UINT32); + g_assert (v_port_id_type); + + v_port_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_PORT_ID, G_VARIANT_TYPE_STRING); + g_assert (v_port_id); + + if ( nm_streq (g_variant_get_string (v_chassis_id, NULL), chassis_id) + && nm_streq (g_variant_get_string (v_port_id, NULL), port_id) + && NM_IN_SET (chassis_id_type, -1, g_variant_get_uint32 (v_chassis_id_type)) + && NM_IN_SET (port_id_type, -1, g_variant_get_uint32 (v_port_id_type))) { + g_assert (!result); + result = variant; + } else + g_variant_unref (variant); } - /* neighbor not found */ - return NULL; + return result; } typedef struct { @@ -137,34 +138,32 @@ static void _test_recv_data0_check (NMLldpListener *listener) { GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; neighbors = nm_lldp_listener_get_neighbors (listener); nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); - /* Check port description */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_PORT_DESCRIPTION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:02:03:04:05", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/3"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 4); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Port"); nm_clear_g_variant (&attr); - /* Check system name */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_SYSTEM_NAME); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "SYS"); nm_clear_g_variant (&attr); - /* Check destination */ - attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", - NM_LLDP_ATTR_DESTINATION); - g_assert (attr != NULL); - g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); - g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, - NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + nm_clear_g_variant (&attr); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "foo"); nm_clear_g_variant (&attr); } From 0b122099512185abb901999a21e6ef4f23975a39 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 15:18:44 +0100 Subject: [PATCH 7/9] lldp/tests: add a test with another lldp frame --- src/devices/tests/test-lldp.c | 136 ++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 6c51f3a912..8d44fd9a80 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -170,6 +170,141 @@ _test_recv_data0_check (NMLldpListener *listener) TEST_RECV_DATA_DEFINE (_test_recv_data0, 1, _test_recv_data0_check, &_test_recv_data0_frame0); TEST_RECV_DATA_DEFINE (_test_recv_data0_twice, 1, _test_recv_data0_check, &_test_recv_data0_frame0, &_test_recv_data0_frame0); + +TEST_RECV_FRAME_DEFINE (_test_recv_data1_frame0, + /* lldp.detailed.pcap from + * https://wiki.wireshark.org/SampleCaptures#Link_Layer_Discovery_Protocol_.28LLDP.29 */ + + /* ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, /* destination mac */ + 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0, /* source mac */ + 0x88, 0xcc, /* ethernet type */ + + 0x02, 0x07, 0x04, 0x00, 0x01, 0x30, /* Chassis Subtype */ + 0xf9, 0xad, 0xa0, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x31, /* Port Subtype */ + 0x06, 0x02, 0x00, 0x78, /* Time To Live */ + 0x08, 0x17, 0x53, 0x75, 0x6d, 0x6d, /* Port Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x2d, 0x50, 0x6f, 0x72, + 0x74, 0x20, 0x31, 0x30, 0x30, 0x31, + 0x00, + 0x0a, 0x0d, 0x53, 0x75, 0x6d, 0x6d, /* System Name */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x00, + 0x0c, 0x4c, 0x53, 0x75, 0x6d, 0x6d, /* System Description */ + 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, + 0x34, 0x38, 0x20, 0x2d, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x37, 0x2e, 0x34, 0x65, 0x2e, + 0x31, 0x20, 0x28, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x20, 0x35, 0x29, 0x20, + 0x62, 0x79, 0x20, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, + 0x30, 0x35, 0x2f, 0x32, 0x37, 0x2f, + 0x30, 0x35, 0x20, 0x30, 0x34, 0x3a, + 0x35, 0x33, 0x3a, 0x31, 0x31, 0x00, + 0x0e, 0x04, 0x00, 0x14, 0x00, 0x14, /* Capabilities */ + 0x10, 0x0e, 0x07, 0x06, 0x00, 0x01, /* Management Address */ + 0x30, 0xf9, 0xad, 0xa0, 0x02, 0x00, + 0x00, 0x03, 0xe9, 0x00, + 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, /* IEEE 802.3 - Power Via MDI */ + 0x07, 0x01, 0x00, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x01, /* IEEE 802.3 - MAC/PHY Configuration/Status */ + 0x03, 0x6c, 0x00, 0x00, 0x10, + 0xfe, 0x09, 0x00, 0x12, 0x0f, 0x03, /* IEEE 802.3 - Link Aggregation */ + 0x01, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x06, 0x00, 0x12, 0x0f, 0x04, /* IEEE 802.3 - Maximum Frame Size */ + 0x05, 0xf2, + 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* IEEE 802.1 - Port VLAN ID */ + 0x01, 0xe8, + 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* IEEE 802.1 - Port and Protocol VLAN ID */ + 0x01, 0x00, 0x00, + 0xfe, 0x17, 0x00, 0x80, 0xc2, 0x03, /* IEEE 802.1 - VLAN Name */ + 0x01, 0xe8, 0x10, 0x76, 0x32, 0x2d, + 0x30, 0x34, 0x38, 0x38, 0x2d, 0x30, + 0x33, 0x2d, 0x30, 0x35, 0x30, 0x35, + 0x00, + 0xfe, 0x05, 0x00, 0x80, 0xc2, 0x04, /* IEEE 802.1 - Protocol Identity */ + 0x00, + 0x00, 0x00 /* End of LLDPDU */ +); + +static void +_test_recv_data1_check (NMLldpListener *listener) +{ + GVariant *neighbors, *attr; + gs_unref_variant GVariant *neighbor = NULL; + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 1); + + neighbor = get_lldp_neighbor (neighbors, + LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:30:F9:AD:A0", + LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/1"); + g_assert (neighbor); + g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 10); + + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_BRIDGE); + nm_clear_g_variant (&attr); + + /* unsupported: Time To Live */ + + /* Port Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_PORT_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48-Port 1001"); + nm_clear_g_variant (&attr); + + /* System Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48"); + nm_clear_g_variant (&attr); + + /* System Description */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "Summit300-48 - Version 7.4e.1 (Build 5) by Release_Master 05/27/05 04:53:11"); + nm_clear_g_variant (&attr); + + /* Capabilities */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 20); + nm_clear_g_variant (&attr); + + /* unsupported: Management Address */ + /* unsupported: IEEE 802.3 - Power Via MDI */ + /* unsupported: IEEE 802.3 - MAC/PHY Configuration/Status */ + /* unsupported: IEEE 802.3 - Link Aggregation */ + /* unsupported: IEEE 802.3 - Maximum Frame Size*/ + + /* IEEE 802.1 - Port VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - Port and Protocol VLAN ID */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 0); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 1); + nm_clear_g_variant (&attr); + + /* IEEE 802.1 - VLAN Name */ + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, G_VARIANT_TYPE_STRING); + nmtst_assert_variant_string (attr, "v2-0488-03-0505"); + nm_clear_g_variant (&attr); + attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VID, G_VARIANT_TYPE_UINT32); + nmtst_assert_variant_uint32 (attr, 488); + nm_clear_g_variant (&attr); + + /* unsupported: IEEE 802.1 - Protocol Identity */ +} + +TEST_RECV_DATA_DEFINE (_test_recv_data1, 1, _test_recv_data1_check, &_test_recv_data1_frame0); + static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { @@ -271,4 +406,5 @@ setup_tests (void) g_test_add (testpath, TestRecvFixture, testdata, _test_recv_fixture_setup, test_recv, _test_recv_fixture_teardown) _TEST_ADD_RECV ("/lldp/recv/0", &_test_recv_data0); _TEST_ADD_RECV ("/lldp/recv/0_twice", &_test_recv_data0_twice); + _TEST_ADD_RECV ("/lldp/recv/1", &_test_recv_data1); } From cba9dc9d03b9688d29552df3a5ac6bf7fa598a13 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 16:38:07 +0100 Subject: [PATCH 8/9] lldp/tests: use nmtst_main_loop_run() --- src/devices/tests/test-lldp.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 8d44fd9a80..54250a4c05 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -336,13 +336,6 @@ typedef struct { int num_called; } TestRecvCallbackInfo; -static gboolean -loop_quit (gpointer user_data) -{ - g_main_loop_quit ((GMainLoop *) user_data); - return G_SOURCE_REMOVE; -} - static void lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) @@ -368,7 +361,6 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, (GCallback) lldp_neighbors_changed, &info); loop = g_main_loop_new (NULL, FALSE); - g_timeout_add (500, loop_quit, loop); for (i_frames = 0; i_frames < data->frames_len; i_frames++) { const TestRecvFrame *f = data->frames[i_frames]; @@ -376,7 +368,8 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) g_assert (write (fixture->fd, f->frame, f->frame_len) == f->frame_len); } - g_main_loop_run (loop); + if (nmtst_main_loop_run (loop, 500)) + g_assert_not_reached (); g_assert_cmpint (info.num_called, ==, data->expected_num_called); From 4f8522423a8bfd64f70a220ee6f38c68d0754bd8 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 10 Mar 2016 16:32:34 +0100 Subject: [PATCH 9/9] lldp/tests: add test for ttl --- src/devices/tests/test-lldp.c | 58 +++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index 54250a4c05..8be52fe76e 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -105,7 +105,7 @@ typedef struct { guint expected_num_called; gsize frames_len; const TestRecvFrame *frames[10]; - void (*check) (NMLldpListener *listener); + void (*check) (GMainLoop *loop, NMLldpListener *listener); } TestRecvData; #define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ static const TestRecvData name = { \ @@ -135,7 +135,7 @@ TEST_RECV_FRAME_DEFINE (_test_recv_data0_frame0, ); static void -_test_recv_data0_check (NMLldpListener *listener) +_test_recv_data0_check (GMainLoop *loop, NMLldpListener *listener) { GVariant *neighbors, *attr; gs_unref_variant GVariant *neighbor = NULL; @@ -232,7 +232,7 @@ TEST_RECV_FRAME_DEFINE (_test_recv_data1_frame0, ); static void -_test_recv_data1_check (NMLldpListener *listener) +_test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener) { GVariant *neighbors, *attr; gs_unref_variant GVariant *neighbor = NULL; @@ -305,6 +305,48 @@ _test_recv_data1_check (NMLldpListener *listener) TEST_RECV_DATA_DEFINE (_test_recv_data1, 1, _test_recv_data1_check, &_test_recv_data1_frame0); +TEST_RECV_FRAME_DEFINE (_test_recv_data2_frame0_ttl1, + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x01, /* TTL: 1 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ +); + +static void +_test_recv_data2_ttl1_check (GMainLoop *loop, NMLldpListener *listener) +{ + gulong notify_id; + GVariant *neighbors; + + _test_recv_data0_check (loop, listener); + + g_test_skip ("the test is known to fail"); + return; + + /* wait for signal. */ + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + nmtst_main_loop_quit_on_notify, loop); + if (!nmtst_main_loop_run (loop, 20000)) + g_assert_not_reached (); + nm_clear_g_signal_handler (listener, ¬ify_id); + + neighbors = nm_lldp_listener_get_neighbors (listener); + nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}")); + g_assert_cmpint (g_variant_n_children (neighbors), ==, 0); +} + +TEST_RECV_DATA_DEFINE (_test_recv_data2_ttl1, 1, _test_recv_data2_ttl1_check, &_test_recv_data2_frame0_ttl1); + static void _test_recv_fixture_setup (TestRecvFixture *fixture, gconstpointer user_data) { @@ -353,13 +395,14 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) GMainLoop *loop; TestRecvCallbackInfo info = { }; gsize i_frames; + gulong notify_id; listener = nm_lldp_listener_new (); g_assert (listener != NULL); g_assert (nm_lldp_listener_start (listener, fixture->ifindex, TEST_IFNAME, fixture->mac, ETH_ALEN, NULL)); - g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, - (GCallback) lldp_neighbors_changed, &info); + notify_id = g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + (GCallback) lldp_neighbors_changed, &info); loop = g_main_loop_new (NULL, FALSE); for (i_frames = 0; i_frames < data->frames_len; i_frames++) { @@ -373,7 +416,9 @@ test_recv (TestRecvFixture *fixture, gconstpointer user_data) g_assert_cmpint (info.num_called, ==, data->expected_num_called); - data->check (listener); + nm_clear_g_signal_handler (listener, ¬ify_id); + + data->check (loop, listener); g_clear_pointer (&loop, g_main_loop_unref); } @@ -400,4 +445,5 @@ setup_tests (void) _TEST_ADD_RECV ("/lldp/recv/0", &_test_recv_data0); _TEST_ADD_RECV ("/lldp/recv/0_twice", &_test_recv_data0_twice); _TEST_ADD_RECV ("/lldp/recv/1", &_test_recv_data1); + _TEST_ADD_RECV ("/lldp/recv/2_ttl1", &_test_recv_data2_ttl1); }