* Copyright(c) 2010-2017 Intel Corporation
*/
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
#include <rte_ethdev_pci.h>
#include <rte_ip.h>
#include <rte_jhash.h>
ixgbe_crypto_clear_ipsec_tables(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct ixgbe_ipsec *priv = IXGBE_DEV_PRIVATE_TO_IPSEC(
+ dev->data->dev_private);
int i = 0;
/* clear Rx IP table*/
IXGBE_WRITE_REG(hw, IXGBE_IPSTXSALT, 0);
IXGBE_WAIT_TWRITE;
}
+
+ memset(priv->rx_ip_tbl, 0, sizeof(priv->rx_ip_tbl));
+ memset(priv->rx_sa_tbl, 0, sizeof(priv->rx_sa_tbl));
+ memset(priv->tx_sa_tbl, 0, sizeof(priv->tx_sa_tbl));
}
static int
if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION) {
int i, ip_index = -1;
+ uint8_t *key;
/* Find a match in the IP table*/
for (i = 0; i < IPSEC_MAX_RX_IP_COUNT; i++) {
priv->rx_sa_tbl[sa_index].spi =
rte_cpu_to_be_32(ic_session->spi);
priv->rx_sa_tbl[sa_index].ip_index = ip_index;
- priv->rx_sa_tbl[sa_index].key[3] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[0]);
- priv->rx_sa_tbl[sa_index].key[2] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[4]);
- priv->rx_sa_tbl[sa_index].key[1] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[8]);
- priv->rx_sa_tbl[sa_index].key[0] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[12]);
- priv->rx_sa_tbl[sa_index].salt =
- rte_cpu_to_be_32(ic_session->salt);
priv->rx_sa_tbl[sa_index].mode = IPSRXMOD_VALID;
if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION)
priv->rx_sa_tbl[sa_index].mode |=
(IPSRXMOD_PROTO | IPSRXMOD_DECRYPT);
- if (ic_session->dst_ip.type == IPv6)
+ if (ic_session->dst_ip.type == IPv6) {
priv->rx_sa_tbl[sa_index].mode |= IPSRXMOD_IPV6;
+ priv->rx_ip_tbl[ip_index].ip.type = IPv6;
+ } else if (ic_session->dst_ip.type == IPv4)
+ priv->rx_ip_tbl[ip_index].ip.type = IPv4;
+
priv->rx_sa_tbl[sa_index].used = 1;
/* write IP table entry*/
IXGBE_WAIT_RWRITE;
/* write Key table entry*/
+ key = malloc(ic_session->key_len);
+ if (!key)
+ return -ENOMEM;
+
+ memcpy(key, ic_session->key, ic_session->key_len);
+
reg_val = IPSRXIDX_RX_EN | IPSRXIDX_WRITE |
IPSRXIDX_TABLE_KEY | (sa_index << 3);
IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(0),
- priv->rx_sa_tbl[sa_index].key[0]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[12]));
IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(1),
- priv->rx_sa_tbl[sa_index].key[1]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[8]));
IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(2),
- priv->rx_sa_tbl[sa_index].key[2]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[4]));
IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(3),
- priv->rx_sa_tbl[sa_index].key[3]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[0]));
IXGBE_WRITE_REG(hw, IXGBE_IPSRXSALT,
- priv->rx_sa_tbl[sa_index].salt);
+ rte_cpu_to_be_32(ic_session->salt));
IXGBE_WRITE_REG(hw, IXGBE_IPSRXMOD,
priv->rx_sa_tbl[sa_index].mode);
IXGBE_WAIT_RWRITE;
+ free(key);
+
} else { /* sess->dir == RTE_CRYPTO_OUTBOUND */
+ uint8_t *key;
int i;
/* Find a free entry in the SA table*/
priv->tx_sa_tbl[sa_index].spi =
rte_cpu_to_be_32(ic_session->spi);
- priv->tx_sa_tbl[sa_index].key[3] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[0]);
- priv->tx_sa_tbl[sa_index].key[2] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[4]);
- priv->tx_sa_tbl[sa_index].key[1] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[8]);
- priv->tx_sa_tbl[sa_index].key[0] =
- rte_cpu_to_be_32(*(uint32_t *)&ic_session->key[12]);
- priv->tx_sa_tbl[sa_index].salt =
- rte_cpu_to_be_32(ic_session->salt);
+ priv->tx_sa_tbl[i].used = 1;
+ ic_session->sa_index = sa_index;
+
+ key = malloc(ic_session->key_len);
+ if (!key)
+ return -ENOMEM;
+
+ memcpy(key, ic_session->key, ic_session->key_len);
+ /* write Key table entry*/
reg_val = IPSRXIDX_RX_EN | IPSRXIDX_WRITE | (sa_index << 3);
IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(0),
- priv->tx_sa_tbl[sa_index].key[0]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[12]));
IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(1),
- priv->tx_sa_tbl[sa_index].key[1]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[8]));
IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(2),
- priv->tx_sa_tbl[sa_index].key[2]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[4]));
IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(3),
- priv->tx_sa_tbl[sa_index].key[3]);
+ rte_cpu_to_be_32(*(uint32_t *)&key[0]));
IXGBE_WRITE_REG(hw, IXGBE_IPSTXSALT,
- priv->tx_sa_tbl[sa_index].salt);
+ rte_cpu_to_be_32(ic_session->salt));
IXGBE_WAIT_TWRITE;
- priv->tx_sa_tbl[i].used = 1;
- ic_session->sa_index = sa_index;
+ free(key);
}
return 0;
conf->crypto_xform->aead.algo !=
RTE_CRYPTO_AEAD_AES_GCM) {
PMD_DRV_LOG(ERR, "Unsupported crypto transformation mode\n");
+ rte_mempool_put(mempool, (void *)ic_session);
return -ENOTSUP;
}
aead_xform = &conf->crypto_xform->aead;
ic_session->op = IXGBE_OP_AUTHENTICATED_DECRYPTION;
} else {
PMD_DRV_LOG(ERR, "IPsec decryption not enabled\n");
+ rte_mempool_put(mempool, (void *)ic_session);
return -ENOTSUP;
}
} else {
ic_session->op = IXGBE_OP_AUTHENTICATED_ENCRYPTION;
} else {
PMD_DRV_LOG(ERR, "IPsec encryption not enabled\n");
+ rte_mempool_put(mempool, (void *)ic_session);
return -ENOTSUP;
}
}
ic_session->key = aead_xform->key.data;
+ ic_session->key_len = aead_xform->key.length;
memcpy(&ic_session->salt,
&aead_xform->key.data[aead_xform->key.length], 4);
ic_session->spi = conf->ipsec.spi;
if (ic_session->op == IXGBE_OP_AUTHENTICATED_ENCRYPTION) {
if (ixgbe_crypto_add_sa(ic_session)) {
PMD_DRV_LOG(ERR, "Failed to add SA\n");
+ rte_mempool_put(mempool, (void *)ic_session);
return -EPERM;
}
}
return 0;
}
+static unsigned int
+ixgbe_crypto_session_get_size(__rte_unused void *device)
+{
+ return sizeof(struct ixgbe_crypto_session);
+}
+
static int
ixgbe_crypto_remove_session(void *device,
struct rte_security_session *session)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint32_t reg;
+ uint64_t rx_offloads;
+ uint64_t tx_offloads;
+
+ rx_offloads = dev->data->dev_conf.rxmode.offloads;
+ tx_offloads = dev->data->dev_conf.txmode.offloads;
/* sanity checks */
- if (dev->data->dev_conf.rxmode.enable_lro) {
+ if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO) {
PMD_DRV_LOG(ERR, "RSC and IPsec not supported");
return -1;
}
- if (!dev->data->dev_conf.rxmode.hw_strip_crc) {
+ if (rx_offloads & DEV_RX_OFFLOAD_KEEP_CRC) {
PMD_DRV_LOG(ERR, "HW CRC strip needs to be enabled for IPsec");
return -1;
}
reg |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg);
- if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_SECURITY) {
+ if (rx_offloads & DEV_RX_OFFLOAD_SECURITY) {
IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, 0);
reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
if (reg != 0) {
return -1;
}
}
- if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_SECURITY) {
+ if (tx_offloads & DEV_TX_OFFLOAD_SECURITY) {
IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL,
IXGBE_SECTXCTRL_STORE_FORWARD);
reg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
static struct rte_security_ops ixgbe_security_ops = {
.session_create = ixgbe_crypto_create_session,
.session_update = NULL,
+ .session_get_size = ixgbe_crypto_session_get_size,
.session_stats_get = NULL,
.session_destroy = ixgbe_crypto_remove_session,
.set_pkt_metadata = ixgbe_crypto_update_mb,
.capabilities_get = ixgbe_crypto_capabilities_get
};
-struct rte_security_ctx *
+static int
+ixgbe_crypto_capable(struct rte_eth_dev *dev)
+{
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t reg_i, reg, capable = 1;
+ /* test if rx crypto can be enabled and then write back initial value*/
+ reg_i = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, 0);
+ reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+ if (reg != 0)
+ capable = 0;
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, reg_i);
+ return capable;
+}
+
+int
ixgbe_ipsec_ctx_create(struct rte_eth_dev *dev)
{
- struct rte_security_ctx *ctx = rte_malloc("rte_security_instances_ops",
- sizeof(struct rte_security_ctx), 0);
- if (ctx) {
- ctx->device = (void *)dev;
- ctx->ops = &ixgbe_security_ops;
- ctx->sess_cnt = 0;
+ struct rte_security_ctx *ctx = NULL;
+
+ if (ixgbe_crypto_capable(dev)) {
+ ctx = rte_malloc("rte_security_instances_ops",
+ sizeof(struct rte_security_ctx), 0);
+ if (ctx) {
+ ctx->device = (void *)dev;
+ ctx->ops = &ixgbe_security_ops;
+ ctx->sess_cnt = 0;
+ dev->security_ctx = ctx;
+ } else {
+ return -ENOMEM;
+ }
}
- return ctx;
+ return 0;
}