[ovs-dev] [PATCH v1 1/1] ovn-northd: add dhcpv6 stateless option support
Zongkai LI
zealokii at gmail.com
Fri Sep 9 06:39:17 UTC 2016
This patch adds DHCPv6 stateless option support, to allow ovn native dhcpv6
work in stateless mode.
User can add new option dhcpv6_stateless with string value true in
DHCP_Options.options column, to let ovn dhcpv6 only reply other configurations
for DHCPv6 request messages come from VM/VIF ports, and let VM/VIF ports get
their IPv6 addresses configured via stateless way.
Signed-off-by: Zongkai LI <zealokii at gmail.com>
---
ovn/northd/ovn-northd.c | 24 ++++++++++++++++++++---
ovn/ovn-nb.xml | 11 +++++++++++
tests/ovn.at | 51 +++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 1731332..d5d9fcd 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1899,10 +1899,26 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
ipv6_string_mapped(ia_addr, offer_ip);
ds_put_format(options_action,
- REGBIT_DHCP_OPTS_RESULT" = put_dhcpv6_opts(ia_addr = %s, ",
- ia_addr);
+ REGBIT_DHCP_OPTS_RESULT" = put_dhcpv6_opts(");
+
+ struct smap dhcpv6_options = SMAP_INITIALIZER(&dhcpv6_options);
+ smap_clone(&dhcpv6_options, &op->nbsp->dhcpv6_options->options);
+
+ /* Check whether the dhcpv6 options should be configured as stateful.
+ * Only reply with ia_addr option for dhcpv6 stateful address mode. */
+ const char *dhcpv6_stateless = smap_get(
+ &dhcpv6_options, "dhcpv6_stateless");
+ if (!dhcpv6_stateless || strcmp(dhcpv6_stateless, "true")) {
+ char ia_addr[INET6_ADDRSTRLEN + 1];
+ ipv6_string_mapped(ia_addr, offer_ip);
+
+ ds_put_format(options_action, "ia_addr = %s, ", ia_addr);
+ }
+ /* dhcpv6_stateless is not DHCPv6 option, delete it from the smap. */
+ smap_remove(&dhcpv6_options, "dhcpv6_stateless");
+
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, ' ');
@@ -1914,6 +1930,8 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
"udp.dst = 546; outport = inport; flags.loopback = 1; "
"output;",
server_mac, server_ip);
+
+ smap_destroy(&dhcpv6_options);
return true;
}
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 5719e74..9b8c0f0 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -1315,6 +1315,17 @@
Example: <code>"ovn.org"</code>.
</p>
</column>
+
+ <column name="options" key="dhcpv6_stateless">
+ <p>
+ This option specifies the OVN native DHCPv6 will work in stateless
+ mode, which means OVN native DHCPv6 will not offer IPv6 addresses
+ for VM/VIF ports, but only reply other configurations, such as
+ DNS and domain search list. When setting this option with string
+ value "true", VM/VIF will configure IPv6 addresses by stateless
+ way. Default value for this option is false.
+ </p>
+ </column>
</group>
</group>
diff --git a/tests/ovn.at b/tests/ovn.at
index a23b422..1de67b6 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -921,6 +921,9 @@ reg1[0] = put_dhcpv6_opts();
reg1[0] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
formats as reg1[0] = put_dhcpv6_opts(dns_server = {ae70::1, ae70::2});
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.17.00.20.00.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
+reg1[0] = put_dhcpv6_opts(server_id=12:34:56:78:9a:bc, dns_server={ae70::1,ae89::2});
+ formats as reg1[0] = put_dhcpv6_opts(server_id = 12:34:56:78:9a:bc, dns_server = {ae70::1, ae89::2});
+ encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.02.00.06.00.12.34.56.78.9a.bc.17.00.20.00.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.01.ae.89.00.00.00.00.00.00.00.00.00.00.00.00.00.02,pause)
reg1[0] = put_dhcpv6_opts(domain_search = "ovn.org");
encodes as controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.18.00.07.00.6f.76.6e.2e.6f.72.67,pause)
reg1[0] = put_dhcpv6_opts(x = 1.2.3.4);
@@ -3744,7 +3747,7 @@ OVS_APP_EXIT_AND_WAIT([ovsdb-server])
AT_CLEANUP
-AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 2 LSPs/LS])
+AT_SETUP([ovn -- dhcpv6 : 1 HV, 2 LS, 5 LSPs])
AT_KEYWORDS([dhcpv6])
AT_SKIP_IF([test $HAVE_PYTHON = no])
ovn_start
@@ -3760,11 +3763,20 @@ ovn-nbctl lsp-add ls1 ls1-lp2 \
ovn-nbctl lsp-set-port-security ls1-lp2 "f0:00:00:00:00:02 ae70::5"
+ovn-nbctl lsp-add ls1 ls1-lp3 \
+-- lsp-set-addresses ls1-lp3 "f0:00:00:00:00:22 ae70::22"
+
+ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
+
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
+ovn-nbctl -- --id=@d2 create DHCP_Options cidr="ae70\:\:/64" \
+options="\"dhcpv6_stateless\"=\"true\" \"server_id\"=\"00:00:00:10:00:01\"" \
+-- add Logical_Switch_Port ls1-lp3 dhcpv6_options @d2
+
ovn-nbctl ls-add ls2
ovn-nbctl lsp-add ls2 ls2-lp1 \
-- lsp-set-addresses ls2-lp1 "f0:00:00:00:00:03 be70::3"
@@ -3803,6 +3815,12 @@ ovs-vsctl -- add-port br-int hv1-vif4 -- \
options:rxq_pcap=hv1/vif4-rx.pcap \
ofport-request=4
+ovs-vsctl -- add-port br-int hv1-vif5 -- \
+ set interface hv1-vif5 external-ids:iface-id=ls1-lp3 \
+ options:tx_pcap=hv1/vif5-tx.pcap \
+ options:rxq_pcap=hv1/vif5-rx.pcap \
+ ofport-request=5
+
ovn_populate_arp
sleep 2
@@ -3812,8 +3830,8 @@ trim_zeros() {
}
# This shell function sends a DHCPv6 request packet
-# test_dhcp INPORT SRC_MAC DHCPv6_MSG_TYPE OUTPORT...
-# The OUTPORTs (zero or more) list the VIFs on which the original DHCP
+# test_dhcpv6 INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP OUTPORT...
+# The OUTPORTs (zero or more) list the VIFs on which the original DHCPv6
# packet should be received twice (one from ovn-controller and the other
# from the "ovs-ofctl monitor br-int resume"
test_dhcpv6() {
@@ -3835,13 +3853,19 @@ test_dhcpv6() {
if test $msg_code = 01; then
reply_code=02
fi
- local reply=${src_mac}${server_mac}86dd0000000000541101${server_lla}${src_lla}
+ local msg_len=54
+ if test $offer_ip = 1; then
+ msg_len=28
+ fi
+ local reply=${src_mac}${server_mac}86dd0000000000${msg_len}1101${server_lla}${src_lla}
# udp header and dhcpv6 header
- reply+=022302220054ffff${reply_code}010203
+ reply+=0223022200${msg_len}ffff${reply_code}010203
# Client identifier
reply+=0001000a00030001${src_mac}
# IA-NA
- reply+=0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
+ if test $offer_ip != 1; then
+ reply+=0003002801020304ffffffffffffffff00050018${offer_ip}ffffffffffffffff
+ fi
# Server identifier
reply+=0002000a00030001${server_mac}
echo $reply | trim_zeros >> $inport.expected
@@ -3950,6 +3974,21 @@ $PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif4-tx.pcap | trim_zeros > 4.pa
cat 4.expected > expout
AT_CHECK([cat 4.packets], [0], [expout])
+# Send DHCPv6 packet on ls1-lp3. native DHCPv6 works as stateless mode for this port.
+# The DHCPv6 reply should doesn't contian offer_ip.
+src_mac=f00000000022
+src_lla=fe80000000000000f20000fffe000022
+reset_pcap_file hv1-vif5 hv1/vif5
+test_dhcpv6 5 $src_mac $src_lla 01 1 5
+
+# NXT_RESUMEs should be 3.
+OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif5-tx.pcap | trim_zeros > 5.packets
+# Skipping the UDP checksum
+cat 5.expected | cut -c 1-120,125- > expout
+AT_CHECK([cat 5.packets | cut -c 1-120,125- ], [0], [expout])
+
as hv1
OVS_APP_EXIT_AND_WAIT([ovn-controller])
OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
--
2.7.4
More information about the dev
mailing list