diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 4799bc90c..214b8a625 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -198,7 +198,10 @@ struct app_sa_prm app_sa_prm = {
 			.cache_sz = SA_CACHE_SZ
 		};
 static const char *cfgfile;
-
+static const char *ddp_file;
+static const char *ddp_bkp_file;
+static uint16_t fdir_portid;
+static int16_t ddp_unload_flag;
 struct lcore_rx_queue {
 	uint16_t port_id;
 	uint8_t queue_id;
@@ -1286,6 +1289,8 @@ print_usage(const char *prgname)
 		" [-e]"
 		" [-a]"
 		" [-c]"
+		" [-L (portid,ddp_file_path,ddp_backup_file_path)]"
+		" [-U (portid,ddp_backup_file_path)]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--single-sa SAIDX]"
@@ -1307,6 +1312,8 @@ print_usage(const char *prgname)
 		"  -a enables SA SQN atomic behaviour\n"
 		"  -c specifies inbound SAD cache size,\n"
 		"     zero value disables the cache (default value: 128)\n"
+		"  -L To load ddp profile on NIC\n"
+		"  -U To unload ddp profile from NIC\n"
 		"  -f CONFIG_FILE: Configuration file\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --single-sa SAIDX: Use single SA index for outbound traffic,\n"
@@ -1379,6 +1386,33 @@ parse_decimal(const char *str)
 	return num;
 }
 
+static int32_t
+parse_ddp_load_args(char *str)
+{
+	int16_t num_args = 0;
+	char *file_fld[3];
+	num_args = rte_strsplit(str, strlen(str), file_fld, 3, ',');
+	if (num_args != 3)
+		return -1;
+	fdir_portid = atoi(file_fld[0]);
+	ddp_file = file_fld[1];
+	ddp_bkp_file = file_fld[2];
+	return 0;
+}
+
+static int32_t
+parse_ddp_unload_args(char *str)
+{
+	int16_t num_args = 0;
+	char *file_fld[2];
+	num_args = rte_strsplit(str, strlen(str), file_fld, 2, ',');
+	if (num_args != 2)
+		return -1;
+	fdir_portid = atoi(file_fld[0]);
+	ddp_bkp_file = file_fld[1];
+	return 0;
+}
+
 static int32_t
 parse_config(const char *q_arg)
 {
@@ -1459,7 +1493,7 @@ parse_args(int32_t argc, char **argv)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:L:U:f:j:w:c:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1483,6 +1517,25 @@ parse_args(int32_t argc, char **argv)
 				return -1;
 			}
 			break;
