ba66534fc7
Inline processing is limited to a specified subset of traffic. It is often unable to handle more complicated situations, such as fragmented traffic. When using inline processing such traffic is dropped. Introduce fallback session for inline crypto processing allowing handling packets that normally would be dropped. A fallback session is configured by adding 'fallback' keyword with 'lookaside-none' parameter to an SA configuration. Only 'inline-crypto-offload" as a primary session and 'lookaside-none' as a fall-back session combination is supported by this patch. Fallback session feature is not available in the legacy mode. Signed-off-by: Marcin Smoczynski <marcinx.smoczynski@intel.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com> Acked-by: Akhil Goyal <akhil.goyal@nxp.com> Tested-by: Bernard Iremonger <bernard.iremonger@intel.com>
382 lines
8.6 KiB
C
382 lines
8.6 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2016-2017 Intel Corporation
|
|
*/
|
|
|
|
#ifndef __IPSEC_H__
|
|
#define __IPSEC_H__
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <rte_byteorder.h>
|
|
#include <rte_crypto.h>
|
|
#include <rte_security.h>
|
|
#include <rte_flow.h>
|
|
#include <rte_ipsec.h>
|
|
|
|
#define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
|
|
#define RTE_LOGTYPE_IPSEC_ESP RTE_LOGTYPE_USER2
|
|
#define RTE_LOGTYPE_IPSEC_IPIP RTE_LOGTYPE_USER3
|
|
|
|
#define MAX_PKT_BURST 32
|
|
#define MAX_INFLIGHT 128
|
|
#define MAX_QP_PER_LCORE 256
|
|
|
|
#define MAX_DIGEST_SIZE 32 /* Bytes -- 256 bits */
|
|
|
|
#define IPSEC_OFFLOAD_ESN_SOFTLIMIT 0xffffff00
|
|
|
|
#define IV_OFFSET (sizeof(struct rte_crypto_op) + \
|
|
sizeof(struct rte_crypto_sym_op))
|
|
|
|
#define uint32_t_to_char(ip, a, b, c, d) do {\
|
|
*a = (uint8_t)(ip >> 24 & 0xff);\
|
|
*b = (uint8_t)(ip >> 16 & 0xff);\
|
|
*c = (uint8_t)(ip >> 8 & 0xff);\
|
|
*d = (uint8_t)(ip & 0xff);\
|
|
} while (0)
|
|
|
|
#define DEFAULT_MAX_CATEGORIES 1
|
|
|
|
#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
|
|
#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
|
|
#define INVALID_SPI (0)
|
|
|
|
#define DISCARD INVALID_SPI
|
|
#define BYPASS UINT32_MAX
|
|
|
|
#define IPSEC_XFORM_MAX 2
|
|
|
|
#define IP6_VERSION (6)
|
|
|
|
struct rte_crypto_xform;
|
|
struct ipsec_xform;
|
|
struct rte_mbuf;
|
|
|
|
struct ipsec_sa;
|
|
|
|
typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
|
|
struct rte_crypto_op *cop);
|
|
|
|
struct ip_addr {
|
|
union {
|
|
uint32_t ip4;
|
|
union {
|
|
uint64_t ip6[2];
|
|
uint8_t ip6_b[16];
|
|
} ip6;
|
|
} ip;
|
|
};
|
|
|
|
#define MAX_KEY_SIZE 32
|
|
|
|
/*
|
|
* application wide SA parameters
|
|
*/
|
|
struct app_sa_prm {
|
|
uint32_t enable; /* use librte_ipsec API for ipsec pkt processing */
|
|
uint32_t window_size; /* replay window size */
|
|
uint32_t enable_esn; /* enable/disable ESN support */
|
|
uint64_t flags; /* rte_ipsec_sa_prm.flags */
|
|
};
|
|
|
|
extern struct app_sa_prm app_sa_prm;
|
|
|
|
enum {
|
|
IPSEC_SESSION_PRIMARY = 0,
|
|
IPSEC_SESSION_FALLBACK = 1,
|
|
IPSEC_SESSION_MAX
|
|
};
|
|
|
|
#define IPSEC_SA_OFFLOAD_FALLBACK_FLAG (1)
|
|
|
|
static inline struct ipsec_sa *
|
|
ipsec_mask_saptr(void *ptr)
|
|
{
|
|
uintptr_t i = (uintptr_t)ptr;
|
|
static const uintptr_t mask = IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
|
|
|
|
i &= ~mask;
|
|
|
|
return (struct ipsec_sa *)i;
|
|
}
|
|
|
|
struct ipsec_sa {
|
|
struct rte_ipsec_session sessions[IPSEC_SESSION_MAX];
|
|
uint32_t spi;
|
|
uint32_t cdev_id_qp;
|
|
uint64_t seq;
|
|
uint32_t salt;
|
|
uint32_t fallback_sessions;
|
|
enum rte_crypto_cipher_algorithm cipher_algo;
|
|
enum rte_crypto_auth_algorithm auth_algo;
|
|
enum rte_crypto_aead_algorithm aead_algo;
|
|
uint16_t digest_len;
|
|
uint16_t iv_len;
|
|
uint16_t block_size;
|
|
uint16_t flags;
|
|
#define IP4_TUNNEL (1 << 0)
|
|
#define IP6_TUNNEL (1 << 1)
|
|
#define TRANSPORT (1 << 2)
|
|
#define IP4_TRANSPORT (1 << 3)
|
|
#define IP6_TRANSPORT (1 << 4)
|
|
struct ip_addr src;
|
|
struct ip_addr dst;
|
|
uint8_t cipher_key[MAX_KEY_SIZE];
|
|
uint16_t cipher_key_len;
|
|
uint8_t auth_key[MAX_KEY_SIZE];
|
|
uint16_t auth_key_len;
|
|
uint16_t aad_len;
|
|
union {
|
|
struct rte_crypto_sym_xform *xforms;
|
|
struct rte_security_ipsec_xform *sec_xform;
|
|
};
|
|
enum rte_security_ipsec_sa_direction direction;
|
|
uint16_t portid;
|
|
|
|
#define MAX_RTE_FLOW_PATTERN (4)
|
|
#define MAX_RTE_FLOW_ACTIONS (3)
|
|
struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
|
|
struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
|
|
struct rte_flow_attr attr;
|
|
union {
|
|
struct rte_flow_item_ipv4 ipv4_spec;
|
|
struct rte_flow_item_ipv6 ipv6_spec;
|
|
};
|
|
struct rte_flow_item_esp esp_spec;
|
|
struct rte_flow *flow;
|
|
struct rte_security_session_conf sess_conf;
|
|
} __rte_cache_aligned;
|
|
|
|
struct ipsec_mbuf_metadata {
|
|
struct ipsec_sa *sa;
|
|
struct rte_crypto_op cop;
|
|
struct rte_crypto_sym_op sym_cop;
|
|
uint8_t buf[32];
|
|
} __rte_cache_aligned;
|
|
|
|
#define IS_TRANSPORT(flags) ((flags) & TRANSPORT)
|
|
|
|
#define IS_TUNNEL(flags) ((flags) & (IP4_TUNNEL | IP6_TUNNEL))
|
|
|
|
#define IS_IP4(flags) ((flags) & (IP4_TUNNEL | IP4_TRANSPORT))
|
|
|
|
#define IS_IP6(flags) ((flags) & (IP6_TUNNEL | IP6_TRANSPORT))
|
|
|
|
#define IS_IP4_TUNNEL(flags) ((flags) & IP4_TUNNEL)
|
|
|
|
#define IS_IP6_TUNNEL(flags) ((flags) & IP6_TUNNEL)
|
|
|
|
/*
|
|
* Macro for getting ipsec_sa flags statuses without version of protocol
|
|
* used for transport (IP4_TRANSPORT and IP6_TRANSPORT flags).
|
|
*/
|
|
#define WITHOUT_TRANSPORT_VERSION(flags) \
|
|
((flags) & (IP4_TUNNEL | \
|
|
IP6_TUNNEL | \
|
|
TRANSPORT))
|
|
|
|
struct cdev_qp {
|
|
uint16_t id;
|
|
uint16_t qp;
|
|
uint16_t in_flight;
|
|
uint16_t len;
|
|
struct rte_crypto_op *buf[MAX_PKT_BURST] __rte_aligned(sizeof(void *));
|
|
};
|
|
|
|
struct ipsec_ctx {
|
|
struct rte_hash *cdev_map;
|
|
struct sp_ctx *sp4_ctx;
|
|
struct sp_ctx *sp6_ctx;
|
|
struct sa_ctx *sa_ctx;
|
|
uint16_t nb_qps;
|
|
uint16_t last_qp;
|
|
struct cdev_qp tbl[MAX_QP_PER_LCORE];
|
|
struct rte_mempool *session_pool;
|
|
struct rte_mempool *session_priv_pool;
|
|
struct rte_mbuf *ol_pkts[MAX_PKT_BURST] __rte_aligned(sizeof(void *));
|
|
uint16_t ol_pkts_cnt;
|
|
uint64_t ipv4_offloads;
|
|
uint64_t ipv6_offloads;
|
|
};
|
|
|
|
struct cdev_key {
|
|
uint16_t lcore_id;
|
|
uint8_t cipher_algo;
|
|
uint8_t auth_algo;
|
|
uint8_t aead_algo;
|
|
};
|
|
|
|
struct socket_ctx {
|
|
struct sa_ctx *sa_in;
|
|
struct sa_ctx *sa_out;
|
|
struct sp_ctx *sp_ip4_in;
|
|
struct sp_ctx *sp_ip4_out;
|
|
struct sp_ctx *sp_ip6_in;
|
|
struct sp_ctx *sp_ip6_out;
|
|
struct rt_ctx *rt_ip4;
|
|
struct rt_ctx *rt_ip6;
|
|
struct rte_mempool *mbuf_pool;
|
|
struct rte_mempool *mbuf_pool_indir;
|
|
struct rte_mempool *session_pool;
|
|
struct rte_mempool *session_priv_pool;
|
|
};
|
|
|
|
struct cnt_blk {
|
|
uint32_t salt;
|
|
uint64_t iv;
|
|
uint32_t cnt;
|
|
} __attribute__((packed));
|
|
|
|
struct traffic_type {
|
|
const uint8_t *data[MAX_PKT_BURST * 2];
|
|
struct rte_mbuf *pkts[MAX_PKT_BURST * 2];
|
|
void *saptr[MAX_PKT_BURST * 2];
|
|
uint32_t res[MAX_PKT_BURST * 2];
|
|
uint32_t num;
|
|
};
|
|
|
|
struct ipsec_traffic {
|
|
struct traffic_type ipsec;
|
|
struct traffic_type ip4;
|
|
struct traffic_type ip6;
|
|
};
|
|
|
|
uint16_t
|
|
ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
|
|
uint16_t nb_pkts, uint16_t len);
|
|
|
|
uint16_t
|
|
ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
|
|
uint32_t sa_idx[], uint16_t nb_pkts, uint16_t len);
|
|
|
|
uint16_t
|
|
ipsec_inbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
|
|
uint16_t len);
|
|
|
|
uint16_t
|
|
ipsec_outbound_cqp_dequeue(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
|
|
uint16_t len);
|
|
|
|
void
|
|
ipsec_process(struct ipsec_ctx *ctx, struct ipsec_traffic *trf);
|
|
|
|
void
|
|
ipsec_cqp_process(struct ipsec_ctx *ctx, struct ipsec_traffic *trf);
|
|
|
|
static inline uint16_t
|
|
ipsec_metadata_size(void)
|
|
{
|
|
return sizeof(struct ipsec_mbuf_metadata);
|
|
}
|
|
|
|
static inline struct ipsec_mbuf_metadata *
|
|
get_priv(struct rte_mbuf *m)
|
|
{
|
|
return rte_mbuf_to_priv(m);
|
|
}
|
|
|
|
static inline void *
|
|
get_cnt_blk(struct rte_mbuf *m)
|
|
{
|
|
struct ipsec_mbuf_metadata *priv = get_priv(m);
|
|
|
|
return &priv->buf[0];
|
|
}
|
|
|
|
static inline void *
|
|
get_aad(struct rte_mbuf *m)
|
|
{
|
|
struct ipsec_mbuf_metadata *priv = get_priv(m);
|
|
|
|
return &priv->buf[16];
|
|
}
|
|
|
|
static inline void *
|
|
get_sym_cop(struct rte_crypto_op *cop)
|
|
{
|
|
return (cop + 1);
|
|
}
|
|
|
|
static inline struct rte_ipsec_session *
|
|
ipsec_get_primary_session(struct ipsec_sa *sa)
|
|
{
|
|
return &sa->sessions[IPSEC_SESSION_PRIMARY];
|
|
}
|
|
|
|
static inline struct rte_ipsec_session *
|
|
ipsec_get_fallback_session(struct ipsec_sa *sa)
|
|
{
|
|
return &sa->sessions[IPSEC_SESSION_FALLBACK];
|
|
}
|
|
|
|
static inline enum rte_security_session_action_type
|
|
ipsec_get_action_type(struct ipsec_sa *sa)
|
|
{
|
|
struct rte_ipsec_session *ips;
|
|
ips = ipsec_get_primary_session(sa);
|
|
return ips->type;
|
|
}
|
|
|
|
int
|
|
inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx);
|
|
|
|
void
|
|
inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
|
|
void *sa[], uint16_t nb_pkts);
|
|
|
|
void
|
|
outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
|
|
void *sa[], uint16_t nb_pkts);
|
|
|
|
void
|
|
sp4_init(struct socket_ctx *ctx, int32_t socket_id);
|
|
|
|
void
|
|
sp6_init(struct socket_ctx *ctx, int32_t socket_id);
|
|
|
|
/*
|
|
* Search through SP rules for given SPI.
|
|
* Returns first rule index if found(greater or equal then zero),
|
|
* or -ENOENT otherwise.
|
|
*/
|
|
int
|
|
sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
|
|
uint32_t mask[2]);
|
|
int
|
|
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
|
|
uint32_t mask[2]);
|
|
|
|
/*
|
|
* Search through SA entries for given SPI.
|
|
* Returns first entry index if found(greater or equal then zero),
|
|
* or -ENOENT otherwise.
|
|
*/
|
|
int
|
|
sa_spi_present(uint32_t spi, int inbound);
|
|
|
|
void
|
|
sa_init(struct socket_ctx *ctx, int32_t socket_id);
|
|
|
|
void
|
|
rt_init(struct socket_ctx *ctx, int32_t socket_id);
|
|
|
|
int
|
|
sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
|
|
uint64_t *tx_offloads);
|
|
|
|
int
|
|
add_dst_ethaddr(uint16_t port, const struct rte_ether_addr *addr);
|
|
|
|
void
|
|
enqueue_cop_burst(struct cdev_qp *cqp);
|
|
|
|
int
|
|
create_lookaside_session(struct ipsec_ctx *ipsec_ctx, struct ipsec_sa *sa,
|
|
struct rte_ipsec_session *ips);
|
|
|
|
int
|
|
create_inline_session(struct socket_ctx *skt_ctx, struct ipsec_sa *sa,
|
|
struct rte_ipsec_session *ips);
|
|
|
|
#endif /* __IPSEC_H__ */
|