On 21 March 2016 at 07:54, Russell Bryant <russ...@ovn.org> wrote:

> Update the "ct_commit;" logical flow action to optionally take
> one or two parameters, setting the value of "ct_mark" or "ct_label".
> Supported ct_commit syntax now includes:
>
>     ct_commit;
>     ct_commit();
>     ct_commit(ct_mark=1);
>     ct_commit(ct_label=1);
>     ct_commit(ct_mark=1, ct_label=1);
>
> Setting ct_mark via this type of logical flow results in an OpenFlow
> flow that looks like:
>
>     actions=ct(commit,zone=NXM_NX_REG5[0..15],exec(set_field:0x1->ct_mark))
>
> Similarly, setting ct_label results in:
>
>
> actions=ct(commit,zone=NXM_NX_REG5[0..15],exec(set_field:0x1->ct_label))
>

I think this feature makes it tricky to share zones with other stateful
additions. If you want to commit only once for all stateful services, then
set-field for ct_mark and ct_label will need to be loaded to registers in
advance, which I guess would mean that you loose 2 registers for this
purpose.

>
> A future commit will make use of this feature.
>
> Signed-off-by: Russell Bryant <russ...@ovn.org>
> ---
>  ovn/lib/actions.c | 128
> ++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  ovn/ovn-sb.xml    |  13 +++++-
>  2 files changed, 136 insertions(+), 5 deletions(-)
>
> diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
> index 6f67b93..a6b1988 100644
> --- a/ovn/lib/actions.c
> +++ b/ovn/lib/actions.c
> @@ -412,7 +412,8 @@ parse_put_arp_action(struct action_context *ctx)
>  }
>
>  static void
> -emit_ct(struct action_context *ctx, bool recirc_next, bool commit)
> +emit_ct(struct action_context *ctx, bool recirc_next, bool commit,
> +        int *ct_mark, ovs_be128 *ct_label)
>  {
>      struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
>      ct->flags |= commit ? NX_CT_F_COMMIT : 0;
> @@ -438,6 +439,127 @@ emit_ct(struct action_context *ctx, bool
> recirc_next, bool commit)
>
>      /* CT only works with IP, so set up a prerequisite. */
>      add_prerequisite(ctx, "ip");
> +
> +    if (ct_mark) {
> +        size_t set_field_offset = ctx->ofpacts->size;
> +        ofpbuf_pull(ctx->ofpacts, set_field_offset);
> +
> +        struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ctx->ofpacts);
> +        sf->field = mf_from_id(MFF_CT_MARK);
> +        sf->value.be32 = htonl(*ct_mark);
> +        sf->mask.be32 = OVS_BE32_MAX;
> +
> +        ctx->ofpacts->header = ofpbuf_push_uninit(ctx->ofpacts,
> set_field_offset);
> +        ct = ctx->ofpacts->header;
> +        ofpact_finish(ctx->ofpacts, &ct->ofpact);
> +    }
> +
> +    if (ct_label) {
> +        size_t set_field_offset = ctx->ofpacts->size;
> +        ofpbuf_pull(ctx->ofpacts, set_field_offset);
> +
> +        struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ctx->ofpacts);
> +        sf->field = mf_from_id(MFF_CT_LABEL);
> +        sf->value.be128 = *ct_label;
> +        sf->mask.be128 = OVS_BE128_MAX;
> +
> +        ctx->ofpacts->header = ofpbuf_push_uninit(ctx->ofpacts,
> set_field_offset);
> +        ct = ctx->ofpacts->header;
> +        ofpact_finish(ctx->ofpacts, &ct->ofpact);
> +
> +    }
> +}
> +
> +/* Parse an argument to the ct_commit(); action.  Supported arguments
> include:
> + *
> + *      ct_mark=0
> + *      ct_label=0
> + *
> + * If a comma separates the current argument from the next argument, this
> + * function will consume it.
> + *
> + * Return true after successfully parsing an argument.  false on failure.
> */
> +static bool
> +parse_ct_commit_arg(struct action_context *ctx,
> +                    bool *set_mark, int *mark_value,
> +                    bool *set_label, ovs_be128 *label_value)
> +{
> +    if (lexer_match_id(ctx->lexer, "ct_mark")) {
> +        if (!lexer_match(ctx->lexer, LEX_T_EQUALS)) {
> +            action_error(ctx, "Expected '=' after argument to ct_commit");
> +            return false;
> +        }
> +        if (!action_get_int(ctx, mark_value)) {
> +            return false;
> +        }
> +        *set_mark = true;
> +    } else if (lexer_match_id(ctx->lexer, "ct_label")) {
> +        if (!lexer_match(ctx->lexer, LEX_T_EQUALS)) {
> +            action_error(ctx, "Expected '=' after argument to ct_commit");
> +            return false;
> +        }
> +        /* XXX We only support a ct_label value specified as decimal.
> +         * ct_label is 128-bit, so we should eventually also support
> specifying
> +         * full 128-bit values as hex.  Hex support isn't really needed
> until
> +         * we need more than 32 bits. */
> +        int val;
> +        if (!action_get_int(ctx, &val)) {
> +            return false;
> +        }
> +        label_value->be32[3] = htonl(val);
> +        *set_label = true;
> +    } else {
> +        action_error(ctx, "Expected argument to ct_commit()");
> +        return false;
> +    }
> +
> +    if (lexer_match(ctx->lexer, LEX_T_COMMA)) {
> +        /* A comma is valid after an argument, but only if another
> +         * argument is present (not a closing paren) */
> +        if (lexer_lookahead(ctx->lexer) != LEX_T_RPAREN) {
> +            action_error(ctx, "Another argument to ct_commit() expected "
> +                              "after comma.");
> +            return false;
> +        }
> +    }
> +
> +    return true;
> +}
> +
> +static void
> +parse_ct_commit_action(struct action_context *ctx)
> +{
> +    if (!lexer_match(ctx->lexer, LEX_T_LPAREN)) {
> +        /* ct_commit; */
> +        emit_ct(ctx, false, true, NULL, NULL);
> +        return;
> +    }
> +
> +    if (lexer_match(ctx->lexer, LEX_T_RPAREN)) {
> +        /* ct_commit(); */
> +        emit_ct(ctx, false, true, NULL, NULL);
> +        return;
> +    }
> +
> +    /* ct_commit(ct_mark=0); */
> +    /* ct_commit(ct_label=0); */
> +    /* ct_commit(ct_mark=0, ct_label=0); */
> +
> +    bool set_mark = false;
> +    bool set_label = false;
> +    int mark_value = 0;
> +    ovs_be128 label_value = { .be32 = { 0, }, };
> +
> +    while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
> +        if (!parse_ct_commit_arg(ctx, &set_mark, &mark_value,
> +                                 &set_label, &label_value)) {
> +            return;
> +        }
> +    }
> +
> +    emit_ct(ctx, false, true,
> +            set_mark ? &mark_value : NULL,
> +            set_label ? &label_value : NULL);
>  }
>
>  static bool
> @@ -464,9 +586,9 @@ parse_action(struct action_context *ctx)
>              action_syntax_error(ctx, "expecting `--'");
>          }
>      } else if (lexer_match_id(ctx->lexer, "ct_next")) {
> -        emit_ct(ctx, true, false);
> +        emit_ct(ctx, true, false, NULL, NULL);
>      } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
> -        emit_ct(ctx, false, true);
> +        parse_ct_commit_action(ctx);
>      } else if (lexer_match_id(ctx->lexer, "arp")) {
>          parse_arp_action(ctx);
>      } else if (lexer_match_id(ctx->lexer, "get_arp")) {
> diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
> index 31af8dc..467f889 100644
> --- a/ovn/ovn-sb.xml
> +++ b/ovn/ovn-sb.xml
> @@ -915,15 +915,24 @@
>          </dd>
>
>          <dt><code>ct_commit;</code></dt>
> +        <dt><code>ct_commit(ct_mark=VALUE);</code></dt>
>          <dd>
>            <p>
>              Commit the flow to the connection tracking entry associated
> -            with it by a previous call to <code>ct_next</code>.
> +            with it by a previous call to <code>ct_next</code>.  When
> +            the ct_mark=VALUE parameter is supplied, ct_mark will be set
> +            to the 32-bit integer indicated by VALUE on the connection
> +            tracking entry.
>            </p>
> +
>            <p>
>              Note that if you want processing to continue in the next
> table,
>              you must execute the <code>next</code> action after
> -            <code>ct_commit</code>.
> +            <code>ct_commit</code>.  You may also leave out
> <code>next</code>
> +            which will commit connection tracking state, and then drop the
> +            packet.  This could be useful for seting <code>ct_mark</code>
> +            on a connection tracking entry before dropping a packet,
> +            for example.
>            </p>
>          </dd>
>
> --
> 2.5.0
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to