diff --git a/drivers/net/atlantic/Makefile b/drivers/net/atlantic/Makefile
index 966676b..7aef5a1 100644
--- a/drivers/net/atlantic/Makefile
+++ b/drivers/net/atlantic/Makefile
@@ -33,8 +33,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_utils.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_llh.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_utils_fw2x.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_b0.c
-SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += rte_pmd_atlantic.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += mdio.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += macsec_api.c
+SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += atl_sec.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c
index b2b3bd3..13b017d 100644
--- a/drivers/net/atlantic/atl_ethdev.c
+++ b/drivers/net/atlantic/atl_ethdev.c
@@ -13,6 +13,8 @@
 #include "hw_atl/hw_atl_llh.h"
 #include "hw_atl/hw_atl_b0.h"
 #include "hw_atl/hw_atl_b0_internal.h"
+#include "atl_sec.h"
+
 
 static int eth_atl_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_atl_dev_uninit(struct rte_eth_dev *eth_dev);
@@ -119,6 +121,7 @@ static int eth_atl_pci_remove(struct rte_pci_device *pci_dev);
 
 static int atl_dev_info_get(struct rte_eth_dev *dev,
 				struct rte_eth_dev_info *dev_info);
+static int atl_macsec_ctx_create(struct rte_eth_dev *dev);
 
 int atl_logtype_init;
 int atl_logtype_driver;
@@ -204,7 +207,7 @@ enum atl_xstats_type {
 
 #define ATL_MACSEC_XSTATS_FIELD(name) { \
 	#name, \
-	offsetof(struct macsec_stats, name), \
+	offsetof(struct atl_macsec_stats, name), \
 	XSTATS_TYPE_MACSEC \
 }
 
@@ -238,13 +241,19 @@ static struct atl_xstats_tbl_s atl_xstats_tbl[] = {
 	ATL_MACSEC_XSTATS_FIELD(in_bad_tag_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_no_sci_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_unknown_sci_pkts),
+
+	ATL_MACSEC_XSTATS_FIELD(in_ecc_error_pkts),
+	ATL_MACSEC_XSTATS_FIELD(in_unctrl_hit_drop_redir),
 	/* Ingress SA Counters */
 	ATL_MACSEC_XSTATS_FIELD(in_untagged_hit_pkts),
+	ATL_MACSEC_XSTATS_FIELD(in_ctrl_hit_drop_redir_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_not_using_sa),
 	ATL_MACSEC_XSTATS_FIELD(in_unused_sa),
 	ATL_MACSEC_XSTATS_FIELD(in_not_valid_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_invalid_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_ok_pkts),
+	ATL_MACSEC_XSTATS_FIELD(in_late_pkts),
+	ATL_MACSEC_XSTATS_FIELD(in_delayed_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_unchecked_pkts),
 	ATL_MACSEC_XSTATS_FIELD(in_validated_octets),
 	ATL_MACSEC_XSTATS_FIELD(in_decrypted_octets),
@@ -409,6 +418,12 @@ eth_atl_dev_init(struct rte_eth_dev *eth_dev)
 
 	pthread_mutex_init(&hw->mbox_mutex, NULL);
 
+#ifdef RTE_LIBRTE_SECURITY
+	/* Initialize security_ctx only for primary process*/
+	if (atl_macsec_ctx_create(eth_dev))
+		return -ENOMEM;
+#endif
+
 	/* disable interrupt */
 	atl_disable_intr(hw);
 
@@ -473,6 +488,10 @@ eth_atl_dev_uninit(struct rte_eth_dev *eth_dev)
 	rte_free(eth_dev->data->mac_addrs);
 	eth_dev->data->mac_addrs = NULL;
 
+#ifdef RTE_LIBRTE_SECURITY
+	rte_free(eth_dev->security_ctx);
+#endif
+
 	pthread_mutex_destroy(&hw->mbox_mutex);
 
 	return 0;
@@ -746,208 +765,6 @@ atl_dev_reset(struct rte_eth_dev *dev)
 }
 
 static int
