All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
To: dev@dpdk.org
Cc: konstantin.ananyev@intel.com, bernard.iremonger@intel.com,
	akhil.goyal@nxp.com
Subject: [dpdk-dev] [PATCH v5 3/5] ipsec: add SAD add/delete/lookup implementation
Date: Thu, 10 Oct 2019 17:49:24 +0100	[thread overview]
Message-ID: <cf3aab9589561b3a304172696e3319c02e0ff5ce.1570725872.git.vladimir.medvedkin@intel.com> (raw)
In-Reply-To: <cover.1570725871.git.vladimir.medvedkin@intel.com>
In-Reply-To: <cover.1570725871.git.vladimir.medvedkin@intel.com>

Replace rte_ipsec_sad_add(), rte_ipsec_sad_del() and
rte_ipsec_sad_lookup() stubs with actual implementation.

It uses three librte_hash tables each of which contains
an entries for a specific SA type (either it is addressed by SPI only
or SPI+DIP or SPI+DIP+SIP)

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Tested-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 lib/librte_ipsec/ipsec_sad.c | 278 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 266 insertions(+), 12 deletions(-)

diff --git a/lib/librte_ipsec/ipsec_sad.c b/lib/librte_ipsec/ipsec_sad.c
index e16c7d9..db2c44c 100644
--- a/lib/librte_ipsec/ipsec_sad.c
+++ b/lib/librte_ipsec/ipsec_sad.c
@@ -49,20 +49,182 @@ static struct rte_tailq_elem rte_ipsec_sad_tailq = {
 };
 EAL_REGISTER_TAILQ(rte_ipsec_sad_tailq)
 
+#define SET_BIT(ptr, bit)	(void *)((uintptr_t)(ptr) | (uintptr_t)(bit))
+#define CLEAR_BIT(ptr, bit)	(void *)((uintptr_t)(ptr) & ~(uintptr_t)(bit))
+#define GET_BIT(ptr, bit)	(void *)((uintptr_t)(ptr) & (uintptr_t)(bit))
+
+/*
+ * @internal helper function
+ * Add a rule of type SPI_DIP or SPI_DIP_SIP.
+ * Inserts a rule into an appropriate hash table,
+ * updates the value for a given SPI in SPI_ONLY hash table
+ * reflecting presence of more specific rule type in two LSBs.
+ * Updates a counter that reflects the number of rules whith the same SPI.
+ */
+static inline int
+add_specific(struct rte_ipsec_sad *sad, const void *key,
+		int key_type, void *sa)
+{
+	void *tmp_val;
+	int ret, notexist;
+
+	/* Check if the key is present in the table.
+	 * Need for further accaunting in cnt_arr
+	 */
+	ret = rte_hash_lookup(sad->hash[key_type], key);
+	notexist = (ret == -ENOENT);
+
+	/* Add an SA to the corresponding table.*/
+	ret = rte_hash_add_key_data(sad->hash[key_type], key, sa);
+	if (ret != 0)
+		return ret;
+
+	/* Check if there is an entry in SPI only table with the same SPI */
+	ret = rte_hash_lookup_data(sad->hash[RTE_IPSEC_SAD_SPI_ONLY],
+		key, &tmp_val);
+	if (ret < 0)
+		tmp_val = NULL;
+	tmp_val = SET_BIT(tmp_val, key_type);
+
+	/* Add an entry into SPI only table */
+	ret = rte_hash_add_key_data(sad->hash[RTE_IPSEC_SAD_SPI_ONLY],
+		key, tmp_val);
+	if (ret != 0)
+		return ret;
+
+	/* Update a counter for a given SPI */
+	ret = rte_hash_lookup(sad->hash[RTE_IPSEC_SAD_SPI_ONLY], key);
+	if (key_type == RTE_IPSEC_SAD_SPI_DIP)
+		sad->cnt_arr[ret].cnt_dip += notexist;
+	else
+		sad->cnt_arr[ret].cnt_dip_sip += notexist;
+
+	return 0;
+}
+
 int
