From patchwork Fri Feb 19 17:25:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Moats X-Patchwork-Id: 585331 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 4B44714056B for ; Sat, 20 Feb 2016 04:31:34 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 9889610C0D; Fri, 19 Feb 2016 09:31:23 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 6DF8810C00 for ; Fri, 19 Feb 2016 09:31:22 -0800 (PST) Received: from bar4.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 02C9A1638F8 for ; Fri, 19 Feb 2016 10:31:22 -0700 (MST) X-ASG-Debug-ID: 1455903081-03dc210c7d3b400001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar4.cudamail.com with ESMTP id 3NVxXII0nXb5WePw (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 19 Feb 2016 10:31:21 -0700 (MST) X-Barracuda-Envelope-From: rmoats@oc7146733065.ibm.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO eastrmfepo101.cox.net) (68.230.241.213) by mx1-pf1.cudamail.com with SMTP; 19 Feb 2016 17:31:20 -0000 Received-SPF: none (mx1-pf1.cudamail.com: domain at oc7146733065.ibm.com does not designate permitted sender hosts) X-Barracuda-Apparent-Source-IP: 68.230.241.213 X-Barracuda-RBL-IP: 68.230.241.213 Received: from eastrmimpo209.cox.net ([68.230.241.224]) by eastrmfepo101.cox.net (InterMail vM.8.01.05.15 201-2260-151-145-20131218) with ESMTP id <20160219173119.OFLI10784.eastrmfepo101.cox.net@eastrmimpo209.cox.net> for ; Fri, 19 Feb 2016 12:31:19 -0500 Received: from oc7146733065.ibm.com ([68.13.99.247]) by eastrmimpo209.cox.net with cox id LHXG1s00D5LF6cs01HXK9m; Fri, 19 Feb 2016 12:31:19 -0500 X-CT-Class: Clean X-CT-Score: 0.00 X-CT-RefID: str=0001.0A020206.56C75167.027A, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CT-Spam: 0 X-Authority-Analysis: v=2.1 cv=B+E30YdM c=1 sm=1 tr=0 a=Jmqd6mthTashISSy/JkQqg==:117 a=Jmqd6mthTashISSy/JkQqg==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=jFJIQSaiL_oA:10 a=VnNF1IyMAAAA:8 a=Pv-F9644gDhiX6KZ_AgA:9 X-CM-Score: 0.00 Authentication-Results: cox.net; none Received: by oc7146733065.ibm.com (Postfix, from userid 500) id 625181880ED4; Fri, 19 Feb 2016 11:31:17 -0600 (CST) X-CudaMail-Envelope-Sender: rmoats@oc7146733065.ibm.com From: Ryan Moats To: dev@openvswitch.org X-CudaMail-MID: CM-E1-218049194 X-CudaMail-DTE: 021916 X-CudaMail-Originating-IP: 68.230.241.213 Date: Fri, 19 Feb 2016 11:25:09 -0600 X-ASG-Orig-Subj: [##CM-E1-218049194##][PATCH v7 3/6] [ovn-controller] Make flow table persistent Message-Id: <1455902712-7756-4-git-send-email-rmoats@us.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1455902712-7756-1-git-send-email-rmoats@us.ibm.com> References: <1455902712-7756-1-git-send-email-rmoats@us.ibm.com> X-GBUdb-Analysis: 0, 68.230.241.213, Ugly c=0.36638 p=-0.257143 Source Normal X-MessageSniffer-Rules: 0-0-0-17576-c X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1455903081 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.27164 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [PATCH v7 3/6] [ovn-controller] Make flow table persistent 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" From: RYAN D. MOATS This is a prerequisite for incremental processing. Signed-off-by: RYAN D. MOATS --- ovn/controller/ofctrl.c | 118 +++++++++++++++++++++++++++------------ ovn/controller/ofctrl.h | 2 + ovn/controller/ovn-controller.c | 4 +- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 3297fb3..7280c8b 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -484,16 +484,53 @@ ofctrl_add_flow(struct hmap *desired_flows, f->ofpacts_len = actions->size; f->hmap_node.hash = ovn_flow_hash(f); - if (ovn_flow_lookup(desired_flows, f)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); - if (!VLOG_DROP_INFO(&rl)) { - char *s = ovn_flow_to_string(f); - VLOG_INFO("dropping duplicate flow: %s", s); - free(s); - } + /* loop through all the flows to see if there is an old flow to be + * removed - do so if the old flow has the same priority, table, and match + * but a different action or if the old flow has the same priority, table + * and action, but the new match is either a superset or subset of the + * old match */ + + struct ovn_flow *d, *next; + HMAP_FOR_EACH_SAFE (d, next, hmap_node, desired_flows) { + if (f->table_id == d->table_id && f->priority == d->priority) { + if ((match_equal(&f->match, &d->match) + && !ofpacts_equal(f->ofpacts, f->ofpacts_len, + d->ofpacts, d->ofpacts_len)) + || (ofpacts_equal(f->ofpacts, f->ofpacts_len, + d->ofpacts, d->ofpacts_len) + && ((flow_wildcards_has_extra(&f->match.wc,&d->match.wc) + && flow_equal_except(&f->match.flow, &d->match.flow, + &f->match.wc)) + || (flow_wildcards_has_extra(&d->match.wc,&f->match.wc) + && flow_equal_except(&d->match.flow, + &f->match.flow, + &d->match.wc))))) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + if (!VLOG_DROP_INFO(&rl)) { + char *s = ovn_flow_to_string(d); + VLOG_INFO("removing superceded flow: %s", s); + free(s); + } - ovn_flow_destroy(f); - return; + hmap_remove(desired_flows, &d->hmap_node); + ovn_flow_destroy(d); + } + + /* if this is a complete duplicate, remove the new flow */ + if (match_equal(&f->match, &d->match) + && ofpacts_equal(f->ofpacts, f->ofpacts_len, + d->ofpacts, d->ofpacts_len)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + if (!VLOG_DROP_INFO(&rl)) { + char *s = ovn_flow_to_string(f); + VLOG_INFO("dropping duplicate flow: %s", s); + free(s); + } + + ovn_flow_destroy(f); + return; + } + } } hmap_insert(desired_flows, &f->hmap_node, f->hmap_node.hash); @@ -501,6 +538,20 @@ ofctrl_add_flow(struct hmap *desired_flows, /* ovn_flow. */ +/* duplicate an ovn_flow structure */ +struct ovn_flow * +ofctrl_dup_flow(struct ovn_flow *source) +{ + struct ovn_flow *answer = xmalloc(sizeof *answer); + answer->table_id = source->table_id; + answer->priority = source->priority; + answer->match = source->match; + answer->ofpacts = xmemdup(source->ofpacts, source->ofpacts_len); + answer->ofpacts_len = source->ofpacts_len; + answer->hmap_node.hash = ovn_flow_hash(answer); + return answer; +} + /* Returns a hash of the key in 'f'. */ static uint32_t ovn_flow_hash(const struct ovn_flow *f) @@ -595,19 +646,16 @@ queue_flow_mod(struct ofputil_flow_mod *fm) * flows from 'flow_table' and frees them. (The hmap itself isn't * destroyed.) * - * This called be called be ofctrl_run() within the main loop. */ + * This can be called by ofctrl_run() within the main loop. */ void ofctrl_put(struct hmap *flow_table) { /* The flow table can be updated if the connection to the switch is up and * in the correct state and not backlogged with existing flow_mods. (Our * criteria for being backlogged appear very conservative, but the socket - * between ovn-controller and OVS provides some buffering.) Otherwise, - * discard the flows. A solution to either of those problems will cause us - * to wake up and retry. */ + * between ovn-controller and OVS provides some buffering.) */ if (state != S_UPDATE_FLOWS || rconn_packet_counter_n_packets(tx_counter)) { - ovn_flow_table_clear(flow_table); return; } @@ -653,31 +701,31 @@ ofctrl_put(struct hmap *flow_table) d->ofpacts = NULL; d->ofpacts_len = 0; } - - hmap_remove(flow_table, &d->hmap_node); - ovn_flow_destroy(d); } } - /* The previous loop removed from 'flow_table' all of the flows that are - * already installed. Thus, any flows remaining in 'flow_table' need to - * be added to the flow table. */ + /* Iterate through the new flows and add those that aren't found + * in the installed flow table */ struct ovn_flow *d; HMAP_FOR_EACH_SAFE (d, next, hmap_node, flow_table) { - /* Send flow_mod to add flow. */ - struct ofputil_flow_mod fm = { - .match = d->match, - .priority = d->priority, - .table_id = d->table_id, - .ofpacts = d->ofpacts, - .ofpacts_len = d->ofpacts_len, - .command = OFPFC_ADD, - }; - queue_flow_mod(&fm); - ovn_flow_log(d, "adding"); - - /* Move 'd' from 'flow_table' to installed_flows. */ - hmap_remove(flow_table, &d->hmap_node); - hmap_insert(&installed_flows, &d->hmap_node, d->hmap_node.hash); + struct ovn_flow *i = ovn_flow_lookup(&installed_flows, d); + if (!i) { + /* Send flow_mod to add flow. */ + struct ofputil_flow_mod fm = { + .match = d->match, + .priority = d->priority, + .table_id = d->table_id, + .ofpacts = d->ofpacts, + .ofpacts_len = d->ofpacts_len, + .command = OFPFC_ADD, + }; + queue_flow_mod(&fm); + ovn_flow_log(d, "adding"); + + /* Copy 'd' from 'flow_table' to installed_flows. */ + struct ovn_flow *new_node = ofctrl_dup_flow(d); + hmap_insert(&installed_flows, &new_node->hmap_node, + new_node->hmap_node.hash); + } } } diff --git a/ovn/controller/ofctrl.h b/ovn/controller/ofctrl.h index 93ef8ea..d3fabc0 100644 --- a/ovn/controller/ofctrl.h +++ b/ovn/controller/ofctrl.h @@ -34,6 +34,8 @@ void ofctrl_put(struct hmap *flows); void ofctrl_wait(void); void ofctrl_destroy(void); +struct ovn_flow *ofctrl_dup_flow(struct ovn_flow *source); + /* Flow table interface to the rest of ovn-controller. */ void ofctrl_add_flow(struct hmap *flows, uint8_t table_id, uint16_t priority, const struct match *, const struct ofpbuf *ofpacts); diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 3638342..5a4174e 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -205,6 +205,8 @@ main(int argc, char *argv[]) bool exiting; int retval; + struct hmap flow_table = HMAP_INITIALIZER(&flow_table); + ovs_cmdl_proctitle_init(argc, argv); set_program_name(argv[0]); service_start(&argc, &argv); @@ -299,14 +301,12 @@ main(int argc, char *argv[]) pinctrl_run(&ctx, br_int); - struct hmap flow_table = HMAP_INITIALIZER(&flow_table); lflow_run(&ctx, &flow_table, &ct_zones, &local_datapaths); if (chassis_id) { physical_run(&ctx, mff_ovn_geneve, br_int, chassis_id, &ct_zones, &flow_table); } ofctrl_put(&flow_table); - hmap_destroy(&flow_table); } /* local_datapaths contains bare hmap_node instances.