if (!dev->ptype_disable)
flags |= NIX_RX_OFFLOAD_PTYPE_F;
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY)
+ flags |= NIX_RX_OFFLOAD_SECURITY_F;
+
return flags;
}
if ((dev->rx_offloads & DEV_RX_OFFLOAD_TIMESTAMP))
flags |= NIX_TX_OFFLOAD_TSTAMP_F;
+ if (dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY)
+ flags |= NIX_TX_OFFLOAD_SECURITY_F;
+
return flags;
}
const struct rte_eth_txconf *tx_conf)
{
struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+ struct roc_cpt_lf *inl_lf;
struct cn9k_eth_txq *txq;
struct roc_nix_sq *sq;
+ uint16_t crypto_qid;
int rc;
RTE_SET_USED(socket);
txq->nb_sqb_bufs_adj = sq->nb_sqb_bufs_adj;
txq->sqes_per_sqb_log2 = sq->sqes_per_sqb_log2;
+ /* Fetch CPT LF info for outbound if present */
+ if (dev->outb.lf_base) {
+ crypto_qid = qid % dev->outb.nb_crypto_qs;
+ inl_lf = dev->outb.lf_base + crypto_qid;
+
+ txq->cpt_io_addr = inl_lf->io_addr;
+ txq->cpt_fc = inl_lf->fc_addr;
+ txq->cpt_desc = inl_lf->nb_desc * 0.7;
+ txq->sa_base = (uint64_t)dev->outb.sa_base;
+ txq->sa_base |= eth_dev->data->port_id;
+ PLT_STATIC_ASSERT(BIT_ULL(16) == ROC_NIX_INL_SA_BASE_ALIGN);
+ }
+
nix_form_default_desc(dev, txq, qid);
txq->lso_tun_fmt = dev->lso_tun_fmt;
return 0;
nix_eth_dev_ops_override();
npc_flow_ops_override();
+ cn9k_eth_sec_ops_override();
+
/* Common probe */
rc = cnxk_nix_probe(pci_drv, pci_dev);
if (rc)
#define __CN9K_ETHDEV_H__
#include <cnxk_ethdev.h>
+#include <cnxk_security.h>
struct cn9k_eth_txq {
uint64_t cmd[8];
uint64_t lso_tun_fmt;
uint16_t sqes_per_sqb_log2;
int16_t nb_sqb_bufs_adj;
+ rte_iova_t cpt_io_addr;
+ uint64_t sa_base;
+ uint64_t *cpt_fc;
+ uint16_t cpt_desc;
} __plt_cache_aligned;
struct cn9k_eth_rxq {
struct cnxk_timesync_info *tstamp;
} __plt_cache_aligned;
+/* Private data in sw rsvd area of struct roc_onf_ipsec_inb_sa */
+struct cn9k_inb_priv_data {
+ void *userdata;
+ struct cnxk_eth_sec_sess *eth_sec;
+};
+
+/* Private data in sw rsvd area of struct roc_onf_ipsec_outb_sa */
+struct cn9k_outb_priv_data {
+ union {
+ uint64_t esn;
+ struct {
+ uint32_t seq;
+ uint32_t esn_hi;
+ };
+ };
+
+ /* Rlen computation data */
+ struct cnxk_ipsec_outb_rlens rlens;
+
+ /* IP identifier */
+ uint16_t ip_id;
+
+ /* SA index */
+ uint32_t sa_idx;
+
+ /* Flags */
+ uint16_t copy_salt : 1;
+
+ /* Salt */
+ uint32_t nonce;
+
+ /* User data pointer */
+ void *userdata;
+
+ /* Back pointer to eth sec session */
+ struct cnxk_eth_sec_sess *eth_sec;
+};
+
+struct cn9k_sec_sess_priv {
+ union {
+ struct {
+ uint32_t sa_idx;
+ uint8_t inb_sa : 1;
+ uint8_t rsvd1 : 2;
+ uint8_t roundup_byte : 5;
+ uint8_t roundup_len;
+ uint16_t partial_len;
+ };
+
+ uint64_t u64;
+ };
+} __rte_packed;
+
/* Rx and Tx routines */
void cn9k_eth_set_rx_function(struct rte_eth_dev *eth_dev);
void cn9k_eth_set_tx_function(struct rte_eth_dev *eth_dev);
+/* Security context setup */
+void cn9k_eth_sec_ops_override(void);
+
#endif /* __CN9K_ETHDEV_H__ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <rte_cryptodev.h>
+#include <rte_security.h>
+#include <rte_security_driver.h>
+
+#include <cn9k_ethdev.h>
+#include <cnxk_security.h>
+
+static struct rte_cryptodev_capabilities cn9k_eth_sec_crypto_caps[] = {
+ { /* AES GCM */
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
+ {.aead = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .block_size = 16,
+ .key_size = {
+ .min = 16,
+ .max = 32,
+ .increment = 8
+ },
+ .digest_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .aad_size = {
+ .min = 8,
+ .max = 12,
+ .increment = 4
+ },
+ .iv_size = {
+ .min = 12,
+ .max = 12,
+ .increment = 0
+ }
+ }, }
+ }, }
+ },
+ RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability cn9k_eth_sec_capabilities[] = {
+ { /* IPsec Inline Protocol ESP Tunnel Ingress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ .options = { 0 }
+ },
+ .crypto_capabilities = cn9k_eth_sec_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ { /* IPsec Inline Protocol ESP Tunnel Egress */
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ .options = { 0 }
+ },
+ .crypto_capabilities = cn9k_eth_sec_crypto_caps,
+ .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE
+ }
+};
+
+static int
+cn9k_eth_sec_session_create(void *device,
+ struct rte_security_session_conf *conf,
+ struct rte_security_session *sess,
+ struct rte_mempool *mempool)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+ struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+ struct rte_security_ipsec_xform *ipsec;
+ struct cn9k_sec_sess_priv sess_priv;
+ struct rte_crypto_sym_xform *crypto;
+ struct cnxk_eth_sec_sess *eth_sec;
+ bool inbound;
+ int rc = 0;
+
+ if (conf->action_type != RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
+ return -ENOTSUP;
+
+ if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC)
+ return -ENOTSUP;
+
+ if (rte_security_dynfield_register() < 0)
+ return -ENOTSUP;
+
+ ipsec = &conf->ipsec;
+ crypto = conf->crypto_xform;
+ inbound = !!(ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS);
+
+ /* Search if a session already exists */
+ if (cnxk_eth_sec_sess_get_by_spi(dev, ipsec->spi, inbound)) {
+ plt_err("%s SA with SPI %u already in use",
+ inbound ? "Inbound" : "Outbound", ipsec->spi);
+ return -EEXIST;
+ }
+
+ if (rte_mempool_get(mempool, (void **)ð_sec)) {
+ plt_err("Could not allocate security session private data");
+ return -ENOMEM;
+ }
+
+ memset(eth_sec, 0, sizeof(struct cnxk_eth_sec_sess));
+ sess_priv.u64 = 0;
+
+ if (inbound) {
+ struct cn9k_inb_priv_data *inb_priv;
+ struct roc_onf_ipsec_inb_sa *inb_sa;
+
+ PLT_STATIC_ASSERT(sizeof(struct cn9k_inb_priv_data) <
+ ROC_NIX_INL_ONF_IPSEC_INB_SW_RSVD);
+
+ /* Get Inbound SA from NIX_RX_IPSEC_SA_BASE. Assume no inline
+ * device always for CN9K.
+ */
+ inb_sa = (struct roc_onf_ipsec_inb_sa *)
+ roc_nix_inl_inb_sa_get(&dev->nix, false, ipsec->spi);
+ if (!inb_sa) {
+ plt_err("Failed to create ingress sa");
+ rc = -EFAULT;
+ goto mempool_put;
+ }
+
+ /* Check if SA is already in use */
+ if (inb_sa->ctl.valid) {
+ plt_err("Inbound SA with SPI %u already in use",
+ ipsec->spi);
+ rc = -EBUSY;
+ goto mempool_put;
+ }
+
+ memset(inb_sa, 0, sizeof(struct roc_onf_ipsec_inb_sa));
+
+ /* Fill inbound sa params */
+ rc = cnxk_onf_ipsec_inb_sa_fill(inb_sa, ipsec, crypto);
+ if (rc) {
+ plt_err("Failed to init inbound sa, rc=%d", rc);
+ goto mempool_put;
+ }
+
+ inb_priv = roc_nix_inl_onf_ipsec_inb_sa_sw_rsvd(inb_sa);
+ /* Back pointer to get eth_sec */
+ inb_priv->eth_sec = eth_sec;
+
+ /* Save userdata in inb private area */
+ inb_priv->userdata = conf->userdata;
+
+ sess_priv.inb_sa = 1;
+ sess_priv.sa_idx = ipsec->spi;
+
+ /* Pointer from eth_sec -> inb_sa */
+ eth_sec->sa = inb_sa;
+ eth_sec->sess = sess;
+ eth_sec->sa_idx = ipsec->spi;
+ eth_sec->spi = ipsec->spi;
+ eth_sec->inb = true;
+
+ TAILQ_INSERT_TAIL(&dev->inb.list, eth_sec, entry);
+ dev->inb.nb_sess++;
+ } else {
+ struct cn9k_outb_priv_data *outb_priv;
+ struct roc_onf_ipsec_outb_sa *outb_sa;
+ uintptr_t sa_base = dev->outb.sa_base;
+ struct cnxk_ipsec_outb_rlens *rlens;
+ uint32_t sa_idx;
+
+ PLT_STATIC_ASSERT(sizeof(struct cn9k_outb_priv_data) <
+ ROC_NIX_INL_ONF_IPSEC_OUTB_SW_RSVD);
+
+ /* Alloc an sa index */
+ rc = cnxk_eth_outb_sa_idx_get(dev, &sa_idx);
+ if (rc)
+ goto mempool_put;
+
+ outb_sa = roc_nix_inl_onf_ipsec_outb_sa(sa_base, sa_idx);
+ outb_priv = roc_nix_inl_onf_ipsec_outb_sa_sw_rsvd(outb_sa);
+ rlens = &outb_priv->rlens;
+
+ memset(outb_sa, 0, sizeof(struct roc_onf_ipsec_outb_sa));
+
+ /* Fill outbound sa params */
+ rc = cnxk_onf_ipsec_outb_sa_fill(outb_sa, ipsec, crypto);
+ if (rc) {
+ plt_err("Failed to init outbound sa, rc=%d", rc);
+ rc |= cnxk_eth_outb_sa_idx_put(dev, sa_idx);
+ goto mempool_put;
+ }
+
+ /* Save userdata */
+ outb_priv->userdata = conf->userdata;
+ outb_priv->sa_idx = sa_idx;
+ outb_priv->eth_sec = eth_sec;
+ /* Start sequence number with 1 */
+ outb_priv->seq = 1;
+
+ memcpy(&outb_priv->nonce, outb_sa->nonce, 4);
+ if (outb_sa->ctl.enc_type == ROC_IE_ON_SA_ENC_AES_GCM)
+ outb_priv->copy_salt = 1;
+
+ /* Save rlen info */
+ cnxk_ipsec_outb_rlens_get(rlens, ipsec, crypto);
+
+ sess_priv.sa_idx = outb_priv->sa_idx;
+ sess_priv.roundup_byte = rlens->roundup_byte;
+ sess_priv.roundup_len = rlens->roundup_len;
+ sess_priv.partial_len = rlens->partial_len;
+
+ /* Pointer from eth_sec -> outb_sa */
+ eth_sec->sa = outb_sa;
+ eth_sec->sess = sess;
+ eth_sec->sa_idx = sa_idx;
+ eth_sec->spi = ipsec->spi;
+
+ TAILQ_INSERT_TAIL(&dev->outb.list, eth_sec, entry);
+ dev->outb.nb_sess++;
+ }
+
+ /* Sync SA content */
+ plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
+
+ plt_nix_dbg("Created %s session with spi=%u, sa_idx=%u",
+ inbound ? "inbound" : "outbound", eth_sec->spi,
+ eth_sec->sa_idx);
+ /*
+ * Update fast path info in priv area.
+ */
+ set_sec_session_private_data(sess, (void *)sess_priv.u64);
+
+ return 0;
+mempool_put:
+ rte_mempool_put(mempool, eth_sec);
+ return rc;
+}
+
+static int
+cn9k_eth_sec_session_destroy(void *device, struct rte_security_session *sess)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
+ struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+ struct roc_onf_ipsec_outb_sa *outb_sa;
+ struct roc_onf_ipsec_inb_sa *inb_sa;
+ struct cnxk_eth_sec_sess *eth_sec;
+ struct rte_mempool *mp;
+
+ eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, sess);
+ if (!eth_sec)
+ return -ENOENT;
+
+ if (eth_sec->inb) {
+ inb_sa = eth_sec->sa;
+ /* Disable SA */
+ inb_sa->ctl.valid = 0;
+
+ TAILQ_REMOVE(&dev->inb.list, eth_sec, entry);
+ dev->inb.nb_sess--;
+ } else {
+ outb_sa = eth_sec->sa;
+ /* Disable SA */
+ outb_sa->ctl.valid = 0;
+
+ /* Release Outbound SA index */
+ cnxk_eth_outb_sa_idx_put(dev, eth_sec->sa_idx);
+ TAILQ_REMOVE(&dev->outb.list, eth_sec, entry);
+ dev->outb.nb_sess--;
+ }
+
+ /* Sync SA content */
+ plt_atomic_thread_fence(__ATOMIC_ACQ_REL);
+
+ plt_nix_dbg("Destroyed %s session with spi=%u, sa_idx=%u",
+ eth_sec->inb ? "inbound" : "outbound", eth_sec->spi,
+ eth_sec->sa_idx);
+
+ /* Put eth_sec object back to pool */
+ mp = rte_mempool_from_obj(eth_sec);
+ set_sec_session_private_data(sess, NULL);
+ rte_mempool_put(mp, eth_sec);
+ return 0;
+}
+
+static const struct rte_security_capability *
+cn9k_eth_sec_capabilities_get(void *device __rte_unused)
+{
+ return cn9k_eth_sec_capabilities;
+}
+
+void
+cn9k_eth_sec_ops_override(void)
+{
+ static int init_once;
+
+ if (init_once)
+ return;
+ init_once = 1;
+
+ /* Update platform specific ops */
+ cnxk_eth_sec_ops.session_create = cn9k_eth_sec_session_create;
+ cnxk_eth_sec_ops.session_destroy = cn9k_eth_sec_session_destroy;
+ cnxk_eth_sec_ops.capabilities_get = cn9k_eth_sec_capabilities_get;
+}
#define NIX_RX_OFFLOAD_MARK_UPDATE_F BIT(3)
#define NIX_RX_OFFLOAD_TSTAMP_F BIT(4)
#define NIX_RX_OFFLOAD_VLAN_STRIP_F BIT(5)
+#define NIX_RX_OFFLOAD_SECURITY_F BIT(6)
/* Flags to control cqe_to_mbuf conversion function.
* Defining it from backwards to denote its been
#define NIX_TX_OFFLOAD_MBUF_NOFF_F BIT(3)
#define NIX_TX_OFFLOAD_TSO_F BIT(4)
#define NIX_TX_OFFLOAD_TSTAMP_F BIT(5)
+#define NIX_TX_OFFLOAD_SECURITY_F BIT(6)
/* Flags to control xmit_prepare function.
* Defining it from backwards to denote its been
return speed_capa;
}
+int
+cnxk_nix_inb_mode_set(struct cnxk_eth_dev *dev, bool use_inl_dev)
+{
+ struct roc_nix *nix = &dev->nix;
+
+ if (dev->inb.inl_dev == use_inl_dev)
+ return 0;
+
+ plt_nix_dbg("Security sessions(%u) still active, inl=%u!!!",
+ dev->inb.nb_sess, !!dev->inb.inl_dev);
+
+ /* Change the mode */
+ dev->inb.inl_dev = use_inl_dev;
+
+ /* Update RoC for NPC rule insertion */
+ roc_nix_inb_mode_set(nix, use_inl_dev);
+
+ /* Setup lookup mem */
+ return cnxk_nix_lookup_mem_sa_base_set(dev);
+}
+
+static int
+nix_security_setup(struct cnxk_eth_dev *dev)
+{
+ struct roc_nix *nix = &dev->nix;
+ int i, rc = 0;
+
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
+ /* Setup Inline Inbound */
+ rc = roc_nix_inl_inb_init(nix);
+ if (rc) {
+ plt_err("Failed to initialize nix inline inb, rc=%d",
+ rc);
+ return rc;
+ }
+
+ /* By default pick using inline device for poll mode.
+ * Will be overridden when event mode rq's are setup.
+ */
+ cnxk_nix_inb_mode_set(dev, true);
+ }
+
+ if (dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY ||
+ dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
+ struct plt_bitmap *bmap;
+ size_t bmap_sz;
+ void *mem;
+
+ /* Setup enough descriptors for all tx queues */
+ nix->outb_nb_desc = dev->outb.nb_desc;
+ nix->outb_nb_crypto_qs = dev->outb.nb_crypto_qs;
+
+ /* Setup Inline Outbound */
+ rc = roc_nix_inl_outb_init(nix);
+ if (rc) {
+ plt_err("Failed to initialize nix inline outb, rc=%d",
+ rc);
+ goto cleanup;
+ }
+
+ dev->outb.lf_base = roc_nix_inl_outb_lf_base_get(nix);
+
+ /* Skip the rest if DEV_TX_OFFLOAD_SECURITY is not enabled */
+ if (!(dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY))
+ goto done;
+
+ rc = -ENOMEM;
+ /* Allocate a bitmap to alloc and free sa indexes */
+ bmap_sz = plt_bitmap_get_memory_footprint(dev->outb.max_sa);
+ mem = plt_zmalloc(bmap_sz, PLT_CACHE_LINE_SIZE);
+ if (mem == NULL) {
+ plt_err("Outbound SA bmap alloc failed");
+
+ rc |= roc_nix_inl_outb_fini(nix);
+ goto cleanup;
+ }
+
+ rc = -EIO;
+ bmap = plt_bitmap_init(dev->outb.max_sa, mem, bmap_sz);
+ if (!bmap) {
+ plt_err("Outbound SA bmap init failed");
+
+ rc |= roc_nix_inl_outb_fini(nix);
+ plt_free(mem);
+ goto cleanup;
+ }
+
+ for (i = 0; i < dev->outb.max_sa; i++)
+ plt_bitmap_set(bmap, i);
+
+ dev->outb.sa_base = roc_nix_inl_outb_sa_base_get(nix);
+ dev->outb.sa_bmap_mem = mem;
+ dev->outb.sa_bmap = bmap;
+ }
+
+done:
+ return 0;
+cleanup:
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY)
+ rc |= roc_nix_inl_inb_fini(nix);
+ return rc;
+}
+
+static int
+nix_security_release(struct cnxk_eth_dev *dev)
+{
+ struct rte_eth_dev *eth_dev = dev->eth_dev;
+ struct cnxk_eth_sec_sess *eth_sec, *tvar;
+ struct roc_nix *nix = &dev->nix;
+ int rc, ret = 0;
+
+ /* Cleanup Inline inbound */
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
+ /* Destroy inbound sessions */
+ tvar = NULL;
+ RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->inb.list, entry, tvar)
+ cnxk_eth_sec_ops.session_destroy(eth_dev,
+ eth_sec->sess);
+
+ /* Clear lookup mem */
+ cnxk_nix_lookup_mem_sa_base_clear(dev);
+
+ rc = roc_nix_inl_inb_fini(nix);
+ if (rc)
+ plt_err("Failed to cleanup nix inline inb, rc=%d", rc);
+ ret |= rc;
+ }
+
+ /* Cleanup Inline outbound */
+ if (dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY ||
+ dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
+ /* Destroy outbound sessions */
+ tvar = NULL;
+ RTE_TAILQ_FOREACH_SAFE(eth_sec, &dev->outb.list, entry, tvar)
+ cnxk_eth_sec_ops.session_destroy(eth_dev,
+ eth_sec->sess);
+
+ rc = roc_nix_inl_outb_fini(nix);
+ if (rc)
+ plt_err("Failed to cleanup nix inline outb, rc=%d", rc);
+ ret |= rc;
+
+ plt_bitmap_free(dev->outb.sa_bmap);
+ plt_free(dev->outb.sa_bmap_mem);
+ dev->outb.sa_bmap = NULL;
+ dev->outb.sa_bmap_mem = NULL;
+ }
+
+ dev->inb.inl_dev = false;
+ roc_nix_inb_mode_set(nix, false);
+ dev->nb_rxq_sso = 0;
+ dev->inb.nb_sess = 0;
+ dev->outb.nb_sess = 0;
+ return ret;
+}
+
static void
nix_enable_mseg_on_jumbo(struct cnxk_eth_rxq_sp *rxq)
{
eth_dev->data->tx_queues[qid] = NULL;
}
+ /* When Tx Security offload is enabled, increase tx desc count by
+ * max possible outbound desc count.
+ */
+ if (dev->tx_offloads & DEV_TX_OFFLOAD_SECURITY)
+ nb_desc += dev->outb.nb_desc;
+
/* Setup ROC SQ */
sq = &dev->sqs[qid];
sq->qid = qid;
struct rte_mempool *mp)
{
struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+ struct roc_nix *nix = &dev->nix;
struct cnxk_eth_rxq_sp *rxq_sp;
struct rte_mempool_ops *ops;
const char *platform_ops;
eth_dev->data->rx_queues[qid] = NULL;
}
+ /* Clam up cq limit to size of packet pool aura for LBK
+ * to avoid meta packet drop as LBK does not currently support
+ * backpressure.
+ */
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY && roc_nix_is_lbk(nix)) {
+ uint64_t pkt_pool_limit = roc_nix_inl_dev_rq_limit_get();
+
+ /* Use current RQ's aura limit if inl rq is not available */
+ if (!pkt_pool_limit)
+ pkt_pool_limit = roc_npa_aura_op_limit_get(mp->pool_id);
+ nb_desc = RTE_MAX(nb_desc, pkt_pool_limit);
+ }
+
/* Setup ROC CQ */
cq = &dev->cqs[qid];
cq->qid = qid;
rq->later_skip = sizeof(struct rte_mbuf);
rq->lpb_size = mp->elt_size;
+ /* Enable Inline IPSec on RQ, will not be used for Poll mode */
+ if (roc_nix_inl_inb_is_enabled(nix))
+ rq->ipsech_ena = true;
+
rc = roc_nix_rq_init(&dev->nix, rq, !!eth_dev->data->dev_started);
if (rc) {
plt_err("Failed to init roc rq for rq=%d, rc=%d", qid, rc);
rxq_sp->qconf.nb_desc = nb_desc;
rxq_sp->qconf.mp = mp;
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
+ /* Setup rq reference for inline dev if present */
+ rc = roc_nix_inl_dev_rq_get(rq);
+ if (rc)
+ goto free_mem;
+ }
+
plt_nix_dbg("rq=%d pool=%s nb_desc=%d->%d", qid, mp->name, nb_desc,
cq->nb_desc);
}
return 0;
+free_mem:
+ plt_free(rxq_sp);
rq_fini:
rc |= roc_nix_rq_fini(rq);
cq_fini:
rxq_sp = cnxk_eth_rxq_to_sp(rxq);
dev = rxq_sp->dev;
qid = rxq_sp->qid;
+ rq = &dev->rqs[qid];
plt_nix_dbg("Releasing rxq %u", qid);
+ /* Release rq reference for inline dev if present */
+ if (dev->rx_offloads & DEV_RX_OFFLOAD_SECURITY)
+ roc_nix_inl_dev_rq_put(rq);
+
/* Cleanup ROC RQ */
- rq = &dev->rqs[qid];
rc = roc_nix_rq_fini(rq);
if (rc)
plt_err("Failed to cleanup rq, rc=%d", rc);
rc = nix_store_queue_cfg_and_then_release(eth_dev);
if (rc)
goto fail_configure;
+
+ /* Cleanup security support */
+ rc = nix_security_release(dev);
+ if (rc)
+ goto fail_configure;
+
roc_nix_tm_fini(nix);
roc_nix_lf_free(nix);
}
plt_err("Failed to initialize flow control rc=%d", rc);
goto cq_fini;
}
+
+ /* Setup Inline security support */
+ rc = nix_security_setup(dev);
+ if (rc)
+ goto cq_fini;
+
/*
* Restore queue config when reconfigure followed by
* reconfigure and no queue configure invoked from application case.
if (dev->configured == 1) {
rc = nix_restore_queue_cfg(eth_dev);
if (rc)
- goto cq_fini;
+ goto sec_release;
}
/* Update the mac address */
dev->nb_txq = data->nb_tx_queues;
return 0;
+sec_release:
+ rc |= nix_security_release(dev);
cq_fini:
roc_nix_unregister_cq_irqs(nix);
q_irq_fini:
cnxk_eth_dev_init(struct rte_eth_dev *eth_dev)
{
struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+ struct rte_security_ctx *sec_ctx;
struct roc_nix *nix = &dev->nix;
struct rte_pci_device *pci_dev;
int rc, max_entries;
eth_dev->dev_ops = &cnxk_eth_dev_ops;
+ /* Alloc security context */
+ sec_ctx = plt_zmalloc(sizeof(struct rte_security_ctx), 0);
+ if (!sec_ctx)
+ return -ENOMEM;
+ sec_ctx->device = eth_dev;
+ sec_ctx->ops = &cnxk_eth_sec_ops;
+ sec_ctx->flags =
+ (RTE_SEC_CTX_F_FAST_SET_MDATA | RTE_SEC_CTX_F_FAST_GET_UDATA);
+ eth_dev->security_ctx = sec_ctx;
+ TAILQ_INIT(&dev->inb.list);
+ TAILQ_INIT(&dev->outb.list);
+
/* For secondary processes, the primary has done all the work */
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
struct roc_nix *nix = &dev->nix;
int rc, i;
+ plt_free(eth_dev->security_ctx);
+ eth_dev->security_ctx = NULL;
+
/* Nothing to be done for secondary processes */
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
}
eth_dev->data->nb_rx_queues = 0;
+ /* Free security resources */
+ nix_security_release(dev);
+
/* Free tm resources */
roc_nix_tm_fini(nix);
#include <rte_mbuf.h>
#include <rte_mbuf_pool_ops.h>
#include <rte_mempool.h>
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#include <rte_tailq.h>
#include <rte_time.h>
#include "roc_api.h"
DEV_TX_OFFLOAD_SCTP_CKSUM | DEV_TX_OFFLOAD_TCP_TSO | \
DEV_TX_OFFLOAD_VXLAN_TNL_TSO | DEV_TX_OFFLOAD_GENEVE_TNL_TSO | \
DEV_TX_OFFLOAD_GRE_TNL_TSO | DEV_TX_OFFLOAD_MULTI_SEGS | \
- DEV_TX_OFFLOAD_IPV4_CKSUM)
+ DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_SECURITY)
#define CNXK_NIX_RX_OFFLOAD_CAPA \
(DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_SCTP_CKSUM | \
DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | DEV_RX_OFFLOAD_SCATTER | \
DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_OUTER_UDP_CKSUM | \
DEV_RX_OFFLOAD_RSS_HASH | DEV_RX_OFFLOAD_TIMESTAMP | \
- DEV_RX_OFFLOAD_VLAN_STRIP)
+ DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_SECURITY)
#define RSS_IPV4_ENABLE \
(ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 | ETH_RSS_NONFRAG_IPV4_UDP | \
#define PTYPE_TUNNEL_ARRAY_SZ BIT(PTYPE_TUNNEL_WIDTH)
#define PTYPE_ARRAY_SZ \
((PTYPE_NON_TUNNEL_ARRAY_SZ + PTYPE_TUNNEL_ARRAY_SZ) * sizeof(uint16_t))
+
+/* NIX_RX_PARSE_S's ERRCODE + ERRLEV (12 bits) */
+#define ERRCODE_ERRLEN_WIDTH 12
+#define ERR_ARRAY_SZ ((BIT(ERRCODE_ERRLEN_WIDTH)) * sizeof(uint32_t))
+
/* Fastpath lookup */
#define CNXK_NIX_FASTPATH_LOOKUP_MEM "cnxk_nix_fastpath_lookup_mem"
((1ull << (PKT_TX_TUNNEL_VXLAN >> 45)) | \
(1ull << (PKT_TX_TUNNEL_GENEVE >> 45)))
+/* Subtype from inline outbound error event */
+#define CNXK_ETHDEV_SEC_OUTB_EV_SUB 0xFFUL
+
struct cnxk_fc_cfg {
enum rte_eth_fc_mode mode;
uint8_t rx_pause;
uint64_t *tx_tstamp;
} __plt_cache_aligned;
+/* Security session private data */
+struct cnxk_eth_sec_sess {
+ /* List entry */
+ TAILQ_ENTRY(cnxk_eth_sec_sess) entry;
+
+ /* Inbound SA is from NIX_RX_IPSEC_SA_BASE or
+ * Outbound SA from roc_nix_inl_outb_sa_base_get()
+ */
+ void *sa;
+
+ /* SA index */
+ uint32_t sa_idx;
+
+ /* SPI */
+ uint32_t spi;
+
+ /* Back pointer to session */
+ struct rte_security_session *sess;
+
+ /* Inbound */
+ bool inb;
+
+ /* Inbound session on inl dev */
+ bool inl_dev;
+};
+
+TAILQ_HEAD(cnxk_eth_sec_sess_list, cnxk_eth_sec_sess);
+
+/* Inbound security data */
+struct cnxk_eth_dev_sec_inb {
+ /* IPSec inbound max SPI */
+ uint16_t max_spi;
+
+ /* Using inbound with inline device */
+ bool inl_dev;
+
+ /* Device argument to force inline device for inb */
+ bool force_inl_dev;
+
+ /* Active sessions */
+ uint16_t nb_sess;
+
+ /* List of sessions */
+ struct cnxk_eth_sec_sess_list list;
+};
+
+/* Outbound security data */
+struct cnxk_eth_dev_sec_outb {
+ /* IPSec outbound max SA */
+ uint16_t max_sa;
+
+ /* Per CPT LF descriptor count */
+ uint32_t nb_desc;
+
+ /* SA Bitmap */
+ struct plt_bitmap *sa_bmap;
+
+ /* SA bitmap memory */
+ void *sa_bmap_mem;
+
+ /* SA base */
+ uint64_t sa_base;
+
+ /* CPT LF base */
+ struct roc_cpt_lf *lf_base;
+
+ /* Crypto queues => CPT lf count */
+ uint16_t nb_crypto_qs;
+
+ /* Active sessions */
+ uint16_t nb_sess;
+
+ /* List of sessions */
+ struct cnxk_eth_sec_sess_list list;
+};
+
struct cnxk_eth_dev {
/* ROC NIX */
struct roc_nix nix;
/* Configured queue count */
uint16_t nb_rxq;
uint16_t nb_txq;
+ uint16_t nb_rxq_sso;
uint8_t configured;
/* Max macfilter entries */
/* Per queue statistics counters */
uint32_t txq_stat_map[RTE_ETHDEV_QUEUE_STAT_CNTRS];
uint32_t rxq_stat_map[RTE_ETHDEV_QUEUE_STAT_CNTRS];
+
+ /* Security data */
+ struct cnxk_eth_dev_sec_inb inb;
+ struct cnxk_eth_dev_sec_outb outb;
};
struct cnxk_eth_rxq_sp {
/* Common flow ops */
extern struct rte_flow_ops cnxk_flow_ops;
+/* Common security ops */
+extern struct rte_security_ops cnxk_eth_sec_ops;
+
/* Ops */
int cnxk_nix_probe(struct rte_pci_driver *pci_drv,
struct rte_pci_device *pci_dev);
/* Debug */
int cnxk_nix_dev_get_reg(struct rte_eth_dev *eth_dev,
struct rte_dev_reg_info *regs);
+/* Security */
+int cnxk_eth_outb_sa_idx_get(struct cnxk_eth_dev *dev, uint32_t *idx_p);
+int cnxk_eth_outb_sa_idx_put(struct cnxk_eth_dev *dev, uint32_t idx);
+int cnxk_nix_lookup_mem_sa_base_set(struct cnxk_eth_dev *dev);
+int cnxk_nix_lookup_mem_sa_base_clear(struct cnxk_eth_dev *dev);
+__rte_internal
+int cnxk_nix_inb_mode_set(struct cnxk_eth_dev *dev, bool use_inl_dev);
+struct cnxk_eth_sec_sess *cnxk_eth_sec_sess_get_by_spi(struct cnxk_eth_dev *dev,
+ uint32_t spi, bool inb);
+struct cnxk_eth_sec_sess *
+cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev,
+ struct rte_security_session *sess);
/* Other private functions */
int nix_recalc_mtu(struct rte_eth_dev *eth_dev);
}
}
+static __rte_always_inline uintptr_t
+cnxk_nix_sa_base_get(uint16_t port, const void *lookup_mem)
+{
+ uintptr_t sa_base_tbl;
+
+ sa_base_tbl = (uintptr_t)lookup_mem;
+ sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
+ return *((const uintptr_t *)sa_base_tbl + port);
+}
+
#endif /* __CNXK_ETHDEV_H__ */
#include "cnxk_ethdev.h"
+static int
+parse_outb_nb_desc(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ *(uint16_t *)extra_args = val;
+
+ return 0;
+}
+
+static int
+parse_outb_nb_crypto_qs(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ if (val < 1 || val > 64)
+ return -EINVAL;
+
+ *(uint16_t *)extra_args = val;
+
+ return 0;
+}
+
+static int
+parse_ipsec_in_max_spi(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ *(uint16_t *)extra_args = val;
+
+ return 0;
+}
+
+static int
+parse_ipsec_out_max_sa(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ *(uint16_t *)extra_args = val;
+
+ return 0;
+}
+
static int
parse_flow_max_priority(const char *key, const char *value, void *extra_args)
{
#define CNXK_SWITCH_HEADER_TYPE "switch_header"
#define CNXK_RSS_TAG_AS_XOR "tag_as_xor"
#define CNXK_LOCK_RX_CTX "lock_rx_ctx"
+#define CNXK_IPSEC_IN_MAX_SPI "ipsec_in_max_spi"
+#define CNXK_IPSEC_OUT_MAX_SA "ipsec_out_max_sa"
+#define CNXK_OUTB_NB_DESC "outb_nb_desc"
+#define CNXK_FORCE_INB_INL_DEV "force_inb_inl_dev"
+#define CNXK_OUTB_NB_CRYPTO_QS "outb_nb_crypto_qs"
int
cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
{
uint16_t reta_sz = ROC_NIX_RSS_RETA_SZ_64;
uint16_t sqb_count = CNXK_NIX_TX_MAX_SQB;
+ uint16_t ipsec_in_max_spi = BIT(8) - 1;
+ uint16_t ipsec_out_max_sa = BIT(12);
uint16_t flow_prealloc_size = 1;
uint16_t switch_header_type = 0;
uint16_t flow_max_priority = 3;
+ uint16_t force_inb_inl_dev = 0;
+ uint16_t outb_nb_crypto_qs = 1;
+ uint16_t outb_nb_desc = 8200;
uint16_t rss_tag_as_xor = 0;
uint16_t scalar_enable = 0;
uint8_t lock_rx_ctx = 0;
rte_kvargs_process(kvlist, CNXK_RSS_TAG_AS_XOR, &parse_flag,
&rss_tag_as_xor);
rte_kvargs_process(kvlist, CNXK_LOCK_RX_CTX, &parse_flag, &lock_rx_ctx);
+ rte_kvargs_process(kvlist, CNXK_IPSEC_IN_MAX_SPI,
+ &parse_ipsec_in_max_spi, &ipsec_in_max_spi);
+ rte_kvargs_process(kvlist, CNXK_IPSEC_OUT_MAX_SA,
+ &parse_ipsec_out_max_sa, &ipsec_out_max_sa);
+ rte_kvargs_process(kvlist, CNXK_OUTB_NB_DESC, &parse_outb_nb_desc,
+ &outb_nb_desc);
+ rte_kvargs_process(kvlist, CNXK_OUTB_NB_CRYPTO_QS,
+ &parse_outb_nb_crypto_qs, &outb_nb_crypto_qs);
+ rte_kvargs_process(kvlist, CNXK_FORCE_INB_INL_DEV, &parse_flag,
+ &force_inb_inl_dev);
rte_kvargs_free(kvlist);
null_devargs:
dev->scalar_ena = !!scalar_enable;
+ dev->inb.force_inl_dev = !!force_inb_inl_dev;
+ dev->inb.max_spi = ipsec_in_max_spi;
+ dev->outb.max_sa = ipsec_out_max_sa;
+ dev->outb.nb_desc = outb_nb_desc;
+ dev->outb.nb_crypto_qs = outb_nb_crypto_qs;
+ dev->nix.ipsec_in_max_spi = ipsec_in_max_spi;
+ dev->nix.ipsec_out_max_sa = ipsec_out_max_sa;
dev->nix.rss_tag_as_xor = !!rss_tag_as_xor;
dev->nix.max_sqb_count = sqb_count;
dev->nix.reta_sz = reta_sz;
CNXK_FLOW_PREALLOC_SIZE "=<1-32>"
CNXK_FLOW_MAX_PRIORITY "=<1-32>"
CNXK_SWITCH_HEADER_TYPE "=<higig2|dsa|chlen90b>"
- CNXK_RSS_TAG_AS_XOR "=1");
+ CNXK_RSS_TAG_AS_XOR "=1"
+ CNXK_IPSEC_IN_MAX_SPI "=<1-65535>"
+ CNXK_OUTB_NB_DESC "=<1-65535>"
+ CNXK_OUTB_NB_CRYPTO_QS "=<1-64>"
+ CNXK_FORCE_INB_INL_DEV "=1");
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <cnxk_ethdev.h>
+
+#define CNXK_NIX_INL_SELFTEST "selftest"
+#define CNXK_NIX_INL_IPSEC_IN_MAX_SPI "ipsec_in_max_spi"
+
+#define CNXK_NIX_INL_DEV_NAME RTE_STR(cnxk_nix_inl_dev_)
+#define CNXK_NIX_INL_DEV_NAME_LEN \
+ (sizeof(CNXK_NIX_INL_DEV_NAME) + PCI_PRI_STR_SIZE)
+
+static inline int
+bitmap_ctzll(uint64_t slab)
+{
+ if (slab == 0)
+ return 0;
+
+ return __builtin_ctzll(slab);
+}
+
+int
+cnxk_eth_outb_sa_idx_get(struct cnxk_eth_dev *dev, uint32_t *idx_p)
+{
+ uint32_t pos, idx;
+ uint64_t slab;
+ int rc;
+
+ if (!dev->outb.sa_bmap)
+ return -ENOTSUP;
+
+ pos = 0;
+ slab = 0;
+ /* Scan from the beginning */
+ plt_bitmap_scan_init(dev->outb.sa_bmap);
+ /* Scan bitmap to get the free sa index */
+ rc = plt_bitmap_scan(dev->outb.sa_bmap, &pos, &slab);
+ /* Empty bitmap */
+ if (rc == 0) {
+ plt_err("Outbound SA' exhausted, use 'ipsec_out_max_sa' "
+ "devargs to increase");
+ return -ERANGE;
+ }
+
+ /* Get free SA index */
+ idx = pos + bitmap_ctzll(slab);
+ plt_bitmap_clear(dev->outb.sa_bmap, idx);
+ *idx_p = idx;
+ return 0;
+}
+
+int
+cnxk_eth_outb_sa_idx_put(struct cnxk_eth_dev *dev, uint32_t idx)
+{
+ if (idx >= dev->outb.max_sa)
+ return -EINVAL;
+
+ /* Check if it is already free */
+ if (plt_bitmap_get(dev->outb.sa_bmap, idx))
+ return -EINVAL;
+
+ /* Mark index as free */
+ plt_bitmap_set(dev->outb.sa_bmap, idx);
+ return 0;
+}
+
+struct cnxk_eth_sec_sess *
+cnxk_eth_sec_sess_get_by_spi(struct cnxk_eth_dev *dev, uint32_t spi, bool inb)
+{
+ struct cnxk_eth_sec_sess_list *list;
+ struct cnxk_eth_sec_sess *eth_sec;
+
+ list = inb ? &dev->inb.list : &dev->outb.list;
+ TAILQ_FOREACH(eth_sec, list, entry) {
+ if (eth_sec->spi == spi)
+ return eth_sec;
+ }
+
+ return NULL;
+}
+
+struct cnxk_eth_sec_sess *
+cnxk_eth_sec_sess_get_by_sess(struct cnxk_eth_dev *dev,
+ struct rte_security_session *sess)
+{
+ struct cnxk_eth_sec_sess *eth_sec = NULL;
+
+ /* Search in inbound list */
+ TAILQ_FOREACH(eth_sec, &dev->inb.list, entry) {
+ if (eth_sec->sess == sess)
+ return eth_sec;
+ }
+
+ /* Search in outbound list */
+ TAILQ_FOREACH(eth_sec, &dev->outb.list, entry) {
+ if (eth_sec->sess == sess)
+ return eth_sec;
+ }
+
+ return NULL;
+}
+
+static unsigned int
+cnxk_eth_sec_session_get_size(void *device __rte_unused)
+{
+ return sizeof(struct cnxk_eth_sec_sess);
+}
+
+struct rte_security_ops cnxk_eth_sec_ops = {
+ .session_get_size = cnxk_eth_sec_session_get_size
+};
+
+static int
+parse_ipsec_in_max_spi(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ *(uint16_t *)extra_args = val;
+
+ return 0;
+}
+
+static int
+parse_selftest(const char *key, const char *value, void *extra_args)
+{
+ RTE_SET_USED(key);
+ uint32_t val;
+
+ val = atoi(value);
+
+ *(uint8_t *)extra_args = !!(val == 1);
+ return 0;
+}
+
+static int
+nix_inl_parse_devargs(struct rte_devargs *devargs,
+ struct roc_nix_inl_dev *inl_dev)
+{
+ uint32_t ipsec_in_max_spi = BIT(8) - 1;
+ struct rte_kvargs *kvlist;
+ uint8_t selftest = 0;
+
+ if (devargs == NULL)
+ goto null_devargs;
+
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL)
+ goto exit;
+
+ rte_kvargs_process(kvlist, CNXK_NIX_INL_SELFTEST, &parse_selftest,
+ &selftest);
+ rte_kvargs_process(kvlist, CNXK_NIX_INL_IPSEC_IN_MAX_SPI,
+ &parse_ipsec_in_max_spi, &ipsec_in_max_spi);
+ rte_kvargs_free(kvlist);
+
+null_devargs:
+ inl_dev->ipsec_in_max_spi = ipsec_in_max_spi;
+ inl_dev->selftest = selftest;
+ return 0;
+exit:
+ return -EINVAL;
+}
+
+static inline char *
+nix_inl_dev_to_name(struct rte_pci_device *pci_dev, char *name)
+{
+ snprintf(name, CNXK_NIX_INL_DEV_NAME_LEN,
+ CNXK_NIX_INL_DEV_NAME PCI_PRI_FMT, pci_dev->addr.domain,
+ pci_dev->addr.bus, pci_dev->addr.devid,
+ pci_dev->addr.function);
+
+ return name;
+}
+
+static int
+cnxk_nix_inl_dev_remove(struct rte_pci_device *pci_dev)
+{
+ char name[CNXK_NIX_INL_DEV_NAME_LEN];
+ const struct rte_memzone *mz;
+ struct roc_nix_inl_dev *dev;
+ int rc;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ mz = rte_memzone_lookup(nix_inl_dev_to_name(pci_dev, name));
+ if (!mz)
+ return 0;
+
+ dev = mz->addr;
+
+ /* Cleanup inline dev */
+ rc = roc_nix_inl_dev_fini(dev);
+ if (rc) {
+ plt_err("Failed to cleanup inl dev, rc=%d(%s)", rc,
+ roc_error_msg_get(rc));
+ return rc;
+ }
+
+ rte_memzone_free(mz);
+ return 0;
+}
+
+static int
+cnxk_nix_inl_dev_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ char name[CNXK_NIX_INL_DEV_NAME_LEN];
+ struct roc_nix_inl_dev *inl_dev;
+ const struct rte_memzone *mz;
+ int rc = -ENOMEM;
+
+ RTE_SET_USED(pci_drv);
+
+ rc = roc_plt_init();
+ if (rc) {
+ plt_err("Failed to initialize platform model, rc=%d", rc);
+ return rc;
+ }
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ mz = rte_memzone_reserve_aligned(nix_inl_dev_to_name(pci_dev, name),
+ sizeof(*inl_dev), SOCKET_ID_ANY, 0,
+ RTE_CACHE_LINE_SIZE);
+ if (mz == NULL)
+ return rc;
+
+ inl_dev = mz->addr;
+ inl_dev->pci_dev = pci_dev;
+
+ /* Parse devargs string */
+ rc = nix_inl_parse_devargs(pci_dev->device.devargs, inl_dev);
+ if (rc) {
+ plt_err("Failed to parse devargs rc=%d", rc);
+ goto free_mem;
+ }
+
+ rc = roc_nix_inl_dev_init(inl_dev);
+ if (rc) {
+ plt_err("Failed to init nix inl device, rc=%d(%s)", rc,
+ roc_error_msg_get(rc));
+ goto free_mem;
+ }
+
+ return 0;
+free_mem:
+ rte_memzone_free(mz);
+ return rc;
+}
+
+static const struct rte_pci_id cnxk_nix_inl_pci_map[] = {
+ {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_PF)},
+ {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_NIX_INL_VF)},
+ {
+ .vendor_id = 0,
+ },
+};
+
+static struct rte_pci_driver cnxk_nix_inl_pci = {
+ .id_table = cnxk_nix_inl_pci_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
+ .probe = cnxk_nix_inl_dev_probe,
+ .remove = cnxk_nix_inl_dev_remove,
+};
+
+RTE_PMD_REGISTER_PCI(cnxk_nix_inl, cnxk_nix_inl_pci);
+RTE_PMD_REGISTER_PCI_TABLE(cnxk_nix_inl, cnxk_nix_inl_pci_map);
+RTE_PMD_REGISTER_KMOD_DEP(cnxk_nix_inl, "vfio-pci");
+
+RTE_PMD_REGISTER_PARAM_STRING(cnxk_nix_inl,
+ CNXK_NIX_INL_SELFTEST "=1"
+ CNXK_NIX_INL_IPSEC_IN_MAX_SPI "=<1-65535>");
#include "cnxk_ethdev.h"
-/* NIX_RX_PARSE_S's ERRCODE + ERRLEV (12 bits) */
-#define ERRCODE_ERRLEN_WIDTH 12
-#define ERR_ARRAY_SZ ((BIT(ERRCODE_ERRLEN_WIDTH)) * sizeof(uint32_t))
-
-#define SA_TBL_SZ (RTE_MAX_ETHPORTS * sizeof(uint64_t))
-#define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_TBL_SZ)
+#define SA_BASE_TBL_SZ (RTE_MAX_ETHPORTS * sizeof(uintptr_t))
+#define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ)
const uint32_t *
cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
{
}
return NULL;
}
+
+int
+cnxk_nix_lookup_mem_sa_base_set(struct cnxk_eth_dev *dev)
+{
+ void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
+ uint16_t port = dev->eth_dev->data->port_id;
+ uintptr_t sa_base_tbl;
+ uintptr_t sa_base;
+ uint8_t sa_w;
+
+ if (!lookup_mem)
+ return -EIO;
+
+ sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
+ if (!sa_base)
+ return -ENOTSUP;
+
+ sa_w = plt_log2_u32(dev->nix.ipsec_in_max_spi + 1);
+
+ /* Set SA Base in lookup mem */
+ sa_base_tbl = (uintptr_t)lookup_mem;
+ sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
+ *((uintptr_t *)sa_base_tbl + port) = sa_base | sa_w;
+ return 0;
+}
+
+int
+cnxk_nix_lookup_mem_sa_base_clear(struct cnxk_eth_dev *dev)
+{
+ void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
+ uint16_t port = dev->eth_dev->data->port_id;
+ uintptr_t sa_base_tbl;
+
+ if (!lookup_mem)
+ return -EIO;
+
+ /* Set SA Base in lookup mem */
+ sa_base_tbl = (uintptr_t)lookup_mem;
+ sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
+ *((uintptr_t *)sa_base_tbl + port) = 0;
+ return 0;
+}
'cnxk_ethdev.c',
'cnxk_ethdev_devargs.c',
'cnxk_ethdev_ops.c',
+ 'cnxk_ethdev_sec.c',
'cnxk_link.c',
'cnxk_lookup.c',
'cnxk_ptp.c',
# CN9K
sources += files(
'cn9k_ethdev.c',
+ 'cn9k_ethdev_sec.c',
'cn9k_rte_flow.c',
'cn9k_rx.c',
'cn9k_rx_mseg.c',
DPDK_22 {
local: *;
};
+
+INTERNAL {
+ global:
+ cnxk_nix_inb_mode_set;
+};