summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-03-10 17:25:11 +0100
committerThomas Haller <thaller@redhat.com>2016-03-10 17:25:11 +0100
commitd432edba558e0eacee9f64b6038ef11cb88b77a4 (patch)
tree44a8f7a2e3791df3fe21906d427c8e103cf5007c
parentfd8c56425e9e94aff52b1e7f00ed17066390e425 (diff)
parent4f8522423a8bfd64f70a220ee6f38c68d0754bd8 (diff)
downloadNetworkManager-d432edba558e0eacee9f64b6038ef11cb88b77a4.tar.gz
lldp: merge branch 'th/lldp-tests'
-rw-r--r--libnm-core/nm-dbus-interface.h2
-rw-r--r--shared/nm-test-utils.h40
-rw-r--r--src/devices/nm-lldp-listener.c2
-rw-r--r--src/devices/tests/test-lldp.c455
4 files changed, 381 insertions, 118 deletions
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"
diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h
index 694e84ccd0..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 *
@@ -1774,6 +1786,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,
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 978821a686..8be52fe76e 100644
--- a/src/devices/tests/test-lldp.c
+++ b/src/devices/tests/test-lldp.c
@@ -28,20 +28,327 @@
#include "nm-lldp-listener.h"
+#include "lldp.h"
+
#include "test-common.h"
#include "nm-test-utils.h"
+/*****************************************************************************/
+
+static GVariant *
+get_lldp_neighbor (GVariant *neighbors,
+ int chassis_id_type,
+ const char *chassis_id,
+ int port_id_type,
+ const char *port_id)
+{
+ 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_variant_iter_init (&iter, neighbors);
+ while (g_variant_iter_next (&iter, "@a{sv}", &variant)) {
+ 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;
+
+ 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);
+
+ v_chassis_id = g_variant_lookup_value (variant, NM_LLDP_ATTR_CHASSIS_ID, G_VARIANT_TYPE_STRING);
+ g_assert (v_chassis_id);
+
+ 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);
+ }
+
+ return result;
+}
+
typedef struct {
int ifindex;
int fd;
guint8 mac[ETH_ALEN];
-} test_fixture;
+} 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) (GMainLoop *loop, 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 (GMainLoop *loop, 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: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);
+
+ 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);
+
+ 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);
+}
+
+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 (GMainLoop *loop, 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);
+
+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
-fixture_setup (test_fixture *fixture, gconstpointer user_data)
+_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, &notify_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)
{
const NMPlatformLink *link;
struct ifreq ifr = { };
@@ -61,9 +368,7 @@ fixture_setup (test_fixture *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);
@@ -71,149 +376,61 @@ fixture_setup (test_fixture *fixture, gconstpointer user_data)
typedef struct {
int num_called;
-} TestInfo;
-
-static gboolean
-loop_quit (gpointer user_data)
-{
- g_main_loop_quit ((GMainLoop *) user_data);
- return G_SOURCE_REMOVE;
-}
+} TestRecvCallbackInfo;
static void
lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec,
gpointer user_data)
{
- TestInfo *info = user_data;
+ TestRecvCallbackInfo *info = user_data;
info->num_called++;
}
-static GVariant *
-get_lldp_neighbor_attribute (GVariant *neighbors,
- const char *chassis, const char *port,
- const char *name)
-{
- GVariantIter iter, attrs_iter;
- GVariant *variant, *attr_variant;
- const char *attr_name;
-
- 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;
-
- 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);
- }
-
- g_variant_unref (variant);
-
- 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);
- }
-
- /* neighbor not found */
- return NULL;
-}
-
static void
-test_receive_frame (test_fixture *fixture, gconstpointer user_data)
+test_recv (TestRecvFixture *fixture, gconstpointer user_data)
{
+ const TestRecvData *data = user_data;
gs_unref_object NMLldpListener *listener = NULL;
GMainLoop *loop;
- TestInfo 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 */
- };
+ 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);
- g_timeout_add_seconds (1, 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);
+ if (nmtst_main_loop_run (loop, 500))
+ g_assert_not_reached ();
- g_assert_cmpint (info.num_called, ==, 1);
- neighbors = nm_lldp_listener_get_neighbors (listener);
- g_assert (neighbors != NULL);
-
- /* 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);
+ g_assert_cmpint (info.num_called, ==, data->expected_num_called);
- /* 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);
+ nm_clear_g_signal_handler (listener, &notify_id);
- /* 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 (loop, listener);
g_clear_pointer (&loop, g_main_loop_unref);
}
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 +440,10 @@ 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);
+#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);
+ _TEST_ADD_RECV ("/lldp/recv/1", &_test_recv_data1);
+ _TEST_ADD_RECV ("/lldp/recv/2_ttl1", &_test_recv_data2_ttl1);
}