From 117573e2d2790231c8ad5fbaba99b2a711c89e77 Mon Sep 17 00:00:00 2001 From: Ales Musil Date: Fri, 15 Mar 2024 18:38:30 +0100 Subject: [PATCH] utilities: Add ovn-debug binary tool. Add ovn-debug binary tool that can be extended with commands that might be useful for tests/debugging of OVN environment. Currently the tool supports only two commands: 1) "lflow-stage-to-ltable STAGE_NAME" that converts stage name into logical flow table id. 2) "lflow-stage-to-oftable STAGE_NAME" that converts stage name into OpenFlow table id. For now it will be used in tests to get rid remaining hardcoded table numbers. Signed-off-by: Ales Musil Acked-by: Mark Michelson Signed-off-by: Mark Michelson --- NEWS | 5 ++ README.rst | 1 + debian/ovn-common.install | 1 + debian/ovn-common.manpages | 1 + rhel/ovn-fedora.spec.in | 2 + utilities/.gitignore | 2 + utilities/automake.mk | 10 ++- utilities/ovn-debug.8.xml | 28 +++++++ utilities/ovn-debug.c | 155 +++++++++++++++++++++++++++++++++++++ 9 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 utilities/ovn-debug.8.xml create mode 100644 utilities/ovn-debug.c diff --git a/NEWS b/NEWS index a9c9a269bb..4d6ebea89e 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,11 @@ Post v24.03.0 disable adding the ARP responder flows if set to true. - IGMP_Group has new "protocol" column that displays the the group protocol version. + - Add ovn-debug tool containing two commands. + "lflow-stage-to-ltable STAGE_NAME" that converts stage name into logical + flow table id. + "lflow-stage-to-oftable STAGE_NAME" that converts stage name into OpenFlow + table id. OVN v24.03.0 - 01 Mar 2024 -------------------------- diff --git a/README.rst b/README.rst index 6fb7177421..428cd8ee87 100644 --- a/README.rst +++ b/README.rst @@ -56,6 +56,7 @@ The main components of this distribution are: - ovn-sbctl, a tool for interfacing with the southbound database. - ovn-trace, a debugging utility that allows for tracing of packets through the logical network. +- ovn-debug, a tool to simplify debugging of OVN setup. - Scripts and specs for building RPMs. What other documentation is available? diff --git a/debian/ovn-common.install b/debian/ovn-common.install index 050d1c63a9..fc48f07e40 100644 --- a/debian/ovn-common.install +++ b/debian/ovn-common.install @@ -5,6 +5,7 @@ usr/bin/ovn-ic-nbctl usr/bin/ovn-ic-sbctl usr/bin/ovn-trace usr/bin/ovn_detrace.py +usr/bin/ovn-debug usr/share/ovn/scripts/ovn-ctl usr/share/ovn/scripts/ovndb-servers.ocf usr/share/ovn/scripts/ovn-lib diff --git a/debian/ovn-common.manpages b/debian/ovn-common.manpages index 1fa3d9cb32..e864512e37 100644 --- a/debian/ovn-common.manpages +++ b/debian/ovn-common.manpages @@ -11,3 +11,4 @@ utilities/ovn-ic-nbctl.8 utilities/ovn-ic-sbctl.8 utilities/ovn-trace.8 utilities/ovn-detrace.1 +utilities/ovn-debug.8 diff --git a/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in index 03c1f27c5f..670f1ca9eb 100644 --- a/rhel/ovn-fedora.spec.in +++ b/rhel/ovn-fedora.spec.in @@ -495,6 +495,7 @@ fi %{_bindir}/ovn-appctl %{_bindir}/ovn-ic-nbctl %{_bindir}/ovn-ic-sbctl +%{_bindir}/ovn-debug %{_datadir}/ovn/scripts/ovn-ctl %{_datadir}/ovn/scripts/ovn-lib %{_datadir}/ovn/scripts/ovndb-servers.ocf @@ -515,6 +516,7 @@ fi %{_mandir}/man8/ovn-ic.8* %{_mandir}/man5/ovn-ic-nb.5* %{_mandir}/man5/ovn-ic-sb.5* +%{_mandir}/man8/ovn-debug.8* %{_prefix}/lib/ocf/resource.d/ovn/ovndb-servers %config(noreplace) %{_sysconfdir}/logrotate.d/ovn %{_unitdir}/ovn-db@.service diff --git a/utilities/.gitignore b/utilities/.gitignore index da237563ba..3ae97b00fa 100644 --- a/utilities/.gitignore +++ b/utilities/.gitignore @@ -13,6 +13,8 @@ /ovn-trace.8 /ovn_detrace.py /ovn-detrace.1 +/ovn-debug +/ovn-debug.8 /ovn-docker-overlay-driver /ovn-docker-underlay-driver /ovn-lib diff --git a/utilities/automake.mk b/utilities/automake.mk index ebb74ec34b..de4f6efb53 100644 --- a/utilities/automake.mk +++ b/utilities/automake.mk @@ -11,7 +11,8 @@ man_MANS += \ utilities/ovn-ic-sbctl.8 \ utilities/ovn-trace.8 \ utilities/ovn-detrace.1 \ - utilities/ovn-appctl.8 + utilities/ovn-appctl.8 \ + utilities/ovn-debug.8 MAN_ROOTS += \ utilities/ovn-detrace.1.in @@ -34,6 +35,7 @@ EXTRA_DIST += \ utilities/ovn-ic-sbctl.8.xml \ utilities/ovn-appctl.8.xml \ utilities/ovn-trace.8.xml \ + utilities/ovn-debug.8.xml \ utilities/ovn_detrace.py.in \ utilities/ovndb-servers.ocf \ utilities/checkpatch.py \ @@ -63,6 +65,7 @@ CLEANFILES += \ utilities/ovn-ic-nbctl.8 \ utilities/ovn-ic-sbctl.8 \ utilities/ovn-trace.8 \ + utilities/ovn-debug.8 \ utilities/ovn-detrace.1 \ utilities/ovn-detrace \ utilities/ovn_detrace.py \ @@ -120,4 +123,9 @@ UNINSTALL_LOCAL += ovn-detrace-uninstall ovn-detrace-uninstall: rm -f $(DESTDIR)$(bindir)/ovn-detrace +# ovn-debug +bin_PROGRAMS += utilities/ovn-debug +utilities_ovn_debug_SOURCES = utilities/ovn-debug.c +utilities_ovn_debug_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la + include utilities/bugtool/automake.mk diff --git a/utilities/ovn-debug.8.xml b/utilities/ovn-debug.8.xml new file mode 100644 index 0000000000..bdd2083287 --- /dev/null +++ b/utilities/ovn-debug.8.xml @@ -0,0 +1,28 @@ + + +

