On 31 October 2016 at 19:00, nickcooper-zhangtonghao <
[email protected]> wrote:

> When the type of NAT is dnat, the externally visible IP address
> and port number can be DNATted to the IP address and port number
> in the logical space. Adds a protocol column for the NAT. Valid
> protocols  are  tcp  or  udp.  This column is useful when a port
> number is provided as part of the external_ip column and the type
> is set as dnat. If this column is empty and a port number is
> provided as part of external_ip column when the type is set as dnat,
> OVN assumes the protocol to be tcp.
>
> For example :
> ovn-nbctl -- --id=@nat create nat type="dnat" protocol="tcp" \
>         logical_ip="192.168.1.2\:8080" external_ip="30.0.0.2\:80" \
>         -- add logical_router R1 nat @nat
>
> This patch improves the "tests/test-l7.py" which can support the
> "--port" argument. This patch also provides the unit tests and
> the documentation.
>
> Signed-off-by: nickcooper-zhangtonghao <nickcooper-zhangtonghao@
> opencloud.tech>
>

Sorry for the delay in the reviews.
I understand that we can extend the current DNAT feature to include
DNAT:port. But is there is a use case where you want to use this? Any
extensions of the NAT table can be better designed if we understand the end
use-case for it. If not, I will just take a look at the first version of
the series.


