On Thu, Apr 30, 2015 at 04:15:13PM -0700, Justin Pettit wrote: > > On Apr 29, 2015, at 11:48 PM, Ben Pfaff <b...@nicira.com> wrote: > > > > + enum lex_type lookahead = lexer_lookahead(ctx->lexer); > > + if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_LSQUARE) { > > I don't think it's clear that bit-level assignment is supported in > the ovn-sb man page. It might be nice to add.
OK, done. > > + parse_set_action(ctx); > > + } else if (lexer_match_id(ctx->lexer, "next")) { > > + emit_resubmit(ctx, ctx->table_id + 1); > > Do you want to enforce that table_id is not equal to the max > table_id? Maybe it's okay, because the next table won't have any > flows so it will get dropped? It still seems surprising, and an > error message might be nice. OK, done. Apparently I'd forgotten to fix up the tests to reflect s/resubmit/next/ earlier, so I fixed that too. > > + } else if (lexer_match_id(ctx->lexer, "output")) { > > + emit_resubmit(ctx, 64); > > The next patch is the one that limits the available table ids to 32, > so this value of 64 looks a little odd. Also, I think it's worth > documenting somewhere what the different tables mean. OK, I moved that change to this patch and added a comment about the table numbers. The comment isn't really sufficient, but I don't think the overall arrangement is finished yet. > Acked-by: Justin Pettit <jpet...@nicira.com> Thanks. I'm appending an incremental diff. I folded this into my "ovn" branch in my ovs-reviews repository. diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 02b7a20..28be688 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -30,7 +30,7 @@ struct action_context { /* Input. */ struct lexer *lexer; /* Lexer for pulling more tokens. */ const struct shash *symtab; /* Symbol table. */ - uint8_t table_id; /* Current logical table. */ + uint8_t next_table_id; /* OpenFlow table for 'next' to resubmit. */ const struct simap *ports; /* Map from port name to number. */ /* State. */ @@ -155,8 +155,13 @@ parse_actions(struct action_context *ctx) if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_LSQUARE) { parse_set_action(ctx); } else if (lexer_match_id(ctx->lexer, "next")) { - emit_resubmit(ctx, ctx->table_id + 1); + if (ctx->next_table_id) { + emit_resubmit(ctx, ctx->next_table_id); + } else { + action_error(ctx, "\"next\" action not allowed here."); + } } else if (lexer_match_id(ctx->lexer, "output")) { + /* Table 64 does logical-to-physical translation. */ emit_resubmit(ctx, 64); } else { action_syntax_error(ctx, "expecting action"); @@ -181,9 +186,8 @@ parse_actions(struct action_context *ctx) * (as one would provide to expr_to_matches()). Strings used in the actions * that are not in 'ports' are translated to zero. * - * 'table_id' should be the OpenFlow table in which the actions will be used, - * to allow OVN "next" actions to go to the correct OpenFlow table (that is, - * table_id+1). + * 'next_table_id' should be the OpenFlow table to which the "next" action will + * resubmit, or 0 to disable "next". * * Some actions add extra requirements (prerequisites) to the flow's match. If * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise, @@ -197,7 +201,7 @@ parse_actions(struct action_context *ctx) */ char * OVS_WARN_UNUSED_RESULT actions_parse(struct lexer *lexer, const struct shash *symtab, - const struct simap *ports, uint8_t table_id, + const struct simap *ports, uint8_t next_table_id, struct ofpbuf *ofpacts, struct expr **prereqsp) { size_t ofpacts_start = ofpacts->size; @@ -206,7 +210,7 @@ actions_parse(struct lexer *lexer, const struct shash *symtab, ctx.lexer = lexer; ctx.symtab = symtab; ctx.ports = ports; - ctx.table_id = table_id; + ctx.next_table_id = next_table_id; ctx.error = NULL; ctx.ofpacts = ofpacts; ctx.prereqs = NULL; @@ -227,7 +231,7 @@ actions_parse(struct lexer *lexer, const struct shash *symtab, /* Like actions_parse(), but the actions are taken from 's'. */ char * OVS_WARN_UNUSED_RESULT actions_parse_string(const char *s, const struct shash *symtab, - const struct simap *ports, uint8_t table_id, + const struct simap *ports, uint8_t next_table_id, struct ofpbuf *ofpacts, struct expr **prereqsp) { struct lexer lexer; @@ -235,7 +239,8 @@ actions_parse_string(const char *s, const struct shash *symtab, lexer_init(&lexer, s); lexer_get(&lexer); - error = actions_parse(&lexer, symtab, ports, table_id, ofpacts, prereqsp); + error = actions_parse(&lexer, symtab, ports, next_table_id, + ofpacts, prereqsp); lexer_destroy(&lexer); return error; diff --git a/ovn/lib/actions.h b/ovn/lib/actions.h index baef953..0139bfc 100644 --- a/ovn/lib/actions.h +++ b/ovn/lib/actions.h @@ -27,11 +27,11 @@ struct shash; struct simap; char *actions_parse(struct lexer *, const struct shash *symtab, - const struct simap *ports, uint8_t table_id, + const struct simap *ports, uint8_t next_table_id, struct ofpbuf *ofpacts, struct expr **prereqsp) OVS_WARN_UNUSED_RESULT;; char *actions_parse_string(const char *s, const struct shash *symtab, - const struct simap *ports, uint8_t table_id, + const struct simap *ports, uint8_t next_table_id, struct ofpbuf *ofpacts, struct expr **prereqsp) OVS_WARN_UNUSED_RESULT;; diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema index 9fd5363..db56211 100644 --- a/ovn/ovn-sb.ovsschema +++ b/ovn/ovn-sb.ovsschema @@ -36,7 +36,7 @@ "logical_datapath": {"type": "uuid"}, "table_id": {"type": {"key": {"type": "integer", "minInteger": 0, - "maxInteger": 127}}}, + "maxInteger": 31}}}, "priority": {"type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 65535}}}, diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index 127d4f1..4bab4e3 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -586,11 +586,19 @@ <dt><code><var>field</var> = <var>constant</var>;</code></dt> <dd> Sets data or metadata field <var>field</var> to constant value - <var>constant</var>. Assigning to a field with prerequisites + <var>constant</var>, e.g. <code>outport = "vif0";</code> to set the + logical output port. Assigning to a field with prerequisites implicitly adds those prerequisites to <ref column="match"/>; thus, for example, a flow that sets <code>tcp.dst</code> applies only to TCP flows, regardless of whether its <ref column="match"/> mentions - any TCP field. + any TCP field. To set only a subset of bits in a field, + <var>field</var> may be a subfield or <var>constant</var> may be + masked, e.g. <code>vlan.pcp[2] = 1;</code> and <code>vlan.pcp = + 4/4;</code> both set the most sigificant bit of the VLAN PCP. Not + all fields are modifiable (e.g. <code>eth.type</code> and + <code>ip.proto</code> are read-only), and not all modifiable fields + may be partially modified (e.g. <code>ip.ttl</code> must assigned as + a whole). </dd> </dl> diff --git a/tests/ovn.at b/tests/ovn.at index 205d70d..ed79192 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -385,9 +385,9 @@ dnl Text before => is input, text after => is expected output. AT_DATA([test-cases.txt], [[ # Positive tests. drop; => actions=drop, prereqs=1 -resubmit; => actions=resubmit(,11), prereqs=1 +next; => actions=resubmit(,11), prereqs=1 output; => actions=resubmit(,64), prereqs=1 -outport="eth0"; resubmit; outport="LOCAL"; resubmit; => actions=set_field:0x5->reg7,resubmit(,11),set_field:0xfffe->reg7,resubmit(,11), prereqs=1 +outport="eth0"; next; outport="LOCAL"; next; => actions=set_field:0x5->reg7,resubmit(,11),set_field:0xfffe->reg7,resubmit(,11), prereqs=1 tcp.dst=80; => actions=set_field:80->tcp_dst, prereqs=ip.proto == 0x6 && (eth.type == 0x800 || eth.type == 0x86dd) eth.dst[40] = 1; => actions=set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst, prereqs=1 vlan.pcp = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=vlan.tci[12] @@ -397,15 +397,15 @@ vlan.tci[13..15] = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=1 ; => Syntax error at `;'. xyzzy; => Syntax error at `xyzzy' expecting action. -resubmit; 123; => Syntax error at `123'. -resubmit; xyzzy; => Syntax error at `xyzzy' expecting action. +next; 123; => Syntax error at `123'. +next; xyzzy; => Syntax error at `xyzzy' expecting action. # "drop;" must be on its own: -drop; resubmit; => Syntax error at `resubmit' expecting end of input. -resubmit; drop; => Syntax error at `drop' expecting action. +drop; next; => Syntax error at `next' expecting end of input. +next; drop; => Syntax error at `drop' expecting action. # Missing ";": -resubmit => Syntax error at end of input expecting ';'. +next => Syntax error at end of input expecting ';'. inport[1] = 1; => Cannot select subfield of string field inport. ip.proto[1] = 1; => Cannot select subfield of nominal field ip.proto. diff --git a/tests/test-ovn.c b/tests/test-ovn.c index 9e56cee..1a005b8 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1136,7 +1136,7 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) char *error; ofpbuf_init(&ofpacts, 0); - error = actions_parse_string(ds_cstr(&input), &symtab, &ports, 10, + error = actions_parse_string(ds_cstr(&input), &symtab, &ports, 11, &ofpacts, &prereqs); if (!error) { struct ds output; -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev