diff --git a/tools/testing/selftests/xsk/Makefile b/tools/testing/selftests/xsk/Makefile
index 472d8975fa5a..79d106b30922 100644
--- a/tools/testing/selftests/xsk/Makefile
+++ b/tools/testing/selftests/xsk/Makefile
@@ -10,7 +10,9 @@ TEST_PROGS := TEST_PREREQUISITES.sh \
 	TEST_XSK_SKB_NOPOLL.sh \
 	TEST_XSK_SKB_POLL.sh \
 	TEST_XSK_DRV_NOPOLL.sh \
-	TEST_XSK_DRV_POLL.sh
+	TEST_XSK_DRV_POLL.sh \
+	TEST_XSK_SKB_TEARDOWN.sh \
+	TEST_XSK_DRV_TEARDOWN.sh
 TEST_FILES := prereqs.sh xskenv.sh
 TEST_TRANSIENT_FILES := veth.spec
 TEST_PROGS_EXTENDED := $(XSKDIR)/$(XSKOBJ)
diff --git a/tools/testing/selftests/xsk/README b/tools/testing/selftests/xsk/README
index 0088c136a0d1..e2ae3c804bfb 100644
--- a/tools/testing/selftests/xsk/README
+++ b/tools/testing/selftests/xsk/README
@@ -63,6 +63,9 @@ The following tests are run:
    generic XDP path. XDP hook from netif_receive_skb().
    a. nopoll - soft-irq processing
    b. poll - using poll() syscall
+   c. Socket Teardown
+      Create a Tx and a Rx socket, Tx from one socket, Rx on another. Destroy
+      both sockets, then repeat multiple times. Only nopoll mode is used
 
 2. AF_XDP DRV/Native mode
    Works on any netdevice with XDP_REDIRECT support, driver dependent. Processes
@@ -70,10 +73,11 @@ The following tests are run:
    hook available just after DMA of buffer descriptor.
    a. nopoll
    b. poll
+   c. Socket Teardown
    * Only copy mode is supported because veth does not currently support
      zero-copy mode
 
-Total tests: 4.
+Total tests: 6.
 
 Flow:
 * Single process spawns two threads: Tx and Rx
diff --git a/tools/testing/selftests/xsk/TEST_XSK_DRV_POLL.sh b/tools/testing/selftests/xsk/TEST_XSK_DRV_POLL.sh
index 05e6c0372074..fbad353f0000 100755
--- a/tools/testing/selftests/xsk/TEST_XSK_DRV_POLL.sh
+++ b/tools/testing/selftests/xsk/TEST_XSK_DRV_POLL.sh
@@ -15,7 +15,4 @@ execxdpxceiver params
 retval=$?
 test_status $retval "${TEST_NAME}"
 
-# Must be called in the last test to execute
-cleanup_exit ${VETH0} ${VETH1} ${NS1}
-
 test_exit $retval 0
