Skip to content

Commit

Permalink
controller: fix ipv6 prefix delegation in gw router mode
Browse files Browse the repository at this point in the history
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: 04292cc ("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>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Han Zhou <hzhou@ovn.org>
(cherry picked from commit f83263c)
  • Loading branch information
LorenzoBianconi authored and hzhou8 committed Oct 5, 2022
1 parent f87e14f commit dcf50d7
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 153 deletions.
4 changes: 2 additions & 2 deletions controller/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -2391,7 +2391,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(
Expand All @@ -2406,7 +2406,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(
Expand Down
13 changes: 9 additions & 4 deletions controller/local_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,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;
Expand Down Expand Up @@ -543,7 +548,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,
Expand Down
2 changes: 1 addition & 1 deletion controller/local_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,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 *);
Expand Down
164 changes: 163 additions & 1 deletion tests/system-common-macros.at
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
]))
154 changes: 9 additions & 145 deletions tests/system-ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -5267,158 +5267,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
])

Expand Down

0 comments on commit dcf50d7

Please sign in to comment.