@@ -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. */
@@ -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);
@@ -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>
@@ -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)
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(-)