[ovs-dev] [PATCH 05/10] actions: Add new OVN action "clone".

Ben Pfaff blp at ovn.org
Fri Jan 20 17:16:27 UTC 2017


Signed-off-by: Ben Pfaff <blp at ovn.org>
---
 include/ovn/actions.h     |  5 ++--
 ovn/lib/actions.c         | 61 ++++++++++++++++++++++++++++++++++++-----------
 ovn/ovn-sb.xml            | 10 ++++++++
 ovn/utilities/ovn-trace.c | 21 +++++++++++++++-
 tests/ovn.at              |  5 ++++
 5 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index 0bf6145..a1b6b90 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016 Nicira, Inc.
+ * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,6 +60,7 @@ struct simap;
     OVNACT(CT_DNAT,       ovnact_ct_nat)            \
     OVNACT(CT_SNAT,       ovnact_ct_nat)            \
     OVNACT(CT_LB,         ovnact_ct_lb)             \
+    OVNACT(CLONE,         ovnact_nest)              \
     OVNACT(ARP,           ovnact_nest)              \
     OVNACT(ND_NA,         ovnact_nest)              \
     OVNACT(GET_ARP,       ovnact_get_mac_bind)      \
@@ -186,7 +187,7 @@ struct ovnact_ct_lb {
     uint8_t ltable;             /* Logical table ID of next table. */
 };
 
-/* OVNACT_ARP, OVNACT_ND_NA. */
+/* OVNACT_ARP, OVNACT_ND_NA, OVNACT_CLONE. */
 struct ovnact_nest {
     struct ovnact ovnact;
     struct ovnact *nested;
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index 7c5a292..213e22e 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -1001,8 +1001,8 @@ ovnact_ct_lb_free(struct ovnact_ct_lb *ct_lb)
     free(ct_lb->dsts);
 }
 
-/* Implements the "arp" and "nd_na" actions, which execute nested actions on a
- * packet derived from the one being processed. */
+/* Implements the "arp", "nd_na", and "clone" actions, which execute nested
+ * actions on a packet derived from the one being processed. */
 static void
 parse_nested_action(struct action_context *ctx, enum ovnact_type type,
                     const char *prereq)
@@ -1018,13 +1018,21 @@ parse_nested_action(struct action_context *ctx, enum ovnact_type type,
         .pp = ctx->pp,
         .lexer = ctx->lexer,
         .ovnacts = &nested,
-        .prereqs = NULL
+        .prereqs = NULL,
     };
     parse_actions(&inner_ctx, LEX_T_RCURLY);
 
-    /* XXX Not really sure what we should do with prerequisites for nested
-     * actions. */
-    expr_destroy(inner_ctx.prereqs);
+    if (prereq) {
+        /* XXX Not really sure what we should do with prerequisites for "arp"
+         * and "nd_na" actions. */
+        expr_destroy(inner_ctx.prereqs);
+        add_prerequisite(ctx, prereq);
+    } else {
+        /* For "clone", the inner prerequisites should just add to the outer
+         * ones. */
+        ctx->prereqs = expr_combine(EXPR_T_AND,
+                                    inner_ctx.prereqs, ctx->prereqs);
+    }
 
     if (inner_ctx.lexer->error) {
         ovnacts_free(nested.data, nested.size);
@@ -1032,8 +1040,6 @@ parse_nested_action(struct action_context *ctx, enum ovnact_type type,
         return;
     }
 
-    add_prerequisite(ctx, prereq);
-
     struct ovnact_nest *on = ovnact_put(ctx->ovnacts, type,
                                         OVNACT_ALIGN(sizeof *on));
     on->nested_len = nested.size;
@@ -1053,6 +1059,12 @@ parse_ND_NA(struct action_context *ctx)
 }
 
 static void
+parse_CLONE(struct action_context *ctx)
+{
+    parse_nested_action(ctx, OVNACT_CLONE, NULL);
+}
+
+static void
 format_nested_action(const struct ovnact_nest *on, const char *name,
                      struct ds *s)
 {
@@ -1074,10 +1086,16 @@ format_ND_NA(const struct ovnact_nest *nest, struct ds *s)
 }
 
 static void
