On 4/17/24 09:04, Ales Musil wrote:
> On Mon, Apr 15, 2024 at 2:15 PM Martin Kalcok <[email protected]>
> wrote:
> 
>> This change adds a new action 'ct_commit_to_zone' that enables users to
>> commit
>> the flow into a specific zone in the connection tracker.
>>
>> A new feature flag, OVN_FEATURE_CT_COMMIT_TO_ZONE, is also included to
>> avoid
>> issues during upgrade in case the northd is upgraded to a version that
>> supports
>> this action before the controller is upgraded.
>>
>> Note that this action is meaningful only in the context of Logical Router
>> datapath. Logical Switch datapath does not use multiple zones and this
>> action
>> falls back to committing the connection into the default zone for the
>> Logical
>> Switch.
>>
>> Signed-off-by: Martin Kalcok <[email protected]>
>> ---
>>
> 
> Hi Martin,
> 

Hi Martin, Ales,

> thank you for the followup. I have a couple of comments down below.
> 

I have a few of my own. :)

> 
>>  controller/chassis.c      |  8 ++++++
>>  include/ovn/actions.h     |  1 +
>>  include/ovn/features.h    |  1 +
>>  lib/actions.c             | 60 +++++++++++++++++++++++++++++++++++++++
>>  northd/en-global-config.c | 11 +++++++
>>  northd/en-global-config.h |  1 +
>>  ovn-sb.xml                | 24 ++++++++++++++++
>>  tests/ovn.at              | 16 +++++++++++
>>  utilities/ovn-trace.c     |  1 +
>>  9 files changed, 123 insertions(+)
>>
>> diff --git a/controller/chassis.c b/controller/chassis.c
>> index ad75df288..9bb2eba95 100644
>> --- a/controller/chassis.c
>> +++ b/controller/chassis.c
>> @@ -371,6 +371,7 @@ chassis_build_other_config(const struct
>> ovs_chassis_cfg *ovs_cfg,
>>      smap_replace(config, OVN_FEATURE_FDB_TIMESTAMP, "true");
>>      smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
>> +    smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
>>  }
>>
>>  /*
>> @@ -516,6 +517,12 @@ chassis_other_config_changed(const struct
>> ovs_chassis_cfg *ovs_cfg,
>>          return true;
>>      }
>>
>> +    if (!smap_get_bool(&chassis_rec->other_config,
>> +                       OVN_FEATURE_CT_COMMIT_TO_ZONE,
>> +                       false)) {
>> +        return true;
>> +    }
>> +
>>      return false;
>>  }
>>
>> @@ -648,6 +655,7 @@ update_supported_sset(struct sset *supported)
>>      sset_add(supported, OVN_FEATURE_FDB_TIMESTAMP);
>>      sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
>> +    sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
>>  }
>>
>>  static void
>> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
>> index 8e794450c..4bcd1f58c 100644
>> --- a/include/ovn/actions.h
>> +++ b/include/ovn/actions.h
>> @@ -68,6 +68,7 @@ struct collector_set_ids;
>>      OVNACT(CT_NEXT,           ovnact_ct_next)         \
>>      /* CT_COMMIT_V1 is not supported anymore. */      \
>>      OVNACT(CT_COMMIT_V2,      ovnact_nest)            \
>> +    OVNACT(CT_COMMIT_TO_ZONE, ovnact_ct_commit_nat)   \
>>      OVNACT(CT_DNAT,           ovnact_ct_nat)          \
>>      OVNACT(CT_SNAT,           ovnact_ct_nat)          \
>>      OVNACT(CT_DNAT_IN_CZONE,  ovnact_ct_nat)          \
>> diff --git a/include/ovn/features.h b/include/ovn/features.h
>> index 08f1d8288..35a5d8ba0 100644
>> --- a/include/ovn/features.h
>> +++ b/include/ovn/features.h
>> @@ -28,6 +28,7 @@
>>  #define OVN_FEATURE_FDB_TIMESTAMP "fdb-timestamp"
>>  #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
>>  #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
>> +#define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
>>
>>  /* OVS datapath supported features.  Based on availability OVN might
>> generate
>>   * different types of openflows.
>> diff --git a/lib/actions.c b/lib/actions.c
>> index 39bb5bc8a..f26817018 100644
>> --- a/lib/actions.c
>> +++ b/lib/actions.c
>> @@ -791,6 +791,64 @@ encode_CT_COMMIT_V2(const struct ovnact_nest *on,
>>      ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset);
>>      ct = ofpacts->header;
>>      ofpact_finish(ofpacts, &ct->ofpact);
>> +}
>> +
>> +static void
>> +parse_CT_COMMIT_TO_ZONE(struct action_context *ctx)
>> +{
>> +    add_prerequisite(ctx, "ip");
>> +
>> +    struct ovnact_ct_commit_nat *ct_commit =
>> +        ovnact_put_CT_COMMIT_TO_ZONE(ctx->ovnacts);
>>
> 
> The reuse "ovnact_ct_commit_nat" doesn't feel right, it should be renamed
> if anything with a flag indicating whether there should be nat or not. By
> doing that the parse + encoding for ct_commit_nat and ct_commit_to_zone can
> be the same differentiated by the flag.
> 

Just to be clear, your suggestion is to change the ct_commit_to_zone()
action so that it accepts an optional "nat" argument, right?  That would
allow actions like:

ct_commit_to_zone(snat, nat)

Can we do this as a follow up and also update northd to generate flows
with ct_commit_to_zone() instead of ct_commit_nat()?

> 
>> +
>> +    lexer_force_match(ctx->lexer, LEX_T_LPAREN);
>> +
>> +    if (lexer_match_id(ctx->lexer, "dnat")) {
>> +        ct_commit->dnat_zone = true;
>> +    } else if (lexer_match_id(ctx->lexer, "snat")) {
>> +        ct_commit->dnat_zone = false;
>> +    } else {
>> +        lexer_syntax_error(ctx->lexer, "expecting parameter 'dnat' or
>> 'snat'");
>> +    }
>> +
>> +    lexer_force_match(ctx->lexer, LEX_T_RPAREN);
>> +}
>> +
>> +static void
>> +format_CT_COMMIT_TO_ZONE(const struct ovnact_ct_commit_nat *ct_commit,
>> +                         struct ds *s)
>> +{
>> +    ds_put_format(s, "ct_commit_to_zone(%s);",
>> +                  ct_commit->dnat_zone ? "dnat" : "snat");
>> +
>> +}
>> +
>> +static void
>> +encode_CT_COMMIT_TO_ZONE(const struct ovnact_ct_commit_nat *ct_commit,
>> +                         const struct ovnact_encode_params *ep,
>> +                         struct ofpbuf *ofpacts)
>> +{
>> +    struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
>> +    ct->flags = NX_CT_F_COMMIT;
>> +    ct->recirc_table = NX_CT_RECIRC_NONE;
>>
> 
> I don't think this action is ever used standalone so we can actually
> include the next table to avoid writing "ct_commit_to_zone(snat); next;".
> 
> 

We'd have to update ovn-trace too in that case.  I'm a bit on the fence
with this one though.  We do have "ct_next;" already and that implicitly
advances to the next table.   But I think I prefer being explicit in the
logical flow actions (and adding "; next;" in northd).  In any case, not
a must, I'm OK with implicit next too.

>> +    ct->zone_src.ofs = 0;
>> +    ct->zone_src.n_bits = 16;
>> +
>> +    if (ep->is_switch) {
>> +        ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
>> +    } else {
>> +        ct->zone_src.field = mf_from_id(ct_commit->dnat_zone
>> +                                        ? MFF_LOG_DNAT_ZONE
>> +                                        : MFF_LOG_SNAT_ZONE);
>> +    }
>> +
>> +    size_t set_field_offset = ofpacts->size;
>> +    ofpbuf_pull(ofpacts, set_field_offset);
>> +    ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset);
>> +    ct = ofpacts->header;
>> +    ofpact_finish(ofpacts, &ct->ofpact);
>>
> 
> This is the "manual" way of finishing the action encoding. There is a way
> shorter and more explicit way to do it:
> 
>     ct = ofpbuf_at_assert(ofpacts, ct_offset, sizeof *ct);
>     ofpacts->header = ct;
>     ofpact_finish_CT(ofpacts, &ct);
> 
> 
> 
>> +
>> +

Nit: too many empty lines.

>>  }
>>
>>  static void
>> @@ -5306,6 +5364,8 @@ parse_action(struct action_context *ctx)
>>          parse_CT_NEXT(ctx);
>>      } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
>>          parse_CT_COMMIT(ctx);
>> +    } else if (lexer_match_id(ctx->lexer, "ct_commit_to_zone")) {
>> +        parse_CT_COMMIT_TO_ZONE(ctx);
>>      } else if (lexer_match_id(ctx->lexer, "ct_dnat")) {
>>          parse_CT_DNAT(ctx);
>>      } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
>> diff --git a/northd/en-global-config.c b/northd/en-global-config.c
>> index 34e393b33..842ac5b64 100644
>> --- a/northd/en-global-config.c
>> +++ b/northd/en-global-config.c
>> @@ -370,6 +370,7 @@ northd_enable_all_features(struct
>> ed_type_global_config *data)
>>          .fdb_timestamp = true,
>>          .ls_dpg_column = true,
>>          .ct_commit_nat_v2 = true,
>> +        .ct_commit_to_zone = true,
>>      };
>>  }
>>
>> @@ -439,6 +440,16 @@ build_chassis_features(const struct
>> sbrec_chassis_table *sbrec_chassis_table,
>>              chassis_features->ct_commit_nat_v2) {
>>              chassis_features->ct_commit_nat_v2 = false;
>>          }
>> +
>> +        bool ct_commit_to_zone =
>> +                smap_get_bool(&chassis->other_config,
>> +                              OVN_FEATURE_CT_COMMIT_TO_ZONE,
>> +                              false);
>> +        if (!ct_commit_to_zone &&
>> +            chassis_features->ct_commit_to_zone) {
>> +            chassis_features->ct_commit_to_zone = false;
>> +        }
>> +
>>      }
>>  }
>>
>> diff --git a/northd/en-global-config.h b/northd/en-global-config.h
>> index 38d732808..842bcee70 100644
>> --- a/northd/en-global-config.h
>> +++ b/northd/en-global-config.h
>> @@ -20,6 +20,7 @@ struct chassis_features {
>>      bool fdb_timestamp;
>>      bool ls_dpg_column;
>>      bool ct_commit_nat_v2;
>> +    bool ct_commit_to_zone;
>>  };
>>
>>  struct global_config_tracked_data {
>> diff --git a/ovn-sb.xml b/ovn-sb.xml
>> index 4c26c6714..0d1f640dd 100644
>> --- a/ovn-sb.xml
>> +++ b/ovn-sb.xml
>> @@ -1432,6 +1432,30 @@
>>            </p>
>>          </dd>
>>
>> +        <dt><code>ct_commit_to_zone(dnat);</code></dt>
>> +        <dt><code>ct_commit_to_zone(snat);</code></dt>
>> +        <dd>
>> +          <p>
>> +            Commit the flow to the specific zone in the connection
>> tracker.
>> +            Similar to the <code>ct_commit</code> action, this action
>> requires
>> +            previous call to <code>ct_next</code> to initialize connection
>> +            tracking state.
>> +          </p>
>>
> 
> ct_next implies only the DNAT zone, which is not correct for SNAT.
> 
> 
>> +
>> +          <p>
>> +            If you want processing to continue in the next table, you must
>> +            execute the <code>next</code> action after
>> +            <code>ct_commit_to_zone</code>.
>> +          </p>
>>
> 
> As mentioned above, I don't think we will want to commit without proceeding.
> 
> 
>> +
>> +          <p>
>> +            Note that this action is meaningful only in the Logical Router
>> +            Datapath as the Logical Switch Datapath does not use separate
>> +            connection tracking zones. Using this action in Logical Switch
>> +            Datapath falls back to committing the flow into the switch's
>> +            default zone.

This is not accurate.  It's actually the logical port's conntrack zone.

>> +          </p>
>> +        </dd>
>>          <dt><code>ct_dnat;</code></dt>
>>          <dt><code>ct_dnat(<var>IP</var>);</code></dt>
>>          <dd>
>> diff --git a/tests/ovn.at b/tests/ovn.at
>> index c8cc1d37f..cbb303459 100644
>> --- a/tests/ovn.at
>> +++ b/tests/ovn.at
>> @@ -1316,6 +1316,22 @@ ct_commit {
>> ct_label=0x181716151413121110090807060504030201; };
>>  ct_commit { ip4.dst = 192.168.0.1; };
>>      Field ip4.dst is not modifiable.
>>
>> +# ct_commit_to_zone
>> +ct_commit_to_zone(dnat);
>> +    encodes as ct(commit,zone=NXM_NX_REG13[[0..15]])
>> +    has prereqs ip
>> +ct_commit_to_zone(dnat);
>>
> 
> s/dnat/snat
> 
> 
>> +    encodes as ct(commit,zone=NXM_NX_REG13[[0..15]])
>> +    has prereqs ip
>> +ct_commit_to_zone;
>> +    Syntax error at `;' expecting `('.
>> +ct_commit_to_zone();
>> +    Syntax error at `)' expecting parameter 'dnat' or 'snat'.
>> +ct_commit_to_zone(foo);
>> +    Syntax error at `foo' expecting parameter 'dnat' or 'snat'.
>> +ct_commit_to_zone(dnat;
>> +    Syntax error at `;' expecting `)'.
>> +
>>  # Legact ct_commit_v1 action.
>>  ct_commit();
>>      Syntax error at `(' expecting `;'.
>> diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
>> index 5e55fbbcc..554682cd0 100644
>> --- a/utilities/ovn-trace.c
>> +++ b/utilities/ovn-trace.c
>> @@ -3107,6 +3107,7 @@ trace_actions(const struct ovnact *ovnacts, size_t
>> ovnacts_len,
>>              execute_ct_next(ovnact_get_CT_NEXT(a), dp, uflow, pipeline,
>> super);
>>              break;
>>
>> +        case OVNACT_CT_COMMIT_TO_ZONE:
>>          case OVNACT_CT_COMMIT_V2:
>>              /* Nothing to do. */
>>              break;
>> --
>> 2.40.1
>>
>>
> Thanks,
> Ales
> 

Regards,
Dumitru

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to