[ovs-dev,RFC,v1,2/3] OVN ACL: Allow ct_mark and ct_label values to be set from register as well

Message ID 1547165793-14659-3-git-send-email-ankur.sharma@nutanix.com
State New
Headers show
Series
  • Associate identifier with OVN ACL connection tracking entry
Related show

Commit Message

Ankur Sharma Jan. 11, 2019, 12:16 a.m.
OVN allows only an integer (or masked integer) to be assigned to
ct_mark and ct_label.

This patch, enhances the parser code to allow ct_mark and ct_label
to be assigned from 32 bit registers (MFF_REG0 - MFF_REG15) and  128
bit registers (MFF_XXREG0 - MFF_XXREG3) respectively.

signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com>
---
 include/ovn/actions.h |  3 +++
 ovn/lib/actions.c     | 73 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 70 insertions(+), 6 deletions(-)

Patch

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index 1c0c67c..58b96a1 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -24,6 +24,7 @@ 
 #include "openvswitch/dynamic-string.h"
 #include "openvswitch/hmap.h"
 #include "openvswitch/uuid.h"
+#include "openvswitch/meta-flow.h"
 #include "util.h"
 
 struct expr;
@@ -196,8 +197,10 @@  struct ovnact_ct_next {
 /* OVNACT_CT_COMMIT. */
 struct ovnact_ct_commit {
     struct ovnact ovnact;
+    bool is_ct_mark_reg, is_ct_label_reg; /* If the value is from a register */
     uint32_t ct_mark, ct_mark_mask;
     ovs_be128 ct_label, ct_label_mask;
+    enum mf_field_id ct_mark_reg, ct_label_reg;
 };
 
 /* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
index 7b7a894..c0c8da7 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -627,8 +627,28 @@  parse_ct_commit_arg(struct action_context *ctx,
         } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
             cc->ct_mark = ntohll(ctx->lexer->token.value.integer);
             cc->ct_mark_mask = ntohll(ctx->lexer->token.mask.integer);
+        } else if (ctx->lexer->token.type == LEX_T_ID) {
+
+           cc->ct_mark_mask = UINT32_MAX;
+
+           const struct mf_field *mf = mf_from_name(ctx->lexer->token.s);
+           if (mf) {
+
+              if (mf->id >= MFF_REG0 && mf->id <= MFF_REG15) {
+                 cc->is_ct_mark_reg = true;
+                 cc->ct_mark_reg = mf->id;
+              } else {
+                 lexer_syntax_error(ctx->lexer, "input: %s,  not a 32 bit "
+                                    "register", mf->name);
+                 return;
+              }
+           } else {
+              lexer_syntax_error(ctx->lexer, "invalid field name: %s",
+                                 ctx->lexer->token.s);
+              return;
+           }
         } else {
-            lexer_syntax_error(ctx->lexer, "expecting integer");
+            lexer_syntax_error(ctx->lexer, "invalid token type");
             return;
         }
         lexer_get(ctx->lexer);
@@ -642,9 +662,28 @@  parse_ct_commit_arg(struct action_context *ctx,
         } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
             cc->ct_label = ctx->lexer->token.value.be128_int;
             cc->ct_label_mask = ctx->lexer->token.mask.be128_int;
+        } else if (ctx->lexer->token.type == LEX_T_ID) {
+
+           cc->ct_label_mask = OVS_BE128_MAX;
+           const struct mf_field *mf = mf_from_name(ctx->lexer->token.s);
+           if (mf) {
+              if (mf->id >= MFF_XXREG0 && mf->id <= MFF_XXREG3) {
+                 cc->is_ct_label_reg = true;
+                 cc->ct_label_reg = mf->id;
+              } else {
+                 lexer_syntax_error(ctx->lexer, "input: %s,  not a 128 bit "
+                                    "register", mf->name);
+                 return;
+              }
+           } else {
+              lexer_syntax_error(ctx->lexer, "invalid field name: %s",
+                                 ctx->lexer->token.s);
+              return;
+           }
+
         } else {
-            lexer_syntax_error(ctx->lexer, "expecting integer");
-            return;
+           lexer_syntax_error(ctx->lexer, "invalid token type");
+           return;
         }
         lexer_get(ctx->lexer);
     } else {
@@ -713,14 +752,36 @@  encode_CT_COMMIT(const struct ovnact_ct_commit *cc,
     ofpbuf_pull(ofpacts, set_field_offset);
 
     if (cc->ct_mark_mask) {
-        const ovs_be32 value = htonl(cc->ct_mark);
-        const ovs_be32 mask = htonl(cc->ct_mark_mask);
-        ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_MARK), &value, &mask);
+       if (cc->is_ct_mark_reg) {
+          struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+
+          move->src.field = mf_from_id(cc->ct_mark_reg);
+          move->src.ofs = 0;
+          move->src.n_bits = 32;
+          move->dst.field = mf_from_id(MFF_CT_MARK);
+          move->dst.ofs = 0;
+          move->dst.n_bits = 32;
+       } else {
+          const ovs_be32 value = htonl(cc->ct_mark);
+          const ovs_be32 mask = htonl(cc->ct_mark_mask);
+          ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_MARK), &value, &mask);
+       }
     }
 
     if (!ovs_be128_is_zero(cc->ct_label_mask)) {
+       if (cc->is_ct_label_reg) {
+          struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+
+          move->src.field = mf_from_id(cc->ct_label_reg);
+          move->src.ofs = 0;
+          move->src.n_bits = 128;
+          move->dst.field = mf_from_id(MFF_CT_LABEL);
+          move->dst.ofs = 0;
+          move->dst.n_bits = 128;
+       } else {
         ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_LABEL), &cc->ct_label,
                              &cc->ct_label_mask);
+       }
     }
 
     ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset);