From patchwork Fri Oct 9 15:29:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1379267 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.136; helo=silver.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=QoUgtGW3; dkim-atps=neutral Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C7Bph1WJnz9sTR for ; Sat, 10 Oct 2020 02:30:20 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 605002E2C4; Fri, 9 Oct 2020 15:30:18 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QdyFLRRZ6fQ7; Fri, 9 Oct 2020 15:29:58 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 6E4942E2D0; Fri, 9 Oct 2020 15:29:52 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5640DC07FF; Fri, 9 Oct 2020 15:29:52 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id C725BC0890 for ; Fri, 9 Oct 2020 15:29:50 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id B3FF2876D7 for ; Fri, 9 Oct 2020 15:29:50 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dSt5w103vsPu for ; Fri, 9 Oct 2020 15:29:45 +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 whitealder.osuosl.org (Postfix) with ESMTPS id 3D208877A4 for ; Fri, 9 Oct 2020 15:29:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602257380; 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=PanBrrhV6Or2A5cjy4BezXjJBHY/zTGwzgaNROJVfE4=; b=QoUgtGW3kcGa0F3CAZ15GpgcsejcnPZzSeyYtwtvM56xKBaY668dEMvE6odH7lzViQyzjf U8vsE/efAd+rEHywY2wUMpI4VCu9Qq/gfzJXzXTbfJ3xq9ZOPLUXi8H79HjfzKQe4WgCR7 gMYIlvlWFITA4beOFn5XVWUopcJbtLg= 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-574-_8e5xuUAOlC-pf6w2xF9BQ-1; Fri, 09 Oct 2020 11:29:32 -0400 X-MC-Unique: _8e5xuUAOlC-pf6w2xF9BQ-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 DC3DA802B77 for ; Fri, 9 Oct 2020 15:29:30 +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 7A37773662 for ; Fri, 9 Oct 2020 15:29:30 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Fri, 9 Oct 2020 11:29:26 -0400 Message-Id: <20201009152928.1312612-2-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 1/3] Add unit test framework. 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 creates an API that allows for unit tests to be registered in code by OVN. This change enables the following: * At configure time, "--enable-unit-tests" can be specified to allow for unit tests to be compiled. * This configure-time variable also enables a testsuite variable to be defined, allowing for unit tests to be run from the testsuite. * Testsuite tests are defined using OVS_CONSTRUCTOR, meaning they are automatically registered prior to main() being run in whichever program the unit test is defined in. * Unit tests can be run for a given OVN program using ovn-appctl. For example, `ovn-appctl -t northd unit-test my-unit-test`. This commit does not define any unit tests. That is saved for a later commit in this series. Signed-off-by: Mark Michelson --- acinclude.m4 | 12 +++++ configure.ac | 1 + lib/automake.mk | 4 +- lib/unit-test.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++ lib/unit-test.h | 41 ++++++++++++++++ tests/atlocal.in | 1 + 6 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 lib/unit-test.c create mode 100644 lib/unit-test.h diff --git a/acinclude.m4 b/acinclude.m4 index a797adc82..8b1888075 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -366,3 +366,15 @@ AC_DEFUN([OVN_CHECK_OVS], [ AC_SUBST(OVSVERSION) AC_MSG_RESULT([OVS version is $OVSVERSION]) ]) + +AC_DEFUN([OVN_ENABLE_UNIT_TESTS], + [AC_ARG_ENABLE( + [unit_tests], + [AC_HELP_STRING([--enable-unit-tests], [Enable unit test framework])], + [], [enable_unit_tests=no]) + AC_CONFIG_COMMANDS_PRE( + [if test "X$enable_unit_tests" = Xyes; then + OVS_CFLAGS="$OVS_CFLAGS -DENABLE_UNIT_TESTS" + fi]) + + AC_SUBST([enable_unit_tests])]) diff --git a/configure.ac b/configure.ac index 0b17f05b9..613e2ba3d 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,7 @@ OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED]) OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER]) OVS_ENABLE_WERROR OVS_ENABLE_SPARSE +OVN_ENABLE_UNIT_TESTS OVS_CHECK_PRAGMA_MESSAGE OVN_CHECK_OVS diff --git a/lib/automake.mk b/lib/automake.mk index f3e9c8818..3e9c2a697 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -23,7 +23,9 @@ lib_libovn_la_SOURCES = \ lib/ovn-util.h \ lib/logical-fields.c \ lib/inc-proc-eng.c \ - lib/inc-proc-eng.h + lib/inc-proc-eng.h \ + lib/unit-test.c \ + lib/unit-test.h nodist_lib_libovn_la_SOURCES = \ lib/ovn-dirs.c \ lib/ovn-nb-idl.c \ diff --git a/lib/unit-test.c b/lib/unit-test.c new file mode 100644 index 000000000..a9eb79e73 --- /dev/null +++ b/lib/unit-test.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "openvswitch/shash.h" +#include "openvswitch/dynamic-string.h" +#include "util.h" +#include "unixctl.h" + +#include "lib/unit-test.h" + +#ifdef ENABLE_UNIT_TESTS +static struct shash unit_tests = SHASH_INITIALIZER(&unit_tests); + +struct unit_test_data { + unit_test_cb cb; + void *data; +}; + +void +register_unit_test(const char *name, unit_test_cb cb, void *data) +{ + struct unit_test_data *test_data = xmalloc(sizeof *test_data); + test_data->cb = cb; + test_data->data = data; + shash_add_once(&unit_tests, name, test_data); +} + +enum test_result +run_unit_test(const char *name) +{ + struct unit_test_data *test_data = shash_find_data(&unit_tests, name); + if (!test_data) { + return OVN_TEST_NOT_FOUND; + } + + return test_data->cb(test_data->data); +} + +static void +unixctl_run_unit_test(struct unixctl_conn *conn, int argc, + const char *argv[], void *ignore OVS_UNUSED) +{ + if (argc < 2) { + unixctl_command_reply_error(conn, "No unit test specified"); + return; + } + + enum test_result result; + bool error; + struct ds reply = DS_EMPTY_INITIALIZER; + + result = run_unit_test(argv[1]); + switch (result) { + case OVN_TEST_NOT_FOUND: + error = true; + ds_put_format(&reply, "Unit test %s not found", argv[1]); + break; + case OVN_TEST_FAIL: + error = true; + ds_put_format(&reply, "Unit test %s failed", argv[1]); + break; + case OVN_TEST_PASS: + error = false; + ds_put_format(&reply, "Unit test %s passed", argv[1]); + break; + case OVN_TEST_SKIP: + error = false; + ds_put_format(&reply, "Unit test %s skipped", argv[1]); + break; + default: + OVS_NOT_REACHED(); + } + + if (error) { + unixctl_command_reply_error(conn, ds_cstr(&reply)); + } else { + unixctl_command_reply(conn, ds_cstr(&reply)); + } + + ds_destroy(&reply); +} + +void +register_unixctl_unit_test(void) +{ + unixctl_command_register("unit-test", "", 1, 1, + unixctl_run_unit_test, NULL); +} + +#else /* ENABLE_UNIT_TESTS */ + +void +register_unit_test(const char *name OVS_UNUSED, unit_test_cb cb OVS_UNUSED, + void *data OVS_UNUSED) +{ + return; +} + +void +enum test_result run_unit_test(const char *name OVS_UNUSED) +{ + return OVN_TEST_NOT_FOUND; +} + +void register_unixctl_unit_test(void) +{ + return; +} + +#endif /* ENABLE_UNIT_TESTS */ diff --git a/lib/unit-test.h b/lib/unit-test.h new file mode 100644 index 000000000..e89a4d8f6 --- /dev/null +++ b/lib/unit-test.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVN_UNIT_TEST_H +#define OVN_UNIT_TEST_H 1 + +#include "openvswitch/compiler.h" + +enum test_result { + OVN_TEST_FAIL, + OVN_TEST_PASS, + OVN_TEST_SKIP, + OVN_TEST_NOT_FOUND, +}; + +typedef enum test_result (*unit_test_cb)(void *data); + +void register_unit_test(const char *name, unit_test_cb cb, void *data); + +enum test_result run_unit_test(const char *name); + +void register_unixctl_unit_test(void); + +#define UNIT_TEST_DEFINE(NAME, CB, DATA) \ + OVS_CONSTRUCTOR(unit_test_##NAME) { \ + register_unit_test(#NAME, CB, DATA); \ + } +#endif diff --git a/tests/atlocal.in b/tests/atlocal.in index 26681f02d..ca48ee93d 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -3,6 +3,7 @@ HAVE_OPENSSL='@HAVE_OPENSSL@' OPENSSL_SUPPORTS_SNI='@OPENSSL_SUPPORTS_SNI@' HAVE_UNBOUND='@HAVE_UNBOUND@' EGREP='@EGREP@' +ENABLE_UNIT_TESTS='@enable_unit_tests@' if test x"$PYTHON3" = x; then PYTHON3='@PYTHON3@' From patchwork Fri Oct 9 15:29:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1379265 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.136; helo=silver.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=cu6jfzmS; dkim-atps=neutral Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C7Bp23bZbz9sTc for ; Sat, 10 Oct 2020 02:29:46 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id EE3672E2AC; Fri, 9 Oct 2020 15:29:42 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DJ3j2lKxd8f8; Fri, 9 Oct 2020 15:29:37 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 98DAD2E2A6; Fri, 9 Oct 2020 15:29:37 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 8BA85C0890; Fri, 9 Oct 2020 15:29:37 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 788ABC07FF for ; Fri, 9 Oct 2020 15:29:36 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 7259487677 for ; Fri, 9 Oct 2020 15:29:36 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3V+nOq6XZtem for ; Fri, 9 Oct 2020 15:29:35 +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 whitealder.osuosl.org (Postfix) with ESMTPS id 4473B876D7 for ; Fri, 9 Oct 2020 15:29:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602257374; 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=sokM9Ewqpe9Hqd1Dr1V1gVt4b9L6GrMILAJSp9I/a4Y=; b=cu6jfzmS4p1f4EyZOrwU6APIq/NZNksQ0uQbNEvP/0fq7UoamPPXKDnpwkFGKEWAji3SoP ZIpydXLKmQYB00YubVU2fc/Hh9/qUxwLbiEllsoLL/QvnbGwt4krAuAZoV8HOEyKlTdDEv Vn9sHqOmchhiO3F1bgMTciwlxJFphi8= 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-592-PE5sXD4hNUiJfRXdVYSx8g-1; Fri, 09 Oct 2020 11:29:32 -0400 X-MC-Unique: PE5sXD4hNUiJfRXdVYSx8g-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 A3DCC18A8238 for ; Fri, 9 Oct 2020 15:29:31 +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 3286873662 for ; Fri, 9 Oct 2020 15:29:31 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Fri, 9 Oct 2020 11:29:27 -0400 Message-Id: <20201009152928.1312612-3-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 2/3] northd: refactor init_ipam_info_for_datapath 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 refactor focuses on two efforts: * Break a large function into smaller functions * Pass more specific data types to functions Smaller functions have clearer purposes, have fewer chances of unwanted side effects, and are easier to test. The next commit in this series will add some unit tests that exercise the new functions created in this commit. Signed-off-by: Mark Michelson --- northd/ovn-northd.c | 186 ++++++++++++++++++++++++++------------------ 1 file changed, 110 insertions(+), 76 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 8bab9b047..d989ddf53 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -893,57 +893,49 @@ lrouter_is_enabled(const struct nbrec_logical_router *lrouter) } static void -init_ipam_info_for_datapath(struct ovn_datapath *od) +init_ipam_ipv6_prefix(const char *ipv6_prefix, struct ipam_info *info) { - if (!od->nbs) { + if (!ipv6_prefix) { return; } - const char *subnet_str = smap_get(&od->nbs->other_config, "subnet"); - const char *ipv6_prefix = smap_get(&od->nbs->other_config, "ipv6_prefix"); - - if (ipv6_prefix) { - if (strstr(ipv6_prefix, "/")) { - /* If a prefix length was specified, it must be 64. */ - struct in6_addr mask; - char *error - = ipv6_parse_masked(ipv6_prefix, - &od->ipam_info.ipv6_prefix, &mask); - if (error) { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s: %s", - ipv6_prefix, error); - free(error); - } else { - if (ipv6_count_cidr_bits(&mask) == 64) { - od->ipam_info.ipv6_prefix_set = true; - } else { - static struct vlog_rate_limit rl - = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s: must be /64", - ipv6_prefix); - } - } + if (strchr(ipv6_prefix, '/')) { + /* If a prefix length was specified, it must be 64. */ + struct in6_addr mask; + char *error + = ipv6_parse_masked(ipv6_prefix, + &info->ipv6_prefix, &mask); + if (error) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s: %s", + ipv6_prefix, error); + free(error); } else { - od->ipam_info.ipv6_prefix_set = ipv6_parse( - ipv6_prefix, &od->ipam_info.ipv6_prefix); - if (!od->ipam_info.ipv6_prefix_set) { + if (ipv6_count_cidr_bits(&mask) == 64) { + info->ipv6_prefix_set = true; + } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s", ipv6_prefix); + VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s: must be /64", + ipv6_prefix); } } - } - - if (!subnet_str) { - if (!ipv6_prefix) { - od->ipam_info.mac_only = smap_get_bool(&od->nbs->other_config, - "mac_only", false); + } else { + info->ipv6_prefix_set = ipv6_parse( + ipv6_prefix, &info->ipv6_prefix); + if (!info->ipv6_prefix_set) { + static struct vlog_rate_limit rl + = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "bad 'ipv6_prefix' %s", ipv6_prefix); } - return; } +} +static void +init_ipam_ipv4(const char *subnet_str, const char *exclude_ip_list, + struct ipam_info *info) +{ ovs_be32 subnet, mask; char *error = ip_parse_masked(subnet_str, &subnet, &mask); if (error || mask == OVS_BE32_MAX || !ip_is_cidr(mask)) { @@ -954,17 +946,14 @@ init_ipam_info_for_datapath(struct ovn_datapath *od) return; } - od->ipam_info.start_ipv4 = ntohl(subnet & mask) + 1; - od->ipam_info.total_ipv4s = ~ntohl(mask); - od->ipam_info.allocated_ipv4s = - bitmap_allocate(od->ipam_info.total_ipv4s); + info->start_ipv4 = ntohl(subnet & mask) + 1; + info->total_ipv4s = ~ntohl(mask); + info->allocated_ipv4s = + bitmap_allocate(info->total_ipv4s); /* Mark first IP as taken */ - bitmap_set1(od->ipam_info.allocated_ipv4s, 0); + bitmap_set1(info->allocated_ipv4s, 0); - /* Check if there are any reserver IPs (list) to be excluded from IPAM */ - const char *exclude_ip_list = smap_get(&od->nbs->other_config, - "exclude_ips"); if (!exclude_ip_list) { return; } @@ -994,11 +983,11 @@ init_ipam_info_for_datapath(struct ovn_datapath *od) } /* Clamp start...end to fit the subnet. */ - start = MAX(od->ipam_info.start_ipv4, start); - end = MIN(od->ipam_info.start_ipv4 + od->ipam_info.total_ipv4s, end); + start = MAX(info->start_ipv4, start); + end = MIN(info->start_ipv4 + info->total_ipv4s, end); if (end > start) { - bitmap_set_multiple(od->ipam_info.allocated_ipv4s, - start - od->ipam_info.start_ipv4, + bitmap_set_multiple(info->allocated_ipv4s, + start - info->start_ipv4, end - start, 1); } else { lexer_error(&lexer, "excluded addresses not in subnet"); @@ -1006,12 +995,44 @@ init_ipam_info_for_datapath(struct ovn_datapath *od) } if (lexer.error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "logical switch "UUID_FMT": bad exclude_ips (%s)", - UUID_ARGS(&od->key), lexer.error); + /* + * VLOG_WARN_RL(&rl, "logical switch "UUID_FMT": bad exclude_ips (%s)", + * UUID_ARGS(&od->key), lexer.error); + */ + VLOG_WARN_RL(&rl, "logical switch: bad exclude_ips (%s)", lexer.error); } lexer_destroy(&lexer); } +static void +init_ipam_info(struct ipam_info *info, const struct smap *config) +{ + const char *subnet_str = smap_get(config, "subnet"); + const char *ipv6_prefix = smap_get(config, "ipv6_prefix"); + const char *exclude_ips = smap_get(config, "exclude_ips"); + + init_ipam_ipv6_prefix(ipv6_prefix, info); + + if (!subnet_str) { + if (!ipv6_prefix) { + info->mac_only = smap_get_bool(config, "mac_only", false); + } + return; + } + + init_ipam_ipv4(subnet_str, exclude_ips, info); +} + +static void +init_ipam_info_for_datapath(struct ovn_datapath *od) +{ + if (!od->nbs) { + return; + } + + init_ipam_info(&od->ipam_info, &od->nbs->other_config); +} + static void init_mcast_info_for_router_datapath(struct ovn_datapath *od) { @@ -1578,23 +1599,36 @@ ipam_insert_mac(struct eth_addr *ea, bool check) hmap_insert(&macam, &new_macam_node->hmap_node, hash_uint64(mac64)); } +static bool +ipam_insert_ip(struct ipam_info *info, uint32_t ip) +{ + if (!info->allocated_ipv4s) { + return true; + } + + if (ip >= info->start_ipv4 && + ip < (info->start_ipv4 + info->total_ipv4s)) { + if (bitmap_is_set(info->allocated_ipv4s, + ip - info->start_ipv4)) { + return false; + } + bitmap_set1(info->allocated_ipv4s, + ip - info->start_ipv4); + } + return true; +} + static void -ipam_insert_ip(struct ovn_datapath *od, uint32_t ip) +ipam_insert_ip_for_datapath(struct ovn_datapath *od, uint32_t ip) { - if (!od || !od->ipam_info.allocated_ipv4s) { + if (!od) { return; } - if (ip >= od->ipam_info.start_ipv4 && - ip < (od->ipam_info.start_ipv4 + od->ipam_info.total_ipv4s)) { - if (bitmap_is_set(od->ipam_info.allocated_ipv4s, - ip - od->ipam_info.start_ipv4)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "Duplicate IP set on switch %s: "IP_FMT, - od->nbs->name, IP_ARGS(htonl(ip))); - } - bitmap_set1(od->ipam_info.allocated_ipv4s, - ip - od->ipam_info.start_ipv4); + if (!ipam_insert_ip(&od->ipam_info, ip)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Duplicate IP set on switch %s: "IP_FMT, + od->nbs->name, IP_ARGS(htonl(ip))); } } @@ -1624,7 +1658,7 @@ ipam_insert_lsp_addresses(struct ovn_datapath *od, struct ovn_port *op, for (size_t j = 0; j < laddrs.n_ipv4_addrs; j++) { uint32_t ip = ntohl(laddrs.ipv4_addrs[j].addr); - ipam_insert_ip(od, ip); + ipam_insert_ip_for_datapath(od, ip); } destroy_lport_addresses(&laddrs); @@ -1666,7 +1700,7 @@ ipam_add_port_addresses(struct ovn_datapath *od, struct ovn_port *op) * about a duplicate IP address. */ if (ip != op->peer->od->ipam_info.start_ipv4) { - ipam_insert_ip(op->peer->od, ip); + ipam_insert_ip_for_datapath(op->peer->od, ip); } } @@ -1701,21 +1735,21 @@ ipam_get_unused_mac(ovs_be32 ip) } static uint32_t -ipam_get_unused_ip(struct ovn_datapath *od) +ipam_get_unused_ip(struct ipam_info *info) { - if (!od || !od->ipam_info.allocated_ipv4s) { + if (!info->allocated_ipv4s) { return 0; } - size_t new_ip_index = bitmap_scan(od->ipam_info.allocated_ipv4s, 0, 0, - od->ipam_info.total_ipv4s - 1); - if (new_ip_index == od->ipam_info.total_ipv4s - 1) { + size_t new_ip_index = bitmap_scan(info->allocated_ipv4s, 0, 0, + info->total_ipv4s - 1); + if (new_ip_index == info->total_ipv4s - 1) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL( &rl, "Subnet address space has been exhausted."); return 0; } - return od->ipam_info.start_ipv4 + new_ip_index; + return info->start_ipv4 + new_ip_index; } enum dynamic_update_type { @@ -1919,7 +1953,7 @@ update_unchanged_dynamic_addresses(struct dynamic_address_update *update) ipam_insert_mac(&update->current_addresses.ea, false); } if (update->ipv4 == NONE && update->current_addresses.n_ipv4_addrs) { - ipam_insert_ip(update->op->od, + ipam_insert_ip_for_datapath(update->op->od, ntohl(update->current_addresses.ipv4_addrs[0].addr)); } } @@ -1999,7 +2033,7 @@ update_dynamic_addresses(struct dynamic_address_update *update) ip4 = update->static_ip; break; case DYNAMIC: - ip4 = htonl(ipam_get_unused_ip(update->od)); + ip4 = htonl(ipam_get_unused_ip(&update->od->ipam_info)); VLOG_INFO("Assigned dynamic IPv4 address '"IP_FMT"' to port '%s'", IP_ARGS(ip4), update->op->nbsp->name); } @@ -2048,7 +2082,7 @@ update_dynamic_addresses(struct dynamic_address_update *update) ipam_insert_mac(&mac, true); if (ip4) { - ipam_insert_ip(update->od, ntohl(ip4)); + ipam_insert_ip_for_datapath(update->od, ntohl(ip4)); ds_put_format(&new_addr, " "IP_FMT, IP_ARGS(ip4)); } if (!IN6_ARE_ADDR_EQUAL(&ip6, &in6addr_any)) { 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])