diff mbox series

[ovs-dev,v3] controller: fix ipv6 prefix delegation in gw router mode

Message ID 725495acc0649a90d1fb103155c5c0e819723fdc.1665001000.git.lorenzo.bianconi@redhat.com
State Accepted
Headers show
Series [ovs-dev,v3] controller: fix ipv6 prefix delegation in gw router mode | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Lorenzo Bianconi Oct. 5, 2022, 8:18 p.m. UTC
Fix regression in ipv6 prefix delegation running in gw router mode
introduce by the following commit '04292cc2dc2c ("controller: fix
potential segmentation violation when removing ports")'.

Fixes: 04292cc2dc2c ("controller: fix potential segmentation violation when removing ports")
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2129244
Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2129247
Acked-by: Mark Michelson <mmichels@redhat.com>
Acked-by: Han Zhou <hzhou@ovn.org>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
Changes since v2:
- refactor IPv6 PD system-test
Changes since v1:
- rename need_add_patch_peer_to_local in need_add_peer_to_local
- refactor IPv6 PD system-test
---
 controller/binding.c          |   4 +-
 controller/local_data.c       |  13 ++-
 controller/local_data.h       |   2 +-
 tests/system-common-macros.at | 164 +++++++++++++++++++++++++++++++++-
 tests/system-ovn.at           | 154 ++-----------------------------
 5 files changed, 184 insertions(+), 153 deletions(-)

Comments