-encode_nested_actions(const struct ovnact_nest *on,
-                      const struct ovnact_encode_params *ep,
-                      enum action_opcode opcode,
-                      struct ofpbuf *ofpacts)
+format_CLONE(const struct ovnact_nest *nest, struct ds *s)
+{
+    format_nested_action(nest, "clone", s);
+}
+
+static void
+encode_nested_neighbor_actions(const struct ovnact_nest *on,
+                               const struct ovnact_encode_params *ep,
+                               enum action_opcode opcode,
+                               struct ofpbuf *ofpacts)
 {
     /* Convert nested actions into ofpacts. */
     uint64_t inner_ofpacts_stub[1024 / 8];
@@ -1102,7 +1120,7 @@ encode_ARP(const struct ovnact_nest *on,
            const struct ovnact_encode_params *ep,
            struct ofpbuf *ofpacts)
 {
-    encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts);
+    encode_nested_neighbor_actions(on, ep, ACTION_OPCODE_ARP, ofpacts);
 }
 
 static void
@@ -1110,9 +1128,22 @@ encode_ND_NA(const struct ovnact_nest *on,
              const struct ovnact_encode_params *ep,
              struct ofpbuf *ofpacts)
 {
-    encode_nested_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts);
+    encode_nested_neighbor_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts);
 }
 
+static void
+encode_CLONE(const struct ovnact_nest *on,
+             const struct ovnact_encode_params *ep,
+             struct ofpbuf *ofpacts)
+{
+    size_t ofs = ofpacts->size;
+    ofpact_put_CLONE(ofpacts);
+    ovnacts_encode(on->nested, on->nested_len, ep, ofpacts);
+
+    struct ofpact_nest *clone = ofpbuf_at_assert(ofpacts, ofs, sizeof *clone);
+    ofpacts->header = clone;
+    ofpact_finish_CLONE(ofpacts, &clone);
+}
 
 static void
 ovnact_nest_free(struct ovnact_nest *on)
@@ -1664,6 +1695,8 @@ parse_action(struct action_context *ctx)
         parse_CT_SNAT(ctx);
     } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
         parse_ct_lb_action(ctx);
+    } else if (lexer_match_id(ctx->lexer, "clone")) {
+        parse_CLONE(ctx);
     } else if (lexer_match_id(ctx->lexer, "arp")) {
         parse_ARP(ctx);
     } else if (lexer_match_id(ctx->lexer, "nd_na")) {
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index 5704f41..bca82e0 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -1137,6 +1137,16 @@
           </p>
         </dd>
 
+
+        <dt><code>clone { <var>action</var>; </code>...<code> };</code></dt>
+        <dd>
+          Makes a copy of the packet being processed and executes each
+          <code>action</code> on the copy.  Actions following the
+          <var>arp</var> action, if any, apply to the original, unmodified
+          packet.  This can be used as a way to ``save and restore'' the packet
+          around a set of actions that may modify it and should not persist.
+        </dd>
+
         <dt><code>arp { <var>action</var>; </code>...<code> };</code></dt>
         <dd>
           <p>
diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c
index 9487b1f..982a81a 100644
--- a/ovn/utilities/ovn-trace.c
+++ b/ovn/utilities/ovn-trace.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Nicira, Inc.
+ * Copyright (c) 2016, 2017 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1228,6 +1228,20 @@ execute_output(const struct ovntrace_datapath *dp, struct flow *uflow,
 }
 
 static void
+execute_clone(const struct ovnact_nest *on, const struct ovntrace_datapath *dp,
+              const struct flow *uflow, uint8_t table_id,
+              enum ovntrace_pipeline pipeline, struct ovs_list *super)
+{
+    struct flow cloned_flow = *uflow;
+
+    struct ovntrace_node *node = ovntrace_node_append(
+        super, OVNTRACE_NODE_TRANSFORMATION, "clone");
+
+    trace_actions(on->nested, on->nested_len, dp, &cloned_flow,
+                  table_id, pipeline, &node->subs);
+}
+
+static void
 execute_arp(const struct ovnact_nest *on, const struct ovntrace_datapath *dp,
             const struct flow *uflow, uint8_t table_id,
             enum ovntrace_pipeline pipeline, struct ovs_list *super)
@@ -1416,6 +1430,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
                                  "*** ct_* actions not implemented");
             break;
 
+        case OVNACT_CLONE:
+            execute_clone(ovnact_get_CLONE(a), dp, uflow, table_id, pipeline,
+                          super);
+            break;
+
         case OVNACT_ARP:
             execute_arp(ovnact_get_ARP(a), dp, uflow, table_id, pipeline,
                         super);
diff --git a/tests/ovn.at b/tests/ovn.at
index a514ebbd..67d73c5 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -867,6 +867,11 @@ ct_snat(foo, bar);
 ct_snat();
     Syntax error at `)' expecting IPv4 address.
 
+# clone
+clone { ip4.dst = 255.255.255.255; output; }; next(11);
+    encodes as clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,27)
+    has prereqs eth.type == 0x800
+
 # arp
 arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
     encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
-- 
2.10.2



More information about the dev mailing list