All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jasvinder Singh <jasvinder.singh@intel.com>
To: dev@dpdk.org
Cc: cristian.dumitrescu@intel.com, bernard.iremonger@intel.com
Subject: [PATCH v3 07/23] net/softnic: add port action profile
Date: Wed, 27 Jun 2018 17:31:07 +0100	[thread overview]
Message-ID: <20180627163123.135686-8-jasvinder.singh@intel.com> (raw)
In-Reply-To: <20180627163123.135686-1-jasvinder.singh@intel.com>

Add pipeline's port action profile implementation to the softnic.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
 drivers/net/softnic/Makefile                    |   3 +
 drivers/net/softnic/hash_func.h                 | 359 ++++++++++++++++++++++++
 drivers/net/softnic/hash_func_arm64.h           | 261 +++++++++++++++++
 drivers/net/softnic/rte_eth_softnic.c           |   2 +
 drivers/net/softnic/rte_eth_softnic_action.c    | 162 +++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h |  38 +++
 mk/rte.app.mk                                   |   2 +
 7 files changed, 827 insertions(+)
 create mode 100644 drivers/net/softnic/hash_func.h
 create mode 100644 drivers/net/softnic/hash_func_arm64.h
 create mode 100644 drivers/net/softnic/rte_eth_softnic_action.c

diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile
index 677a5b1..82f1eb5 100644
--- a/drivers/net/softnic/Makefile
+++ b/drivers/net/softnic/Makefile
@@ -8,8 +8,10 @@ include $(RTE_SDK)/mk/rte.vars.mk
 #
 LIB = librte_pmd_softnic.a
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_pipeline
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_sched
 LDLIBS += -lrte_bus_vdev
@@ -27,6 +29,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c
 
 #
 # Export include files
