#include "db-ctl-base.h"
#include "dirs.h"
#include "fatal-signal.h"
-#include "json.h"
+#include "openvswitch/json.h"
#include "ovn/lib/ovn-nb-idl.h"
#include "packets.h"
#include "poll-loop.h"
#include "process.h"
#include "smap.h"
+#include "sset.h"
#include "stream.h"
#include "stream-ssl.h"
#include "svec.h"
lr-list print the names of all logical routers\n\
\n\
Logical router port commands:\n\
- lrp-add ROUTER PORT MAC NETWORK [PEER]\n\
+ lrp-add ROUTER PORT MAC NETWORK... [peer=PEER]\n\
add logical port PORT on ROUTER\n\
lrp-del PORT delete PORT from its attached router\n\
lrp-list ROUTER print the names of all ports on ROUTER\n\
ds_put_format(s, " port %s\n", lrp->name);
if (lrp->mac) {
ds_put_cstr(s, " mac: ");
- ds_put_format(s, "\"%s\"", lrp->mac);
+ ds_put_format(s, "\"%s\"\n", lrp->mac);
+ }
+ if (lrp->n_networks) {
+ ds_put_cstr(s, " networks: [");
+ for (size_t j = 0; j < lrp->n_networks; j++) {
+ ds_put_format(s, "%s\"%s\"",
+ j == 0 ? "" : ", ",
+ lrp->networks[j]);
+ }
+ ds_put_cstr(s, "]\n");
}
- ds_put_format(s, "\n");
}
}
const char *lrp_name = ctx->argv[2];
const char *mac = ctx->argv[3];
- const char *network = ctx->argv[4];
- const char *peer = (ctx->argc == 6) ? ctx->argv[5] : NULL;
+ const char **networks = (const char **) &ctx->argv[4];
+
+ int n_networks = ctx->argc - 4;
+ for (int i = 4; i < ctx->argc; i++) {
+ if (strchr(ctx->argv[i], '=')) {
+ n_networks = i - 4;
+ break;
+ }
+ }
+
+ if (!n_networks) {
+ ctl_fatal("%s: router port requires specifying a network", lrp_name);
+ }
+
+ char **settings = (char **) &ctx->argv[n_networks + 4];
+ int n_settings = ctx->argc - 4 - n_networks;
const struct nbrec_logical_router_port *lrp;
lrp = lrp_by_name_or_uuid(ctx, lrp_name, false);
lrp->mac);
}
- if (strcmp(network, lrp->network)) {
- ctl_fatal("%s: port already exists with network %s", lrp_name,
- lrp->network);
+ struct sset new_networks = SSET_INITIALIZER(&new_networks);
+ for (int i = 0; i < n_networks; i++) {
+ sset_add(&new_networks, networks[i]);
+ }
+
+ struct sset orig_networks = SSET_INITIALIZER(&orig_networks);
+ sset_add_array(&orig_networks, lrp->networks, lrp->n_networks);
+
+ if (!sset_equals(&orig_networks, &new_networks)) {
+ ctl_fatal("%s: port already exists with different network",
+ lrp_name);
+ }
+
+ sset_destroy(&orig_networks);
+ sset_destroy(&new_networks);
+
+ /* Special-case sanity-check of peer ports. */
+ const char *peer = NULL;
+ for (int i = 0; i < n_settings; i++) {
+ if (!strncmp(settings[i], "peer=", 5)) {
+ peer = settings[i] + 5;
+ break;
+ }
}
if ((!peer != !lrp->peer) ||
struct eth_addr ea;
if (!ovs_scan(mac, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))) {
- ctl_fatal("%s: invalid mac address.", mac);
+ ctl_fatal("%s: invalid mac address %s", lrp_name, mac);
}
- ovs_be32 ipv4;
- unsigned int plen;
- char *error = ip_parse_cidr(network, &ipv4, &plen);
- if (error) {
- free(error);
- struct in6_addr ipv6;
- error = ipv6_parse_cidr(network, &ipv6, &plen);
+ for (int i = 0; i < n_networks; i++) {
+ ovs_be32 ipv4;
+ unsigned int plen;
+ char *error = ip_parse_cidr(networks[i], &ipv4, &plen);
if (error) {
free(error);
- ctl_fatal("%s: invalid network address.", network);
+ struct in6_addr ipv6;
+ error = ipv6_parse_cidr(networks[i], &ipv6, &plen);
+ if (error) {
+ free(error);
+ ctl_fatal("%s: invalid network address: %s", lrp_name,
+ networks[i]);
+ }
}
}
lrp = nbrec_logical_router_port_insert(ctx->txn);
nbrec_logical_router_port_set_name(lrp, lrp_name);
nbrec_logical_router_port_set_mac(lrp, mac);
- nbrec_logical_router_port_set_network(lrp, network);
- if (peer) {
- nbrec_logical_router_port_set_peer(lrp, peer);
+ nbrec_logical_router_port_set_networks(lrp, networks, n_networks);
+
+ for (int i = 0; i < n_settings; i++) {
+ ctl_set_column("Logical_Router_Port", &lrp->header_, settings[i],
+ ctx->symtab);
}
/* Insert the logical port into the logical router. */
{ "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO },
/* logical router port commands. */
- { "lrp-add", 4, 5, "ROUTER PORT MAC NETWORK [PEER]", NULL, nbctl_lrp_add,
- NULL, "--may-exist", RW },
- { "lrp-del", 1, 1, "LPORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
+ { "lrp-add", 4, INT_MAX,
+ "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...",
+ NULL, nbctl_lrp_add, NULL, "--may-exist", RW },
+ { "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
{ "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
{ "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,
NULL, "", RW },