Skip to content

Commit

Permalink
actions: Add stack push and pop actions.
Browse files Browse the repository at this point in the history
Add two new actions push & pop for stack operations.

Signed-off-by: Han Zhou <[email protected]>
Acked-by: Numan Siddique <[email protected]>
  • Loading branch information
hzhou8 committed Mar 29, 2022
1 parent 3357440 commit 8ce8477
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/ovn/actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ struct ovn_extend_table;
OVNACT(NEXT, ovnact_next) \
OVNACT(LOAD, ovnact_load) \
OVNACT(MOVE, ovnact_move) \
OVNACT(PUSH, ovnact_push_pop) \
OVNACT(POP, ovnact_push_pop) \
OVNACT(EXCHANGE, ovnact_move) \
OVNACT(DEC_TTL, ovnact_null) \
OVNACT(CT_NEXT, ovnact_ct_next) \
Expand Down Expand Up @@ -234,6 +236,12 @@ struct ovnact_move {
struct expr_field rhs;
};

/* OVNACT_PUSH, OVNACT_POP. */
struct ovnact_push_pop {
struct ovnact ovnact;
struct expr_field field;
};

/* OVNACT_CT_NEXT. */
struct ovnact_ct_next {
struct ovnact ovnact;
Expand Down
73 changes: 73 additions & 0 deletions lib/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,75 @@ ovnact_move_free(struct ovnact_move *move OVS_UNUSED)
{
}


static void
parse_push_pop(struct action_context *ctx, bool is_push)
{
lexer_force_match(ctx->lexer, LEX_T_LPAREN);

struct expr_field f;
if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, &f, &ctx->prereqs)) {
return;
}
size_t ofs = ctx->ovnacts->size;
char *error = expr_type_check(&f, f.n_bits, !is_push, ctx->scope);
if (error) {
ctx->ovnacts->size = ofs;
lexer_error(ctx->lexer, "%s", error);
free(error);
return;
}

lexer_force_match(ctx->lexer, LEX_T_RPAREN);

struct ovnact_push_pop *p;
if (is_push) {
p = ovnact_put_PUSH(ctx->ovnacts);
} else {
p = ovnact_put_POP(ctx->ovnacts);
}
p->field = f;
}

static void
format_PUSH(const struct ovnact_push_pop *push, struct ds *s)
{
ds_put_cstr(s, "push(");
expr_field_format(&push->field, s);
ds_put_cstr(s, ");");
}

static void
encode_PUSH(const struct ovnact_push_pop *push,
const struct ovnact_encode_params *ep OVS_UNUSED,
struct ofpbuf *ofpacts)
{
ofpact_put_STACK_PUSH(ofpacts)->subfield =
expr_resolve_field(&push->field);
}

static void
format_POP(const struct ovnact_push_pop *pop, struct ds *s)
{
ds_put_cstr(s, "pop(");
expr_field_format(&pop->field, s);
ds_put_cstr(s, ");");
}

static void
encode_POP(const struct ovnact_push_pop *pop,
const struct ovnact_encode_params *ep OVS_UNUSED,
struct ofpbuf *ofpacts)
{
ofpact_put_STACK_POP(ofpacts)->subfield =
expr_resolve_field(&pop->field);
}

static void
ovnact_push_pop_free(struct ovnact_push_pop *push OVS_UNUSED)
{
}

static void
parse_DEC_TTL(struct action_context *ctx)
{
Expand Down Expand Up @@ -4237,6 +4306,10 @@ parse_action(struct action_context *ctx)
parse_set_action(ctx);
} else if (lexer_match_id(ctx->lexer, "next")) {
parse_NEXT(ctx);
} else if (lexer_match_id(ctx->lexer, "push")) {
parse_push_pop(ctx, true);
} else if (lexer_match_id(ctx->lexer, "pop")) {
parse_push_pop(ctx, false);
} else if (lexer_match_id(ctx->lexer, "output")) {
ovnact_put_OUTPUT(ctx->ovnacts);
} else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
Expand Down
15 changes: 15 additions & 0 deletions ovn-sb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,21 @@
</p>
</dd>

<dt><code>push(<var>field</var>);</code></dt>
<dd>
<p>
Push the value of <var>field</var> to the stack top.
</p>
</dd>

<dt><code>pop(<var>field</var>);</code></dt>
<dd>
<p>
Pop the stack top and store the value to <var>field</var>,
which must be modifiable.
</p>
</dd>