-atl_dev_configure_macsec(struct rte_eth_dev *dev)
-{
-	struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct aq_hw_cfg_s *cf = ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-	struct aq_macsec_config *aqcfg = &cf->aq_macsec;
-	struct macsec_msg_fw_request msg_macsec;
-	struct macsec_msg_fw_response response;
-
-	if (!aqcfg->common.macsec_enabled ||
-	    hw->aq_fw_ops->send_macsec_req == NULL)
-		return 0;
-
-	memset(&msg_macsec, 0, sizeof(msg_macsec));
-
-	/* Creating set of sc/sa structures from parameters provided by DPDK */
-
-	/* Configure macsec */
-	msg_macsec.msg_type = macsec_cfg_msg;
-	msg_macsec.cfg.enabled = aqcfg->common.macsec_enabled;
-	msg_macsec.cfg.interrupts_enabled = 1;
-
-	hw->aq_fw_ops->send_macsec_req(hw, &msg_macsec, &response);
-
-	if (response.result)
-		return -1;
-
-	memset(&msg_macsec, 0, sizeof(msg_macsec));
-
-	/* Configure TX SC */
-
-	msg_macsec.msg_type = macsec_add_tx_sc_msg;
-	msg_macsec.txsc.index = 0; /* TXSC always one (??) */
-	msg_macsec.txsc.protect = aqcfg->common.encryption_enabled;
-
-	/* MAC addr for TX */
-	msg_macsec.txsc.mac_sa[0] = rte_bswap32(aqcfg->txsc.mac[1]);
-	msg_macsec.txsc.mac_sa[1] = rte_bswap32(aqcfg->txsc.mac[0]);
-	msg_macsec.txsc.sa_mask = 0x3f;
-
-	msg_macsec.txsc.da_mask = 0;
-	msg_macsec.txsc.tci = 0x0B;
-	msg_macsec.txsc.curr_an = 0; /* SA index which currently used */
-
-	/*
-	 * Creating SCI (Secure Channel Identifier).
-	 * SCI constructed from Source MAC and Port identifier
-	 */
-	uint32_t sci_hi_part = (msg_macsec.txsc.mac_sa[1] << 16) |
-			       (msg_macsec.txsc.mac_sa[0] >> 16);
-	uint32_t sci_low_part = (msg_macsec.txsc.mac_sa[0] << 16);
-
-	uint32_t port_identifier = 1;
-
-	msg_macsec.txsc.sci[1] = sci_hi_part;
-	msg_macsec.txsc.sci[0] = sci_low_part | port_identifier;
-
-	hw->aq_fw_ops->send_macsec_req(hw, &msg_macsec, &response);
-
-	if (response.result)
-		return -1;
-
-	memset(&msg_macsec, 0, sizeof(msg_macsec));
-
-	/* Configure RX SC */
-
-	msg_macsec.msg_type = macsec_add_rx_sc_msg;
-	msg_macsec.rxsc.index = aqcfg->rxsc.pi;
-	msg_macsec.rxsc.replay_protect =
-		aqcfg->common.replay_protection_enabled;
-	msg_macsec.rxsc.anti_replay_window = 0;
-
-	/* MAC addr for RX */
-	msg_macsec.rxsc.mac_da[0] = rte_bswap32(aqcfg->rxsc.mac[1]);
-	msg_macsec.rxsc.mac_da[1] = rte_bswap32(aqcfg->rxsc.mac[0]);
-	msg_macsec.rxsc.da_mask = 0;//0x3f;
-
-	msg_macsec.rxsc.sa_mask = 0;
-
-	hw->aq_fw_ops->send_macsec_req(hw, &msg_macsec, &response);
-
-	if (response.result)
-		return -1;
-
-	memset(&msg_macsec, 0, sizeof(msg_macsec));
-
-	/* Configure RX SC */
-
-	msg_macsec.msg_type = macsec_add_tx_sa_msg;
-	msg_macsec.txsa.index = aqcfg->txsa.idx;
-	msg_macsec.txsa.next_pn = aqcfg->txsa.pn;
-
-	msg_macsec.txsa.key[0] = rte_bswap32(aqcfg->txsa.key[3]);
-	msg_macsec.txsa.key[1] = rte_bswap32(aqcfg->txsa.key[2]);
-	msg_macsec.txsa.key[2] = rte_bswap32(aqcfg->txsa.key[1]);
-	msg_macsec.txsa.key[3] = rte_bswap32(aqcfg->txsa.key[0]);
-
-	hw->aq_fw_ops->send_macsec_req(hw, &msg_macsec, &response);
-
-	if (response.result)
-		return -1;
-
-	memset(&msg_macsec, 0, sizeof(msg_macsec));
-
-	/* Configure RX SA */
-
-	msg_macsec.msg_type = macsec_add_rx_sa_msg;
-	msg_macsec.rxsa.index = aqcfg->rxsa.idx;
-	msg_macsec.rxsa.next_pn = aqcfg->rxsa.pn;
-
-	msg_macsec.rxsa.key[0] = rte_bswap32(aqcfg->rxsa.key[3]);
-	msg_macsec.rxsa.key[1] = rte_bswap32(aqcfg->rxsa.key[2]);
-	msg_macsec.rxsa.key[2] = rte_bswap32(aqcfg->rxsa.key[1]);
-	msg_macsec.rxsa.key[3] = rte_bswap32(aqcfg->rxsa.key[0]);
-
-	hw->aq_fw_ops->send_macsec_req(hw, &msg_macsec, &response);
-
-	if (response.result)
-		return -1;
-
-	return 0;
-}
-
-int atl_macsec_enable(struct rte_eth_dev *dev,
-		      uint8_t encr, uint8_t repl_prot)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	cfg->aq_macsec.common.macsec_enabled = 1;
-	cfg->aq_macsec.common.encryption_enabled = encr;
-	cfg->aq_macsec.common.replay_protection_enabled = repl_prot;
-
-	return 0;
-}
-
-int atl_macsec_disable(struct rte_eth_dev *dev)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	cfg->aq_macsec.common.macsec_enabled = 0;
-
-	return 0;
-}
-
-int atl_macsec_config_txsc(struct rte_eth_dev *dev, uint8_t *mac)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	memset(&cfg->aq_macsec.txsc.mac, 0, sizeof(cfg->aq_macsec.txsc.mac));
-	memcpy((uint8_t *)&cfg->aq_macsec.txsc.mac + 2, mac,
-		RTE_ETHER_ADDR_LEN);
-
-	return 0;
-}
-
-int atl_macsec_config_rxsc(struct rte_eth_dev *dev,
-			   uint8_t *mac, uint16_t pi)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	memset(&cfg->aq_macsec.rxsc.mac, 0, sizeof(cfg->aq_macsec.rxsc.mac));
-	memcpy((uint8_t *)&cfg->aq_macsec.rxsc.mac + 2, mac,
-		RTE_ETHER_ADDR_LEN);
-	cfg->aq_macsec.rxsc.pi = pi;
-
-	return 0;
-}
-
-int atl_macsec_select_txsa(struct rte_eth_dev *dev,
-			   uint8_t idx, uint8_t an,
-			   uint32_t pn, uint8_t *key)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	cfg->aq_macsec.txsa.idx = idx;
-	cfg->aq_macsec.txsa.pn = pn;
-	cfg->aq_macsec.txsa.an = an;
-
-	memcpy(&cfg->aq_macsec.txsa.key, key, 16);
-	return 0;
-}
-
-int atl_macsec_select_rxsa(struct rte_eth_dev *dev,
-			   uint8_t idx, uint8_t an,
-			   uint32_t pn, uint8_t *key)
-{
-	struct aq_hw_cfg_s *cfg =
-		ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private);
-
-	cfg->aq_macsec.rxsa.idx = idx;
-	cfg->aq_macsec.rxsa.pn = pn;
-	cfg->aq_macsec.rxsa.an = an;
-
-	memcpy(&cfg->aq_macsec.rxsa.key, key, 16);
-	return 0;
-}
-
-static int
 atl_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
 	struct atl_adapter *adapter = ATL_DEV_TO_ADAPTER(dev);
@@ -1040,9 +857,8 @@ atl_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
 {
 	struct atl_adapter *adapter = dev->data->dev_private;
 	struct aq_hw_s *hw = &adapter->hw;
-	struct get_stats req = { 0 };
-	struct macsec_msg_fw_request msg = { 0 };
-	struct macsec_msg_fw_response resp = { 0 };
+	struct atl_macsec_stats ms_stats;
+	struct atl_get_stats_param req = { 0 };;
 	int err = -1;
 	unsigned int i;
 	unsigned int count = atl_dev_xstats_get_count(dev);
@@ -1050,16 +866,7 @@ atl_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
 	if (!stats)
 		return count;
 
-	if (hw->aq_fw_ops->send_macsec_req != NULL) {
-		req.ingress_sa_index = 0xff;
-		req.egress_sc_index = 0xff;
-		req.egress_sa_index = 0xff;
-
-		msg.msg_type = macsec_get_stats_msg;
-		msg.stats = req;
-
-		err = hw->aq_fw_ops->send_macsec_req(hw, &msg, &resp);
-	}
+	err = atl_macsec_send_stats_req(dev, &req, &ms_stats);	
 
 	for (i = 0; i < n && i < count; i++) {
 		stats[i].id = i;
@@ -1072,7 +879,7 @@ atl_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
 		case XSTATS_TYPE_MACSEC:
 			if (!err) {
 				stats[i].value =
-					*(u64 *)((uint8_t *)&resp.stats +
+					*(u64 *)((uint8_t *)&ms_stats +
 					atl_xstats_tbl[i].offset);
 			}
 			break;
@@ -1171,15 +978,6 @@ atl_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	return NULL;
 }
 
-static void
-atl_dev_delayed_handler(void *param)
-{
-	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
-
-	atl_dev_configure_macsec(dev);
-}
-
-
 /* return 0 means link status changed, -1 means not changed */
 static int
 atl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused)
@@ -1230,10 +1028,6 @@ atl_dev_link_update(struct rte_eth_dev *dev, int wait __rte_unused)
 		hw_atl_b0_set_fc(hw, fc, 0U);
 	}
 
-	if (rte_eal_alarm_set(1000 * 1000,
-			      atl_dev_delayed_handler, (void *)dev) < 0)
-		PMD_DRV_LOG(ERR, "rte_eal_alarm_set fail");
-
 	return 0;
 }
 
