[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