summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec/ipsec_spd_fp_lookup.h
diff options
context:
space:
mode:
authorPiotr Bronowski <piotrx.bronowski@intel.com>2022-09-20 14:44:36 +0000
committerFan Zhang <royzhang1980@hotmail.com>2022-09-21 15:11:54 +0000
commit06abf235269558fe75d72019a437337b24d7199e (patch)
treef1827b0781e2821e5ceed55117f21afa428180b2 /src/vnet/ipsec/ipsec_spd_fp_lookup.h
parenta2a7a4031be4896529cce591c26e8cebe8ca22ec (diff)
ipsec: introduce fast path ipv6 inbound matching
This patch introduces fast path matching for inbound traffic ipv6. Fast path uses bihash tables in order to find matching policy. Adding and removing policies in fast path is much faster than in current implementation. It is still new feature and further work needs and can be done in order to improve the perfromance. Type: feature Change-Id: Iaef6638033666ad6eb028ffe0c8a4f4374451753 Signed-off-by: Piotr Bronowski <piotrx.bronowski@intel.com>
Diffstat (limited to 'src/vnet/ipsec/ipsec_spd_fp_lookup.h')
-rw-r--r--src/vnet/ipsec/ipsec_spd_fp_lookup.h114
1 files changed, 103 insertions, 11 deletions
diff --git a/src/vnet/ipsec/ipsec_spd_fp_lookup.h b/src/vnet/ipsec/ipsec_spd_fp_lookup.h
index e4ef194d68d..a372ac77a50 100644
--- a/src/vnet/ipsec/ipsec_spd_fp_lookup.h
+++ b/src/vnet/ipsec/ipsec_spd_fp_lookup.h
@@ -20,9 +20,8 @@
#include <vnet/ipsec/ipsec.h>
-
static_always_inline int
-single_rule_match_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *match)
+single_rule_out_match_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *match)
{
if (PREDICT_FALSE (policy->is_ipv6 != match->is_ipv6))
return (0);
@@ -138,7 +137,98 @@ static_always_inline u32
ipsec_fp_in_ip6_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
ipsec_policy_t **policies, u32 n)
{
- return 0;
+ u32 last_priority[n];
+ u32 i = 0;
+ u32 counter = 0;
+ ipsec_fp_mask_type_entry_t *mte;
+ ipsec_fp_mask_id_t *mti;
+ ipsec_fp_5tuple_t *match = tuples;
+ ipsec_policy_t *policy;
+ u32 n_left = n;
+ clib_bihash_kv_40_8_t kv;
+ /* result of the lookup */
+ clib_bihash_kv_40_8_t result;
+ ipsec_fp_lookup_value_t *result_val =
+ (ipsec_fp_lookup_value_t *) &result.value;
+ u64 *pkey, *pmatch, *pmask;
+ ipsec_main_t *im = &ipsec_main;
+ ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
+ ipsec_fp_mask_id_t *mask_type_ids = pspd_fp->fp_mask_ids[match->action];
+ clib_bihash_40_8_t *bihash_table = pool_elt_at_index (
+ im->fp_ip6_lookup_hashes_pool, pspd_fp->ip6_in_lookup_hash_idx);
+
+ /* clear the list of matched policies pointers */
+ clib_memset (policies, 0, n * sizeof (*policies));
+ clib_memset (last_priority, 0, n * sizeof (u32));
+ n_left = n;
+ while (n_left)
+ {
+ vec_foreach (mti, mask_type_ids)
+ {
+ mte = im->fp_mask_types + mti->mask_type_idx;
+ if (mte->mask.action == 0)
+ continue;
+
+ pmatch = (u64 *) match->kv_40_8.key;
+ pmask = (u64 *) mte->mask.kv_40_8.key;
+ pkey = (u64 *) kv.key;
+
+ *pkey++ = *pmatch++ & *pmask++;
+ *pkey++ = *pmatch++ & *pmask++;
+ *pkey++ = *pmatch++ & *pmask++;
+ *pkey++ = *pmatch++ & *pmask++;
+ *pkey = *pmatch & *pmask;
+
+ int res =
+ clib_bihash_search_inline_2_40_8 (bihash_table, &kv, &result);
+ /* lookup the hash by each packet in the burst for this mask. */
+
+ if (res == 0)
+ {
+ /* There is a hit in the hash table. */
+ /* Find the policy with highest priority. */
+ /* Store the lookup results in a dedicated array. */
+
+ if (vec_len (result_val->fp_policies_ids) > 1)
+ {
+ u32 *policy_id;
+ vec_foreach (policy_id, result_val->fp_policies_ids)
+ {
+ policy = im->policies + *policy_id;
+
+ if ((last_priority[i] < policy->priority) &&
+ (single_rule_in_match_5tuple (policy, match)))
+ {
+ last_priority[i] = policy->priority;
+ if (policies[i] == 0)
+ counter++;
+ policies[i] = policy;
+ }
+ }
+ }
+ else
+ {
+ u32 *policy_id;
+ ASSERT (vec_len (result_val->fp_policies_ids) == 1);
+ policy_id = result_val->fp_policies_ids;
+ policy = im->policies + *policy_id;
+ if ((last_priority[i] < policy->priority) &&
+ (single_rule_in_match_5tuple (policy, match)))
+ {
+ last_priority[i] = policy->priority;
+ if (policies[i] == 0)
+ counter++;
+ policies[i] = policy;
+ }
+ }
+ }
+ }
+
+ i++;
+ n_left--;
+ match++;
+ }
+ return counter;
}
static_always_inline u32
@@ -253,7 +343,7 @@ ipsec_fp_in_policy_match_n (void *spd_fp, u8 is_ipv6,
}
static_always_inline u32
-ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
+ipsec_fp_out_ip6_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
ipsec_policy_t **policies, u32 *ids, u32 n)
{
@@ -288,6 +378,8 @@ ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
vec_foreach (mti, mask_type_ids)
{
mte = im->fp_mask_types + mti->mask_type_idx;
+ if (mte->mask.action != 0)
+ continue;
pmatch = (u64 *) match->kv_40_8.key;
pmask = (u64 *) mte->mask.kv_40_8.key;
@@ -316,7 +408,7 @@ ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
{
policy = im->policies + *policy_id;
- if (single_rule_match_5tuple (policy, match))
+ if (single_rule_out_match_5tuple (policy, match))
{
if (last_priority[i] < policy->priority)
{
@@ -335,7 +427,7 @@ ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
ASSERT (vec_len (result_val->fp_policies_ids) == 1);
policy_id = result_val->fp_policies_ids;
policy = im->policies + *policy_id;
- if (single_rule_match_5tuple (policy, match))
+ if (single_rule_out_match_5tuple (policy, match))
{
if (last_priority[i] < policy->priority)
{
@@ -357,7 +449,7 @@ ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
}
static_always_inline u32
-ipsec_fp_ip4_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
+ipsec_fp_out_ip4_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
ipsec_policy_t **policies, u32 *ids, u32 n)
{
@@ -420,7 +512,7 @@ ipsec_fp_ip4_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
policy = im->policies + *policy_id;
if ((last_priority[i] < policy->priority) &&
- (single_rule_match_5tuple (policy, match)))
+ (single_rule_out_match_5tuple (policy, match)))
{
last_priority[i] = policy->priority;
if (policies[i] == 0)
@@ -437,7 +529,7 @@ ipsec_fp_ip4_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
policy_id = result_val->fp_policies_ids;
policy = im->policies + *policy_id;
if ((last_priority[i] < policy->priority) &&
- (single_rule_match_5tuple (policy, match)))
+ (single_rule_out_match_5tuple (policy, match)))
{
last_priority[i] = policy->priority;
if (policies[i] == 0)
@@ -469,9 +561,9 @@ ipsec_fp_out_policy_match_n (void *spd_fp, u8 is_ipv6,
{
if (is_ipv6)
- return ipsec_fp_ip6_out_policy_match_n (spd_fp, tuples, policies, ids, n);
+ return ipsec_fp_out_ip6_policy_match_n (spd_fp, tuples, policies, ids, n);
else
- return ipsec_fp_ip4_out_policy_match_n (spd_fp, tuples, policies, ids, n);
+ return ipsec_fp_out_ip4_policy_match_n (spd_fp, tuples, policies, ids, n);
}
#endif /* !IPSEC_SPD_FP_LOOKUP_H */