Traces should not modify the flow table without the a packet or
"-generate" option.

This patch also adds further testing to verify that MPLS recirculation
works.

Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 ofproto/ofproto-dpif-xlate.c |   59 ++++++++++++++++++++++++------------------
 tests/mpls-xlate.at          |   14 ++++++++--
 2 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 1133a06..3f866ce 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3255,16 +3255,9 @@ compose_recirculate_action(struct xlate_ctx *ctx,
 {
     uint32_t id;
     int error;
-    unsigned ofpacts_len;
-    struct match match;
-    struct rule *rule;
-    struct ofpbuf ofpacts;
 
     ctx->exit = true;
 
-    ofpacts_len = ofpacts_base_len -
-        ((uint8_t *)ofpact_current - (uint8_t *)ofpacts_base);
-
     if (ctx->rule) {
         id = rule_dpif_get_recirc_id(ctx->rule);
     } else {
@@ -3283,26 +3276,37 @@ compose_recirculate_action(struct xlate_ctx *ctx,
         return;
     }
 
-    match_init_catchall(&match);
-    match_set_recirc_id(&match, id);
-    ofpbuf_use_const(&ofpacts, ofpact_current, ofpacts_len);
-    error = ofproto_dpif_add_internal_flow(ctx->xbridge->ofproto, &match,
-                                           RECIRC_RULE_PRIORITY,
-                                           RECIRC_TIMEOUT, &ofpacts, &rule);
-    if (error) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
-        VLOG_ERR_RL(&rl, "Failed to add post recirculation flow %s",
-                    match_to_string(&match, 0));
+    /* Only create the recirculation flow if we have a packet. */
+    if (ctx->xin->packet) {
+        struct match match;
+        struct rule *rule;
+        unsigned ofpacts_len;
+        struct ofpbuf ofpacts;
+
+        ofpacts_len = ofpacts_base_len -
+            ((uint8_t *)ofpact_current - (uint8_t *)ofpacts_base);
+
+        match_init_catchall(&match);
+        match_set_recirc_id(&match, id);
+        ofpbuf_use_const(&ofpacts, ofpact_current, ofpacts_len);
+        error = ofproto_dpif_add_internal_flow(ctx->xbridge->ofproto, &match,
+                                               RECIRC_RULE_PRIORITY,
+                                               RECIRC_TIMEOUT, &ofpacts, 
&rule);
+        if (error) {
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+            VLOG_ERR_RL(&rl, "Failed to add post recirculation flow %s",
+                        match_to_string(&match, 0));
+            if (!ctx->rule) {
+                ofproto_dpif_free_recirc_id(ctx->xbridge->ofproto, id);
+            }
+            return;
+        }
+        /* If ctx has no rule then associate the recirc id, which
+         * was allocated above, with the internal rule.  This allows
+         * the recirc id to be released when the internal rule times out. */
         if (!ctx->rule) {
-            ofproto_dpif_free_recirc_id(ctx->xbridge->ofproto, id);
+            rule_set_recirc_id(rule, id);
         }
-        return;
-    }
-    /* If ctx has no rule then associate the recirc id, which
-     * was allocated above, with the internal rule. This allows
-     * the recirc id to be released when the internal rule times out. */
-    if (!ctx->rule) {
-        rule_set_recirc_id(rule, id);
     }
 
     ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
@@ -3310,6 +3314,11 @@ compose_recirculate_action(struct xlate_ctx *ctx,
                                           &ctx->xout->wc,
                                           ctx->xbridge->masked_set_action);
     nl_msg_put_u32(ctx->xout->odp_actions, OVS_ACTION_ATTR_RECIRC, id);
+
+    /* Free recirc id if it was not associated with any rule. */
+    if (!ctx->rule && !ctx->xin->packet) {
+        ofproto_dpif_free_recirc_id(ctx->xbridge->ofproto, id);
+    }
 }
 
 static void
diff --git a/tests/mpls-xlate.at b/tests/mpls-xlate.at
index e2ef2e7..47e6680 100644
--- a/tests/mpls-xlate.at
+++ b/tests/mpls-xlate.at
@@ -32,7 +32,7 @@ AT_CHECK([ovs-ofctl del-flows br0])
 
 AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 
in_port=local,dl_type=0x0800,action=push_mpls:0x8847,set_field:10-\>mpls_label,push_mpls:0x8847,set_field:20-\>mpls_label,output:1])
 AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 
table=0,dl_type=0x8847,in_port=1,mpls_label=60,action=pop_mpls:0x8847,goto_table:1])
-AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 
table=1,dl_type=0x8847,in_port=1,mpls_label=50,action=pop_mpls:0x0800,output:LOCAL])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 
table=1,dl_type=0x8847,in_port=1,mpls_label=50,action=pop_mpls:0x0800,set_field:10-\>nw_ttl,output:LOCAL])
 
 dnl Double MPLS push
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'in_port(100),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'],
 [0], [stdout])
@@ -41,10 +41,20 @@ AT_CHECK([tail -1 stdout], [0],
 ])
 
 dnl Double MPLS pop
-AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=60,tc=0/0,ttl=64,bos=0)'],
 [0], [stdout])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=60,tc=0/0,ttl=64,bos=0)'
 -generate], [0], [stdout])
 AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: pop_mpls(eth_type=0x8847),recirc(300)
 ])
 
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'recirc_id(300),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x8847),mpls(label=50,tc=0/0,ttl=64,bos=0)'
 -generate], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: pop_mpls(eth_type=0x800),recirc(301)
+])
+
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'recirc_id(301),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=f8:bc:12:46:58:e0),eth_type(0x0800),ipv4(src=1.1.2.92,dst=1.1.2.88,proto=47,tos=0,ttl=64,frag=no)'
 -generate], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: set(ipv4(ttl=10)),100
+])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
-- 
1.7.10.4

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

Reply via email to