All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konstantin Ananyev <konstantin.ananyev@intel.com>
To: dev@dpdk.org
Cc: 0000-cover-letter.patch@dpdk.org,
	Konstantin Ananyev <konstantin.ananyev@intel.com>,
	Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Subject: [PATCH v4 04/10] lib: introduce ipsec library
Date: Fri, 14 Dec 2018 16:23:04 +0000	[thread overview]
Message-ID: <1544804589-10338-4-git-send-email-konstantin.ananyev@intel.com> (raw)
In-Reply-To: <1544110714-4514-2-git-send-email-konstantin.ananyev@intel.com>

Introduce librte_ipsec library.
The library is supposed to utilize existing DPDK crypto-dev and
security API to provide application with transparent IPsec processing API.
That initial commit provides some base API to manage
IPsec Security Association (SA) object.

Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Declan Doherty <declan.doherty@intel.com>
---
 MAINTAINERS                            |   5 +
 config/common_base                     |   5 +
 lib/Makefile                           |   2 +
 lib/librte_ipsec/Makefile              |  24 ++
 lib/librte_ipsec/ipsec_sqn.h           |  48 ++++
 lib/librte_ipsec/meson.build           |  10 +
 lib/librte_ipsec/rte_ipsec_sa.h        | 139 +++++++++++
 lib/librte_ipsec/rte_ipsec_version.map |  10 +
 lib/librte_ipsec/sa.c                  | 327 +++++++++++++++++++++++++
 lib/librte_ipsec/sa.h                  |  77 ++++++
 lib/meson.build                        |   2 +
 mk/rte.app.mk                          |   2 +
 12 files changed, 651 insertions(+)
 create mode 100644 lib/librte_ipsec/Makefile
 create mode 100644 lib/librte_ipsec/ipsec_sqn.h
 create mode 100644 lib/librte_ipsec/meson.build
 create mode 100644 lib/librte_ipsec/rte_ipsec_sa.h
 create mode 100644 lib/librte_ipsec/rte_ipsec_version.map
 create mode 100644 lib/librte_ipsec/sa.c
 create mode 100644 lib/librte_ipsec/sa.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 71ba31208..3cf0a84a2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1071,6 +1071,11 @@ F: doc/guides/prog_guide/pdump_lib.rst
 F: app/pdump/
 F: doc/guides/tools/pdump.rst
 
+IPsec - EXPERIMENTAL
+M: Konstantin Ananyev <konstantin.ananyev@intel.com>
+F: lib/librte_ipsec/
+M: Bernard Iremonger <bernard.iremonger@intel.com>
+F: test/test/test_ipsec.c
 
 Packet Framework
 ----------------
diff --git a/config/common_base b/config/common_base
index d12ae98bc..32499d772 100644
--- a/config/common_base
+++ b/config/common_base
@@ -925,6 +925,11 @@ CONFIG_RTE_LIBRTE_BPF=y
 # allow load BPF from ELF files (requires libelf)
 CONFIG_RTE_LIBRTE_BPF_ELF=n
 
+#
+# Compile librte_ipsec
+#
+CONFIG_RTE_LIBRTE_IPSEC=y
+
 #
 # Compile the test application
 #
diff --git a/lib/Makefile b/lib/Makefile
index b7370ef97..5dc774604 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -106,6 +106,8 @@ DEPDIRS-librte_gso := librte_eal librte_mbuf librte_ethdev librte_net
 DEPDIRS-librte_gso += librte_mempool
 DIRS-$(CONFIG_RTE_LIBRTE_BPF) += librte_bpf
 DEPDIRS-librte_bpf := librte_eal librte_mempool librte_mbuf librte_ethdev
+DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += librte_ipsec
+DEPDIRS-librte_ipsec := librte_eal librte_mbuf librte_cryptodev librte_security
 DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry
 DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev
 
