#include "lex.h"
#include "ofp-actions.h"
#include "ofpbuf.h"
+#include "simap.h"
/* Context maintained during actions_parse(). */
struct action_context {
uint8_t first_ptable; /* First OpenFlow table. */
uint8_t cur_ltable; /* 0 <= cur_ltable < n_tables. */
uint8_t output_ptable; /* OpenFlow table for 'output' to resubmit. */
+ const struct simap *ct_zones; /* Map from port name to conntrack zone. */
/* State. */
char *error; /* Error, if any, otherwise NULL. */
}
}
+static void
+emit_ct(struct action_context *ctx, bool recirc_next, bool commit)
+{
+ struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
+ ct->flags |= commit ? NX_CT_F_COMMIT : 0;
+
+ /* If "recirc" is set, we automatically go to the next table. */
+ if (recirc_next) {
+ if (ctx->cur_ltable < ctx->n_tables) {
+ ct->recirc_table = ctx->first_ptable + ctx->cur_ltable + 1;
+ } else {
+ action_error(ctx, "\"ct_next\" action not allowed in last table.");
+ return;
+ }
+ } else {
+ ct->recirc_table = NX_CT_RECIRC_NONE;
+ }
+
+ /* xxx Should remove hard-coding reg5 if we refactor library. */
+ ct->zone_src.field = mf_from_id(MFF_REG5);
+ ct->zone_src.ofs = 0;
+ ct->zone_src.n_bits = 16;
+
+ /* We do not support ALGs yet. */
+ ct->alg = 0;
+
+ /* CT only works with IP, so set up a prerequisite. */
+ struct expr *expr;
+ char *error;
+
+ expr = expr_parse_string("ip", ctx->symtab, &error);
+ ovs_assert(!error);
+ ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
+}
+
static void
parse_actions(struct action_context *ctx)
{
} else {
action_syntax_error(ctx, "expecting `--'");
}
+ } else if (lexer_match_id(ctx->lexer, "ct_next")) {
+ emit_ct(ctx, true, false);
+ } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
+ emit_ct(ctx, false, true);
} else {
action_syntax_error(ctx, "expecting action");
}
* (as one would provide to expr_to_matches()). Strings used in the actions
* that are not in 'ports' are translated to zero.
*
+ * 'ct_zones' provides a map from a port name to its connection tracking zone.
+ *
* OVN maps each logical flow table (ltable), one-to-one, onto a physical
* OpenFlow flow table (ptable). A number of parameters describe this mapping
* and data related to flow tables:
* cur_ltable + 1 < n_tables, then this defines the default table that
* "next" will jump to.
*
+ * 'next_table_id' should be the OpenFlow table to which the "next" action will
+ * resubmit, or 0 to disable "next".
+ *
* - 'output_ptable' should be the OpenFlow table to which the logical
* "output" action will resubmit
*
*/
char * OVS_WARN_UNUSED_RESULT
actions_parse(struct lexer *lexer, const struct shash *symtab,
- const struct simap *ports,
+ const struct simap *ports, const struct simap *ct_zones,
uint8_t first_ptable, uint8_t n_tables, uint8_t cur_ltable,
uint8_t output_ptable, struct ofpbuf *ofpacts,
struct expr **prereqsp)
ctx.lexer = lexer;
ctx.symtab = symtab;
ctx.ports = ports;
+ ctx.ct_zones = ct_zones;
ctx.first_ptable = first_ptable;
ctx.n_tables = n_tables;
ctx.cur_ltable = cur_ltable;
/* 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 first_table,
- uint8_t n_tables, uint8_t cur_table,
+ const struct simap *ports, const struct simap *ct_zones,
+ uint8_t first_table, uint8_t n_tables, uint8_t cur_table,
uint8_t output_table, struct ofpbuf *ofpacts,
struct expr **prereqsp)
{
lexer_init(&lexer, s);
lexer_get(&lexer);
- error = actions_parse(&lexer, symtab, ports, first_table, n_tables,
- cur_table, output_table, ofpacts, prereqsp);
+ error = actions_parse(&lexer, symtab, ports, ct_zones, first_table,
+ n_tables, cur_table, output_table, ofpacts,
+ prereqsp);
lexer_destroy(&lexer);
return error;