[ovs-dev] [PATCH 1/1] Implement DNAT based on destnation port

lg.yue kernelluck at 163.com
Wed Mar 22 09:25:19 UTC 2017


Hi, Guru Shetty:
 the reasons for this patch are:
 1. it should support port range DNAT, LB does not have such needs .
 2. besides  from the view of modularization  this is reasonable, though  working principle is same.




thanks
 






在 2017-03-02 01:09:56,"Guru Shetty" <guru at ovn.org> 写道:





On 28 February 2017 at 19:16, lg.yue <kernelluck at 163.com> wrote:
Add support  for dnat based on destnation port.



A DNAT with a destination port is the same as a Load Balancer with a single endpoint. Load balancer supports adding ports. Can you try using it and tell what is it that it lacks? 

From 0dd41ed18d520c6d61bc23c5fefad5132aa9dadd Mon Sep 17 00:00:00 2001
From: "lg.yue" <yuelongguang at gmail.com>
Date: Wed, 1 Mar 2017 11:07:16 +0800
Subject: [PATCH 1/1] Implement DNAT based on destnation port

Signed-off-by: lg.yue <yuelongguang at gmail.com>
---
 include/ovn/actions.h     |  1 +
 ovn/lib/actions.c         | 11 +++++++
 ovn/lib/lex.c             |  8 +++++
 ovn/northd/ovn-northd.c   | 24 +++++++++++---
 ovn/ovn-nb.ovsschema      |  6 ++--
 ovn/ovn-nb.xml            | 18 ++++++++++
 ovn/utilities/ovn-nbctl.c | 83 ++++++++++++++++++++++++++++++++++-------------
 7 files changed, 122 insertions(+), 29 deletions(-)

diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index d2510fd..f4a9780 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -194,6 +194,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 fff838b..3b8ed28 100644
--- a/ovn/lib/actions.c
+++ b/ovn/lib/actions.c
@@ -746,6 +746,14 @@ parse_ct_nat(struct action_context *ctx, const char *name,
         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;
         }
@@ -822,6 +830,9 @@ encode_ct_nat(const struct ovnact_ct_nat *cn,
             nat->flags |= NX_NAT_F_SRC;
         } else {
             nat->flags |= NX_NAT_F_DST;
+           if (cn->port) {
+                nat->range.proto.min = cn->port;
+            }
         }
     }

diff --git a/ovn/lib/lex.c b/ovn/lib/lex.c
index 4b504cb..9937d9d 100644
--- a/ovn/lib/lex.c
+++ b/ovn/lib/lex.c
@@ -417,6 +417,14 @@ lex_parse_integer__(const char *p, struct lex_token *token)
         char copy[INET6_ADDRSTRLEN];
         memcpy(copy, p, len);
         copy[len] = '\0';
+
+       if (strchr(copy, '.') && strchr(copy, ':')) {
+            char *ps = strchr(copy, ':');
+            int l;
+            l = ps - p;
+            copy[l] = '\0';
+            end = p + l;
+        }

         if (ip_parse(copy, &token->value.ipv4)) {
             token->format = LEX_F_IPV4;
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 03dc850..688c1b7 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1177,7 +1177,6 @@ tag_alloc_create_new_tag(struct hmap *tag_alloc_table,
         nbrec_logical_switch_port_set_tag(nbsp, nbsp->tag_request, 1);
     }
 }
-

 /*
  * This function checks if the MAC in "address" parameter (if present) is
@@ -4355,6 +4354,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
             /* Ingress DNAT table: Packets enter the pipeline with destination
              * IP address that needs to be DNATted from a external IP address
              * to a logical IP address. */
