2 *------------------------------------------------------------------
3 * Copyright (c) 2022 Intel and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
18 #ifndef IPSEC_SPD_FP_LOOKUP_H
19 #define IPSEC_SPD_FP_LOOKUP_H
21 #include <vnet/ipsec/ipsec.h>
24 * @brief function handler to perform lookup in fastpath SPD
25 * for inbound traffic burst of n packets
29 ipsec_fp_in_policy_match_n (void *spd_fp, u8 is_ipv6,
30 ipsec_fp_5tuple_t *tuples,
31 ipsec_policy_t **policies, u32 *policy_ids, u32 n)
36 static_always_inline int
37 single_rule_match_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *match)
39 if (PREDICT_FALSE (policy->is_ipv6 != match->is_ipv6))
42 if (PREDICT_FALSE (policy->protocol != IPSEC_POLICY_PROTOCOL_ANY &&
43 (policy->protocol != match->protocol)))
49 clib_net_to_host_u32 (match->laddr.as_u32) <
50 clib_net_to_host_u32 (policy->laddr.start.ip4.as_u32)))
53 if (PREDICT_FALSE (clib_net_to_host_u32 (match->laddr.as_u32) >
54 clib_net_to_host_u32 (policy->laddr.stop.ip4.as_u32)))
58 clib_net_to_host_u32 (match->raddr.as_u32) <
59 clib_net_to_host_u32 (policy->raddr.start.ip4.as_u32)))
62 if (PREDICT_FALSE (clib_net_to_host_u32 (match->raddr.as_u32) >
63 clib_net_to_host_u32 (policy->raddr.stop.ip4.as_u32)))
69 if (ip6_address_compare (&match->ip6_laddr, &policy->laddr.start.ip6) <
73 if (ip6_address_compare (&policy->laddr.stop.ip6, &match->ip6_laddr) < 0)
77 if (ip6_address_compare (&match->ip6_raddr, &policy->raddr.start.ip6) <
82 if (ip6_address_compare (&policy->raddr.stop.ip6, &match->ip6_raddr) < 0)
87 if (PREDICT_FALSE ((match->protocol != IP_PROTOCOL_TCP) &&
88 (match->protocol != IP_PROTOCOL_UDP) &&
89 (match->protocol != IP_PROTOCOL_SCTP)))
94 if (match->lport < policy->lport.start)
97 if (match->lport > policy->lport.stop)
100 if (match->rport < policy->rport.start)
103 if (match->rport > policy->rport.stop)
109 static_always_inline u32
110 ipsec_fp_ip6_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
111 ipsec_policy_t **policies, u32 *ids, u32 n)
114 u32 last_priority[n];
117 ipsec_fp_mask_type_entry_t *mte;
119 ipsec_fp_5tuple_t *match = tuples;
120 ipsec_policy_t *policy;
123 clib_bihash_kv_40_8_t kv;
124 /* result of the lookup */
125 clib_bihash_kv_40_8_t result;
126 ipsec_fp_lookup_value_t *result_val =
127 (ipsec_fp_lookup_value_t *) &result.value;
128 u64 *pkey, *pmatch, *pmask;
129 ipsec_main_t *im = &ipsec_main;
130 ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
131 u32 *mask_type_ids = pspd_fp->fp_mask_types[IPSEC_SPD_POLICY_IP4_OUTBOUND];
133 /*clear the list of matched policies pointers */
134 clib_memset (policies, 0, n * sizeof (*policies));
135 clib_memset (last_priority, 0, n * sizeof (u32));
139 vec_foreach (mti, mask_type_ids)
141 mte = im->fp_mask_types + *mti;
143 pmatch = (u64 *) match;
144 pmask = (u64 *) &mte->mask;
145 pkey = (u64 *) kv.key;
147 *pkey++ = *pmatch++ & *pmask++;
148 *pkey++ = *pmatch++ & *pmask++;
149 *pkey++ = *pmatch++ & *pmask++;
150 *pkey++ = *pmatch++ & *pmask++;
151 *pkey++ = *pmatch++ & *pmask++;
152 *pkey++ = *pmatch++ & *pmask++;
154 int res = clib_bihash_search_inline_2_40_8 (
155 &pspd_fp->fp_ip6_lookup_hash, &kv, &result);
156 /* lookup the hash by each packet in the burst for this mask. */
160 /* There is a hit in the hash table. */
161 /* Find the policy with highest priority. */
162 /* Store the lookup results in a dedicated array. */
164 if (vec_len (result_val->fp_policies_ids) > 1)
167 vec_foreach (policy_id, result_val->fp_policies_ids)
169 policy = im->policies + *policy_id;
171 if (single_rule_match_5tuple (policy, match))
173 if (last_priority[i] < policy->priority)
175 last_priority[i] = policy->priority;
176 if (policies[i] == 0)
178 policies[i] = policy;
187 ASSERT (vec_len (result_val->fp_policies_ids) == 1);
188 policy_id = result_val->fp_policies_ids;
189 policy = im->policies + *policy_id;
190 if (single_rule_match_5tuple (policy, match))
192 if (last_priority[i] < policy->priority)
194 last_priority[i] = policy->priority;
195 if (policies[i] == 0)
197 policies[i] = policy;
211 static_always_inline u32
212 ipsec_fp_ip4_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
213 ipsec_policy_t **policies, u32 *ids, u32 n)
216 u32 last_priority[n];
219 ipsec_fp_mask_type_entry_t *mte;
221 ipsec_fp_5tuple_t *match = tuples;
222 ipsec_policy_t *policy;
225 clib_bihash_kv_16_8_t kv;
226 /* result of the lookup */
227 clib_bihash_kv_16_8_t result;
228 ipsec_fp_lookup_value_t *result_val =
229 (ipsec_fp_lookup_value_t *) &result.value;
230 u64 *pkey, *pmatch, *pmask;
231 ipsec_main_t *im = &ipsec_main;
232 ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
233 u32 *mask_type_ids = pspd_fp->fp_mask_types[IPSEC_SPD_POLICY_IP4_OUTBOUND];
235 /* clear the list of matched policies pointers */
236 clib_memset (policies, 0, n * sizeof (*policies));
237 clib_memset (last_priority, 0, n * sizeof (u32));
241 vec_foreach (mti, mask_type_ids)
243 mte = im->fp_mask_types + *mti;
245 pmatch = (u64 *) &match->laddr;
246 pmask = (u64 *) &mte->mask.laddr;
247 pkey = (u64 *) kv.key;
249 *pkey++ = *pmatch++ & *pmask++;
250 *pkey++ = *pmatch++ & *pmask++;
252 int res = clib_bihash_search_inline_2_16_8 (
253 &pspd_fp->fp_ip4_lookup_hash, &kv, &result);
254 /* lookup the hash by each packet in the burst for this mask. */
258 /* There is a hit in the hash table. */
259 /* Find the policy with highest priority. */
260 /* Store the lookup results in a dedicated array. */
262 if (vec_len (result_val->fp_policies_ids) > 1)
265 vec_foreach (policy_id, result_val->fp_policies_ids)
267 policy = im->policies + *policy_id;
269 if ((last_priority[i] < policy->priority) &&
270 (single_rule_match_5tuple (policy, match)))
272 last_priority[i] = policy->priority;
273 if (policies[i] == 0)
275 policies[i] = policy;
283 ASSERT (vec_len (result_val->fp_policies_ids) == 1);
284 policy_id = result_val->fp_policies_ids;
285 policy = im->policies + *policy_id;
286 if ((last_priority[i] < policy->priority) &&
287 (single_rule_match_5tuple (policy, match)))
289 last_priority[i] = policy->priority;
290 if (policies[i] == 0)
292 policies[i] = policy;
307 * @brief function handler to perform lookup in fastpath SPD
308 * for outbound traffic burst of n packets
309 * returns number of successfully matched policies
312 static_always_inline u32
313 ipsec_fp_out_policy_match_n (void *spd_fp, u8 is_ipv6,
314 ipsec_fp_5tuple_t *tuples,
315 ipsec_policy_t **policies, u32 *ids, u32 n)
319 return ipsec_fp_ip6_out_policy_match_n (spd_fp, tuples, policies, ids, n);
321 return ipsec_fp_ip4_out_policy_match_n (spd_fp, tuples, policies, ids, n);
324 #endif /* !IPSEC_SPD_FP_LOOKUP_H */