[{"id":1764713,"web_url":"http://patchwork.ozlabs.org/comment/1764713/","msgid":"<20170907151219.4107929b@beetle>","list_archive_url":null,"date":"2017-09-07T13:12:19","subject":"Re: [ovs-dev] [PATCH 2/4] ovn: Allow ct_lb actions to take IPv6\n\taddress arguments.","submitter":{"id":68710,"url":"http://patchwork.ozlabs.org/api/people/68710/","name":"Jakub Sitnicki","email":"jkbs@redhat.com"},"content":"Hi Mark,\n\nOn Wed,  6 Sep 2017 16:08:37 -0500\nMark Michelson <mmichels@redhat.com> wrote:\n\n> The ct_lb action previously assumed that any address arguments were\n> IPv4. This patch expands the parsing, formatting, and encoding of ct_lb\n> to be amenable to IPv6 addresses as well.\n> \n> Signed-off-by: Mark Michelson <mmichels@redhat.com>\n> ---\n>  include/ovn/actions.h |  4 ++-\n>  ovn/lib/actions.c     | 99 ++++++++++++++++++++++++++++++++++++++++-----------\n>  tests/ovn.at          |  8 ++++-\n>  3 files changed, 89 insertions(+), 22 deletions(-)\n> \n> diff --git a/include/ovn/actions.h b/include/ovn/actions.h\n> index 0a04af7aa..ec0063efc 100644\n> --- a/include/ovn/actions.h\n> +++ b/include/ovn/actions.h\n> @@ -200,7 +200,9 @@ struct ovnact_ct_nat {\n>  };\n>  \n>  struct ovnact_ct_lb_dst {\n> -    ovs_be32 ip;\n> +    int family;\n> +    struct in6_addr ipv6;\n> +    ovs_be32 ipv4;\n>      uint16_t port;\n>  };\n>  \n\nDo you think it would make sense to put 'ipv6' and 'ipv4' in an\nanonymous union to emphasize the fact that we're using only one or the\nother? Similar to how it was done in flow_hash_symmetric_l4():\n\nuint32_t\nflow_hash_symmetric_l4(const struct flow *flow, uint32_t basis)\n{\n    struct {\n        union {\n            ovs_be32 ipv4_addr;\n            struct in6_addr ipv6_addr;\n        };\n        ovs_be16 eth_type;\n        ovs_be16 vlan_tci;\n        ovs_be16 tp_port;\n        struct eth_addr eth_addr;\n        uint8_t ip_proto;\n    } fields;\n    /* ... */\n}\n\n-Jakub\n   \n> diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c\n> index d0d73b69c..8d60529cb 100644\n> --- a/ovn/lib/actions.c\n> +++ b/ovn/lib/actions.c\n> @@ -883,23 +883,63 @@ parse_ct_lb_action(struct action_context *ctx)\n>  \n>      if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {\n>          while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {\n> -            if (ctx->lexer->token.type != LEX_T_INTEGER\n> -                || mf_subvalue_width(&ctx->lexer->token.value) > 32) {\n> -                free(dsts);\n> -                lexer_syntax_error(ctx->lexer, \"expecting IPv4 address\");\n> -                return;\n> -            }\n> +            struct ovnact_ct_lb_dst dst;\n> +            if (lexer_match(ctx->lexer, LEX_T_LSQUARE)) {\n> +                /* IPv6 address and port */\n> +                if (ctx->lexer->token.type != LEX_T_INTEGER\n> +                    || ctx->lexer->token.format != LEX_F_IPV6) {\n> +                    free(dsts);\n> +                    lexer_syntax_error(ctx->lexer, \"expecting IPv6 address\");\n> +                    return;\n> +                }\n> +                dst.family = AF_INET6;\n> +                dst.ipv6 = ctx->lexer->token.value.ipv6;\n>  \n> -            /* Parse IP. */\n> -            ovs_be32 ip = ctx->lexer->token.value.ipv4;\n> -            lexer_get(ctx->lexer);\n> +                lexer_get(ctx->lexer);\n> +                if (!lexer_match(ctx->lexer, LEX_T_RSQUARE)) {\n> +                    free(dsts);\n> +                    lexer_syntax_error(ctx->lexer, \"no closing square \"\n> +                                                   \"bracket\");\n> +                    return;\n> +                }\n> +                dst.port = 0;\n> +                if (lexer_match(ctx->lexer, LEX_T_COLON)\n> +                    && !action_parse_port(ctx, &dst.port)) {\n> +                    free(dsts);\n> +                    return;\n> +                }\n> +            } else {\n> +                if (ctx->lexer->token.type != LEX_T_INTEGER\n> +                    || (ctx->lexer->token.format != LEX_F_IPV4\n> +                    && ctx->lexer->token.format != LEX_F_IPV6)) {\n> +                    free(dsts);\n> +                    lexer_syntax_error(ctx->lexer, \"expecting IP address\");\n> +                    return;\n> +                }\n>  \n> -            /* Parse optional port. */\n> -            uint16_t port = 0;\n> -            if (lexer_match(ctx->lexer, LEX_T_COLON)\n> -                && !action_parse_port(ctx, &port)) {\n> -                free(dsts);\n> -                return;\n> +                /* Parse IP. */\n> +                struct ovnact_ct_lb_dst dst;\n> +                if (ctx->lexer->token.format == LEX_F_IPV4) {\n> +                    dst.family = AF_INET;\n> +                    dst.ipv4 = ctx->lexer->token.value.ipv4;\n> +                } else {\n> +                    dst.family = AF_INET6;\n> +                    dst.ipv6 = ctx->lexer->token.value.ipv6;\n> +                }\n> +\n> +                lexer_get(ctx->lexer);\n> +                dst.port = 0;\n> +                if (lexer_match(ctx->lexer, LEX_T_COLON)) {\n> +                    if (dst.family == AF_INET6) {\n> +                        free(dsts);\n> +                        lexer_syntax_error(ctx->lexer, \"IPv6 address needs \"\n> +                                \"square brackets if port is included\");\n> +                        return;\n> +                    } else if (!action_parse_port(ctx, &dst.port)) {\n> +                        free(dsts);\n> +                        return;\n> +                    }\n> +                }\n>              }\n>              lexer_match(ctx->lexer, LEX_T_COMMA);\n>  \n> @@ -907,7 +947,7 @@ parse_ct_lb_action(struct action_context *ctx)\n>              if (n_dsts >= allocated_dsts) {\n>                  dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);\n>              }\n> -            dsts[n_dsts++] = (struct ovnact_ct_lb_dst) { ip, port };\n> +            dsts[n_dsts++] = dst;\n>          }\n>      }\n>  \n> @@ -929,9 +969,19 @@ format_CT_LB(const struct ovnact_ct_lb *cl, struct ds *s)\n>              }\n>  \n>              const struct ovnact_ct_lb_dst *dst = &cl->dsts[i];\n> -            ds_put_format(s, IP_FMT, IP_ARGS(dst->ip));\n> -            if (dst->port) {\n> -                ds_put_format(s, \":%\"PRIu16, dst->port);\n> +            if (dst->family == AF_INET) {\n> +                ds_put_format(s, IP_FMT, IP_ARGS(dst->ipv4));\n> +                if (dst->port) {\n> +                    ds_put_format(s, \":%\"PRIu16, dst->port);\n> +                }\n> +            } else {\n> +                if (dst->port) {\n> +                    ds_put_char(s, '[');\n> +                }\n> +                ipv6_format_addr(&dst->ipv6, s);\n> +                if (dst->port) {\n> +                    ds_put_format(s, \"]:%\"PRIu16, dst->port);\n> +                }\n>              }\n>          }\n>          ds_put_char(s, ')');\n> @@ -991,8 +1041,17 @@ encode_CT_LB(const struct ovnact_ct_lb *cl,\n>      BUILD_ASSERT(MFF_LOG_DNAT_ZONE < MFF_REG0 + FLOW_N_REGS);\n>      for (size_t bucket_id = 0; bucket_id < cl->n_dsts; bucket_id++) {\n>          const struct ovnact_ct_lb_dst *dst = &cl->dsts[bucket_id];\n> +        char ip_addr[INET6_ADDRSTRLEN];\n> +        if (dst->family == AF_INET) {\n> +            inet_ntop(AF_INET, &dst->ipv4, ip_addr, sizeof ip_addr);\n> +        } else {\n> +            inet_ntop(AF_INET6, &dst->ipv6, ip_addr, sizeof ip_addr);\n> +        }\n>          ds_put_format(&ds, \",bucket=bucket_id=%\"PRIuSIZE\",weight:100,actions=\"\n> -                      \"ct(nat(dst=\"IP_FMT, bucket_id, IP_ARGS(dst->ip));\n> +                      \"ct(nat(dst=%s%s%s\", bucket_id,\n> +                      dst->family == AF_INET6 && dst->port ? \"[\" : \"\",\n> +                      ip_addr,\n> +                      dst->family == AF_INET6 && dst->port ? \"]\" : \"\");\n>          if (dst->port) {\n>              ds_put_format(&ds, \":%\"PRIu16, dst->port);\n>          }\n> diff --git a/tests/ovn.at b/tests/ovn.at\n> index fb9fc7352..9118f2839 100644\n> --- a/tests/ovn.at\n> +++ b/tests/ovn.at\n> @@ -793,13 +793,19 @@ ct_lb(192.168.1.2, 192.168.1.3, );\n>      formats as ct_lb(192.168.1.2, 192.168.1.3);\n>      encodes as group:2\n>      has prereqs ip\n> +ct_lb(fd0f::2, fd0f::3, );\n> +    formats as ct_lb(fd0f::2, fd0f::3);\n> +    encodes as group:3\n> +    has prereqs ip\n>  \n>  ct_lb(192.168.1.2:);\n>      Syntax error at `)' expecting port number.\n>  ct_lb(192.168.1.2:123456);\n>      Syntax error at `123456' expecting port number.\n>  ct_lb(foo);\n> -    Syntax error at `foo' expecting IPv4 address.\n> +    Syntax error at `foo' expecting IP address.\n> +ct_lb([192.168.1.2]);\n> +    Syntax error at `192.168.1.2' expecting IPv6 address.\n>  \n>  # ct_next\n>  ct_next;","headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","ovs-dev@mail.linuxfoundation.org"],"Authentication-Results":"ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=openvswitch.org\n\t(client-ip=140.211.169.12; helo=mail.linuxfoundation.org;\n\tenvelope-from=ovs-dev-bounces@openvswitch.org;\n\treceiver=<UNKNOWN>)","Received":["from mail.linuxfoundation.org (mail.linuxfoundation.org\n\t[140.211.169.12])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xp18H2B7dz9sPk\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu,  7 Sep 2017 23:12:30 +1000 (AEST)","from mail.linux-foundation.org (localhost [127.0.0.1])\n\tby mail.linuxfoundation.org (Postfix) with ESMTP id A6BFEA67;\n\tThu,  7 Sep 2017 13:12:26 +0000 (UTC)","from smtp1.linuxfoundation.org (smtp1.linux-foundation.org\n\t[172.17.192.35])\n\tby mail.linuxfoundation.org (Postfix) with ESMTPS id 92C21A49\n\tfor <dev@openvswitch.org>; Thu,  7 Sep 2017 13:12:25 +0000 (UTC)","from mail-wr0-f175.google.com (mail-wr0-f175.google.com\n\t[209.85.128.175])\n\tby smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9B3B2E0\n\tfor <dev@openvswitch.org>; Thu,  7 Sep 2017 13:12:24 +0000 (UTC)","by mail-wr0-f175.google.com with SMTP id o42so8853466wrb.3\n\tfor <dev@openvswitch.org>; Thu, 07 Sep 2017 06:12:24 -0700 (PDT)","from beetle (red-hat-inc.vlan404.asr1.mad1.gblx.net.\n\t[64.215.113.190]) by smtp.gmail.com with ESMTPSA id\n\tl72sm616171wmi.1.2017.09.07.06.12.22\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tThu, 07 Sep 2017 06:12:22 -0700 (PDT)"],"X-Greylist":"whitelisted by SQLgrey-1.7.6","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:in-reply-to\n\t:references:mime-version:content-transfer-encoding;\n\tbh=AhdoM5736zVizKA/B6L+UPMwbNKB1UVayI6zsmmjHpg=;\n\tb=MUsFrI8lNBLWplFIRG47dZrFItjvK6nA8THiUqEleVcq+aQB4vLNT5lveSIj4GSv1+\n\tIBKnukUG10m0+PvTjFTltYELpdwWbB4vQBK9GgEC1MwqmBTC9G35v1A0tc1J0ForhVa7\n\t7Egzs3PXUvLsHrso0N1XnCepbONKgX4MpTNtqPw2xMYSB6O7cmmycerVduoPUC93SjRA\n\tGs6ZtasdgkiaxcZxP5DyC2xrqRLChHRhCPmdYaDN3NHBkuDrXWP2pc+Dcf7kD+SUqYnX\n\toOe6dvvB+McWho1xmQeKAOmHe9hqbZRs5usmRIG1d+EMWc5Gjz8MZZ7HwO4nQsAEFUrV\n\tT6/Q==","X-Gm-Message-State":"AHPjjUgGk1NFJz+vfpvFpHDEF/1Q7yeOu0LDOElIM6Y3rDCjzEYMwczX\n\tl022Xrfsj6GRuvYM","X-Google-Smtp-Source":"ADKCNb5Q+TWJ+Y8cXCxukekaokd2cbfGdBwUVkvfy2/Vz/hcC5zyOv8pjM9C/b/KFzi6K9SORzbgCA==","X-Received":"by 10.223.164.206 with SMTP id h14mr2287721wrb.221.1504789942983;\n\tThu, 07 Sep 2017 06:12:22 -0700 (PDT)","Date":"Thu, 7 Sep 2017 15:12:19 +0200","From":"Jakub Sitnicki <jkbs@redhat.com>","To":"Mark Michelson <mmichels@redhat.com>","Message-ID":"<20170907151219.4107929b@beetle>","In-Reply-To":"<20170906210839.26091-3-mmichels@redhat.com>","References":"<20170906210839.26091-1-mmichels@redhat.com>\n\t<20170906210839.26091-3-mmichels@redhat.com>","X-Mailer":"Claws Mail 3.14.1 (GTK+ 2.24.31; x86_64-redhat-linux-gnu)","MIME-Version":"1.0","X-Spam-Status":"No, score=0.5 required=5.0 tests=RCVD_IN_DNSWL_NONE,\n\tRCVD_IN_SORBS_SPAM autolearn=disabled version=3.3.1","X-Spam-Checker-Version":"SpamAssassin 3.3.1 (2010-03-16) on\n\tsmtp1.linux-foundation.org","Cc":"dev@openvswitch.org","Subject":"Re: [ovs-dev] [PATCH 2/4] ovn: Allow ct_lb actions to take IPv6\n\taddress arguments.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.12","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"ovs-dev-bounces@openvswitch.org","Errors-To":"ovs-dev-bounces@openvswitch.org"}},{"id":1764716,"web_url":"http://patchwork.ozlabs.org/comment/1764716/","msgid":"<CAA1+qOOXoQanJotFLBENkLa1M=sEsmTzvpdZCHUOVHB8O7ythA@mail.gmail.com>","list_archive_url":null,"date":"2017-09-07T13:16:38","subject":"Re: [ovs-dev] [PATCH 2/4] ovn: Allow ct_lb actions to take IPv6\n\taddress arguments.","submitter":{"id":71978,"url":"http://patchwork.ozlabs.org/api/people/71978/","name":"Mark Michelson","email":"mmichels@redhat.com"},"content":"On Thu, Sep 7, 2017 at 8:12 AM Jakub Sitnicki <jkbs@redhat.com> wrote:\n\n> Hi Mark,\n>\n> On Wed,  6 Sep 2017 16:08:37 -0500\n> Mark Michelson <mmichels@redhat.com> wrote:\n>\n> > The ct_lb action previously assumed that any address arguments were\n> > IPv4. This patch expands the parsing, formatting, and encoding of ct_lb\n> > to be amenable to IPv6 addresses as well.\n> >\n> > Signed-off-by: Mark Michelson <mmichels@redhat.com>\n> > ---\n> >  include/ovn/actions.h |  4 ++-\n> >  ovn/lib/actions.c     | 99\n> ++++++++++++++++++++++++++++++++++++++++-----------\n> >  tests/ovn.at          |  8 ++++-\n> >  3 files changed, 89 insertions(+), 22 deletions(-)\n> >\n> > diff --git a/include/ovn/actions.h b/include/ovn/actions.h\n> > index 0a04af7aa..ec0063efc 100644\n> > --- a/include/ovn/actions.h\n> > +++ b/include/ovn/actions.h\n> > @@ -200,7 +200,9 @@ struct ovnact_ct_nat {\n> >  };\n> >\n> >  struct ovnact_ct_lb_dst {\n> > -    ovs_be32 ip;\n> > +    int family;\n> > +    struct in6_addr ipv6;\n> > +    ovs_be32 ipv4;\n> >      uint16_t port;\n> >  };\n> >\n>\n> Do you think it would make sense to put 'ipv6' and 'ipv4' in an\n> anonymous union to emphasize the fact that we're using only one or the\n> other? Similar to how it was done in flow_hash_symmetric_l4():\n>\n>\nSure, I can do that. I think I'm going to wait for more feedback on the\npatchset before posting new revisions, though.\n\nThanks for giving this a look!\n\n\n\n> uint32_t\n> flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis)\n> {\n>     struct {\n>         union {\n>             ovs_be32 ipv4_addr;\n>             struct in6_addr ipv6_addr;\n>         };\n>         ovs_be16 eth_type;\n>         ovs_be16 vlan_tci;\n>         ovs_be16 tp_port;\n>         struct eth_addr eth_addr;\n>         uint8_t ip_proto;\n>     } fields;\n>     /* ... */\n> }\n>\n> -Jakub\n>\n> > diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c\n> > index d0d73b69c..8d60529cb 100644\n> > --- a/ovn/lib/actions.c\n> > +++ b/ovn/lib/actions.c\n> > @@ -883,23 +883,63 @@ parse_ct_lb_action(struct action_context *ctx)\n> >\n> >      if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {\n> >          while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {\n> > -            if (ctx->lexer->token.type != LEX_T_INTEGER\n> > -                || mf_subvalue_width(&ctx->lexer->token.value) > 32) {\n> > -                free(dsts);\n> > -                lexer_syntax_error(ctx->lexer, \"expecting IPv4\n> address\");\n> > -                return;\n> > -            }\n> > +            struct ovnact_ct_lb_dst dst;\n> > +            if (lexer_match(ctx->lexer, LEX_T_LSQUARE)) {\n> > +                /* IPv6 address and port */\n> > +                if (ctx->lexer->token.type != LEX_T_INTEGER\n> > +                    || ctx->lexer->token.format != LEX_F_IPV6) {\n> > +                    free(dsts);\n> > +                    lexer_syntax_error(ctx->lexer, \"expecting IPv6\n> address\");\n> > +                    return;\n> > +                }\n> > +                dst.family = AF_INET6;\n> > +                dst.ipv6 = ctx->lexer->token.value.ipv6;\n> >\n> > -            /* Parse IP. */\n> > -            ovs_be32 ip = ctx->lexer->token.value.ipv4;\n> > -            lexer_get(ctx->lexer);\n> > +                lexer_get(ctx->lexer);\n> > +                if (!lexer_match(ctx->lexer, LEX_T_RSQUARE)) {\n> > +                    free(dsts);\n> > +                    lexer_syntax_error(ctx->lexer, \"no closing square \"\n> > +                                                   \"bracket\");\n> > +                    return;\n> > +                }\n> > +                dst.port = 0;\n> > +                if (lexer_match(ctx->lexer, LEX_T_COLON)\n> > +                    && !action_parse_port(ctx, &dst.port)) {\n> > +                    free(dsts);\n> > +                    return;\n> > +                }\n> > +            } else {\n> > +                if (ctx->lexer->token.type != LEX_T_INTEGER\n> > +                    || (ctx->lexer->token.format != LEX_F_IPV4\n> > +                    && ctx->lexer->token.format != LEX_F_IPV6)) {\n> > +                    free(dsts);\n> > +                    lexer_syntax_error(ctx->lexer, \"expecting IP\n> address\");\n> > +                    return;\n> > +                }\n> >\n> > -            /* Parse optional port. */\n> > -            uint16_t port = 0;\n> > -            if (lexer_match(ctx->lexer, LEX_T_COLON)\n> > -                && !action_parse_port(ctx, &port)) {\n> > -                free(dsts);\n> > -                return;\n> > +                /* Parse IP. */\n> > +                struct ovnact_ct_lb_dst dst;\n> > +                if (ctx->lexer->token.format == LEX_F_IPV4) {\n> > +                    dst.family = AF_INET;\n> > +                    dst.ipv4 = ctx->lexer->token.value.ipv4;\n> > +                } else {\n> > +                    dst.family = AF_INET6;\n> > +                    dst.ipv6 = ctx->lexer->token.value.ipv6;\n> > +                }\n> > +\n> > +                lexer_get(ctx->lexer);\n> > +                dst.port = 0;\n> > +                if (lexer_match(ctx->lexer, LEX_T_COLON)) {\n> > +                    if (dst.family == AF_INET6) {\n> > +                        free(dsts);\n> > +                        lexer_syntax_error(ctx->lexer, \"IPv6 address\n> needs \"\n> > +                                \"square brackets if port is included\");\n> > +                        return;\n> > +                    } else if (!action_parse_port(ctx, &dst.port)) {\n> > +                        free(dsts);\n> > +                        return;\n> > +                    }\n> > +                }\n> >              }\n> >              lexer_match(ctx->lexer, LEX_T_COMMA);\n> >\n> > @@ -907,7 +947,7 @@ parse_ct_lb_action(struct action_context *ctx)\n> >              if (n_dsts >= allocated_dsts) {\n> >                  dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);\n> >              }\n> > -            dsts[n_dsts++] = (struct ovnact_ct_lb_dst) { ip, port };\n> > +            dsts[n_dsts++] = dst;\n> >          }\n> >      }\n> >\n> > @@ -929,9 +969,19 @@ format_CT_LB(const struct ovnact_ct_lb *cl, struct\n> ds *s)\n> >              }\n> >\n> >              const struct ovnact_ct_lb_dst *dst = &cl->dsts[i];\n> > -            ds_put_format(s, IP_FMT, IP_ARGS(dst->ip));\n> > -            if (dst->port) {\n> > -                ds_put_format(s, \":%\"PRIu16, dst->port);\n> > +            if (dst->family == AF_INET) {\n> > +                ds_put_format(s, IP_FMT, IP_ARGS(dst->ipv4));\n> > +                if (dst->port) {\n> > +                    ds_put_format(s, \":%\"PRIu16, dst->port);\n> > +                }\n> > +            } else {\n> > +                if (dst->port) {\n> > +                    ds_put_char(s, '[');\n> > +                }\n> > +                ipv6_format_addr(&dst->ipv6, s);\n> > +                if (dst->port) {\n> > +                    ds_put_format(s, \"]:%\"PRIu16, dst->port);\n> > +                }\n> >              }\n> >          }\n> >          ds_put_char(s, ')');\n> > @@ -991,8 +1041,17 @@ encode_CT_LB(const struct ovnact_ct_lb *cl,\n> >      BUILD_ASSERT(MFF_LOG_DNAT_ZONE < MFF_REG0 + FLOW_N_REGS);\n> >      for (size_t bucket_id = 0; bucket_id < cl->n_dsts; bucket_id++) {\n> >          const struct ovnact_ct_lb_dst *dst = &cl->dsts[bucket_id];\n> > +        char ip_addr[INET6_ADDRSTRLEN];\n> > +        if (dst->family == AF_INET) {\n> > +            inet_ntop(AF_INET, &dst->ipv4, ip_addr, sizeof ip_addr);\n> > +        } else {\n> > +            inet_ntop(AF_INET6, &dst->ipv6, ip_addr, sizeof ip_addr);\n> > +        }\n> >          ds_put_format(&ds,\n> \",bucket=bucket_id=%\"PRIuSIZE\",weight:100,actions=\"\n> > -                      \"ct(nat(dst=\"IP_FMT, bucket_id, IP_ARGS(dst->ip));\n> > +                      \"ct(nat(dst=%s%s%s\", bucket_id,\n> > +                      dst->family == AF_INET6 && dst->port ? \"[\" : \"\",\n> > +                      ip_addr,\n> > +                      dst->family == AF_INET6 && dst->port ? \"]\" : \"\");\n> >          if (dst->port) {\n> >              ds_put_format(&ds, \":%\"PRIu16, dst->port);\n> >          }\n> > diff --git a/tests/ovn.at b/tests/ovn.at\n> > index fb9fc7352..9118f2839 100644\n> > --- a/tests/ovn.at\n> > +++ b/tests/ovn.at\n> > @@ -793,13 +793,19 @@ ct_lb(192.168.1.2, 192.168.1.3, );\n> >      formats as ct_lb(192.168.1.2, 192.168.1.3);\n> >      encodes as group:2\n> >      has prereqs ip\n> > +ct_lb(fd0f::2, fd0f::3, );\n> > +    formats as ct_lb(fd0f::2, fd0f::3);\n> > +    encodes as group:3\n> > +    has prereqs ip\n> >\n> >  ct_lb(192.168.1.2:);\n> >      Syntax error at `)' expecting port number.\n> >  ct_lb(192.168.1.2:123456);\n> >      Syntax error at `123456' expecting port number.\n> >  ct_lb(foo);\n> > -    Syntax error at `foo' expecting IPv4 address.\n> > +    Syntax error at `foo' expecting IP address.\n> > +ct_lb([192.168.1.2]);\n> > +    Syntax error at `192.168.1.2' expecting IPv6 address.\n> >\n> >  # ct_next\n> >  ct_next;\n>\n>","headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@bilbo.ozlabs.org","ovs-dev@mail.linuxfoundation.org"],"Authentication-Results":"ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=openvswitch.org\n\t(client-ip=140.211.169.12; helo=mail.linuxfoundation.org;\n\tenvelope-from=ovs-dev-bounces@openvswitch.org;\n\treceiver=<UNKNOWN>)","Received":["from mail.linuxfoundation.org (mail.linuxfoundation.org\n\t[140.211.169.12])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xp1FM07y1z9sNd\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu,  7 Sep 2017 23:16:55 +1000 (AEST)","from mail.linux-foundation.org (localhost [127.0.0.1])\n\tby mail.linuxfoundation.org (Postfix) with ESMTP id C6A3BAB8;\n\tThu,  7 Sep 2017 13:16:51 +0000 (UTC)","from smtp1.linuxfoundation.org (smtp1.linux-foundation.org\n\t[172.17.192.35])\n\tby mail.linuxfoundation.org (Postfix) with ESMTPS id 663B8AB6\n\tfor <dev@openvswitch.org>; Thu,  7 Sep 2017 13:16:50 +0000 (UTC)","from mail-io0-f182.google.com (mail-io0-f182.google.com\n\t[209.85.223.182])\n\tby smtp1.linuxfoundation.org (Postfix) with ESMTPS id 46722469\n\tfor <dev@openvswitch.org>; Thu,  7 Sep 2017 13:16:49 +0000 (UTC)","by mail-io0-f182.google.com with SMTP id d16so4025416ioj.3\n\tfor <dev@openvswitch.org>; Thu, 07 Sep 2017 06:16:49 -0700 (PDT)"],"X-Greylist":"whitelisted by SQLgrey-1.7.6","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=jRVGIjKqxTuzjs/BVcJq5cmMf/UjPxDAHP8hlveRxoc=;\n\tb=DRJ5rq0pZWFN2C0PfGFzwiMIB+o2eHr7yjxV4sFv3iYPluq44dqsa4jEKYVN4N6pBF\n\t3SccQzzdOEe/O1MEa2ARLvMvggWxegxRuRT+nYTfFMhjqEwBAx1CJFbz0nhrufDxP6kc\n\tvlxudaPB5FRL0kl/VeerLsbplHBOtmVdG2YJlKjY+PTtGSUSwgfyb1SRU79LaqltW9LS\n\tf9tBJ2OuG+TtYsrpFrzs75ev/7cmH/BoTlC825vOqSuvz1hNxaS/EShuoTkGLsNDDWe+\n\tdzTQHmiXks0P8aYExxa/QDez0Qo02F5Whs9wEJJexvwGq4RJvFnhfTowjywg4sNUH3Hw\n\t5TLg==","X-Gm-Message-State":"AHPjjUgdhduru+QGmLIDY4K06eXPADIfEbDyKKPvHQWAYtpco3jd06q6\n\tZBYYwpO2ww013sELWjBGPf34LsVgkRxC","X-Google-Smtp-Source":"AOwi7QCUU19pdWpFQeBaezf5xhNIP56GRXxHfu5LyIUr+uHdHiOgEQTm6RdBfi9dRF8YrwTpzK5QRo+u77TMe32yXCg=","X-Received":"by 10.107.222.6 with SMTP id v6mr3352380iog.264.1504790208618;\n\tThu, 07 Sep 2017 06:16:48 -0700 (PDT)","MIME-Version":"1.0","References":"<20170906210839.26091-1-mmichels@redhat.com>\n\t<20170906210839.26091-3-mmichels@redhat.com>\n\t<20170907151219.4107929b@beetle>","In-Reply-To":"<20170907151219.4107929b@beetle>","From":"Mark Michelson <mmichels@redhat.com>","Date":"Thu, 07 Sep 2017 13:16:38 +0000","Message-ID":"<CAA1+qOOXoQanJotFLBENkLa1M=sEsmTzvpdZCHUOVHB8O7ythA@mail.gmail.com>","To":"Jakub Sitnicki <jkbs@redhat.com>","X-Spam-Status":"No, score=1.8 required=5.0 tests=HTML_MESSAGE,\n\tRCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, URI_HEX,\n\tWEIRD_PORT autolearn=disabled version=3.3.1","X-Spam-Level":"*","X-Spam-Checker-Version":"SpamAssassin 3.3.1 (2010-03-16) on\n\tsmtp1.linux-foundation.org","X-Content-Filtered-By":"Mailman/MimeDel 2.1.12","Cc":"dev@openvswitch.org","Subject":"Re: [ovs-dev] [PATCH 2/4] ovn: Allow ct_lb actions to take IPv6\n\taddress arguments.","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.12","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n\t<mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"ovs-dev-bounces@openvswitch.org","Errors-To":"ovs-dev-bounces@openvswitch.org"}}]