Name

+

ovn-debug -- Open Virtual Network debug tool

+ +

Synopsis

+

ovn-debug COMMAND [ARG...]

+ +

Description

+

+ ovn-debug, OVN debug tool, is a tool to help with + debugging of OVN setup. +

+ +

Commands

+
+
lflow-stage-to-ltable STAGE_NAME
+
+ Convert the logical flow stage name e.g. ls_in_lb into + the logical flow table number e.g. 13. +
+
lflow-stage-to-oftable STAGE_NAME
+
+ Convert the logical flow stage name e.g. ls_in_lb into + the OpenFlow table number e.g. 21. +
+
+
diff --git a/utilities/ovn-debug.c b/utilities/ovn-debug.c new file mode 100644 index 0000000000..0cec9f6716 --- /dev/null +++ b/utilities/ovn-debug.c @@ -0,0 +1,155 @@ +/* Copyright (c) 2024, 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 +#include + +#include "command-line.h" +#include "controller/lflow.h" +#include "northd/northd.h" +#include "ovn-util.h" + +struct ovn_lflow_stage { + const char *name; + uint8_t table_id; + enum ovn_pipeline pipeline; +}; + +static const struct ovn_lflow_stage ovn_lflow_stages[] = { +#define PIPELINE_STAGE(DP_TYPE, PIPELINE, STAGE, TABLE, NAME) \ + (struct ovn_lflow_stage) { \ + .name = NAME, \ + .table_id = TABLE, \ + .pipeline = P_##PIPELINE, \ + }, + PIPELINE_STAGES +#undef PIPELINE_STAGE +}; + +static const struct ovn_lflow_stage * +ovn_lflow_stage_find_by_name(const char *name) +{ + + for (size_t i = 0; i < ARRAY_SIZE(ovn_lflow_stages); i++) { + const struct ovn_lflow_stage *stage = &ovn_lflow_stages[i]; + if (!strcmp(stage->name, name)) { + return stage; + } + } + + return NULL; +} + +static void +lflow_stage_to_table(struct ovs_cmdl_context *ctx) +{ + const char *name = ctx->argv[1]; + const struct ovn_lflow_stage *stage = ovn_lflow_stage_find_by_name(name); + + if (!stage) { + ovs_fatal(0, "Couldn't find OVN logical flow stage with name \"%s\"", + name); + } + + uint8_t table = stage->table_id; + + if (!strcmp("lflow-stage-to-oftable", ctx->argv[0])) { + table += stage->pipeline == P_IN + ? OFTABLE_LOG_INGRESS_PIPELINE + : OFTABLE_LOG_EGRESS_PIPELINE; + } + + printf("%"PRIu8"\n", table); + exit(EXIT_SUCCESS); +} + + +static void +usage(void) +{ + printf("\ +%s: OVN debug utility\n\ +usage: %s COMMAND [ARG...]\n\ +\n\ +lflow-stage-to-ltable STAGE_NAME\n\ + Converts STAGE_NAME into logical flow table number.\n\ +lflow-stage-to-oftable STAGE_NAME\n\ + Converts STAGE_NAME into OpenFlow table number.\n\ +\n\ +Options:\n\ + -h, --help display this help message\n\ + -V, --version display version information\n", + program_name, program_name); + exit(EXIT_SUCCESS); +} + +static void +help(struct ovs_cmdl_context *ctx OVS_UNUSED) +{ + usage(); +} + +int +main(int argc, char *argv[]) +{ + static const struct option long_options[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0}, + }; + char *short_options = ovs_cmdl_long_options_to_short_options(long_options); + + ovn_set_program_name(argv[0]); + + for (;;) { + int option_index = 0; + int c = getopt_long(argc, argv, short_options, long_options, + &option_index); + + if (c == -1) { + break; + } + switch (c) { + case 'V': + ovn_print_version(0, 0); + exit(EXIT_SUCCESS); + + case 'h': + usage(); + /* fall through */ + + case '?': + exit(1); + + default: + ovs_abort(0, "Invalid option."); + } + } + free(short_options); + + static const struct ovs_cmdl_command commands[] = { + {"lflow-stage-to-oftable", NULL, 1, 1, lflow_stage_to_table, + OVS_RO}, + {"lflow-stage-to-ltable", NULL, 1, 1, lflow_stage_to_table, + OVS_RO}, + { "help", NULL, 0, INT_MAX, help, OVS_RO }, + {NULL, NULL, 0, 0, NULL, OVS_RO}, + }; + struct ovs_cmdl_context ctx; + ctx.argc = argc - optind; + ctx.argv = argv + optind; + ovs_cmdl_run_command(&ctx, commands); +}