diff --git a/lib/librte_ipsec/Makefile b/lib/librte_ipsec/Makefile
new file mode 100644
index 000000000..7758dcc6d
--- /dev/null
+++ b/lib/librte_ipsec/Makefile
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_ipsec.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+LDLIBS += -lrte_eal -lrte_mbuf -lrte_cryptodev -lrte_security
+
+EXPORT_MAP := rte_ipsec_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += sa.c
+
+# install header files
+SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_sa.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ipsec/ipsec_sqn.h b/lib/librte_ipsec/ipsec_sqn.h
new file mode 100644
index 000000000..1935f6e30
--- /dev/null
+++ b/lib/librte_ipsec/ipsec_sqn.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _IPSEC_SQN_H_
+#define _IPSEC_SQN_H_
+
+#define WINDOW_BUCKET_BITS		6 /* uint64_t */
+#define WINDOW_BUCKET_SIZE		(1 << WINDOW_BUCKET_BITS)
+#define WINDOW_BIT_LOC_MASK		(WINDOW_BUCKET_SIZE - 1)
+
+/* minimum number of bucket, power of 2*/
+#define WINDOW_BUCKET_MIN		2
+#define WINDOW_BUCKET_MAX		(INT16_MAX + 1)
+
+#define IS_ESN(sa)	((sa)->sqn_mask == UINT64_MAX)
+
+/*
+ * for given size, calculate required number of buckets.
+ */
+static uint32_t
+replay_num_bucket(uint32_t wsz)
+{
+	uint32_t nb;
+
+	nb = rte_align32pow2(RTE_ALIGN_MUL_CEIL(wsz, WINDOW_BUCKET_SIZE) /
+		WINDOW_BUCKET_SIZE);
+	nb = RTE_MAX(nb, (uint32_t)WINDOW_BUCKET_MIN);
+
+	return nb;
+}
+
+/**
+ * Based on number of buckets calculated required size for the
+ * structure that holds replay window and sequence number (RSN) information.
+ */
+static size_t
+rsn_size(uint32_t nb_bucket)
+{
+	size_t sz;
+	struct replay_sqn *rsn;
+
+	sz = sizeof(*rsn) + nb_bucket * sizeof(rsn->window[0]);
+	sz = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE);
+	return sz;
+}
+
+#endif /* _IPSEC_SQN_H_ */
diff --git a/lib/librte_ipsec/meson.build b/lib/librte_ipsec/meson.build
new file mode 100644
index 000000000..52c78eaeb
--- /dev/null
+++ b/lib/librte_ipsec/meson.build
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+allow_experimental_apis = true
+
+sources=files('sa.c')
+
+install_headers = files('rte_ipsec_sa.h')
+
+deps += ['mbuf', 'net', 'cryptodev', 'security']
diff --git a/lib/librte_ipsec/rte_ipsec_sa.h b/lib/librte_ipsec/rte_ipsec_sa.h
new file mode 100644
index 000000000..4e36fd99b
--- /dev/null
+++ b/lib/librte_ipsec/rte_ipsec_sa.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _RTE_IPSEC_SA_H_
+#define _RTE_IPSEC_SA_H_
+
+/**
+ * @file rte_ipsec_sa.h
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Defines API to manage IPsec Security Association (SA) objects.
+ */
+
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_security.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An opaque structure to represent Security Association (SA).
+ */
+struct rte_ipsec_sa;
+
+/**
+ * SA initialization parameters.
+ */
+struct rte_ipsec_sa_prm {
+
+	uint64_t userdata; /**< provided and interpreted by user */
+	uint64_t flags;  /**< see RTE_IPSEC_SAFLAG_* below */
+	/** ipsec configuration */
+	struct rte_security_ipsec_xform ipsec_xform;
+	struct rte_crypto_sym_xform *crypto_xform;
+	union {
+		struct {
+			uint8_t hdr_len;     /**< tunnel header len */
+			uint8_t hdr_l3_off;  /**< offset for IPv4/IPv6 header */
+			uint8_t next_proto;  /**< next header protocol */
+			const void *hdr;     /**< tunnel header template */
+		} tun; /**< tunnel mode repated parameters */
+		struct {
+			uint8_t proto;  /**< next header protocol */
+		} trs; /**< transport mode repated parameters */
+	};
+
+	uint32_t replay_win_sz;
+	/**< window size to enable sequence replay attack handling.
+	 * Replay checking is disabled if the window size is 0.
+	 */
+};
+
+/**
+ * SA type is an 64-bit value that contain the following information:
+ * - IP version (IPv4/IPv6)
+ * - IPsec proto (ESP/AH)
+ * - inbound/outbound
+ * - mode (TRANSPORT/TUNNEL)
+ * - for TUNNEL outer IP version (IPv4/IPv6)
+ * ...
+ */
+
+enum {
+	RTE_SATP_LOG_IPV,
+	RTE_SATP_LOG_PROTO,
+	RTE_SATP_LOG_DIR,
+	RTE_SATP_LOG_MODE,
+	RTE_SATP_LOG_NUM
+};
+
+#define RTE_IPSEC_SATP_IPV_MASK		(1ULL << RTE_SATP_LOG_IPV)
+#define RTE_IPSEC_SATP_IPV4		(0ULL << RTE_SATP_LOG_IPV)
+#define RTE_IPSEC_SATP_IPV6		(1ULL << RTE_SATP_LOG_IPV)
+
+#define RTE_IPSEC_SATP_PROTO_MASK	(1ULL << RTE_SATP_LOG_PROTO)
+#define RTE_IPSEC_SATP_PROTO_AH		(0ULL << RTE_SATP_LOG_PROTO)
+#define RTE_IPSEC_SATP_PROTO_ESP	(1ULL << RTE_SATP_LOG_PROTO)
+
+#define RTE_IPSEC_SATP_DIR_MASK		(1ULL << RTE_SATP_LOG_DIR)
+#define RTE_IPSEC_SATP_DIR_IB		(0ULL << RTE_SATP_LOG_DIR)
+#define RTE_IPSEC_SATP_DIR_OB		(1ULL << RTE_SATP_LOG_DIR)
+
+#define RTE_IPSEC_SATP_MODE_MASK	(3ULL << RTE_SATP_LOG_MODE)
+#define RTE_IPSEC_SATP_MODE_TRANS	(0ULL << RTE_SATP_LOG_MODE)
+#define RTE_IPSEC_SATP_MODE_TUNLV4	(1ULL << RTE_SATP_LOG_MODE)
+#define RTE_IPSEC_SATP_MODE_TUNLV6	(2ULL << RTE_SATP_LOG_MODE)
+
+/**
+ * get type of given SA
+ * @return
+ *   SA type value.
+ */
+uint64_t __rte_experimental
+rte_ipsec_sa_type(const struct rte_ipsec_sa *sa);
+
+/**
+ * Calculate requied SA size based on provided input parameters.
+ * @param prm
+ *   Parameters that wil be used to initialise SA object.
+ * @return
+ *   - Actual size required for SA with given parameters.
+ *   - -EINVAL if the parameters are invalid.
+ */
+int __rte_experimental
+rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm);
+
+/**
+ * initialise SA based on provided input parameters.
+ * @param sa
+ *   SA object to initialise.
+ * @param prm
+ *   Parameters used to initialise given SA object.
+ * @param size
+ *   size of the provided buffer for SA.
+ * @return
+ *   - Actual size of SA object if operation completed successfully.
+ *   - -EINVAL if the parameters are invalid.
+ *   - -ENOSPC if the size of the provided buffer is not big enough.
+ */
+int __rte_experimental
+rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
+	uint32_t size);
+
+/**
+ * cleanup SA
+ * @param sa
+ *   Pointer to SA object to de-initialize.
+ */
+void __rte_experimental
+rte_ipsec_sa_fini(struct rte_ipsec_sa *sa);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_IPSEC_SA_H_ */
diff --git a/lib/librte_ipsec/rte_ipsec_version.map b/lib/librte_ipsec/rte_ipsec_version.map
new file mode 100644
index 000000000..1a66726b8
--- /dev/null
+++ b/lib/librte_ipsec/rte_ipsec_version.map
@@ -0,0 +1,10 @@
+EXPERIMENTAL {
+	global:
+
+	rte_ipsec_sa_fini;
+	rte_ipsec_sa_init;
+	rte_ipsec_sa_size;
+	rte_ipsec_sa_type;
+
+	local: *;
+};
diff --git a/lib/librte_ipsec/sa.c b/lib/librte_ipsec/sa.c
new file mode 100644
index 000000000..f927a82bf
--- /dev/null
+++ b/lib/librte_ipsec/sa.c
@@ -0,0 +1,327 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <rte_ipsec_sa.h>
+#include <rte_esp.h>
+#include <rte_ip.h>
+#include <rte_errno.h>
+
+#include "sa.h"
+#include "ipsec_sqn.h"
+
+/* some helper structures */
+struct crypto_xform {
+	struct rte_crypto_auth_xform *auth;
+	struct rte_crypto_cipher_xform *cipher;
+	struct rte_crypto_aead_xform *aead;
+};
+
+
+static int
+check_crypto_xform(struct crypto_xform *xform)
+{
+	uintptr_t p;
+
+	p = (uintptr_t)xform->auth | (uintptr_t)xform->cipher;
+
+	/* either aead or both auth and cipher should be not NULLs */
+	if (xform->aead) {
+		if (p)
+			return -EINVAL;
+	} else if (p == (uintptr_t)xform->auth) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+fill_crypto_xform(struct crypto_xform *xform,
+	const struct rte_ipsec_sa_prm *prm)
+{
+	struct rte_crypto_sym_xform *xf;
+
+	memset(xform, 0, sizeof(*xform));
+
+	for (xf = prm->crypto_xform; xf != NULL; xf = xf->next) {
+		if (xf->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+			if (xform->auth != NULL)
+				return -EINVAL;
+			xform->auth = &xf->auth;
+		} else if (xf->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+			if (xform->cipher != NULL)
+				return -EINVAL;
+			xform->cipher = &xf->cipher;
+		} else if (xf->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+			if (xform->aead != NULL)
+				return -EINVAL;
+			xform->aead = &xf->aead;
+		} else
+			return -EINVAL;
+	}
+
+	return check_crypto_xform(xform);
+}
+
+uint64_t __rte_experimental
+rte_ipsec_sa_type(const struct rte_ipsec_sa *sa)
+{
+	return sa->type;
+}
+
+static int32_t
+ipsec_sa_size(uint32_t wsz, uint64_t type, uint32_t *nb_bucket)
+{
+	uint32_t n, sz;
+
+	n = 0;
+	if (wsz != 0 && (type & RTE_IPSEC_SATP_DIR_MASK) ==
+			RTE_IPSEC_SATP_DIR_IB)
+		n = replay_num_bucket(wsz);
+
+	if (n > WINDOW_BUCKET_MAX)
+		return -EINVAL;
+
+	*nb_bucket = n;
+
+	sz = rsn_size(n);
+	sz += sizeof(struct rte_ipsec_sa);
+	return sz;
+}
+
+void __rte_experimental
+rte_ipsec_sa_fini(struct rte_ipsec_sa *sa)
+{
+	memset(sa, 0, sa->size);
+}
+
+static int
+fill_sa_type(const struct rte_ipsec_sa_prm *prm, uint64_t *type)
+{
+	uint64_t tp;
+
+	tp = 0;
+
+	if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
+		tp |= RTE_IPSEC_SATP_PROTO_AH;
+	else if (prm->ipsec_xform.proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
+		tp |= RTE_IPSEC_SATP_PROTO_ESP;
+	else
+		return -EINVAL;
+
+	if (prm->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		tp |= RTE_IPSEC_SATP_DIR_OB;
+	else if (prm->ipsec_xform.direction ==
+			RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+		tp |= RTE_IPSEC_SATP_DIR_IB;
+	else
+		return -EINVAL;
+
+	if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
+		if (prm->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV4)
+			tp |= RTE_IPSEC_SATP_MODE_TUNLV4;
+		else if (prm->ipsec_xform.tunnel.type ==
+				RTE_SECURITY_IPSEC_TUNNEL_IPV6)
+			tp |= RTE_IPSEC_SATP_MODE_TUNLV6;
+		else
+			return -EINVAL;
+
+		if (prm->tun.next_proto == IPPROTO_IPIP)
+			tp |= RTE_IPSEC_SATP_IPV4;
+		else if (prm->tun.next_proto == IPPROTO_IPV6)
+			tp |= RTE_IPSEC_SATP_IPV6;
+		else
+			return -EINVAL;
+	} else if (prm->ipsec_xform.mode ==
+			RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
+		tp |= RTE_IPSEC_SATP_MODE_TRANS;
+		if (prm->trs.proto == IPPROTO_IPIP)
+			tp |= RTE_IPSEC_SATP_IPV4;
+		else if (prm->trs.proto == IPPROTO_IPV6)
+			tp |= RTE_IPSEC_SATP_IPV6;
+		else
+			return -EINVAL;
+	} else
+		return -EINVAL;
+
+	*type = tp;
+	return 0;
+}
+
+static void
+esp_inb_init(struct rte_ipsec_sa *sa)
+{
+	/* these params may differ with new algorithms support */
+	sa->ctp.auth.offset = 0;
+	sa->ctp.auth.length = sa->icv_len - sa->sqh_len;
+	sa->ctp.cipher.offset = sizeof(struct esp_hdr) + sa->iv_len;
+	sa->ctp.cipher.length = sa->icv_len + sa->ctp.cipher.offset;
+}
+
+static void
+esp_inb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
+{
+	sa->proto = prm->tun.next_proto;
+	esp_inb_init(sa);
+}
+
+static void
+esp_outb_init(struct rte_ipsec_sa *sa, uint32_t hlen)
+{
+	sa->sqn.outb = 1;
+
+	/* these params may differ with new algorithms support */
+	sa->ctp.auth.offset = hlen;
+	sa->ctp.auth.length = sizeof(struct esp_hdr) + sa->iv_len + sa->sqh_len;
+	if (sa->aad_len != 0) {
+		sa->ctp.cipher.offset = hlen + sizeof(struct esp_hdr) +
+			sa->iv_len;
+		sa->ctp.cipher.length = 0;
+	} else {
+		sa->ctp.cipher.offset = sa->hdr_len + sizeof(struct esp_hdr);
+		sa->ctp.cipher.length = sa->iv_len;
+	}
+}
+
+static void
+esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm)
+{
+	sa->proto = prm->tun.next_proto;
+	sa->hdr_len = prm->tun.hdr_len;
+	sa->hdr_l3_off = prm->tun.hdr_l3_off;
+	memcpy(sa->hdr, prm->tun.hdr, sa->hdr_len);
+
+	esp_outb_init(sa, sa->hdr_len);
+}
+
+static int
+esp_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
+	const struct crypto_xform *cxf)
+{
+	static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
+				RTE_IPSEC_SATP_MODE_MASK;
+
+	if (cxf->aead != NULL) {
+		/* RFC 4106 */
+		if (cxf->aead->algo != RTE_CRYPTO_AEAD_AES_GCM)
+			return -EINVAL;
+		sa->icv_len = cxf->aead->digest_length;
+		sa->iv_ofs = cxf->aead->iv.offset;
+		sa->iv_len = sizeof(uint64_t);
+		sa->pad_align = 4;
+	} else {
+		sa->icv_len = cxf->auth->digest_length;
+		sa->iv_ofs = cxf->cipher->iv.offset;
+		sa->sqh_len = IS_ESN(sa) ? sizeof(uint32_t) : 0;
+		if (cxf->cipher->algo == RTE_CRYPTO_CIPHER_NULL) {
+			sa->pad_align = 4;
+			sa->iv_len = 0;
+		} else if (cxf->cipher->algo == RTE_CRYPTO_CIPHER_AES_CBC) {
+			sa->pad_align = IPSEC_MAX_IV_SIZE;
+			sa->iv_len = IPSEC_MAX_IV_SIZE;
+		} else
+			return -EINVAL;
+	}
+
+	sa->udata = prm->userdata;
+	sa->spi = rte_cpu_to_be_32(prm->ipsec_xform.spi);
+	sa->salt = prm->ipsec_xform.salt;
+
+	switch (sa->type & msk) {
+	case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV4):
+	case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TUNLV6):
+		esp_inb_tun_init(sa, prm);
+		break;
+	case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
+		esp_inb_init(sa);
+		break;
+	case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
+	case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
+		esp_outb_tun_init(sa, prm);
+		break;
+	case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
+		esp_outb_init(sa, 0);
+		break;
+	}
+
+	return 0;
+}
+
+int __rte_experimental
+rte_ipsec_sa_size(const struct rte_ipsec_sa_prm *prm)
+{
+	uint64_t type;
+	uint32_t nb;
+	int32_t rc;
+
+	if (prm == NULL)
+		return -EINVAL;
+
+	/* determine SA type */
+	rc = fill_sa_type(prm, &type);
+	if (rc != 0)
+		return rc;
+
+	/* determine required size */
+	return ipsec_sa_size(prm->replay_win_sz, type, &nb);
+}
+
+int __rte_experimental
+rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm,
+	uint32_t size)
+{
+	int32_t rc, sz;
+	uint32_t nb;
+	uint64_t type;
+	struct crypto_xform cxf;
+
+	if (sa == NULL || prm == NULL)
+		return -EINVAL;
+
+	/* determine SA type */
+	rc = fill_sa_type(prm, &type);
+	if (rc != 0)
+		return rc;
+
+	/* determine required size */
+	sz = ipsec_sa_size(prm->replay_win_sz, type, &nb);
+	if (sz < 0)
+		return sz;
+	else if (size < (uint32_t)sz)
+		return -ENOSPC;
+
+	/* only esp is supported right now */
+	if (prm->ipsec_xform.proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP)
+		return -EINVAL;
+
+	if (prm->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL &&
+			prm->tun.hdr_len > sizeof(sa->hdr))
+		return -EINVAL;
+
+	rc = fill_crypto_xform(&cxf, prm);
+	if (rc != 0)
+		return rc;
+
+	sa->type = type;
+	sa->size = sz;
+
+	/* check for ESN flag */
+	sa->sqn_mask = (prm->ipsec_xform.options.esn == 0) ?
+		UINT32_MAX : UINT64_MAX;
+
+	rc = esp_sa_init(sa, prm, &cxf);
+	if (rc != 0)
+		rte_ipsec_sa_fini(sa);
+
+	/* fill replay window related fields */
+	if (nb != 0) {
+		sa->replay.win_sz = prm->replay_win_sz;
+		sa->replay.nb_bucket = nb;
+		sa->replay.bucket_index_mask = sa->replay.nb_bucket - 1;
+		sa->sqn.inb = (struct replay_sqn *)(sa + 1);
+	}
+
+	return sz;
+}
diff --git a/lib/librte_ipsec/sa.h b/lib/librte_ipsec/sa.h
new file mode 100644
index 000000000..5d113891a
--- /dev/null
+++ b/lib/librte_ipsec/sa.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _SA_H_
+#define _SA_H_
+
+#define IPSEC_MAX_HDR_SIZE	64
+#define IPSEC_MAX_IV_SIZE	16
+#define IPSEC_MAX_IV_QWORD	(IPSEC_MAX_IV_SIZE / sizeof(uint64_t))
+
+/* these definitions probably has to be in rte_crypto_sym.h */
+union sym_op_ofslen {
+	uint64_t raw;
+	struct {
+		uint32_t offset;
+		uint32_t length;
+	};
+};
+
+union sym_op_data {
+#ifdef __SIZEOF_INT128__
+	__uint128_t raw;
+#endif
+	struct {
+		uint8_t *va;
+		rte_iova_t pa;
+	};
+};
+
+struct replay_sqn {
+	uint64_t sqn;
+	__extension__ uint64_t window[0];
+};
+
+struct rte_ipsec_sa {
+	uint64_t type;     /* type of given SA */
+	uint64_t udata;    /* user defined */
+	uint32_t size;     /* size of given sa object */
+	uint32_t spi;
+	/* sqn calculations related */
+	uint64_t sqn_mask;
+	struct {
+		uint32_t win_sz;
+		uint16_t nb_bucket;
+		uint16_t bucket_index_mask;
+	} replay;
+	/* template for crypto op fields */
+	struct {
+		union sym_op_ofslen cipher;
+		union sym_op_ofslen auth;
+	} ctp;
+	uint32_t salt;
+	uint8_t proto;    /* next proto */
+	uint8_t aad_len;
+	uint8_t hdr_len;
+	uint8_t hdr_l3_off;
+	uint8_t icv_len;
+	uint8_t sqh_len;
+	uint8_t iv_ofs; /* offset for algo-specific IV inside crypto op */
+	uint8_t iv_len;
+	uint8_t pad_align;
+
+	/* template for tunnel header */
+	uint8_t hdr[IPSEC_MAX_HDR_SIZE];
+
+	/*
+	 * sqn and replay window
+	 */
+	union {
+		uint64_t outb;
+		struct replay_sqn *inb;
+	} sqn;
+
+} __rte_cache_aligned;
+
+#endif /* _SA_H_ */
diff --git a/lib/meson.build b/lib/meson.build
index bb7f443f9..69684ef14 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -22,6 +22,8 @@ libraries = [ 'compat', # just a header, used for versioning
 	'kni', 'latencystats', 'lpm', 'member',
 	'meter', 'power', 'pdump', 'rawdev',
 	'reorder', 'sched', 'security', 'vhost',
+	#ipsec lib depends on crypto and security
+	'ipsec',
 	# add pkt framework libs which use other libs from above
 	'port', 'table', 'pipeline',
 	# flow_classify lib depends on pkt framework table lib
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 5699d979d..f4cd75252 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -67,6 +67,8 @@ ifeq ($(CONFIG_RTE_LIBRTE_BPF_ELF),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_BPF)            += -lelf
 endif
 
+_LDLIBS-$(CONFIG_RTE_LIBRTE_IPSEC)            += -lrte_ipsec
+
 _LDLIBS-y += --whole-archive
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE)        += -lrte_cfgfile
-- 
2.17.1

  parent reply	other threads:[~2018-12-14 16:23 UTC|newest]