+            int dnat = 0, pro = 100;
             if (!strcmp(nat->type, "dnat")
                 || !strcmp(nat->type, "dnat_and_snat")) {
                 if (!od->l3dgw_port) {
@@ -4365,6 +4365,17 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                     ds_clear(&match);
                     ds_put_format(&match, "ip && ip4.dst == %s",
                                   nat->external_ip);
+                   if(!strcmp(nat->type, "dnat")){
+                       if(nat->eport && nat->protocol){
+                           if(!strcmp(nat->protocol, "tcp")) {
+                               ds_put_format(&match, " && tcp && tcp.dst == %d", (short int)nat->eport);
+                               dnat = 1;
+                           } else if (!strcmp(nat->protocol, "udp")) {
+                               ds_put_format(&match, " && udp && udp.dst == %d", (short int)nat->eport);
+                               dnat = 1;
+                           } else { continue; }
+                       } else { ;}
+                   }
                     ds_clear(&actions);
                     if (dnat_force_snat_ip) {
                         /* Indicate to the future tables that a DNAT has taken
@@ -4373,9 +4384,14 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
                         ds_put_format(&actions,
                                       "flags.force_snat_for_dnat = 1; ");
                     }
-                    ds_put_format(&actions, "flags.loopback = 1; ct_dnat(%s);",
-                                  nat->logical_ip);
-                    ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100,
+
+                   if(dnat) {
+                       pro = 90;
+                        ds_put_format(&actions, "flags.loopback = 1; ct_dnat(%s:%d);", nat->logical_ip, (short int)(nat->lport?:nat->eport));
+                   } else {
+                        ds_put_format(&actions, "flags.loopback = 1; ct_dnat(%s);", nat->logical_ip);
+                   }
+                    ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, pro,
                                   ds_cstr(&match), ds_cstr(&actions));
                 } else {
                     /* Distributed router. */
diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
index dd0ac3d..21bf29a 100644
--- a/ovn/ovn-nb.ovsschema
+++ b/ovn/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
     "version": "5.5.0",
-    "cksum": "2099428463 14236",
+    "cksum": "1556209089 14350",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -229,7 +229,9 @@
                                            "enum": ["set", ["dnat",
                                                              "snat",
                                                              "dnat_and_snat"
-                                                               ]]}}}},
+                                                               ]]}}},
+               "protocol": {"type": "string"},
+               "eport": {"type": {"key": "integer"}}, "lport": {"type": {"key": "integer"}}},
             "isRoot": false},
         "DHCP_Options": {
             "columns": {
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index c5ebbea..ec80ced 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -1276,6 +1276,14 @@
       An IPv4 address.
     </column>

+    <column name="eport">
+      port responding to external_ip.
+    </column>
+
+    <column name="lport">
+      port responding to logical_ip.
+    </column>
+
     <column name="external_mac">
       <p>
         A MAC address.
@@ -1317,6 +1325,16 @@
         port instance on the <code>redirect-chassis</code>.
       </p>
     </column>
+
+     <column name="protocol">
+       <p>
+         Valid protocols are <code>tcp</code> or <code>udp</code> or <code>all</code>.
+          This column is useful when a port number is provided as part of the
+         <code>vips</code> column.  If this column is empty and a port number
+         is provided as part of <code>vips</code> column, OVN assumes the
+         protocol to be <code>tcp</code>.
+       </p>
+     </column>
   </table>

   <table name="DHCP_Options" title="DHCP options">
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index 3dac434..4e376dd 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -2208,7 +2208,8 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
     const char *nat_type = ctx->argv[2];
     const char *external_ip = ctx->argv[3];
     const char *logical_ip = ctx->argv[4];
-    char *new_logical_ip = NULL;
+    ovs_be16 lport = 0, eport = 0;
+    char *new_logical_ip = NULL, *prt = NULL;

     lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);

@@ -2229,6 +2230,15 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
             ctl_fatal("%s: should be an IPv4 address.", logical_ip);
         }
         new_logical_ip = xstrdup(logical_ip);
