The ct_commit nat was hardcoded to use DNAT zone in router pipeline. Extend it that it accepts two new arguments (snat/dnat) which will determine the zone for router pipeline. The switch pipeline has only one so it resolves to the same for both arguments.
In order to keep backward compatibility the ct_commit_nat without any arguments is the same as ct_commit_nat(dnat). Other arguments for this function are ignored to make it more future proof. Signed-off-by: Ales Musil <[email protected]> --- include/ovn/actions.h | 12 ++++++-- include/ovn/lex.h | 1 + lib/actions.c | 68 ++++++++++++++++++++++++++++++++++--------- lib/lex.c | 15 ++++++++++ tests/ovn.at | 14 +++++++++ utilities/ovn-trace.c | 2 +- 6 files changed, 95 insertions(+), 17 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 49cfe0624..49fb96fc6 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -75,7 +75,7 @@ struct collector_set_ids; OVNACT(CT_LB_MARK, ovnact_ct_lb) \ OVNACT(SELECT, ovnact_select) \ OVNACT(CT_CLEAR, ovnact_null) \ - OVNACT(CT_COMMIT_NAT, ovnact_ct_nat) \ + OVNACT(CT_COMMIT_NAT, ovnact_ct_commit_nat) \ OVNACT(CLONE, ovnact_nest) \ OVNACT(ARP, ovnact_nest) \ OVNACT(ICMP4, ovnact_nest) \ @@ -274,7 +274,7 @@ enum ovnact_ct_nat_type { OVNACT_CT_NAT_UNSPEC, }; -/* OVNACT_CT_DNAT, OVNACT_CT_SNAT, OVNACT_CT_COMMIT_NAT. */ +/* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */ struct ovnact_ct_nat { struct ovnact ovnact; int family; @@ -296,6 +296,14 @@ struct ovnact_ct_nat { uint8_t ltable; /* Logical table ID of next table. */ }; +/* OVNACT_CT_COMMIT_NAT. */ +struct ovnact_ct_commit_nat { + struct ovnact ovnact; + + bool dnat_zone; + uint8_t ltable; +}; + enum ovnact_ct_lb_flag { OVNACT_CT_LB_FLAG_NONE, OVNACT_CT_LB_FLAG_SKIP_SNAT, diff --git a/include/ovn/lex.h b/include/ovn/lex.h index 64d33361f..13947fa6d 100644 --- a/include/ovn/lex.h +++ b/include/ovn/lex.h @@ -138,6 +138,7 @@ void lexer_init(struct lexer *, const char *input); void lexer_destroy(struct lexer *); enum lex_type lexer_get(struct lexer *); +bool lexer_get_until(struct lexer *, enum lex_type); enum lex_type lexer_lookahead(const struct lexer *); bool lexer_match(struct lexer *, enum lex_type); bool lexer_force_match(struct lexer *, enum lex_type); diff --git a/lib/actions.c b/lib/actions.c index a73fe1a1e..849dbf462 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -1024,12 +1024,26 @@ parse_CT_COMMIT_NAT(struct action_context *ctx) return; } - struct ovnact_ct_nat *cn = ovnact_put_CT_COMMIT_NAT(ctx->ovnacts); - cn->commit = true; + struct ovnact_ct_commit_nat *cn = ovnact_put_CT_COMMIT_NAT(ctx->ovnacts); cn->ltable = ctx->pp->cur_ltable + 1; - cn->family = AF_UNSPEC; - cn->type = OVNACT_CT_NAT_UNSPEC; - cn->port_range.exists = false; + cn->dnat_zone = true; + + if (!lexer_match(ctx->lexer, LEX_T_LPAREN)) { + return; + } + + while (lexer_get_until(ctx->lexer, LEX_T_ID)) { + if (lexer_match_id(ctx->lexer, "dnat")) { + cn->dnat_zone = true; + break; + } else if (lexer_match_id(ctx->lexer, "snat")) { + cn->dnat_zone = false; + break; + } + } + + lexer_get_until(ctx->lexer, LEX_T_RPAREN); + lexer_force_match(ctx->lexer, LEX_T_RPAREN); } static void @@ -1082,9 +1096,10 @@ format_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s) } static void -format_CT_COMMIT_NAT(const struct ovnact_ct_nat *cn OVS_UNUSED, struct ds *s) +format_CT_COMMIT_NAT(const struct ovnact_ct_commit_nat *cn, struct ds *s) { - ds_put_cstr(s, "ct_commit_nat;"); + ds_put_cstr(s, "ct_commit_nat"); + ds_put_cstr(s, cn->dnat_zone ? "(dnat);" : "(snat);"); } static void @@ -1177,20 +1192,45 @@ encode_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, } static void -encode_CT_COMMIT_NAT(const struct ovnact_ct_nat *cn, - const struct ovnact_encode_params *ep, - struct ofpbuf *ofpacts) +encode_CT_COMMIT_NAT(const struct ovnact_ct_commit_nat *cn, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) { - enum mf_field_id zone = ep->is_switch - ? MFF_LOG_CT_ZONE - : MFF_LOG_DNAT_ZONE; - encode_ct_nat(cn, ep, zone, ofpacts); + const size_t ct_offset = ofpacts->size; + + struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts); + ct->recirc_table = cn->ltable + first_ptable(ep, ep->pipeline); + ct->zone_src.ofs = 0; + ct->zone_src.n_bits = 16; + ct->flags = NX_CT_F_COMMIT; + ct->alg = 0; + + if (ep->is_switch) { + ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE); + } else { + ct->zone_src.field = mf_from_id(cn->dnat_zone + ? MFF_LOG_DNAT_ZONE + : MFF_LOG_SNAT_ZONE); + } + + struct ofpact_nat *nat = ofpact_put_NAT(ofpacts); + nat->range_af = AF_UNSPEC; + nat->flags = 0; + + ct = ofpbuf_at_assert(ofpacts, ct_offset, sizeof *ct); + ofpacts->header = ct; + ofpact_finish_CT(ofpacts, &ct); } static void ovnact_ct_nat_free(struct ovnact_ct_nat *ct_nat OVS_UNUSED) { } + +static void +ovnact_ct_commit_nat_free(struct ovnact_ct_commit_nat *cn OVS_UNUSED) +{ +} static void parse_ct_lb_action(struct action_context *ctx, bool ct_lb_mark) diff --git a/lib/lex.c b/lib/lex.c index a8b9812bb..01bf0a0f6 100644 --- a/lib/lex.c +++ b/lib/lex.c @@ -865,6 +865,21 @@ lexer_get(struct lexer *lexer) return lexer->token.type; } +/* Consumes all tokens from 'lexer' until type 't', the token with type 't' + * can be examined via 'lexer->token'. Returns 'true' if token was found, + * otherwise 'false'. */ +bool +lexer_get_until(struct lexer *lexer, enum lex_type t) +{ + enum lex_type type = lexer->token.type; + + while (type != t && type != LEX_T_END) { + type = lexer_get(lexer); + } + + return type == t; +} + /* Returns the type of the next token that will be fetched by lexer_get(), * without advancing 'lexer->token' to that token. */ enum lex_type diff --git a/tests/ovn.at b/tests/ovn.at index e8c79512b..94f57d796 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1498,6 +1498,20 @@ ct_clear; # ct_commit_nat ct_commit_nat; + formats as ct_commit_nat(dnat); + encodes as ct(commit,table=19,zone=NXM_NX_REG13[0..15],nat) + has prereqs ip + +ct_commit_nat(snat); + encodes as ct(commit,table=19,zone=NXM_NX_REG13[0..15],nat) + has prereqs ip + +ct_commit_nat(dnat); + encodes as ct(commit,table=19,zone=NXM_NX_REG13[0..15],nat) + has prereqs ip + +ct_commit_nat(snat, dnat, ignore, 1, "ignore"); + formats as ct_commit_nat(snat); encodes as ct(commit,table=19,zone=NXM_NX_REG13[0..15],nat) has prereqs ip diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 0b86eae7b..b8055f7d9 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2462,7 +2462,7 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, } static void -execute_ct_commit_nat(const struct ovnact_ct_nat *ct_nat, +execute_ct_commit_nat(const struct ovnact_ct_commit_nat *ct_nat, const struct ovntrace_datapath *dp, struct flow *uflow, enum ovnact_pipeline pipeline, struct ovs_list *super) { -- 2.43.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