Han Zhou Oct. 5, 2022, 11:52 p.m. UTC | #1
On Wed, Oct 5, 2022 at 1:19 PM Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
wrote:
>
> Fix regression in ipv6 prefix delegation running in gw router mode
> introduce by the following commit '04292cc2dc2c ("controller: fix
> potential segmentation violation when removing ports")'.
>
> Fixes: 04292cc2dc2c ("controller: fix potential segmentation violation
when removing ports")
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2129244
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2129247
> Acked-by: Mark Michelson <mmichels@redhat.com>
> Acked-by: Han Zhou <hzhou@ovn.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> ---
> Changes since v2:
> - refactor IPv6 PD system-test
> Changes since v1:
> - rename need_add_patch_peer_to_local in need_add_peer_to_local
> - refactor IPv6 PD system-test
> ---
>  controller/binding.c          |   4 +-
>  controller/local_data.c       |  13 ++-
>  controller/local_data.h       |   2 +-
>  tests/system-common-macros.at | 164 +++++++++++++++++++++++++++++++++-
>  tests/system-ovn.at           | 154 ++-----------------------------
>  5 files changed, 184 insertions(+), 153 deletions(-)
>
> diff --git a/controller/binding.c b/controller/binding.c
> index 8f6b4b19d..c3d2b2e42 100644
> --- a/controller/binding.c
> +++ b/controller/binding.c
> @@ -2666,7 +2666,7 @@ consider_patch_port_for_local_datapaths(const
struct sbrec_port_binding *pb,
>                  get_local_datapath(b_ctx_out->local_datapaths,
>                                     peer->datapath->tunnel_key);
>          }
> -        if (peer_ld && need_add_patch_peer_to_local(
> +        if (peer_ld && need_add_peer_to_local(
>                  b_ctx_in->sbrec_port_binding_by_name, peer,
>                  b_ctx_in->chassis_rec)) {
>              add_local_datapath(
> @@ -2681,7 +2681,7 @@ consider_patch_port_for_local_datapaths(const
struct sbrec_port_binding *pb,
>          /* Add the peer datapath to the local datapaths if it's
>           * not present yet.
>           */
> -        if (need_add_patch_peer_to_local(
> +        if (need_add_peer_to_local(
>                  b_ctx_in->sbrec_port_binding_by_name, pb,
>                  b_ctx_in->chassis_rec)) {
>              add_local_datapath_peer_port(
> diff --git a/controller/local_data.c b/controller/local_data.c
> index 9eee568d1..035f10fff 100644
> --- a/controller/local_data.c
> +++ b/controller/local_data.c
> @@ -115,14 +115,19 @@ local_datapath_destroy(struct local_datapath *ld)
>      free(ld);
>  }
>
> -/* Checks if pb is a patch port and the peer datapath should be added to
local
> - * datapaths. */
> +/* Checks if pb is running on local gw router or pb is a patch port
> + * and the peer datapath should be added to local datapaths. */
>  bool
> -need_add_patch_peer_to_local(
> +need_add_peer_to_local(
>      struct ovsdb_idl_index *sbrec_port_binding_by_name,
>      const struct sbrec_port_binding *pb,
>      const struct sbrec_chassis *chassis)
>  {
> +    /* This port is running on local gw router. */
> +    if (!strcmp(pb->type, "l3gateway") && pb->chassis == chassis) {
> +        return true;
> +    }
> +
>      /* If it is not a patch port, no peer to add. */
>      if (strcmp(pb->type, "patch")) {
>          return false;
> @@ -571,7 +576,7 @@ add_local_datapath__(struct ovsdb_idl_index
*sbrec_datapath_binding_by_key,
>                                              peer_name);
>
>                  if (peer && peer->datapath) {
> -                    if (need_add_patch_peer_to_local(
> +                    if (need_add_peer_to_local(
>                              sbrec_port_binding_by_name, pb, chassis)) {
>                          struct local_datapath *peer_ld =
>
 add_local_datapath__(sbrec_datapath_binding_by_key,
> diff --git a/controller/local_data.h b/controller/local_data.h
> index d898c8aa5..b5429eb58 100644
> --- a/controller/local_data.h
> +++ b/controller/local_data.h
> @@ -66,7 +66,7 @@ struct local_datapath *local_datapath_alloc(
>  struct local_datapath *get_local_datapath(const struct hmap *,
>                                            uint32_t tunnel_key);
>  bool
> -need_add_patch_peer_to_local(
> +need_add_peer_to_local(
>      struct ovsdb_idl_index *sbrec_port_binding_by_name,
>      const struct sbrec_port_binding *,
>      const struct sbrec_chassis *);
> diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
> index 544407bb5..8e6cb415c 100644
> --- a/tests/system-common-macros.at
> +++ b/tests/system-common-macros.at
> @@ -356,4 +356,166 @@ m4_define([OVS_CHECK_CT_CLEAR],
>
>  # OVS_CHECK_CT_ZERO_SNAT()
>  m4_define([OVS_CHECK_CT_ZERO_SNAT],
> -    [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat"
ovs-vswitchd.log])]))
> +    [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat"
ovs-vswitchd.log])])
> +
> +# OVN_TEST_IPV6_PREFIX_DELEGATION()
> +m4_define([OVN_TEST_IPV6_PREFIX_DELEGATION],
> +[
> +ovn_start
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +ADD_BR([br-int])
> +ADD_BR([br-ext])
> +
> +ovs-ofctl add-flow br-ext action=normal
> +# 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
> +
> +ADD_NAMESPACES(sw01)
> +ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> +         "192.168.1.1")
> +ADD_NAMESPACES(sw11)
> +ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
> +         "192.168.2.1")
> +ADD_NAMESPACES(server)
> +ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64",
"f0:00:00:01:02:05", \
> +         "2001:1db8:3333::1")
> +
> +if test X"$1" = X"GR"; then
> +   ovn-nbctl create Logical_Router name=R1 options:chassis=hv1
> +else
> +   ovn-nbctl lr-add R1
> +fi
> +
> +ovn-nbctl ls-add sw0
> +ovn-nbctl ls-add sw1
> +ovn-nbctl ls-add public
> +
> +ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
> +ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
> +ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24
> +
> +if test X"$1" != X"GR"; then
> +    ovn-nbctl lrp-set-gateway-chassis rp-public hv1
> +fi
> +
> +ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
> +    type=router options:router-port=rp-sw0 \
> +    -- lsp-set-addresses sw0-rp router
> +ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
> +    type=router options:router-port=rp-sw1 \
> +    -- lsp-set-addresses sw1-rp router
> +
> +ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
> +    type=router options:router-port=rp-public \
> +    -- lsp-set-addresses public-rp router
> +
> +ovn-nbctl lsp-add sw0 sw01 \
> +    -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
> +
> +ovn-nbctl lsp-add sw1 sw11 \
> +    -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
> +
> +OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep
2001:1db8:3333::2 | grep tentative)" = ""])
> +OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep
tentative)" = ""])
> +
> +AT_CHECK([ovs-vsctl set Open_vSwitch .
external-ids:ovn-bridge-mappings=phynet:br-ext])
> +ovn-nbctl lsp-add public public1 \
> +        -- lsp-set-addresses public1 unknown \
> +        -- lsp-set-type public1 localnet \
> +        -- lsp-set-options public1 network_name=phynet
> +
> +ovn-nbctl set logical_router_port rp-public
options:prefix_delegation=true
> +ovn-nbctl set logical_router_port rp-public options:prefix=true
> +ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
> +ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
> +
> +OVN_POPULATE_ARP
> +
> +ovn-nbctl --wait=hv sync
> +
> +cat > /etc/dhcp/dhcpd.conf <<EOF
> +option dhcp-rebinding-time 15;
> +option dhcp-renewal-time 10;
> +option dhcp6.unicast 2001:1db8:3333::1;
> +subnet6 2001:1db8:3333::/64 {
> +    prefix6 2001:1db8:3333:100:: 2001:1db8:3333:111:: /96;
> +}
> +EOF
> +rm -f /var/lib/dhcp/dhcpd6.leases
> +touch /var/lib/dhcp/dhcpd6.leases
> +chown root:dhcpd /var/lib/dhcp /var/lib/dhcp/dhcpd6.leases
> +chmod 775 /var/lib/dhcp
> +chmod 664 /var/lib/dhcp/dhcpd6.leases
> +
> +NS_CHECK_EXEC([server], [tcpdump -nni s1 > pkt.pcap &])
> +
> +NETNS_DAEMONIZE([server], [dhcpd -6 -f s1 > dhcpd.log 2>&1], [dhcpd.pid])
> +ovn-nbctl --wait=hv sync
> +
> +OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public
ipv6_prefix | cut -c4-15)" = ""])
> +OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0
ipv6_prefix | cut -c4-15)" = ""])
> +OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1
ipv6_prefix | cut -c4-15)" = ""])
> +
> +AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut
-c3-16], [0], [dnl
> +[2001:1db8:3333]
> +])
> +AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut
-c3-16], [0], [dnl
> +[2001:1db8:3333]
> +])
> +AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut
-c3-16], [0], [dnl
> +[2001:1db8:3333]
> +])
> +
> +prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/
'/ipv6_prefix/{print substr($ 1,25,9)}' | sed 's/://g')
> +ovn-nbctl list logical_router_port rp-public > /tmp/rp-public
> +ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
> +ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
> +# Renew message
> +NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and
ip6[[113:4]]=0x${prefix} > renew.pcap &])
> +# Reply message with Status OK
> +NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and
ip6[[81:4]]=0x${prefix} > reply.pcap &])
> +
> +OVS_WAIT_UNTIL([
> +    total_pkts=$(cat renew.pcap | wc -l)
> +    test "${total_pkts}" = "1"
> +])
> +
> +OVS_WAIT_UNTIL([
> +    total_pkts=$(cat reply.pcap | wc -l)
> +    test "${total_pkts}" = "1"
> +])
> +
> +kill $(pidof tcpdump)
> +
> +ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
> +ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
> +OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0
ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
> +AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut
-c3-16], [0], [dnl
> +[]
> +])
> +
> +kill $(pidof 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([NORTHD_TYPE])
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
> +/failed to query port patch-.*/d
> +/.*terminating with signal 15.*/d"])
> +]))
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index d6ecd6eee..20c058415 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -5272,158 +5272,22 @@ AT_CLEANUP
>  ])
>
>  OVN_FOR_EACH_NORTHD([
> -AT_SETUP([IPv6 prefix delegation])
> +AT_SETUP([IPv6 prefix delegation - distributed router])
>  AT_SKIP_IF([test $HAVE_DHCPD = no])
>  AT_SKIP_IF([test $HAVE_TCPDUMP = no])
>  AT_KEYWORDS([ovn-ipv6-prefix_d])
>
> -ovn_start
> -OVS_TRAFFIC_VSWITCHD_START()
> -
> -ADD_BR([br-int])
> -ADD_BR([br-ext])
> -
> -ovs-ofctl add-flow br-ext action=normal
> -# 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
> -
> -ovn-nbctl lr-add R1
> -
> -ovn-nbctl ls-add sw0
> -ovn-nbctl ls-add sw1
> -ovn-nbctl ls-add public
> -
> -ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
> -ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
> -ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 \
> -    -- lrp-set-gateway-chassis rp-public hv1
> -
> -ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
> -    type=router options:router-port=rp-sw0 \
> -    -- lsp-set-addresses sw0-rp router
> -ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
> -    type=router options:router-port=rp-sw1 \
> -    -- lsp-set-addresses sw1-rp router
> -
> -ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
> -    type=router options:router-port=rp-public \
> -    -- lsp-set-addresses public-rp router
> -
> -ADD_NAMESPACES(sw01)
> -ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
> -         "192.168.1.1")
> -ovn-nbctl lsp-add sw0 sw01 \
> -    -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
> -
> -ADD_NAMESPACES(sw11)
> -ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
> -         "192.168.2.1")
> -ovn-nbctl lsp-add sw1 sw11 \
> -    -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
> -
> -ADD_NAMESPACES(server)
> -ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64",
"f0:00:00:01:02:05", \
> -         "2001:1db8:3333::1")
> -
> -OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep
2001:1db8:3333::2 | grep tentative)" = ""])
> -OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep
tentative)" = ""])
> -
> -AT_CHECK([ovs-vsctl set Open_vSwitch .
external-ids:ovn-bridge-mappings=phynet:br-ext])
> -ovn-nbctl lsp-add public public1 \
> -        -- lsp-set-addresses public1 unknown \
> -        -- lsp-set-type public1 localnet \
> -        -- lsp-set-options public1 network_name=phynet
> -
> -ovn-nbctl set logical_router_port rp-public
options:prefix_delegation=true
> -ovn-nbctl set logical_router_port rp-public options:prefix=true
> -ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
> -ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
> -
> -OVN_POPULATE_ARP
> -
> -ovn-nbctl --wait=hv sync
> -
> -cat > /etc/dhcp/dhcpd.conf <<EOF
> -option dhcp-rebinding-time 15;
> -option dhcp-renewal-time 10;
> -option dhcp6.unicast 2001:1db8:3333::1;
> -subnet6 2001:1db8:3333::/64 {
> -    prefix6 2001:1db8:3333:100:: 2001:1db8:3333:111:: /96;
> -}
> -EOF
> -rm -f /var/lib/dhcp/dhcpd6.leases
> -touch /var/lib/dhcp/dhcpd6.leases
> -chown root:dhcpd /var/lib/dhcp /var/lib/dhcp/dhcpd6.leases
> -chmod 775 /var/lib/dhcp
> -chmod 664 /var/lib/dhcp/dhcpd6.leases
> -
> -NETNS_DAEMONIZE([server], [dhcpd -6 -f s1 > dhcpd.log 2>&1], [dhcpd.pid])
> -ovn-nbctl --wait=hv sync
> -
> -OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public
ipv6_prefix | cut -c4-15)" = ""])
> -OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0
ipv6_prefix | cut -c4-15)" = ""])
> -OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1
ipv6_prefix | cut -c4-15)" = ""])
> -
> -AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut
-c3-16], [0], [dnl
> -[2001:1db8:3333]
> -])
> -AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut
-c3-16], [0], [dnl
> -[2001:1db8:3333]
> -])
> -AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut
-c3-16], [0], [dnl
> -[2001:1db8:3333]
> -])
> -
> -prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/
'/ipv6_prefix/{print substr($1,25,9)}' | sed 's/://g')
> -ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
> -ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
> -
> -# Renew message
> -NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and
ip6[[113:4]]=0x${prefix} > renew.pcap &])
> -# Reply message with Status OK
> -NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and
ip6[[81:4]]=0x${prefix} > reply.pcap &])
> -
> -OVS_WAIT_UNTIL([
> -    total_pkts=$(cat renew.pcap | wc -l)
> -    test "${total_pkts}" = "1"
> -])
> -
> -OVS_WAIT_UNTIL([
> -    total_pkts=$(cat reply.pcap | wc -l)
> -    test "${total_pkts}" = "1"
> -])
> -
> -kill $(pidof tcpdump)
> -
> -ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
> -ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
> -OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0
ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
> -AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut
-c3-16], [0], [dnl
> -[]
> +OVN_TEST_IPV6_PREFIX_DELEGATION(DGP)
> +AT_CLEANUP
>  ])
>
> -kill $(pidof 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([NORTHD_TYPE])
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([IPv6 prefix delegation - gw router])
> +AT_SKIP_IF([test $HAVE_DHCPD = no])
> +AT_SKIP_IF([test $HAVE_TCPDUMP = no])
> +AT_KEYWORDS([ovn-ipv6-prefix_d])
>
> -as
> -OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
> -/.*terminating with signal 15.*/d"])
> +OVN_TEST_IPV6_PREFIX_DELEGATION(GR)
>  AT_CLEANUP
>  ])
>
> --
> 2.37.3
>