+
+       if (!strcmp("dnat", nat_type) && ctx->argc > 6) {
+            prt = ctx->argv[5];
+           eport = (ovs_be16)atoi(ctx->argv[6]);
+
+           lport = ctx->argc == 8 ? (ovs_be16)atoi(ctx->argv[7]) : eport;
+       } else {
+               ctl_fatal("lr-nat-add with eport and lport");
+       }
     } else {
         char *error = ip_parse_cidr(logical_ip, &ipv4, &plen);
         if (error) {
@@ -2241,10 +2251,10 @@ nbctl_lr_nat_add(struct ctl_context *ctx)

     const char *logical_port;
     const char *external_mac;
-    if (ctx->argc == 6) {
+    if (ctx->argc == 6 && strcmp(nat_type, "dnat") || ctx->argc == 9 && !strcmp(nat_type, "dnat")) {
         ctl_fatal("lr-nat-add with logical_port "
                   "must also specify external_mac.");
-    } else if (ctx->argc == 7) {
+    } else if (ctx->argc == 7 && strcmp(nat_type, "dnat")) {
         if (strcmp(nat_type, "dnat_and_snat")) {
             ctl_fatal("logical_port and external_mac are only valid when "
                       "type is \"dnat_and_snat\".");
@@ -2258,6 +2268,9 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
         if (!eth_addr_from_string(external_mac, &ea)) {
             ctl_fatal("invalid mac address %s.", external_mac);
         }
+    } else if (ctx->argc == 10 && !strcmp(nat_type, "dnat")) {
+            ctl_fatal("logical_port and external_mac are only valid when "
+                      "type is \"dnat_and_snat\".");
     } else {
         logical_port = NULL;
         external_mac = NULL;
@@ -2272,18 +2285,24 @@ nbctl_lr_nat_add(struct ctl_context *ctx)
                         is_snat ? nat->logical_ip : nat->external_ip)) {
                 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;
-                        }
-                        ctl_fatal("%s, %s: a NAT with this external_ip and "
+                   if ( !strcmp(nat_type, "dnat") && (eport != nat->eport || strcmp(prt, nat->protocol))) {
+                       continue;
+                   }
+                    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;
+                    }
+                    ctl_fatal("%s:%d, %s:%d a NAT with this external_ip and "
                                 "logical_ip already exists",
-                                external_ip, new_logical_ip);
-                } else {
+                                external_ip, (ovs_be16)eport, new_logical_ip, (ovs_be16)lport);
+                } else if (!strcmp("dnat", nat_type)){
+                       if (eport == nat->eport && !strcmp(prt, nat->protocol))
+                           ctl_fatal("A DNAT can not mapped to multiple logical ip");
+               } else {
                         ctl_fatal("a NAT with this type (%s) and %s (%s) "
                                 "already exists",
                                 nat_type,
@@ -2299,6 +2318,11 @@ 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 (!strcmp(nat_type, "dnat")) {
+        nbrec_nat_set_lport(nat, lport);
+        nbrec_nat_set_eport(nat, eport);
+        nbrec_nat_set_protocol(nat, prt);
+    }
     if (logical_port && external_mac) {
         nbrec_nat_set_logical_port(nat, logical_port);
         nbrec_nat_set_external_mac(nat, external_mac);
@@ -2353,12 +2377,25 @@ nbctl_lr_nat_del(struct ctl_context *ctx)
     }

     const char *nat_ip = ctx->argv[3];
+    const char *pt = NULL;
+    ovs_be16 port = 0;
+    if(!strcmp(nat_type, "dnat")) {
+       if (ctx->argc == 6){
+           port = (ovs_be16)atoi(ctx->argv[5]);
+           pt = ctx->argv[4];
+       }
+    }
     int is_snat = !strcmp("snat", nat_type);
     /* Remove the matching NAT. */
     for (size_t i = 0; i < lr->n_nat; i++) {
         struct nbrec_nat *nat = lr->nat[i];
         if (!strcmp(nat_type, nat->type) &&
              !strcmp(nat_ip, is_snat ? nat->logical_ip : nat->external_ip)) {
+           if (!strcmp("dnat", nat_type) && pt && (port != nat->eport || strcmp(pt, nat->protocol))) {
+               continue;
+           } else if (!pt && (nat->eport != 0 || nat->lport != 0)){
+               continue;
+           }
             struct nbrec_nat **new_nats
                 = xmemdup(lr->nat, sizeof *new_nats * lr->n_nat);
             new_nats[i] = lr->nat[lr->n_nat - 1];
@@ -2385,24 +2422,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];
-        const char *key = xasprintf("%-17.13s%s", nat->type, nat->external_ip);
+        const char *key = xasprintf("%-17.13s%-10.10s%-20.17s%-10d", nat->type, nat->protocol, nat->external_ip, (int)nat->eport & 0xffff);
         if (nat->external_mac && nat->logical_port) {
-            smap_add_format(&lr_nats, key, "%-22.18s%-21.17s%s",
-                            nat->logical_ip, nat->external_mac,
+            smap_add_format(&lr_nats, key, "%-20.17s%-10d%-22.17s%s",
+                            nat->logical_ip, (int)nat->lport & 0xffff, nat->external_mac,
                             nat->logical_port);
         } else {
-            smap_add_format(&lr_nats, key, "%s", nat->logical_ip);
+            smap_add_format(&lr_nats, key, "%-20.17s%-10d", nat->logical_ip, (int)nat->lport & 0xffff);
         }
     }

     const struct smap_node **nodes = smap_sort(&lr_nats);
     if (nodes) {
-        ds_put_format(&ctx->output, "%-17.13s%-19.15s%-22.18s%-21.17s%s\n",
-                "TYPE", "EXTERNAL_IP", "LOGICAL_IP", "EXTERNAL_MAC",
+        ds_put_format(&ctx->output, "%-17.13s%-10.10s%-20.17s%-10s%-20.17s%-10s%-22.17s%s\n",
+                "TYPE", "PROTOCOL", "EXTERNAL_IP", "EPORT", "LOGICAL_IP", "LPORT", "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, "%-36.32s%s\n",
+            ds_put_format(&ctx->output, "%-47.57s%s\n",
                     node->key, node->value);
         }
         free(nodes);
@@ -3353,10 +3390,10 @@ static const struct ctl_command_syntax nbctl_commands[] = {
       "", RO },

     /* NAT commands. */
-    { "lr-nat-add", 4, 6,
+    { "lr-nat-add", 4, 8,
       "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,
+    { "lr-nat-del", 1, 6, "ROUTER [TYPE [IP] [PROTOCOL] [PORT]]", NULL,
         nbctl_lr_nat_del, NULL, "--if-exists", RW },
     { "lr-nat-list", 1, 1, "ROUTER", NULL, nbctl_lr_nat_list, NULL, "", RO },

--
1.8.3.1
_______________________________________________
dev mailing list
dev at openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev




More information about the dev mailing list