<dt><code>ip.ttl--;</code></dt>
<dd>
<p>
Expand Down
11 changes: 11 additions & 0 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -1982,6 +1982,17 @@ reg1[1] = lookup_fdb(outport, ip4.src);
reg1[1] = lookup_fdb(ip4.src, eth.src);
Cannot use numeric field ip4.src where string field is required.

# push/pop
push(xxreg0);push(xxreg1[10..20]);push(eth.src);pop(xxreg0[0..47]);pop(xxreg0[48..57]);pop(xxreg1);
formats as push(xxreg0); push(xxreg1[10..20]); push(eth.src); pop(xxreg0[0..47]); pop(xxreg0[48..57]); pop(xxreg1);
encodes as push:NXM_NX_XXREG0[],push:NXM_NX_XXREG1[10..20],push:NXM_OF_ETH_SRC[],pop:NXM_NX_XXREG0[0..47],pop:NXM_NX_XXREG0[48..57],pop:NXM_NX_XXREG1[]

pop(eth.type);
Field eth.type is not modifiable.

push(abc);
Syntax error at `abc' expecting field name.

# Miscellaneous negative tests.
;
Syntax error at `;'.
Expand Down
64 changes: 64 additions & 0 deletions utilities/ovn-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,59 @@ execute_exchange(const struct ovnact_move *move, struct flow *uflow,
mf_subfield_swap(&a, &b, uflow, NULL);
}

static void
execute_push(const struct ovnact_push_pop *p, struct ofpbuf *stack,
struct flow *uflow OVS_UNUSED, struct ovs_list *super)
{
struct mf_subfield sf = expr_resolve_field(&p->field);
union mf_subvalue sv;
mf_read_subfield(&sf, uflow, &sv);

struct ds s = DS_EMPTY_INITIALIZER;
ds_put_cstr(&s, "push(");
expr_field_format(&p->field, &s);
ds_put_cstr(&s, ") -> ");
mf_format_subvalue(&sv, &s);

ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s", ds_cstr(&s));
ds_destroy(&s);

uint8_t bytes = DIV_ROUND_UP(sf.n_bits, 8);
nx_stack_push(stack, &sv.u8[sizeof sv - bytes], bytes);
}

static void
execute_pop(const struct ovnact_push_pop *p, struct ofpbuf *stack,
struct flow *uflow OVS_UNUSED, struct ovs_list *super)
{
struct mf_subfield sf = expr_resolve_field(&p->field);
struct ds s = DS_EMPTY_INITIALIZER;
ds_put_cstr(&s, "pop(");
expr_field_format(&p->field, &s);
ds_put_cstr(&s, ") <- ");

uint8_t src_bytes;
const void *src = nx_stack_pop(stack, &src_bytes);
if (src) {
union mf_subvalue sv;
uint8_t dst_bytes = DIV_ROUND_UP(sf.n_bits, 8);

if (src_bytes < dst_bytes) {
memset(&sv.u8[sizeof sv - dst_bytes], 0,
dst_bytes - src_bytes);
}
memcpy(&sv.u8[sizeof sv - src_bytes], src, src_bytes);
mf_write_subfield_flow(&sf, &sv, uflow);
mf_format_subvalue(&sv, &s);
} else {
ds_put_cstr(&s, "/* empty stack */");
}

ovntrace_node_append(super, OVNTRACE_NODE_MODIFY, "%s", ds_cstr(&s));

ds_destroy(&s);
}

static void
trace__(const struct ovntrace_datapath *dp, struct flow *uflow,
uint8_t table_id, enum ovnact_pipeline pipeline,
Expand Down Expand Up @@ -2558,6 +2611,8 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
return;
}

struct ofpbuf stack;
ofpbuf_init(&stack, 0);
struct ds s = DS_EMPTY_INITIALIZER;
const struct ovnact *a;
OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
Expand Down Expand Up @@ -2588,6 +2643,14 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
execute_exchange(ovnact_get_EXCHANGE(a), uflow, super);
break;

case OVNACT_PUSH:
execute_push(ovnact_get_PUSH(a), &stack, uflow, super);
break;

case OVNACT_POP:
execute_pop(ovnact_get_POP(a), &stack, uflow, super);
break;

case OVNACT_DEC_TTL:
if (is_ip_any(uflow)) {
if (uflow->nw_ttl) {
Expand Down Expand Up @@ -2829,6 +2892,7 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
break;
}
}
ofpbuf_uninit(&stack);
ds_destroy(&s);
}

Expand Down

0 comments on commit 8ce8477

Please sign in to comment.