[ovs-dev] [PATCH RFC v2] ovn-northd: add default_dhcpvx_options for Logical_Switch
Zongkai LI
zealokii at gmail.com
Tue Aug 30 03:48:37 UTC 2016
This patch adds default_dhcpv4_options and default_dhcpv6_options columns for
Logical_Switch, which should help CMS not to calculate and set dhcpv4_options
and dhcpv6_options columns for lswitch ports on lswitchs one by one, when
most of lswitch ports on the same lswitch are using the DHCPv4_Options and
DHCPv6_Options. Default DHCP(v4 and v6) Options should benefit in case
scalling up and DB synchronization between CMS and OVN NB.
v1 -> v2
add ACL lflows support for lswitch ports using default_dhcpvx_options from
lswitch.
---
ovn/northd/ovn-northd.c | 144 ++++++++++++++++++++++++++++++++++++------------
ovn/ovn-nb.ovsschema | 18 +++++-
ovn/ovn-nb.xml | 26 +++++++++
tests/ovn.at | 6 +-
4 files changed, 152 insertions(+), 42 deletions(-)
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 19f3fb1..8919165 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1784,14 +1784,27 @@ static bool
build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
struct ds *options_action, struct ds *response_action)
{
+ char *cidr = NULL;
+ struct smap dhcpv4_options = SMAP_INITIALIZER(&dhcpv4_options);
if (!op->nbsp->dhcpv4_options) {
- /* CMS has disabled native DHCPv4 for this lport. */
- return false;
+ if ((!op->nbsp->use_default_dhcpv4 || *op->nbsp->use_default_dhcpv4)
+ && op->od->nbs->default_dhcpv4_options) {
+ /* Use lswitch default DHCPv4 options for this lport. */
+ cidr = op->od->nbs->default_dhcpv4_options->cidr;
+ smap_clone(&dhcpv4_options,
+ &op->od->nbs->default_dhcpv4_options->options);
+ } else {
+ /* CMS has disabled native DHCPv4 for this lport. */
+ smap_destroy(&dhcpv4_options);
+ return false;
+ }
+ } else {
+ cidr = op->nbsp->dhcpv4_options->cidr;
+ smap_clone(&dhcpv4_options, &op->nbsp->dhcpv4_options->options);
}
ovs_be32 host_ip, mask;
- char *error = ip_parse_masked(op->nbsp->dhcpv4_options->cidr, &host_ip,
- &mask);
+ char *error = ip_parse_masked(cidr, &host_ip, &mask);
if (error || ((offer_ip ^ host_ip) & mask)) {
/* Either
* - cidr defined is invalid or
@@ -1802,14 +1815,10 @@ build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
return false;
}
- const char *server_ip = smap_get(
- &op->nbsp->dhcpv4_options->options, "server_id");
- const char *server_mac = smap_get(
- &op->nbsp->dhcpv4_options->options, "server_mac");
- const char *lease_time = smap_get(
- &op->nbsp->dhcpv4_options->options, "lease_time");
- const char *router = smap_get(
- &op->nbsp->dhcpv4_options->options, "router");
+ const char *server_ip = smap_get(&dhcpv4_options, "server_id");
+ const char *server_mac = smap_get(&dhcpv4_options, "server_mac");
+ const char *lease_time = smap_get(&dhcpv4_options, "lease_time");
+ const char *router = smap_get(&dhcpv4_options, "router");
if (!(server_ip && server_mac && lease_time && router)) {
/* "server_id", "server_mac", "lease_time" and "router" should be
@@ -1820,8 +1829,8 @@ build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
return false;
}
- struct smap dhcpv4_options = SMAP_INITIALIZER(&dhcpv4_options);
- smap_clone(&dhcpv4_options, &op->nbsp->dhcpv4_options->options);
+ char server_mac_str[ETH_ADDR_STRLEN + 1];
+ strcpy(server_mac_str, server_mac);
/* server_mac is not DHCPv4 option, delete it from the smap. */
smap_remove(&dhcpv4_options, "server_mac");
@@ -1845,7 +1854,7 @@ build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
"ip4.dst = "IP_FMT"; ip4.src = %s; udp.src = 67; "
"udp.dst = 68; outport = inport; flags.loopback = 1; "
"output;",
- server_mac, IP_ARGS(offer_ip), server_ip);
+ server_mac_str, IP_ARGS(offer_ip), server_ip);
smap_destroy(&dhcpv4_options);
return true;
@@ -1855,15 +1864,28 @@ static bool
build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
struct ds *options_action, struct ds *response_action)
{
+ char *cidr = NULL;
+ struct smap dhcpv6_options = SMAP_INITIALIZER(&dhcpv6_options);
if (!op->nbsp->dhcpv6_options) {
- /* CMS has disabled native DHCPv6 for this lport. */
- return false;
+ if ((!op->nbsp->use_default_dhcpv6 || *op->nbsp->use_default_dhcpv6)
+ && op->od->nbs->default_dhcpv6_options) {
+ /* Use lswitch default DHCPv6 options for this lport. */
+ cidr = op->od->nbs->default_dhcpv6_options->cidr;
+ smap_clone(&dhcpv6_options,
+ &op->od->nbs->default_dhcpv6_options->options);
+ } else {
+ /* CMS has disabled native DHCPv6 for this lport. */
+ smap_destroy(&dhcpv6_options);
+ return false;
+ }
+ } else {
+ cidr = op->nbsp->dhcpv6_options->cidr;
+ smap_clone(&dhcpv6_options, &op->nbsp->dhcpv6_options->options);
}
struct in6_addr host_ip, mask;
- char *error = ipv6_parse_masked(op->nbsp->dhcpv6_options->cidr, &host_ip,
- &mask);
+ char *error = ipv6_parse_masked(cidr, &host_ip, &mask);
if (error) {
free(error);
return false;
@@ -1877,8 +1899,7 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
}
/* "server_id" should be the MAC address. */
- const char *server_mac = smap_get(&op->nbsp->dhcpv6_options->options,
- "server_id");
+ const char *server_mac = smap_get(&dhcpv6_options, "server_id");
struct eth_addr ea;
if (!server_mac || !eth_addr_from_string(server_mac, &ea)) {
/* "server_id" should be present in the dhcpv6_options. */
@@ -1902,7 +1923,7 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
REGBIT_DHCP_OPTS_RESULT" = put_dhcpv6_opts(ia_addr = %s, ",
ia_addr);
struct smap_node *node;
- SMAP_FOR_EACH (node, &op->nbsp->dhcpv6_options->options) {
+ SMAP_FOR_EACH (node, &dhcpv6_options) {
ds_put_format(options_action, "%s = %s, ", node->key, node->value);
}
ds_chomp(options_action, ' ');
@@ -2324,6 +2345,39 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
/* Add 34000 priority flow to allow DHCP reply from ovn-controller to all
* logical ports of the datapath if the CMS has configured DHCPv4 options*/
+ struct ds od_default_dhcpv4_match = DS_EMPTY_INITIALIZER;
+ if (od->nbs->default_dhcpv4_options) {
+ const char *server_id = smap_get(
+ &od->nbs->default_dhcpv4_options->options, "server_id");
+ const char *server_mac = smap_get(
+ &od->nbs->default_dhcpv4_options->options, "server_mac");
+ const char *lease_time = smap_get(
+ &od->nbs->default_dhcpv4_options->options, "lease_time");
+ const char *router = smap_get(
+ &od->nbs->default_dhcpv4_options->options, "router");
+ if (server_id && server_mac && lease_time && router) {
+ ds_put_format(&od_default_dhcpv4_match, "eth.src == %s "
+ "&& ip4.src == %s && udp && udp.src == 67 "
+ "&& udp.dst == 68",
+ server_mac, server_id);
+ }
+ }
+ struct ds od_default_dhcpv6_match = DS_EMPTY_INITIALIZER;
+ if (od->nbs->default_dhcpv6_options) {
+ const char *server_mac = smap_get(
+ &od->nbs->default_dhcpv6_options->options, "server_id");
+ struct eth_addr ea;
+ if (server_mac && eth_addr_from_string(server_mac, &ea)) {
+ struct in6_addr lla;
+ in6_generate_lla(ea, &lla);
+ char server_ip[INET6_ADDRSTRLEN + 1];
+ ipv6_string_mapped(server_ip, &lla);
+ ds_put_format(&od_default_dhcpv6_match, "eth.src == %s "
+ "&& ip6.src == %s && udp && udp.src == 547 "
+ "&& udp.dst == 546",
+ server_mac, server_ip);
+ }
+ }
for (size_t i = 0; i < od->nbs->n_ports; i++) {
if (od->nbs->ports[i]->dhcpv4_options) {
const char *server_id = smap_get(
@@ -2346,6 +2400,18 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
actions);
}
+ } else if (od_default_dhcpv4_match.length != 0
+ && (!od->nbs->ports[i]->use_default_dhcpv4
+ || *od->nbs->ports[i]->use_default_dhcpv4)) {
+ struct ds match = DS_EMPTY_INITIALIZER;
+ const char *actions =
+ has_stateful ? "ct_commit; next;" : "next;";
+ ds_put_format(&match, "outport == \"%s\" && %s",
+ od->nbs->ports[i]->name,
+ ds_cstr(&od_default_dhcpv4_match));
+ ovn_lflow_add(
+ lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
+ actions);
}
if (od->nbs->ports[i]->dhcpv6_options) {
@@ -2372,6 +2438,18 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
actions);
}
+ } else if (od_default_dhcpv6_match.length != 0
+ && (!od->nbs->ports[i]->use_default_dhcpv6
+ || *od->nbs->ports[i]->use_default_dhcpv6)) {
+ struct ds match = DS_EMPTY_INITIALIZER;
+ const char *actions =
+ has_stateful ? "ct_commit; next;" : "next;";
+ ds_put_format(&match, "outport == \"%s\" && %s",
+ od->nbs->ports[i]->name,
+ ds_cstr(&od_default_dhcpv6_match));
+ ovn_lflow_add(
+ lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
+ actions);
}
}
}
@@ -2664,16 +2742,12 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
continue;
}
- if (!op->nbsp->dhcpv4_options && !op->nbsp->dhcpv6_options) {
- /* CMS has disabled both native DHCPv4 and DHCPv6 for this lport.
- */
- continue;
- }
-
+ struct ds options_action = DS_EMPTY_INITIALIZER;
+ struct ds response_action = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < op->n_lsp_addrs; i++) {
+ ds_clear(&options_action);
+ ds_clear(&response_action);
for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) {
- struct ds options_action = DS_EMPTY_INITIALIZER;
- struct ds response_action = DS_EMPTY_INITIALIZER;
if (build_dhcpv4_action(
op, op->lsp_addrs[i].ipv4_addrs[j].addr,
&options_action, &response_action)) {
@@ -2694,15 +2768,13 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
100, ds_cstr(&match),
ds_cstr(&response_action));
ds_destroy(&match);
- ds_destroy(&options_action);
- ds_destroy(&response_action);
break;
}
}
+ ds_clear(&options_action);
+ ds_clear(&response_action);
for (size_t j = 0; j < op->lsp_addrs[i].n_ipv6_addrs; j++) {
- struct ds options_action = DS_EMPTY_INITIALIZER;
- struct ds response_action = DS_EMPTY_INITIALIZER;
if (build_dhcpv6_action(
op, &op->lsp_addrs[i].ipv6_addrs[j].addr,
&options_action, &response_action)) {
@@ -2722,12 +2794,12 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100,
ds_cstr(&match), ds_cstr(&response_action));
ds_destroy(&match);
- ds_destroy(&options_action);
- ds_destroy(&response_action);
break;
}
}
}
+ ds_destroy(&options_action);
+ ds_destroy(&response_action);
}
/* Ingress table 10 and 11: DHCP options and response, by default goto next.
diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
index 456ae98..0591065 100644
--- a/ovn/ovn-nb.ovsschema
+++ b/ovn/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
- "version": "5.3.1",
- "cksum": "1921908091 9353",
+ "version": "5.4.0",
+ "cksum": "2099971381 10299",
"tables": {
"NB_Global": {
"columns": {
@@ -31,6 +31,16 @@
"refType": "strong"},
"min": 0,
"max": "unlimited"}},
+ "default_dhcpv4_options": {"type": {"key": {"type": "uuid",
+ "refTable": "DHCP_Options",
+ "refType": "weak"},
+ "min": 0,
+ "max": 1}},
+ "default_dhcpv6_options": {"type": {"key": {"type": "uuid",
+ "refTable": "DHCP_Options",
+ "refType": "weak"},
+ "min": 0,
+ "max": 1}},
"other_config": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
@@ -74,6 +84,10 @@
"refType": "weak"},
"min": 0,
"max": 1}},
+ "use_default_dhcpv4": {"type": {"key": "boolean",
+ "min": 0, "max": 1}},
+ "use_default_dhcpv6": {"type": {"key": "boolean",
+ "min": 0, "max": 1}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 5719e74..37b4481 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -119,6 +119,18 @@
Access control rules that apply to packets within the logical switch.
</column>
+ <column name="default_dhcpv4_options">
+ This column defines the DHCPv4 Options would used by ports on switch.
+ Check column <ref column="use_default_dhcpv4"/> in table
+ <ref table="Logical_Switch_Port"/>.
+ </column>
+
+ <column name="default_dhcpv6_options">
+ This column defines the DHCPv6 Options would used by ports on switch.
+ Check column <ref column="use_default_dhcpv6"/> in table
+ <ref table="Logical_Switch_Port"/>.
+ </column>
+
<group title="other_config">
<p>
Additional configuration options for the logical switch.
@@ -609,6 +621,20 @@
Please see the <ref table="DHCP_Options"/> table.
</column>
+ <column name="use_default_dhcpv4">
+ This column defines whether the port should use DHCPv4 Options owned by
+ lswitch. Only when column <ref column="dhcpv4_options"/> is unset or
+ empty, and this column is set to true, port will use DHCPv4 Options
+ owned by lswitch. Default to true.
+ </column>
+
+ <column name="use_default_dhcpv6">
+ This column defines whether the port should use DHCPv6 Options owned by
+ lswitch. Only when column <ref column="dhcpv6_options"/> is unset or
+ empty, and this column is set to true, port will use DHCPv6 Options
+ owned by lswitch. Default to true.
+ </column>
+
<column name="external_ids">
See <em>External IDs</em> at the beginning of this document.
</column>
diff --git a/tests/ovn.at b/tests/ovn.at
index 2fa5d0b..9441d38 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -3502,8 +3502,7 @@ ovn-nbctl lsp-set-port-security ls2-lp2 "f0:00:00:00:00:04 30.0.0.7"
ovn-nbctl -- --id=@d1 create DHCP_Options cidr=10.0.0.0/24 \
options="\"server_id\"=\"10.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:01\" \
\"lease_time\"=\"3600\" \"router\"=\"10.0.0.1\"" \
--- add Logical_Switch_Port ls1-lp1 dhcpv4_options @d1 \
--- add Logical_Switch_Port ls1-lp2 dhcpv4_options @d1
+-- add Logical_Switch ls1 default_dhcpv4_options @d1
ovn-nbctl -- --id=@d2 create DHCP_Options cidr=30.0.0.0/24 \
options="\"server_id\"=\"30.0.0.1\" \"server_mac\"=\"ff:10:00:00:00:02\" \
@@ -3762,8 +3761,7 @@ ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
ovn-nbctl -- --id=@d1 create DHCP_Options cidr="ae70\:\:/64" \
options="\"server_id\"=\"00:00:00:10:00:01\"" \
--- add Logical_Switch_Port ls1-lp1 dhcpv6_options @d1 \
--- add Logical_Switch_Port ls1-lp2 dhcpv6_options @d1
+-- add Logical_Switch ls1 default_dhcpv6_options @d1 \
ovn-nbctl ls-add ls2
ovn-nbctl lsp-add ls2 ls2-lp1 \
--
2.7.4
More information about the dev
mailing list