diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index 4cb4b18da..a40beeeb0 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -56,6 +56,7 @@ The application has a number of command line options::
                              [--ipv6]
                              [--parse-ptype]
                              [--per-port-pool]
+                             [--lock-free]
 
 Where,
 
@@ -86,6 +87,8 @@ Where,
 
 * ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.
 
+* ``--lock-free:`` Optional, set to enable lock-free table read-write concurrency.
+
 For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,
 while cores 8-15 and 24-31 appear on socket 1.
 
diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
index 293fb1fa2..eaf71d429 100644
--- a/examples/l3fwd/l3fwd.h
+++ b/examples/l3fwd/l3fwd.h
@@ -171,10 +171,10 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
 
 /* Function pointers for LPM or EM functionality. */
 void
-setup_lpm(const int socketid);
+setup_lpm(const int socketid, const unsigned int flags);
 
 void
-setup_hash(const int socketid);
+setup_hash(const int socketid, const unsigned int flags);
 
 int
 em_check_ptype(int portid);
diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c
index 74a7c8fa4..7263ede04 100644
--- a/examples/l3fwd/l3fwd_em.c
+++ b/examples/l3fwd/l3fwd_em.c
@@ -703,7 +703,7 @@ em_main_loop(__attribute__((unused)) void *dummy)
  * Initialize exact match (hash) parameters.
  */
 void
-setup_hash(const int socketid)
+setup_hash(const int socketid, const unsigned int flags)
 {
 	struct rte_hash_parameters ipv4_l3fwd_hash_params = {
 		.name = NULL,
@@ -727,6 +727,10 @@ setup_hash(const int socketid)
 	snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socketid);
 	ipv4_l3fwd_hash_params.name = s;
 	ipv4_l3fwd_hash_params.socket_id = socketid;
+	/* enable lock free hash algorithm for ipv4 forward*/
+	if (flags & RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF)
+		ipv4_l3fwd_hash_params.extra_flag |=
+			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
 	ipv4_l3fwd_em_lookup_struct[socketid] =
 		rte_hash_create(&ipv4_l3fwd_hash_params);
 	if (ipv4_l3fwd_em_lookup_struct[socketid] == NULL)
@@ -738,6 +742,10 @@ setup_hash(const int socketid)
 	snprintf(s, sizeof(s), "ipv6_l3fwd_hash_%d", socketid);
 	ipv6_l3fwd_hash_params.name = s;
 	ipv6_l3fwd_hash_params.socket_id = socketid;
+	/* enable lock free hash algorithm for ipv6 forward*/
+	if (flags & RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF)
+		ipv6_l3fwd_hash_params.extra_flag |=
+			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
 	ipv6_l3fwd_em_lookup_struct[socketid] =
 		rte_hash_create(&ipv6_l3fwd_hash_params);
 	if (ipv6_l3fwd_em_lookup_struct[socketid] == NULL)
diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c
index 4143683cb..1435a5711 100644
--- a/examples/l3fwd/l3fwd_lpm.c
+++ b/examples/l3fwd/l3fwd_lpm.c
@@ -255,7 +255,7 @@ lpm_main_loop(__attribute__((unused)) void *dummy)
 }
 
 void
-setup_lpm(const int socketid)
+setup_lpm(const int socketid, __rte_unused const unsigned int flags)
 {
 	struct rte_lpm6_config config;
 	struct rte_lpm_config config_ipv4;
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 3800bad19..1b435e9eb 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -41,6 +41,7 @@
 #include <rte_udp.h>
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
+#include <rte_hash.h>
 
 #include <cmdline_parse.h>
 #include <cmdline_parse_etheraddr.h>
@@ -76,6 +77,10 @@ static int parse_ptype; /**< Parse packet type using rx callback, and */
 			/**< disabled by default */
 static int per_port_pool; /**< Use separate buffer pools per port; disabled */
 			  /**< by default */
+static int rw_lf;	/**< Enable lock-free read-write concurrency, */
+			/**< disabled by default */
+
+/* Global variables. */
 
 volatile bool force_quit;
 
@@ -139,7 +144,7 @@ static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS];
 static uint8_t lkp_per_socket[NB_SOCKETS];
 
 struct l3fwd_lkp_mode {
-	void  (*setup)(int);
+	void  (*setup)(int, unsigned int);
 	int   (*check_ptype)(int);
 	rte_rx_callback_fn cb_parse_ptype;
 	int   (*main_loop)(void *);
@@ -290,6 +295,7 @@ print_usage(const char *prgname)
 		" [--ipv6]"
 		" [--parse-ptype]"
 		" [--per-port-pool]\n\n"
+		" [--lock-free]\n\n"
 
 		"  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
 		"  -P : Enable promiscuous mode\n"
@@ -304,7 +310,8 @@ print_usage(const char *prgname)
 		"  --hash-entry-num: Specify the hash entry number in hexadecimal to be setup\n"
 		"  --ipv6: Set if running ipv6 packets\n"
 		"  --parse-ptype: Set to use software to analyze packet type\n"
-		"  --per-port-pool: Use separate buffer pool per port\n\n",
+		"  --per-port-pool: Use separate buffer pool per port\n\n"
+		"  --lock-free: Set to enable lock-free table read-write concurrency\n\n",
 		prgname);
 }
 
@@ -458,6 +465,8 @@ static const char short_options[] =
 #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num"
 #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"
 #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool"
+#define CMD_LINE_OPT_LOCK_FREE "lock-free"
+
 enum {
 	/* long options mapped to a short option */
 
@@ -472,6 +481,7 @@ enum {
 	CMD_LINE_OPT_HASH_ENTRY_NUM_NUM,
 	CMD_LINE_OPT_PARSE_PTYPE_NUM,
 	CMD_LINE_OPT_PARSE_PER_PORT_POOL,
+	CMD_LINE_OPT_LOCK_FREE_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -483,6 +493,7 @@ static const struct option lgopts[] = {
 	{CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, CMD_LINE_OPT_HASH_ENTRY_NUM_NUM},
 	{CMD_LINE_OPT_PARSE_PTYPE, 0, 0, CMD_LINE_OPT_PARSE_PTYPE_NUM},
 	{CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL},
+	{CMD_LINE_OPT_LOCK_FREE, 0, 0, CMD_LINE_OPT_LOCK_FREE_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -607,6 +618,10 @@ parse_args(int argc, char **argv)
 			per_port_pool = 1;
 			break;
 
+		case CMD_LINE_OPT_LOCK_FREE_NUM:
+			rw_lf = 1;
+			break;
+
 		default:
 			print_usage(prgname);
 			return -1;
@@ -661,6 +676,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 	int socketid;
 	unsigned lcore_id;
 	char s[64];
+	unsigned int flags = 0;
 
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		if (rte_lcore_is_enabled(lcore_id) == 0)
@@ -695,8 +711,10 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
 			/* Setup either LPM or EM(f.e Hash). But, only once per
 			 * available socket.
 			 */
+			if (rw_lf)
+				flags |= RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
 			if (!lkp_per_socket[socketid]) {
-				l3fwd_lkp.setup(socketid);
+				l3fwd_lkp.setup(socketid, flags);
 				lkp_per_socket[socketid] = 1;
 			}
 		}
