mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-17 11:30:46 +02:00
lldp: add test case
Add a test for the LLDP listener to ensure that things don't accidentally break when we import new code from systemd upstream. https://bugzilla.gnome.org/show_bug.cgi?id=757005
This commit is contained in:
parent
6bfa0674c1
commit
ff31171a1c
5 changed files with 267 additions and 0 deletions
|
|
@ -1031,6 +1031,8 @@ src/platform/Makefile
|
|||
src/platform/tests/Makefile
|
||||
src/rdisc/Makefile
|
||||
src/rdisc/tests/Makefile
|
||||
src/devices/Makefile
|
||||
src/devices/tests/Makefile
|
||||
src/devices/adsl/Makefile
|
||||
src/devices/bluetooth/Makefile
|
||||
src/devices/team/Makefile
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ SUBDIRS += \
|
|||
dhcp-manager/tests \
|
||||
dnsmasq-manager/tests \
|
||||
platform \
|
||||
devices \
|
||||
rdisc \
|
||||
supplicant-manager/tests \
|
||||
tests
|
||||
|
|
|
|||
1
src/devices/Makefile.am
Normal file
1
src/devices/Makefile.am
Normal file
|
|
@ -0,0 +1 @@
|
|||
SUBDIRS = tests
|
||||
42
src/devices/tests/Makefile.am
Normal file
42
src/devices/tests/Makefile.am
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/libnm-core \
|
||||
-I$(top_builddir)/libnm-core \
|
||||
-I$(top_srcdir)/src/platform \
|
||||
-I$(top_srcdir)/src/devices \
|
||||
-I$(top_srcdir)/src/systemd/ \
|
||||
-I$(top_srcdir)/src/systemd/src/systemd/ \
|
||||
-I$(top_srcdir)/src/systemd/src/libsystemd-network/ \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_builddir)/src \
|
||||
-DG_LOG_DOMAIN=\""NetworkManager"\" \
|
||||
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
|
||||
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
|
||||
$(GLIB_CFLAGS)
|
||||
|
||||
AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
|
||||
AM_LDFLAGS = $(GLIB_LIBS) $(CODE_COVERAGE_LDFLAGS)
|
||||
DEVICES_LDADD = \
|
||||
$(top_builddir)/src/libNetworkManager.la
|
||||
|
||||
@GNOME_CODE_COVERAGE_RULES@
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
test-lldp
|
||||
|
||||
test_lldp_SOURCES = \
|
||||
test-lldp.c \
|
||||
../nm-lldp-listener.c \
|
||||
$(top_srcdir)/src/platform/tests/test-common.c
|
||||
|
||||
test_lldp_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-I$(top_srcdir)/src/platform/tests \
|
||||
-DSETUP=nm_linux_platform_setup
|
||||
|
||||
test_lldp_LDADD = $(DEVICES_LDADD)
|
||||
|
||||
@VALGRIND_RULES@
|
||||
TESTS = \
|
||||
test-lldp
|
||||
221
src/devices/tests/test-lldp.c
Normal file
221
src/devices/tests/test-lldp.c
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-platform.c - Handle runtime kernel networking configuration
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "nm-default.h"
|
||||
#include "nm-lldp-listener.h"
|
||||
#include "test-common.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;
|
||||
strncpy (ifr.ifr_name, TEST_IFNAME, IFNAMSIZ);
|
||||
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,
|
||||
const char *chassis, const char *port,
|
||||
const char *name)
|
||||
{
|
||||
GVariantIter iter, attrs_iter;
|
||||
GVariant *variant, *attr_variant;
|
||||
const char *attr_name;
|
||||
GVariant *chassis_v, *port_v, *attr_v;
|
||||
|
||||
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)) {
|
||||
g_variant_iter_init (&attrs_iter, variant);
|
||||
chassis_v = NULL;
|
||||
port_v = NULL;
|
||||
attr_v = NULL;
|
||||
|
||||
while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) {
|
||||
if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID))
|
||||
chassis_v = attr_variant;
|
||||
else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID))
|
||||
port_v = attr_variant;
|
||||
else if (!g_strcmp0 (attr_name, name))
|
||||
attr_v = attr_variant;
|
||||
}
|
||||
|
||||
if ( 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))) {
|
||||
|
||||
g_variant_ref (attr_v);
|
||||
g_variant_unref (variant);
|
||||
|
||||
return attr_v;
|
||||
}
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
/* neighbor not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_receive_frame (test_fixture *fixture, gconstpointer user_data)
|
||||
{
|
||||
NMLldpListener *listener;
|
||||
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 */
|
||||
};
|
||||
|
||||
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);
|
||||
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));
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
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");
|
||||
|
||||
/* 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");
|
||||
|
||||
/* 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);
|
||||
|
||||
g_clear_pointer (&loop, g_main_loop_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
fixture_teardown (test_fixture *fixture, gconstpointer user_data)
|
||||
{
|
||||
nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
g_test_add ("/lldp/receive_frame", test_fixture, NULL, fixture_setup,
|
||||
test_receive_frame, fixture_teardown);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue