From patchwork Sat Sep 5 00:39:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Justin Pettit X-Patchwork-Id: 514781 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id 48071140284 for ; Sat, 5 Sep 2015 10:39:17 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 04E6822C39C; Fri, 4 Sep 2015 17:39:11 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 02C5222C394 for ; Fri, 4 Sep 2015 17:39:10 -0700 (PDT) Received: from bar3.cudamail.com (bar1 [192.168.15.1]) by mx3v1.cudamail.com (Postfix) with ESMTP id 556486189ED for ; Fri, 4 Sep 2015 18:39:09 -0600 (MDT) X-ASG-Debug-ID: 1441413547-03dd7b516943eb0001-byXFYA Received: from mx3-pf1.cudamail.com ([192.168.14.2]) by bar3.cudamail.com with ESMTP id raEQaGpT9K5EDyCe (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 04 Sep 2015 18:39:07 -0600 (MDT) X-Barracuda-Envelope-From: jpettit@nicira.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.2 Received: from unknown (HELO mail-pa0-f50.google.com) (209.85.220.50) by mx3-pf1.cudamail.com with ESMTPS (RC4-SHA encrypted); 5 Sep 2015 00:39:07 -0000 Received-SPF: unknown (mx3-pf1.cudamail.com: Multiple SPF records returned) X-Barracuda-Apparent-Source-IP: 209.85.220.50 X-Barracuda-RBL-IP: 209.85.220.50 Received: by pacex6 with SMTP id ex6so38493221pac.0 for ; Fri, 04 Sep 2015 17:39:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=Yw6zQ5GaGfURiKGCJPdG3T5cPabMek4hNL+811riXG0=; b=b7QGs3mfmlUfejQJ5L6ALG9v12lNykJ8jGfVZ3lrDVstYthblb+DUaSEAMCWUlkI/C 0w6fie3S/KSNAqmLKk1EgN7fyHBy6mJji5kQ2KCC60O7ZNdsTq5Oms6gEELYMzI+BRVP RHWunRJgrkX5qxkKNHDtI6imC7w644C/Ixnh4jIEnQ462dt3qr3Rsua1Uns7G5/o/vKZ xsdP1ZG0AARmlLkXDe6hIsIqZ84uN1IVgarEDFRfMKaX99FzMWdUl1NOpv0HOykxApj+ YmW91Wu7mPFS8z/y7n6fdF+vSAb68q7Bd3LPQon9QC723pttJpYXH6prTtx1liS9fzC5 7ghQ== X-Gm-Message-State: ALoCoQk/wWS24HRmvK+Jjb8sHx5rZYZmI+mwT9eBaTxjeyEQyrXDBI36qBf+IbA1pbKLk7lJOk+K X-Received: by 10.68.196.202 with SMTP id io10mr14001579pbc.141.1441413547042; Fri, 04 Sep 2015 17:39:07 -0700 (PDT) Received: from localhost.localdomain ([208.91.2.4]) by smtp.gmail.com with ESMTPSA id d4sm3828325pdc.93.2015.09.04.17.39.06 for (version=TLSv1/SSLv3 cipher=OTHER); Fri, 04 Sep 2015 17:39:06 -0700 (PDT) X-CudaMail-Envelope-Sender: jpettit@nicira.com From: Justin Pettit To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-V1-903054327 X-CudaMail-DTE: 090415 X-CudaMail-Originating-IP: 209.85.220.50 Date: Fri, 4 Sep 2015 17:39:02 -0700 X-ASG-Orig-Subj: [##CM-V1-903054327##][PATCH 2/2] ovn-nbctl: Add ACL commands. Message-Id: <1441413542-92140-2-git-send-email-jpettit@nicira.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1441413542-92140-1-git-send-email-jpettit@nicira.com> References: <1441413542-92140-1-git-send-email-jpettit@nicira.com> X-Barracuda-Connect: UNKNOWN[192.168.14.2] X-Barracuda-Start-Time: 1441413547 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH 2/2] ovn-nbctl: Add ACL commands. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Justin Pettit --- ovn/utilities/ovn-nbctl.8.xml | 28 +++++ ovn/utilities/ovn-nbctl.c | 242 +++++++++++++++++++++++++++++++++++++++++ tests/ovn-nbctl.at | 49 ++++++++ 3 files changed, 319 insertions(+), 0 deletions(-) diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index ba3cc82..1555b02 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -66,6 +66,34 @@ +

ACL Commands

+
+
acl-add lswitch direction priority match action [log]
+
+ Adds the specified ACL to lswitch. + direction must be either from-lport or + to-lport. priority must be between + 1 and 65534, inclusive. If + log is supplied, packet logging is enabled for the + ACL. A full description of the fields are in ovn-nb(5). +
+ +
acl-del lswitch [direction [priority match]]
+
+ Deletes ACLs from lswitch. If only + lswitch is supplied, all the ACLs from the logical + switch are deleted. If direction is also specified, + then all the flows in that direction will be deleted from the + logical switch. If all the fields are given, then a single flow + that matches all the fields will be deleted. +
+ +
acl-list lswitch
+
+ Lists the ACLs on lswitch. +
+
+

Logical Port Commands

lport-add lswitch lport
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index d095df1..0b19521 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -63,6 +63,13 @@ Logical switch commands:\n\ lswitch-get-external-id LSWITCH [KEY]\n\ list one or all external-ids on LSWITCH\n\ \n\ +ACL commands:\n\ + acl-add LSWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\ + add an ACL to LSWITCH\n\ + acl-del LSWITCH [DIRECTION [PRIORITY MATCH]]\n\ + remove ACLs from LSWITCH\n\ + acl-list LSWITCH print ACLs for 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\ @@ -747,6 +754,220 @@ do_lport_get_options(struct ovs_cmdl_context *ctx) printf("%s=%s\n", node->key, node->value); } } + +enum { + DIR_FROM_LPORT, + DIR_TO_LPORT +}; + +static int +dir_encode(const char *dir) +{ + if (!strcmp(dir, "from-lport")) { + return DIR_FROM_LPORT; + } else if (!strcmp(dir, "to-lport")) { + return DIR_TO_LPORT; + } + + OVS_NOT_REACHED(); +} + +static int +acl_cmp(const void *acl1_, const void *acl2_) +{ + const struct nbrec_acl *acl1, *acl2; + + acl1 = *((struct nbrec_acl **) acl1_); + acl2 = *((struct nbrec_acl **) acl2_); + + int dir1 = dir_encode(acl1->direction); + int dir2 = dir_encode(acl2->direction); + +#define CMP(expr) \ + do { \ + int res; \ + res = (expr); \ + if (res) { \ + return res; \ + } \ + } while (0) + + CMP(dir1 - dir2); + CMP(acl1->priority > acl2->priority ? -1 : + (acl1->priority < acl2->priority ? 1 : 0)); + CMP(strcmp(acl1->match, acl2->match)); + +#undef CMP + + return 0; +} + +static void +do_acl_list(struct ovs_cmdl_context *ctx) +{ + const struct nbrec_logical_switch *lswitch; + struct nbctl_context *nb_ctx = ctx->pvt; + const struct nbrec_acl **acls; + size_t i; + + lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]); + if (!lswitch) { + return; + } + + acls = xmalloc(sizeof *acls * lswitch->n_acls); + for (i = 0; i < lswitch->n_acls; i++) { + acls[i] = lswitch->acls[i]; + } + + qsort(acls, lswitch->n_acls, sizeof *acls, acl_cmp); + + for (i = 0; i < lswitch->n_acls; i++) { + const struct nbrec_acl *acl = acls[i]; + printf("%10s %5ld (%s) %s%s\n", acl->direction, acl->priority, + acl->match, acl->action, acl->log ? " log" : ""); + } + + free(acls); +} + +static void +do_acl_add(struct ovs_cmdl_context *ctx) +{ + const struct nbrec_logical_switch *lswitch; + struct nbctl_context *nb_ctx = ctx->pvt; + const char *action = ctx->argv[5]; + const char *direction; + int64_t priority; + + lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]); + if (!lswitch) { + return; + } + + /* Validate direction. Only require the first letter. */ + if (ctx->argv[2][0] == 't') { + direction = "to-lport"; + } else if (ctx->argv[2][0] == 'f') { + direction = "from-lport"; + } else { + VLOG_WARN("Invalid direction '%s'", ctx->argv[2]); + return; + } + + /* Validate priority. */ + if (!ovs_scan(ctx->argv[3], "%"SCNd64, &priority) || priority < 1 + || priority > 65535) { + VLOG_WARN("Invalid priority '%s'", ctx->argv[3]); + return; + } + + /* Validate action. */ + if (strcmp(action, "allow") && strcmp(action, "allow-related") + && strcmp(action, "drop") && strcmp(action, "reject")) { + VLOG_WARN("Invalid action '%s'", action); + return; + } + + /* Create the acl. */ + struct nbrec_acl *acl = nbrec_acl_insert(nb_ctx->txn); + nbrec_acl_set_priority(acl, priority); + nbrec_acl_set_direction(acl, direction); + nbrec_acl_set_match(acl, ctx->argv[4]); + nbrec_acl_set_action(acl, action); + if (ctx->argc == 7 && ctx->argv[6][0] == 'l') { + nbrec_acl_set_log(acl, true); + } + + /* Insert the acl into the logical switch. */ + nbrec_logical_switch_verify_acls(lswitch); + struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * + (lswitch->n_acls + 1)); + memcpy(new_acls, lswitch->acls, sizeof *new_acls * lswitch->n_acls); + new_acls[lswitch->n_acls] = acl; + nbrec_logical_switch_set_acls(lswitch, new_acls, lswitch->n_acls + 1); + free(new_acls); +} + +static void +do_acl_del(struct ovs_cmdl_context *ctx) +{ + const struct nbrec_logical_switch *lswitch; + struct nbctl_context *nb_ctx = ctx->pvt; + const char *direction; + int64_t priority = 0; + + lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]); + if (!lswitch) { + return; + } + + if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) { + VLOG_WARN("Invalid number of arguments"); + return; + } + + if (ctx->argc == 2) { + /* If direction, priority, and match are not specified, delete + * all ACLs. */ + nbrec_logical_switch_verify_acls(lswitch); + nbrec_logical_switch_set_acls(lswitch, NULL, 0); + return; + } + + /* Validate direction. Only require first letter. */ + if (ctx->argv[2][0] == 't') { + direction = "to-lport"; + } else if (ctx->argv[2][0] == 'f') { + direction = "from-lport"; + } else { + VLOG_WARN("Invalid direction '%s'", ctx->argv[2]); + return; + } + + /* If priority and match are not specified, delete all ACLs with the + * specified direction. */ + if (ctx->argc == 3) { + struct nbrec_acl **new_acls + = xmalloc(sizeof *new_acls * lswitch->n_acls); + + int n_acls = 0; + for (size_t i = 0; i < lswitch->n_acls; i++) { + if (strcmp(direction, lswitch->acls[i]->direction)) { + new_acls[n_acls++] = lswitch->acls[i]; + } + } + + nbrec_logical_switch_verify_acls(lswitch); + nbrec_logical_switch_set_acls(lswitch, new_acls, n_acls); + free(new_acls); + return; + } + + /* Validate priority. */ + if (!ovs_scan(ctx->argv[3], "%"SCNd64, &priority) || priority < 1 + || priority > 65535) { + VLOG_WARN("Invalid priority '%s'", ctx->argv[3]); + return; + } + + /* Remove the matching rule. */ + for (size_t i = 0; i < lswitch->n_acls; i++) { + struct nbrec_acl *acl = lswitch->acls[i]; + + if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) && + !strcmp(direction, acl->direction)) { + struct nbrec_acl **new_acls + = xmemdup(lswitch->acls, sizeof *new_acls * lswitch->n_acls); + new_acls[i] = lswitch->acls[lswitch->n_acls - 1]; + nbrec_logical_switch_verify_acls(lswitch); + nbrec_logical_switch_set_acls(lswitch, new_acls, + lswitch->n_acls - 1); + free(new_acls); + return; + } + } +} static void parse_options(int argc, char *argv[]) @@ -849,6 +1070,27 @@ static const struct ovs_cmdl_command all_commands[] = { .handler = do_lswitch_get_external_id, }, { + .name = "acl-add", + .usage = "LSWITCH DIRECTION PRIORITY MATCH ACTION [log]", + .min_args = 5, + .max_args = 6, + .handler = do_acl_add, + }, + { + .name = "acl-del", + .usage = "LSWITCH [DIRECTION [PRIORITY MATCH]]", + .min_args = 1, + .max_args = 4, + .handler = do_acl_del, + }, + { + .name = "acl-list", + .usage = "LSWITCH", + .min_args = 1, + .max_args = 1, + .handler = do_acl_list, + }, + { .name = "lport-add", .usage = "LSWITCH LPORT [PARENT] [TAG]", .min_args = 2, diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 8729ec0..fd9fce8 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -117,3 +117,52 @@ AT_CHECK([ovn-nbctl lport-get-port-security lp0], [0], [dnl OVN_NBCTL_TEST_STOP AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - ACLs]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lswitch-add ls0]) +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 600 udp drop log]) +AT_CHECK([ovn-nbctl acl-add ls0 to-lport 500 udp drop log]) +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 400 tcp drop]) +AT_CHECK([ovn-nbctl acl-add ls0 to-lport 300 tcp drop]) +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 200 ip drop]) +AT_CHECK([ovn-nbctl acl-add ls0 to-lport 100 ip drop]) + +AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl +from-lport 600 (udp) drop log +from-lport 400 (tcp) drop +from-lport 200 (ip) drop + to-lport 500 (udp) drop log + to-lport 300 (tcp) drop + to-lport 100 (ip) drop +]) + +dnl Delete in one direction. +AT_CHECK([ovn-nbctl acl-del ls0 to-lport]) +AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl +from-lport 600 (udp) drop log +from-lport 400 (tcp) drop +from-lport 200 (ip) drop +]) + +dnl Delete all ACLs. +AT_CHECK([ovn-nbctl acl-del ls0]) +AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl +]) + +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 600 udp drop]) +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 400 tcp drop]) +AT_CHECK([ovn-nbctl acl-add ls0 from-lport 200 ip drop]) + +dnl Delete a single flow. +AT_CHECK([ovn-nbctl acl-del ls0 from-lport 400 tcp]) +AT_CHECK([ovn-nbctl acl-list ls0], [0], [dnl +from-lport 600 (udp) drop +from-lport 200 (ip) drop +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP