/ovn-sb.5
/ovn-sb.gv
/ovn-sb.pic
-/ovn-nbctl
-/ovn-nbctl.8
$(srcdir)/ovn/ovn-nb.xml > $@.tmp && \
mv $@.tmp $@
-man_MANS += ovn/ovn-architecture.7 ovn/ovn-nbctl.8
-EXTRA_DIST += ovn/ovn-architecture.7.xml ovn/ovn-nbctl.8.xml
-DISTCLEANFILES += ovn/ovn-nbctl.8 ovn/ovn-architecture.7
+man_MANS += ovn/ovn-architecture.7
+EXTRA_DIST += ovn/ovn-architecture.7.xml
+DISTCLEANFILES += ovn/ovn-architecture.7
EXTRA_DIST += \
ovn/TODO \
ovn/CONTAINERS.OpenStack.md \
ovn/OVN-GW-HA.md
-# ovn-nbctl
-bin_PROGRAMS += ovn/ovn-nbctl
-ovn_ovn_nbctl_SOURCES = ovn/ovn-nbctl.c
-ovn_ovn_nbctl_LDADD = ovn/lib/libovn.la ovsdb/libovsdb.la lib/libopenvswitch.la
-
include ovn/controller/automake.mk
include ovn/lib/automake.mk
include ovn/northd/automake.mk
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<manpage program="ovn-nbctl" section="8" title="ovn-nbctl">
- <h1>Name</h1>
- <p>ovn-nbctl -- Open Virtual Network northbound db management utility</p>
-
- <h1>Synopsys</h1>
- <p><code>ovn-nbctl</code> [<var>options</var>] <var>command</var> [<var>arg</var>...]</p>
-
- <h1>Description</h1>
- <p>This utility can be used to manage the OVN northbound database.</p>
-
- <h1>General Commands</h1>
-
- <dl>
- <dt><code>show [<var>lswitch</var>]</code></dt>
- <dd>
- Prints a brief overview of the database contents. If
- <var>lswitch</var> is provided, only records related to that
- logical switch are shown.
- </dd>
- </dl>
-
- <h1>Logical Switch Commands</h1>
-
- <dl>
- <dt><code>lswitch-add</code> [<var>lswitch</var>]</dt> <dd> Creates a new logical switch named <var>lswitch</var>. If
- <var>lswitch</var> is not provided, the switch will not have a
- name so other commands must refer to this switch by its UUID.
- Initially the switch will have no ports.
- </dd>
-
- <dt><code>lswitch-del</code> <var>lswitch</var></dt>
- <dd>
- Deletes <var>lswitch</var>.
- </dd>
-
- <dt><code>lswitch-list</code></dt>
- <dd>
- Lists all existing switches on standard output, one per line.
- </dd>
-
- <dt><code>lswitch-set-external-id</code> <var>lswitch</var> <var>key</var> [<var>value</var>]</dt>
- <dd>
- <p>Sets or clears an ``external ID'' value on <var>lswitch</var>.
- These values are intended to identify entities external to OVN
- with which <var>lswitch</var> is associated. The OVN Northbound
- database schema may specify well-known <var>key</var> values,
- but <var>key</var> and <var>value</var> are otherwise arbitrary
- strings.</p>
-
- <p>If <var>value</var> is specified, then <var>key</var> is set to
- <var>value</var> for <var>lswitch</var>, overwriting any
- previous value. If <var>value</var> is omitted, then
- <var>key</var> is removed from <var>lswitch</var>'s set of
- external IDs (if it was present.</p>
- </dd>
-
- <dt><code>lswitch-get-external-id</code> <var>lswitch</var> [<var>key</var>]</dt>
- <dd>
- Queries the external IDs on <var>lswitch</var>. If
- <var>key</var> is specified, the output is the value for that
- <var>key</var> or the empty string if <var>key</var> is unset.
- If <var>key</var> is omitted, the output is
- <var>key</var><code>=</code><var>value</var>, one per line, for
- each key-value pair.
- </dd>
- </dl>
-
- <h1>Logical Port Commands</h1>
- <dl>
- <dt><code>lport-add</code> <var>lswitch</var> <var>lport</var></dt>
- <dd>
- Creates on <var>lswitch</var> a new logical port named
- <var>lport</var>.
- </dd>
-
- <dt><code>lport-add</code> <var>lswitch</var> <var>lport</var> <var>parent</var> <var>tag</var></dt>
- <dd>
- Creates on <var>lswitch</var> a logical port named <var>lport</var>
- that is a child of <var>parent</var> that is identied with
- <var>tag</var>. This is useful in cases such as virtualized
- container environments where Open vSwitch does not have a direct
- connection to the container's port and it must be shared with
- the virtual machine's port.
- </dd>
-
- <dt><code>lport-del</code> <var>lport</var></dt>
- <dd>
- Deletes <var>lport</var>.
- </dd>
-
- <dt><code>lport-list</code> <var>lswitch</var></dt>
- <dd>
- Lists all the logical ports within <var>lswitch</var> on
- standard output, one per line.
- </dd>
-
- <dt><code>lport-get-parent</code> <var>lport</var></dt>
- <dd>
- If set, get the parent port of <var>lport</var>. If not set, print
- nothing.
- </dd>
-
- <dt><code>lport-get-tag</code> <var>lport</var></dt>
- <dd>
- If set, get the tag for <var>lport</var> traffic. If not set, print
- nothing.
- </dd>
-
- <dt><code>lport-set-external-id</code> <var>lport</var> <var>key</var> [<var>value</var>]</dt>
- <dd>
- <p>Sets or clears an ``external ID'' value on <var>lport</var>.
- These values are intended to identify entities external to OVN
- with which <var>lport</var> is associated. The OVN Northbound
- database schema may specify well-known <var>key</var> values,
- but <var>key</var> and <var>value</var> are otherwise arbitrary
- strings.</p>
-
- <p>If <var>value</var> is specified, then <var>key</var> is set to
- <var>value</var> for <var>lport</var>, overwriting any
- previous value. If <var>value</var> is omitted, then
- <var>key</var> is removed from <var>lport</var>'s set of
- external IDs (if it was present.</p>
- </dd>
-
- <dt><code>lport-get-external-id</code> <var>lport</var> [<var>key</var>]</dt>
- <dd>
- Queries the external IDs on <var>lport</var>. If
- <var>key</var> is specified, the output is the value for that
- <var>key</var> or the empty string if <var>key</var> is unset.
- If <var>key</var> is omitted, the output is
- <var>key</var><code>=</code><var>value</var>, one per line, for
- each key-value pair.
- </dd>
-
- <dt><code>lport-set-macs</code> <var>lport</var> [<var>mac</var>]...</dt>
- <dd>
- Sets the MACs associated with <var>lport</var> to
- <var>mac</var>. Multiple MACs may be sets by using multiple
- <var>mac</var> arguments. If no <var>mac</var> argument is
- given, <var>lport</var> will have no MACs associated with it.
- </dd>
-
- <dt><code>lport-get-macs</code> <var>lport</var></dt>
- <dd>
- Lists all the MACs associated with <var>lport</var> on standard
- output, one per line.
- </dd>
-
- <dt><code>lport-set-port-security</code> <var>lport</var> [<var>addrs</var>]...</dt>
- <dd>
- <p>
- Sets the port security addresses associated with <var>lport</var> to
- <var>addrs</var>. Multiple sets of addresses may be set by using
- multiple <var>addrs</var> arguments. If no <var>addrs</var> argument
- is given, <var>lport</var> will not have port security enabled.
- </p>
-
- <p>
- Port security limits the addresses from which a logical port may send
- packets and to which it may receive packets. See the
- <code>ovn-nb</code>(5) documentation for the <ref
- column="port_security" table="Logical_Port"/> column in the <ref
- table="Logical_Port"/> table for details.
- </p>
- </dd>
-
- <dt><code>lport-get-port-security</code> <var>lport</var></dt>
- <dd>
- Lists all the port security addresses associated with <var>lport</var>
- on standard output, one per line.
- </dd>
-
- <dt><code>lport-get-up</code> <var>lport</var></dt>
- <dd>
- Prints the state of <var>lport</var>, either <code>up</code> or
- <code>down</code>.
- </dd>
-
- <dt><code>lport-set-enabled</code> <var>lport</var> <var>state</var></dt>
- <dd>
- Set the administrative state of <var>lport</var>, either <code>enabled</code>
- or <code>disabled</code>. When a port is disabled, no traffic is allowed into
- or out of the port.
- </dd>
-
- <dt><code>lport-get-enabled</code> <var>lport</var></dt>
- <dd>
- Prints the administrative state of <var>lport</var>, either <code>enabled</code>
- or <code>disabled</code>.
- </dd>
-
- <dt><code>lport-set-type</code> <var>lport</var> <var>type</var></dt>
- <dd>
- Set the type for the logical port. No special types have been implemented yet.
- </dd>
-
- <dt><code>lport-get-type</code> <var>lport</var></dt>
- <dd>
- Get the type for the logical port.
- </dd>
-
- <dt><code>lport-set-options</code> <var>lport</var> [<var>key=value</var>]...</dt>
- <dd>
- Set type-specific key-value options for the logical port.
- </dd>
-
- <dt><code>lport-get-options</code> <var>lport</var></dt>
- <dd>
- Get the type-specific options for the logical port.
- </dd>
-
- </dl>
-
- <h1>Options</h1>
-
- <dl>
- <dt><code>-d</code> <var>database</var></dt>
- <dt><code>--db</code> <var>database</var></dt>
- <dd>
- The OVSDB database remote to contact. If the <env>OVN_NB_DB</env>
- environment variable is set, its value is used as the default.
- Otherwise, the default is <code>unix:@RUNDIR@/db.sock</code>, but this
- default is unlikely to be useful outside of single-machine OVN test
- environments.
- </dd>
-
- <dt><code>-h</code> | <code>--help</code></dt>
- <dt><code>-o</code> | <code>--options</code></dt>
- <dt><code>-V</code> | <code>--version</code></dt>
- </dl>
-
- <h1>Logging options</h1>
- <dl>
- <dt><code>-v</code><var>spec</var>, <code>--verbose=</code><var>spec</var></dt>
- <dt><code>-v</code>, <code>--verbose</code></dt>
- <dt><code>--log-file</code>[<code>=</code><var>file</var>]</dt>
- <dt><code>--syslog-target=</code><var>host</var><code>:</code><var>port</var></dt>
- </dl>
-
- <h1>PKI configuration (required to use SSL)</h1>
- <dl>
- <dt><code>-p</code>, <code>--private-key=</code><var>file</var> file with private key</dt>
- <dt><code>-c</code>, <code>--certificate=</code><var>file</var> file with certificate for private key</dt>
- <dt><code>-C</code>, <code>--ca-cert=</code><var>file</var> file with peer CA certificate</dt>
- </dl>
-
-</manpage>
+++ /dev/null
-/*
- * 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 <config.h>
-
-#include <getopt.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "command-line.h"
-#include "dirs.h"
-#include "fatal-signal.h"
-#include "ovn/lib/ovn-nb-idl.h"
-#include "poll-loop.h"
-#include "process.h"
-#include "stream.h"
-#include "stream-ssl.h"
-#include "util.h"
-#include "openvswitch/vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(ovn_nbctl);
-
-struct nbctl_context {
- struct ovsdb_idl *idl;
- struct ovsdb_idl_txn *txn;
-};
-
-static const char *db;
-
-static const char *default_db(void);
-
-static void
-usage(void)
-{
- printf("\
-%s: OVN northbound DB management utility\n\
-usage: %s [OPTIONS] COMMAND [ARG...]\n\
-\n\
-General commands:\n\
- show print overview of database contents\n\
- show LSWITCH print overview of database contents for LSWITCH\n\
-\n\
-Logical switch commands:\n\
- lswitch-add [LSWITCH] create a logical switch named LSWITCH\n\
- lswitch-del LSWITCH delete LSWITCH and all its ports\n\
- lswitch-list print the names of all logical switches\n\
- lswitch-set-external-id LSWITCH KEY [VALUE]\n\
- set or delete an external-id on LSWITCH\n\
- lswitch-get-external-id LSWITCH [KEY]\n\
- list one or all external-ids on LSWITCH\n\
-\n\
-Logical port commands:\n\
- lport-add LSWITCH LPORT add logical port LPORT on LSWITCH\n\
- lport-add LSWITCH LPORT PARENT TAG\n\
- add logical port LPORT on LSWITCH with PARENT\n\
- on TAG\n\
- lport-del LPORT delete LPORT from its attached switch\n\
- lport-list LSWITCH print the names of all logical ports on LSWITCH\n\
- lport-get-parent LPORT get the parent of LPORT if set\n\
- lport-get-tag LPORT get the LPORT's tag if set\n\
- lport-set-external-id LPORT KEY [VALUE]\n\
- set or delete an external-id on LPORT\n\
- lport-get-external-id LPORT [KEY]\n\
- list one or all external-ids on LPORT\n\
- lport-set-macs LPORT [MAC]...\n\
- set MAC addresses for LPORT.\n\
- lport-get-macs LPORT get a list of MAC addresses on LPORT\n\
- lport-set-port-security LPORT [ADDRS]...\n\
- set port security addresses for LPORT.\n\
- lport-get-port-security LPORT get LPORT's port security addresses\n\
- lport-get-up LPORT get state of LPORT ('up' or 'down')\n\
- lport-set-enabled LPORT STATE\n\
- set administrative state LPORT\n\
- ('enabled' or 'disabled')\n\
- lport-get-enabled LPORT get administrative state LPORT\n\
- ('enabled' or 'disabled')\n\
- lport-set-type LPORT TYPE Set the type for LPORT\n\
- lport-get-type LPORT Get the type for LPORT\n\
- lport-set-options LPORT KEY=VALUE [KEY=VALUE]...\n\
- Set options related to the type of LPORT\n\
- lport-get-options LPORT Get the type specific options for LPORT\n\
-\n\
-Options:\n\
- --db=DATABASE connect to DATABASE\n\
- (default: %s)\n\
- -h, --help display this help message\n\
- -o, --options list available options\n\
- -V, --version display version information\n\
-", program_name, program_name, default_db());
- vlog_usage();
- stream_usage("database", true, true, false);
-}
-\f
-static const struct nbrec_logical_switch *
-lswitch_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
-{
- const struct nbrec_logical_switch *lswitch = NULL;
- bool is_uuid = false;
- bool duplicate = false;
- struct uuid lswitch_uuid;
-
- if (uuid_from_string(&lswitch_uuid, id)) {
- is_uuid = true;
- lswitch = nbrec_logical_switch_get_for_uuid(nb_ctx->idl,
- &lswitch_uuid);
- }
-
- if (!lswitch) {
- const struct nbrec_logical_switch *iter;
-
- NBREC_LOGICAL_SWITCH_FOR_EACH(iter, nb_ctx->idl) {
- if (strcmp(iter->name, id)) {
- continue;
- }
- if (lswitch) {
- VLOG_WARN("There is more than one logical switch named '%s'. "
- "Use a UUID.", id);
- lswitch = NULL;
- duplicate = true;
- break;
- }
- lswitch = iter;
- }
- }
-
- if (!lswitch && !duplicate) {
- VLOG_WARN("lswitch not found for %s: '%s'",
- is_uuid ? "UUID" : "name", id);
- }
-
- return lswitch;
-}
-
-static void
-print_lswitch(const struct nbrec_logical_switch *lswitch)
-{
- printf(" lswitch "UUID_FMT" (%s)\n",
- UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
-
- for (size_t i = 0; i < lswitch->n_ports; i++) {
- const struct nbrec_logical_port *lport = lswitch->ports[i];
-
- printf(" lport %s\n", lport->name);
- if (lport->parent_name && lport->n_tag) {
- printf(" parent: %s, tag:%"PRIu64"\n",
- lport->parent_name, lport->tag[0]);
- }
- if (lport->n_macs) {
- printf(" macs:");
- for (size_t j = 0; j < lport->n_macs; j++) {
- printf(" %s", lport->macs[j]);
- }
- printf("\n");
- }
- }
-}
-
-static void
-do_show(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const struct nbrec_logical_switch *lswitch;
-
- if (ctx->argc == 2) {
- lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
- if (lswitch) {
- print_lswitch(lswitch);
- }
- } else {
- NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
- print_lswitch(lswitch);
- }
- }
-}
-
-static void
-do_lswitch_add(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- struct nbrec_logical_switch *lswitch;
-
- lswitch = nbrec_logical_switch_insert(nb_ctx->txn);
- if (ctx->argc == 2) {
- nbrec_logical_switch_set_name(lswitch, ctx->argv[1]);
- }
-}
-
-static void
-do_lswitch_del(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_switch *lswitch;
-
- lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
- if (!lswitch) {
- return;
- }
-
- nbrec_logical_switch_delete(lswitch);
-}
-
-static void
-do_lswitch_list(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const struct nbrec_logical_switch *lswitch;
-
- NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
- printf(UUID_FMT " (%s)\n",
- UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
- }
-}
-
-static void
-do_lswitch_set_external_id(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_switch *lswitch;
- struct smap new_external_ids;
-
- lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
- if (!lswitch) {
- return;
- }
-
- smap_init(&new_external_ids);
- smap_clone(&new_external_ids, &lswitch->external_ids);
- if (ctx->argc == 4) {
- smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
- } else {
- smap_remove(&new_external_ids, ctx->argv[2]);
- }
- nbrec_logical_switch_set_external_ids(lswitch, &new_external_ids);
- smap_destroy(&new_external_ids);
-}
-
-static void
-do_lswitch_get_external_id(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_switch *lswitch;
-
- lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
- if (!lswitch) {
- return;
- }
-
- if (ctx->argc == 3) {
- const char *key = ctx->argv[2];
- const char *value;
-
- /* List one external ID */
-
- value = smap_get(&lswitch->external_ids, key);
- if (value) {
- printf("%s\n", value);
- }
- } else {
- struct smap_node *node;
-
- /* List all external IDs */
-
- SMAP_FOR_EACH(node, &lswitch->external_ids) {
- printf("%s=%s\n", node->key, node->value);
- }
- }
-}
-\f
-static const struct nbrec_logical_port *
-lport_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
-{
- const struct nbrec_logical_port *lport = NULL;
- bool is_uuid = false;
- struct uuid lport_uuid;
-
- if (uuid_from_string(&lport_uuid, id)) {
- is_uuid = true;
- lport = nbrec_logical_port_get_for_uuid(nb_ctx->idl, &lport_uuid);
- }
-
- if (!lport) {
- NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
- if (!strcmp(lport->name, id)) {
- break;
- }
- }
- }
-
- if (!lport) {
- VLOG_WARN("lport not found for %s: '%s'",
- is_uuid ? "UUID" : "name", id);
- }
-
- return lport;
-}
-
-static void
-do_lport_add(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- struct nbrec_logical_port *lport;
- const struct nbrec_logical_switch *lswitch;
- int64_t tag;
-
- lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
- if (!lswitch) {
- return;
- }
-
- if (ctx->argc != 3 && ctx->argc != 5) {
- /* If a parent_name is specified, a tag must be specified as well. */
- VLOG_WARN("Invalid arguments to lport-add.");
- return;
- }
-
- if (ctx->argc == 5) {
- /* Validate tag. */
- if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag) || tag < 0 || tag > 4095) {
- VLOG_WARN("Invalid tag '%s'", ctx->argv[4]);
- return;
- }
- }
-
- /* Create the logical port. */
- lport = nbrec_logical_port_insert(nb_ctx->txn);
- nbrec_logical_port_set_name(lport, ctx->argv[2]);
- if (ctx->argc == 5) {
- nbrec_logical_port_set_parent_name(lport, ctx->argv[3]);
- nbrec_logical_port_set_tag(lport, &tag, 1);
- }
-
- /* Insert the logical port into the logical switch. */
- nbrec_logical_switch_verify_ports(lswitch);
- struct nbrec_logical_port **new_ports = xmalloc(sizeof *new_ports *
- (lswitch->n_ports + 1));
- memcpy(new_ports, lswitch->ports, sizeof *new_ports * lswitch->n_ports);
- new_ports[lswitch->n_ports] = lport;
- nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports + 1);
- free(new_ports);
-}
-
-/* Removes lport 'lswitch->ports[idx]'. */
-static void
-remove_lport(const struct nbrec_logical_switch *lswitch, size_t idx)
-{
- const struct nbrec_logical_port *lport = lswitch->ports[idx];
-
- /* First remove 'lport' from the array of ports. This is what will
- * actually cause the logical port to be deleted when the transaction is
- * sent to the database server (due to garbage collection). */
- struct nbrec_logical_port **new_ports
- = xmemdup(lswitch->ports, sizeof *new_ports * lswitch->n_ports);
- new_ports[idx] = new_ports[lswitch->n_ports - 1];
- nbrec_logical_switch_verify_ports(lswitch);
- nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports - 1);
- free(new_ports);
-
- /* Delete 'lport' from the IDL. This won't have a real effect on the
- * database server (the IDL will suppress it in fact) but it means that it
- * won't show up when we iterate with NBREC_LOGICAL_PORT_FOR_EACH later. */
- nbrec_logical_port_delete(lport);
-}
-
-static void
-do_lport_del(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
- if (!lport) {
- return;
- }
-
- /* Find the switch that contains 'lport', then delete it. */
- const struct nbrec_logical_switch *lswitch;
- NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, nb_ctx->idl) {
- for (size_t i = 0; i < lswitch->n_ports; i++) {
- if (lswitch->ports[i] == lport) {
- remove_lport(lswitch, i);
- return;
- }
- }
- }
-
- VLOG_WARN("logical port %s is not part of any logical switch",
- ctx->argv[1]);
-}
-
-static void
-do_lport_list(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_switch *lswitch;
-
- lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
- if (!lswitch) {
- return;
- }
-
- for (size_t i = 0; i < lswitch->n_ports; i++) {
- const struct nbrec_logical_port *lport = lswitch->ports[i];
- printf(UUID_FMT " (%s)\n",
- UUID_ARGS(&lport->header_.uuid), lport->name);
- }
-}
-
-static void
-do_lport_get_parent(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
- if (!lport) {
- return;
- }
-
- if (lport->parent_name) {
- printf("%s\n", lport->parent_name);
- }
-}
-
-static void
-do_lport_get_tag(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
- if (!lport) {
- return;
- }
-
- if (lport->n_tag > 0) {
- printf("%"PRId64"\n", lport->tag[0]);
- }
-}
-
-static void
-do_lport_set_external_id(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
- struct smap new_external_ids;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- smap_init(&new_external_ids);
- smap_clone(&new_external_ids, &lport->external_ids);
- if (ctx->argc == 4) {
- smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
- } else {
- smap_remove(&new_external_ids, ctx->argv[2]);
- }
- nbrec_logical_port_set_external_ids(lport, &new_external_ids);
- smap_destroy(&new_external_ids);
-}
-
-static void
-do_lport_get_external_id(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- if (ctx->argc == 3) {
- const char *key = ctx->argv[2];
- const char *value;
-
- /* List one external ID */
-
- value = smap_get(&lport->external_ids, key);
- if (value) {
- printf("%s\n", value);
- }
- } else {
- struct smap_node *node;
-
- /* List all external IDs */
-
- SMAP_FOR_EACH(node, &lport->external_ids) {
- printf("%s=%s\n", node->key, node->value);
- }
- }
-}
-
-static void
-do_lport_set_macs(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- nbrec_logical_port_set_macs(lport,
- (const char **) ctx->argv + 2, ctx->argc - 2);
-}
-
-static void
-do_lport_get_macs(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
- size_t i;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- for (i = 0; i < lport->n_macs; i++) {
- printf("%s\n", lport->macs[i]);
- }
-}
-
-static void
-do_lport_set_port_security(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- nbrec_logical_port_set_port_security(lport,
- (const char **) ctx->argv + 2, ctx->argc - 2);
-}
-
-static void
-do_lport_get_port_security(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
- size_t i;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- for (i = 0; i < lport->n_port_security; i++) {
- printf("%s\n", lport->port_security[i]);
- }
-}
-
-static void
-do_lport_get_up(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- printf("%s\n", (lport->up && *lport->up) ? "up" : "down");
-}
-
-static void
-do_lport_set_enabled(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const char *state = ctx->argv[2];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- if (!strcasecmp(state, "enabled")) {
- bool enabled = true;
- nbrec_logical_port_set_enabled(lport, &enabled, 1);
- } else if (!strcasecmp(state, "disabled")) {
- bool enabled = false;
- nbrec_logical_port_set_enabled(lport, &enabled, 1);
- } else {
- VLOG_ERR("Invalid state '%s' provided to lport-set-enabled", state);
- }
-}
-
-static void
-do_lport_get_enabled(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- printf("%s\n",
- (!lport->enabled || *lport->enabled) ? "enabled" : "disabled");
-}
-
-static void
-do_lport_set_type(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const char *type = ctx->argv[2];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- nbrec_logical_port_set_type(lport, type);
-}
-
-static void
-do_lport_get_type(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- printf("%s\n", lport->type);
-}
-
-static void
-do_lport_set_options(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
- size_t i;
- struct smap options = SMAP_INITIALIZER(&options);
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- for (i = 2; i < ctx->argc; i++) {
- char *key, *value;
- value = xstrdup(ctx->argv[i]);
- key = strsep(&value, "=");
- if (value) {
- smap_add(&options, key, value);
- }
- free(key);
- }
-
- nbrec_logical_port_set_options(lport, &options);
-
- smap_destroy(&options);
-}
-
-static void
-do_lport_get_options(struct ovs_cmdl_context *ctx)
-{
- struct nbctl_context *nb_ctx = ctx->pvt;
- const char *id = ctx->argv[1];
- const struct nbrec_logical_port *lport;
- struct smap_node *node;
-
- lport = lport_by_name_or_uuid(nb_ctx, id);
- if (!lport) {
- return;
- }
-
- SMAP_FOR_EACH(node, &lport->options) {
- printf("%s=%s\n", node->key, node->value);
- }
-}
-\f
-static void
-parse_options(int argc, char *argv[])
-{
- enum {
- VLOG_OPTION_ENUMS,
- };
- static const struct option long_options[] = {
- {"db", required_argument, NULL, 'd'},
- {"help", no_argument, NULL, 'h'},
- {"options", no_argument, NULL, 'o'},
- {"version", no_argument, NULL, 'V'},
- VLOG_LONG_OPTIONS,
- STREAM_SSL_LONG_OPTIONS,
- {NULL, 0, NULL, 0},
- };
- char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
-
- for (;;) {
- int c;
-
- c = getopt_long(argc, argv, short_options, long_options, NULL);
- if (c == -1) {
- break;
- }
-
- switch (c) {
- VLOG_OPTION_HANDLERS;
- STREAM_SSL_OPTION_HANDLERS;
-
- case 'd':
- db = optarg;
- break;
-
- case 'h':
- usage();
- exit(EXIT_SUCCESS);
-
- case 'o':
- ovs_cmdl_print_options(long_options);
- exit(EXIT_SUCCESS);
-
- case 'V':
- ovs_print_version(0, 0);
- exit(EXIT_SUCCESS);
-
- default:
- break;
- }
- }
-
- if (!db) {
- db = default_db();
- }
-
- free(short_options);
-}
-
-static const struct ovs_cmdl_command all_commands[] = {
- {
- .name = "show",
- .usage = "[LSWITCH]",
- .min_args = 0,
- .max_args = 1,
- .handler = do_show,
- },
- {
- .name = "lswitch-add",
- .usage = "[LSWITCH]",
- .min_args = 0,
- .max_args = 1,
- .handler = do_lswitch_add,
- },
- {
- .name = "lswitch-del",
- .usage = "LSWITCH",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lswitch_del,
- },
- {
- .name = "lswitch-list",
- .usage = "",
- .min_args = 0,
- .max_args = 0,
- .handler = do_lswitch_list,
- },
- {
- .name = "lswitch-set-external-id",
- .usage = "LSWITCH KEY [VALUE]",
- .min_args = 2,
- .max_args = 3,
- .handler = do_lswitch_set_external_id,
- },
- {
- .name = "lswitch-get-external-id",
- .usage = "LSWITCH [KEY]",
- .min_args = 1,
- .max_args = 2,
- .handler = do_lswitch_get_external_id,
- },
- {
- .name = "lport-add",
- .usage = "LSWITCH LPORT [PARENT] [TAG]",
- .min_args = 2,
- .max_args = 4,
- .handler = do_lport_add,
- },
- {
- .name = "lport-del",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_del,
- },
- {
- .name = "lport-list",
- .usage = "LSWITCH",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_list,
- },
- {
- .name = "lport-get-parent",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_parent,
- },
- {
- .name = "lport-get-tag",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_tag,
- },
- {
- .name = "lport-set-external-id",
- .usage = "LPORT KEY [VALUE]",
- .min_args = 2,
- .max_args = 3,
- .handler = do_lport_set_external_id,
- },
- {
- .name = "lport-get-external-id",
- .usage = "LPORT [KEY]",
- .min_args = 1,
- .max_args = 2,
- .handler = do_lport_get_external_id,
- },
- {
- .name = "lport-set-macs",
- .usage = "LPORT [MAC]...",
- .min_args = 1,
- /* Accept however many arguments the system will allow. */
- .max_args = INT_MAX,
- .handler = do_lport_set_macs,
- },
- {
- .name = "lport-get-macs",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_macs,
- },
- {
- .name = "lport-set-port-security",
- .usage = "LPORT [ADDRS]...",
- .min_args = 0,
- /* Accept however many arguments the system will allow. */
- .max_args = INT_MAX,
- .handler = do_lport_set_port_security,
- },
- {
- .name = "lport-get-port-security",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_port_security,
- },
- {
- .name = "lport-get-up",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_up,
- },
- {
- .name = "lport-set-enabled",
- .usage = "LPORT STATE",
- .min_args = 2,
- .max_args = 2,
- .handler = do_lport_set_enabled,
- },
- {
- .name = "lport-get-enabled",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_enabled,
- },
- {
- .name = "lport-set-type",
- .usage = "LPORT TYPE",
- .min_args = 2,
- .max_args = 2,
- .handler = do_lport_set_type,
- },
- {
- .name = "lport-get-type",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_type,
- },
- {
- .name = "lport-set-options",
- .usage = "LPORT KEY=VALUE [KEY=VALUE]...",
- .min_args = 1,
- .max_args = INT_MAX,
- .handler = do_lport_set_options
- },
- {
- .name = "lport-get-options",
- .usage = "LPORT",
- .min_args = 1,
- .max_args = 1,
- .handler = do_lport_get_options,
- },
-
- {
- /* sentinel */
- .name = NULL,
- },
-};
-
-static const struct ovs_cmdl_command *
-get_all_commands(void)
-{
- return all_commands;
-}
-
-static const char *
-default_db(void)
-{
- static char *def;
- if (!def) {
- def = getenv("OVN_NB_DB");
- if (!def) {
- def = xasprintf("unix:%s/db.sock", ovs_rundir());
- }
- }
- return def;
-}
-
-int
-main(int argc, char *argv[])
-{
- extern struct vlog_module VLM_reconnect;
- struct ovs_cmdl_context ctx;
- struct nbctl_context nb_ctx = { .idl = NULL, };
- enum ovsdb_idl_txn_status txn_status;
- unsigned int seqno;
- int res = 0;
- char *args;
-
- fatal_ignore_sigpipe();
- set_program_name(argv[0]);
- vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
- vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
- parse_options(argc, argv);
- nbrec_init();
-
- args = process_escape_args(argv);
-
- nb_ctx.idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
- ctx.pvt = &nb_ctx;
- ctx.argc = argc - optind;
- ctx.argv = argv + optind;
-
- seqno = ovsdb_idl_get_seqno(nb_ctx.idl);
- for (;;) {
- ovsdb_idl_run(nb_ctx.idl);
-
- if (!ovsdb_idl_is_alive(nb_ctx.idl)) {
- int retval = ovsdb_idl_get_last_error(nb_ctx.idl);
- VLOG_ERR("%s: database connection failed (%s)",
- db, ovs_retval_to_string(retval));
- res = 1;
- break;
- }
-
- if (seqno != ovsdb_idl_get_seqno(nb_ctx.idl)) {
- nb_ctx.txn = ovsdb_idl_txn_create(nb_ctx.idl);
- ovsdb_idl_txn_add_comment(nb_ctx.txn, "ovn-nbctl: %s", args);
- ovs_cmdl_run_command(&ctx, get_all_commands());
- txn_status = ovsdb_idl_txn_commit_block(nb_ctx.txn);
- if (txn_status == TXN_TRY_AGAIN) {
- ovsdb_idl_txn_destroy(nb_ctx.txn);
- nb_ctx.txn = NULL;
- continue;
- } else {
- break;
- }
- }
-
- if (seqno == ovsdb_idl_get_seqno(nb_ctx.idl)) {
- ovsdb_idl_wait(nb_ctx.idl);
- poll_block();
- }
- }
-
- if (nb_ctx.txn) {
- ovsdb_idl_txn_destroy(nb_ctx.txn);
- }
- ovsdb_idl_destroy(nb_ctx.idl);
- free(args);
-
- exit(res);
-}
/ovn-ctl.8
+/ovn-nbctl
+/ovn-nbctl.8
ovn/utilities/ovn-ctl
man_MANS += \
- ovn/utilities/ovn-ctl.8
+ ovn/utilities/ovn-ctl.8 \
+ ovn/utilities/ovn-nbctl.8
EXTRA_DIST += \
ovn/utilities/ovn-ctl \
- ovn/utilities/ovn-ctl.8.xml
+ ovn/utilities/ovn-ctl.8.xml \
+ ovn/utilities/ovn-nbctl.8.xml
DISTCLEANFILES += \
- ovn/utilities/ovn-ctl.8
+ ovn/utilities/ovn-ctl.8 \
+ ovn/utilities/ovn-nbctl.8
+
+# ovn-nbctl
+bin_PROGRAMS += ovn/utilities/ovn-nbctl
+ovn_utilities_ovn_nbctl_SOURCES = ovn/utilities/ovn-nbctl.c
+ovn_utilities_ovn_nbctl_LDADD = ovn/lib/libovn.la ovsdb/libovsdb.la lib/libopenvswitch.la
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manpage program="ovn-nbctl" section="8" title="ovn-nbctl">
+ <h1>Name</h1>
+ <p>ovn-nbctl -- Open Virtual Network northbound db management utility</p>
+
+ <h1>Synopsys</h1>
+ <p><code>ovn-nbctl</code> [<var>options</var>] <var>command</var> [<var>arg</var>...]</p>
+
+ <h1>Description</h1>
+ <p>This utility can be used to manage the OVN northbound database.</p>
+
+ <h1>General Commands</h1>
+
+ <dl>
+ <dt><code>show [<var>lswitch</var>]</code></dt>
+ <dd>
+ Prints a brief overview of the database contents. If
+ <var>lswitch</var> is provided, only records related to that
+ logical switch are shown.
+ </dd>
+ </dl>
+
+ <h1>Logical Switch Commands</h1>
+
+ <dl>
+ <dt><code>lswitch-add</code> [<var>lswitch</var>]</dt> <dd> Creates a new logical switch named <var>lswitch</var>. If
+ <var>lswitch</var> is not provided, the switch will not have a
+ name so other commands must refer to this switch by its UUID.
+ Initially the switch will have no ports.
+ </dd>
+
+ <dt><code>lswitch-del</code> <var>lswitch</var></dt>
+ <dd>
+ Deletes <var>lswitch</var>.
+ </dd>
+
+ <dt><code>lswitch-list</code></dt>
+ <dd>
+ Lists all existing switches on standard output, one per line.
+ </dd>
+
+ <dt><code>lswitch-set-external-id</code> <var>lswitch</var> <var>key</var> [<var>value</var>]</dt>
+ <dd>
+ <p>Sets or clears an ``external ID'' value on <var>lswitch</var>.
+ These values are intended to identify entities external to OVN
+ with which <var>lswitch</var> is associated. The OVN Northbound
+ database schema may specify well-known <var>key</var> values,
+ but <var>key</var> and <var>value</var> are otherwise arbitrary
+ strings.</p>
+
+ <p>If <var>value</var> is specified, then <var>key</var> is set to
+ <var>value</var> for <var>lswitch</var>, overwriting any
+ previous value. If <var>value</var> is omitted, then
+ <var>key</var> is removed from <var>lswitch</var>'s set of
+ external IDs (if it was present.</p>
+ </dd>
+
+ <dt><code>lswitch-get-external-id</code> <var>lswitch</var> [<var>key</var>]</dt>
+ <dd>
+ Queries the external IDs on <var>lswitch</var>. If
+ <var>key</var> is specified, the output is the value for that
+ <var>key</var> or the empty string if <var>key</var> is unset.
+ If <var>key</var> is omitted, the output is
+ <var>key</var><code>=</code><var>value</var>, one per line, for
+ each key-value pair.
+ </dd>
+ </dl>
+
+ <h1>Logical Port Commands</h1>
+ <dl>
+ <dt><code>lport-add</code> <var>lswitch</var> <var>lport</var></dt>
+ <dd>
+ Creates on <var>lswitch</var> a new logical port named
+ <var>lport</var>.
+ </dd>
+
+ <dt><code>lport-add</code> <var>lswitch</var> <var>lport</var> <var>parent</var> <var>tag</var></dt>
+ <dd>
+ Creates on <var>lswitch</var> a logical port named <var>lport</var>
+ that is a child of <var>parent</var> that is identied with
+ <var>tag</var>. This is useful in cases such as virtualized
+ container environments where Open vSwitch does not have a direct
+ connection to the container's port and it must be shared with
+ the virtual machine's port.
+ </dd>
+
+ <dt><code>lport-del</code> <var>lport</var></dt>
+ <dd>
+ Deletes <var>lport</var>.
+ </dd>
+
+ <dt><code>lport-list</code> <var>lswitch</var></dt>
+ <dd>
+ Lists all the logical ports within <var>lswitch</var> on
+ standard output, one per line.
+ </dd>
+
+ <dt><code>lport-get-parent</code> <var>lport</var></dt>
+ <dd>
+ If set, get the parent port of <var>lport</var>. If not set, print
+ nothing.
+ </dd>
+
+ <dt><code>lport-get-tag</code> <var>lport</var></dt>
+ <dd>
+ If set, get the tag for <var>lport</var> traffic. If not set, print
+ nothing.
+ </dd>
+
+ <dt><code>lport-set-external-id</code> <var>lport</var> <var>key</var> [<var>value</var>]</dt>
+ <dd>
+ <p>Sets or clears an ``external ID'' value on <var>lport</var>.
+ These values are intended to identify entities external to OVN
+ with which <var>lport</var> is associated. The OVN Northbound
+ database schema may specify well-known <var>key</var> values,
+ but <var>key</var> and <var>value</var> are otherwise arbitrary
+ strings.</p>
+
+ <p>If <var>value</var> is specified, then <var>key</var> is set to
+ <var>value</var> for <var>lport</var>, overwriting any
+ previous value. If <var>value</var> is omitted, then
+ <var>key</var> is removed from <var>lport</var>'s set of
+ external IDs (if it was present.</p>
+ </dd>
+
+ <dt><code>lport-get-external-id</code> <var>lport</var> [<var>key</var>]</dt>
+ <dd>
+ Queries the external IDs on <var>lport</var>. If
+ <var>key</var> is specified, the output is the value for that
+ <var>key</var> or the empty string if <var>key</var> is unset.
+ If <var>key</var> is omitted, the output is
+ <var>key</var><code>=</code><var>value</var>, one per line, for
+ each key-value pair.
+ </dd>
+
+ <dt><code>lport-set-macs</code> <var>lport</var> [<var>mac</var>]...</dt>
+ <dd>
+ Sets the MACs associated with <var>lport</var> to
+ <var>mac</var>. Multiple MACs may be sets by using multiple
+ <var>mac</var> arguments. If no <var>mac</var> argument is
+ given, <var>lport</var> will have no MACs associated with it.
+ </dd>
+
+ <dt><code>lport-get-macs</code> <var>lport</var></dt>
+ <dd>
+ Lists all the MACs associated with <var>lport</var> on standard
+ output, one per line.
+ </dd>
+
+ <dt><code>lport-set-port-security</code> <var>lport</var> [<var>addrs</var>]...</dt>
+ <dd>
+ <p>
+ Sets the port security addresses associated with <var>lport</var> to
+ <var>addrs</var>. Multiple sets of addresses may be set by using
+ multiple <var>addrs</var> arguments. If no <var>addrs</var> argument
+ is given, <var>lport</var> will not have port security enabled.
+ </p>
+
+ <p>
+ Port security limits the addresses from which a logical port may send
+ packets and to which it may receive packets. See the
+ <code>ovn-nb</code>(5) documentation for the <ref
+ column="port_security" table="Logical_Port"/> column in the <ref
+ table="Logical_Port"/> table for details.
+ </p>
+ </dd>
+
+ <dt><code>lport-get-port-security</code> <var>lport</var></dt>
+ <dd>
+ Lists all the port security addresses associated with <var>lport</var>
+ on standard output, one per line.
+ </dd>
+
+ <dt><code>lport-get-up</code> <var>lport</var></dt>
+ <dd>
+ Prints the state of <var>lport</var>, either <code>up</code> or
+ <code>down</code>.
+ </dd>
+
+ <dt><code>lport-set-enabled</code> <var>lport</var> <var>state</var></dt>
+ <dd>
+ Set the administrative state of <var>lport</var>, either <code>enabled</code>
+ or <code>disabled</code>. When a port is disabled, no traffic is allowed into
+ or out of the port.
+ </dd>
+
+ <dt><code>lport-get-enabled</code> <var>lport</var></dt>
+ <dd>
+ Prints the administrative state of <var>lport</var>, either <code>enabled</code>
+ or <code>disabled</code>.
+ </dd>
+
+ <dt><code>lport-set-type</code> <var>lport</var> <var>type</var></dt>
+ <dd>
+ Set the type for the logical port. No special types have been implemented yet.
+ </dd>
+
+ <dt><code>lport-get-type</code> <var>lport</var></dt>
+ <dd>
+ Get the type for the logical port.
+ </dd>
+
+ <dt><code>lport-set-options</code> <var>lport</var> [<var>key=value</var>]...</dt>
+ <dd>
+ Set type-specific key-value options for the logical port.
+ </dd>
+
+ <dt><code>lport-get-options</code> <var>lport</var></dt>
+ <dd>
+ Get the type-specific options for the logical port.
+ </dd>
+
+ </dl>
+
+ <h1>Options</h1>
+
+ <dl>
+ <dt><code>-d</code> <var>database</var></dt>
+ <dt><code>--db</code> <var>database</var></dt>
+ <dd>
+ The OVSDB database remote to contact. If the <env>OVN_NB_DB</env>
+ environment variable is set, its value is used as the default.
+ Otherwise, the default is <code>unix:@RUNDIR@/db.sock</code>, but this
+ default is unlikely to be useful outside of single-machine OVN test
+ environments.
+ </dd>
+
+ <dt><code>-h</code> | <code>--help</code></dt>
+ <dt><code>-o</code> | <code>--options</code></dt>
+ <dt><code>-V</code> | <code>--version</code></dt>
+ </dl>
+
+ <h1>Logging options</h1>
+ <dl>
+ <dt><code>-v</code><var>spec</var>, <code>--verbose=</code><var>spec</var></dt>
+ <dt><code>-v</code>, <code>--verbose</code></dt>
+ <dt><code>--log-file</code>[<code>=</code><var>file</var>]</dt>
+ <dt><code>--syslog-target=</code><var>host</var><code>:</code><var>port</var></dt>
+ </dl>
+
+ <h1>PKI configuration (required to use SSL)</h1>
+ <dl>
+ <dt><code>-p</code>, <code>--private-key=</code><var>file</var> file with private key</dt>
+ <dt><code>-c</code>, <code>--certificate=</code><var>file</var> file with certificate for private key</dt>
+ <dt><code>-C</code>, <code>--ca-cert=</code><var>file</var> file with peer CA certificate</dt>
+ </dl>
+
+</manpage>
--- /dev/null
+/*
+ * 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 <config.h>
+
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "command-line.h"
+#include "dirs.h"
+#include "fatal-signal.h"
+#include "ovn/lib/ovn-nb-idl.h"
+#include "poll-loop.h"
+#include "process.h"
+#include "stream.h"
+#include "stream-ssl.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(ovn_nbctl);
+
+struct nbctl_context {
+ struct ovsdb_idl *idl;
+ struct ovsdb_idl_txn *txn;
+};
+
+static const char *db;
+
+static const char *default_db(void);
+
+static void
+usage(void)
+{
+ printf("\
+%s: OVN northbound DB management utility\n\
+usage: %s [OPTIONS] COMMAND [ARG...]\n\
+\n\
+General commands:\n\
+ show print overview of database contents\n\
+ show LSWITCH print overview of database contents for LSWITCH\n\
+\n\
+Logical switch commands:\n\
+ lswitch-add [LSWITCH] create a logical switch named LSWITCH\n\
+ lswitch-del LSWITCH delete LSWITCH and all its ports\n\
+ lswitch-list print the names of all logical switches\n\
+ lswitch-set-external-id LSWITCH KEY [VALUE]\n\
+ set or delete an external-id on LSWITCH\n\
+ lswitch-get-external-id LSWITCH [KEY]\n\
+ list one or all external-ids on LSWITCH\n\
+\n\
+Logical port commands:\n\
+ lport-add LSWITCH LPORT add logical port LPORT on LSWITCH\n\
+ lport-add LSWITCH LPORT PARENT TAG\n\
+ add logical port LPORT on LSWITCH with PARENT\n\
+ on TAG\n\
+ lport-del LPORT delete LPORT from its attached switch\n\
+ lport-list LSWITCH print the names of all logical ports on LSWITCH\n\
+ lport-get-parent LPORT get the parent of LPORT if set\n\
+ lport-get-tag LPORT get the LPORT's tag if set\n\
+ lport-set-external-id LPORT KEY [VALUE]\n\
+ set or delete an external-id on LPORT\n\
+ lport-get-external-id LPORT [KEY]\n\
+ list one or all external-ids on LPORT\n\
+ lport-set-macs LPORT [MAC]...\n\
+ set MAC addresses for LPORT.\n\
+ lport-get-macs LPORT get a list of MAC addresses on LPORT\n\
+ lport-set-port-security LPORT [ADDRS]...\n\
+ set port security addresses for LPORT.\n\
+ lport-get-port-security LPORT get LPORT's port security addresses\n\
+ lport-get-up LPORT get state of LPORT ('up' or 'down')\n\
+ lport-set-enabled LPORT STATE\n\
+ set administrative state LPORT\n\
+ ('enabled' or 'disabled')\n\
+ lport-get-enabled LPORT get administrative state LPORT\n\
+ ('enabled' or 'disabled')\n\
+ lport-set-type LPORT TYPE Set the type for LPORT\n\
+ lport-get-type LPORT Get the type for LPORT\n\
+ lport-set-options LPORT KEY=VALUE [KEY=VALUE]...\n\
+ Set options related to the type of LPORT\n\
+ lport-get-options LPORT Get the type specific options for LPORT\n\
+\n\
+Options:\n\
+ --db=DATABASE connect to DATABASE\n\
+ (default: %s)\n\
+ -h, --help display this help message\n\
+ -o, --options list available options\n\
+ -V, --version display version information\n\
+", program_name, program_name, default_db());
+ vlog_usage();
+ stream_usage("database", true, true, false);
+}
+\f
+static const struct nbrec_logical_switch *
+lswitch_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
+{
+ const struct nbrec_logical_switch *lswitch = NULL;
+ bool is_uuid = false;
+ bool duplicate = false;
+ struct uuid lswitch_uuid;
+
+ if (uuid_from_string(&lswitch_uuid, id)) {
+ is_uuid = true;
+ lswitch = nbrec_logical_switch_get_for_uuid(nb_ctx->idl,
+ &lswitch_uuid);
+ }
+
+ if (!lswitch) {
+ const struct nbrec_logical_switch *iter;
+
+ NBREC_LOGICAL_SWITCH_FOR_EACH(iter, nb_ctx->idl) {
+ if (strcmp(iter->name, id)) {
+ continue;
+ }
+ if (lswitch) {
+ VLOG_WARN("There is more than one logical switch named '%s'. "
+ "Use a UUID.", id);
+ lswitch = NULL;
+ duplicate = true;
+ break;
+ }
+ lswitch = iter;
+ }
+ }
+
+ if (!lswitch && !duplicate) {
+ VLOG_WARN("lswitch not found for %s: '%s'",
+ is_uuid ? "UUID" : "name", id);
+ }
+
+ return lswitch;
+}
+
+static void
+print_lswitch(const struct nbrec_logical_switch *lswitch)
+{
+ printf(" lswitch "UUID_FMT" (%s)\n",
+ UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
+
+ for (size_t i = 0; i < lswitch->n_ports; i++) {
+ const struct nbrec_logical_port *lport = lswitch->ports[i];
+
+ printf(" lport %s\n", lport->name);
+ if (lport->parent_name && lport->n_tag) {
+ printf(" parent: %s, tag:%"PRIu64"\n",
+ lport->parent_name, lport->tag[0]);
+ }
+ if (lport->n_macs) {
+ printf(" macs:");
+ for (size_t j = 0; j < lport->n_macs; j++) {
+ printf(" %s", lport->macs[j]);
+ }
+ printf("\n");
+ }
+ }
+}
+
+static void
+do_show(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const struct nbrec_logical_switch *lswitch;
+
+ if (ctx->argc == 2) {
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+ if (lswitch) {
+ print_lswitch(lswitch);
+ }
+ } else {
+ NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
+ print_lswitch(lswitch);
+ }
+ }
+}
+
+static void
+do_lswitch_add(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ struct nbrec_logical_switch *lswitch;
+
+ lswitch = nbrec_logical_switch_insert(nb_ctx->txn);
+ if (ctx->argc == 2) {
+ nbrec_logical_switch_set_name(lswitch, ctx->argv[1]);
+ }
+}
+
+static void
+do_lswitch_del(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_switch *lswitch;
+
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
+ if (!lswitch) {
+ return;
+ }
+
+ nbrec_logical_switch_delete(lswitch);
+}
+
+static void
+do_lswitch_list(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const struct nbrec_logical_switch *lswitch;
+
+ NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
+ printf(UUID_FMT " (%s)\n",
+ UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
+ }
+}
+
+static void
+do_lswitch_set_external_id(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_switch *lswitch;
+ struct smap new_external_ids;
+
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
+ if (!lswitch) {
+ return;
+ }
+
+ smap_init(&new_external_ids);
+ smap_clone(&new_external_ids, &lswitch->external_ids);
+ if (ctx->argc == 4) {
+ smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
+ } else {
+ smap_remove(&new_external_ids, ctx->argv[2]);
+ }
+ nbrec_logical_switch_set_external_ids(lswitch, &new_external_ids);
+ smap_destroy(&new_external_ids);
+}
+
+static void
+do_lswitch_get_external_id(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_switch *lswitch;
+
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
+ if (!lswitch) {
+ return;
+ }
+
+ if (ctx->argc == 3) {
+ const char *key = ctx->argv[2];
+ const char *value;
+
+ /* List one external ID */
+
+ value = smap_get(&lswitch->external_ids, key);
+ if (value) {
+ printf("%s\n", value);
+ }
+ } else {
+ struct smap_node *node;
+
+ /* List all external IDs */
+
+ SMAP_FOR_EACH(node, &lswitch->external_ids) {
+ printf("%s=%s\n", node->key, node->value);
+ }
+ }
+}
+\f
+static const struct nbrec_logical_port *
+lport_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
+{
+ const struct nbrec_logical_port *lport = NULL;
+ bool is_uuid = false;
+ struct uuid lport_uuid;
+
+ if (uuid_from_string(&lport_uuid, id)) {
+ is_uuid = true;
+ lport = nbrec_logical_port_get_for_uuid(nb_ctx->idl, &lport_uuid);
+ }
+
+ if (!lport) {
+ NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
+ if (!strcmp(lport->name, id)) {
+ break;
+ }
+ }
+ }
+
+ if (!lport) {
+ VLOG_WARN("lport not found for %s: '%s'",
+ is_uuid ? "UUID" : "name", id);
+ }
+
+ return lport;
+}
+
+static void
+do_lport_add(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ struct nbrec_logical_port *lport;
+ const struct nbrec_logical_switch *lswitch;
+ int64_t tag;
+
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+ if (!lswitch) {
+ return;
+ }
+
+ if (ctx->argc != 3 && ctx->argc != 5) {
+ /* If a parent_name is specified, a tag must be specified as well. */
+ VLOG_WARN("Invalid arguments to lport-add.");
+ return;
+ }
+
+ if (ctx->argc == 5) {
+ /* Validate tag. */
+ if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag) || tag < 0 || tag > 4095) {
+ VLOG_WARN("Invalid tag '%s'", ctx->argv[4]);
+ return;
+ }
+ }
+
+ /* Create the logical port. */
+ lport = nbrec_logical_port_insert(nb_ctx->txn);
+ nbrec_logical_port_set_name(lport, ctx->argv[2]);
+ if (ctx->argc == 5) {
+ nbrec_logical_port_set_parent_name(lport, ctx->argv[3]);
+ nbrec_logical_port_set_tag(lport, &tag, 1);
+ }
+
+ /* Insert the logical port into the logical switch. */
+ nbrec_logical_switch_verify_ports(lswitch);
+ struct nbrec_logical_port **new_ports = xmalloc(sizeof *new_ports *
+ (lswitch->n_ports + 1));
+ memcpy(new_ports, lswitch->ports, sizeof *new_ports * lswitch->n_ports);
+ new_ports[lswitch->n_ports] = lport;
+ nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports + 1);
+ free(new_ports);
+}
+
+/* Removes lport 'lswitch->ports[idx]'. */
+static void
+remove_lport(const struct nbrec_logical_switch *lswitch, size_t idx)
+{
+ const struct nbrec_logical_port *lport = lswitch->ports[idx];
+
+ /* First remove 'lport' from the array of ports. This is what will
+ * actually cause the logical port to be deleted when the transaction is
+ * sent to the database server (due to garbage collection). */
+ struct nbrec_logical_port **new_ports
+ = xmemdup(lswitch->ports, sizeof *new_ports * lswitch->n_ports);
+ new_ports[idx] = new_ports[lswitch->n_ports - 1];
+ nbrec_logical_switch_verify_ports(lswitch);
+ nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports - 1);
+ free(new_ports);
+
+ /* Delete 'lport' from the IDL. This won't have a real effect on the
+ * database server (the IDL will suppress it in fact) but it means that it
+ * won't show up when we iterate with NBREC_LOGICAL_PORT_FOR_EACH later. */
+ nbrec_logical_port_delete(lport);
+}
+
+static void
+do_lport_del(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+ if (!lport) {
+ return;
+ }
+
+ /* Find the switch that contains 'lport', then delete it. */
+ const struct nbrec_logical_switch *lswitch;
+ NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, nb_ctx->idl) {
+ for (size_t i = 0; i < lswitch->n_ports; i++) {
+ if (lswitch->ports[i] == lport) {
+ remove_lport(lswitch, i);
+ return;
+ }
+ }
+ }
+
+ VLOG_WARN("logical port %s is not part of any logical switch",
+ ctx->argv[1]);
+}
+
+static void
+do_lport_list(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_switch *lswitch;
+
+ lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
+ if (!lswitch) {
+ return;
+ }
+
+ for (size_t i = 0; i < lswitch->n_ports; i++) {
+ const struct nbrec_logical_port *lport = lswitch->ports[i];
+ printf(UUID_FMT " (%s)\n",
+ UUID_ARGS(&lport->header_.uuid), lport->name);
+ }
+}
+
+static void
+do_lport_get_parent(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+ if (!lport) {
+ return;
+ }
+
+ if (lport->parent_name) {
+ printf("%s\n", lport->parent_name);
+ }
+}
+
+static void
+do_lport_get_tag(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+ if (!lport) {
+ return;
+ }
+
+ if (lport->n_tag > 0) {
+ printf("%"PRId64"\n", lport->tag[0]);
+ }
+}
+
+static void
+do_lport_set_external_id(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+ struct smap new_external_ids;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ smap_init(&new_external_ids);
+ smap_clone(&new_external_ids, &lport->external_ids);
+ if (ctx->argc == 4) {
+ smap_replace(&new_external_ids, ctx->argv[2], ctx->argv[3]);
+ } else {
+ smap_remove(&new_external_ids, ctx->argv[2]);
+ }
+ nbrec_logical_port_set_external_ids(lport, &new_external_ids);
+ smap_destroy(&new_external_ids);
+}
+
+static void
+do_lport_get_external_id(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ if (ctx->argc == 3) {
+ const char *key = ctx->argv[2];
+ const char *value;
+
+ /* List one external ID */
+
+ value = smap_get(&lport->external_ids, key);
+ if (value) {
+ printf("%s\n", value);
+ }
+ } else {
+ struct smap_node *node;
+
+ /* List all external IDs */
+
+ SMAP_FOR_EACH(node, &lport->external_ids) {
+ printf("%s=%s\n", node->key, node->value);
+ }
+ }
+}
+
+static void
+do_lport_set_macs(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ nbrec_logical_port_set_macs(lport,
+ (const char **) ctx->argv + 2, ctx->argc - 2);
+}
+
+static void
+do_lport_get_macs(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+ size_t i;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ for (i = 0; i < lport->n_macs; i++) {
+ printf("%s\n", lport->macs[i]);
+ }
+}
+
+static void
+do_lport_set_port_security(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ nbrec_logical_port_set_port_security(lport,
+ (const char **) ctx->argv + 2, ctx->argc - 2);
+}
+
+static void
+do_lport_get_port_security(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+ size_t i;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ for (i = 0; i < lport->n_port_security; i++) {
+ printf("%s\n", lport->port_security[i]);
+ }
+}
+
+static void
+do_lport_get_up(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ printf("%s\n", (lport->up && *lport->up) ? "up" : "down");
+}
+
+static void
+do_lport_set_enabled(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const char *state = ctx->argv[2];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ if (!strcasecmp(state, "enabled")) {
+ bool enabled = true;
+ nbrec_logical_port_set_enabled(lport, &enabled, 1);
+ } else if (!strcasecmp(state, "disabled")) {
+ bool enabled = false;
+ nbrec_logical_port_set_enabled(lport, &enabled, 1);
+ } else {
+ VLOG_ERR("Invalid state '%s' provided to lport-set-enabled", state);
+ }
+}
+
+static void
+do_lport_get_enabled(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ printf("%s\n",
+ (!lport->enabled || *lport->enabled) ? "enabled" : "disabled");
+}
+
+static void
+do_lport_set_type(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const char *type = ctx->argv[2];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ nbrec_logical_port_set_type(lport, type);
+}
+
+static void
+do_lport_get_type(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ printf("%s\n", lport->type);
+}
+
+static void
+do_lport_set_options(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+ size_t i;
+ struct smap options = SMAP_INITIALIZER(&options);
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ for (i = 2; i < ctx->argc; i++) {
+ char *key, *value;
+ value = xstrdup(ctx->argv[i]);
+ key = strsep(&value, "=");
+ if (value) {
+ smap_add(&options, key, value);
+ }
+ free(key);
+ }
+
+ nbrec_logical_port_set_options(lport, &options);
+
+ smap_destroy(&options);
+}
+
+static void
+do_lport_get_options(struct ovs_cmdl_context *ctx)
+{
+ struct nbctl_context *nb_ctx = ctx->pvt;
+ const char *id = ctx->argv[1];
+ const struct nbrec_logical_port *lport;
+ struct smap_node *node;
+
+ lport = lport_by_name_or_uuid(nb_ctx, id);
+ if (!lport) {
+ return;
+ }
+
+ SMAP_FOR_EACH(node, &lport->options) {
+ printf("%s=%s\n", node->key, node->value);
+ }
+}
+\f
+static void
+parse_options(int argc, char *argv[])
+{
+ enum {
+ VLOG_OPTION_ENUMS,
+ };
+ static const struct option long_options[] = {
+ {"db", required_argument, NULL, 'd'},
+ {"help", no_argument, NULL, 'h'},
+ {"options", no_argument, NULL, 'o'},
+ {"version", no_argument, NULL, 'V'},
+ VLOG_LONG_OPTIONS,
+ STREAM_SSL_LONG_OPTIONS,
+ {NULL, 0, NULL, 0},
+ };
+ char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
+
+ for (;;) {
+ int c;
+
+ c = getopt_long(argc, argv, short_options, long_options, NULL);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ VLOG_OPTION_HANDLERS;
+ STREAM_SSL_OPTION_HANDLERS;
+
+ case 'd':
+ db = optarg;
+ break;
+
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+
+ case 'o':
+ ovs_cmdl_print_options(long_options);
+ exit(EXIT_SUCCESS);
+
+ case 'V':
+ ovs_print_version(0, 0);
+ exit(EXIT_SUCCESS);
+
+ default:
+ break;
+ }
+ }
+
+ if (!db) {
+ db = default_db();
+ }
+
+ free(short_options);
+}
+
+static const struct ovs_cmdl_command all_commands[] = {
+ {
+ .name = "show",
+ .usage = "[LSWITCH]",
+ .min_args = 0,
+ .max_args = 1,
+ .handler = do_show,
+ },
+ {
+ .name = "lswitch-add",
+ .usage = "[LSWITCH]",
+ .min_args = 0,
+ .max_args = 1,
+ .handler = do_lswitch_add,
+ },
+ {
+ .name = "lswitch-del",
+ .usage = "LSWITCH",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lswitch_del,
+ },
+ {
+ .name = "lswitch-list",
+ .usage = "",
+ .min_args = 0,
+ .max_args = 0,
+ .handler = do_lswitch_list,
+ },
+ {
+ .name = "lswitch-set-external-id",
+ .usage = "LSWITCH KEY [VALUE]",
+ .min_args = 2,
+ .max_args = 3,
+ .handler = do_lswitch_set_external_id,
+ },
+ {
+ .name = "lswitch-get-external-id",
+ .usage = "LSWITCH [KEY]",
+ .min_args = 1,
+ .max_args = 2,
+ .handler = do_lswitch_get_external_id,
+ },
+ {
+ .name = "lport-add",
+ .usage = "LSWITCH LPORT [PARENT] [TAG]",
+ .min_args = 2,
+ .max_args = 4,
+ .handler = do_lport_add,
+ },
+ {
+ .name = "lport-del",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_del,
+ },
+ {
+ .name = "lport-list",
+ .usage = "LSWITCH",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_list,
+ },
+ {
+ .name = "lport-get-parent",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_parent,
+ },
+ {
+ .name = "lport-get-tag",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_tag,
+ },
+ {
+ .name = "lport-set-external-id",
+ .usage = "LPORT KEY [VALUE]",
+ .min_args = 2,
+ .max_args = 3,
+ .handler = do_lport_set_external_id,
+ },
+ {
+ .name = "lport-get-external-id",
+ .usage = "LPORT [KEY]",
+ .min_args = 1,
+ .max_args = 2,
+ .handler = do_lport_get_external_id,
+ },
+ {
+ .name = "lport-set-macs",
+ .usage = "LPORT [MAC]...",
+ .min_args = 1,
+ /* Accept however many arguments the system will allow. */
+ .max_args = INT_MAX,
+ .handler = do_lport_set_macs,
+ },
+ {
+ .name = "lport-get-macs",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_macs,
+ },
+ {
+ .name = "lport-set-port-security",
+ .usage = "LPORT [ADDRS]...",
+ .min_args = 0,
+ /* Accept however many arguments the system will allow. */
+ .max_args = INT_MAX,
+ .handler = do_lport_set_port_security,
+ },
+ {
+ .name = "lport-get-port-security",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_port_security,
+ },
+ {
+ .name = "lport-get-up",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_up,
+ },
+ {
+ .name = "lport-set-enabled",
+ .usage = "LPORT STATE",
+ .min_args = 2,
+ .max_args = 2,
+ .handler = do_lport_set_enabled,
+ },
+ {
+ .name = "lport-get-enabled",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_enabled,
+ },
+ {
+ .name = "lport-set-type",
+ .usage = "LPORT TYPE",
+ .min_args = 2,
+ .max_args = 2,
+ .handler = do_lport_set_type,
+ },
+ {
+ .name = "lport-get-type",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_type,
+ },
+ {
+ .name = "lport-set-options",
+ .usage = "LPORT KEY=VALUE [KEY=VALUE]...",
+ .min_args = 1,
+ .max_args = INT_MAX,
+ .handler = do_lport_set_options
+ },
+ {
+ .name = "lport-get-options",
+ .usage = "LPORT",
+ .min_args = 1,
+ .max_args = 1,
+ .handler = do_lport_get_options,
+ },
+
+ {
+ /* sentinel */
+ .name = NULL,
+ },
+};
+
+static const struct ovs_cmdl_command *
+get_all_commands(void)
+{
+ return all_commands;
+}
+
+static const char *
+default_db(void)
+{
+ static char *def;
+ if (!def) {
+ def = getenv("OVN_NB_DB");
+ if (!def) {
+ def = xasprintf("unix:%s/db.sock", ovs_rundir());
+ }
+ }
+ return def;
+}
+
+int
+main(int argc, char *argv[])
+{
+ extern struct vlog_module VLM_reconnect;
+ struct ovs_cmdl_context ctx;
+ struct nbctl_context nb_ctx = { .idl = NULL, };
+ enum ovsdb_idl_txn_status txn_status;
+ unsigned int seqno;
+ int res = 0;
+ char *args;
+
+ fatal_ignore_sigpipe();
+ set_program_name(argv[0]);
+ vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+ vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
+ parse_options(argc, argv);
+ nbrec_init();
+
+ args = process_escape_args(argv);
+
+ nb_ctx.idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
+ ctx.pvt = &nb_ctx;
+ ctx.argc = argc - optind;
+ ctx.argv = argv + optind;
+
+ seqno = ovsdb_idl_get_seqno(nb_ctx.idl);
+ for (;;) {
+ ovsdb_idl_run(nb_ctx.idl);
+
+ if (!ovsdb_idl_is_alive(nb_ctx.idl)) {
+ int retval = ovsdb_idl_get_last_error(nb_ctx.idl);
+ VLOG_ERR("%s: database connection failed (%s)",
+ db, ovs_retval_to_string(retval));
+ res = 1;
+ break;
+ }
+
+ if (seqno != ovsdb_idl_get_seqno(nb_ctx.idl)) {
+ nb_ctx.txn = ovsdb_idl_txn_create(nb_ctx.idl);
+ ovsdb_idl_txn_add_comment(nb_ctx.txn, "ovn-nbctl: %s", args);
+ ovs_cmdl_run_command(&ctx, get_all_commands());
+ txn_status = ovsdb_idl_txn_commit_block(nb_ctx.txn);
+ if (txn_status == TXN_TRY_AGAIN) {
+ ovsdb_idl_txn_destroy(nb_ctx.txn);
+ nb_ctx.txn = NULL;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (seqno == ovsdb_idl_get_seqno(nb_ctx.idl)) {
+ ovsdb_idl_wait(nb_ctx.idl);
+ poll_block();
+ }
+ }
+
+ if (nb_ctx.txn) {
+ ovsdb_idl_txn_destroy(nb_ctx.txn);
+ }
+ ovsdb_idl_destroy(nb_ctx.idl);
+ free(args);
+
+ exit(res);
+}
fi
PATH=$builddir/ovsdb:$builddir/vswitchd:$builddir/utilities:$PATH
if $ovn; then
- PATH=$builddir/ovn:$builddir/ovn/controller:$builddir/ovn/northd:$PATH
+ PATH=$builddir/ovn:$builddir/ovn/controller:$builddir/ovn/northd:$builddir/ovn/utilities:$PATH
fi
export PATH
else
# Put built tools early in $PATH.
PATH=$sim_builddir/ovsdb:$sim_builddir/vswitchd:$sim_builddir/utilities:$PATH
-PATH=$sim_builddir/ovn:$sim_srcdir/ovn:$sim_builddir/ovn/controller:$sim_builddir/ovn/northd:$PATH
+PATH=$sim_builddir/ovn:$sim_srcdir/ovn:$sim_builddir/ovn/controller:$sim_builddir/ovn/northd:$sim_builddir/ovn/utilities:$PATH
export PATH
rm -rf sandbox