[ovs-dev] [PATCH v11 4/5] ovn: ovn-nbctl commands for distributed NAT

Guru Shetty guru at ovn.org
Thu Jan 26 17:20:37 UTC 2017


On 21 January 2017 at 16:52, Mickey Spiegel <mickeys.dev at gmail.com> wrote:

> This patch adds the new optional arguments "logical_port" and
> "external_mac" to lr-nat-add, and displays that information in
> lr-nat-list.
>
> Signed-off-by: Mickey Spiegel <mickeys.dev at gmail.com>
>


Acked-by: Gurucharan Shetty <guru at ovn.org>

On a different note, can the external_mac be the same as the logical_port's
mac? I guess, it does not matter. It may makes sense to add that
information in ovn-nb.



> ---
>  ovn/utilities/ovn-nbctl.8.xml | 27 +++++++++++++++++++---
>  ovn/utilities/ovn-nbctl.c     | 54 ++++++++++++++++++++++++++++++
> +++++++------
>  tests/ovn-nbctl.at            | 47 +++++++++++++++++++++++++++++++++----
>  tests/system-ovn.at           | 30 +++++-------------------
>  4 files changed, 119 insertions(+), 39 deletions(-)
>
> diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml
> index f95b88d..d81e99f 100644
> --- a/ovn/utilities/ovn-nbctl.8.xml
> +++ b/ovn/utilities/ovn-nbctl.8.xml
> @@ -444,7 +444,7 @@
>      <h1>NAT Commands</h1>
>
>      <dl>
> -      <dt>[<code>--may-exist</code>] <code>lr-nat-add</code>
> <var>router</var> <var>type</var> <var>external_ip</var>
> <var>logical_ip</var></dt>
> +      <dt>[<code>--may-exist</code>] <code>lr-nat-add</code>
> <var>router</var> <var>type</var> <var>external_ip</var>
> <var>logical_ip</var> [<var>logical_port</var> <var>external_mac</var>]</dt>
>        <dd>
>          <p>
>            Adds the specified NAT to <var>router</var>.
> @@ -453,6 +453,13 @@
>            The <var>external_ip</var> is an IPv4 address.
>            The <var>logical_ip</var> is an IPv4 network (e.g
> 192.168.1.0/24)
>            or an IPv4 address.
> +          The <var>logical_port</var> and <var>external_mac</var> are only
> +          accepted when <var>router</var> is a distributed router (rather
> +          than a gateway router) and <var>type</var> is
> +          <code>dnat_and_snat</code>.
> +          The <var>logical_port</var> is the name of an existing logical
> +          switch port where the <var>logical_ip</var> resides.
> +          The <var>external_mac</var> is an Ethernet address.
>          </p>
>          <p>
>            When <var>type</var> is <code>dnat</code>, the externally
> @@ -475,8 +482,22 @@
>            the IP address in <var>external_ip</var>.
>          </p>
>          <p>
> -          It is an error if a NAT already exists,
> -          unless <code>--may-exist</code> is specified.
> +          When the <var>logical_port</var> and <var>external_mac</var>
> +          are specified, the NAT rule will be programmed on the chassis
> +          where the <var>logical_port</var> resides.  This includes
> +          ARP replies for the <var>external_ip</var>, which return the
> +          value of <var>external_mac</var>.  All packets transmitted
> +          with source IP address equal to <var>external_ip</var> will
> +          be sent using the <var>external_mac</var>.
> +        </p>
> +        <p>
> +          It is an error if a NAT already exists with the same values
> +          of <var>router</var>, <var>type</var>, <var>external_ip</var>,
> +          and <var>logical_ip</var>, unless <code>--may-exist</code> is
> +          specified.  When <code>--may-exist</code>,
> +          <var>logical_port</var>, and <var>external_mac</var> are all
> +          specified, the existing values of <var>logical_port</var> and
> +          <var>external_mac</var> are overwritten.
>          </p>
>        </dd>
>
> diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
> index f0ff27a..3dac434 100644
> --- a/ovn/utilities/ovn-nbctl.c
> +++ b/ovn/utilities/ovn-nbctl.c
> @@ -390,7 +390,7 @@ Route commands:\n\
>    lr-route-list ROUTER      print routes for ROUTER\n\
>  \n\
>  NAT commands:\n\
> -  lr-nat-add ROUTER TYPE EXTERNAL_IP LOGICAL_IP\n\
> +  lr-nat-add ROUTER TYPE EXTERNAL_IP LOGICAL_IP [LOGICAL_PORT
> EXTERNAL_MAC]\n\
>                              add a NAT to ROUTER\n\
>    lr-nat-del ROUTER [TYPE [IP]]\n\
>                              remove NATs from ROUTER\n\
> @@ -2239,6 +2239,30 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
>          new_logical_ip = normalize_ipv4_prefix(ipv4, plen);
>      }
>
> +    const char *logical_port;
> +    const char *external_mac;
> +    if (ctx->argc == 6) {
> +        ctl_fatal("lr-nat-add with logical_port "
> +                  "must also specify external_mac.");
> +    } else if (ctx->argc == 7) {
> +        if (strcmp(nat_type, "dnat_and_snat")) {
> +            ctl_fatal("logical_port and external_mac are only valid when "
> +                      "type is \"dnat_and_snat\".");
> +        }
> +
> +        logical_port = ctx->argv[5];
> +        lsp_by_name_or_uuid(ctx, logical_port, true);
> +
> +        external_mac = ctx->argv[6];
> +        struct eth_addr ea;
> +        if (!eth_addr_from_string(external_mac, &ea)) {
> +            ctl_fatal("invalid mac address %s.", external_mac);
> +        }
> +    } else {
> +        logical_port = NULL;
> +        external_mac = NULL;
> +    }
> +
>      bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
>      int is_snat = !strcmp("snat", nat_type);
>      for (size_t i = 0; i < lr->n_nat; i++) {
> @@ -2249,6 +2273,10 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
>                  if (!strcmp(is_snat ? external_ip : new_logical_ip,
>                              is_snat ? nat->external_ip :
> nat->logical_ip)) {
>                          if (may_exist) {
> +                            nbrec_nat_verify_logical_port(nat);
> +                            nbrec_nat_verify_external_mac(nat);
> +                            nbrec_nat_set_logical_port(nat,
> logical_port);
> +                            nbrec_nat_set_external_mac(nat,
> external_mac);
>                              free(new_logical_ip);
>                              return;
>                          }
> @@ -2271,6 +2299,10 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
>      nbrec_nat_set_type(nat, nat_type);
>      nbrec_nat_set_external_ip(nat, external_ip);
>      nbrec_nat_set_logical_ip(nat, new_logical_ip);
> +    if (logical_port && external_mac) {
> +        nbrec_nat_set_logical_port(nat, logical_port);
> +        nbrec_nat_set_external_mac(nat, external_mac);
> +    }
>      free(new_logical_ip);
>
>      /* Insert the NAT into the logical router. */
> @@ -2353,17 +2385,24 @@ nbctl_lr_nat_list(struct ctl_context *ctx)
>      struct smap lr_nats = SMAP_INITIALIZER(&lr_nats);
>      for (size_t i = 0; i < lr->n_nat; i++) {
>          const struct nbrec_nat *nat = lr->nat[i];
> -        smap_add_format(&lr_nats, nat->type, "%-19.15s%s",
> -                        nat->external_ip, nat->logical_ip);
> +        const char *key = xasprintf("%-17.13s%s", nat->type,
> nat->external_ip);
> +        if (nat->external_mac && nat->logical_port) {
> +            smap_add_format(&lr_nats, key, "%-22.18s%-21.17s%s",
> +                            nat->logical_ip, nat->external_mac,
> +                            nat->logical_port);
> +        } else {
> +            smap_add_format(&lr_nats, key, "%s", nat->logical_ip);
> +        }
>      }
>
>      const struct smap_node **nodes = smap_sort(&lr_nats);
>      if (nodes) {
> -        ds_put_format(&ctx->output, "%-17.13s%-19.15s%s\n",
> -                "TYPE", "EXTERNAL_IP", "LOGICAL_IP");
> +        ds_put_format(&ctx->output, "%-17.13s%-19.15s%-22.18s%-21.
> 17s%s\n",
> +                "TYPE", "EXTERNAL_IP", "LOGICAL_IP", "EXTERNAL_MAC",
> +                "LOGICAL_PORT");
>          for (size_t i = 0; i < smap_count(&lr_nats); i++) {
>              const struct smap_node *node = nodes[i];
> -            ds_put_format(&ctx->output, "%-17.13s%s\n",
> +            ds_put_format(&ctx->output, "%-36.32s%s\n",
>                      node->key, node->value);
>          }
>          free(nodes);
> @@ -3314,7 +3353,8 @@ static const struct ctl_command_syntax
> nbctl_commands[] = {
>        "", RO },
>
>      /* NAT commands. */
> -    { "lr-nat-add", 4, 4, "ROUTER TYPE EXTERNAL_IP LOGICAL_IP", NULL,
> +    { "lr-nat-add", 4, 6,
> +      "ROUTER TYPE EXTERNAL_IP LOGICAL_IP [LOGICAL_PORT EXTERNAL_MAC]",
> NULL,
>        nbctl_lr_nat_add, NULL, "--may-exist", RW },
>      { "lr-nat-del", 1, 3, "ROUTER [TYPE [IP]]", NULL,
>          nbctl_lr_nat_del, NULL, "--if-exists", RW },
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index 164c81a..cec516f 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -283,15 +283,34 @@ AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2
> 192.168.1.2/24], [1], [],
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2/24],
> [1], [],
>  [ovn-nbctl: 192.168.1.2/24: should be an IPv4 address.
>  ])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2
> lp0], [1], [],
> +[ovn-nbctl: lr-nat-add with logical_port must also specify external_mac.
> +])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> +[ovn-nbctl: logical_port and external_mac are only valid when type is
> "dnat_and_snat".
> +])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> +[ovn-nbctl: logical_port and external_mac are only valid when type is
> "dnat_and_snat".
> +])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02:03], [1], [],
> +[ovn-nbctl: lp0: port name not found
> +])
> +AT_CHECK([ovn-nbctl ls-add ls0])
> +AT_CHECK([ovn-nbctl lsp-add ls0 lp0])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.2 lp0
> 00:00:00:01:02], [1], [],
> +[ovn-nbctl: invalid mac address 00:00:00:01:02.
> +])
>
>  dnl Add snat and dnat
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24])
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat 30.0.0.1 192.168.1.2])
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.2])
> +AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.2 192.168.1.3 lp0
> 00:00:00:01:02:03])
>  AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP
> +TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
>  dnat             30.0.0.1           192.168.1.2
>  dnat_and_snat    30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.2           192.168.1.3
>  00:00:00:01:02:03    lp0
>  snat             30.0.0.1           192.168.1.0/24
>  ])
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 30.0.0.1 192.168.1.0/24], [1],
> [],
> @@ -318,10 +337,26 @@ AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0
> dnat_and_snat 30.0.0.1 192.168.1.
>  AT_CHECK([ovn-nbctl lr-nat-add lr0 dnat_and_snat 30.0.0.1 192.168.1.3],
> [1], [],
>  [ovn-nbctl: a NAT with this type (dnat_and_snat) and external_ip
> (30.0.0.1) already exists
>  ])
> +AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2
> 192.168.1.3 lp0 00:00:00:04:05:06])
> +AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> +TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> +dnat             30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.2           192.168.1.3
>  00:00:00:04:05:06    lp0
> +snat             30.0.0.1           192.168.1.0/24
> +])
> +AT_CHECK([ovn-nbctl --may-exist lr-nat-add lr0 dnat_and_snat 30.0.0.2
> 192.168.1.3])
> +AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> +TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> +dnat             30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.2           192.168.1.3
> +snat             30.0.0.1           192.168.1.0/24
> +])
>
>  dnl Deletes the NATs
> -AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.2], [1], [],
> -[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and external_ip
> (30.0.0.2)
> +AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.3], [1], [],
> +[ovn-nbctl: no matching NAT with the type (dnat_and_snat) and external_ip
> (30.0.0.3)
>  ])
>  AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat 30.0.0.2], [1], [],
>  [ovn-nbctl: no matching NAT with the type (dnat) and external_ip
> (30.0.0.2)
> @@ -333,14 +368,16 @@ AT_CHECK([ovn-nbctl --if-exists lr-nat-del lr0 snat
> 192.168.10.0/24])
>
>  AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat_and_snat 30.0.0.1])
>  AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP
> +TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
>  dnat             30.0.0.1           192.168.1.2
> +dnat_and_snat    30.0.0.2           192.168.1.3
>  snat             30.0.0.1           192.168.1.0/24
>  ])
>
>  AT_CHECK([ovn-nbctl lr-nat-del lr0 dnat])
>  AT_CHECK([ovn-nbctl lr-nat-list lr0], [0], [dnl
> -TYPE             EXTERNAL_IP        LOGICAL_IP
> +TYPE             EXTERNAL_IP        LOGICAL_IP            EXTERNAL_MAC
>      LOGICAL_PORT
> +dnat_and_snat    30.0.0.2           192.168.1.3
>  snat             30.0.0.1           192.168.1.0/24
>  ])
>
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index 307cbb3..638ac56 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -1145,20 +1145,11 @@ ovn-nbctl lsp-add alice alice1 \
>  -- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>
>  # Add DNAT rules
> -ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" \
> -    logical_ip=192.168.1.2 external_ip=172.16.1.3 \
> -    external_mac=\"00:00:02:02:03:04\" logical_port=foo1 \
> -    -- add logical_router R1 nat @nat
> -
> -ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" \
> -    logical_ip=192.168.1.3 external_ip=172.16.1.4 \
> -    external_mac=\"00:00:02:02:03:05\" logical_port=foo2 \
> -    -- add logical_router R1 nat @nat
> +AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2
> foo1 00:00:02:02:03:04])
> +AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.1.3
> foo2 00:00:02:02:03:05])
>
>  # Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" \
> -    logical_ip=192.168.0.0/16 external_ip=172.16.1.1 \
> -    -- add logical_router R1 nat @nat
> +AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
>
>  OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep ct\( | grep nat])
>
> @@ -1300,20 +1291,11 @@ ovn-nbctl lsp-add alice alice1 \
>  -- lsp-set-addresses alice1 "f0:00:00:01:02:05 172.16.1.2"
>
>  # Add DNAT rules
> -ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" \
> -    logical_ip=192.168.1.2 external_ip=172.16.1.3 \
> -    external_mac=\"00:00:02:02:03:04\" logical_port=foo1 \
> -    -- add logical_router R1 nat @nat
> -
> -ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" \
> -    logical_ip=192.168.2.2 external_ip=172.16.1.4 \
> -    external_mac=\"00:00:02:02:03:05\" logical_port=bar1 \
> -    -- add logical_router R1 nat @nat
> +AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.3 192.168.1.2
> foo1 00:00:02:02:03:04])
> +AT_CHECK([ovn-nbctl lr-nat-add R1 dnat_and_snat 172.16.1.4 192.168.2.2
> bar1 00:00:02:02:03:05])
>
>  # Add a SNAT rule
> -ovn-nbctl -- --id=@nat create nat type="snat" \
> -    logical_ip=192.168.0.0/16 external_ip=172.16.1.1 \
> -    -- add logical_router R1 nat @nat
> +AT_CHECK([ovn-nbctl lr-nat-add R1 snat 172.16.1.1 192.168.0.0/16])
>
>  OVS_WAIT_UNTIL([ovs-ofctl dump-flows br-int | grep ct\( | grep nat])
>
> --
> 1.9.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list