Message ID | df85460db21e9e6d4977801b965b35623edb5377.1575542805.git.lorenzo.bianconi@redhat.com |
---|---|
State | Superseded |
Headers | show |
Series | Add IPv6 Prefix delegation (RFC3633) | expand |
On Thu, Dec 5, 2019 at 5:51 AM Lorenzo Bianconi <lorenzo.bianconi@redhat.com> wrote: > > Introduce logical flows in ovn router pipeline in order to parse dhcpv6 > advertise/reply from IPv6 prefix delegation router. > Do not overwrite ipv6_ra_pd_list info in options column of SB port_binding > table written by ovn-controller > > Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> > --- > northd/ovn-northd.c | 69 +++++++++++++++++++++++++++- > ovn-nb.xml | 17 +++++++ > tests/atlocal.in | 5 +- > tests/system-ovn.at | 109 ++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 198 insertions(+), 2 deletions(-) > > diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c > index f0847d81e..8c50218ee 100644 > --- a/northd/ovn-northd.c > +++ b/northd/ovn-northd.c > @@ -2644,6 +2644,8 @@ ovn_port_update_sbrec(struct northd_context *ctx, > struct sset *active_ha_chassis_grps) > { > sbrec_port_binding_set_datapath(op->sb, op->od->sb); > + const char *ipv6_pd_list = NULL; > + > if (op->nbrp) { > /* If the router is for l3 gateway, it resides on a chassis > * and its port type is "l3gateway". */ > @@ -2766,6 +2768,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, > smap_add(&new, "l3gateway-chassis", chassis_name); > } > } > + > + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); > + if (ipv6_pd_list) { > + smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list); > + } > + > sbrec_port_binding_set_options(op->sb, &new); > smap_destroy(&new); > > @@ -2815,6 +2823,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, > smap_add_format(&options, > "qdisc_queue_id", "%d", queue_id); > } > + > + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); > + if (ipv6_pd_list) { > + smap_add(&options, "ipv6_ra_pd_list", ipv6_pd_list); > + } > + > sbrec_port_binding_set_options(op->sb, &options); > smap_destroy(&options); > if (ovn_is_known_nb_lsp_type(op->nbsp->type)) { > @@ -2864,6 +2878,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, > if (chassis) { > smap_add(&new, "l3gateway-chassis", chassis); > } > + > + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); > + if (ipv6_pd_list) { > + smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list); > + } > + > sbrec_port_binding_set_options(op->sb, &new); > smap_destroy(&new); > } else { > @@ -7833,7 +7853,36 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, > free(snat_ips); > } > > - /* Logical router ingress table 3: IP Input for IPv6. */ > + /* DHCPv6 reply handling */ > + HMAP_FOR_EACH (op, key_node, ports) { > + if (!op->nbrp) { > + continue; > + } > + > + if (op->derived) { > + continue; > + } > + > + struct lport_addresses lrp_networks; > + if (!extract_lrp_networks(op->nbrp, &lrp_networks)) { > + continue; > + } > + > + for (size_t i = 0; i < lrp_networks.n_ipv6_addrs; i++) { > + ds_clear(&actions); > + ds_clear(&match); > + ds_put_format(&match, "ip6.dst == %s && udp.src == 547 &&" > + " udp.dst == 546", > + lrp_networks.ipv6_addrs[i].addr_s); > + ds_put_format(&actions, "reg0 = 0; handle_dhcpv6_reply { " > + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " > + "outport <-> inport; output; };"); > + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100, > + ds_cstr(&match), ds_cstr(&actions)); > + } > + } > + > + /* Logical router ingress table 1: IP Input for IPv6. */ > HMAP_FOR_EACH (op, key_node, ports) { > if (!op->nbrp) { > continue; > @@ -8634,6 +8683,24 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, > continue; > } > > + struct smap options; > + /* enable IPv6 prefix delegation */ > + bool prefix_delegation = smap_get_bool(&op->nbrp->options, > + "prefix_delegation", false); > + if (prefix_delegation) { > + smap_clone(&options, &op->sb->options); > + smap_add(&options, "ipv6_prefix_delegation", "true"); > + sbrec_port_binding_set_options(op->sb, &options); > + smap_destroy(&options); > + } > + > + if (smap_get_bool(&op->nbrp->options, "prefix", false)) { > + smap_clone(&options, &op->sb->options); > + smap_add(&options, "ipv6_prefix", "true"); > + sbrec_port_binding_set_options(op->sb, &options); > + smap_destroy(&options); > + } > + > const char *address_mode = smap_get( > &op->nbrp->ipv6_ra_configs, "address_mode"); > > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 5ae52bbde..d7fddcae2 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -2142,6 +2142,23 @@ > to <code>true</code>. > </p> > </column> > + > + <column name="options" key="prefix_delegation" > + type='{"type": "boolean"}'> > + <p> > + If set to <code>true</code>, enable IPv6 prefix delegation state > + machine on this logical router port (RFC3633). IPv6 prefix > + delegation is available just on a gateway router or on a gateway > + router port. > + </p> > + </column> > + > + <column name="options" key="prefix" type='{"type": "boolean"}'> > + <p> > + If set to <code>true</code>, this interface will receive an IPv6 > + prefix according to RFC3663 > + </p> > + </column> > </group> > > <group title="Attachment"> > diff --git a/tests/atlocal.in b/tests/atlocal.in > index 5f14c3da0..8f3ff03b9 100644 > --- a/tests/atlocal.in > +++ b/tests/atlocal.in > @@ -157,7 +157,7 @@ find_command() > { > which $1 > /dev/null 2>&1 > status=$? > - var=HAVE_`echo "$1" | tr '[a-z]' '[A-Z]'` > + var=HAVE_`echo "$1" | tr '-' '_' | tr '[a-z]' '[A-Z]'` > if test "$status" = "0"; then > eval ${var}="yes" > else > @@ -192,6 +192,9 @@ else > DIFF_SUPPORTS_NORMAL_FORMAT=no > fi > > +# Set HAVE_DIBBLER-SERVER > +find_command dibbler-server > + > # Turn off proxies. > unset http_proxy > unset https_proxy > diff --git a/tests/system-ovn.at b/tests/system-ovn.at > index 1a5b0bb7e..dbff58f24 100644 > --- a/tests/system-ovn.at > +++ b/tests/system-ovn.at > @@ -3425,3 +3425,112 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d > /connection dropped.*/d"]) > > AT_CLEANUP > + > +AT_SETUP([ovn -- IPv6 prefix delegation]) > +AT_SKIP_IF([test $HAVE_DIBBLER_SERVER = no]) > +AT_KEYWORDS([ovn-ipv6-prefix_d]) > + > +ovn_start > +OVS_TRAFFIC_VSWITCHD_START() > +ADD_BR([br-int]) > + > +# Set external-ids in br-int needed for ovn-controller > +ovs-vsctl \ > + -- set Open_vSwitch . external-ids:system-id=hv1 \ > + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ > + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ > + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ > + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true > + > +# Start ovn-controller > +start_daemon ovn-controller > + > +# Logical network: > +# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24), > +# and alice (172.16.1.0/24) connected to it. The port between R1 and > +# alice is the router gateway port where the R1 NAT rules are applied. > +# > +# R1 -- join -- dibbler-server > +# | > +# bar > + > +ovn-nbctl lr-add R1 > + > +ovn-nbctl ls-add bar > +ovn-nbctl ls-add join > + > +ovn-nbctl lrp-add R1 bar 00:00:01:01:02:03 192.168.1.1/24 > +ovn-nbctl lrp-add R1 join 00:00:02:01:02:03 172.16.1.1/24 2001:db8:3333::1/64 \ > + -- set Logical_Router_Port join options:redirect-chassis=hv1 > + > +# Connect bar to R1 > +ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \ > + type=router options:router-port=bar \ > + -- lsp-set-addresses rp-bar router > + > +# Connect join to R1 > +ovn-nbctl lsp-add join rp-join -- set Logical_Switch_Port rp-join \ > + type=router options:router-port=join \ > + -- lsp-set-addresses rp-join router > + > +# Logical port 'bar1' in switch 'bar'. > +ADD_NAMESPACES(bar1) > +ADD_VETH(bar1, bar1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \ > + "192.168.1.1") > +ovn-nbctl lsp-add bar bar1 \ > +-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2" > + > +# Logical port 'join1' in switch 'join'. > +ADD_NAMESPACES(join1) > +ADD_VETH(join1, join1, br-int, "2001:db8:3333::2/64", "f0:00:00:01:02:05", \ > + "2001:db8:3333::1") > +OVS_WAIT_UNTIL([test "$(ip netns exec join1 ip a | grep 2001:db8:3333::2 | grep tentative)" = ""]) > +ovn-nbctl lsp-add join join1 \ > +-- lsp-set-addresses join1 "f0:00:00:01:02:05 2001:db8:3333::2" > + > +ovn-nbctl set logical_router_port join options:prefix_delegation=true > +ovn-nbctl set logical_router_port join options:prefix=true > + > +# reset dibbler state > +sed s/eth0/join1/g -i /etc/dibbler/server.conf > +cat > /var/lib/dibbler/server-AddrMgr.xml <<EOF > +<AddrMgr> > + <timestamp>1575481348</timestamp> > + <replayDetection>0</replayDetection> > +</AddrMgr> > +EOF > +cat > /var/lib/dibbler/server-CfgMgr.xml <<EOF > +<SrvCfgMgr> > + <workDir>/var/lib/dibbler</workDir> > + <LogName>Server</LogName> > + <LogLevel>8</LogLevel> > + <InactiveMode>0</InactiveMode> > + <GuessMode>0</GuessMode> > +</SrvCfgMgr> > +EOF > + > +NS_CHECK_EXEC([join1], [dibbler-server run &]) I think it's better to start dibbler-server in a port attached to the provider bridge instead of br-int. Also can you please add another logical router port and make sure that prefix delegation address is learnt in both the router ports. Something like LR1 - Public (with localnet port) - SW0 -> address learnt for this router port - SW1 -> address learnt for this router port. Thanks Numan > +ovn-nbctl --wait=hv sync > + > +OVS_WAIT_UNTIL([ovn-sbctl list port_binding join | grep ipv6_ra_pd_list]) > +AT_CHECK([ovn-sbctl get port_binding join options:ipv6_ra_pd_list], [0], [dnl > +"\"2001:db8:3333::6a2f:0:0\"/96" > +]) > +kill $(pidof dibbler-server) > + > +sleep 2 > +OVS_APP_EXIT_AND_WAIT([ovn-controller]) > + > +as ovn-sb > +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > + > +as ovn-nb > +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) > + > +as northd > +OVS_APP_EXIT_AND_WAIT([ovn-northd]) > + > +as > +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d > +/connection dropped.*/d"]) > +AT_CLEANUP > -- > 2.21.0 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev >
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index f0847d81e..8c50218ee 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -2644,6 +2644,8 @@ ovn_port_update_sbrec(struct northd_context *ctx, struct sset *active_ha_chassis_grps) { sbrec_port_binding_set_datapath(op->sb, op->od->sb); + const char *ipv6_pd_list = NULL; + if (op->nbrp) { /* If the router is for l3 gateway, it resides on a chassis * and its port type is "l3gateway". */ @@ -2766,6 +2768,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, smap_add(&new, "l3gateway-chassis", chassis_name); } } + + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); + if (ipv6_pd_list) { + smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list); + } + sbrec_port_binding_set_options(op->sb, &new); smap_destroy(&new); @@ -2815,6 +2823,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, smap_add_format(&options, "qdisc_queue_id", "%d", queue_id); } + + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); + if (ipv6_pd_list) { + smap_add(&options, "ipv6_ra_pd_list", ipv6_pd_list); + } + sbrec_port_binding_set_options(op->sb, &options); smap_destroy(&options); if (ovn_is_known_nb_lsp_type(op->nbsp->type)) { @@ -2864,6 +2878,12 @@ ovn_port_update_sbrec(struct northd_context *ctx, if (chassis) { smap_add(&new, "l3gateway-chassis", chassis); } + + ipv6_pd_list = smap_get(&op->sb->options, "ipv6_ra_pd_list"); + if (ipv6_pd_list) { + smap_add(&new, "ipv6_ra_pd_list", ipv6_pd_list); + } + sbrec_port_binding_set_options(op->sb, &new); smap_destroy(&new); } else { @@ -7833,7 +7853,36 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, free(snat_ips); } - /* Logical router ingress table 3: IP Input for IPv6. */ + /* DHCPv6 reply handling */ + HMAP_FOR_EACH (op, key_node, ports) { + if (!op->nbrp) { + continue; + } + + if (op->derived) { + continue; + } + + struct lport_addresses lrp_networks; + if (!extract_lrp_networks(op->nbrp, &lrp_networks)) { + continue; + } + + for (size_t i = 0; i < lrp_networks.n_ipv6_addrs; i++) { + ds_clear(&actions); + ds_clear(&match); + ds_put_format(&match, "ip6.dst == %s && udp.src == 547 &&" + " udp.dst == 546", + lrp_networks.ipv6_addrs[i].addr_s); + ds_put_format(&actions, "reg0 = 0; handle_dhcpv6_reply { " + "eth.dst <-> eth.src; ip6.dst <-> ip6.src; " + "outport <-> inport; output; };"); + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100, + ds_cstr(&match), ds_cstr(&actions)); + } + } + + /* Logical router ingress table 1: IP Input for IPv6. */ HMAP_FOR_EACH (op, key_node, ports) { if (!op->nbrp) { continue; @@ -8634,6 +8683,24 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, continue; } + struct smap options; + /* enable IPv6 prefix delegation */ + bool prefix_delegation = smap_get_bool(&op->nbrp->options, + "prefix_delegation", false); + if (prefix_delegation) { + smap_clone(&options, &op->sb->options); + smap_add(&options, "ipv6_prefix_delegation", "true"); + sbrec_port_binding_set_options(op->sb, &options); + smap_destroy(&options); + } + + if (smap_get_bool(&op->nbrp->options, "prefix", false)) { + smap_clone(&options, &op->sb->options); + smap_add(&options, "ipv6_prefix", "true"); + sbrec_port_binding_set_options(op->sb, &options); + smap_destroy(&options); + } + const char *address_mode = smap_get( &op->nbrp->ipv6_ra_configs, "address_mode"); diff --git a/ovn-nb.xml b/ovn-nb.xml index 5ae52bbde..d7fddcae2 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -2142,6 +2142,23 @@ to <code>true</code>. </p> </column> + + <column name="options" key="prefix_delegation" + type='{"type": "boolean"}'> + <p> + If set to <code>true</code>, enable IPv6 prefix delegation state + machine on this logical router port (RFC3633). IPv6 prefix + delegation is available just on a gateway router or on a gateway + router port. + </p> + </column> + + <column name="options" key="prefix" type='{"type": "boolean"}'> + <p> + If set to <code>true</code>, this interface will receive an IPv6 + prefix according to RFC3663 + </p> + </column> </group> <group title="Attachment"> diff --git a/tests/atlocal.in b/tests/atlocal.in index 5f14c3da0..8f3ff03b9 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -157,7 +157,7 @@ find_command() { which $1 > /dev/null 2>&1 status=$? - var=HAVE_`echo "$1" | tr '[a-z]' '[A-Z]'` + var=HAVE_`echo "$1" | tr '-' '_' | tr '[a-z]' '[A-Z]'` if test "$status" = "0"; then eval ${var}="yes" else @@ -192,6 +192,9 @@ else DIFF_SUPPORTS_NORMAL_FORMAT=no fi +# Set HAVE_DIBBLER-SERVER +find_command dibbler-server + # Turn off proxies. unset http_proxy unset https_proxy diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 1a5b0bb7e..dbff58f24 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -3425,3 +3425,112 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d /connection dropped.*/d"]) AT_CLEANUP + +AT_SETUP([ovn -- IPv6 prefix delegation]) +AT_SKIP_IF([test $HAVE_DIBBLER_SERVER = no]) +AT_KEYWORDS([ovn-ipv6-prefix_d]) + +ovn_start +OVS_TRAFFIC_VSWITCHD_START() +ADD_BR([br-int]) + +# Set external-ids in br-int needed for ovn-controller +ovs-vsctl \ + -- set Open_vSwitch . external-ids:system-id=hv1 \ + -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ + -- set bridge br-int fail-mode=secure other-config:disable-in-band=true + +# Start ovn-controller +start_daemon ovn-controller + +# Logical network: +# One LR R1 with switches foo (192.168.1.0/24), bar (192.168.2.0/24), +# and alice (172.16.1.0/24) connected to it. The port between R1 and +# alice is the router gateway port where the R1 NAT rules are applied. +# +# R1 -- join -- dibbler-server +# | +# bar + +ovn-nbctl lr-add R1 + +ovn-nbctl ls-add bar +ovn-nbctl ls-add join + +ovn-nbctl lrp-add R1 bar 00:00:01:01:02:03 192.168.1.1/24 +ovn-nbctl lrp-add R1 join 00:00:02:01:02:03 172.16.1.1/24 2001:db8:3333::1/64 \ + -- set Logical_Router_Port join options:redirect-chassis=hv1 + +# Connect bar to R1 +ovn-nbctl lsp-add bar rp-bar -- set Logical_Switch_Port rp-bar \ + type=router options:router-port=bar \ + -- lsp-set-addresses rp-bar router + +# Connect join to R1 +ovn-nbctl lsp-add join rp-join -- set Logical_Switch_Port rp-join \ + type=router options:router-port=join \ + -- lsp-set-addresses rp-join router + +# Logical port 'bar1' in switch 'bar'. +ADD_NAMESPACES(bar1) +ADD_VETH(bar1, bar1, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \ + "192.168.1.1") +ovn-nbctl lsp-add bar bar1 \ +-- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2" + +# Logical port 'join1' in switch 'join'. +ADD_NAMESPACES(join1) +ADD_VETH(join1, join1, br-int, "2001:db8:3333::2/64", "f0:00:00:01:02:05", \ + "2001:db8:3333::1") +OVS_WAIT_UNTIL([test "$(ip netns exec join1 ip a | grep 2001:db8:3333::2 | grep tentative)" = ""]) +ovn-nbctl lsp-add join join1 \ +-- lsp-set-addresses join1 "f0:00:00:01:02:05 2001:db8:3333::2" + +ovn-nbctl set logical_router_port join options:prefix_delegation=true +ovn-nbctl set logical_router_port join options:prefix=true + +# reset dibbler state +sed s/eth0/join1/g -i /etc/dibbler/server.conf +cat > /var/lib/dibbler/server-AddrMgr.xml <<EOF +<AddrMgr> + <timestamp>1575481348</timestamp> + <replayDetection>0</replayDetection> +</AddrMgr> +EOF +cat > /var/lib/dibbler/server-CfgMgr.xml <<EOF +<SrvCfgMgr> + <workDir>/var/lib/dibbler</workDir> + <LogName>Server</LogName> + <LogLevel>8</LogLevel> + <InactiveMode>0</InactiveMode> + <GuessMode>0</GuessMode> +</SrvCfgMgr> +EOF + +NS_CHECK_EXEC([join1], [dibbler-server run &]) +ovn-nbctl --wait=hv sync + +OVS_WAIT_UNTIL([ovn-sbctl list port_binding join | grep ipv6_ra_pd_list]) +AT_CHECK([ovn-sbctl get port_binding join options:ipv6_ra_pd_list], [0], [dnl +"\"2001:db8:3333::6a2f:0:0\"/96" +]) +kill $(pidof dibbler-server) + +sleep 2 +OVS_APP_EXIT_AND_WAIT([ovn-controller]) + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([ovn-northd]) + +as +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d +/connection dropped.*/d"]) +AT_CLEANUP
Introduce logical flows in ovn router pipeline in order to parse dhcpv6 advertise/reply from IPv6 prefix delegation router. Do not overwrite ipv6_ra_pd_list info in options column of SB port_binding table written by ovn-controller Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com> --- northd/ovn-northd.c | 69 +++++++++++++++++++++++++++- ovn-nb.xml | 17 +++++++ tests/atlocal.in | 5 +- tests/system-ovn.at | 109 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 2 deletions(-)