[ovs-dev] [PATCH ovn v2 1/2] actions: Add new actions - ct_dnat_in_czone and ct_snat_in_czone.

Mark Michelson mmichels at redhat.com
Thu Nov 18 21:37:37 UTC 2021


Acked-by: Mark Michelson <mmichels at redhat.com>

On 11/18/21 13:13, numans at ovn.org wrote:
> From: Numan Siddique <numans at ovn.org>
> 
> These actions are very similar to ct_dnat and ct_snat respectively
> with one difference.  These new actions use the same zone id
> for natting.  Upcoming patch will make use of these actions.
> 
> Signed-off-by: Numan Siddique <numans at ovn.org>
> ---
> 
> v1 -> v2
> ----
>   * No changes.
> 
>   include/ovn/actions.h        |  2 ++
>   include/ovn/logical-fields.h |  2 ++
>   lib/actions.c                | 59 +++++++++++++++++++++++++-----
>   ovn-sb.xml                   | 44 +++++++++++++++++++++++
>   tests/ovn.at                 | 69 ++++++++++++++++++++++++++++++++++++
>   utilities/ovn-trace.c        | 18 ++++++++--
>   6 files changed, 184 insertions(+), 10 deletions(-)
> 
> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> index f023a37b9..ede5eb93c 100644
> --- a/include/ovn/actions.h
> +++ b/include/ovn/actions.h
> @@ -66,6 +66,8 @@ struct ovn_extend_table;
>       OVNACT(CT_COMMIT_V2,      ovnact_nest)            \
>       OVNACT(CT_DNAT,           ovnact_ct_nat)          \
>       OVNACT(CT_SNAT,           ovnact_ct_nat)          \
> +    OVNACT(CT_DNAT_IN_CZONE,  ovnact_ct_nat)          \
> +    OVNACT(CT_SNAT_IN_CZONE,  ovnact_ct_nat)          \
>       OVNACT(CT_LB,             ovnact_ct_lb)           \
>       OVNACT(SELECT,            ovnact_select)          \
>       OVNACT(CT_CLEAR,          ovnact_null)            \
> diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
> index ef97117b9..c9675f81c 100644
> --- a/include/ovn/logical-fields.h
> +++ b/include/ovn/logical-fields.h
> @@ -36,6 +36,8 @@ enum ovn_controller_event {
>                                          * (32 bits). */
>   #define MFF_LOG_SNAT_ZONE  MFF_REG12  /* conntrack snat zone for gateway router
>                                          * (32 bits). */
> +#define MFF_LOG_NAT_ZONE   MFF_LOG_DNAT_ZONE /* conntrack zone for both snat
> +                                              * and dnat. */
>   #define MFF_LOG_CT_ZONE    MFF_REG13  /* Logical conntrack zone for lports
>                                          * (32 bits). */
>   #define MFF_LOG_INPORT     MFF_REG14  /* Logical input port (32 bits). */
> diff --git a/lib/actions.c b/lib/actions.c
> index 7cf6be308..6b9a426ae 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -917,6 +917,20 @@ parse_CT_SNAT(struct action_context *ctx)
>       parse_ct_nat(ctx, "ct_snat", ovnact_put_CT_SNAT(ctx->ovnacts));
>   }
>   
> +static void
> +parse_CT_DNAT_IN_CZONE(struct action_context *ctx)
> +{
> +    parse_ct_nat(ctx, "ct_dnat_in_czone",
> +                 ovnact_put_CT_DNAT_IN_CZONE(ctx->ovnacts));
> +}
> +
> +static void
> +parse_CT_SNAT_IN_CZONE(struct action_context *ctx)
> +{
> +    parse_ct_nat(ctx, "ct_snat_in_czone",
> +                 ovnact_put_CT_SNAT_IN_CZONE(ctx->ovnacts));
> +}
> +
>   static void
>   format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s)
>   {
> @@ -954,21 +968,30 @@ format_CT_SNAT(const struct ovnact_ct_nat *cn, struct ds *s)
>       format_ct_nat(cn, "ct_snat", s);
>   }
>   
> +static void
> +format_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s)
> +{
> +    format_ct_nat(cn, "ct_dnat_in_czone", s);
> +}
> +
> +static void
> +format_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn, struct ds *s)
> +{
> +    format_ct_nat(cn, "ct_snat_in_czone", s);
> +}
> +
>   static void
>   encode_ct_nat(const struct ovnact_ct_nat *cn,
>                 const struct ovnact_encode_params *ep,
> -              bool snat, struct ofpbuf *ofpacts)
> +              bool snat, enum mf_field_id zone_src,
> +              struct ofpbuf *ofpacts)
>   {
>       const size_t ct_offset = ofpacts->size;
>       ofpbuf_pull(ofpacts, ct_offset);
>   
>       struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
>       ct->recirc_table = cn->ltable + first_ptable(ep, ep->pipeline);
> -    if (snat) {
> -        ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE);
> -    } else {
> -        ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE);
> -    }
> +    ct->zone_src.field = mf_from_id(zone_src);
>       ct->zone_src.ofs = 0;
>       ct->zone_src.n_bits = 16;
>       ct->flags = 0;
> @@ -1020,7 +1043,7 @@ encode_CT_DNAT(const struct ovnact_ct_nat *cn,
>                  const struct ovnact_encode_params *ep,
>                  struct ofpbuf *ofpacts)
>   {
> -    encode_ct_nat(cn, ep, false, ofpacts);
> +    encode_ct_nat(cn, ep, false, MFF_LOG_DNAT_ZONE, ofpacts);
>   }
>   
>   static void
> @@ -1028,7 +1051,23 @@ encode_CT_SNAT(const struct ovnact_ct_nat *cn,
>                  const struct ovnact_encode_params *ep,
>                  struct ofpbuf *ofpacts)
>   {
> -    encode_ct_nat(cn, ep, true, ofpacts);
> +    encode_ct_nat(cn, ep, true, MFF_LOG_SNAT_ZONE, ofpacts);
> +}
> +
> +static void
> +encode_CT_DNAT_IN_CZONE(const struct ovnact_ct_nat *cn,
> +                        const struct ovnact_encode_params *ep,
> +                        struct ofpbuf *ofpacts)
> +{
> +    encode_ct_nat(cn, ep, false, MFF_LOG_NAT_ZONE, ofpacts);
> +}
> +
> +static void
> +encode_CT_SNAT_IN_CZONE(const struct ovnact_ct_nat *cn,
> +                        const struct ovnact_encode_params *ep,
> +                        struct ofpbuf *ofpacts)
> +{
> +    encode_ct_nat(cn, ep, true, MFF_LOG_NAT_ZONE, ofpacts);
>   }
>   
>   static void
> @@ -4017,6 +4056,10 @@ parse_action(struct action_context *ctx)
>           parse_CT_DNAT(ctx);
>       } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
>           parse_CT_SNAT(ctx);
> +    } else if (lexer_match_id(ctx->lexer, "ct_dnat_in_czone")) {
> +        parse_CT_DNAT_IN_CZONE(ctx);
> +    } else if (lexer_match_id(ctx->lexer, "ct_snat_in_czone")) {
> +        parse_CT_SNAT_IN_CZONE(ctx);
>       } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
>           parse_ct_lb_action(ctx);
>       } else if (lexer_match_id(ctx->lexer, "ct_clear")) {
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 150051f26..9ddacdf09 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -1383,6 +1383,50 @@
>             </p>
>           </dd>
>   
> +        <dt><code>ct_dnat_in_czone;</code></dt>
> +        <dt><code>ct_dnat_in_czone(<var>IP</var>);</code></dt>
> +        <dd>
> +          <p>
> +            <code>ct_dnat_in_czone</code> sends the packet through the common
> +            NAT zone (used for both DNAT and SNAT) in connection tracking table
> +            to unDNAT any packet that was DNATed in the opposite direction.
> +            The packet is then automatically sent to to the next tables as if
> +            followed by <code>next;</code> action.  The next tables will see
> +            the changes in the packet caused by the connection tracker.
> +          </p>
> +          <p>
> +            <code>ct_dnat_in_czone(<var>IP</var>)</code> sends the packet
> +            through the common NAT zone to change the destination IP address
> +            of the packet to the one provided inside the parentheses and
> +            commits the connection.  The packet is then automatically sent to
> +            the next tables as if followed by <code>next;</code> action.  The
> +            next tables will see the changes in the packet caused by the
> +            connection tracker.
> +          </p>
> +        </dd>
> +
> +        <dt><code>ct_snat_in_czone;</code></dt>
> +        <dt><code>ct_snat_in_czone(<var>IP</var>);</code></dt>
> +        <dd>
> +          <p>
> +            <code>ct_snat_in_czone</code> sends the packet through the common
> +            NAT zone to unSNAT any packet that was SNATed in the opposite
> +            direction.  The packet is automatically sent to the next tables as
> +            if followed by the <code>next;</code> action.   The next tables
> +            will see the changes in the packet caused by the connection
> +            tracker.
> +          </p>
> +          <p>
> +            <code>ct_snat_in_czone(<var>IP</var>)</code> sends the packet\
> +            through the common NAT zone to change the source IP address of
> +            the packet to the one provided inside the parenthesis and commits
> +            the connection.  The packet is then automatically sent to the next
> +            tables as if followed by <code>next;</code> action.  The next
> +            tables will see the changes in the packet caused by the connection
> +            tracker.
> +          </p>
> +        </dd>
> +
>           <dt><code>ct_clear;</code></dt>
>           <dd>
>             Clears connection tracking state.
> diff --git a/tests/ovn.at b/tests/ovn.at
> index ae832918c..0d606b42f 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1193,6 +1193,40 @@ ct_dnat(192.168.1.2, 1000);
>   ct_dnat(192.168.1.2, 1000-100);
>       Syntax error at `100' range high should be greater than range low.
>   
> +# ct_dnat_in_czone
> +ct_dnat_in_czone;
> +    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
> +    has prereqs ip
> +ct_dnat_in_czone(192.168.1.2);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2))
> +    has prereqs ip
> +ct_dnat_in_czone(fd11::2);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=fd11::2))
> +    has prereqs ip
> +ct_dnat_in_czone(192.168.1.2, 1-3000);
> +    formats as ct_dnat_in_czone(192.168.1.2,1-3000);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1-3000))
> +    has prereqs ip
> +
> +ct_dnat_in_czone(192.168.1.2, 192.168.1.3);
> +    Syntax error at `192.168.1.3' expecting Integer for port range.
> +ct_dnat_in_czone(foo);
> +    Syntax error at `foo' expecting IPv4 or IPv6 address.
> +ct_dnat_in_czone(foo, bar);
> +    Syntax error at `foo' expecting IPv4 or IPv6 address.
> +ct_dnat_in_czone();
> +    Syntax error at `)' expecting IPv4 or IPv6 address.
> +ct_dnat_in_czone(192.168.1.2, foo);
> +    Syntax error at `foo' expecting Integer for port range.
> +ct_dnat_in_czone(192.168.1.2, 1000-foo);
> +    Syntax error at `foo' expecting Integer for port range.
> +ct_dnat_in_czone(192.168.1.2, 1000);
> +    formats as ct_dnat_in_czone(192.168.1.2,1000);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=192.168.1.2:1000))
> +    has prereqs ip
> +ct_dnat_in_czone(192.168.1.2, 1000-100);
> +    Syntax error at `100' range high should be greater than range low.
> +
>   # ct_snat
>   ct_snat;
>       encodes as ct(table=19,zone=NXM_NX_REG12[0..15],nat)
> @@ -1226,6 +1260,41 @@ ct_snat(192.168.1.2, 1000);
>       has prereqs ip
>   ct_snat(192.168.1.2, 1000-100);
>       Syntax error at `100' range high should be greater than range low.
> +
> +# ct_snat_in_czone
> +ct_snat_in_czone;
> +    encodes as ct(table=19,zone=NXM_NX_REG11[0..15],nat)
> +    has prereqs ip
> +ct_snat_in_czone(192.168.1.2);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2))
> +    has prereqs ip
> +ct_snat_in_czone(fd11::2);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=fd11::2))
> +    has prereqs ip
> +ct_snat_in_czone(192.168.1.2, 1-3000);
> +    formats as ct_snat_in_czone(192.168.1.2,1-3000);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1-3000))
> +    has prereqs ip
> +
> +ct_snat_in_czone(192.168.1.2, 192.168.1.3);
> +    Syntax error at `192.168.1.3' expecting Integer for port range.
> +ct_snat_in_czone(foo);
> +    Syntax error at `foo' expecting IPv4 or IPv6 address.
> +ct_snat_in_czone(foo, bar);
> +    Syntax error at `foo' expecting IPv4 or IPv6 address.
> +ct_snat_in_czone();
> +    Syntax error at `)' expecting IPv4 or IPv6 address.
> +ct_snat_in_czone(192.168.1.2, foo);
> +    Syntax error at `foo' expecting Integer for port range.
> +ct_snat_in_czone(192.168.1.2, 1000-foo);
> +    Syntax error at `foo' expecting Integer for port range.
> +ct_snat_in_czone(192.168.1.2, 1000);
> +    formats as ct_snat_in_czone(192.168.1.2,1000);
> +    encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(src=192.168.1.2:1000))
> +    has prereqs ip
> +ct_snat_in_czone(192.168.1.2, 1000-100);
> +    Syntax error at `100' range high should be greater than range low.
> +
>   # ct_clear
>   ct_clear;
>       encodes as ct_clear
> diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
> index 65a1822ea..617ad834c 100644
> --- a/utilities/ovn-trace.c
> +++ b/utilities/ovn-trace.c
> @@ -2286,7 +2286,10 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat,
>                  const struct ovntrace_datapath *dp, struct flow *uflow,
>                  enum ovnact_pipeline pipeline, struct ovs_list *super)
>   {
> -    bool is_dst = ct_nat->ovnact.type == OVNACT_CT_DNAT;
> +    bool is_dst = (ct_nat->ovnact.type == OVNACT_CT_DNAT ||
> +                   ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE);
> +    bool nat_in_czone = (ct_nat->ovnact.type == OVNACT_CT_DNAT_IN_CZONE ||
> +                         ct_nat->ovnact.type == OVNACT_CT_SNAT_IN_CZONE);
>       if (!is_dst && dp->has_local_l3gateway && ct_nat->family == AF_UNSPEC) {
>           /* "ct_snat;" has no visible effect in a gateway router. */
>           return;
> @@ -2297,7 +2300,8 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat,
>        * and figure out the changes if any. */
>       struct flow ct_flow = *uflow;
>       struct ds s = DS_EMPTY_INITIALIZER;
> -    ds_put_format(&s, "ct_%cnat", direction[0]);
> +    ds_put_format(&s, "ct_%cnat%s", direction[0],
> +                  nat_in_czone ? "in_czone" : "");
>       if (ct_nat->family != AF_UNSPEC) {
>           if (ct_nat->family == AF_INET) {
>               ds_put_format(&s, "(ip4.%s="IP_FMT")", direction,
> @@ -2610,6 +2614,16 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
>               execute_ct_nat(ovnact_get_CT_SNAT(a), dp, uflow, pipeline, super);
>               break;
>   
> +        case OVNACT_CT_DNAT_IN_CZONE:
> +            execute_ct_nat(ovnact_get_CT_DNAT_IN_CZONE(a), dp, uflow,
> +                           pipeline, super);
> +            break;
> +
> +        case OVNACT_CT_SNAT_IN_CZONE:
> +            execute_ct_nat(ovnact_get_CT_SNAT_IN_CZONE(a), dp, uflow,
> +                           pipeline, super);
> +            break;
> +
>           case OVNACT_CT_LB:
>               execute_ct_lb(ovnact_get_CT_LB(a), dp, uflow, pipeline, super);
>               break;
> 



More information about the dev mailing list