X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ovn%2Fovn-nbctl.c;h=0bdb3a38778d7796a5bf908bef8ca9755fc90ef1;hb=62fdd819efe859cb35ae0e4292c0b1cdad330f64;hp=b00d7b1d147df27fff90b1749f360f0138b4115f;hpb=a367622aea312ce5c6e219212af08d5ed20ca61c;p=cascardo%2Fovs.git diff --git a/ovn/ovn-nbctl.c b/ovn/ovn-nbctl.c index b00d7b1d1..0bdb3a387 100644 --- a/ovn/ovn-nbctl.c +++ b/ovn/ovn-nbctl.c @@ -15,13 +15,14 @@ #include #include +#include #include #include #include "command-line.h" #include "dirs.h" #include "fatal-signal.h" -#include "ovn/ovn-nb-idl.h" +#include "ovn/lib/ovn-nb-idl.h" #include "poll-loop.h" #include "process.h" #include "stream.h" @@ -47,6 +48,10 @@ usage(void) %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\ @@ -58,17 +63,34 @@ Logical switch commands:\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] [MAC] [...]\n\ - set MAC addresses for LPORT. Specify more\n\ - than one using additional arguments.\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\ @@ -121,6 +143,48 @@ lswitch_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *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) { @@ -251,15 +315,65 @@ 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]); - nbrec_logical_port_set_lswitch(lport, lswitch); + 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 @@ -273,46 +387,69 @@ do_lport_del(struct ovs_cmdl_context *ctx) return; } - nbrec_logical_port_delete(lport); + /* 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 bool -is_lswitch(const struct nbrec_logical_switch *lswitch, - struct uuid *lswitch_uuid, const char *name) +static void +do_lport_list(struct ovs_cmdl_context *ctx) { - if (lswitch_uuid) { - return uuid_equals(lswitch_uuid, &lswitch->header_.uuid); - } else { - return !strcmp(lswitch->name, name); + 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_list(struct ovs_cmdl_context *ctx) +do_lport_get_tag(struct ovs_cmdl_context *ctx) { struct nbctl_context *nb_ctx = ctx->pvt; - const char *id = ctx->argv[1]; const struct nbrec_logical_port *lport; - bool is_uuid = false; - struct uuid lswitch_uuid; - if (uuid_from_string(&lswitch_uuid, id)) { - is_uuid = true; + lport = lport_by_name_or_uuid(nb_ctx, ctx->argv[1]); + if (!lport) { + return; } - NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) { - bool match; - if (is_uuid) { - match = is_lswitch(lport->lswitch, &lswitch_uuid, NULL); - } else { - match = is_lswitch(lport->lswitch, NULL, id); - } - if (!match) { - continue; - } - printf(UUID_FMT " (%s)\n", - UUID_ARGS(&lport->header_.uuid), lport->name); + if (lport->n_tag > 0) { + printf("%"PRId64"\n", lport->tag[0]); } } @@ -407,6 +544,40 @@ do_lport_get_macs(struct ovs_cmdl_context *ctx) } } +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) { @@ -421,6 +592,124 @@ do_lport_get_up(struct ovs_cmdl_context *ctx) 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); + } +} static void parse_options(int argc, char *argv[]) @@ -480,6 +769,13 @@ parse_options(int argc, char *argv[]) } 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]", @@ -517,9 +813,9 @@ static const struct ovs_cmdl_command all_commands[] = { }, { .name = "lport-add", - .usage = "LSWITCH LPORT", + .usage = "LSWITCH LPORT [PARENT] [TAG]", .min_args = 2, - .max_args = 2, + .max_args = 4, .handler = do_lport_add, }, { @@ -536,6 +832,20 @@ static const struct ovs_cmdl_command all_commands[] = { .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]", @@ -552,7 +862,7 @@ static const struct ovs_cmdl_command all_commands[] = { }, { .name = "lport-set-macs", - .usage = "LPORT [MAC] [MAC] [...]", + .usage = "LPORT [MAC]...", .min_args = 1, /* Accept however many arguments the system will allow. */ .max_args = INT_MAX, @@ -565,6 +875,21 @@ static const struct ovs_cmdl_command all_commands[] = { .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", @@ -572,6 +897,48 @@ static const struct ovs_cmdl_command all_commands[] = { .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 */ @@ -590,7 +957,10 @@ default_db(void) { static char *def; if (!def) { - def = xasprintf("unix:%s/db.sock", ovs_rundir()); + def = getenv("OVN_NB_DB"); + if (!def) { + def = xasprintf("unix:%s/db.sock", ovs_rundir()); + } } return def; }