On Thu, Jul 19, 2012 at 10:28:03AM -0700, Justin Pettit wrote: > > On Jul 19, 2012, at 10:04 AM, Ben Pfaff wrote: > > > On Thu, Jul 19, 2012 at 12:45:19AM -0700, Justin Pettit wrote: > >> The new abstraction introduced in commit f25d0cf (Introduce ofpacts, an > >> abstraction of OpenFlow actions.) provides a mechanism for storing the > >> original action type for when converting from the internal representation > >> to a public one may be ambiguous. The "resubmit" action must > >> distinguish between OFPUTIL_NXAST_RESUBMIT_TABLE and > >> OFPUTIL_NXAST_RESUBMIT, so the parsing function needs to properly fill > >> out the "compat" member of the ofpact structure. > >> > >> Bug #8899 > >> Reported-by: Luca Giraudo <lgira...@nicira.com> > >> Signed-off-by: Justin Pettit <jpet...@nicira.com> > > > > Good catch. > > > > Hmm. I hadn't considered this issue when I wrote the ofpacts code. If > > I understand what's going on, it's essentially that ofpacts that differ > > bitwise can yield the same representation as a string (or as OpenFlow > > 1.0 actions). That's going to continue to come up, even if we paper > > over it in this one case. > > > > So, I'd suggest that, instead of comparing ofpacts bytewise, we compare > > some other representation. We could, for example, format the old rule > > and the new rule as strings, then if they're the same just don't print > > the difference (it's false). This would avoid printing false > > differences too. > > Yes, I think this is a better approach and more future-proof as new actions > get added. > > > Do you have a test case we could add to the unit tests? > > No, I don't have one written up beyond what Luca described in the bug report.
OK, I wrote one. I'm glad I did since the patch I posted didn't work. Here's a fixed version for final review. --8<--------------------------cut here-------------------------->8-- From: Ben Pfaff <b...@nicira.com> Date: Thu, 19 Jul 2012 11:18:25 -0700 Subject: [PATCH] ovs-ofctl: Avoid printing false differences on "ovs-ofctl diff-flows". It is possible for "struct ofpact"s to differ bytewise even if they are equivalent when converted to another representation, such as OpenFlow 1.0 action format or a string representation. This can cause "ovs-ofctl diff-flows" to print surprising false "differences", e.g. as in the bug report: - actions=resubmit(,1) + actions=resubmit(,1) This commit fixes the problem by comparing not just the ofpacts but also the string representation and printing a difference only if both differ. Bug #8899. Reported-by: Luca Giraudo <lgira...@nicira.com> Signed-off-by: Ben Pfaff <b...@nicira.com> --- tests/ovs-ofctl.at | 17 ++++++++++++++++ utilities/ovs-ofctl.c | 50 ++++++++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index d6ade55..213007f 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -1825,3 +1825,20 @@ AT_CHECK([ovs-ofctl diff-flows add-flows.txt br0 | sort], [0], [expout]) OVS_VSWITCHD_STOP AT_CLEANUP + +dnl ofpacts that differ bytewise don't necessarily differ when +dnl converted to another representation, such as OpenFlow 1.0 +dnl or to a string. "resubmit(,1)" is an example of an action +dnl of this type: "ofpact_resubmit"s can differ in their "compat" +dnl values even though this doesn't affect the string format. +dnl +dnl This test checks that "ovs-ofctl diff-flows" doesn't report +dnl false ofpacts differences. +AT_SETUP([ovs-ofctl diff-flows - suppress false differences]) +OVS_VSWITCHD_START +AT_DATA([flows.txt], [actions=resubmit(,1) +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) +AT_CHECK([ovs-ofctl diff-flows br0 flows.txt]) +OVS_VSWITCHD_STOP +AT_CLEANUP diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 39c3dae..d4023fa 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -1740,13 +1740,19 @@ fte_version_equals(const struct fte_version *a, const struct fte_version *b) b->ofpacts, b->ofpacts_len)); } -/* Prints 'version' on stdout. Expects the caller to have printed the rule - * associated with the version. */ +/* Clears 's', then if 's' has a version 'index', formats 'fte' and version + * 'index' into 's', followed by a new-line. */ static void -fte_version_print(const struct fte_version *version) +fte_version_format(const struct fte *fte, int index, struct ds *s) { - struct ds s; + const struct fte_version *version = fte->versions[index]; + ds_clear(s); + if (!version) { + return; + } + + cls_rule_format(&fte->rule, s); if (version->cookie != htonll(0)) { printf(" cookie=0x%"PRIx64, ntohll(version->cookie)); } @@ -1757,10 +1763,10 @@ fte_version_print(const struct fte_version *version) printf(" hard_timeout=%"PRIu16, version->hard_timeout); } - ds_init(&s); - ofpacts_format(version->ofpacts, version->ofpacts_len, &s); - printf(" %s\n", ds_cstr(&s)); - ds_destroy(&s); + ds_put_char(s, ' '); + ofpacts_format(version->ofpacts, version->ofpacts_len, s); + + ds_put_char(s, '\n'); } static struct fte * @@ -2067,33 +2073,39 @@ ofctl_diff_flows(int argc OVS_UNUSED, char *argv[]) bool differences = false; struct cls_cursor cursor; struct classifier cls; + struct ds a_s, b_s; struct fte *fte; classifier_init(&cls); read_flows_from_source(argv[1], &cls, 0); read_flows_from_source(argv[2], &cls, 1); + ds_init(&a_s); + ds_init(&b_s); + cls_cursor_init(&cursor, &cls, NULL); CLS_CURSOR_FOR_EACH (fte, rule, &cursor) { struct fte_version *a = fte->versions[0]; struct fte_version *b = fte->versions[1]; if (!a || !b || !fte_version_equals(a, b)) { - char *rule_s = cls_rule_to_string(&fte->rule); - if (a) { - printf("-%s", rule_s); - fte_version_print(a); - } - if (b) { - printf("+%s", rule_s); - fte_version_print(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; } - free(rule_s); - - differences = true; } } + ds_destroy(&a_s); + ds_destroy(&b_s); + fte_free_all(&cls); if (differences) { -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev