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_IP6_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->kv_40_8.key;
144 pmask = (u64 *) mte->mask.kv_40_8.key;
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;
153 int res = clib_bihash_search_inline_2_40_8 (
154 &pspd_fp->fp_ip6_lookup_hash, &kv, &result);
155 /* lookup the hash by each packet in the burst for this mask. */
159 /* There is a hit in the hash table. */
160 /* Find the policy with highest priority. */
161 /* Store the lookup results in a dedicated array. */
163 if (vec_len (result_val->fp_policies_ids) > 1)
166 vec_foreach (policy_id, result_val->fp_policies_ids)
168 policy = im->policies + *policy_id;
170 if (single_rule_match_5tuple (policy, match))
172 if (last_priority[i] < policy->priority)
174 last_priority[i] = policy->priority;
175 if (policies[i] == 0)
177 policies[i] = policy;
186 ASSERT (vec_len (result_val->fp_policies_ids) == 1);
187 policy_id = result_val->fp_policies_ids;
188 policy = im->policies + *policy_id;
189 if (single_rule_match_5tuple (policy, match))
191 if (last_priority[i] < policy->priority)
193 last_priority[i] = policy->priority;
194 if (policies[i] == 0)
196 policies[i] = policy;
210 static_always_inline u32
211 ipsec_fp_ip4_out_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
212 ipsec_policy_t **policies, u32 *ids, u32 n)
215 u32 last_priority[n];
218 ipsec_fp_mask_type_entry_t *mte;
220 ipsec_fp_5tuple_t *match = tuples;
221 ipsec_policy_t *policy;
224 clib_bihash_kv_16_8_t kv;
225 /* result of the lookup */
226 clib_bihash_kv_16_8_t result;
227 ipsec_fp_lookup_value_t *result_val =
228 (ipsec_fp_lookup_value_t *) &result.value;
229 u64 *pkey, *pmatch, *pmask;
230 ipsec_main_t *im = &ipsec_main;
231 ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
232 u32 *mask_type_ids = pspd_fp->fp_mask_types[IPSEC_SPD_POLICY_IP4_OUTBOUND];
234 /* clear the list of matched policies pointers */
235 clib_memset (policies, 0, n * sizeof (*policies));
236 clib_memset (last_priority, 0, n * sizeof (u32));
240 vec_foreach (mti, mask_type_ids)
242 mte = im->fp_mask_types + *mti;
244 pmatch = (u64 *) match->kv_16_8.key;
245 pmask = (u64 *) mte->mask.kv_16_8.key;
246 pkey = (u64 *) kv.key;
248 *pkey++ = *pmatch++ & *pmask++;
249 *pkey = *pmatch & *pmask;
251 int res = clib_bihash_search_inline_2_16_8 (
252 &pspd_fp->fp_ip4_lookup_hash, &kv, &result);
253 /* lookup the hash by each packet in the burst for this mask. */
257 /* There is a hit in the hash table. */
258 /* Find the policy with highest priority. */
259 /* Store the lookup results in a dedicated array. */
261 if (vec_len (result_val->fp_policies_ids) > 1)
264 vec_foreach (policy_id, result_val->fp_policies_ids)
266 policy = im->policies + *policy_id;
268 if ((last_priority[i] < policy->priority) &&
269 (single_rule_match_5tuple (policy, match)))
271 last_priority[i] = policy->priority;
272 if (policies[i] == 0)
274 policies[i] = policy;
282 ASSERT (vec_len (result_val->fp_policies_ids) == 1);
283 policy_id = result_val->fp_policies_ids;
284 policy = im->policies + *policy_id;
285 if ((last_priority[i] < policy->priority) &&
286 (single_rule_match_5tuple (policy, match)))
288 last_priority[i] = policy->priority;
289 if (policies[i] == 0)
291 policies[i] = policy;
306 * @brief function handler to perform lookup in fastpath SPD
307 * for outbound traffic burst of n packets
308 * returns number of successfully matched policies
311 static_always_inline u32
312 ipsec_fp_out_policy_match_n (void *spd_fp, u8 is_ipv6,
313 ipsec_fp_5tuple_t *tuples,
314 ipsec_policy_t **policies, u32 *ids, u32 n)
318 return ipsec_fp_ip6_out_policy_match_n (spd_fp, tuples, policies, ids, n);
320 return ipsec_fp_ip4_out_policy_match_n (spd_fp, tuples, policies, ids, n);
323 #endif /* !IPSEC_SPD_FP_LOOKUP_H */