diff --git a/tools/testing/selftests/xsk/TEST_XSK_DRV_TEARDOWN.sh b/tools/testing/selftests/xsk/TEST_XSK_DRV_TEARDOWN.sh
new file mode 100755
index 000000000000..1867f3c07d74
--- /dev/null
+++ b/tools/testing/selftests/xsk/TEST_XSK_DRV_TEARDOWN.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright(c) 2020 Intel Corporation.
+
+. prereqs.sh
+. xskenv.sh
+
+TEST_NAME="DRV SOCKET TEARDOWN"
+
+vethXDPnative ${VETH0} ${VETH1} ${NS1}
+
+params=("-N" "-T")
+execxdpxceiver params
+
+retval=$?
+test_status $retval "${TEST_NAME}"
+
+# Must be called in the last test to execute
+cleanup_exit ${VETH0} ${VETH1} ${NS1}
+
+test_exit $retval 0
diff --git a/tools/testing/selftests/xsk/TEST_XSK_SKB_TEARDOWN.sh b/tools/testing/selftests/xsk/TEST_XSK_SKB_TEARDOWN.sh
new file mode 100755
index 000000000000..51be8f30163d
--- /dev/null
+++ b/tools/testing/selftests/xsk/TEST_XSK_SKB_TEARDOWN.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright(c) 2020 Intel Corporation.
+
+. prereqs.sh
+. xskenv.sh
+
+TEST_NAME="SKB SOCKET TEARDOWN"
+
+vethXDPgeneric ${VETH0} ${VETH1} ${NS1}
+
+params=("-S" "-T")
+execxdpxceiver params
+
+retval=$?
+test_status $retval "${TEST_NAME}"
+
+test_exit $retval 0
diff --git a/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.c b/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.c
index 777f839bbd3a..6877b59f4534 100644
--- a/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.c
+++ b/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.c
@@ -49,7 +49,8 @@ static void __exit_with_error(int error, const char *file, const char *func, int
 #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__)
 
 #define print_ksft_result(void)\
-	(ksft_test_result_pass("PASS: %s %s\n", uut ? "DRV" : "SKB", opt_poll ? "POLL" : "NOPOLL"))
+	(ksft_test_result_pass("PASS: %s %s %s\n", uut ? "DRV" : "SKB", opt_poll ? "POLL" :\
+			       "NOPOLL", opt_teardown ? "Socket Teardown" : ""))
 
 static void pthread_init_mutex(void)
 {
@@ -274,6 +275,7 @@ static struct option long_options[] = {
 	{"xdp-skb", no_argument, 0, 'S'},
 	{"xdp-native", no_argument, 0, 'N'},
 	{"copy", no_argument, 0, 'c'},
+	{"tear-down", no_argument, 0, 'T'},
 	{"debug", optional_argument, 0, 'D'},
 	{"tx-pkt-count", optional_argument, 0, 'C'},
 	{0, 0, 0, 0}
@@ -290,6 +292,7 @@ static void usage(const char *prog)
 	    "  -S, --xdp-skb=n      Use XDP SKB mode\n"
 	    "  -N, --xdp-native=n   Enforce XDP DRV (native) mode\n"
 	    "  -c, --copy           Force copy mode\n"
+	    "  -T, --tear-down      Tear down sockets by repeatedly recreating them\n"
 	    "  -D, --debug          Debug mode - dump packets L2 - L5\n"
 	    "  -C, --tx-pkt-count=n Number of packets to send\n";
 	ksft_print_msg(str, prog);
@@ -380,7 +383,7 @@ static void parse_command_line(int argc, char **argv)
 	opterr = 0;
 
 	for (;;) {
-		c = getopt_long(argc, argv, "i:q:pSNcDC:", long_options, &option_index);
+		c = getopt_long(argc, argv, "i:q:pSNcTDC:", long_options, &option_index);
 
 		if (c == -1)
 			break;
@@ -418,6 +421,9 @@ static void parse_command_line(int argc, char **argv)
 		case 'c':
 			opt_xdp_bind_flags |= XDP_COPY;
 			break;
+		case 'T':
+			opt_teardown = 1;
+			break;
 		case 'D':
 			debug_pkt_dump = 1;
 			break;
@@ -806,6 +812,9 @@ static void *worker_testapp_validate(void *arg)
 
 		ksft_print_msg("Received %d packets on interface %s\n",
 			       pkt_counter, ((struct ifobject *)arg)->ifname);
+
+		if (opt_teardown)
+			ksft_print_msg("Destroying socket\n");
 	}
 
 	xsk_socket__delete(((struct ifobject *)arg)->xsk->xsk);
@@ -851,6 +860,20 @@ static void testapp_validate(void)
 		free(pkt_buf);
 	}
 
+	if (!opt_teardown)
+		print_ksft_result();
+}
+
+static void testapp_sockets(void)
+{
+	for (int i = 0; i < MAX_TEARDOWN_ITER; i++) {
+		pkt_counter = 0;
+		prev_pkt = -1;
+		sigvar = 0;
+		ksft_print_msg("Creating socket\n");
+		testapp_validate();
+	}
+
 	print_ksft_result();
 }
 
@@ -917,7 +940,7 @@ int main(int argc, char **argv)
 
 	ksft_set_plan(1);
 
-	testapp_validate();
+	opt_teardown ? testapp_sockets() : testapp_validate();
 
 	for (int i = 0; i < MAX_INTERFACES; i++)
 		free(ifdict[i]);
diff --git a/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.h b/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.h
index 91ddc01836c9..41fc62adad3b 100644
--- a/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.h
+++ b/tools/testing/selftests/xsk/xdpprogs/xdpxceiver.h
@@ -21,6 +21,7 @@
 #define MAX_INTERFACE_NAME_CHARS 7
 #define MAX_INTERFACES_NAMESPACE_CHARS 10
 #define MAX_SOCKS 1
+#define MAX_TEARDOWN_ITER 10
 #define PKT_HDR_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
 			sizeof(struct udphdr))
 #define MIN_PKT_SIZE 64
@@ -56,6 +57,7 @@ static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static int opt_queue;
 static int opt_pkt_count;
 static int opt_poll;
+static int opt_teardown;
 static u32 opt_xdp_bind_flags = XDP_USE_NEED_WAKEUP;
 static u8 pkt_data[XSK_UMEM__DEFAULT_FRAME_SIZE];
 static u32 pkt_counter;