+		case 'L':
+			printf("Loading ddp package selected\n");
+			ret = parse_ddp_load_args(optarg);
+			if (ret < 0) {
+				printf("Invalid ddp load args: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			break;
+		case 'U':
+			printf("Unloading ddp package selected\n");
+			ret = parse_ddp_unload_args(optarg);
+			if (ret < 0) {
+				printf("Invalid ddp unload args: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			ddp_unload_flag = 1;
+			break;
 		case 'f':
 			if (f_present == 1) {
 				printf("\"-f\" option present more than "
@@ -2505,6 +2558,16 @@ main(int32_t argc, char **argv)
 		sa_check_offloads(portid, &req_rx_offloads, &req_tx_offloads);
 		port_init(portid, req_rx_offloads, req_tx_offloads);
 	}
+	if (ddp_file != NULL && ddp_bkp_file != NULL) {
+		ret = load_ddp_esp_package(fdir_portid, ddp_file, ddp_bkp_file);
+		if (ret < 0)
+			printf("loading ddp package failed\n");
+	}
+	if (ddp_unload_flag && ddp_bkp_file != NULL) {
+		ret = unload_ddp_esp_package(fdir_portid, ddp_bkp_file);
+		if (ret < 0)
+			printf("unloading ddp package failed\n");
+	}
 
 	cryptodevs_init();
 
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 6e8120702..3840a0848 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -4,6 +4,9 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #include <rte_branch_prediction.h>
 #include <rte_log.h>
@@ -14,6 +17,9 @@
 #include <rte_ethdev.h>
 #include <rte_mbuf.h>
 #include <rte_hash.h>
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
 
 #include "ipsec.h"
 #include "esp.h"
@@ -155,6 +161,158 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 	return 0;
 }
 
+static int
+close_file(uint8_t *buf)
+{
+	if (buf) {
+		free((void *)buf);
+		return 0;
+	}
+
+	return -1;
+}
+
+static uint8_t *
+open_file(const char *file_path, uint32_t *size)
+{
+	int fd = open(file_path, O_RDONLY);
+	off_t pkg_size;
+	uint8_t *buf = NULL;
+	int ret = 0;
+	struct stat st_buf;
+
+	if (size)
+		*size = 0;
+
+	if (fd == -1) {
+		printf("%s: Failed to open %s\n", __func__, file_path);
+		return buf;
+	}
+
+	if ((fstat(fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
+		close(fd);
+		printf("%s: File operations failed\n", __func__);
+		return buf;
+	}
+
+	pkg_size = st_buf.st_size;
+	if (pkg_size < 0) {
+		close(fd);
+		printf("%s: File operations failed\n", __func__);
+		return buf;
+	}
+
+	buf = (uint8_t *)malloc(pkg_size);
+	if (!buf) {
+		close(fd);
+		printf("%s: Failed to malloc memory\n",	__func__);
+		return buf;
+	}
+
+	ret = read(fd, buf, pkg_size);
+	if (ret < 0) {
+		close(fd);
+		printf("%s: File read operation failed\n", __func__);
+		close_file(buf);
+		return NULL;
+	}
+
+	if (size)
+		*size = pkg_size;
+
+	close(fd);
+
+	return buf;
+}
+
+static int
+save_file(const char *file_path, uint8_t *buf, uint32_t size)
+{
+	FILE *fh = fopen(file_path, "wb");
+
+	if (fh == NULL) {
+		printf("%s: Failed to open %s\n", __func__, file_path);
+		return -1;
+	}
+
+	if (fwrite(buf, 1, size, fh) != size) {
+		fclose(fh);
+		printf("%s: File write operation failed\n", __func__);
+		return -1;
+	}
+
+	fclose(fh);
+
+	return 0;
+}
+
+/* Load dynamic device personalization profile */
+int
+load_ddp_esp_package(uint16_t fdir_portid, const char *ddp_file,
+		const char *ddp_bkp_file)
+{
+	uint8_t *buff;
+	uint32_t size;
+	int ret = -ENOTSUP;
+
+	buff = open_file(ddp_file, &size);
+	if (!buff)
+		return -1;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+	ret = rte_pmd_i40e_process_ddp_package(fdir_portid,
+					       buff, size,
+					       RTE_PMD_I40E_PKG_OP_WR_ADD);
+#endif
+
+	if (ret == -EEXIST)
+		printf("Profile has already existed.\n");
+	else if (ret < 0) {
+		printf("Failed to load profile.\n");
+		close_file(buff);
+		return -1;
+	} else
+		printf("loading ddp profile success\n");
+	if (ddp_bkp_file != NULL)
+		save_file(ddp_bkp_file, buff, size);
+
+	close_file(buff);
+	return 0;
+}
+
+/* Unload dynamic device personalization profile */
+int
+unload_ddp_esp_package(uint16_t fdir_portid, const char *ddp_bkp_file)
+{
+
+	uint8_t *buff;
+	uint32_t size;
+	int ret = -ENOTSUP;
+
+	buff = open_file(ddp_bkp_file, &size);
+	if (!buff)
+		return -1;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+	ret = rte_pmd_i40e_process_ddp_package(fdir_portid,
+					       buff, size,
+					       RTE_PMD_I40E_PKG_OP_WR_DEL);
+#endif
+
+	if (ret == -EACCES) {
+		printf("Profile does not exist.\n");
+		close_file(buff);
+		return -1;
+	} else if (ret < 0) {
+		printf("Failed to delete profile.\n");
+		close_file(buff);
+		return -1;
+	} else
+		printf("ddp profile deleted successfully\n");
+	close_file(buff);
+	return 0;
+}
+
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 4f2fd6184..73eec47ab 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -383,5 +383,9 @@ create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
 int
 create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
 		struct rte_ipsec_session *ips);
-
+int
+load_ddp_esp_package(uint16_t fdir_portid, const char *ddp_file,
+		const char *ddp_bkp_file);
+int
+unload_ddp_esp_package(uint16_t fdir_portid, const char *ddp_bkp_file);
 #endif /* __IPSEC_H__ */