diff --git a/drivers/net/softnic/hash_func.h b/drivers/net/softnic/hash_func.h
new file mode 100644
index 0000000..198d2b2
--- /dev/null
+++ b/drivers/net/softnic/hash_func.h
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#ifndef __INCLUDE_HASH_FUNC_H__
+#define __INCLUDE_HASH_FUNC_H__
+
+#include <rte_common.h>
+
+static inline uint64_t
+hash_xor_key8(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0;
+
+	xor0 = seed ^ (k[0] & m[0]);
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key16(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key24(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+
+	xor0 ^= k[2] & m[2];
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key32(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0, xor1;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+	xor1 = (k[2] & m[2]) ^ (k[3] & m[3]);
+
+	xor0 ^= xor1;
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key40(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0, xor1;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+	xor1 = (k[2] & m[2]) ^ (k[3] & m[3]);
+
+	xor0 ^= xor1;
+
+	xor0 ^= k[4] & m[4];
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key48(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0, xor1, xor2;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+	xor1 = (k[2] & m[2]) ^ (k[3] & m[3]);
+	xor2 = (k[4] & m[4]) ^ (k[5] & m[5]);
+
+	xor0 ^= xor1;
+
+	xor0 ^= xor2;
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key56(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0, xor1, xor2;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+	xor1 = (k[2] & m[2]) ^ (k[3] & m[3]);
+	xor2 = (k[4] & m[4]) ^ (k[5] & m[5]);
+
+	xor0 ^= xor1;
+	xor2 ^= k[6] & m[6];
+
+	xor0 ^= xor2;
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+static inline uint64_t
+hash_xor_key64(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t xor0, xor1, xor2, xor3;
+
+	xor0 = ((k[0] & m[0]) ^ seed) ^ (k[1] & m[1]);
+	xor1 = (k[2] & m[2]) ^ (k[3] & m[3]);
+	xor2 = (k[4] & m[4]) ^ (k[5] & m[5]);
+	xor3 = (k[6] & m[6]) ^ (k[7] & m[7]);
+
+	xor0 ^= xor1;
+	xor2 ^= xor3;
+
+	xor0 ^= xor2;
+
+	return (xor0 >> 32) ^ xor0;
+}
+
+#if defined(RTE_ARCH_X86_64)
+
+#include <x86intrin.h>
+
+static inline uint64_t
+hash_crc_key8(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t crc0;
+
+	crc0 = _mm_crc32_u64(seed, k[0] & m[0]);
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key16(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, crc0, crc1;
+
+	k0 = k[0] & m[0];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key24(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, crc0, crc1;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc0 = _mm_crc32_u64(crc0, k2);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key32(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc2 = _mm_crc32_u64(k2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+
+	crc0 = _mm_crc32_u64(crc0, crc1);
+	crc1 = _mm_crc32_u64(crc2, crc3);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key40(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc2 = _mm_crc32_u64(k2, k[3] & m[3]);
+	crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]);
+
+	crc0 = _mm_crc32_u64(crc0, crc1);
+	crc1 = _mm_crc32_u64(crc2, crc3);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key48(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, k5, crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc2 = _mm_crc32_u64(k2, k[3] & m[3]);
+	crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]);
+
+	crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+	crc1 = _mm_crc32_u64(crc3, k5);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key56(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc2 = _mm_crc32_u64(k2, k[3] & m[3]);
+	crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]);
+
+	crc4 = _mm_crc32_u64(k5, k[6] & m[6]);
+	crc5 = k5 >> 32;
+
+	crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+	crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key64(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint64_t k0, k2, k5, crc0, crc1, crc2, crc3, crc4, crc5;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = _mm_crc32_u64(k0, seed);
+	crc1 = _mm_crc32_u64(k0 >> 32, k[1] & m[1]);
+
+	crc2 = _mm_crc32_u64(k2, k[3] & m[3]);
+	crc3 = _mm_crc32_u64(k2 >> 32, k[4] & m[4]);
+
+	crc4 = _mm_crc32_u64(k5, k[6] & m[6]);
+	crc5 = _mm_crc32_u64(k5 >> 32, k[7] & m[7]);
+
+	crc0 = _mm_crc32_u64(crc0, (crc1 << 32) ^ crc2);
+	crc1 = _mm_crc32_u64(crc3, (crc4 << 32) ^ crc5);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+#define hash_default_key8			hash_crc_key8
+#define hash_default_key16			hash_crc_key16
+#define hash_default_key24			hash_crc_key24
+#define hash_default_key32			hash_crc_key32
+#define hash_default_key40			hash_crc_key40
+#define hash_default_key48			hash_crc_key48
+#define hash_default_key56			hash_crc_key56
+#define hash_default_key64			hash_crc_key64
+
+#elif defined(RTE_ARCH_ARM64)
+#include "hash_func_arm64.h"
+#else
+
+#define hash_default_key8			hash_xor_key8
+#define hash_default_key16			hash_xor_key16
+#define hash_default_key24			hash_xor_key24
+#define hash_default_key32			hash_xor_key32
+#define hash_default_key40			hash_xor_key40
+#define hash_default_key48			hash_xor_key48
+#define hash_default_key56			hash_xor_key56
+#define hash_default_key64			hash_xor_key64
+
+#endif
+
+#endif
diff --git a/drivers/net/softnic/hash_func_arm64.h b/drivers/net/softnic/hash_func_arm64.h
new file mode 100644
index 0000000..ae6c0f4
--- /dev/null
+++ b/drivers/net/softnic/hash_func_arm64.h
@@ -0,0 +1,261 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Linaro Limited. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HASH_FUNC_ARM64_H__
+#define __HASH_FUNC_ARM64_H__
+
+#define _CRC32CX(crc, val)	\
+	__asm__("crc32cx %w[c], %w[c], %x[v]":[c] "+r" (crc):[v] "r" (val))
+
+static inline uint64_t
+hash_crc_key8(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key;
+	uint64_t *m = mask;
+	uint32_t crc0;
+
+	crc0 = seed;
+	_CRC32CX(crc0, k[0] & m[0]);
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key16(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1;
+
+	k0 = k[0] & m[0];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key24(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	_CRC32CX(crc0, k2);
+
+	crc0 ^= crc1;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key32(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc2 = k2;
+	_CRC32CX(crc2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+
+	_CRC32CX(crc0, crc1);
+	_CRC32CX(crc2, crc3);
+
+	crc0 ^= crc2;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key40(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc2 = k2;
+	_CRC32CX(crc2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+	_CRC32CX(crc3, k[4] & m[4]);
+
+	_CRC32CX(crc0, crc1);
+	_CRC32CX(crc2, crc3);
+
+	crc0 ^= crc2;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key48(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2, k5;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1, crc2, crc3;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc2 = k2;
+	_CRC32CX(crc2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+	_CRC32CX(crc3, k[4] & m[4]);
+
+	_CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2);
+	_CRC32CX(crc3, k5);
+
+	crc0 ^= crc3;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key56(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2, k5;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1, crc2, crc3, crc4, crc5;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc2 = k2;
+	_CRC32CX(crc2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+	_CRC32CX(crc3, k[4] & m[4]);
+
+	crc4 = k5;
+	 _CRC32CX(crc4, k[6] & m[6]);
+	crc5 = k5 >> 32;
+
+	_CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2);
+	_CRC32CX(crc3, ((uint64_t)crc4 << 32) ^ crc5);
+
+	crc0 ^= crc3;
+
+	return crc0;
+}
+
+static inline uint64_t
+hash_crc_key64(void *key, void *mask, __rte_unused uint32_t key_size,
+	uint64_t seed)
+{
+	uint64_t *k = key, k0, k2, k5;
+	uint64_t *m = mask;
+	uint32_t crc0, crc1, crc2, crc3, crc4, crc5;
+
+	k0 = k[0] & m[0];
+	k2 = k[2] & m[2];
+	k5 = k[5] & m[5];
+
+	crc0 = k0;
+	_CRC32CX(crc0, seed);
+	crc1 = k0 >> 32;
+	_CRC32CX(crc1, k[1] & m[1]);
+
+	crc2 = k2;
+	_CRC32CX(crc2, k[3] & m[3]);
+	crc3 = k2 >> 32;
+	_CRC32CX(crc3, k[4] & m[4]);
+
+	crc4 = k5;
+	 _CRC32CX(crc4, k[6] & m[6]);
+	crc5 = k5 >> 32;
+	_CRC32CX(crc5, k[7] & m[7]);
+
+	_CRC32CX(crc0, ((uint64_t)crc1 << 32) ^ crc2);
+	_CRC32CX(crc3, ((uint64_t)crc4 << 32) ^ crc5);
+
+	crc0 ^= crc3;
+
+	return crc0;
+}
+
+#define hash_default_key8			hash_crc_key8
+#define hash_default_key16			hash_crc_key16
+#define hash_default_key24			hash_crc_key24
+#define hash_default_key32			hash_crc_key32
+#define hash_default_key40			hash_crc_key40
+#define hash_default_key48			hash_crc_key48
+#define hash_default_key56			hash_crc_key56
+#define hash_default_key64			hash_crc_key64
+
+#endif
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index d7580f6..87463c3 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -241,6 +241,7 @@ pmd_init(struct pmd_params *params)
 	tm_init(p);
 	tmgr_init(p);
 	tap_init(p);
+	port_in_action_profile_init(p);
 
 	return p;
 }
@@ -251,6 +252,7 @@ pmd_free(struct pmd_internals *p)
 	if (p == NULL)
 		return;
 
+	port_in_action_profile_free(p);
 	tap_free(p);
 	tmgr_free(p);
 	tm_free(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_action.c b/drivers/net/softnic/rte_eth_softnic_action.c
new file mode 100644
index 0000000..ace87ed
--- /dev/null
+++ b/drivers/net/softnic/rte_eth_softnic_action.c
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+
+#include "hash_func.h"
+#include "rte_eth_softnic_internals.h"
+
+/**
+ * Input port
+ */
+int
+port_in_action_profile_init(struct pmd_internals *p)
+{
+	TAILQ_INIT(&p->port_in_action_profile_list);
+
+	return 0;
+}
+
+void
+port_in_action_profile_free(struct pmd_internals *p)
+{
+	for ( ; ; ) {
+		struct port_in_action_profile *profile;
+
+		profile = TAILQ_FIRST(&p->port_in_action_profile_list);
+		if (profile == NULL)
+			break;
+
+		TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node);
+		free(profile);
+	}
+}
+
+struct port_in_action_profile *
+port_in_action_profile_find(struct pmd_internals *p,
+	const char *name)
+{
+	struct port_in_action_profile *profile;
+
+	if (name == NULL)
+		return NULL;
+
+	TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node)
+		if (strcmp(profile->name, name) == 0)
+			return profile;
+
+	return NULL;
+}
+
+struct port_in_action_profile *
+port_in_action_profile_create(struct pmd_internals *p,
+	const char *name,
+	struct port_in_action_profile_params *params)
+{
+	struct port_in_action_profile *profile;
+	struct rte_port_in_action_profile *ap;
+	int status;
+
+	/* Check input params */
+	if (name == NULL ||
+		port_in_action_profile_find(p, name) ||
+		params == NULL)
+		return NULL;
+
+	if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) &&
+		params->lb.f_hash == NULL) {
+		switch (params->lb.key_size) {
+		case  8:
+			params->lb.f_hash = hash_default_key8;
+			break;
+
+		case 16:
+			params->lb.f_hash = hash_default_key16;
+			break;
+
+		case 24:
+			params->lb.f_hash = hash_default_key24;
+			break;
+
+		case 32:
+			params->lb.f_hash = hash_default_key32;
+			break;
+
+		case 40:
+			params->lb.f_hash = hash_default_key40;
+			break;
+
+		case 48:
+			params->lb.f_hash = hash_default_key48;
+			break;
+
+		case 56:
+			params->lb.f_hash = hash_default_key56;
+			break;
+
+		case 64:
+			params->lb.f_hash = hash_default_key64;
+			break;
+
+		default:
+			return NULL;
+		}
+
+		params->lb.seed = 0;
+	}
+
+	/* Resource */
+	ap = rte_port_in_action_profile_create(0);
+	if (ap == NULL)
+		return NULL;
+
+	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) {
+		status = rte_port_in_action_profile_action_register(ap,
+			RTE_PORT_IN_ACTION_FLTR,
+			&params->fltr);
+
+		if (status) {
+			rte_port_in_action_profile_free(ap);
+			return NULL;
+		}
+	}
+
+	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) {
+		status = rte_port_in_action_profile_action_register(ap,
+			RTE_PORT_IN_ACTION_LB,
+			&params->lb);
+
+		if (status) {
+			rte_port_in_action_profile_free(ap);
+			return NULL;
+		}
+	}
+
+	status = rte_port_in_action_profile_freeze(ap);
+	if (status) {
+		rte_port_in_action_profile_free(ap);
+		return NULL;
+	}
+
+	/* Node allocation */
+	profile = calloc(1, sizeof(struct port_in_action_profile));
+	if (profile == NULL) {
+		rte_port_in_action_profile_free(ap);
+		return NULL;
+	}
+
+	/* Node fill in */
+	strlcpy(profile->name, name, sizeof(profile->name));
+	memcpy(&profile->params, params, sizeof(*params));
+	profile->ap = ap;
+
+	/* Node add to list */
+	TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node);
+
+	return profile;
+}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index e724cba..0906b6d 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -14,6 +14,7 @@
 #include <rte_ring.h>
 #include <rte_ethdev.h>
 #include <rte_sched.h>
+#include <rte_port_in_action.h>
 #include <rte_ethdev_driver.h>
 #include <rte_tm_driver.h>
 
@@ -220,6 +221,24 @@ struct tap {
 TAILQ_HEAD(tap_list, tap);
 
 /**
+ * Input port action
+ */
+struct port_in_action_profile_params {
+	uint64_t action_mask;
+	struct rte_port_in_action_fltr_config fltr;
+	struct rte_port_in_action_lb_config lb;
+};
+
+struct port_in_action_profile {
+	TAILQ_ENTRY(port_in_action_profile) node;
+	char name[NAME_SIZE];
+	struct port_in_action_profile_params params;
+	struct rte_port_in_action_profile *ap;
+};
+
+TAILQ_HEAD(port_in_action_profile_list, port_in_action_profile);
+
+/**
  * PMD Internals
  */
 struct pmd_internals {
@@ -235,6 +254,7 @@ struct pmd_internals {
 	struct link_list link_list;
 	struct tmgr_port_list tmgr_port_list;
 	struct tap_list tap_list;
+	struct port_in_action_profile_list port_in_action_profile_list;
 };
 
 /**
@@ -348,4 +368,22 @@ struct tap *
 tap_create(struct pmd_internals *p,
 	const char *name);
 
+/**
+ * Input port action
+ */
+int
+port_in_action_profile_init(struct pmd_internals *p);
+
+void
+port_in_action_profile_free(struct pmd_internals *p);
+
+struct port_in_action_profile *
+port_in_action_profile_find(struct pmd_internals *p,
+	const char *name);
+
+struct port_in_action_profile *
+port_in_action_profile_create(struct pmd_internals *p,
+	const char *name,
+	struct port_in_action_profile_params *params);
+
 #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 87a0c80..a9d65d9 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -31,7 +31,9 @@ _LDLIBS-y += -L$(RTE_SDK_BIN)/lib
 # Order is important: from higher level to lower level
 #
 _LDLIBS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY)  += -lrte_flow_classify
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE)       += --whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE)       += -lrte_pipeline
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE)       += --no-whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE)          += -lrte_table
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT)           += -lrte_port
 
-- 
2.9.3

  parent reply	other threads:[~2018-06-27 16:31 UTC|newest]

Thread overview: 132+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-06-08 12:41 [PATCH 00/21] net/softnic: refactoring Jasvinder Singh
2018-06-08 12:41 ` [PATCH 01/21] net/softnic: restructuring Jasvinder Singh
2018-06-15 16:52   ` [PATCH v2 00/22] net/softnic: refactoring Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 01/22] net/softnic: restructuring Jasvinder Singh
2018-06-27 16:31       ` [PATCH v3 00/23] net/softnic: refactoring Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 01/23] net/softnic: restructuring Jasvinder Singh
2018-07-05 15:47           ` [PATCH v4 00/23] net/softnic: refactoring Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 01/23] net/softnic: restructuring Jasvinder Singh
2018-07-06 17:20               ` [PATCH v5 00/23] net/softnic: refactoring Jasvinder Singh
2018-07-06 17:20                 ` [PATCH v5 01/23] net/softnic: restructuring Jasvinder Singh
2018-07-11 10:47                   ` Thomas Monjalon
2018-07-06 17:20                 ` [PATCH v5 02/23] net/softnic: add software queue object Jasvinder Singh
2018-07-06 17:20                 ` [PATCH v5 03/23] net/softnic: add link object Jasvinder Singh
2018-07-06 17:20                 ` [PATCH v5 04/23] net/softnic: add mempool object Jasvinder Singh
2018-07-06 17:20                 ` [PATCH v5 05/23] net/softnic: add tap object Jasvinder Singh
2018-07-06 17:20                 ` [PATCH v5 06/23] net/softnic: add traffic manager object Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 07/23] net/softnic: add port action profile Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 08/23] net/softnic: add table " Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 09/23] net/softnic: add pipeline object Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 10/23] net/softnic: add thread Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 11/23] net/softnic: add softnic run API Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 12/23] net/softnic: add cli interface Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 13/23] net/softnic: add connection agent Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 14/23] net/softnic: add cli to create softnic objects Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 15/23] net/softnic: add cli to enable and disable pipeline Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 16/23] net/softnic: add cli for pipeline table entries Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 17/23] net/softnic: add cli to read stats Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 18/23] net/softnic: add cli for meter action Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 19/23] net/softnic: add cli for ttl action Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 20/23] net/softnic: receive and transmit queue setup Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 21/23] net/softnic: start and stop function Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 22/23] net/softnic: add firmware script Jasvinder Singh
2018-07-06 17:21                 ` [PATCH v5 23/23] app/testpmd: rework softnic forward mode Jasvinder Singh
2018-07-06 17:33                 ` [PATCH v5 00/23] net/softnic: refactoring Dumitrescu, Cristian
2018-07-05 15:47             ` [PATCH v4 02/23] net/softnic: add software queue object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 03/23] net/softnic: add link object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 04/23] net/softnic: add mempool object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 05/23] net/softnic: add tap object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 06/23] net/softnic: add traffic manager object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 07/23] net/softnic: add port action profile Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 08/23] net/softnic: add table " Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 09/23] net/softnic: add pipeline object Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 10/23] net/softnic: add thread Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 11/23] net/softnic: add softnic run API Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 12/23] net/softnic: add cli interface Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 13/23] net/softnic: add connection agent Jasvinder Singh
2018-07-11 19:58               ` Thomas Monjalon
2018-07-05 15:47             ` [PATCH v4 14/23] net/softnic: add cli to create softnic objects Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 15/23] net/softnic: add cli to enable and disable pipeline Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 16/23] net/softnic: add cli for pipeline table entries Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 17/23] net/softnic: add cli to read stats Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 18/23] net/softnic: add cli for meter action Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 19/23] net/softnic: add cli for ttl action Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 20/23] net/softnic: receive and transmit queue setup Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 21/23] net/softnic: start and stop function Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 22/23] net/softnic: add firmware script Jasvinder Singh
2018-07-05 15:47             ` [PATCH v4 23/23] app/testpmd: rework softnic forward mode Jasvinder Singh
2018-07-06 10:37             ` [PATCH v4 00/23] net/softnic: refactoring Dumitrescu, Cristian
2018-06-27 16:31         ` [PATCH v3 02/23] net/softnic: add software queue object Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 03/23] net/softnic: add link object Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 04/23] net/softnic: add mempool object Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 05/23] net/softnic: add tap object Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 06/23] net/softnic: add traffic manager object Jasvinder Singh
2018-06-27 16:31         ` Jasvinder Singh [this message]
2018-06-27 16:31         ` [PATCH v3 08/23] net/softnic: add table action profile Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 09/23] net/softnic: add pipeline object Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 10/23] net/softnic: add thread Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 11/23] net/softnic: add softnic run API Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 12/23] net/softnic: add cli interface Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 13/23] net/softnic: add connection agent Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 14/23] net/softnic: add cli to create softnic objects Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 15/23] net/softnic: add cli to enable and disable pipeline Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 16/23] net/softnic: add cli for pipeline table entries Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 17/23] net/softnic: add cli to read stats Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 18/23] net/softnic: add cli for meter action Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 19/23] net/softnic: add cli for ttl action Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 20/23] net/softnic: receive and transmit queue setup Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 21/23] net/softnic: start and stop function Jasvinder Singh
2018-06-27 16:31         ` [PATCH v3 22/23] net/softnic: add firmware script Jasvinder Singh
2018-06-28 10:13           ` Pattan, Reshma
2018-06-28 10:18             ` Singh, Jasvinder
2018-06-27 16:31         ` [PATCH v3 23/23] app/testpmd: rework softnic forward mode Jasvinder Singh
2018-06-28 10:27           ` Iremonger, Bernard
2018-06-28 10:29             ` Singh, Jasvinder
2018-06-28 11:15               ` Iremonger, Bernard
2018-06-28 12:45                 ` Iremonger, Bernard
2018-06-28 13:45           ` Iremonger, Bernard
2018-06-28 13:50             ` Singh, Jasvinder
2018-06-28 13:17         ` [PATCH v3 00/23] net/softnic: refactoring Dumitrescu, Cristian
2018-06-15 16:52     ` [PATCH v2 02/22] net/softnic: add software queue object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 03/22] net/softnic: add link object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 04/22] net/softnic: add mempool object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 05/22] net/softnic: add tap object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 06/22] net/softnic: add trafic manager object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 07/22] net/softnic: add port action profile Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 08/22] net/softnic: add table " Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 09/22] net/softnic: add pipeline object Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 10/22] net/softnic: add thread Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 11/22] net/softnic: add softnic run API Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 12/22] net/softnic: add cli interface Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 13/22] net/softnic: add connection agent Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 14/22] net/softnic: add cli to create softnic objects Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 15/22] net/softnic: add cli to enable and disable pipeline Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 16/22] net/softnic: add cli for pipeline table entries Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 17/22] net/softnic: add cli to read pipeline port and table stats Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 18/22] net/softnic: add cli for meter action Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 19/22] net/softnic: add cli for ttl action Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 20/22] net/softnic: receive and transmit queue setup Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 21/22] net/softnic: start and stop function Jasvinder Singh
2018-06-15 16:52     ` [PATCH v2 22/22] app/testpmd: rework softnic forward mode Jasvinder Singh
2018-06-26  8:55       ` Iremonger, Bernard
2018-06-26  8:59         ` Singh, Jasvinder
2018-06-08 12:41 ` [PATCH 02/21] net/softnic: add software queue object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 03/21] net/softnic: add link object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 04/21] net/softnic: add mempool object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 05/21] net/softnic: add tap object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 06/21] net/softnic: add trafic manager object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 07/21] net/softnic: add port action profile Jasvinder Singh
2018-06-08 12:41 ` [PATCH 08/21] net/softnic: add table " Jasvinder Singh
2018-06-08 12:41 ` [PATCH 09/21] net/softnic: add pipeline object Jasvinder Singh
2018-06-08 12:41 ` [PATCH 10/21] net/softnic: add thread Jasvinder Singh
2018-06-08 12:41 ` [PATCH 11/21] net/softnic: add softnic run API Jasvinder Singh
2018-06-08 12:41 ` [PATCH 12/21] net/softnic: add cli interface Jasvinder Singh
2018-06-08 12:41 ` [PATCH 13/21] net/softnic: add connection agent Jasvinder Singh
2018-06-08 12:41 ` [PATCH 14/21] net/softnic: add cli to create softnic objects Jasvinder Singh
2018-06-08 12:41 ` [PATCH 15/21] net/softnic: add cli to enable and disable pipeline Jasvinder Singh
2018-06-08 12:41 ` [PATCH 16/21] net/softnic: add cli for pipeline table entries Jasvinder Singh
2018-06-08 12:41 ` [PATCH 17/21] net/softnic: add cli to read pipeline port and table stats Jasvinder Singh
2018-06-08 12:41 ` [PATCH 18/21] net/softnic: add cli for meter action Jasvinder Singh
2018-06-08 12:41 ` [PATCH 19/21] net/softnic: add cli for ttl action Jasvinder Singh
2018-06-08 12:41 ` [PATCH 20/21] net/softnic: receive and transmit queue setup Jasvinder Singh
2018-06-08 12:41 ` [PATCH 21/21] net/softnic: start and stop function Jasvinder Singh

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=20180627163123.135686-8-jasvinder.singh@intel.com \
    --to=jasvinder.singh@intel.com \
    --cc=bernard.iremonger@intel.com \
    --cc=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    /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.