> ---
>  include/ovn/actions.h       |   1 +
>  ovn/lib/actions.c           |  13 +++-
>  ovn/northd/ovn-northd.8.xml |  10 +++
>  ovn/northd/ovn-northd.c     | 149 ++++++++++++++++++++++++++++++
> ++++----------
>  ovn/ovn-nb.ovsschema        |   8 ++-
>  ovn/ovn-nb.xml              |  22 +++++--
>  tests/system-ovn.at         | 113 +++++++++++++++++++++++++++++++++
>  tests/test-l7.py            |  13 +++-
>  8 files changed, 287 insertions(+), 42 deletions(-)
>
> diff --git a/include/ovn/actions.h b/include/ovn/actions.h
> index 0bf6145..ce8aca5 100644
> --- a/include/ovn/actions.h
> +++ b/include/ovn/actions.h
> @@ -170,6 +170,7 @@ struct ovnact_ct_commit {
>  struct ovnact_ct_nat {
>      struct ovnact ovnact;
>      ovs_be32 ip;
> +    uint16_t port;
>      uint8_t ltable;             /* Logical table ID of next table. */
>  };
>
> diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c
> index df526c0..90c19f3 100644
> --- a/ovn/lib/actions.c
> +++ b/ovn/lib/actions.c
> @@ -697,13 +697,21 @@ 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) {
> +            || mf_subvalue_width(&ctx->lexer->token.value) > 32) {
>              lexer_syntax_error(ctx->lexer, "expecting IPv4 address");
>              return;
>          }
>          cn->ip = ctx->lexer->token.value.ipv4;
>          lexer_get(ctx->lexer);
>
> +        /* Parse optional port. */
> +        uint16_t port = 0;
> +        if (lexer_match(ctx->lexer, LEX_T_COLON)
> +            && !action_parse_port(ctx, &port)) {
> +            return;
> +        }
> +        cn->port = port;
> +
>          if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
>              return;
>          }
> @@ -779,6 +787,9 @@ encode_ct_nat(const struct ovnact_ct_nat *cn,
>          if (snat) {
>              nat->flags |= NX_NAT_F_SRC;
>          } else {
> +            if (cn->port) {
> +                nat->range.proto.min = cn->port;
> +            }
>              nat->flags |= NX_NAT_F_DST;
>          }
>      }
> diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
> index df53d4c..f141462 100644
> --- a/ovn/northd/ovn-northd.8.xml
> +++ b/ovn/northd/ovn-northd.8.xml
> @@ -1191,6 +1191,16 @@ icmp4 {
>
>        <li>
>          For each configuration in the OVN Northbound database, that asks
> +        to change the destination IP address <var>A</var> with a port
> +        <var>P1</var> of protocol <var>P</var> to IP address <var>B</var>
> +        and port <var>P2</var>, a priority-100 flow matches <code>ip
> &amp;&amp;
> +        ip4.dst == <var>A</var> &amp;&amp; <var>P</var> &amp;&amp;
> +        <var>P</var>.dst == <var>P1</var></code> with an action
> +        <code>flags.loopback = 1; ct_dnat(<var>B</var>:<var>P2</
> var>);</code>.
> +      </li>
> +
> +      <li>
> +        For each configuration in the OVN Northbound database, that asks
>          to change the destination IP address of a packet from
> <var>A</var> to
>          <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;
>          ip4.dst == <var>A</var></code> with an action
> diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
> index ad0739c..03bd9e4 100644
> --- a/ovn/northd/ovn-northd.c
> +++ b/ovn/northd/ovn-northd.c
> @@ -2252,7 +2252,7 @@ build_pre_acls(struct ovn_datapath *od, struct hmap
> *lflows)
>   * 'ip_address'.  The caller must free() the memory allocated for
>   * 'ip_address'. */
>  static void
> -ip_address_and_port_from_lb_key(const char *key, char **ip_address,
> +ip_address_and_port(const char *key, char **ip_address,
>                                  uint16_t *port)
>  {
>      char *ip_str, *start, *next;
> @@ -2262,8 +2262,6 @@ ip_address_and_port_from_lb_key(const char *key,
> char **ip_address,
>      next = start = xstrdup(key);
>      ip_str = strsep(&next, ":");
>      if (!ip_str || !ip_str[0]) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -        VLOG_WARN_RL(&rl, "bad ip address for load balancer key %s", key);
>          free(start);
>          return;
>      }
> @@ -2271,8 +2269,6 @@ ip_address_and_port_from_lb_key(const char *key,
> char **ip_address,
>      ovs_be32 ip, mask;
>      char *error = ip_parse_masked(ip_str, &ip, &mask);
>      if (error || mask != OVS_BE32_MAX) {
> -        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -        VLOG_WARN_RL(&rl, "bad ip address for load balancer key %s", key);
>          free(start);
>          free(error);
>          return;
> @@ -2281,8 +2277,6 @@ ip_address_and_port_from_lb_key(const char *key,
> char **ip_address,
>      int l4_port = 0;
>      if (next && next[0]) {
>          if (!str_to_int(next, 0, &l4_port) || l4_port < 0 || l4_port >
> 65535) {
> -            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> -            VLOG_WARN_RL(&rl, "bad ip port for load balancer key %s",
> key);
>              free(start);
>              return;
>          }
> @@ -2313,8 +2307,11 @@ build_pre_lb(struct ovn_datapath *od, struct hmap
> *lflows)
>              /* node->key contains IP:port or just IP. */
>              char *ip_address = NULL;
>              uint16_t port;
> -            ip_address_and_port_from_lb_key(node->key, &ip_address,
> &port);
> +            ip_address_and_port(node->key, &ip_address, &port);
>              if (!ip_address) {
> +                static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(5, 1);
> +                VLOG_WARN_RL(&rl, "bad ip address or port for load
> balancer "
> +                             "key %s", node->key);
>                  continue;
>              }
>
> @@ -2719,8 +2716,11 @@ build_stateful(struct ovn_datapath *od, struct hmap
> *lflows)
>
>              /* node->key contains IP:port or just IP. */
>              char *ip_address = NULL;
> -            ip_address_and_port_from_lb_key(node->key, &ip_address,
> &port);
> +            ip_address_and_port(node->key, &ip_address, &port);
>              if (!ip_address) {
> +                static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(5, 1);
> +                VLOG_WARN_RL(&rl, "bad ip address or port for load
> balancer "
> +                             "key %s", node->key);
>                  continue;
>              }
>
> @@ -3613,8 +3613,12 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>                  char *ip_address = NULL;
>                  uint16_t port;
>
> -                ip_address_and_port_from_lb_key(node->key, &ip_address,
> &port);
> +                ip_address_and_port(node->key, &ip_address, &port);
>                  if (!ip_address) {
> +                    static struct vlog_rate_limit rl =
> +                        VLOG_RATE_LIMIT_INIT(5, 1);
> +                    VLOG_WARN_RL(&rl, "bad ip address or port for load "
> +                                 "balancer key %s", node->key);
>                      continue;
>                  }
>
> @@ -3669,10 +3673,25 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>
>              ovs_be32 ip;
>              if (!ip_parse(nat->external_ip, &ip) || !ip) {
> -                static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(5, 1);
> -                VLOG_WARN_RL(&rl, "bad ip address %s in nat configuration
> "
> -                             "for router %s", nat->external_ip, op->key);
> -                continue;
> +                bool is_external_port = false;
> +                if (!strcmp(nat->type, "dnat")) {
> +                    ovs_be16 port;
> +                    char *error = ip_parse_port(nat->external_ip, &ip,
> &port);
> +                    if (error) {
> +                        free(error);
> +                    } else {
> +                        is_external_port = true;
> +                    }
> +                }
> +
> +                if (!is_external_port) {
> +                    static struct vlog_rate_limit rl =
> +                        VLOG_RATE_LIMIT_INIT(5, 1);
> +                    VLOG_WARN_RL(&rl, "bad external ip address %s in nat "
> +                                 "configuration for router %s",
> +                                 nat->external_ip, op->key);
> +                    continue;
> +                }
>              }
>
>              if (!strcmp(nat->type, "snat")) {
> @@ -3845,8 +3864,12 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>
>                  /* node->key contains IP:port or just IP. */
>                  char *ip_address = NULL;
> -                ip_address_and_port_from_lb_key(node->key, &ip_address,
> &port);
> +                ip_address_and_port(node->key, &ip_address, &port);
>                  if (!ip_address) {
> +                    static struct vlog_rate_limit rl =
> +                        VLOG_RATE_LIMIT_INIT(5, 1);
> +                    VLOG_WARN_RL(&rl, "bad ip address or port for load "
> +                                 "balancer key %s", node->key);
>                      continue;
>                  }
>
> @@ -3905,37 +3928,78 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>
>              nat = od->nbr->nat[i];
>
> -            ovs_be32 ip, mask;
> -
> -            char *error = ip_parse_masked(nat->external_ip, &ip, &mask);
> -            if (error || mask != OVS_BE32_MAX) {
> +            uint16_t external_port = 0;
> +            char *external_ip = NULL;
> +            ip_address_and_port(nat->external_ip,
> +                                &external_ip, &external_port);
> +            if (!external_ip) {
>                  static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(5, 1);
>                  VLOG_WARN_RL(&rl, "bad external ip %s for nat",
>                               nat->external_ip);
> -                free(error);
> +                continue;
> +            }
> +
> +            if (strcmp(nat->type, "dnat") && external_port) {
> +                static struct vlog_rate_limit rl =
> VLOG_RATE_LIMIT_INIT(5, 1);
> +                VLOG_WARN_RL(&rl, "the external ip (%s) with port should
> not "
> +                             "be configured for snat or dnat_and_snat",
> +                             nat->external_ip);
> +                free(external_ip);
>                  continue;
>              }
>
>              /* Check the validity of nat->logical_ip. 'logical_ip' can
>               * be a subnet when the type is "snat". */
> -            error = ip_parse_masked(nat->logical_ip, &ip, &mask);
> -            if (!strcmp(nat->type, "snat")) {
> -                if (error) {
> +            uint16_t logical_port = 0;
> +            char *error, *logical_ip = NULL;
> +            ovs_be32 ip, mask = OVS_BE32_MAX;
> +            ip_address_and_port(nat->logical_ip,
> +                                &logical_ip, &logical_port);
> +            if (!logical_ip) {
> +                if (!strcmp(nat->type, "snat")) {
> +                    error = ip_parse_masked(nat->logical_ip, &ip, &mask);
> +                    if (error) {
> +                        static struct vlog_rate_limit rl =
> +                            VLOG_RATE_LIMIT_INIT(5, 1);
> +                        VLOG_WARN_RL(&rl, "bad logical ip network or ip
> %s "
> +                                     "for snat in router "UUID_FMT"",
> +                                     nat->logical_ip,
> UUID_ARGS(&od->key));
> +                        free(external_ip);
> +                        free(error);
> +                        continue;
> +                    }
> +                } else {
>                      static struct vlog_rate_limit rl =
>                          VLOG_RATE_LIMIT_INIT(5, 1);
> -                    VLOG_WARN_RL(&rl, "bad ip network or ip %s for snat "
> -                                 "in router "UUID_FMT"",
> +                    VLOG_WARN_RL(&rl, "bad logical ip %s for dnat or "
> +                                 "dnat_and_snat in router "UUID_FMT"",
>                                   nat->logical_ip, UUID_ARGS(&od->key));
> -                    free(error);
> +                    free(external_ip);
> +                    continue;
> +                }
> +            }
> +
> +            if (!strcmp(nat->type, "dnat")) {
> +                if ((external_port != 0 && logical_port == 0)
> +                    || (external_port == 0 && logical_port != 0)) {
> +                    static struct vlog_rate_limit rl =
> +                        VLOG_RATE_LIMIT_INIT(5, 1);
> +                    VLOG_WARN_RL(&rl, "the external/logical ip (%s, %s)
> with "
> +                                 "port should be configured at same time
> for "
> +                                 "dnat", nat->external_ip,
> nat->logical_ip);
> +                    free(external_ip);
> +                    free(logical_ip);
>                      continue;
>                  }
>              } else {
> -                if (error || mask != OVS_BE32_MAX) {
> +                if (logical_port) {
>                      static struct vlog_rate_limit rl =
>                          VLOG_RATE_LIMIT_INIT(5, 1);
> -                    VLOG_WARN_RL(&rl, "bad ip %s for dnat in router "
> -                        ""UUID_FMT"", nat->logical_ip,
> UUID_ARGS(&od->key));
> -                    free(error);
> +                    VLOG_WARN_RL(&rl, "the logical ip (%s) with port
> should "
> +                                 "not be configured for snat or
> dnat_and_snat",
> +                                 nat->logical_ip);
> +                    free(external_ip);
> +                    free(logical_ip);
>                      continue;
>                  }
>              }
> @@ -3966,10 +4030,27 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>                   * We need to zero the inport because the router can
>                   * send the packet back through the same interface. */
>                  ds_clear(&match);
> -                ds_put_format(&match, "ip && ip4.dst == %s",
> nat->external_ip);
>                  ds_clear(&actions);
> -                ds_put_format(&actions,"flags.loopback = 1;
> ct_dnat(%s);",
> -                              nat->logical_ip);
> +                if (external_port && logical_port) {
> +                    /* The external_port and logical port should be
> configured
> +                     * only for DNAT.*/
> +                    char *protocol = "tcp";
> +                    if (nat->protocol && !strcmp(nat->protocol, "udp")) {
> +                       protocol = "udp";
> +                    }
> +                    ds_put_format(&match, "ip && ip4.dst == %s "
> +                                  "&& %s && %s.dst == %d",
> +                                  external_ip, protocol,
> +                                  protocol, external_port);
> +                    ds_put_format(&actions,"flags.loopback = 1; "
> +                                  "ct_dnat(%s:%d);",
> +                                  logical_ip, logical_port);
> +                } else {
> +                    ds_put_format(&match, "ip && ip4.dst == %s",
> +                                  external_ip);
> +                    ds_put_format(&actions,"flags.loopback = 1;
> ct_dnat(%s);",
> +                                  logical_ip);
> +                }
>                  ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100,
>                                ds_cstr(&match), ds_cstr(&actions));
>              }
> @@ -3991,6 +4072,8 @@ build_lrouter_flows(struct hmap *datapaths, struct
> hmap *ports,
>                                count_1bits(ntohl(mask)) + 1,
>                                ds_cstr(&match), ds_cstr(&actions));
>              }
> +            free(external_ip);
> +            free(logical_ip);
>          }
>
>          /* Re-circulate every packet through the DNAT zone.
> diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
> index 865dd34..a290c67 100644
> --- a/ovn/ovn-nb.ovsschema
> +++ b/ovn/ovn-nb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Northbound",
> -    "version": "5.4.0",
> -    "cksum": "4176761817 11225",
> +    "version": "5.4.1",
> +    "cksum": "944843976 11424",
>      "tables": {
>          "NB_Global": {
>              "columns": {
> @@ -203,6 +203,10 @@
>              "columns": {
>                  "external_ip": {"type": "string"},
>                  "logical_ip": {"type": "string"},
> +                "protocol": {
> +                    "type": {"key": {"type": "string",
> +                             "enum": ["set", ["tcp", "udp"]]},
> +                             "min": 0, "max": 1}},
>                  "type": {"type": {"key": {"type": "string",
>                                             "enum": ["set", ["dnat",
>                                                               "snat",
> diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
> index e1b3136..ec13278 100644
> --- a/ovn/ovn-nb.xml
> +++ b/ovn/ovn-nb.xml
> @@ -1116,8 +1116,10 @@
>        <ul>
>          <li>
>            When <ref column="type"/> is <code>dnat</code>, the externally
> -          visible IP address <ref column="external_ip"/> is DNATted to
> the IP
> -          address <ref column="logical_ip"/> in the logical space.
> +          visible IP address (and an optional port number with
> <code>:</code>
> +          as a separator) <ref column="external_ip"/> is DNATted to the IP
> +          address (and an optional port number with <code>:</code> as a
> +          separator) <ref column="logical_ip"/> in the logical space.
>          </li>
>          <li>
>            When <ref column="type"/> is <code>snat</code>, IP packets
> @@ -1138,11 +1140,23 @@
>      </column>
>
>      <column name="external_ip">
> -      An IPv4 address.
> +     An IPv4 address (and an optional port number with <code>:</code>
> +     as a separator).
>      </column>
>
>      <column name="logical_ip">
> -      An IPv4 network (e.g 192.168.1.0/24) or an IPv4 address.
> +     An IPv4 network (e.g 192.168.1.0/24) or an IPv4 address (and an
> optional
> +     port number with <code>:</code> as a separator).
> +    </column>
> +
> +    <column name="protocol">
> +     Valid protocols are <code>tcp</code> or <code>udp</code>.  This
> column
> +     is useful when a port number is provided as part of the
> +     <code>external_ip</code> column and the <code>type</code> is set
> +     as <code>dnat</code>.  If this column is empty and a port number
> +     is provided as part of <code>external_ip</code> column when
> +     the <code>type</code> is set as <code>dnat</code>, OVN assumes the
> +     <code>protocol</code> to be <code>tcp</code>.
>      </column>
>    </table>
>
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 21226d9..ba69df6 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -279,6 +279,119 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port
> patch-.*/d
>  /connection dropped.*/d"])
>  AT_CLEANUP
>
> +AT_SETUP([ovn -- 2 LRs connected via LS, gateway router, DNAT with port])
> +AT_KEYWORDS([ovnnat])
> +
> +CHECK_CONNTRACK()
> +CHECK_CONNTRACK_NAT()
> +ovn_start
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-int])
> +
> +# Set external-ids in br-int needed for ovn-controller
> +ovs-vsctl \
> +        -- set Open_vSwitch . external-ids:system-id=hv1 \
> +        -- set Open_vSwitch . 
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock
> \
> +        -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> +        -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \
> +        -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> +
> +# Start ovn-controller
> +start_daemon ovn-controller
> +
> +# Logical network:
> +# Two LRs - R1 and R2 that are connected to each other via LS "join"
> +# in 20.0.0.0/24 network. R1 has switchess foo (192.168.1.0/24) connected
> +# to it.  R2 has alice (172.16.1.0/24) connected to it.
> +# R2 is a gateway router on which we add NAT rules.
> +#
> +#    foo -- R1 -- join - R2 -- alice
> +
> +ovn-nbctl lr-add R1
> +ovn-nbctl lr-add R2 -- set Logical_Router R2 options:chassis=hv1
> +
> +ovn-nbctl ls-add foo
> +ovn-nbctl ls-add alice
> +ovn-nbctl ls-add join
> +
> +ovn-nbctl lrp-add R1 foo 00:00:01:01:02:03 192.168.1.1/24
> +ovn-nbctl lrp-add R2 alice 00:00:02:01:02:03 172.16.1.1/24
> +ovn-nbctl lrp-add R1 R1_join 00:00:04:01:02:03 20.0.0.1/24
> +ovn-nbctl lrp-add R2 R2_join 00:00:04:01:02:04 20.0.0.2/24
> +
> +# Connect foo to R1
> +ovn-nbctl lsp-add foo rp-foo -- set Logical_Switch_Port rp-foo \
> +    type=router options:router-port=foo addresses=\"00:00:01:01:02:03\"
> +
> +# Connect alice to R2
> +ovn-nbctl lsp-add alice rp-alice -- set Logical_Switch_Port rp-alice \
> +    type=router options:router-port=alice addresses=\"00:00:02:01:02:03\"
> +
> +# Connect R1 to join
> +ovn-nbctl lsp-add join r1-join -- set Logical_Switch_Port r1-join \
> +    type=router options:router-port=R1_join addresses='"00:00:04:01:02:03"
> '
> +
> +# Connect R2 to join
> +ovn-nbctl lsp-add join r2-join -- set Logical_Switch_Port r2-join \
> +    type=router options:router-port=R2_join addresses='"00:00:04:01:02:04"
> '
> +
> +# Static routes.
> +ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2
> +ovn-nbctl lr-route-add R2 192.168.0.0/16 20.0.0.1
> +
> +# Logical port 'foo1' in switch 'foo'.
> +ADD_NAMESPACES(foo1)
> +ADD_VETH(foo1, foo1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> +         "192.168.1.1")
> +ovn-nbctl lsp-add foo foo1 \
> +-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2"
> +
> +# Logical port 'alice1' in switch 'alice'.
> +ADD_NAMESPACES(alice1)
> +ADD_VETH(alice1, alice1, br-int, "172.16.1.2/24", "f0:00:00:01:02:04", \
> +         "172.16.1.1")
> +ovn-nbctl lsp-add alice alice1 \
> +-- lsp-set-addresses alice1 "f0:00:00:01:02:04 172.16.1.2"
> +
> +# Add a DNAT with port rule
> +ovn-nbctl -- --id=@nat create nat type="dnat" protocol="tcp"
> logical_ip="192.168.1.2\:8080" \
> +    external_ip="30.0.0.2\:80" -- add logical_router R2 nat @nat
> +ovn-nbctl -- --id=@nat create nat type="dnat" protocol="udp"
> logical_ip="192.168.1.2\:8181" \
> +    external_ip="30.0.0.3\:81" -- add logical_router R2 nat @nat
> +
> +OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep ct\( | grep nat])
> +
> +# South-North DNAT
> +NETNS_DAEMONIZE([foo1], [[$PYTHON $srcdir/test-l7.py --port 8080]],
> [http0.pid])
> +NS_CHECK_EXEC([alice1], [wget 30.0.0.2 -t 3 -T 1 --retry-connrefused -v
> -o wget0.log])
> +AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br-int ovs-alice1 normal '
> 000002010203F0000001020408004500001C000100004011AFBBAC100102
> 1E0000030035005100083443'])
> +
> +# We verify that DNAT indeed happened via 'dump-conntrack' command.
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.2) | \
> +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
> +tcp,orig=(src=172.16.1.2,dst=30.0.0.2,sport=<cleared>,
> dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,
> sport=<cleared>,dport=<cleared>),zone=<cleared>,
> protoinfo=(state=<cleared>)
> +])
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(30.0.0.3) | \
> +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
> +udp,orig=(src=172.16.1.2,dst=30.0.0.3,sport=<cleared>,
> dport=<cleared>),reply=(src=192.168.1.2,dst=172.16.1.2,
> sport=<cleared>,dport=<cleared>),zone=<cleared>
> +])
> +
> +OVS_APP_EXIT_AND_WAIT([ovn-controller])
> +
> +as ovn-sb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as ovn-nb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as northd
> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> +/connection dropped.*/d"])
> +AT_CLEANUP
> +
>  AT_SETUP([ovn -- load-balancing])
>  AT_KEYWORDS([ovnlb])
>
> diff --git a/tests/test-l7.py b/tests/test-l7.py
> index aed34f4..c6aae4e 100755
> --- a/tests/test-l7.py
> +++ b/tests/test-l7.py
> @@ -61,8 +61,14 @@ def main():
>      protocols = [srv for srv in SERVERS]
>      parser = argparse.ArgumentParser(
>              description='Run basic application servers.')
> -    parser.add_argument('proto', default='http', nargs='?',
> -            help='protocol to serve (%s)' % protocols)
> +    parser.add_argument('proto',
> +                        default='http',
> +                        nargs='?',
> +                        help='protocol to serve (%s)' % protocols)
> +    parser.add_argument('-o','--port',
> +                        type=int,
> +                        action='store',
> +                        help='Port to connect on')
>      args = parser.parse_args()
>
>      if args.proto not in SERVERS:
> @@ -72,6 +78,9 @@ def main():
>      constructor = SERVERS[args.proto][0]
>      handler = SERVERS[args.proto][1]
>      port = SERVERS[args.proto][2]
> +    if args.port:
> +        port = args.port
> +
>      srv = constructor(('', port), handler)
>      srv.serve_forever()
>
> --
> 1.8.3.1
>
>
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to