git: 053937ce6e1a - stable/13 - tests/netgraph: Tests for ng_vlan_rotate

Lutz Donnerhacke donner at FreeBSD.org
Wed Jun 16 11:26:19 UTC 2021


The branch stable/13 has been updated by donner:

URL: https://cgit.FreeBSD.org/src/commit/?id=053937ce6e1a72a72f8845c0dc8a10be71fea336

commit 053937ce6e1a72a72f8845c0dc8a10be71fea336
Author:     Lutz Donnerhacke <donner at FreeBSD.org>
AuthorDate: 2021-06-06 23:56:12 +0000
Commit:     Lutz Donnerhacke <donner at FreeBSD.org>
CommitDate: 2021-06-16 11:25:04 +0000

    tests/netgraph: Tests for ng_vlan_rotate
    
    Test functionality of ng_vlan_rotate(4):
     - Rotate 1 to 9 stagged vlans in any possible direction and length
     - Rotate random combinations of ethertypes (8100, 88a8, 9100)
     - Automatic reverse rotating for backward data flow
     - Test too many and too few vlans
    
    Reviewed by:    kp (earlier version)
    Differential Revision: https://reviews.freebsd.org/D30670
    
    (cherry picked from commit 6b08e68be111d50931b0d30145f8b7e3402decaf)
---
 tests/sys/netgraph/Makefile      |   8 +-
 tests/sys/netgraph/vlan_rotate.c | 335 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 340 insertions(+), 3 deletions(-)

diff --git a/tests/sys/netgraph/Makefile b/tests/sys/netgraph/Makefile
index 2ae9882b2bc3..f397e66a22bc 100644
--- a/tests/sys/netgraph/Makefile
+++ b/tests/sys/netgraph/Makefile
@@ -10,13 +10,15 @@ TAP_TESTS_SH+=	ng_macfilter_test
 TEST_METADATA.ng_macfilter_test+=	required_user="root"
 TEST_METADATA.ng_macfilter_test+=	required_programs="perl"
 
-ATF_TESTS_C+=	basic	\
-		bridge	\
-		hub	\
+ATF_TESTS_C+=	basic		\
+		bridge		\
+		hub		\
+		vlan_rotate	\
 
 SRCS.basic=	basic.c util.c
 SRCS.bridge=	bridge.c util.c
 SRCS.hub=	hub.c util.c
+SRCS.vlan_rotate=vlan_rotate.c util.c
 
 LIBADD+=	netgraph
 
