From patchwork Thu Oct 15 21:28:03 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarno Rajahalme X-Patchwork-Id: 530917 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 70FFB14012C for ; Fri, 16 Oct 2015 08:28:38 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id E786C10B2F; Thu, 15 Oct 2015 14:28:30 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e3.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 56AE610B23 for ; Thu, 15 Oct 2015 14:28:29 -0700 (PDT) Received: from bar5.cudamail.com (localhost [127.0.0.1]) by mx1e3.cudamail.com (Postfix) with ESMTPS id B96FB420095 for ; Thu, 15 Oct 2015 15:28:28 -0600 (MDT) X-ASG-Debug-ID: 1444944508-09eadd546722410001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id 6ULDIhEfpj9olpte (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 15 Oct 2015 15:28:28 -0600 (MDT) X-Barracuda-Envelope-From: jrajahalme@nicira.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mail-lf0-f44.google.com) (209.85.215.44) by mx1-pf2.cudamail.com with ESMTPS (RC4-SHA encrypted); 15 Oct 2015 21:28:27 -0000 Received-SPF: unknown (mx1-pf2.cudamail.com: Multiple SPF records returned) X-Barracuda-Apparent-Source-IP: 209.85.215.44 X-Barracuda-RBL-IP: 209.85.215.44 Received: by lfaz124 with SMTP id z124so49810478lfa.1 for ; Thu, 15 Oct 2015 14:28:25 -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:cc:subject:date:message-id:in-reply-to :references; bh=lQO69wMoYROjzNxt1TYy8mozK7CNtzAFhSzT9hH4RSw=; b=FebI04/M2SplhU8s6yF+tw9QOv1gZz7hIK2n2eGpVDTNVU7y4IMt39e7vCQpeJhamA nFkva5R0W7v8V4qvA8NZ1hgzzZ7+0iGAWXt2NKtxH86MbfejyzB57rQxLuj3AYNN4i9v +LXxKIEqrnZSKHdGh/GZ705qPzILtOCaV8iC57UrYBSyQVJEDKbTSzC72w6hYmNqzPFy rGwq8W2kVr9eazJsZW+s62VkIdZDxI/wTKg9kPcZgcowiZk/12y918cPL4KN0jpWzev3 tag0LoydP/yXUQFJ/YqHcAnYglMEFCqtDVaJkFTWBajyYAF5Ndg6tnx7qyngGUAZ+czx w5eA== X-Gm-Message-State: ALoCoQkd9Wg120b2UFq78IMWV+6KBgd/JDFEX2ZpSvE/nrCz6lN0AsIaklMdKsfqNrQoTdQGS6mU X-Received: by 10.180.102.230 with SMTP id fr6mr864734wib.66.1444944505494; Thu, 15 Oct 2015 14:28:25 -0700 (PDT) Received: from sc9-mailhost1.vmware.com ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id gt4sm629339wib.21.2015.10.15.14.28.24 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Oct 2015 14:28:25 -0700 (PDT) X-CudaMail-Envelope-Sender: jrajahalme@nicira.com From: Jarno Rajahalme To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E2-1014117439 X-CudaMail-DTE: 101515 X-CudaMail-Originating-IP: 209.85.215.44 Date: Thu, 15 Oct 2015 14:28:03 -0700 X-ASG-Orig-Subj: [##CM-E2-1014117439##][PATCH 3/4] ovs-ofctl: Support multiple tables in replace-flows and diff-flows. Message-Id: <1444944484-117214-3-git-send-email-jrajahalme@nicira.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1444944484-117214-1-git-send-email-jrajahalme@nicira.com> References: <1444944484-117214-1-git-send-email-jrajahalme@nicira.com> X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1444944508 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 3/4] ovs-ofctl: Support multiple tables in replace-flows and diff-flows. 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: Jarno Rajahalme --- tests/ovs-ofctl.at | 60 ++++++++--------- utilities/ovs-ofctl.c | 174 +++++++++++++++++++++++++++++++------------------- 2 files changed, 140 insertions(+), 94 deletions(-) diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 7375cad..e52cbf9 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -2869,11 +2869,11 @@ OVS_VSWITCHD_START AT_CHECK([ovs-appctl vlog/set vconn:dbg]) dnl Add flows to br0 with importance via OF1.4+, using an OF1.4+ bundle. For more details refer "ovs-ofctl rule with importance" test case. -for i in 1 2 3 4 5 6 7 8; do echo "dl_vlan=$i,importance=$i,actions=drop"; done > add-flows.txt +for i in 1 2 3 4 5 6 7 8; do echo "table=$i,dl_vlan=$i,importance=$i,actions=drop"; done > add-flows.txt AT_CHECK([ovs-ofctl --bundle add-flows br0 add-flows.txt]) dnl Replace some flows in the bridge. -for i in 1 3 5 7; do echo " importance=`expr $i + 10`, dl_vlan=$i actions=drop"; done > replace-flows.txt +for i in 1 3 5 7; do echo " table=$i, importance=`expr $i + 10`, dl_vlan=$i actions=drop"; done > replace-flows.txt AT_CHECK([ovs-ofctl --bundle replace-flows br0 replace-flows.txt]) dnl Dump them and compare the dump flows output against the expected output. @@ -2897,28 +2897,28 @@ vconn|DBG|unix: sent (Success): OFPT_BUNDLE_CONTROL (OF1.4): bundle_id=0 type=OPEN_REPLY flags=0 vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=1 importance:1 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:1 dl_vlan=1 importance:1 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=2 importance:2 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:2 dl_vlan=2 importance:2 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=3 importance:3 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:3 dl_vlan=3 importance:3 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=4 importance:4 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:4 dl_vlan=4 importance:4 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=5 importance:5 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:5 dl_vlan=5 importance:5 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=6 importance:6 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:6 dl_vlan=6 importance:6 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=7 importance:7 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:7 dl_vlan=7 importance:7 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=8 importance:8 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:8 dl_vlan=8 importance:8 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_CONTROL (OF1.4): bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered vconn|DBG|unix: sent (Success): OFPT_BUNDLE_CONTROL (OF1.4): @@ -2930,42 +2930,42 @@ vconn|DBG|unix: received: OFPT_HELLO (OF1.4): vconn|DBG|unix: negotiated OpenFlow version 0x05 (we support version 0x06 and earlier, peer supports version 0x05) vconn|DBG|unix: received: OFPST_FLOW request (OF1.4): vconn|DBG|unix: sent (Success): OFPST_FLOW reply (OF1.4): - importance=1, dl_vlan=1 actions=drop - importance=2, dl_vlan=2 actions=drop - importance=3, dl_vlan=3 actions=drop - importance=4, dl_vlan=4 actions=drop - importance=5, dl_vlan=5 actions=drop - importance=6, dl_vlan=6 actions=drop - importance=7, dl_vlan=7 actions=drop - importance=8, dl_vlan=8 actions=drop + table=1, importance=1, dl_vlan=1 actions=drop + table=2, importance=2, dl_vlan=2 actions=drop + table=3, importance=3, dl_vlan=3 actions=drop + table=4, importance=4, dl_vlan=4 actions=drop + table=5, importance=5, dl_vlan=5 actions=drop + table=6, importance=6, dl_vlan=6 actions=drop + table=7, importance=7, dl_vlan=7 actions=drop + table=8, importance=8, dl_vlan=8 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_CONTROL (OF1.4): bundle_id=0 type=OPEN_REQUEST flags=atomic ordered vconn|DBG|unix: sent (Success): OFPT_BUNDLE_CONTROL (OF1.4): bundle_id=0 type=OPEN_REPLY flags=0 vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:255 dl_vlan=2 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:1 dl_vlan=1 importance:11 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:255 dl_vlan=4 actions=drop +OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:2 dl_vlan=2 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:255 dl_vlan=6 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:3 dl_vlan=3 importance:13 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:255 dl_vlan=8 actions=drop +OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:4 dl_vlan=4 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=1 importance:11 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:5 dl_vlan=5 importance:15 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=3 importance:13 actions=drop +OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:6 dl_vlan=6 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=5 importance:15 actions=drop +OFPT_FLOW_MOD (OF1.4): ADD table:7 dl_vlan=7 importance:17 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_ADD_MESSAGE (OF1.4): bundle_id=0 flags=atomic ordered -OFPT_FLOW_MOD (OF1.4): ADD dl_vlan=7 importance:17 actions=drop +OFPT_FLOW_MOD (OF1.4): DEL_STRICT table:8 dl_vlan=8 actions=drop vconn|DBG|unix: received: OFPT_BUNDLE_CONTROL (OF1.4): bundle_id=0 type=COMMIT_REQUEST flags=atomic ordered vconn|DBG|unix: sent (Success): OFPT_BUNDLE_CONTROL (OF1.4): @@ -2977,10 +2977,10 @@ vconn|DBG|unix: received: OFPT_HELLO (OF1.4): vconn|DBG|unix: negotiated OpenFlow version 0x05 (we support version 0x06 and earlier, peer supports version 0x05) vconn|DBG|unix: received: OFPST_FLOW request (OF1.4): vconn|DBG|unix: sent (Success): OFPST_FLOW reply (OF1.4): - importance=11, dl_vlan=1 actions=drop - importance=13, dl_vlan=3 actions=drop - importance=15, dl_vlan=5 actions=drop - importance=17, dl_vlan=7 actions=drop + table=1, importance=11, dl_vlan=1 actions=drop + table=3, importance=13, dl_vlan=3 actions=drop + table=5, importance=15, dl_vlan=5 actions=drop + table=7, importance=17, dl_vlan=7 actions=drop ]) OVS_VSWITCHD_STOP diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index ee15e1a..7398e7f 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -2472,6 +2472,18 @@ ofctl_list_commands(struct ovs_cmdl_context *ctx OVS_UNUSED) /* replace-flows and diff-flows commands. */ +struct flow_tables { + struct classifier tables[254]; +}; + +static void +flow_tables_init(struct flow_tables *tables) +{ + for (int i = 0; i < ARRAY_SIZE(tables->tables); i++) { + classifier_init(&tables->tables[i], NULL); + } +} + /* A flow table entry, possibly with two different versions. */ struct fte { struct cls_rule rule; /* Within a "struct classifier". */ @@ -2487,6 +2499,7 @@ struct fte_version { uint16_t flags; struct ofpact *ofpacts; size_t ofpacts_len; + uint8_t table_id; }; /* Frees 'version' and the data that it owns. */ @@ -2510,6 +2523,7 @@ fte_version_equals(const struct fte_version *a, const struct fte_version *b) && a->idle_timeout == b->idle_timeout && a->hard_timeout == b->hard_timeout && a->importance == b->importance + && a->table_id == b->table_id && ofpacts_equal(a->ofpacts, a->ofpacts_len, b->ofpacts, b->ofpacts_len)); } @@ -2526,6 +2540,9 @@ fte_version_format(const struct fte *fte, int index, struct ds *s) return; } + if (version->table_id) { + ds_put_format(s, "table=%"PRIu8" ", version->table_id); + } cls_rule_format(&fte->rule, s); if (version->cookie != htonll(0)) { ds_put_format(s, " cookie=0x%"PRIx64, ntohll(version->cookie)); @@ -2564,18 +2581,21 @@ fte_free(struct fte *fte) } } -/* Frees all of the FTEs within 'cls'. */ +/* Frees all of the FTEs within 'tables'. */ static void -fte_free_all(struct classifier *cls) +fte_free_all(struct flow_tables *tables) { - struct fte *fte; + for (int i = 0; i < ARRAY_SIZE(tables->tables); i++) { + struct classifier *cls = &tables->tables[i]; + struct fte *fte; - classifier_defer(cls); - CLS_FOR_EACH (fte, rule, cls) { - classifier_remove(cls, &fte->rule); - ovsrcu_postpone(fte_free, fte); + classifier_defer(cls); + CLS_FOR_EACH (fte, rule, cls) { + classifier_remove(cls, &fte->rule); + ovsrcu_postpone(fte_free, fte); + } + classifier_destroy(cls); } - classifier_destroy(cls); } /* Searches 'cls' for an FTE matching 'rule', inserting a new one if @@ -2603,16 +2623,18 @@ fte_insert(struct classifier *cls, const struct match *match, } } -/* Reads the flows in 'filename' as flow table entries in 'cls' for the version - * with the specified 'index'. Returns the flow formats able to represent the - * flows that were read. */ +/* Reads the flows in 'filename' as flow table entries in 'tables' for the + * version with the specified 'index'. Returns the flow formats able to + * represent the flows that were read. */ static enum ofputil_protocol -read_flows_from_file(const char *filename, struct classifier *cls, int index) +read_flows_from_file(const char *filename, struct flow_tables *tables, + int index) { enum ofputil_protocol usable_protocols; int line_number; struct ds s; FILE *file; + int i; file = !strcmp(filename, "-") ? stdin : fopen(filename, "r"); if (file == NULL) { @@ -2622,7 +2644,10 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index) ds_init(&s); usable_protocols = OFPUTIL_P_ANY; line_number = 0; - classifier_defer(cls); + + for (i = 0; i < ARRAY_SIZE(tables->tables); i++) { + classifier_defer(&tables->tables[i]); + } while (!ds_get_preprocessed_line(&s, file, &line_number)) { struct fte_version *version; struct ofputil_flow_mod fm; @@ -2644,10 +2669,14 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index) | OFPUTIL_FF_EMERG); version->ofpacts = fm.ofpacts; version->ofpacts_len = fm.ofpacts_len; + version->table_id = fm.table_id != 255 ? fm.table_id : 0; - fte_insert(cls, &fm.match, fm.priority, version, index); + fte_insert(&tables->tables[version->table_id], &fm.match, fm.priority, + version, index); + } + for (i = 0; i < ARRAY_SIZE(tables->tables); i++) { + classifier_publish(&tables->tables[i]); } - classifier_publish(cls); ds_destroy(&s); if (file != stdin) { @@ -2711,12 +2740,12 @@ recv_flow_stats_reply(struct vconn *vconn, ovs_be32 send_xid, } /* Reads the OpenFlow flow table from 'vconn', which has currently active flow - * format 'protocol', and adds them as flow table entries in 'cls' for the + * format 'protocol', and adds them as flow table entries in 'tables' for the * version with the specified 'index'. */ static void read_flows_from_switch(struct vconn *vconn, enum ofputil_protocol protocol, - struct classifier *cls, int index) + struct flow_tables *tables, int index) { struct ofputil_flow_stats_request fsr; struct ofputil_flow_stats fs; @@ -2724,6 +2753,7 @@ read_flows_from_switch(struct vconn *vconn, struct ofpbuf ofpacts; struct ofpbuf *reply; ovs_be32 send_xid; + int i; fsr.aggregate = false; match_init_catchall(&fsr.match); @@ -2737,7 +2767,10 @@ read_flows_from_switch(struct vconn *vconn, reply = NULL; ofpbuf_init(&ofpacts, 0); - classifier_defer(cls); + + for (i = 0; i < ARRAY_SIZE(tables->tables); i++) { + classifier_defer(&tables->tables[i]); + } while (recv_flow_stats_reply(vconn, send_xid, &reply, &fs, &ofpacts)) { struct fte_version *version; @@ -2749,10 +2782,14 @@ read_flows_from_switch(struct vconn *vconn, version->flags = 0; version->ofpacts_len = fs.ofpacts_len; version->ofpacts = xmemdup(fs.ofpacts, fs.ofpacts_len); + version->table_id = fs.table_id; - fte_insert(cls, &fs.match, fs.priority, version, index); + fte_insert(&tables->tables[version->table_id], &fs.match, fs.priority, + version, index); + } + for (i = 0; i < ARRAY_SIZE(tables->tables); i++) { + classifier_publish(&tables->tables[i]); } - classifier_publish(cls); ofpbuf_uninit(&ofpacts); } @@ -2770,7 +2807,7 @@ fte_make_flow_mod(const struct fte *fte, int index, uint16_t command, fm.cookie_mask = htonll(0); fm.new_cookie = version->cookie; fm.modify_cookie = true; - fm.table_id = 0xff; + fm.table_id = version->table_id; fm.command = command; fm.idle_timeout = version->idle_timeout; fm.hard_timeout = version->hard_timeout; @@ -2798,41 +2835,45 @@ ofctl_replace_flows(struct ovs_cmdl_context *ctx) { enum { FILE_IDX = 0, SWITCH_IDX = 1 }; enum ofputil_protocol usable_protocols, protocol; - struct classifier cls; + struct flow_tables tables; struct ovs_list requests; struct vconn *vconn; struct fte *fte; - classifier_init(&cls, NULL); - usable_protocols = read_flows_from_file(ctx->argv[2], &cls, FILE_IDX); + flow_tables_init(&tables); + usable_protocols = read_flows_from_file(ctx->argv[2], &tables, FILE_IDX); protocol = open_vconn(ctx->argv[1], &vconn); protocol = set_protocol_for_flow_dump(vconn, protocol, usable_protocols); - read_flows_from_switch(vconn, protocol, &cls, SWITCH_IDX); + read_flows_from_switch(vconn, protocol, &tables, SWITCH_IDX); list_init(&requests); + for (int i = 0; i < ARRAY_SIZE(tables.tables); i++) { + struct classifier *cls = &tables.tables[i]; - /* Delete flows that exist on the switch but not in the file. */ - CLS_FOR_EACH (fte, rule, &cls) { - struct fte_version *file_ver = fte->versions[FILE_IDX]; - struct fte_version *sw_ver = fte->versions[SWITCH_IDX]; + /* Delete flows that exist on the switch but not in the file. */ + CLS_FOR_EACH (fte, rule, cls) { + struct fte_version *file_ver = fte->versions[FILE_IDX]; + struct fte_version *sw_ver = fte->versions[SWITCH_IDX]; - if (sw_ver && !file_ver) { - fte_make_flow_mod(fte, SWITCH_IDX, OFPFC_DELETE_STRICT, - protocol, &requests); + if (sw_ver && !file_ver) { + fte_make_flow_mod(fte, SWITCH_IDX, OFPFC_DELETE_STRICT, + protocol, &requests); + } } - } - /* Add flows that exist in the file but not on the switch. - * Update flows that exist in both places but differ. */ - CLS_FOR_EACH (fte, rule, &cls) { - struct fte_version *file_ver = fte->versions[FILE_IDX]; - struct fte_version *sw_ver = fte->versions[SWITCH_IDX]; + /* Add flows that exist in the file but not on the switch. + * Update flows that exist in both places but differ. */ + CLS_FOR_EACH (fte, rule, cls) { + struct fte_version *file_ver = fte->versions[FILE_IDX]; + struct fte_version *sw_ver = fte->versions[SWITCH_IDX]; - if (file_ver - && (readd || !sw_ver || !fte_version_equals(sw_ver, file_ver))) { - fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, protocol, &requests); + if (file_ver && + (readd || !sw_ver || !fte_version_equals(sw_ver, file_ver))) { + fte_make_flow_mod(fte, FILE_IDX, OFPFC_ADD, protocol, + &requests); + } } } if (bundle) { @@ -2842,24 +2883,25 @@ ofctl_replace_flows(struct ovs_cmdl_context *ctx) } vconn_close(vconn); - fte_free_all(&cls); + fte_free_all(&tables); } static void -read_flows_from_source(const char *source, struct classifier *cls, int index) +read_flows_from_source(const char *source, struct flow_tables *tables, + int index) { struct stat s; if (source[0] == '/' || source[0] == '.' || (!strchr(source, ':') && !stat(source, &s))) { - read_flows_from_file(source, cls, index); + read_flows_from_file(source, tables, index); } else { enum ofputil_protocol protocol; struct vconn *vconn; protocol = open_vconn(source, &vconn); protocol = set_protocol_for_flow_dump(vconn, protocol, OFPUTIL_P_ANY); - read_flows_from_switch(vconn, protocol, cls, index); + read_flows_from_switch(vconn, protocol, tables, index); vconn_close(vconn); } } @@ -2868,40 +2910,44 @@ static void ofctl_diff_flows(struct ovs_cmdl_context *ctx) { bool differences = false; - struct classifier cls; + struct flow_tables tables; struct ds a_s, b_s; struct fte *fte; + int i; - classifier_init(&cls, NULL); - read_flows_from_source(ctx->argv[1], &cls, 0); - read_flows_from_source(ctx->argv[2], &cls, 1); + flow_tables_init(&tables); + read_flows_from_source(ctx->argv[1], &tables, 0); + read_flows_from_source(ctx->argv[2], &tables, 1); ds_init(&a_s); ds_init(&b_s); - CLS_FOR_EACH (fte, rule, &cls) { - struct fte_version *a = fte->versions[0]; - struct fte_version *b = fte->versions[1]; + for (i = 0; i < ARRAY_SIZE(tables.tables); i++) { + struct classifier *cls = &tables.tables[i]; - if (!a || !b || !fte_version_equals(a, b)) { - fte_version_format(fte, 0, &a_s); - fte_version_format(fte, 1, &b_s); - if (strcmp(ds_cstr(&a_s), ds_cstr(&b_s))) { - if (a_s.length) { - printf("-%s", ds_cstr(&a_s)); - } - if (b_s.length) { - printf("+%s", ds_cstr(&b_s)); + CLS_FOR_EACH (fte, rule, cls) { + struct fte_version *a = fte->versions[0]; + struct fte_version *b = fte->versions[1]; + + if (!a || !b || !fte_version_equals(a, b)) { + fte_version_format(fte, 0, &a_s); + fte_version_format(fte, 1, &b_s); + if (strcmp(ds_cstr(&a_s), ds_cstr(&b_s))) { + if (a_s.length) { + printf("-%s", ds_cstr(&a_s)); + } + if (b_s.length) { + printf("+%s", ds_cstr(&b_s)); + } + differences = true; } - differences = true; } } } - ds_destroy(&a_s); ds_destroy(&b_s); - fte_free_all(&cls); + fte_free_all(&tables); if (differences) { exit(2);