-rte_ipsec_sad_add(__rte_unused struct rte_ipsec_sad *sad,
-		__rte_unused const union rte_ipsec_sad_key *key,
-		__rte_unused int key_type, __rte_unused void *sa)
+rte_ipsec_sad_add(struct rte_ipsec_sad *sad,
+		const union rte_ipsec_sad_key *key,
+		int key_type, void *sa)
 {
-	return -ENOTSUP;
+	void *tmp_val;
+	int ret;
+
+	if ((sad == NULL) || (key == NULL) || (sa == NULL) ||
+			/* sa must be 4 byte aligned */
+			(GET_BIT(sa, RTE_IPSEC_SAD_KEY_TYPE_MASK) != 0))
+		return -EINVAL;
+
+	/*
+	 * Rules are stored in three hash tables depending on key_type.
+	 * All rules will also have an entry in SPI_ONLY table, with entry
+	 * value's two LSB's also indicating presence of rule with this SPI
+	 * in other tables.
+	 */
+	switch (key_type) {
+	case(RTE_IPSEC_SAD_SPI_ONLY):
+		ret = rte_hash_lookup_data(sad->hash[key_type],
+			key, &tmp_val);
+		if (ret >= 0)
+			tmp_val = SET_BIT(sa, GET_BIT(tmp_val,
+				RTE_IPSEC_SAD_KEY_TYPE_MASK));
+		else
+			tmp_val = sa;
+		ret = rte_hash_add_key_data(sad->hash[key_type],
+			key, tmp_val);
+		return ret;
+	case(RTE_IPSEC_SAD_SPI_DIP):
+	case(RTE_IPSEC_SAD_SPI_DIP_SIP):
+		return add_specific(sad, key, key_type, sa);
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * @internal helper function
+ * Delete a rule of type SPI_DIP or SPI_DIP_SIP.
+ * Deletes an entry from an appropriate hash table and decrements
+ * an entry counter for given SPI.
+ * If entry to remove is the last one with given SPI within the table,
+ * then it will also update related entry in SPI_ONLY table.
+ * Removes an entry from SPI_ONLY hash table if there no rule left
+ * for this SPI in any table.
+ */
+static inline int
+del_specific(struct rte_ipsec_sad *sad, const void *key, int key_type)
+{
+	void *tmp_val;
+	int ret;
+	uint32_t *cnt;
+
+	/* Remove an SA from the corresponding table.*/
+	ret = rte_hash_del_key(sad->hash[key_type], key);
+	if (ret < 0)
+		return ret;
+
+	/* Get an index of cnt_arr entry for a given SPI */
+	ret = rte_hash_lookup_data(sad->hash[RTE_IPSEC_SAD_SPI_ONLY],
+		key, &tmp_val);
+	if (ret < 0)
+		return ret;
+	cnt = (key_type == RTE_IPSEC_SAD_SPI_DIP) ?
+			&sad->cnt_arr[ret].cnt_dip :
+			&sad->cnt_arr[ret].cnt_dip_sip;
+	if (--(*cnt) != 0)
+		return 0;
+
+	/* corresponding counter is 0, clear the bit indicating
+	 * the presence of more specific rule for a given SPI.
+	 */
+	tmp_val = CLEAR_BIT(tmp_val, key_type);
+
+	/* if there are no rules left with same SPI,
+	 * remove an entry from SPI_only table
+	 */
+	if (tmp_val == NULL)
+		ret = rte_hash_del_key(sad->hash[RTE_IPSEC_SAD_SPI_ONLY], key);
+	else
+		ret = rte_hash_add_key_data(sad->hash[RTE_IPSEC_SAD_SPI_ONLY],
+			key, tmp_val);
+	if (ret < 0)
+		return ret;
+	return 0;
 }
 
 int
-rte_ipsec_sad_del(__rte_unused struct rte_ipsec_sad *sad,
-		__rte_unused const union rte_ipsec_sad_key *key,
-		__rte_unused int key_type)
+rte_ipsec_sad_del(struct rte_ipsec_sad *sad,
+		const union rte_ipsec_sad_key *key,
+		int key_type)
 {
-	return -ENOTSUP;
+	void *tmp_val;
+	int ret;
+
+	if ((sad == NULL) || (key == NULL))
+		return -EINVAL;
+	switch (key_type) {
+	case(RTE_IPSEC_SAD_SPI_ONLY):
+		ret = rte_hash_lookup_data(sad->hash[key_type],
+			key, &tmp_val);
+		if (ret < 0)
+			return ret;
+		if (GET_BIT(tmp_val, RTE_IPSEC_SAD_KEY_TYPE_MASK) == 0) {
+			ret = rte_hash_del_key(sad->hash[key_type],
+				key);
+			ret = ret < 0 ? ret : 0;
+		} else {
+			tmp_val = GET_BIT(tmp_val,
+				RTE_IPSEC_SAD_KEY_TYPE_MASK);
+			ret = rte_hash_add_key_data(sad->hash[key_type],
+				key, tmp_val);
+		}
+		return ret;
+	case(RTE_IPSEC_SAD_SPI_DIP):
+	case(RTE_IPSEC_SAD_SPI_DIP_SIP):
+		return del_specific(sad, key, key_type);
+	default:
+		return -EINVAL;
+	}
 }
 
 struct rte_ipsec_sad *
@@ -252,10 +414,102 @@ rte_ipsec_sad_destroy(struct rte_ipsec_sad *sad)
 		rte_free(te);
 }
 
+/*
+ * @internal helper function
+ * Lookup a batch of keys in three hash tables.
+ * First lookup key in SPI_ONLY table.
+ * If there is an entry for the corresponding SPI check its value.
+ * Two least significant bits of the value indicate
+ * the presence of more specific rule in other tables.
+ * Perform additional lookup in corresponding hash tables
+ * and update the value if lookup succeeded.
+ */
+static int
+__ipsec_sad_lookup(const struct rte_ipsec_sad *sad,
+		const union rte_ipsec_sad_key *keys[], void *sa[], uint32_t n)
+{
+	const void *keys_2[RTE_HASH_LOOKUP_BULK_MAX];
+	const void *keys_3[RTE_HASH_LOOKUP_BULK_MAX];
+	void *vals_2[RTE_HASH_LOOKUP_BULK_MAX] = {NULL};
+	void *vals_3[RTE_HASH_LOOKUP_BULK_MAX] = {NULL};
+	uint32_t idx_2[RTE_HASH_LOOKUP_BULK_MAX];
+	uint32_t idx_3[RTE_HASH_LOOKUP_BULK_MAX];
+	uint64_t mask_1, mask_2, mask_3;
+	uint64_t map, map_spec;
+	uint32_t n_2 = 0;
+	uint32_t n_3 = 0;
+	uint32_t i;
+	int found = 0;
+
+	for (i = 0; i < n; i++)
+		sa[i] = NULL;
+
+	/*
+	 * Lookup keys in SPI only hash table first.
+	 */
+	rte_hash_lookup_bulk_data(sad->hash[RTE_IPSEC_SAD_SPI_ONLY],
+		(const void **)keys, n, &mask_1, sa);
+	for (map = mask_1; map; map &= (map - 1)) {
+		i = rte_bsf64(map);
+		/*
+		 * if returned value indicates presence of a rule in other
+		 * tables save a key for further lookup.
+		 */
+		if ((uintptr_t)sa[i] & RTE_IPSEC_SAD_SPI_DIP_SIP) {
+			idx_3[n_3] = i;
+			keys_3[n_3++] = keys[i];
+		}
+		if ((uintptr_t)sa[i] & RTE_IPSEC_SAD_SPI_DIP) {
+			idx_2[n_2] = i;
+			keys_2[n_2++] = keys[i];
+		}
+		/* clear 2 LSB's which indicate the presence
+		 * of more specific rules
+		 */
+		sa[i] = CLEAR_BIT(sa[i], RTE_IPSEC_SAD_KEY_TYPE_MASK);
+	}
+
+	/* Lookup for more specific rules in SPI_DIP table */
+	if (n_2 != 0) {
+		rte_hash_lookup_bulk_data(sad->hash[RTE_IPSEC_SAD_SPI_DIP],
+			keys_2, n_2, &mask_2, vals_2);
+		for (map_spec = mask_2; map_spec; map_spec &= (map_spec - 1)) {
+			i = rte_bsf64(map_spec);
+			sa[idx_2[i]] = vals_2[i];
+		}
+	}
+	/* Lookup for more specific rules in SPI_DIP_SIP table */
+	if (n_3 != 0) {
+		rte_hash_lookup_bulk_data(sad->hash[RTE_IPSEC_SAD_SPI_DIP_SIP],
+			keys_3, n_3, &mask_3, vals_3);
+		for (map_spec = mask_3; map_spec; map_spec &= (map_spec - 1)) {
+			i = rte_bsf64(map_spec);
+			sa[idx_3[i]] = vals_3[i];
+		}
+	}
+
+	for (i = 0; i < n; i++)
+		found += (sa[i] != NULL);
+
+	return found;
+}
+
 int
-rte_ipsec_sad_lookup(__rte_unused const struct rte_ipsec_sad *sad,
-		__rte_unused const union rte_ipsec_sad_key *keys[],
-		__rte_unused void *sa[], __rte_unused uint32_t n)
+rte_ipsec_sad_lookup(const struct rte_ipsec_sad *sad,
+		const union rte_ipsec_sad_key *keys[], void *sa[], uint32_t n)
 {
-	return -ENOTSUP;
+	uint32_t num, i = 0;
+	int found = 0;
+
+	if (unlikely((sad == NULL) || (keys == NULL) || (sa == NULL)))
+		return -EINVAL;
+
+	do {
+		num = RTE_MIN(n - i, (uint32_t)RTE_HASH_LOOKUP_BULK_MAX);
+		found += __ipsec_sad_lookup(sad,
+			&keys[i], &sa[i], num);
+		i += num;
+	} while (i != n);
+
+	return found;
 }
-- 
2.7.4


  parent reply	other threads:[~2019-10-10 16:50 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-13 15:13 [dpdk-dev] [RFC 0/5] ipsec: add inbound SAD Vladimir Medvedkin
2019-08-13 15:13 ` [dpdk-dev] [RFC 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-08-13 15:13 ` [dpdk-dev] [RFC 2/5] ipsec: add SAD create/free API Vladimir Medvedkin
2019-08-13 15:13 ` [dpdk-dev] [RFC 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-08-13 15:13 ` [dpdk-dev] [RFC 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-08-13 15:13 ` [dpdk-dev] [RFC 5/5] app: add test-sad application Vladimir Medvedkin
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 0/5] ipsec: add inbound SAD Vladimir Medvedkin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 " Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
2019-10-10 16:49         ` [dpdk-dev] [PATCH v5 " Vladimir Medvedkin
2019-10-11 11:34           ` Akhil Goyal
2019-10-17 15:47           ` [dpdk-dev] [PATCH v6 0/6] " Vladimir Medvedkin
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 0/5] " Vladimir Medvedkin
2019-10-22  7:53               ` Akhil Goyal
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 2/5] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-21 14:35             ` [dpdk-dev] [PATCH v7 5/5] app: add test-sad application Vladimir Medvedkin
2019-10-17 15:47           ` [dpdk-dev] [PATCH v6 1/6] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-17 15:47           ` [dpdk-dev] [PATCH v6 2/6] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-17 15:48           ` [dpdk-dev] [PATCH v6 3/6] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-10-17 15:48           ` [dpdk-dev] [PATCH v6 4/6] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-17 15:48           ` [dpdk-dev] [PATCH v6 5/6] app: add test-sad application Vladimir Medvedkin
2019-10-21  9:57             ` Akhil Goyal
2019-10-17 15:48           ` [dpdk-dev] [PATCH v6 6/6] doc/ipsec: update ipsec programmer's guide Vladimir Medvedkin
2019-10-18 10:09             ` Ananyev, Konstantin
2019-10-21  8:19             ` Akhil Goyal
2019-10-10 16:49         ` [dpdk-dev] [PATCH v5 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-10 16:49         ` [dpdk-dev] [PATCH v5 2/5] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-10 16:49         ` Vladimir Medvedkin [this message]
2019-10-11 10:42           ` [dpdk-dev] [PATCH v5 3/5] ipsec: add SAD add/delete/lookup implementation Akhil Goyal
2019-10-10 16:49         ` [dpdk-dev] [PATCH v5 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-10 16:49         ` [dpdk-dev] [PATCH v5 5/5] app: add test-sad application Vladimir Medvedkin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-09 10:49         ` Ananyev, Konstantin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 2/5] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-09 10:56         ` Ananyev, Konstantin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-08 16:55       ` [dpdk-dev] [PATCH v4 5/5] app: add test-sad application Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 2/5] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-08  9:40     ` [dpdk-dev] [PATCH v3 5/5] app: add test-sad application Vladimir Medvedkin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-10-02 11:24     ` Ananyev, Konstantin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 2/5] ipsec: add SAD create/destroy implementation Vladimir Medvedkin
2019-10-02 11:55     ` Ananyev, Konstantin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-10-02 12:04     ` Ananyev, Konstantin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-10-02 11:16     ` Ananyev, Konstantin
2019-10-01 17:25   ` [dpdk-dev] [PATCH v2 5/5] app: add test-sad application Vladimir Medvedkin
2019-10-02 13:27     ` Ananyev, Konstantin
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 1/5] ipsec: add inbound SAD API Vladimir Medvedkin
2019-09-14 23:05   ` Ananyev, Konstantin
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 2/5] ipsec: add SAD create/free API Vladimir Medvedkin
2019-09-12 18:08   ` Ananyev, Konstantin
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 3/5] ipsec: add SAD add/delete/lookup implementation Vladimir Medvedkin
2019-09-12 17:58   ` Ananyev, Konstantin
2019-10-01 17:24     ` Medvedkin, Vladimir
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 4/5] test/ipsec: add ipsec SAD autotests Vladimir Medvedkin
2019-09-03 16:55 ` [dpdk-dev] [PATCH v1 5/5] app: add test-sad application Vladimir Medvedkin
2019-09-12 18:30   ` Ananyev, Konstantin
2019-09-12 18:33     ` Ananyev, Konstantin
2019-09-12 18:34 ` [dpdk-dev] [RFC 0/5] ipsec: add inbound SAD Ananyev, Konstantin

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=cf3aab9589561b3a304172696e3319c02e0ff5ce.1570725872.git.vladimir.medvedkin@intel.com \
    --to=vladimir.medvedkin@intel.com \
    --cc=akhil.goyal@nxp.com \
    --cc=bernard.iremonger@intel.com \
    --cc=dev@dpdk.org \
    --cc=konstantin.ananyev@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.