@@ -1386,8 +1180,6 @@ atl_dev_interrupt_action(struct rte_eth_dev *dev,
 {
 	struct atl_interrupt *intr =
 		ATL_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-	struct atl_adapter *adapter = dev->data->dev_private;
-	struct aq_hw_s *hw = &adapter->hw;
 
 	if (!(intr->flags & ATL_FLAG_NEED_LINK_UPDATE))
 		goto done;
@@ -1399,39 +1191,12 @@ atl_dev_interrupt_action(struct rte_eth_dev *dev,
 		atl_dev_link_status_print(dev);
 		_rte_eth_dev_callback_process(dev,
 			RTE_ETH_EVENT_INTR_LSC, NULL);
-	} else {
-		if (hw->aq_fw_ops->send_macsec_req == NULL)
-			goto done;
-
-		/* Check macsec Keys expired */
-		struct get_stats req = { 0 };
-		struct macsec_msg_fw_request msg = { 0 };
-		struct macsec_msg_fw_response resp = { 0 };
-
-		req.ingress_sa_index = 0x0;
-		req.egress_sc_index = 0x0;
-		req.egress_sa_index = 0x0;
-		msg.msg_type = macsec_get_stats_msg;
-		msg.stats = req;
-
-		int err = hw->aq_fw_ops->send_macsec_req(hw, &msg, &resp);
-		if (err) {
-			PMD_DRV_LOG(ERR, "send_macsec_req fail");
-			goto done;
-		}
-		if (resp.stats.egress_threshold_expired ||
-		    resp.stats.ingress_threshold_expired ||
-		    resp.stats.egress_expired ||
-		    resp.stats.ingress_expired) {
-			PMD_DRV_LOG(INFO, "RTE_ETH_EVENT_MACSEC");
-			_rte_eth_dev_callback_process(dev,
-				RTE_ETH_EVENT_MACSEC, NULL);
-		}
 	}
-done:
+
 	atl_enable_intr(dev);
 	rte_intr_ack(intr_handle);
 
+done:
 	return 0;
 }
 
@@ -1911,6 +1676,35 @@ atl_rss_hash_conf_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static struct rte_security_ops atl_security_ops = {
+	.session_create = atl_macsec_create_session,
+	.session_update = atl_macsec_update_session,
+	.session_get_size = atl_macsec_session_get_size,
+	.session_stats_get = atl_macsec_session_stats_get,
+	.session_destroy = atl_macsec_destroy_session,
+	.set_pkt_metadata = NULL,
+	.capabilities_get = atl_macsec_capabilities_get,
+};
+
+static int
+atl_macsec_ctx_create(struct rte_eth_dev *dev)
+{
+	struct rte_security_ctx *ctx = NULL;
+
+	ctx = rte_malloc("rte_security_instances_ops",
+				sizeof(struct rte_security_ctx), 0);
+	if (ctx) {
+		ctx->device = (void *)dev;
+		ctx->ops = &atl_security_ops;
+		ctx->sess_cnt = 0;
+		dev->security_ctx = ctx;
+	} else {
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+
 static bool
 is_device_supported(struct rte_eth_dev *dev, struct rte_pci_driver *drv)
 {
diff --git a/drivers/net/atlantic/atl_sec.c b/drivers/net/atlantic/atl_sec.c
new file mode 100644
index 0000000..8702408
--- /dev/null
+++ b/drivers/net/atlantic/atl_sec.c
@@ -0,0 +1,615 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Aquantia Corporation
+ */
+
+#include <rte_ethdev_driver.h>
+
+
+#include "atl_logs.h"
+
+#include "atl_sec.h"
+#include "atl_ethdev.h"
+
+#include "macsec/MSS_Egress_registers.h"
+#include "macsec/MSS_Ingress_registers.h"
+#include "macsec/mdio.h"
+#include "macsec/macsec_api.h"
+
+
+#define STATS_2x32_TO_64(stat_field) \
+        (((uint64_t)stat_field[1] << 32) | stat_field[0])
+
+static void ether_addr_to_mac(uint32_t mac[2], struct rte_ether_addr *emac)
+{
+	uint32_t tmp[2] = {0};
+
+	memcpy(((uint8_t*)tmp) + 2, emac->addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	mac[0] = rte_bswap32(tmp[1]);
+	mac[1] = rte_bswap32(tmp[0]);
+}
+
+static int atl_macsec_configure(struct rte_eth_dev *dev,
+				struct rte_security_session *sess __rte_unused,
+				struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+
+	struct macsec_msg_fw_request msg = { 0 };
+	struct macsec_msg_fw_response resp = { 0 };
+	int ret = -1;
+	struct rte_security_macsec_param *conf = &xform->config_options;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (hw->aq_fw_ops->send_macsec_req != NULL) {
+		struct macsec_cfg cfg = { 0 };
+
+		cfg.enabled = conf->enabled;
+		cfg.egress_threshold = conf->egress_pn_threshold;
+		cfg.ingress_threshold = conf->ingress_pn_threshold;
+		cfg.interrupts_enabled = conf->interrupts_enabled;
+
+		msg.msg_type = macsec_cfg_msg;
+		msg.cfg = cfg;
+
+		ret = hw->aq_fw_ops->send_macsec_req(hw, &msg, &resp);
+	}
+
+
+	if (conf->enabled) {
+		int index = 0;
+		int num_ctl_ether_types = 0;
+
+		/* Init Ethertype bypass filters */
+		for (index = 0; index < 8; index++) {
+			if (conf->ctl_ether_types[index] != 0) {
+				AQ_API_SEC_EgressCTLFRecord egressCTLFRecord = {0};
+				egressCTLFRecord.eth_type = conf->ctl_ether_types[index];
+				egressCTLFRecord.match_type = 4; /* Match eth_type only */
+				egressCTLFRecord.match_mask = 0xf; /* match for eth_type */
+				egressCTLFRecord.action = 0; /* Bypass remaining MACSEC modules */
+				AQ_API_SetEgressCTLFRecord(hw, &egressCTLFRecord, NUMROWS_EGRESSCTLFRECORD - num_ctl_ether_types - 1);
+
+				AQ_API_SEC_IngressPreCTLFRecord ingressPreCTLFRecord = {0};
+				ingressPreCTLFRecord.eth_type = conf->ctl_ether_types[index];
+				ingressPreCTLFRecord.match_type = 4; /* Match eth_type only */
+				ingressPreCTLFRecord.match_mask = 0xf; /* match for eth_type */
+				ingressPreCTLFRecord.action = 0;
+				AQ_API_SetIngressPreCTLFRecord(hw, &ingressPreCTLFRecord, NUMROWS_INGRESSPRECTLFRECORD - num_ctl_ether_types - 1);
+
+				num_ctl_ether_types++;
+			}
+		}
+	}
+
+	return ret;
+}
+
+int atl_macsec_send_stats_req(struct rte_eth_dev *dev,
+			 struct atl_get_stats_param *param,
+			 struct atl_macsec_stats *stats)
+{
+        struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct get_stats req = { 0 };
+	struct macsec_msg_fw_request msg = { 0 };
+	struct macsec_msg_fw_response resp = { 0 };
+	int ret = -1;
+
+	memset(stats, 0, sizeof(*stats));
+
+	if (hw->aq_fw_ops->send_macsec_req != NULL) {
+		req.ingress_sa_index = param->ingress_sa_index;
+		req.egress_sc_index = param->egress_sc_index;
+		req.egress_sa_index = param->egress_sa_index;
+
+		msg.msg_type = macsec_get_stats_msg;
+		msg.stats = req;
+
+		ret = hw->aq_fw_ops->send_macsec_req(hw, &msg, &resp);
+
+		memcpy(stats, &resp.stats, sizeof(*stats));
+	}
+
+	return ret;
+}
+
+static void atl_rotate_keys(uint32_t (*key)[8], int key_len)
+{
+	uint32_t tmp[8] = {0};
+
+	memcpy(&tmp, key, sizeof(tmp));
+	memset(*key, 0, sizeof(*key));
+
+	if (key_len == 16) {
+		(*key)[0] = tmp[3];
+		(*key)[1] = tmp[2];
+		(*key)[2] = tmp[1];
+		(*key)[3] = tmp[0];
+	} else if (key_len == 32) {
+		(*key)[0] = tmp[7];
+		(*key)[1] = tmp[6];
+		(*key)[2] = tmp[5];
+		(*key)[3] = tmp[4];
+		(*key)[4] = tmp[3];
+		(*key)[5] = tmp[2];
+		(*key)[6] = tmp[1];
+		(*key)[7] = tmp[0];
+	} else {
+		printf("Rotate_keys: invalid key_len\n");
+	}
+
+}
+
+static int atl_macsec_set_rx_sa(struct rte_eth_dev *dev,
+				struct rte_security_session *sess __rte_unused,
+				struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	struct rte_security_macsec_sa_param* param = &xform->sa_options;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_IngressSARecord matchSARecord = {0};
+	matchSARecord.valid = 1;
+	matchSARecord.fresh = 1;
+	matchSARecord.next_pn = param->packet_number;
+
+	AQ_API_SetIngressSARecord(hw, &matchSARecord, param->an);
+
+	AQ_API_SEC_IngressSAKeyRecord matchKeyRecord = {0};
+	memcpy(&matchKeyRecord.key, &param->key, sizeof(matchKeyRecord.key));
+
+	switch (param->key_len) {
+	case 16:
+		matchKeyRecord.key_len = 0;
+		break;
+	case 24:
+		matchKeyRecord.key_len = 1;
+		break;
+	case 32:
+		matchKeyRecord.key_len = 2;
+		break;
+	default:
+		return -1;
+	}
+
+	atl_rotate_keys(&matchKeyRecord.key, param->key_len);
+
+	return AQ_API_SetIngressSAKeyRecord(hw, &matchKeyRecord, param->an);
+}
+
+static int atl_macsec_delete_rx_sa(struct rte_eth_dev *dev,
+			    struct rte_security_session *sess __rte_unused,
+			    struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	struct rte_security_macsec_sa_param* param = &xform->sa_options;
+	uint16_t sa_index = param->sa_idx;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_IngressSARecord blankIngressSARecord = {0};
+	AQ_API_SetIngressSARecord(hw, &blankIngressSARecord, sa_index);
+
+	AQ_API_SEC_IngressSAKeyRecord blankIngressKeyRecord = {0};
+	AQ_API_SetIngressSAKeyRecord(hw, &blankIngressKeyRecord, sa_index);
+	return 0;
+}
+
+static int atl_macsec_set_tx_sa(struct rte_eth_dev *dev, 
+				struct rte_security_session *sess __rte_unused,
+				struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	struct rte_security_macsec_sa_param* param = &xform->sa_options;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_EgressSARecord matchSARecord = {0};
+	matchSARecord.valid = 1;
+	matchSARecord.fresh = 1;
+	matchSARecord.next_pn = param->packet_number;
+
+	AQ_API_SetEgressSARecord(hw, &matchSARecord, param->an);
+
+	AQ_API_SEC_EgressSAKeyRecord matchKeyRecord = {0};
+	memcpy(&matchKeyRecord.key, &param->key, sizeof(matchKeyRecord.key));
+
+	atl_rotate_keys(&matchKeyRecord.key, param->key_len);
+
+	return AQ_API_SetEgressSAKeyRecord(hw, &matchKeyRecord, param->an);
+}
+
+static int atl_macsec_delete_tx_sa(struct rte_eth_dev *dev,
+			    struct rte_security_session *sess __rte_unused,
+			    struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	struct rte_security_macsec_sa_param* param = &xform->sa_options;
+	uint16_t sa_index = param->sa_idx;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_EgressSARecord blankEgressSARecord = {0};
+	AQ_API_SetEgressSARecord(hw, &blankEgressSARecord, sa_index);
+
+	AQ_API_SEC_EgressSAKeyRecord blankEgressKeyRecord = {0};
+	AQ_API_SetEgressSAKeyRecord(hw, &blankEgressKeyRecord, sa_index);
+	return 0;
+}
+
+static int atl_macsec_get_idx_by_sa_num(int sa_num, int sc_index, int an)
+{
+	if (sa_num == 1) {
+		return an; //SA index
+	} else if (sa_num == 2) {
+		return (sc_index << 1) | an; //SC index
+	} else { //sa_num = 4
+		return (sc_index << 2) | an; //SC index
+	}
+}
+
+static int atl_macsec_set_rx_sc(struct rte_eth_dev *dev,
+				struct rte_security_session *sess __rte_unused,
+				struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	int err = 0;
+	struct rte_security_macsec_rxsc_param* param = &xform->rxsc_options;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_IngressPreClassRecord matchIngressPreClassRecord = {0};
+
+	matchIngressPreClassRecord.sci[0] = param->sci & 0xffffffff;
+	matchIngressPreClassRecord.sci[1] = param->sci >> 32;
+
+	matchIngressPreClassRecord.tci = param->tci;
+
+	ether_addr_to_mac(matchIngressPreClassRecord.mac_sa, &param->s_mac);
+	ether_addr_to_mac(matchIngressPreClassRecord.mac_da, &param->d_mac);
+
+	matchIngressPreClassRecord.sa_mask = 0x3f;
+	matchIngressPreClassRecord.da_mask = 0x3f;
+
+	matchIngressPreClassRecord.sci_mask = 0xff;
+
+	matchIngressPreClassRecord.valid = 1;
+
+	matchIngressPreClassRecord.eth_type = 0x88e5; //match all MACSEC ethertype packets
+	matchIngressPreClassRecord.eth_type_mask = 0x3;
+	matchIngressPreClassRecord.action = 0x0; //forward for decryption
+
+	matchIngressPreClassRecord.sc_idx = atl_macsec_get_idx_by_sa_num(param->sa_num, param->index, 0);
+	// Num SA per SC: # 0: 4SA, 2: 2SA, 3: 1SA
+	switch (param->sa_num) {
+	case 4:
+		matchIngressPreClassRecord.an_mask = 0;
+		break;
+	case 2:
+		matchIngressPreClassRecord.an_mask = 2;
+		break;
+	case 1:
+		matchIngressPreClassRecord.an_mask = 3;
+		break;
+	default:
+		break;
+	}
+
+	err = AQ_API_SetIngressPreClassRecord(hw, &matchIngressPreClassRecord, param->index);
+
+	
+	AQ_API_SEC_IngressSCRecord matchSCRecord = {0};
+
+	matchSCRecord.validate_frames = param->validate_frames;
+	matchSCRecord.an_rol = param->auto_rollover_enabled;
+	matchSCRecord.replay_protect = param->replay_protection;
+	matchSCRecord.anti_replay_window = param->anti_replay_window;
+	matchSCRecord.valid = 1;
+	matchSCRecord.fresh = 1;
+
+	err = AQ_API_SetIngressSCRecord(hw, &matchSCRecord, param->index);
+	return err;
+}
+
+static int atl_macsec_delete_rx_sc(struct rte_eth_dev *dev,
+			    struct rte_security_session *sess __rte_unused,
+			    struct rte_security_macsec_xform *xform)
+{
+	struct rte_security_macsec_rxsc_param* param = &xform->rxsc_options;
+	uint16_t sc_index = param->index;
+	struct aq_hw_s *hw;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_IngressSCRecord blankSCRecord = {0};
+	return AQ_API_SetIngressSCRecord(hw, &blankSCRecord, sc_index);
+}
+
+static int atl_macsec_set_tx_sc(struct rte_eth_dev *dev,
+				struct rte_security_session *sess __rte_unused,
+				struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw;
+	struct rte_security_macsec_txsc_param *param = &xform->txsc_options;
+
+	hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	AQ_API_SEC_EgressClassRecord matchEgressClassRecord = {0};
+
+/* SA/SC lookup */
+	ether_addr_to_mac(matchEgressClassRecord.mac_sa, &param->s_mac);
+	ether_addr_to_mac(matchEgressClassRecord.mac_da, &param->d_mac);
+
+	matchEgressClassRecord.sci[0] = param->sci & 0xffffffff;
+	matchEgressClassRecord.sci[1] = param->sci >> 32;
+	matchEgressClassRecord.sci_mask = 0xff;
+
+	matchEgressClassRecord.sa_mask = 0x3f; 
+	matchEgressClassRecord.da_mask = 0x3f;
+
+	matchEgressClassRecord.action = 0; //forward to SA/SC table
+	matchEgressClassRecord.valid = 1;
+
+	matchEgressClassRecord.sc_idx = param->index;
+
+	switch (param->sa_num) {
+	case 4:
+		matchEgressClassRecord.sc_sa = 0;
+		break;
+	case 2:
+		matchEgressClassRecord.sc_sa = 2;
+		break;
+	case 1:
+		matchEgressClassRecord.sc_sa = 3;
+		break;
+	default:
+		break;
+	}
+
+	AQ_API_SetEgressClassRecord(hw, &matchEgressClassRecord, param->index);
+
+	AQ_API_SEC_EgressSCRecord matchSCRecord = {0};
+
+	matchSCRecord.protect = param->protect;
+	matchSCRecord.tci = param->tci;
+	matchSCRecord.an_roll = param->auto_rollover_enabled;
+
+	switch (param->key_len) {
+	case 16:
+		matchSCRecord.sak_len = 0;
+		break;
+	case 24:
+		matchSCRecord.sak_len = 1;
+		break;
+	case 32:
+		matchSCRecord.sak_len = 2;
+		break;
+	default:
+		return -1;
+	}
+
+	/* Current Associacion Number (according to doc: Not used when there is only one SA per SC) */
+	matchSCRecord.curr_an = param->curr_an;
+
+	matchSCRecord.valid = 1;
+	matchSCRecord.fresh = 1;
+	return AQ_API_SetEgressSCRecord(hw, &matchSCRecord, param->index);
+}
+
+static int atl_macsec_delete_tx_sc(struct rte_eth_dev *dev,
+				   struct rte_security_session *sess __rte_unused,
+				   struct rte_security_macsec_xform *xform)
+{
+	struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_security_macsec_txsc_param *param = &xform->txsc_options;
+	AQ_API_SEC_EgressSCRecord blankSCRecord = {0};
+
+	return AQ_API_SetEgressSCRecord(hw, &blankSCRecord, param->index);
+}
+
+/* MACSEC op jump table */
+typedef struct {
+	int op;
+	int (*func)(struct rte_eth_dev *dev, struct rte_security_session *sess, struct rte_security_macsec_xform *xform);
+} macsec_op_jump_tbl_entry;
+
+static const macsec_op_jump_tbl_entry macsec_op_jmp_tbl[] = {
+	{ RTE_SECURITY_MACSEC_OP_CONFIG, atl_macsec_configure },
+	{ RTE_SECURITY_MACSEC_OP_ADD_TXSC, atl_macsec_set_tx_sc },
+	{ RTE_SECURITY_MACSEC_OP_DEL_TXSC, atl_macsec_delete_tx_sc },
+	{ RTE_SECURITY_MACSEC_OP_UPD_TXSC, atl_macsec_set_tx_sc },
+
+	{ RTE_SECURITY_MACSEC_OP_ADD_RXSC, atl_macsec_set_rx_sc },
+	{ RTE_SECURITY_MACSEC_OP_DEL_RXSC, atl_macsec_delete_rx_sc },
+	{ RTE_SECURITY_MACSEC_OP_UPD_RXSC, atl_macsec_set_rx_sc },
+
+	{ RTE_SECURITY_MACSEC_OP_ADD_TXSA, atl_macsec_set_tx_sa },
+	{ RTE_SECURITY_MACSEC_OP_DEL_TXSA, atl_macsec_delete_tx_sa },
+	{ RTE_SECURITY_MACSEC_OP_UPD_TXSA, atl_macsec_set_tx_sa },
+
+	{ RTE_SECURITY_MACSEC_OP_ADD_RXSA, atl_macsec_set_rx_sa },
+	{ RTE_SECURITY_MACSEC_OP_DEL_RXSA, atl_macsec_delete_rx_sa },
+	{ RTE_SECURITY_MACSEC_OP_UPD_RXSA, atl_macsec_set_rx_sa },
+};
+
+int
+atl_macsec_create_session(void *device,
+				struct rte_security_session_conf *conf,
+				struct rte_security_session *session,
+				struct rte_mempool *mp)
+{
+	struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+	struct atl_macsec_session *macsec_session = NULL;
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_MACSEC) {
+		PMD_DRV_LOG(ERR, "Unsupported security protocol\n");
+		return -ENOTSUP;
+	}
+
+	/* For create_session only CONFIG OP is supported */
+	if (conf->macsec.op != RTE_SECURITY_MACSEC_OP_CONFIG) {
+		PMD_DRV_LOG(ERR, "Unsupported OP for create_session\n");
+		return -ENOTSUP;
+	}
+
+	if (rte_mempool_get(mp, (void **)&macsec_session)) {
+		PMD_DRV_LOG(ERR, "Cannot get object from ic_session mempool\n");
+		return -ENOMEM;
+	}
+
+
+	macsec_session->dev = eth_dev;
+
+	set_sec_session_private_data(session, macsec_session);
+
+	return 0;
+}
+
+int
+atl_macsec_update_session(void *device,
+			  struct rte_security_session *sess,
+			  struct rte_security_session_conf *conf)
+{
+	struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+	struct rte_security_macsec_xform *xform = &conf->macsec;
+
+	if (xform->op > RTE_DIM(macsec_op_jmp_tbl))
+		return -ENOTSUP;
+
+	return macsec_op_jmp_tbl[xform->op].func(eth_dev, sess, xform);
+}
+
+unsigned int
+atl_macsec_session_get_size(void *device __rte_unused)
+{
+	return sizeof(struct atl_macsec_session);
+}
+
+int
+atl_macsec_destroy_session(void *device,
+			   struct rte_security_session *sess)
+{
+	struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+	struct atl_macsec_session *macsec_session =
+		(struct atl_macsec_session*) get_sec_session_private_data(sess);
+	struct rte_mempool *mp = rte_mempool_from_obj(macsec_session);
+
+	if (eth_dev != macsec_session->dev) {
+		PMD_DRV_LOG(ERR, "Session not bound to this device\n");
+		return -ENODEV;
+	}
+
+	set_sec_session_private_data(sess, NULL);
+	rte_mempool_put(mp, (void *)macsec_session);
+
+	return 0;
+}
+
+int
+atl_macsec_session_stats_get(void *device,
+			     struct rte_security_session *sess __rte_unused,
+			     struct rte_security_stats *stats)
+{
+	struct rte_eth_dev *dev = (struct rte_eth_dev *)device;
+	struct atl_macsec_stats macsec_stats = { 0 };
+	struct atl_get_stats_param param = { 0 };
+	struct rte_security_macsec_stats *result_stats = &stats->macsec;
+	int err = 0;
+
+	dev = dev;
+
+	memset(result_stats, 0, sizeof(struct rte_security_macsec_stats));
+
+	err = atl_macsec_send_stats_req(dev, &param, &macsec_stats);
+
+	if (err)
+		return err;
+
+
+	result_stats->in_ctl_pkts = macsec_stats.in_ctl_pkts;
+	result_stats->in_tagged_miss_pkts = macsec_stats.in_tagged_miss_pkts;
+	result_stats->in_untagged_miss_pkts = macsec_stats.in_untagged_miss_pkts;
+	result_stats->in_notag_pkts = macsec_stats.in_notag_pkts;
+	result_stats->in_untagged_pkts = macsec_stats.in_untagged_pkts;
+	result_stats->in_bad_tag_pkts = macsec_stats.in_bad_tag_pkts;
+	result_stats->in_no_sci_pkts = macsec_stats.in_no_sci_pkts;
+	result_stats->in_unknown_sci_pkts = macsec_stats.in_unknown_sci_pkts;
+
+	result_stats->out_ctl_pkts = macsec_stats.out_ctl_pkts;
+	result_stats->out_unknown_sa_pkts = macsec_stats.out_unknown_sa_pkts;
+	result_stats->out_untagged_pkts = macsec_stats.out_untagged_pkts;
+	result_stats->out_too_long = macsec_stats.out_too_long;
+
+	result_stats->in_untagged_hit_pkts = macsec_stats.in_untagged_hit_pkts;
+	result_stats->in_not_using_sa = macsec_stats.in_not_using_sa;
+	result_stats->in_unused_sa = macsec_stats.in_unused_sa;
+	result_stats->in_not_valid_pkts = macsec_stats.in_not_valid_pkts;
+	result_stats->in_invalid_pkts = macsec_stats.in_invalid_pkts;
+	result_stats->in_ok_pkts = macsec_stats.in_ok_pkts;
+	result_stats->in_unchecked_pkts = macsec_stats.in_unchecked_pkts;
+	result_stats->in_validated_octets = macsec_stats.in_validated_octets;
+	result_stats->in_decrypted_octets = macsec_stats.in_decrypted_octets;
+	result_stats->out_sc_protected_pkts = macsec_stats.out_sc_protected_pkts;
+	result_stats->out_sc_encrypted_pkts = macsec_stats.out_sc_encrypted_pkts;
+	result_stats->out_sc_protected_octets = macsec_stats.out_sc_protected_octets;
+	result_stats->out_sc_encrypted_octets = macsec_stats.out_sc_encrypted_octets;
+	result_stats->out_sa_hit_drop_redirect = macsec_stats.out_sa_hit_drop_redirect;
+	result_stats->out_sa_protected2_pkts = macsec_stats.out_sa_protected2_pkts;
+	result_stats->out_sa_protected_pkts = macsec_stats.out_sa_protected_pkts;
+	result_stats->out_sa_encrypted_pkts = macsec_stats.out_sa_encrypted_pkts;
+
+	return err;
+}
+
+const struct rte_security_capability *
+atl_macsec_capabilities_get(void *device)
+{
+	struct rte_eth_dev *dev = (struct rte_eth_dev *)device;
+	struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	static const struct rte_cryptodev_capabilities
+	aes_gcm_gmac_crypto_capabilities[] = {
+		{       /* AES GMAC (128-bit) */
+			.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			{.sym = {
+				.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+				{.auth = {
+					.algo = RTE_CRYPTO_AUTH_AES_GMAC,
+					.block_size = 16,
+					.key_size = {
+						.min = 16,
+						.max = 16,
+						.increment = 0
+					},
+				}, }
+			}, }
+		},
+	};
+
+	static const struct rte_security_capability
+	alt_security_capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_MACSEC,
+			{.macsec = {
+				.caps = {
+					.xpn = 0, /* Extended Packet Numbers (64 bit) not supported */
+				},
+			} },
+			.crypto_capabilities = aes_gcm_gmac_crypto_capabilities,
+			.ol_flags = 0
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE
+		}
+	};
+
+/* No MACSEC support for AQC100 devices */
+	if ((hw->caps_lo & BIT(CAPS_LO_MACSEC)) == 0)
+		return NULL;
+
+	return alt_security_capabilities;
+}
+
diff --git a/drivers/net/atlantic/atl_sec.h b/drivers/net/atlantic/atl_sec.h
new file mode 100644
index 0000000..1d8651d
--- /dev/null
+++ b/drivers/net/atlantic/atl_sec.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Aquantia Corporation
+ */
+
+/**
+ * @file rte_pmd_atlantic.h
+ * atlantic PMD specific functions.
+ *
+ **/
+
+#ifndef _ATL_SEC_H_
+#define _ATL_SEC_H_
+
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#include <rte_cryptodev.h>
+#include <rte_tailq.h>
+
+#include <rte_ethdev_driver.h>
+
+struct atl_get_stats_param {
+        uint8_t version_only;
+        uint8_t ingress_sa_index;
+        uint8_t egress_sa_index;
+        uint8_t egress_sc_index;
+};
+
+struct atl_macsec_stats {
+    /* Retrieve Atlantic MACSEC FW version*/
+    uint32_t api_version;
+    /* Ingress Common Counters */
+    uint64_t in_ctl_pkts;
+    uint64_t in_tagged_miss_pkts;
+    uint64_t in_untagged_miss_pkts;
+    uint64_t in_notag_pkts;
+    uint64_t in_untagged_pkts;
+    uint64_t in_bad_tag_pkts;
+    uint64_t in_no_sci_pkts;
+    uint64_t in_unknown_sci_pkts;
+    uint64_t in_ctrl_prt_pass_pkts;
+    uint64_t in_unctrl_prt_pass_pkts;
+    uint64_t in_ctrl_prt_fail_pkts;
+    uint64_t in_unctrl_prt_fail_pkts;
+    uint64_t in_too_long_pkts;
+    uint64_t in_igpoc_ctl_pkts;
+    uint64_t in_ecc_error_pkts;
+    uint64_t in_unctrl_hit_drop_redir;
+
+    /* Egress Common Counters */
+    uint64_t out_ctl_pkts;
+    uint64_t out_unknown_sa_pkts;
+    uint64_t out_untagged_pkts;
+    uint64_t out_too_long;
+    uint64_t out_ecc_error_pkts;
+    uint64_t out_unctrl_hit_drop_redir;
+
+    /* Ingress SA Counters */
+    uint64_t in_untagged_hit_pkts;
+    uint64_t in_ctrl_hit_drop_redir_pkts;
+    uint64_t in_not_using_sa;
+    uint64_t in_unused_sa;
+    uint64_t in_not_valid_pkts;
+    uint64_t in_invalid_pkts;
+    uint64_t in_ok_pkts;
+    uint64_t in_late_pkts;
+    uint64_t in_delayed_pkts;
+    uint64_t in_unchecked_pkts;
+    uint64_t in_validated_octets;
+    uint64_t in_decrypted_octets;
+
+    /* Egress SA Counters */
+    uint64_t out_sa_hit_drop_redirect;
+    uint64_t out_sa_protected2_pkts;
+    uint64_t out_sa_protected_pkts;
+    uint64_t out_sa_encrypted_pkts;
+
+    /* Egress SC Counters */
+    uint64_t out_sc_protected_pkts;
+    uint64_t out_sc_encrypted_pkts;
+    uint64_t out_sc_protected_octets;
+    uint64_t out_sc_encrypted_octets;
+
+    /* SA Counters expiration info */
+    uint32_t egress_threshold_expired;
+    uint32_t ingress_threshold_expired;
+    uint32_t egress_expired;
+    uint32_t ingress_expired;
+} __attribute__((__packed__));
+
+int atl_macsec_send_stats_req(struct rte_eth_dev *dev,
+			      struct atl_get_stats_param *param,
+			      struct atl_macsec_stats *stats);
+
+struct atl_macsec_session {
+	unsigned int session_id;
+	struct rte_eth_dev *dev;
+};
+
+TAILQ_HEAD(atl_macsec_sessions_list, atl_macsec_session);
+
+struct atl_macsec {
+	struct atl_macsec_sessions_list sessions_list;
+};
+
+int atl_macsec_create_session(void *device,
+				struct rte_security_session_conf *conf,
+				struct rte_security_session *session,
+				struct rte_mempool *mp);
+
+int atl_macsec_update_session(void *device,
+				struct rte_security_session *sess,
+				struct rte_security_session_conf *conf);
+
+unsigned int atl_macsec_session_get_size(void *device);
+
+int atl_macsec_destroy_session(void *device, struct rte_security_session *sess);
+
+int atl_macsec_session_stats_get(void *device,
+				 struct rte_security_session *sess,
+				 struct rte_security_stats *stats);
+
+const struct rte_security_capability *atl_macsec_capabilities_get(void *device);
+
+#endif /* _ATL_SEC_H_ */
diff --git a/drivers/net/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/atlantic/hw_atl/hw_atl_utils.h
index 81caffa..af4dd82 100644
--- a/drivers/net/atlantic/hw_atl/hw_atl_utils.h
+++ b/drivers/net/atlantic/hw_atl/hw_atl_utils.h
@@ -11,6 +11,8 @@
 #define BIT(x)  (1UL << (x))
 #define HW_ATL_FLUSH() { (void)aq_hw_read_reg(self, 0x10); }
 
+#include "../atl_sec.h"
+
 /* Hardware tx descriptor */
 struct hw_atl_txd_s {
 	u64 buf_addr;
@@ -360,51 +362,6 @@ struct macsec_cfg {
 	uint32_t interrupts_enabled;
 } __attribute__((__packed__));
 
-struct add_rx_sc {
-	uint32_t index;
-	uint32_t pi; /* Port identifier */
-	uint32_t sci[2]; /* Secure Channel identifier */
-	uint32_t sci_mask; /* 1: enable comparison of SCI, 0: don't care */
-	uint32_t tci;
-	uint32_t tci_mask;
-	uint32_t mac_sa[2];
-	uint32_t sa_mask; /* 0: ignore mac_sa */
-	uint32_t mac_da[2];
-	uint32_t da_mask; /* 0: ignore mac_da */
-	uint32_t validate_frames; /* 0: strict, 1:check, 2:disabled */
-	uint32_t replay_protect; /* 1: enabled, 0:disabled */
-	uint32_t anti_replay_window; /* default 0 */
-	/* 1: auto_rollover enabled (when SA next_pn is saturated */
-	uint32_t an_rol;
-} __attribute__((__packed__));
-
-struct add_tx_sc {
-	uint32_t index;
-	uint32_t pi; /* Port identifier */
-	uint32_t sci[2]; /* Secure Channel identifier */
-	uint32_t sci_mask; /* 1: enable comparison of SCI, 0: don't care */
-	uint32_t tci; /* TCI value, used if packet is not explicitly tagged */
-	uint32_t tci_mask;
-	uint32_t mac_sa[2];
-	uint32_t sa_mask; /* 0: ignore mac_sa */
-	uint32_t mac_da[2];
-	uint32_t da_mask; /* 0: ignore mac_da */
-	uint32_t protect;
-	uint32_t curr_an; /* SA index which currently used */
-} __attribute__((__packed__));
-
-struct add_rx_sa {
-	uint32_t index;
-	uint32_t next_pn;
-	uint32_t key[4]; /* 128 bit key */
-} __attribute__((__packed__));
-
-struct add_tx_sa {
-	uint32_t index;
-	uint32_t next_pn;
-	uint32_t key[4]; /* 128 bit key */
-} __attribute__((__packed__));
-
 struct get_stats {
 	uint32_t version_only;
 	uint32_t ingress_sa_index;
@@ -412,84 +369,19 @@ struct get_stats {
 	uint32_t egress_sc_index;
 } __attribute__((__packed__));
 
-struct macsec_stats {
-	uint32_t api_version;
-	/* Ingress Common Counters */
-	uint64_t in_ctl_pkts;
-	uint64_t in_tagged_miss_pkts;
-	uint64_t in_untagged_miss_pkts;
-	uint64_t in_notag_pkts;
-	uint64_t in_untagged_pkts;
-	uint64_t in_bad_tag_pkts;
-	uint64_t in_no_sci_pkts;
-	uint64_t in_unknown_sci_pkts;
-	uint64_t in_ctrl_prt_pass_pkts;
-	uint64_t in_unctrl_prt_pass_pkts;
-	uint64_t in_ctrl_prt_fail_pkts;
-	uint64_t in_unctrl_prt_fail_pkts;
-	uint64_t in_too_long_pkts;
-	uint64_t in_igpoc_ctl_pkts;
-	uint64_t in_ecc_error_pkts;
-	uint64_t in_unctrl_hit_drop_redir;
-
-	/* Egress Common Counters */
-	uint64_t out_ctl_pkts;
-	uint64_t out_unknown_sa_pkts;
-	uint64_t out_untagged_pkts;
-	uint64_t out_too_long;
-	uint64_t out_ecc_error_pkts;
-	uint64_t out_unctrl_hit_drop_redir;
-
-	/* Ingress SA Counters */
-	uint64_t in_untagged_hit_pkts;
-	uint64_t in_ctrl_hit_drop_redir_pkts;
-	uint64_t in_not_using_sa;
-	uint64_t in_unused_sa;
-	uint64_t in_not_valid_pkts;
-	uint64_t in_invalid_pkts;
-	uint64_t in_ok_pkts;
-	uint64_t in_late_pkts;
-	uint64_t in_delayed_pkts;
-	uint64_t in_unchecked_pkts;
-	uint64_t in_validated_octets;
-	uint64_t in_decrypted_octets;
-
-	/* Egress SA Counters */
-	uint64_t out_sa_hit_drop_redirect;
-	uint64_t out_sa_protected2_pkts;
-	uint64_t out_sa_protected_pkts;
-	uint64_t out_sa_encrypted_pkts;
-
-	/* Egress SC Counters */
-	uint64_t out_sc_protected_pkts;
-	uint64_t out_sc_encrypted_pkts;
-	uint64_t out_sc_protected_octets;
-	uint64_t out_sc_encrypted_octets;
-
-	/* SA Counters expiration info */
-	uint32_t egress_threshold_expired;
-	uint32_t ingress_threshold_expired;
-	uint32_t egress_expired;
-	uint32_t ingress_expired;
-} __attribute__((__packed__));
-
 struct macsec_msg_fw_request {
-	uint32_t offset; /* not used */
+	uint32_t msg_id; /* not used */
 	uint32_t msg_type;
 
 	union {
 		struct macsec_cfg cfg;
-		struct add_rx_sc rxsc;
-		struct add_tx_sc txsc;
-		struct add_rx_sa rxsa;
-		struct add_tx_sa txsa;
 		struct get_stats stats;
 	};
 } __attribute__((__packed__));
 
 struct macsec_msg_fw_response {
 	uint32_t result;
-	struct macsec_stats stats;
+	struct atl_macsec_stats stats;
 } __attribute__((__packed__));
 
 #define HAL_ATLANTIC_UTILS_CHIP_MIPS         0x00000001U
diff --git a/drivers/net/atlantic/meson.build b/drivers/net/atlantic/meson.build
index 139cdec..986c6d6 100644
--- a/drivers/net/atlantic/meson.build
+++ b/drivers/net/atlantic/meson.build
@@ -7,11 +7,13 @@ sources = files(
 	'atl_rxtx.c',
 	'atl_ethdev.c',
 	'atl_hw_regs.c',
+	'atl_sec.c',
 	'hw_atl/hw_atl_b0.c',
 	'hw_atl/hw_atl_llh.c',
 	'hw_atl/hw_atl_utils_fw2x.c',
 	'hw_atl/hw_atl_utils.c',
-	'rte_pmd_atlantic.c',
 	'macsec/mdio.c',
 	'macsec/macsec_api.c',
 )
+
+deps += ['security']
diff --git a/drivers/net/atlantic/rte_pmd_atlantic.c b/drivers/net/atlantic/rte_pmd_atlantic.c
deleted file mode 100644
index 2962f5c..0000000
--- a/drivers/net/atlantic/rte_pmd_atlantic.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Aquantia Corporation
- */
-
-#include <rte_ethdev_driver.h>
-
-#include "rte_pmd_atlantic.h"
-#include "atl_ethdev.h"
-
-
-int
-rte_pmd_atl_macsec_enable(uint16_t port,
-			  uint8_t encr, uint8_t repl_prot)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_enable(dev, encr, repl_prot);
-}
-
-int
-rte_pmd_atl_macsec_disable(uint16_t port)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_disable(dev);
-}
-
-int
-rte_pmd_atl_macsec_config_txsc(uint16_t port, uint8_t *mac)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_config_txsc(dev, mac);
-}
-
-int
-rte_pmd_atl_macsec_config_rxsc(uint16_t port, uint8_t *mac, uint16_t pi)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_config_rxsc(dev, mac, pi);
-}
-
-int
-rte_pmd_atl_macsec_select_txsa(uint16_t port, uint8_t idx, uint8_t an,
-				 uint32_t pn, uint8_t *key)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_select_txsa(dev, idx, an, pn, key);
-}
-
-int
-rte_pmd_atl_macsec_select_rxsa(uint16_t port, uint8_t idx, uint8_t an,
-				 uint32_t pn, uint8_t *key)
-{
-	struct rte_eth_dev *dev;
-
-	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
-
-	dev = &rte_eth_devices[port];
-
-	if (!is_atlantic_supported(dev))
-		return -ENOTSUP;
-
-	return atl_macsec_select_rxsa(dev, idx, an, pn, key);
-}
diff --git a/drivers/net/atlantic/rte_pmd_atlantic.h b/drivers/net/atlantic/rte_pmd_atlantic.h
deleted file mode 100644
index c020856..0000000
--- a/drivers/net/atlantic/rte_pmd_atlantic.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Aquantia Corporation
- */
-
-/**
- * @file rte_pmd_atlantic.h
- * atlantic PMD specific functions.
- *
- **/
-
-#ifndef _PMD_ATLANTIC_H_
-#define _PMD_ATLANTIC_H_
-
-#include <rte_ethdev_driver.h>
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Enable MACsec offload.
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param encr
- *    1 - Enable encryption (encrypt and add integrity signature).
- *    0 - Disable encryption (only add integrity signature).
- * @param repl_prot
- *    1 - Enable replay protection.
- *    0 - Disable replay protection.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_enable(uint16_t port, uint8_t encr, uint8_t repl_prot);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Disable MACsec offload.
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_disable(uint16_t port);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Configure Tx SC (Secure Connection).
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param mac
- *   The MAC address on the local side.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_config_txsc(uint16_t port, uint8_t *mac);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Configure Rx SC (Secure Connection).
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param mac
- *   The MAC address on the remote side.
- * @param pi
- *   The PI (port identifier) on the remote side.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_config_rxsc(uint16_t port, uint8_t *mac, uint16_t pi);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Enable Tx SA (Secure Association).
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param idx
- *   The SA to be enabled (0 or 1).
- * @param an
- *   The association number on the local side.
- * @param pn
- *   The packet number on the local side.
- * @param key
- *   The key on the local side.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- *   - (-EINVAL) if bad parameter.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_select_txsa(uint16_t port, uint8_t idx, uint8_t an,
-				   uint32_t pn, uint8_t *key);
-
-/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
- * Enable Rx SA (Secure Association).
- *
- * @param port
- *   The port identifier of the Ethernet device.
- * @param idx
- *   The SA to be enabled (0 or 1)
- * @param an
- *   The association number on the remote side.
- * @param pn
- *   The packet number on the remote side.
- * @param key
- *   The key on the remote side.
- * @return
- *   - (0) if successful.
- *   - (-ENODEV) if *port* invalid.
- *   - (-ENOTSUP) if hardware doesn't support this feature.
- *   - (-EINVAL) if bad parameter.
- */
-__rte_experimental
-int rte_pmd_atl_macsec_select_rxsa(uint16_t port, uint8_t idx, uint8_t an,
-				   uint32_t pn, uint8_t *key);
-
-#endif /* _PMD_ATLANTIC_H_ */
diff --git a/drivers/net/atlantic/rte_pmd_atlantic_version.map b/drivers/net/atlantic/rte_pmd_atlantic_version.map
deleted file mode 100644
index b16faa9..0000000
--- a/drivers/net/atlantic/rte_pmd_atlantic_version.map
+++ /dev/null
@@ -1,16 +0,0 @@
-DPDK_18.11 {
-
-	local: *;
-};
-
-EXPERIMENTAL {
-	global:
-
-	rte_pmd_atl_macsec_enable;
-	rte_pmd_atl_macsec_disable;
-	rte_pmd_atl_macsec_config_txsc;
-	rte_pmd_atl_macsec_config_rxsc;
-	rte_pmd_atl_macsec_select_txsa;
-	rte_pmd_atl_macsec_select_rxsa;
-};
-
