diff --git a/gtests/net/packetdrill/config.c b/gtests/net/packetdrill/config.c
index 676b2d189ae524edaeafb813644a164c9164aae1..bff0d71efacd9cc2e6c8482829e9149c420a4291 100644
--- a/gtests/net/packetdrill/config.c
+++ b/gtests/net/packetdrill/config.c
@@ -63,6 +63,7 @@ enum option_codes {
 	OPT_UDP_ENCAPS,
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 	OPT_TUN_DEV,
+	OPT_PERSISTENT_TUN_DEV,
 #endif
 };
 
@@ -96,6 +97,7 @@ struct option options[] = {
 	{ "udp_encapsulation",	.has_arg = true,  NULL, OPT_UDP_ENCAPS },
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 	{ "tun_dev",		.has_arg = true,  NULL, OPT_TUN_DEV },
+	{ "persistent_tun_dev",	.has_arg = false, NULL, OPT_PERSISTENT_TUN_DEV },
 #endif
 	{ NULL },
 };
@@ -131,6 +133,7 @@ void show_usage(void)
 		"\t[--udp_encapsulation=[sctp,tcp]]\n"
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 		"\t[--tun_dev=<tun_dev_name>]\n"
+		"\t[--persistent_tun_dev]\n"
 #endif
 		"\tscript_path ...\n");
 }
@@ -345,6 +348,20 @@ void finalize_config(struct config *config)
 			die("wire_server_ip not specified\n");
 		}
 	}
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+	if ((config->tun_device == NULL) &&
+	    (config->persistent_tun_device == true)) {
+		die("tun_dev not specified\n");
+	}
+	if ((config->is_wire_client) || (config->is_wire_server)){
+		if (config->tun_device != NULL) {
+			die("tun_dev specified specified\n");
+		}
+		if (config->persistent_tun_device == true) {
+			die("persistent_tun_dev requested\n");
+		}
+	}
+#endif
 }
 
 /* Expect that arg is comma-delimited, allowing for spaces. */
@@ -498,6 +515,9 @@ static void process_option(int opt, char *optarg, struct config *config,
 	case OPT_TUN_DEV:
 		config->tun_device = strdup(optarg);
 		break;
+	case OPT_PERSISTENT_TUN_DEV:
+		config->persistent_tun_device = true;
+		break;
 #endif
 	default:
 		show_usage();
diff --git a/gtests/net/packetdrill/config.h b/gtests/net/packetdrill/config.h
index 796887dcc49141b6f776edbfa9e79b5bd5c33b67..3ee061d4aa4643e1f8cabdba1cb9fc5456447563 100644
--- a/gtests/net/packetdrill/config.h
+++ b/gtests/net/packetdrill/config.h
@@ -110,6 +110,7 @@ struct config {
 	/* For local testing using a tun interface. */
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
 	char *tun_device;
+	bool persistent_tun_device;
 #endif
 };
 
diff --git a/gtests/net/packetdrill/netdev.c b/gtests/net/packetdrill/netdev.c
index 83f81964c5e884e20c6dfbfb7d7c3a90c5153ba4..d8c9d54d2f30a0a7eb11b30bd646903afa48cd1d 100644
--- a/gtests/net/packetdrill/netdev.c
+++ b/gtests/net/packetdrill/netdev.c
@@ -65,6 +65,7 @@ struct local_netdev {
 	int ipv6_control_fd;	/* fd for IPv6 configuration of tun interface */
 	int index;		/* interface index from if_nametoindex */
 	struct packet_socket *psock;	/* for sniffing packets (owned) */
+	bool persistent;
 };
 
 struct netdev_ops local_netdev_ops;
@@ -88,7 +89,7 @@ static void cleanup_old_device(struct config *config,
 	int result;
 #endif
 
-	if (config->tun_device == NULL) {
+	if ((config->tun_device == NULL) || config->persistent_tun_device) {
 		return;
 	}
 	asprintf(&cleanup_command,
@@ -128,6 +129,7 @@ static void create_device(struct config *config, struct local_netdev *netdev)
 #endif
 
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+	netdev->persistent = config->persistent_tun_device;
 	if (config->tun_device != NULL) {
 		asprintf(&tun_path, "%s/%s", TUN_DIR, config->tun_device);
 	} else {
@@ -351,7 +353,7 @@ static void local_netdev_free(struct netdev *a_netdev)
 	if (netdev->tun_fd >= 0) {
 		close(netdev->tun_fd);
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-		if (netdev->name != NULL) {
+		if ((netdev->name != NULL) && !netdev->persistent) {
 			char *cleanup_command = NULL;
 
 			asprintf(&cleanup_command,