Thanks Lorenzo! Applied and backported down to branch-22.03.
Han
diff mbox series

Patch

diff --git a/controller/binding.c b/controller/binding.c
index 8f6b4b19d..c3d2b2e42 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -2666,7 +2666,7 @@  consider_patch_port_for_local_datapaths(const struct sbrec_port_binding *pb,
                 get_local_datapath(b_ctx_out->local_datapaths,
                                    peer->datapath->tunnel_key);
         }
-        if (peer_ld && need_add_patch_peer_to_local(
+        if (peer_ld && need_add_peer_to_local(
                 b_ctx_in->sbrec_port_binding_by_name, peer,
                 b_ctx_in->chassis_rec)) {
             add_local_datapath(
@@ -2681,7 +2681,7 @@  consider_patch_port_for_local_datapaths(const struct sbrec_port_binding *pb,
         /* Add the peer datapath to the local datapaths if it's
          * not present yet.
          */
-        if (need_add_patch_peer_to_local(
+        if (need_add_peer_to_local(
                 b_ctx_in->sbrec_port_binding_by_name, pb,
                 b_ctx_in->chassis_rec)) {
             add_local_datapath_peer_port(
diff --git a/controller/local_data.c b/controller/local_data.c
index 9eee568d1..035f10fff 100644
--- a/controller/local_data.c
+++ b/controller/local_data.c
@@ -115,14 +115,19 @@  local_datapath_destroy(struct local_datapath *ld)
     free(ld);
 }
 
-/* Checks if pb is a patch port and the peer datapath should be added to local
- * datapaths. */
+/* Checks if pb is running on local gw router or pb is a patch port
+ * and the peer datapath should be added to local datapaths. */
 bool
-need_add_patch_peer_to_local(
+need_add_peer_to_local(
     struct ovsdb_idl_index *sbrec_port_binding_by_name,
     const struct sbrec_port_binding *pb,
     const struct sbrec_chassis *chassis)
 {
+    /* This port is running on local gw router. */
+    if (!strcmp(pb->type, "l3gateway") && pb->chassis == chassis) {
+        return true;
+    }
+
     /* If it is not a patch port, no peer to add. */
     if (strcmp(pb->type, "patch")) {
         return false;
@@ -571,7 +576,7 @@  add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key,
                                             peer_name);
 
                 if (peer && peer->datapath) {
-                    if (need_add_patch_peer_to_local(
+                    if (need_add_peer_to_local(
                             sbrec_port_binding_by_name, pb, chassis)) {
                         struct local_datapath *peer_ld =
                             add_local_datapath__(sbrec_datapath_binding_by_key,
diff --git a/controller/local_data.h b/controller/local_data.h
index d898c8aa5..b5429eb58 100644
--- a/controller/local_data.h
+++ b/controller/local_data.h
@@ -66,7 +66,7 @@  struct local_datapath *local_datapath_alloc(
 struct local_datapath *get_local_datapath(const struct hmap *,
                                           uint32_t tunnel_key);
 bool
-need_add_patch_peer_to_local(
+need_add_peer_to_local(
     struct ovsdb_idl_index *sbrec_port_binding_by_name,
     const struct sbrec_port_binding *,
     const struct sbrec_chassis *);
diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 544407bb5..8e6cb415c 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -356,4 +356,166 @@  m4_define([OVS_CHECK_CT_CLEAR],
 
 # OVS_CHECK_CT_ZERO_SNAT()
 m4_define([OVS_CHECK_CT_ZERO_SNAT],
-    [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat" ovs-vswitchd.log])]))
+    [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat" ovs-vswitchd.log])])
+
+# OVN_TEST_IPV6_PREFIX_DELEGATION()
+m4_define([OVN_TEST_IPV6_PREFIX_DELEGATION],
+[
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_BR([br-int])
+ADD_BR([br-ext])
+
+ovs-ofctl add-flow br-ext action=normal
+# 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
+
+ADD_NAMESPACES(sw01)
+ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
+         "192.168.1.1")
+ADD_NAMESPACES(sw11)
+ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
+         "192.168.2.1")
+ADD_NAMESPACES(server)
+ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64", "f0:00:00:01:02:05", \
+         "2001:1db8:3333::1")
+
+if test X"$1" = X"GR"; then
+   ovn-nbctl create Logical_Router name=R1 options:chassis=hv1
+else
+   ovn-nbctl lr-add R1
+fi
+
+ovn-nbctl ls-add sw0
+ovn-nbctl ls-add sw1
+ovn-nbctl ls-add public
+
+ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
+ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
+ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24
+
+if test X"$1" != X"GR"; then
+    ovn-nbctl lrp-set-gateway-chassis rp-public hv1
+fi
+
+ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
+    type=router options:router-port=rp-sw0 \
+    -- lsp-set-addresses sw0-rp router
+ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
+    type=router options:router-port=rp-sw1 \
+    -- lsp-set-addresses sw1-rp router
+
+ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
+    type=router options:router-port=rp-public \
+    -- lsp-set-addresses public-rp router
+
+ovn-nbctl lsp-add sw0 sw01 \
+    -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
+
+ovn-nbctl lsp-add sw1 sw11 \
+    -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
+
+OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep 2001:1db8:3333::2 | grep tentative)" = ""])
+OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep tentative)" = ""])
+
+AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext])
+ovn-nbctl lsp-add public public1 \
+        -- lsp-set-addresses public1 unknown \
+        -- lsp-set-type public1 localnet \
+        -- lsp-set-options public1 network_name=phynet
+
+ovn-nbctl set logical_router_port rp-public options:prefix_delegation=true
+ovn-nbctl set logical_router_port rp-public options:prefix=true
+ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
+ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
+
+OVN_POPULATE_ARP
+
+ovn-nbctl --wait=hv sync
+
+cat > /etc/dhcp/dhcpd.conf <<EOF
+option dhcp-rebinding-time 15;
+option dhcp-renewal-time 10;
+option dhcp6.unicast 2001:1db8:3333::1;
+subnet6 2001:1db8:3333::/64 {
+    prefix6 2001:1db8:3333:100:: 2001:1db8:3333:111:: /96;
+}
+EOF
+rm -f /var/lib/dhcp/dhcpd6.leases
+touch /var/lib/dhcp/dhcpd6.leases
+chown root:dhcpd /var/lib/dhcp /var/lib/dhcp/dhcpd6.leases
+chmod 775 /var/lib/dhcp
+chmod 664 /var/lib/dhcp/dhcpd6.leases
+
+NS_CHECK_EXEC([server], [tcpdump -nni s1 > pkt.pcap &])
+
+NETNS_DAEMONIZE([server], [dhcpd -6 -f s1 > dhcpd.log 2>&1], [dhcpd.pid])
+ovn-nbctl --wait=hv sync
+
+OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c4-15)" = ""])
+OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c4-15)" = ""])
+OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c4-15)" = ""])
+
+AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c3-16], [0], [dnl
+[2001:1db8:3333]
+])
+AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
+[2001:1db8:3333]
+])
+AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c3-16], [0], [dnl
+[2001:1db8:3333]
+])
+
+prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/ '/ipv6_prefix/{print substr($ 1,25,9)}' | sed 's/://g')
+ovn-nbctl list logical_router_port rp-public > /tmp/rp-public
+ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
+ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
+# Renew message
+NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and ip6[[113:4]]=0x${prefix} > renew.pcap &])
+# Reply message with Status OK
+NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and ip6[[81:4]]=0x${prefix} > reply.pcap &])
+
+OVS_WAIT_UNTIL([
+    total_pkts=$(cat renew.pcap | wc -l)
+    test "${total_pkts}" = "1"
+])
+
+OVS_WAIT_UNTIL([
+    total_pkts=$(cat reply.pcap | wc -l)
+    test "${total_pkts}" = "1"
+])
+
+kill $(pidof tcpdump)
+
+ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
+ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
+OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
+AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
+[]
+])
+
+kill $(pidof 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([NORTHD_TYPE])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
+/failed to query port patch-.*/d
+/.*terminating with signal 15.*/d"])
+]))
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index d6ecd6eee..20c058415 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -5272,158 +5272,22 @@  AT_CLEANUP
 ])
 
 OVN_FOR_EACH_NORTHD([
-AT_SETUP([IPv6 prefix delegation])
+AT_SETUP([IPv6 prefix delegation - distributed router])
 AT_SKIP_IF([test $HAVE_DHCPD = no])
 AT_SKIP_IF([test $HAVE_TCPDUMP = no])
 AT_KEYWORDS([ovn-ipv6-prefix_d])
 
-ovn_start
-OVS_TRAFFIC_VSWITCHD_START()
-
-ADD_BR([br-int])
-ADD_BR([br-ext])
-
-ovs-ofctl add-flow br-ext action=normal
-# 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
-
-ovn-nbctl lr-add R1
-
-ovn-nbctl ls-add sw0
-ovn-nbctl ls-add sw1
-ovn-nbctl ls-add public
-
-ovn-nbctl lrp-add R1 rp-sw0 00:00:01:01:02:03 192.168.1.1/24
-ovn-nbctl lrp-add R1 rp-sw1 00:00:03:01:02:03 192.168.2.1/24
-ovn-nbctl lrp-add R1 rp-public 00:00:02:01:02:03 172.16.1.1/24 \
-    -- lrp-set-gateway-chassis rp-public hv1
-
-ovn-nbctl lsp-add sw0 sw0-rp -- set Logical_Switch_Port sw0-rp \
-    type=router options:router-port=rp-sw0 \
-    -- lsp-set-addresses sw0-rp router
-ovn-nbctl lsp-add sw1 sw1-rp -- set Logical_Switch_Port sw1-rp \
-    type=router options:router-port=rp-sw1 \
-    -- lsp-set-addresses sw1-rp router
-
-ovn-nbctl lsp-add public public-rp -- set Logical_Switch_Port public-rp \
-    type=router options:router-port=rp-public \
-    -- lsp-set-addresses public-rp router
-
-ADD_NAMESPACES(sw01)
-ADD_VETH(sw01, sw01, br-int, "192.168.1.2/24", "f0:00:00:01:02:03", \
-         "192.168.1.1")
-ovn-nbctl lsp-add sw0 sw01 \
-    -- lsp-set-addresses sw01 "f0:00:00:01:02:03 192.168.1.2"
-
-ADD_NAMESPACES(sw11)
-ADD_VETH(sw11, sw11, br-int, "192.168.2.2/24", "f0:00:00:02:02:03", \
-         "192.168.2.1")
-ovn-nbctl lsp-add sw1 sw11 \
-    -- lsp-set-addresses sw11 "f0:00:00:02:02:03 192.168.2.2"
-
-ADD_NAMESPACES(server)
-ADD_VETH(s1, server, br-ext, "2001:1db8:3333::2/64", "f0:00:00:01:02:05", \
-         "2001:1db8:3333::1")
-
-OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep 2001:1db8:3333::2 | grep tentative)" = ""])
-OVS_WAIT_UNTIL([test "$(ip netns exec server ip a | grep fe80 | grep tentative)" = ""])
-
-AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext])
-ovn-nbctl lsp-add public public1 \
-        -- lsp-set-addresses public1 unknown \
-        -- lsp-set-type public1 localnet \
-        -- lsp-set-options public1 network_name=phynet
-
-ovn-nbctl set logical_router_port rp-public options:prefix_delegation=true
-ovn-nbctl set logical_router_port rp-public options:prefix=true
-ovn-nbctl set logical_router_port rp-sw0 options:prefix=true
-ovn-nbctl set logical_router_port rp-sw1 options:prefix=true
-
-OVN_POPULATE_ARP
-
-ovn-nbctl --wait=hv sync
-
-cat > /etc/dhcp/dhcpd.conf <<EOF
-option dhcp-rebinding-time 15;
-option dhcp-renewal-time 10;
-option dhcp6.unicast 2001:1db8:3333::1;
-subnet6 2001:1db8:3333::/64 {
-    prefix6 2001:1db8:3333:100:: 2001:1db8:3333:111:: /96;
-}
-EOF
-rm -f /var/lib/dhcp/dhcpd6.leases
-touch /var/lib/dhcp/dhcpd6.leases
-chown root:dhcpd /var/lib/dhcp /var/lib/dhcp/dhcpd6.leases
-chmod 775 /var/lib/dhcp
-chmod 664 /var/lib/dhcp/dhcpd6.leases
-
-NETNS_DAEMONIZE([server], [dhcpd -6 -f s1 > dhcpd.log 2>&1], [dhcpd.pid])
-ovn-nbctl --wait=hv sync
-
-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c4-15)" = ""])
-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c4-15)" = ""])
-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c4-15)" = ""])
-
-AT_CHECK([ovn-nbctl get logical_router_port rp-public ipv6_prefix | cut -c3-16], [0], [dnl
-[2001:1db8:3333]
-])
-AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
-[2001:1db8:3333]
-])
-AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c3-16], [0], [dnl
-[2001:1db8:3333]
-])
-
-prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/ '/ipv6_prefix/{print substr($1,25,9)}' | sed 's/://g')
-ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
-ovn-nbctl set logical_router_port rp-sw1 options:prefix=false
-
-# Renew message
-NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and ip6[[113:4]]=0x${prefix} > renew.pcap &])
-# Reply message with Status OK
-NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and ip6[[81:4]]=0x${prefix} > reply.pcap &])
-
-OVS_WAIT_UNTIL([
-    total_pkts=$(cat renew.pcap | wc -l)
-    test "${total_pkts}" = "1"
-])
-
-OVS_WAIT_UNTIL([
-    total_pkts=$(cat reply.pcap | wc -l)
-    test "${total_pkts}" = "1"
-])
-
-kill $(pidof tcpdump)
-
-ovn-nbctl set logical_router_port rp-sw0 options:prefix=false
-ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix
-OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"])
-AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0], [dnl
-[]
+OVN_TEST_IPV6_PREFIX_DELEGATION(DGP)
+AT_CLEANUP
 ])
 
-kill $(pidof 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([NORTHD_TYPE])
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([IPv6 prefix delegation - gw router])
+AT_SKIP_IF([test $HAVE_DHCPD = no])
+AT_SKIP_IF([test $HAVE_TCPDUMP = no])
+AT_KEYWORDS([ovn-ipv6-prefix_d])
 
-as
-OVS_TRAFFIC_VSWITCHD_STOP(["/.*error receiving.*/d
-/.*terminating with signal 15.*/d"])
+OVN_TEST_IPV6_PREFIX_DELEGATION(GR)
 AT_CLEANUP
 ])