@@ -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. */
};
@@ -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);
@@ -1043,15 +1043,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;
@@ -1060,15 +1063,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;
@@ -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;
Signed-off-by: Russell Bryant <russell@ovn.org> --- include/ovn/actions.h | 6 +++++- lib/actions.c | 35 +++++++++++++++++++++++++++-------- tests/ovn.at | 18 ++++++++++++------ utilities/ovn-trace.c | 15 ++++++++++----- 4 files changed, 54 insertions(+), 20 deletions(-)