json: Move from lib to include/openvswitch.
[cascardo/ovs.git] / ovn / utilities / ovn-nbctl.c
index 7789cdd..d523eec 100644 (file)
 #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"
@@ -235,7 +236,7 @@ parse_options(int argc, char *argv[], struct shash *local_options)
             }
             shash_add_nocopy(local_options,
                              xasprintf("--%s", options[idx].name),
-                             optarg ? xstrdup(optarg) : NULL);
+                             nullable_xstrdup(optarg));
             break;
 
         case 'h':
@@ -340,7 +341,7 @@ Logical router commands:\n\
   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\
@@ -459,9 +460,17 @@ print_lr(const struct nbrec_logical_router *lr, struct ds *s)
         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");
     }
 }
 
@@ -1383,6 +1392,10 @@ nbctl_lr_route_add(struct ctl_context *ctx)
         nbrec_logical_router_static_route_verify_nexthop(route);
         nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
         nbrec_logical_router_static_route_set_nexthop(route, next_hop);
+        if (ctx->argc == 5) {
+            nbrec_logical_router_static_route_set_output_port(route,
+                                                              ctx->argv[4]);
+        }
         free(rt_prefix);
         free(next_hop);
         free(prefix);
@@ -1523,8 +1536,22 @@ nbctl_lrp_add(struct ctl_context *ctx)
 
     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);
@@ -1547,9 +1574,29 @@ nbctl_lrp_add(struct ctl_context *ctx)
                       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) ||
@@ -1563,19 +1610,22 @@ nbctl_lrp_add(struct ctl_context *ctx)
 
     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]);
+            }
         }
     }
 
@@ -1583,9 +1633,11 @@ nbctl_lrp_add(struct ctl_context *ctx)
     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. */
@@ -1795,7 +1847,8 @@ nbctl_lr_route_list(struct ctl_context *ctx)
             free(error);
 
             struct in6_addr ipv6;
-            if (!ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen)) {
+            error = ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen);
+            if (!error) {
                 ipv6_routes[n_ipv6_routes].plen = plen;
                 ipv6_routes[n_ipv6_routes].addr = ipv6;
                 ipv6_routes[n_ipv6_routes].route = route;
@@ -1847,6 +1900,10 @@ static const struct ctl_table_class tables[] = {
      {{NULL, NULL, NULL},
       {NULL, NULL, NULL}}},
 
+    {&nbrec_table_load_balancer,
+     {{NULL, NULL, NULL},
+      {NULL, NULL, NULL}}},
+
     {&nbrec_table_logical_router,
      {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
       {NULL, NULL, NULL}}},
@@ -1866,6 +1923,10 @@ static const struct ctl_table_class tables[] = {
        NULL},
       {NULL, NULL, NULL}}},
 
+    {&nbrec_table_address_set,
+     {{&nbrec_table_address_set, &nbrec_address_set_col_name, NULL},
+      {NULL, NULL, NULL}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 \f
@@ -2120,9 +2181,10 @@ static const struct ctl_command_syntax nbctl_commands[] = {
     { "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 },