On Oct 21, 2013, at 3:52 PM, Ben Pfaff <b...@nicira.com> wrote:

> Commit e3b5693319c (Fix table checking for goto table instruction.) moved
> action checking into modify_flows__(), for good reason, but as a side
> effect made modify_flows__() abandon and never commit the ofopgroup that it
> started, if action checking failed.  This commit fixes the problem.
> 
> The following commands, run under "make sandbox", illustrate the problem.
> Without this change, the final command hangs because the barrier request
> that ovs-ofctl sends never gets a response (because barriers wait for all
> ofopgroups to complete, which never happens).  With this commit, the
> commands complete quickly:
> 
> ovs-vsctl add-br br0
> ovs-vsctl set bridge br0 protocols=OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13
> ovs-ofctl add-flow -O OpenFlow11 br0 table=1,action=mod_tp_dst:79,goto_table:2
> ovs-ofctl add-flow -O OpenFlow11 br0 table=1,action=mod_tp_dst:79,goto_table:1
> 
> Reported-by: Jarno Rajahalme <jrajaha...@vmware.com>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
> ofproto/ofproto.c |   19 ++++++++++++-------
> tests/ofproto.at  |   26 ++++++++++++++++++++++++++
> 2 files changed, 38 insertions(+), 7 deletions(-)
> 
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index f67e1fb..8dba732 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -4041,6 +4041,18 @@ modify_flows__(struct ofproto *ofproto, struct ofconn 
> *ofconn,
>     enum ofperr error;
>     size_t i;
> 
> +    /* Verify actions before we start to modify any rules, to avoid partial
> +     * flow table modifications. */
> +    for (i = 0; i < rules->n; i++) {
> +        struct rule *rule = rules->rules[i];
> +
> +        error = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
> +                              u16_to_ofp(ofproto->max_ports), 
> rule->table_id);
> +        if (error) {
> +            return error;
> +        }
> +    }
> +

This fixes the problem I had, thank you!

While we are at this, we should use ofproto_check_ofpacts() instead and maybe 
avoid repeating the same check over and over again. How about this incremental:

commit f61dcc149af6b132959eefb8a210ea6e99d191cc
Author: Jarno Rajahalme <jrajaha...@nicira.com>
Date:   Thu Oct 24 13:56:14 2013 -0700

    Fixup.
    
    Use ofproto_check_ofpacts() instead of ofpacts_check() directly.
    Avoid repeating the same check.
---
 ofproto/ofproto.c |   19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 87d9f7a..63d9684 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -4040,16 +4040,23 @@ modify_flows__(struct ofproto *ofproto, struct ofconn 
*ofconn,
     struct ofopgroup *group;
     enum ofperr error;
     size_t i;
+    uint8_t last_table = 255; /* Invalid table value. */
 
     /* Verify actions before we start to modify any rules, to avoid partial
-     * flow table modifications. */
+     * flow table modifications.
+     *
+     * Rules are collected one table at a time, avoid checking with the same
+     * table_id multiple times. */
     for (i = 0; i < rules->n; i++) {
         struct rule *rule = rules->rules[i];
-
-        error = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
-                              u16_to_ofp(ofproto->max_ports), rule->table_id);
-        if (error) {
-            return error;
+        if (rule->table_id != last_table) {
+            error = ofproto_check_ofpacts(ofproto, fm->ofpacts,
+                                          fm->ofpacts_len, &fm->match.flow,
+                                          rule->table_id);
+            if (error) {
+                return error;
+            }
+            last_table = rule->table_id;
         }
     }
 

  Jarno

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to