diff --git a/tests/sys/netgraph/vlan_rotate.c b/tests/sys/netgraph/vlan_rotate.c
new file mode 100644
index 000000000000..8df3ab981a7c
--- /dev/null
+++ b/tests/sys/netgraph/vlan_rotate.c
@@ -0,0 +1,335 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright 2021 Lutz Donnerhacke
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <atf-c.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <net/ethernet.h>
+#include <netinet/in.h>
+
+#include "util.h"
+#include <netgraph/ng_bridge.h>
+
+struct vlan
+{
+	uint16_t	proto;
+	uint16_t	tag;
+}		__packed;
+
+struct frame
+{
+	u_char		dst[ETHER_ADDR_LEN];
+	u_char		src[ETHER_ADDR_LEN];
+	struct vlan	vlan[10];
+}		__packed;
+
+static struct frame msg = {
+	.src = {2, 4, 6, 1, 3, 5},
+	.dst = {2, 4, 6, 1, 3, 7},
+	.vlan[0] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(1, 0, 0))},
+	.vlan[1] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(2, 0, 0))},
+	.vlan[2] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(3, 0, 0))},
+	.vlan[3] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(4, 0, 0))},
+	.vlan[4] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(5, 0, 0))},
+	.vlan[5] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(6, 0, 0))},
+	.vlan[6] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(7, 0, 0))},
+	.vlan[7] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(8, 0, 0))},
+	.vlan[8] = {htons(ETHERTYPE_VLAN), htons(EVL_MAKETAG(9, 0, 0))},
+	.vlan[9] = {0}
+};
+
+static void	_basic(int);
+static void	get_vlan(void *data, size_t len, void *ctx);
+
+static void
+get_vlan(void *data, size_t len, void *ctx)
+{
+	int	       *v = ctx, i;
+	struct frame   *f = data;
+
+	(void)len;
+	for (i = 0; i < 10; i++)
+		v[i] = EVL_VLANOFTAG(ntohs(f->vlan[i].tag));
+}
+
+static void
+_basic(int direction)
+{
+	int		r[10];
+	int		i, rot, len;
+
+	ng_init();
+	ng_errors(PASS);
+	ng_shutdown("vr:");
+	ng_errors(FAIL);
+
+	ng_mkpeer(".", "a", "vlan_rotate", direction > 0 ? "original" : "ordered");
+	ng_name("a", "vr");
+	ng_connect(".", "b", "vr:", direction > 0 ? "ordered" : "original");
+	ng_register_data("b", get_vlan);
+
+	for (len = 9; len > 0; len--)
+	{
+		/* reduce the number of vlans */
+		msg.vlan[len].proto = htons(ETHERTYPE_IP);
+
+		for (rot = -len + 1; rot < len; rot++)
+		{
+			char		cmd[40];
+
+			/* set rotation offset */
+			snprintf(cmd, sizeof(cmd), "setconf { min=0 max=9 rot=%d }", rot);
+			ng_send_msg("vr:", cmd);
+
+			ng_send_data("a", &msg, sizeof(msg));
+			ng_handle_events(50, &r);
+
+			/* check rotation */
+			for (i = 0; i < len; i++)
+			{
+				int		expect = (2 * len + i - direction * rot) % len + 1;
+				int		vlan = r[i];
+
+				ATF_CHECK_MSG(vlan == expect,
+				 "len=%d rot=%d i=%d -> vlan=%d, expect=%d",
+					      len, rot, i, r[i], expect);
+			}
+		}
+	}
+
+	ng_shutdown("vr:");
+}
+
+ATF_TC(basic);
+ATF_TC_HEAD(basic, conf)
+{
+	atf_tc_set_md_var(conf, "require.user", "root");
+}
+
+ATF_TC_BODY(basic, dummy)
+{
+	_basic(1);
+}
+
+ATF_TC(reverse);
+ATF_TC_HEAD(reverse, conf)
+{
+	atf_tc_set_md_var(conf, "require.user", "root");
+}
+
+ATF_TC_BODY(reverse, dummy)
+{
+	_basic(-1);
+}
+
+static void	_ethertype(int);
+static void	get_ethertype(void *data, size_t len, void *ctx);
+
+static void
+get_ethertype(void *data, size_t len, void *ctx)
+{
+	int	       *v = ctx, i;
+	struct frame   *f = data;
+
+	(void)len;
+	for (i = 0; i < 10; i++)
+		v[i] = ntohs(f->vlan[i].proto);
+}
+
+static void
+_ethertype(int direction)
+{
+	int		r[10];
+	int		i, rounds = 20;
+
+	ng_init();
+	ng_errors(PASS);
+	ng_shutdown("vr:");
+	ng_errors(FAIL);
+
+	ng_mkpeer(".", "a", "vlan_rotate", direction > 0 ? "original" : "ordered");
+	ng_name("a", "vr");
+	ng_connect(".", "b", "vr:", direction > 0 ? "ordered" : "original");
+	ng_register_data("b", get_ethertype);
+
+	while (rounds-- > 0)
+	{
+		char		cmd[40];
+		int		len = 9;
+		int		rot = rand() % (2 * len - 1) - len + 1;
+		int		vlan[10];
+
+		for (i = 0; i < len; i++)
+		{
+			switch (rand() % 3)
+			{
+			default:
+				msg.vlan[i].proto = htons(ETHERTYPE_VLAN);
+				break;
+			case 1:
+				msg.vlan[i].proto = htons(ETHERTYPE_QINQ);
+				break;
+			case 2:
+				msg.vlan[i].proto = htons(ETHERTYPE_8021Q9100);
+				break;
+			}
+		}
+		msg.vlan[i].proto = htons(ETHERTYPE_IP);
+
+		for (i = 0; i < len; i++)
+			vlan[i] = msg.vlan[i].proto;
+
+		snprintf(cmd, sizeof(cmd), "setconf { min=0 max=9 rot=%d }", rot);
+		ng_send_msg("vr:", cmd);
+
+		bzero(r, sizeof(r));
+		ng_send_data("a", &msg, sizeof(msg));
+		ng_handle_events(50, &r);
+
+		/* check rotation */
+		for (i = 0; i < len; i++)
+		{
+			int		expect = (2 * len + i - direction * rot) % len;
+
+			ATF_CHECK_MSG(r[i] == ntohs(vlan[expect]),
+			 "len=%d rot=%d i=%d -> vlan=%04x, expect(%d)=%04x",
+			    len, rot, i, ntohs(r[i]), expect, vlan[expect]);
+		}
+	}
+
+	ng_shutdown("vr:");
+}
+
+ATF_TC(ethertype);
+ATF_TC_HEAD(ethertype, conf)
+{
+	atf_tc_set_md_var(conf, "require.user", "root");
+}
+
+ATF_TC_BODY(ethertype, dummy)
+{
+	_ethertype(1);
+}
+
+ATF_TC(typeether);
+ATF_TC_HEAD(typeether, conf)
+{
+	atf_tc_set_md_var(conf, "require.user", "root");
+}
+
+ATF_TC_BODY(typeether, dummy)
+{
+	_ethertype(-1);
+}
+
+ATF_TC(minmax);
+ATF_TC_HEAD(minmax, conf)
+{
+	atf_tc_set_md_var(conf, "require.user", "root");
+}
+
+ATF_TC_BODY(minmax, dummy)
+{
+	ng_counter_t	r;
+	int		len;
+
+	ng_init();
+	ng_errors(PASS);
+	ng_shutdown("vr:");
+	ng_errors(FAIL);
+
+	ng_mkpeer(".", "a", "vlan_rotate", "original");
+	ng_name("a", "vr");
+	ng_connect(".", "b", "vr:", "ordered");
+	ng_connect(".", "c", "vr:", "excessive");
+	ng_connect(".", "d", "vr:", "incomplete");
+	ng_register_data("a", get_data0);
+	ng_register_data("b", get_data1);
+	ng_register_data("c", get_data2);
+	ng_register_data("d", get_data3);
+
+	ng_send_msg("vr:", "setconf { min=3 max=7 rot=0 }");
+	for (len = 9; len > 0; len--)
+	{
+		/* reduce the number of vlans */
+		msg.vlan[len].proto = htons(ETHERTYPE_IP);
+
+		ng_counter_clear(r);
+		ng_send_data("a", &msg, sizeof(msg));
+		ng_handle_events(50, &r);
+		if (len < 3)
+			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 0 && r[3] == 1);
+		else if (len > 7)
+			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
+		else
+			ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 0 && r[3] == 0);
+
+		ng_counter_clear(r);
+		ng_send_data("b", &msg, sizeof(msg));
+		ng_handle_events(50, &r);
+		if (len < 3)
+			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 0 && r[3] == 1);
+		else if (len > 7)
+			ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
+		else
+			ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
+
+		ng_counter_clear(r);
+		ng_send_data("c", &msg, sizeof(msg));
+		ng_handle_events(50, &r);
+		ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
+
+		ng_counter_clear(r);
+		ng_send_data("d", &msg, sizeof(msg));
+		ng_handle_events(50, &r);
+		ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
+	}
+
+	ng_shutdown("vr:");
+}
+
+ATF_TP_ADD_TCS(vlan_rotate)
+{
+	/* Use "dd if=/dev/random bs=2 count=1 | od -x" to reproduce */
+	srand(0xb93b);
+
+	ATF_TP_ADD_TC(vlan_rotate, basic);
+	ATF_TP_ADD_TC(vlan_rotate, ethertype);
+	ATF_TP_ADD_TC(vlan_rotate, reverse);
+	ATF_TP_ADD_TC(vlan_rotate, typeether);
+	ATF_TP_ADD_TC(vlan_rotate, minmax);
+
+	return atf_no_error();
+}


More information about the dev-commits-src-all mailing list