diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 240a464..da77752 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -58,6 +58,7 @@
 #include <rte_debug.h>
 #include <rte_cycles.h>
 #include <rte_memory.h>
+#include <rte_malloc.h>
 #include <rte_memzone.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
@@ -685,6 +686,10 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"flush_flow_diretor (port_id)\n"
 			"    Flush all flow director entries of a device.\n\n"
+
+			"flow_director_flex_payload (port_id)"
+			" (l2|l3|l4) (config)\n"
+			"    configure flexible payload selection.\n\n"
 		);
 	}
 }
@@ -7903,6 +7908,144 @@ cmdline_parse_inst_t cmd_flush_flow_director = {
 	},
 };
 
+/* *** deal with flow director flexible payload configuration *** */
+struct cmd_flow_director_flexpayload_result {
+	cmdline_fixed_string_t flow_director_flexpayload;
+	uint8_t port_id;
+	cmdline_fixed_string_t payload_layer;
+	cmdline_fixed_string_t payload_cfg;
+};
+
+static inline int
+parse_flex_payload_cfg(const char *q_arg,
+			     struct rte_eth_flex_payload_cfg *cfg)
+{
+	char s[256];
+	const char *p, *p0 = q_arg;
+	char *end;
+	enum fieldnames {
+		FLD_OFFSET = 0,
+		FLD_SIZE,
+		_NUM_FLD
+	};
+	unsigned long int_fld[_NUM_FLD];
+	char *str_fld[_NUM_FLD];
+	int i;
+	unsigned size;
+
+	cfg->nb_field = 0;
+	p = strchr(p0, '(');
+	while (p != NULL) {
+		++p;
+		p0 = strchr(p, ')');
+		if (p0 == NULL)
+			return -1;
+
+		size = p0 - p;
+		if (size >= sizeof(s))
+			return -1;
+
+		snprintf(s, sizeof(s), "%.*s", size, p);
+		if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+			return -1;
+		for (i = 0; i < _NUM_FLD; i++) {
+			errno = 0;
+			int_fld[i] = strtoul(str_fld[i], &end, 0);
+			if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+				return -1;
+		}
+		cfg->field[cfg->nb_field].offset = (uint8_t)int_fld[FLD_OFFSET];
+		cfg->field[cfg->nb_field].size = (uint8_t)int_fld[FLD_SIZE];
+		cfg->nb_field++;
+		if (cfg->nb_field > 3) {
+			printf("exceeded max number of fields\n");
+			return -1;
+		}
+		p = strchr(p0, '(');
+	}
+	return 0;
+}
+
+static void
+cmd_flow_director_flxpld_parsed(void *parsed_result,
+			  __attribute__((unused)) struct cmdline *cl,
+			  __attribute__((unused)) void *data)
+{
+	struct cmd_flow_director_flexpayload_result *res = parsed_result;
+	struct rte_eth_fdir_cfg fdir_cfg;
+	struct rte_eth_flex_payload_cfg *flxpld_cfg;
+	int ret = 0;
+	int cfg_size = 3 * sizeof(struct rte_eth_field_vector) +
+		  offsetof(struct rte_eth_flex_payload_cfg, field);
+
+	ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+	if (ret < 0) {
+		printf("flow director is not supported on port %u.\n",
+			res->port_id);
+		return;
+	}
+
+	memset(&fdir_cfg, 0, sizeof(struct rte_eth_fdir_cfg));
+
+	flxpld_cfg = (struct rte_eth_flex_payload_cfg *)rte_zmalloc_socket("CLI",
+		cfg_size, CACHE_LINE_SIZE, rte_socket_id());
+
+	if (flxpld_cfg == NULL) {
+		printf("fail to malloc memory to configure flexible payload\n");
+		return;
+	}
+
+	if (!strcmp(res->payload_layer, "l2"))
+		flxpld_cfg->type = RTE_ETH_L2_PAYLOAD;
+	else if (!strcmp(res->payload_layer, "l3"))
+		flxpld_cfg->type = RTE_ETH_L3_PAYLOAD;
+	else if (!strcmp(res->payload_layer, "l4"))
+		flxpld_cfg->type = RTE_ETH_L4_PAYLOAD;
+
+	ret = parse_flex_payload_cfg(res->payload_cfg, flxpld_cfg);
+	if (ret < 0) {
+		printf("fdir flexpayload parsing error: (%s)\n",
+			strerror(-ret));
+		rte_free(flxpld_cfg);
+		return;
+	}
+	fdir_cfg.cmd = RTE_ETH_FDIR_CFG_FLX;
+	fdir_cfg.cfg = flxpld_cfg;
+	ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+				     RTE_ETH_FILTER_OP_SET, &fdir_cfg);
+	if (ret < 0)
+		printf("fdir flexpayload setting error: (%s)\n",
+			strerror(-ret));
+	rte_free(flxpld_cfg);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexpayload =
+	TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+				 flow_director_flexpayload,
+				 "flow_director_flex_payload");
+cmdline_parse_token_num_t cmd_flow_director_flexpayload_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+			      port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_layer =
+	TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+				 payload_layer, "l2#l3#l4");
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_cfg =
+	TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+				 payload_cfg, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_payload = {
+	.f = cmd_flow_director_flxpld_parsed,
+	.data = NULL,
+	.help_str = "set flow director's flexible payload on NIC",
+	.tokens = {
+		(void *)&cmd_flow_director_flexpayload,
+		(void *)&cmd_flow_director_flexpayload_port_id,
+		(void *)&cmd_flow_director_flexpayload_payload_layer,
+		(void *)&cmd_flow_director_flexpayload_payload_cfg,
+		NULL,
+	},
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -8033,6 +8176,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director,
 	(cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director,
 	(cmdline_parse_inst_t *)&cmd_flush_flow_director,
+	(cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
 	NULL,
 };
 
