summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ofproto/ofproto-dpif.c28
-rw-r--r--tests/system-interface.at59
2 files changed, 68 insertions, 19 deletions
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index f87e27a8c..fad7342b0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -714,12 +714,6 @@ close_dpif_backer(struct dpif_backer *backer, bool del)
free(backer);
}
-/* Datapath port slated for removal from datapath. */
-struct odp_garbage {
- struct ovs_list list_node;
- odp_port_t odp_port;
-};
-
static void check_support(struct dpif_backer *backer);
static int
@@ -729,8 +723,6 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
struct dpif_port_dump port_dump;
struct dpif_port port;
struct shash_node *node;
- struct ovs_list garbage_list;
- struct odp_garbage *garbage;
struct sset names;
char *backer_name;
@@ -792,25 +784,23 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
dpif_flow_flush(backer->dpif);
}
- /* Loop through the ports already on the datapath and remove any
- * that we don't need anymore. */
- ovs_list_init(&garbage_list);
+ /* Loop through the ports already on the datapath and find ones that are
+ * not on the initial OpenFlow ports list. These are stale ports, that we
+ * do not need anymore, or tunnel backing interfaces, that do not generally
+ * match the name of OpenFlow tunnel ports, or both. Add all of them to
+ * the list of tunnel backers. type_run() will garbage collect those that
+ * are not active tunnel backing interfaces during revalidation. */
dpif_port_dump_start(&port_dump, backer->dpif);
while (dpif_port_dump_next(&port_dump, &port)) {
node = shash_find(&init_ofp_ports, port.name);
if (!node && strcmp(port.name, dpif_base_name(backer->dpif))) {
- garbage = xmalloc(sizeof *garbage);
- garbage->odp_port = port.port_no;
- ovs_list_push_front(&garbage_list, &garbage->list_node);
+ simap_put(&backer->tnl_backers, port.name,
+ odp_to_u32(port.port_no));
+ backer->need_revalidate = REV_RECONFIGURE;
}
}
dpif_port_dump_done(&port_dump);
- LIST_FOR_EACH_POP (garbage, list_node, &garbage_list) {
- dpif_port_del(backer->dpif, garbage->odp_port, false);
- free(garbage);
- }
-
shash_add(&all_dpif_backers, type, backer);
check_support(backer);
diff --git a/tests/system-interface.at b/tests/system-interface.at
index 784bada12..3bf339582 100644
--- a/tests/system-interface.at
+++ b/tests/system-interface.at
@@ -63,3 +63,62 @@ AT_CHECK([
[stdout], [Device "br-p1" does not exist.]
)
AT_CLEANUP
+
+AT_SETUP([interface - datapath ports garbage collection])
+OVS_CHECK_GENEVE()
+OVS_TRAFFIC_VSWITCHD_START()
+
+dnl Not relevant for userspace datapath.
+AT_SKIP_IF([! ovs-appctl dpctl/show | grep -q ovs-system])
+
+AT_CHECK([ovs-vsctl add-port br0 tunnel_port dnl
+ -- set Interface tunnel_port dnl
+ type=geneve options:remote_ip=flow options:key=123])
+
+AT_CHECK([ip link add ovs-veth0 type veth peer name ovs-veth1])
+on_exit 'ip link del ovs-veth0'
+
+AT_CHECK([ovs-vsctl add-port br0 ovs-veth0])
+
+OVS_WAIT_UNTIL([ip link show | grep -q " genev_sys_[[0-9]]*: .* ovs-system "])
+
+dnl Store the output of ip link for geneve port to compare ifindex later.
+AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " > geneve.0])
+
+AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
+ port 0: ovs-system (internal)
+ port 1: br0 (internal)
+ port 2: genev_sys_6081 (geneve: packet_type=ptap)
+ port 3: ovs-veth0
+])
+
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([ovs-vswitchd], [ovs-vswitchd.pid])
+
+dnl Check that geneve backing interface is still in the datapath.
+AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " | diff -u - geneve.0])
+
+dnl Remove the veth port from the database while ovs-vswitchd is down.
+AT_CHECK([ovs-vsctl --no-wait del-port ovs-veth0])
+
+dnl Check that it is still tied to the OVS datapath.
+AT_CHECK([ip link show ovs-veth0 | grep -q ovs-system])
+
+dnl Bring ovs-vswitchd back up.
+AT_CHECK([ovs-vswitchd --detach --no-chdir --pidfile --log-file -vdpif:dbg],
+ [0], [], [stderr])
+
+dnl Wait for the veth port to be removed from the datapath.
+OVS_WAIT_WHILE([ip link show ovs-veth0 | grep -q ovs-system])
+
+AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
+ port 0: ovs-system (internal)
+ port 1: br0 (internal)
+ port 2: genev_sys_6081 (geneve: packet_type=ptap)
+])
+
+dnl Check that geneve backing interface is still in the datapath and it wasn't
+dnl re-created, i.e. the ifindex is the same.
+AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " | diff -u - geneve.0])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP