From 67b9788bb5c4de9a22f52ebfaee2701c804cd9e8 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Fri, 25 Oct 2019 17:20:32 -0400 Subject: [PATCH 2/5] actions: Add IPv6 support to lflow NAT actions Signed-off-by: Russell Bryant Acked-by: Numan Siddique --- include/ovn/actions.h | 6 +++++- ovn/lib/actions.c | 35 +++++++++++++++++++++++++++-------- ovn/utilities/ovn-trace.c | 15 ++++++++++----- tests/ovn.at | 18 ++++++++++++------ 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 4e2f4d28d..f4997e9c9 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -225,7 +225,11 @@ struct ovnact_ct_commit { /* OVNACT_CT_DNAT, OVNACT_CT_SNAT. */ struct ovnact_ct_nat { struct ovnact ovnact; - ovs_be32 ip; + int family; + union { + struct in6_addr ipv6; + ovs_be32 ipv4; + }; uint8_t ltable; /* Logical table ID of next table. */ }; diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 45f8715cf..7857f658a 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -755,11 +755,18 @@ parse_ct_nat(struct action_context *ctx, const char *name, if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { if (ctx->lexer->token.type != LEX_T_INTEGER - || ctx->lexer->token.format != LEX_F_IPV4) { - lexer_syntax_error(ctx->lexer, "expecting IPv4 address"); + || (ctx->lexer->token.format != LEX_F_IPV4 + && ctx->lexer->token.format != LEX_F_IPV6)) { + lexer_syntax_error(ctx->lexer, "expecting IPv4 or IPv6 address"); return; } - cn->ip = ctx->lexer->token.value.ipv4; + if (ctx->lexer->token.format == LEX_F_IPV4) { + cn->family = AF_INET; + cn->ipv4 = ctx->lexer->token.value.ipv4; + } else if (ctx->lexer->token.format == LEX_F_IPV6) { + cn->family = AF_INET6; + cn->ipv6 = ctx->lexer->token.value.ipv6; + } lexer_get(ctx->lexer); if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) { @@ -784,8 +791,12 @@ static void format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s) { ds_put_cstr(s, name); - if (cn->ip) { - ds_put_format(s, "("IP_FMT")", IP_ARGS(cn->ip)); + if (cn->family == AF_INET) { + ds_put_format(s, "("IP_FMT")", IP_ARGS(cn->ipv4)); + } else if (cn->family == AF_INET6) { + ds_put_char(s, '('); + ipv6_format_addr(&cn->ipv6, s); + ds_put_char(s, ')'); } ds_put_char(s, ';'); } @@ -831,9 +842,17 @@ encode_ct_nat(const struct ovnact_ct_nat *cn, nat->flags = 0; nat->range_af = AF_UNSPEC; - if (cn->ip) { + if (cn->family == AF_INET) { nat->range_af = AF_INET; - nat->range.addr.ipv4.min = cn->ip; + nat->range.addr.ipv4.min = cn->ipv4; + if (snat) { + nat->flags |= NX_NAT_F_SRC; + } else { + nat->flags |= NX_NAT_F_DST; + } + } else if (cn->family == AF_INET6) { + nat->range_af = AF_INET6; + nat->range.addr.ipv6.min = cn->ipv6; if (snat) { nat->flags |= NX_NAT_F_SRC; } else { @@ -843,7 +862,7 @@ encode_ct_nat(const struct ovnact_ct_nat *cn, ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset); ct = ofpacts->header; - if (cn->ip) { + if (cn->family == AF_INET || cn->family == AF_INET6) { ct->flags |= NX_CT_F_COMMIT; } ofpact_finish(ofpacts, &ct->ofpact); diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 103b25891..7ed4a3842 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1886,7 +1886,7 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, enum ovnact_pipeline pipeline, struct ovs_list *super) { bool is_dst = ct_nat->ovnact.type == OVNACT_CT_DNAT; - if (!is_dst && dp->has_local_l3gateway && !ct_nat->ip) { + if (!is_dst && dp->has_local_l3gateway && ct_nat->family == AF_UNSPEC) { /* "ct_snat;" has no visible effect in a gateway router. */ return; } @@ -1897,10 +1897,15 @@ execute_ct_nat(const struct ovnact_ct_nat *ct_nat, struct flow ct_flow = *uflow; struct ds s = DS_EMPTY_INITIALIZER; ds_put_format(&s, "ct_%cnat", direction[0]); - if (ct_nat->ip) { - ds_put_format(&s, "(ip4.%s="IP_FMT")", direction, IP_ARGS(ct_nat->ip)); - ovs_be32 *ip = is_dst ? &ct_flow.nw_dst : &ct_flow.nw_src; - *ip = ct_nat->ip; + if (ct_nat->family != AF_UNSPEC) { + if (ct_nat->family == AF_INET) { + ds_put_format(&s, "(ip4.%s="IP_FMT")", direction, + IP_ARGS(ct_nat->ipv4)); + } else { + ds_put_format(&s, "(ip6.%s=", direction); + ipv6_format_addr(&ct_nat->ipv6, &s); + ds_put_char(&s, ')'); + } uint8_t state = is_dst ? CS_DST_NAT : CS_SRC_NAT; ct_flow.ct_state |= state; diff --git a/tests/ovn.at b/tests/ovn.at index ccf6a5332..e38d14cdf 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1027,15 +1027,18 @@ ct_dnat; ct_dnat(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(fd11::2); + encodes as ct(commit,table=19,zone=NXM_NX_REG11[0..15],nat(dst=fd11::2)) + has prereqs ip ct_dnat(192.168.1.2, 192.168.1.3); Syntax error at `,' expecting `)'. ct_dnat(foo); - Syntax error at `foo' expecting IPv4 address. + Syntax error at `foo' expecting IPv4 or IPv6 address. ct_dnat(foo, bar); - Syntax error at `foo' expecting IPv4 address. + Syntax error at `foo' expecting IPv4 or IPv6 address. ct_dnat(); - Syntax error at `)' expecting IPv4 address. + Syntax error at `)' expecting IPv4 or IPv6 address. # ct_snat ct_snat; @@ -1044,15 +1047,18 @@ ct_snat; ct_snat(192.168.1.2); encodes as ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=192.168.1.2)) has prereqs ip +ct_snat(fd11::2); + encodes as ct(commit,table=19,zone=NXM_NX_REG12[0..15],nat(src=fd11::2)) + has prereqs ip ct_snat(192.168.1.2, 192.168.1.3); Syntax error at `,' expecting `)'. ct_snat(foo); - Syntax error at `foo' expecting IPv4 address. + Syntax error at `foo' expecting IPv4 or IPv6 address. ct_snat(foo, bar); - Syntax error at `foo' expecting IPv4 address. + Syntax error at `foo' expecting IPv4 or IPv6 address. ct_snat(); - Syntax error at `)' expecting IPv4 address. + Syntax error at `)' expecting IPv4 or IPv6 address. # ct_clear ct_clear; -- 2.23.0