[ovs-dev,v4,2/3,ovn] OVN ACL: Allow ct_mark and ct_label values to be set from register as well
diff mbox series

Message ID 1573267855-102768-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 Nov. 9, 2019, 2:49 a.m. UTC
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 registers as well.

Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com>
---
 include/ovn/actions.h |  3 +++
 lib/actions.c         | 72 ++++++++++++++++++++++++++++++++++++++++++++-------
 ovn-sb.xml            | 41 +++++++++++++++++++++--------
 tests/ovn.at          | 31 ++++++++++++++++++++++
 4 files changed, 126 insertions(+), 21 deletions(-)

Patch
diff mbox series

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index f4997e9..dda9a66 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -218,8 +218,11 @@  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;
+    uint16_t ct_mark_reg_bits, ct_label_reg_bits;
 };
 
 /* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */
diff --git a/lib/actions.c b/lib/actions.c
index a999a4f..2b00469 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -634,8 +634,21 @@  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 && mf_is_register(mf->id)) {
+                cc->is_ct_mark_reg = true;
+                cc->ct_mark_reg = mf->id;
+           } 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);
@@ -649,9 +662,21 @@  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) {
+
+           const struct mf_field *mf = mf_from_name(ctx->lexer->token.s);
+           if (mf && mf_is_register(mf->id)) {
+               cc->is_ct_label_reg = true;
+               cc->ct_label_reg = mf->id;
+           } 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 {
@@ -719,15 +744,42 @@  encode_CT_COMMIT(const struct ovnact_ct_commit *cc,
     size_t set_field_offset = ofpacts->size;
     ofpbuf_pull(ofpacts, set_field_offset);
 
-    if (cc->ct_mark_mask) {
+    if (cc->is_ct_mark_reg) {
+        struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+        const struct mf_field *src_reg = mf_from_id(cc->ct_mark_reg);
+        const struct mf_field *ct_mark = mf_from_id(MFF_CT_MARK);
+
+        move->src.field = src_reg;
+        move->src.ofs = 0;
+        move->src.n_bits = src_reg->n_bits < ct_mark->n_bits ?
+                           src_reg->n_bits : ct_mark->n_bits;
+        move->dst.field = mf_from_id(MFF_CT_MARK);
+        move->dst.ofs = 0;
+        move->dst.n_bits = src_reg->n_bits < ct_mark->n_bits ?
+                           src_reg->n_bits : ct_mark->n_bits;
+    } else 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 (!ovs_be128_is_zero(cc->ct_label_mask)) {
-        ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_LABEL), &cc->ct_label,
-                             &cc->ct_label_mask);
+        ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_MARK), &value,
+                             &mask);
+    }
+
+    if (cc->is_ct_label_reg) {
+        struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts);
+        const struct mf_field *src_reg = mf_from_id(cc->ct_label_reg);
+        const struct mf_field *ct_label = mf_from_id(MFF_CT_LABEL);
+
+        move->src.field = src_reg;
+        move->src.ofs = 0;
+        move->src.n_bits = src_reg->n_bits < ct_label->n_bits ?
+                           src_reg->n_bits : ct_label->n_bits;
+        move->dst.field = ct_label;
+        move->dst.ofs = 0;
+        move->dst.n_bits = src_reg->n_bits < ct_label->n_bits ?
+                           src_reg->n_bits : ct_label->n_bits;
+    } else if (!ovs_be128_is_zero(cc->ct_label_mask)) {
+        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);
diff --git a/ovn-sb.xml b/ovn-sb.xml
index e5fb51a..c8306ab 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -1243,20 +1243,39 @@ 
         </dd>
 
         <dt><code>ct_commit;</code></dt>