Thread overview: 194+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-24 16:53 [RFC] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-09-03 12:41 ` Joseph, Anoob
2018-09-03 18:21   ` Ananyev, Konstantin
2018-09-05 14:39     ` Joseph, Anoob
     [not found]       ` <2601191342CEEE43887BDE71AB977258EA954BAD@irsmsx105.ger.corp.intel.com>
2018-09-12 18:09         ` Ananyev, Konstantin
2018-09-15 17:06           ` Joseph, Anoob
2018-09-16 10:56             ` Jerin Jacob
2018-09-17 18:12               ` Ananyev, Konstantin
2018-09-18 12:42                 ` Ananyev, Konstantin
2018-09-20 14:26                   ` Akhil Goyal
2018-09-24 10:51                     ` Ananyev, Konstantin
2018-09-25  7:48                       ` Akhil Goyal
2018-09-30 21:00                         ` Ananyev, Konstantin
2018-10-01 12:49                           ` Akhil Goyal
2018-10-02 23:24                             ` Ananyev, Konstantin
2018-09-18 17:54                 ` Jerin Jacob
2018-09-24  8:45                   ` Ananyev, Konstantin
2018-09-26 18:02                     ` Jerin Jacob
2018-10-02 23:56                       ` Ananyev, Konstantin
2018-10-03  9:37                         ` Jerin Jacob
2018-10-09 18:24                           ` Ananyev, Konstantin
2018-09-17 10:36             ` Ananyev, Konstantin
2018-09-17 14:41               ` Joseph, Anoob
2018-10-09 18:23 ` [RFC v2 0/9] " Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 1/9] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 2/9] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 3/9] net: add ESP trailer structure definition Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 4/9] lib: introduce ipsec library Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 5/9] ipsec: add SA data-path API Konstantin Ananyev
2018-10-18 17:37   ` Jerin Jacob
2018-10-21 22:01     ` Ananyev, Konstantin
2018-10-24 12:03       ` Jerin Jacob
2018-10-28 20:37         ` Ananyev, Konstantin
2018-10-29 10:19           ` Jerin Jacob
2018-10-30 13:53             ` Ananyev, Konstantin
2018-10-31  6:37               ` Jerin Jacob
2018-10-09 18:23 ` [RFC v2 6/9] ipsec: implement " Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 7/9] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 8/9] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-10-09 18:23 ` [RFC v2 9/9] test/ipsec: introduce functional test Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 0/9] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 1/9] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2018-11-16 10:23   ` Mohammad Abdul Awal
2018-11-30 16:45   ` [PATCH v2 0/9] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-11-30 16:45   ` [PATCH v2 1/9] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2018-12-04 13:13     ` Mohammad Abdul Awal
2018-12-04 15:32       ` Trahe, Fiona
2018-12-06 15:38     ` [PATCH v3 0/9] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-12-06 15:38     ` [PATCH v3 1/9] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2018-12-11 17:24       ` Doherty, Declan
2018-12-14 16:23       ` [PATCH v4 01/10] " Konstantin Ananyev
2018-12-19  9:26         ` Akhil Goyal
2018-12-28 15:17         ` [PATCH v5 00/10] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 01/10] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 00/10] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2019-01-11  1:09             ` Xu, Yanjie
2019-01-03 20:16           ` [PATCH v6 01/10] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2019-01-04  0:25             ` Stephen Hemminger
2019-01-04  9:29               ` Ananyev, Konstantin
2019-01-09 23:41                 ` Thomas Monjalon
2019-01-10 14:20             ` [PATCH v7 00/10] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2019-01-10 14:25               ` Thomas Monjalon
2019-01-10 14:40                 ` De Lara Guarch, Pablo
2019-01-10 14:52                 ` Ananyev, Konstantin
2019-01-10 14:54                   ` Thomas Monjalon
2019-01-10 14:58                     ` Ananyev, Konstantin
2019-01-10 15:00                       ` Akhil Goyal
2019-01-10 15:09                         ` Akhil Goyal
2019-01-10 14:51               ` Akhil Goyal
2019-01-10 14:20             ` [PATCH v7 01/10] cryptodev: add opaque userdata pointer into crypto sym session Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 0/9] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2019-01-10 23:59                 ` De Lara Guarch, Pablo
2019-01-10 21:06               ` [PATCH v8 1/9] security: add opaque userdata pointer into security session Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 2/9] net: add ESP trailer structure definition Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 3/9] lib: introduce ipsec library Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 4/9] ipsec: add SA data-path API Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 5/9] ipsec: implement " Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 6/9] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 7/9] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 8/9] test/ipsec: introduce functional test Konstantin Ananyev
2019-01-10 21:06               ` [PATCH v8 9/9] doc: add IPsec library guide Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 02/10] security: add opaque userdata pointer into security session Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 03/10] net: add ESP trailer structure definition Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 04/10] lib: introduce ipsec library Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 05/10] ipsec: add SA data-path API Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 06/10] ipsec: implement " Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 07/10] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 08/10] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 09/10] test/ipsec: introduce functional test Konstantin Ananyev
2019-01-10 14:20             ` [PATCH v7 10/10] doc: add IPsec library guide Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 02/10] security: add opaque userdata pointer into security session Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 03/10] net: add ESP trailer structure definition Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 04/10] lib: introduce ipsec library Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 05/10] ipsec: add SA data-path API Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 06/10] ipsec: implement " Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 07/10] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 08/10] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 09/10] test/ipsec: introduce functional test Konstantin Ananyev
2019-01-03 20:16           ` [PATCH v6 10/10] doc: add IPsec library guide Konstantin Ananyev
2019-01-10  8:35             ` Thomas Monjalon
2018-12-28 15:17         ` [PATCH v5 02/10] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 03/10] net: add ESP trailer structure definition Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 04/10] lib: introduce ipsec library Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 05/10] ipsec: add SA data-path API Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 06/10] ipsec: implement " Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 07/10] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 08/10] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 09/10] test/ipsec: introduce functional test Konstantin Ananyev
2018-12-28 15:17         ` [PATCH v5 10/10] doc: add IPsec library guide Konstantin Ananyev
2018-12-14 16:23       ` [PATCH v4 02/10] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-12-19  9:26         ` Akhil Goyal
2018-12-14 16:23       ` [PATCH v4 03/10] net: add ESP trailer structure definition Konstantin Ananyev
2018-12-19  9:32         ` Akhil Goyal
2018-12-27 10:13           ` Olivier Matz
2018-12-14 16:23       ` Konstantin Ananyev [this message]
2018-12-19 12:08         ` [PATCH v4 04/10] lib: introduce ipsec library Akhil Goyal
2018-12-19 12:39           ` Thomas Monjalon
2018-12-20 14:06           ` Ananyev, Konstantin
2018-12-20 14:14             ` Thomas Monjalon
2018-12-20 14:26               ` Ananyev, Konstantin
2018-12-20 18:17             ` Ananyev, Konstantin
2018-12-21 11:57               ` Akhil Goyal
2018-12-21 11:53             ` Akhil Goyal
2018-12-21 12:41               ` Ananyev, Konstantin
2018-12-21 12:54                 ` Ananyev, Konstantin
2018-12-14 16:23       ` [PATCH v4 05/10] ipsec: add SA data-path API Konstantin Ananyev
2018-12-19 13:04         ` Akhil Goyal
2018-12-20 10:17           ` Ananyev, Konstantin
2018-12-21 12:14             ` Akhil Goyal
2018-12-14 16:23       ` [PATCH v4 06/10] ipsec: implement " Konstantin Ananyev
2018-12-19 15:32         ` Akhil Goyal
2018-12-20 12:56           ` Ananyev, Konstantin
2018-12-21 12:36             ` Akhil Goyal
2018-12-21 14:27               ` Ananyev, Konstantin
2018-12-21 14:39                 ` Thomas Monjalon
2018-12-21 14:51                 ` Akhil Goyal
2018-12-21 15:16                   ` Ananyev, Konstantin
2018-12-14 16:23       ` [PATCH v4 07/10] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-12-14 16:23       ` [PATCH v4 08/10] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-12-19 15:46         ` Akhil Goyal
2018-12-20 13:00           ` Ananyev, Konstantin
2018-12-21 12:37             ` Akhil Goyal
2018-12-14 16:23       ` [PATCH v4 09/10] test/ipsec: introduce functional test Konstantin Ananyev
2018-12-19 15:53         ` Akhil Goyal
2018-12-20 13:03           ` Ananyev, Konstantin
2018-12-21 12:41             ` Akhil Goyal
2018-12-14 16:27       ` [PATCH v4 10/10] doc: add IPsec library guide Konstantin Ananyev
2018-12-19  3:46         ` Thomas Monjalon
2018-12-19 16:01         ` Akhil Goyal
2018-12-20 13:06           ` Ananyev, Konstantin
2018-12-21 12:58             ` Akhil Goyal
2018-12-14 16:29       ` [PATCH v4 00/10] ipsec: new library for IPsec data-path processing Konstantin Ananyev
2018-12-21 13:32         ` Akhil Goyal
2018-12-06 15:38     ` [PATCH v3 2/9] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-12-11 17:25       ` Doherty, Declan
2018-12-06 15:38     ` [PATCH v3 3/9] net: add ESP trailer structure definition Konstantin Ananyev
2018-12-11 17:25       ` Doherty, Declan
2018-12-06 15:38     ` [PATCH v3 4/9] lib: introduce ipsec library Konstantin Ananyev
2018-12-11 17:25       ` Doherty, Declan
2018-12-06 15:38     ` [PATCH v3 5/9] ipsec: add SA data-path API Konstantin Ananyev
2018-12-11 17:25       ` Doherty, Declan
2018-12-12  7:37         ` Ananyev, Konstantin
2018-12-06 15:38     ` [PATCH v3 6/9] ipsec: implement " Konstantin Ananyev
2018-12-12 17:47       ` Doherty, Declan
2018-12-13 11:21         ` Ananyev, Konstantin
2018-12-06 15:38     ` [PATCH v3 7/9] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-12-13 12:14       ` Doherty, Declan
2018-12-06 15:38     ` [PATCH v3 8/9] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-12-13 12:14       ` Doherty, Declan
2018-12-06 15:38     ` [PATCH v3 9/9] test/ipsec: introduce functional test Konstantin Ananyev
2018-12-13 12:54       ` Doherty, Declan
2018-11-30 16:45   ` [PATCH v2 2/9] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-12-04 13:13     ` Mohammad Abdul Awal
2018-11-30 16:46   ` [PATCH v2 3/9] net: add ESP trailer structure definition Konstantin Ananyev
2018-12-04 13:12     ` Mohammad Abdul Awal
2018-11-30 16:46   ` [PATCH v2 4/9] lib: introduce ipsec library Konstantin Ananyev
2018-11-30 16:46   ` [PATCH v2 5/9] ipsec: add SA data-path API Konstantin Ananyev
2018-11-30 16:46   ` [PATCH v2 6/9] ipsec: implement " Konstantin Ananyev
2018-11-30 16:46   ` [PATCH v2 7/9] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-11-30 16:46   ` [PATCH v2 8/9] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-11-30 16:46   ` [PATCH v2 9/9] test/ipsec: introduce functional test Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 2/9] security: add opaque userdata pointer into security session Konstantin Ananyev
2018-11-16 10:24   ` Mohammad Abdul Awal
2018-11-15 23:53 ` [PATCH 3/9] net: add ESP trailer structure definition Konstantin Ananyev
2018-11-16 10:22   ` Mohammad Abdul Awal
2018-11-15 23:53 ` [PATCH 4/9] lib: introduce ipsec library Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 5/9] ipsec: add SA data-path API Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 6/9] ipsec: implement " Konstantin Ananyev
2018-11-20  1:03   ` Zhang, Qi Z
2018-11-20  9:44     ` Ananyev, Konstantin
2018-11-20 10:02       ` Ananyev, Konstantin
2018-11-15 23:53 ` [PATCH 7/9] ipsec: rework SA replay window/SQN for MT environment Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 8/9] ipsec: helper functions to group completed crypto-ops Konstantin Ananyev
2018-11-15 23:53 ` [PATCH 9/9] test/ipsec: introduce functional test Konstantin Ananyev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1544804589-10338-4-git-send-email-konstantin.ananyev@intel.com \
    --to=konstantin.ananyev@intel.com \
    --cc=0000-cover-letter.patch@dpdk.org \
    --cc=dev@dpdk.org \
    --cc=mohammad.abdul.awal@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.