Add fixes to have lock on security session update, write and read to
prevent corruption.

Fixes: a72e15611303 ("net/cnxk: add PMD API for IPsec SA base and flush")
Fixes: 8efa348e8160 ("net/cnxk: support custom SA index")

Signed-off-by: Rahul Bhansali <rbhans...@marvell.com>
---
Changes in v2: Updated fixes in commit message.

 drivers/net/cnxk/cn10k_ethdev_sec.c | 65 +++++++++++++++++++++++------
 drivers/net/cnxk/cnxk_ethdev_sec.c  | 60 ++++++++++++++++++++++++--
 2 files changed, 109 insertions(+), 16 deletions(-)

diff --git a/drivers/net/cnxk/cn10k_ethdev_sec.c 
b/drivers/net/cnxk/cn10k_ethdev_sec.c
index 0dc5c22444..110630596e 100644
--- a/drivers/net/cnxk/cn10k_ethdev_sec.c
+++ b/drivers/net/cnxk/cn10k_ethdev_sec.c
@@ -786,7 +786,6 @@ cn10k_eth_sec_session_create(void *device,
        inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
        inl_dev = !!dev->inb.inl_dev;

-       memset(eth_sec, 0, sizeof(struct cnxk_eth_sec_sess));
        sess_priv.u64 = 0;

        lock = inbound ? &dev->inb.lock : &dev->outb.lock;
@@ -796,6 +795,8 @@ cn10k_eth_sec_session_create(void *device,
        if (inbound && inl_dev)
                roc_nix_inl_dev_lock();

+       memset(eth_sec, 0, sizeof(struct cnxk_eth_sec_sess));
+
        if (inbound) {
                struct roc_ot_ipsec_inb_sa *inb_sa, *inb_sa_dptr;
                struct cn10k_inb_priv_data *inb_priv;
@@ -1007,7 +1008,7 @@ cn10k_eth_sec_session_create(void *device,
                roc_nix_inl_dev_unlock();
        rte_spinlock_unlock(lock);

-       plt_nix_dbg("Created %s session with spi=%u, sa_idx=%u inl_dev=%u",
+       plt_nix_dbg("Created %s session with spi=0x%x, sa_idx=0x%x inl_dev=%u",
                    inbound ? "inbound" : "outbound", eth_sec->spi,
                    eth_sec->sa_idx, eth_sec->inl_dev);
        /*
@@ -1089,7 +1090,7 @@ cn10k_eth_sec_session_destroy(void *device, struct 
rte_security_session *sess)

        rte_spinlock_unlock(lock);

-       plt_nix_dbg("Destroyed %s session with spi=%u, sa_idx=%u, inl_dev=%u",
+       plt_nix_dbg("Destroyed %s session with spi=0x%x, sa_idx=0x%x, 
inl_dev=%u",
                    eth_sec->inb ? "inbound" : "outbound", eth_sec->spi,
                    eth_sec->sa_idx, eth_sec->inl_dev);

@@ -1112,7 +1113,8 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,
        struct cn10k_sec_sess_priv sess_priv;
        struct rte_crypto_sym_xform *crypto;
        struct cnxk_eth_sec_sess *eth_sec;
-       bool inbound;
+       bool inbound, inl_dev;
+       rte_spinlock_t *lock;
        int rc;

        if (conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
@@ -1127,6 +1129,14 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,
        if (!eth_sec)
                return -ENOENT;

+       inl_dev = !!dev->inb.inl_dev;
+       lock = inbound ? &dev->inb.lock : &dev->outb.lock;
+       rte_spinlock_lock(lock);
+
+       /* Acquire lock on inline dev for inbound */
+       if (inbound && inl_dev)
+               roc_nix_inl_dev_lock();
+
        eth_sec->spi = conf->ipsec.spi;

        if (inbound) {
@@ -1140,7 +1150,7 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,

                rc = cnxk_ot_ipsec_inb_sa_fill(inb_sa_dptr, ipsec, crypto);
                if (rc)
-                       return -EINVAL;
+                       goto err;
                /* Use cookie for original data */
                inb_sa_dptr->w1.s.cookie = inb_sa->w1.s.cookie;

@@ -1158,7 +1168,7 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,
                                           eth_sec->inb,
                                           sizeof(struct roc_ot_ipsec_inb_sa));
                if (rc)
-                       return -EINVAL;
+                       goto err;

                /* Save userdata in inb private area */
                inb_priv->userdata = conf->userdata;
@@ -1175,7 +1185,7 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,

                rc = cnxk_ot_ipsec_outb_sa_fill(outb_sa_dptr, ipsec, crypto);
                if (rc)
-                       return -EINVAL;
+                       goto err;

                /* Save rlen info */
                cnxk_ipsec_outb_rlens_get(rlens, ipsec, crypto);
@@ -1204,24 +1214,40 @@ cn10k_eth_sec_session_update(void *device, struct 
rte_security_session *sess,
                                           eth_sec->inb,
                                           sizeof(struct roc_ot_ipsec_outb_sa));
                if (rc)
-                       return -EINVAL;
+                       goto err;

                /* Save userdata */
                outb_priv->userdata = conf->userdata;
                sess->fast_mdata = sess_priv.u64;
        }

+       if (inbound && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);
+
+       plt_nix_dbg("Updated %s session with spi=0x%x, sa_idx=0x%x inl_dev=%u",
+                   inbound ? "inbound" : "outbound", eth_sec->spi, 
eth_sec->sa_idx,
+                   eth_sec->inl_dev);
        return 0;
+
+err:
+       if (inbound && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);
+
+       return rc;
 }

 static int
 cn10k_eth_sec_session_stats_get(void *device, struct rte_security_session 
*sess,
-                           struct rte_security_stats *stats)
+                               struct rte_security_stats *stats)
 {
        struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
        struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
        struct cnxk_macsec_sess *macsec_sess;
        struct cnxk_eth_sec_sess *eth_sec;
+       rte_spinlock_t *lock;
+       bool inl_dev, inb;
        int rc;

        eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
@@ -1232,10 +1258,18 @@ cn10k_eth_sec_session_stats_get(void *device, struct 
rte_security_session *sess,
                return -EINVAL;
        }

-       rc = roc_nix_inl_sa_sync(&dev->nix, eth_sec->sa, eth_sec->inb,
-                           ROC_NIX_INL_SA_OP_FLUSH);
+       inl_dev = !!dev->inb.inl_dev;
+       inb = eth_sec->inb;
+       lock = inb ? &dev->inb.lock : &dev->outb.lock;
+       rte_spinlock_lock(lock);
+
+       /* Acquire lock on inline dev for inbound */
+       if (inb && inl_dev)
+               roc_nix_inl_dev_lock();
+
+       rc = roc_nix_inl_sa_sync(&dev->nix, eth_sec->sa, eth_sec->inb, 
ROC_NIX_INL_SA_OP_FLUSH);
        if (rc)
-               return -EINVAL;
+               goto err;

        stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;

@@ -1251,7 +1285,12 @@ cn10k_eth_sec_session_stats_get(void *device, struct 
rte_security_session *sess,
                        ((struct roc_ot_ipsec_outb_sa 
*)eth_sec->sa)->ctx.mib_octs;
        }

-       return 0;
+err:
+       if (inb && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);
+
+       return rc;
 }

 static void
diff --git a/drivers/net/cnxk/cnxk_ethdev_sec.c 
b/drivers/net/cnxk/cnxk_ethdev_sec.c
index 614997bd3d..ac6ee79f78 100644
--- a/drivers/net/cnxk/cnxk_ethdev_sec.c
+++ b/drivers/net/cnxk/cnxk_ethdev_sec.c
@@ -354,8 +354,25 @@ rte_pmd_cnxk_sa_flush(uint16_t portid, union 
rte_pmd_cnxk_ipsec_hw_sa *sess, boo
 {
        struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
        struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+       rte_spinlock_t *lock;
+       bool inl_dev;
+       int rc;
+
+       inl_dev = !!dev->inb.inl_dev;
+       lock = inb ? &dev->inb.lock : &dev->outb.lock;
+       rte_spinlock_lock(lock);
+
+       /* Acquire lock on inline dev for inbound */
+       if (inb && inl_dev)
+               roc_nix_inl_dev_lock();
+
+       rc = roc_nix_inl_sa_sync(&dev->nix, sess, inb, ROC_NIX_INL_SA_OP_FLUSH);
+
+       if (inb && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);

-       return roc_nix_inl_sa_sync(&dev->nix, sess, inb, 
ROC_NIX_INL_SA_OP_FLUSH);
+       return rc;
 }

 RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_read, 22.07)
@@ -366,6 +383,8 @@ rte_pmd_cnxk_hw_sa_read(uint16_t portid, void *sess, union 
rte_pmd_cnxk_ipsec_hw
        struct rte_eth_dev *eth_dev = &rte_eth_devices[portid];
        struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
        struct cnxk_eth_sec_sess *eth_sec;
+       rte_spinlock_t *lock;
+       bool inl_dev;
        void *sa;
        int rc;

@@ -375,13 +394,31 @@ rte_pmd_cnxk_hw_sa_read(uint16_t portid, void *sess, 
union rte_pmd_cnxk_ipsec_hw
        else
                sa = sess;

+       inl_dev = !!dev->inb.inl_dev;
+       lock = inb ? &dev->inb.lock : &dev->outb.lock;
+       rte_spinlock_lock(lock);
+
+       /* Acquire lock on inline dev for inbound */
+       if (inb && inl_dev)
+               roc_nix_inl_dev_lock();
+
        rc = roc_nix_inl_sa_sync(&dev->nix, sa, inb, ROC_NIX_INL_SA_OP_FLUSH);
        if (rc)
-               return -EINVAL;
+               goto err;
+
+       if (inb && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);

        memcpy(data, sa, len);

        return 0;
+err:
+       if (inb && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);
+
+       return rc;
 }

 RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_hw_sa_write, 22.07)
@@ -393,7 +430,10 @@ rte_pmd_cnxk_hw_sa_write(uint16_t portid, void *sess, 
union rte_pmd_cnxk_ipsec_h
        struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
        struct cnxk_eth_sec_sess *eth_sec;
        struct roc_nix_inl_dev_q *q;
+       rte_spinlock_t *lock;
+       bool inl_dev;
        void *sa;
+       int rc;

        eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
        if (eth_sec)
@@ -405,7 +445,21 @@ rte_pmd_cnxk_hw_sa_write(uint16_t portid, void *sess, 
union rte_pmd_cnxk_ipsec_h
        if (q && cnxk_nix_inl_fc_check(q->fc_addr, &q->fc_addr_sw, q->nb_desc, 
1))
                return -EAGAIN;

-       return roc_nix_inl_ctx_write(&dev->nix, data, sa, inb, len);
+       inl_dev = !!dev->inb.inl_dev;
+       lock = inb ? &dev->inb.lock : &dev->outb.lock;
+       rte_spinlock_lock(lock);
+
+       /* Acquire lock on inline dev for inbound */
+       if (inb && inl_dev)
+               roc_nix_inl_dev_lock();
+
+       rc = roc_nix_inl_ctx_write(&dev->nix, data, sa, inb, len);
+
+       if (inb && inl_dev)
+               roc_nix_inl_dev_unlock();
+       rte_spinlock_unlock(lock);
+
+       return rc;
 }

 RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_cnxk_inl_ipsec_res, 23.11)
--
2.25.1

Reply via email to