-        <dt><code>ct_commit(ct_mark=<var>value[/mask]</var>);</code></dt>
-        <dt><code>ct_commit(ct_label=<var>value[/mask]</var>);</code></dt>
-        <dt><code>ct_commit(ct_mark=<var>value[/mask]</var>, ct_label=<var>value[/mask]</var>);</code></dt>
+        <dt>
+          <code>
+            ct_commit(ct_mark=(<var>value[/mask]</var> OR <var>regX</var> OR <var>xregX</var> OR <var>xxregX</var>));
+          </code>
+        </dt>
+        <dt>
+          <code>
+            ct_commit(ct_label=(<var>value[/mask]</var> OR <var>regX</var> OR <var>xregX</var> OR <var>xxregX</var>));
+          </code>
+        </dt>
+        <dt>
+          <code>
+            ct_commit(ct_mark=(<var>value[/mask]</var> OR <var>regX</var> OR <var>xregX</var> OR <var>xxregX</var>),
+            ct_label=(<var>value[/mask]</var> OR <var>regX</var> OR <var>xregX</var> OR <var>xxregX</var> ));
+          </code>
+        </dt>
         <dd>
           <p>
             Commit the flow to the connection tracking entry associated with it
-            by a previous call to <code>ct_next</code>.  When
-            <code>ct_mark=<var>value[/mask]</var></code> and/or
-            <code>ct_label=<var>value[/mask]</var></code> are supplied,
-            <code>ct_mark</code> and/or <code>ct_label</code> will be set to the
-            values indicated by <var>value[/mask]</var> on the connection
-            tracking entry. <code>ct_mark</code> is a 32-bit field.
-            <code>ct_label</code> is a 128-bit field. The <var>value[/mask]</var>
-            should be specified in hex string if more than 64bits are to be used.
+            by a previous call to <code>ct_next</code>. When
+            <code>ct_mark=<var>value[/mask]</var> OR <var>regX</var> OR
+            <var>xregX</var> OR <var>xxregX</var> </code> and/or
+            <code>ct_label=<var>value[/mask]</var> OR <var>regX
+            </var> OR <var>xregX</var> OR <var>xxregX</var> </code> are
+            supplied, <code>ct_mark</code> and/or <code>ct_label</code>
+            will be set to the values indicated by <var>value[/mask]</var>
+            or 32 bit/128 bit registers on the connection tracking entry.
+            <code>ct_mark</code> is a 32-bit field and hence will read
+            value only from a 32 bit register (reg0 - reg9).
+            <code>ct_label</code> is a 128-bit field and hence
+            will read value only from a 128 bit register (xxreg0 - xxreg1).
+            The <var>value[/mask]</var> should be specified in hex string if
+            more than 64bits are to be used.
           </p>
 
           <p>
diff --git a/tests/ovn.at b/tests/ovn.at
index 3e20c84..042abee 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1037,6 +1037,37 @@  ct_commit(ct_label=18446744073709551615);
 ct_commit(ct_label=18446744073709551616);
     Decimal constants must be less than 2**64.
 
+ct_commit(ct_label=xxreg1);
+    formats as ct_commit;
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:NXM_NX_XXREG1[]->NXM_NX_CT_LABEL[]))
+    has prereqs ip
+
+ct_commit(ct_label=xreg1);
+    formats as ct_commit;
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:OXM_OF_PKT_REG1[]->NXM_NX_CT_LABEL[0..63]))
+    has prereqs ip
+
+ct_commit(ct_label=reg1);
+    formats as ct_commit;
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:NXM_NX_REG1[]->NXM_NX_CT_LABEL[0..31]))
+    has prereqs ip
+
+ct_commit(ct_mark=xxreg1);
+    formats as ct_commit(ct_mark=0);
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:NXM_NX_XXREG1[0..31]->NXM_NX_CT_MARK[]))
+    has prereqs ip
+
+ct_commit(ct_mark=xreg1);
+    formats as ct_commit(ct_mark=0);
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:OXM_OF_PKT_REG1[0..31]->NXM_NX_CT_MARK[]))
+    has prereqs ip
+
+ct_commit(ct_mark=reg1);
+    formats as ct_commit(ct_mark=0);
+    encodes as ct(commit,zone=NXM_NX_REG13[0..15],exec(move:NXM_NX_REG1[]->NXM_NX_CT_MARK[]))
+    has prereqs ip
+
+
 # ct_dnat
 ct_dnat;
     encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)