From patchwork Fri Oct 9 15:29:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1379264 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=iu0aVFSH; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C7Bp06kRxz9sSn for ; Sat, 10 Oct 2020 02:29:44 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 3F8778715A; Fri, 9 Oct 2020 15:29:42 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7ri3don2o37y; Fri, 9 Oct 2020 15:29:39 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id A937487165; Fri, 9 Oct 2020 15:29:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 91202C07FF; Fri, 9 Oct 2020 15:29:39 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id C73F3C07FF for ; Fri, 9 Oct 2020 15:29:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id B6DDA87786 for ; Fri, 9 Oct 2020 15:29:38 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7ijuS8K3oFQX for ; Fri, 9 Oct 2020 15:29:36 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by hemlock.osuosl.org (Postfix) with ESMTPS id 501C387779 for ; Fri, 9 Oct 2020 15:29:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602257375; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=W8YxT/nnEI4dsjx4LgfG/hdTyrk6+mTn/YbXcmdwVo0=; b=iu0aVFSH1F1lhNatSQiAmyRRVOSTREmC9b6w3H+UnHfcql5sO4ZpGkHjGKDH94e5f9uciZ 6qb8yrMvhtfVwCCQ8r9z7KYcsFzqoVIscUodgRSifTXgATw1l40tSHeNhpspS9KNCEVutS twxnVhA/Sim6nVk7h3bLhwoMWg/VEe0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-64-MAj5jcCeNjiYM0I5nMiZtQ-1; Fri, 09 Oct 2020 11:29:33 -0400 X-MC-Unique: MAj5jcCeNjiYM0I5nMiZtQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4EFAE18A8255 for ; Fri, 9 Oct 2020 15:29:32 +0000 (UTC) Received: from monae.redhat.com (ovpn-115-79.rdu2.redhat.com [10.10.115.79]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1C357FB89 for ; Fri, 9 Oct 2020 15:29:31 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Fri, 9 Oct 2020 11:29:28 -0400 Message-Id: <20201009152928.1312612-4-mmichels@redhat.com> In-Reply-To: <20201009152928.1312612-1-mmichels@redhat.com> References: <20201009152928.1312612-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH ovn 3/3] northd: Add init_ipam unit tests. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This adds unit tests for IPAM IPv6 initialization, IPv4 initialization, and IPv4 address retrieval to ovn-northd. It also adds testsuite tests corresponding to these unit tests. Note that these unit tests are meant to serve as examples. They are not nearly as exhaustive as they should be in order to test their pertinent functions. Signed-off-by: Mark Michelson --- northd/ovn-northd.c | 176 ++++++++++++++++++++++++++++++++++++++++ tests/automake.mk | 3 +- tests/ovn-unit-tests.at | 26 ++++++ tests/testsuite.at | 1 + 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 tests/ovn-unit-tests.at diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index d989ddf53..10671edb7 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -35,6 +35,7 @@ #include "lib/ovn-nb-idl.h" #include "lib/ovn-sb-idl.h" #include "lib/ovn-util.h" +#include "lib/unit-test.h" #include "ovn/actions.h" #include "ovn/logical-fields.h" #include "packets.h" @@ -13050,6 +13051,8 @@ main(int argc, char *argv[]) cluster_state_reset_cmd, &reset_ovnnb_idl_min_index); + register_unixctl_unit_test(); + daemonize_complete(); /* We want to detect (almost) all changes to the ovn-nb db. */ @@ -13464,3 +13467,176 @@ cluster_state_reset_cmd(struct unixctl_conn *conn, int argc OVS_UNUSED, poll_immediate_wake(); unixctl_command_reply(conn, NULL); } + +#ifdef ENABLE_UNIT_TESTS + +static enum test_result +test_init_ipam_ipv6_prefix(void *ignore OVS_UNUSED) +{ + struct ipam_info ipam; + struct { + const char *prefix; + bool expected_ipv6_prefix_set; + struct in6_addr expected_ipv6_prefix; + } test_cases[] = { + /* No prefix */ + { NULL, false, in6addr_any }, + /* Bad prefix */ + { "aef02::", false, in6addr_any}, + /* Bad subnet size */ + { "aef0::/8", false, in6addr_any}, + /* Good prefix, no subnet size */ + { "aef0::", true, {{{0xae, 0xf0}}}}, + /* Good prefix, good subnet size */ + { "aef0::/64", true, {{{0xae, 0xf0}}}}, + }; + + enum test_result result = OVN_TEST_PASS; + + for (size_t i = 0; i < ARRAY_SIZE(test_cases); i++) { + memset(&ipam, 0, sizeof ipam); + init_ipam_ipv6_prefix(test_cases[i].prefix, &ipam); + if (ipam.ipv6_prefix_set != test_cases[i].expected_ipv6_prefix_set) { + VLOG_WARN("Expected ipv6_prefix_set to be %s but got %s", + test_cases[i].expected_ipv6_prefix_set ? "true" : "false", + ipam.ipv6_prefix_set ? "true" : "false"); + result = OVN_TEST_FAIL; + continue; + } + if (ipam.ipv6_prefix_set + && !IN6_ARE_ADDR_EQUAL(&ipam.ipv6_prefix, + &test_cases[i].expected_ipv6_prefix)) { + char expected[INET6_ADDRSTRLEN]; + char actual[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &ipam.ipv6_prefix, + actual, sizeof actual); + inet_ntop(AF_INET6, &test_cases[i].expected_ipv6_prefix, + expected, sizeof expected); + VLOG_WARN("Expected IPv6 prefix %s but got %s", + expected, actual); + result = OVN_TEST_FAIL; + continue; + } + } + + return result; +} + +UNIT_TEST_DEFINE(init_ipam_ipv6_prefix, test_init_ipam_ipv6_prefix, NULL); + +static enum test_result +test_init_ipam_ipv4(void *ignore OVS_UNUSED) +{ + struct { + const char *subnet; + const char *exclude; + struct ipam_info info; + uint32_t expected_start_ip; + size_t expected_total_ips; + unsigned long *expected_allocated_ips; + } test_cases[] = { + { "192.168.0.0/24", NULL, {0,}, 0xc0a80001, 255, + bitmap_set1(bitmap_allocate(255), 0) }, + { "192.168.0.0/24", "192.168.0.10", {0,}, 0xc0a80001, 255, + bitmap_set1(bitmap_set1(bitmap_allocate(255), 0), 9)}, + { "192.168.0.0/24", "192.168.0.10..192.168.0.19", {0, }, 0xc0a80001, 255, + bitmap_set_multiple(bitmap_set1(bitmap_allocate(255), 0), 9, 10, true)}, + }; + enum test_result result = OVN_TEST_PASS; + + for (size_t i = 0; i < ARRAY_SIZE(test_cases); i++) { + init_ipam_ipv4(test_cases[i].subnet, + test_cases[i].exclude, + &test_cases[i].info); + + if (test_cases[i].info.start_ipv4 != test_cases[i].expected_start_ip) { + VLOG_WARN("Mismatched starting IP. Expected %" PRIu32 + " but got %" PRIu32 "\n", + test_cases[i].expected_start_ip, + test_cases[i].info.start_ipv4); + result = OVN_TEST_FAIL; + continue; + } + if (test_cases[i].info.total_ipv4s != test_cases[i].expected_total_ips) { + VLOG_WARN("Mismatched total IPs. Expected %" PRIuSIZE + " but got %" PRIuSIZE "\n", + test_cases[i].expected_total_ips, + test_cases[i].info.total_ipv4s); + result = OVN_TEST_FAIL; + continue; + } + if (!bitmap_equal(test_cases[i].info.allocated_ipv4s, + test_cases[i].expected_allocated_ips, + test_cases[i].expected_total_ips)) { + VLOG_WARN("Mismatched allocated IPs\n"); + result = OVN_TEST_FAIL; + continue; + } + } + + for (size_t i = 0; i < ARRAY_SIZE(test_cases); i++) { + bitmap_free(test_cases[i].info.allocated_ipv4s); + bitmap_free(test_cases[i].expected_allocated_ips); + } + + return result; +} + +UNIT_TEST_DEFINE(init_ipam_ipv4, test_init_ipam_ipv4, NULL); + +static enum test_result +test_ipam_get_unused_ip(void *ignore OVS_UNUSED) +{ + enum test_result result = OVN_TEST_PASS; + struct ipam_info info; + + struct smap config = SMAP_INITIALIZER(&config); + smap_add(&config, "subnet", "192.168.0.0/29"); + smap_add(&config, "exclude_ips", "192.168.0.5"); + init_ipam_info(&info, &config); + + uint32_t expected_ip [] = { + /* First IP we retrieve will be 192.168.0.2 since + * 192.168.0.1 is reserved for the connected router + */ + 0xc0a80002, + 0xc0a80003, + 0xc0a80004, + /* We should skip 192.168.0.5 since it is excluded */ + 0xc0a80006, + /* After 192.168.0.6, we should be out of space for the + * subnet. + */ + 0, + /* Just to be safe, let's make sure we get the same result + * when we try again. + */ + 0, + }; + + for (size_t i = 0; i < ARRAY_SIZE(expected_ip); i++) { + uint32_t next_ip; + + next_ip = ipam_get_unused_ip(&info); + if (next_ip != expected_ip[i]) { + VLOG_WARN("Expected IP address "IP_FMT" but got "IP_FMT" instead", + IP_ARGS(htonl(expected_ip[i])), IP_ARGS(htonl(next_ip))); + result = OVN_TEST_FAIL; + break; + } + if (next_ip && !ipam_insert_ip(&info, next_ip)) { + VLOG_WARN("Unable to insert ip "IP_FMT" into IPAM", + IP_ARGS(htonl(next_ip))); + result = OVN_TEST_FAIL; + break; + } + } + + smap_destroy(&config); + bitmap_free(info.allocated_ipv4s); + return result; +} + +UNIT_TEST_DEFINE(ipam_get_unused_ip, test_ipam_get_unused_ip, NULL); + +#endif /* ENABLE_UNIT_TESTS */ diff --git a/tests/automake.mk b/tests/automake.mk index 26b6d11b4..9ad577576 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -30,7 +30,8 @@ TESTSUITE_AT = \ tests/ovn-controller-vtep.at \ tests/ovn-ic.at \ tests/ovn-macros.at \ - tests/ovn-performance.at + tests/ovn-performance.at \ + tests/ovn-unit-tests.at SYSTEM_KMOD_TESTSUITE_AT = \ tests/system-common-macros.at \ diff --git a/tests/ovn-unit-tests.at b/tests/ovn-unit-tests.at new file mode 100644 index 000000000..b7d16667c --- /dev/null +++ b/tests/ovn-unit-tests.at @@ -0,0 +1,26 @@ +AT_BANNER([OVN unit tests]) + +AT_SETUP([ovn -- unit test -- init_ipam_ipv4]) +AT_SKIP_IF([test "$ENABLE_UNIT_TESTS" = no]) +ovn_start +AT_CHECK([ovn-appctl -t northd/ovn-northd unit-test init_ipam_ipv4], [0], [dnl +Unit test init_ipam_ipv4 passed +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- init_ipam_ipv6_prefix]) +AT_SKIP_IF([test "$ENABLE_UNIT_TESTS" = no]) +ovn_start +AT_CHECK([ovn-appctl -t northd/ovn-northd unit-test init_ipam_ipv6_prefix], [0], [dnl +Unit test init_ipam_ipv6_prefix passed +]) +AT_CLEANUP + +AT_SETUP([ovn -- unit test -- ipam_get_unused_ip]) +AT_SKIP_IF([test "$ENABLE_UNIT_TESTS" = no]) +ovn_start +AT_CHECK([ovn-appctl -t northd/ovn-northd unit-test ipam_get_unused_ip], [0], [dnl +Unit test ipam_get_unused_ip passed +]) +AT_CLEANUP + diff --git a/tests/testsuite.at b/tests/testsuite.at index 1985923d5..5e60bad73 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -21,6 +21,7 @@ m4_include([tests/ovsdb-macros.at]) m4_include([tests/ofproto-macros.at]) m4_include([tests/ovn-macros.at]) +m4_include([tests/ovn-unit-tests.at]) m4_include([tests/ovn.at]) m4_include([tests/ovn-performance.at]) m4_include([tests/ovn-northd.at])