From owner-dev-commits-src-main@freebsd.org Wed Jun 9 11:46:48 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 2EF1E64C726; Wed, 9 Jun 2021 11:46:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4G0QLc0s9dz3wJF; Wed, 9 Jun 2021 11:46:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 01C5D1BA19; Wed, 9 Jun 2021 11:46:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 159Bkldd087259; Wed, 9 Jun 2021 11:46:47 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 159BklZV087258; Wed, 9 Jun 2021 11:46:47 GMT (envelope-from git) Date: Wed, 9 Jun 2021 11:46:47 GMT Message-Id: <202106091146.159BklZV087258@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Lutz Donnerhacke Subject: git: 6b08e68be111 - main - tests/netgraph: Tests for ng_vlan_rotate MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: donner X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 6b08e68be111d50931b0d30145f8b7e3402decaf Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Jun 2021 11:46:48 -0000 The branch main has been updated by donner: URL: https://cgit.FreeBSD.org/src/commit/?id=6b08e68be111d50931b0d30145f8b7e3402decaf commit 6b08e68be111d50931b0d30145f8b7e3402decaf Author: Lutz Donnerhacke AuthorDate: 2021-06-06 23:56:12 +0000 Commit: Lutz Donnerhacke CommitDate: 2021-06-09 11:45:37 +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 to few vlans Reviewed by: kp (earlier version) MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D30670 --- 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 +#include +#include +#include + +#include +#include + +#include "util.h" +#include + +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(); +}