ipsec: fast path outbound policy matching implementation for ipv6
[vpp.git] / src / vnet / ipsec / ipsec_spd_policy.h
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef __IPSEC_SPD_POLICY_H__
16 #define __IPSEC_SPD_POLICY_H__
17
18 #include <vppinfra/bihash_40_8.h>
19 #include <vppinfra/bihash_16_8.h>
20 #include <vnet/ipsec/ipsec_spd.h>
21 /**
22  * calculated as max number of flows (2^10) divided by KVP_PER_PAGE (4)
23  */
24 #define IPSEC_FP_HASH_LOOKUP_HASH_BUCKETS (1 << 8)
25
26 #define IPSEC_POLICY_PROTOCOL_ANY IP_PROTOCOL_RESERVED
27
28 /**
29  * This number is calculated as ceil power of 2 for the number
30  * sizeof(clib_bihash_kv_16_8_t)=24 * BIHASH_KVP_PER_PAGE=4 * COLLISIONS_NO=8
31  *
32  */
33
34 #define IPSEC_FP_IP4_HASH_MEM_PER_BUCKET 1024
35
36 /**
37  * This number is calculated as ceil power of 2 for the number
38  * sizeof(clib_bihash_kv_40_8_t)=48 * BIHASH_KVP_PER_PAGE=4 * COLLISIONS_NO=8
39  *
40  */
41 #define IPSEC_FP_IP6_HASH_MEM_PER_BUCKET 2048
42
43 #define foreach_ipsec_policy_action \
44   _ (0, BYPASS, "bypass")           \
45   _ (1, DISCARD, "discard")         \
46   _ (2, RESOLVE, "resolve")         \
47   _ (3, PROTECT, "protect")
48
49 typedef enum
50 {
51 #define _(v, f, s) IPSEC_POLICY_ACTION_##f = v,
52   foreach_ipsec_policy_action
53 #undef _
54 } ipsec_policy_action_t;
55
56 #define IPSEC_POLICY_N_ACTION (IPSEC_POLICY_ACTION_PROTECT + 1)
57
58 typedef struct
59 {
60   ip46_address_t start, stop;
61 } ip46_address_range_t;
62
63 typedef struct
64 {
65   u16 start, stop;
66 } port_range_t;
67
68 /**
69  * @brief
70  * Policy packet & bytes counters
71  */
72 extern vlib_combined_counter_main_t ipsec_spd_policy_counters;
73
74 /**
75  * @brief A Secruity Policy. An entry in an SPD
76  */
77 typedef struct ipsec_policy_t_
78 {
79   u32 id;
80   i32 priority;
81
82   // the type of policy
83   ipsec_spd_policy_type_t type;
84
85   // Selector
86   u8 is_ipv6;
87   ip46_address_range_t laddr;
88   ip46_address_range_t raddr;
89   u8 protocol;
90   port_range_t lport;
91   port_range_t rport;
92
93   // Policy
94   ipsec_policy_action_t policy;
95   u32 sa_id;
96   u32 sa_index;
97   u32 fp_mask_type_id;
98 } ipsec_policy_t;
99
100 /**
101  * @brief Add/Delete a SPD
102  */
103 extern int ipsec_add_del_policy (vlib_main_t * vm,
104                                  ipsec_policy_t * policy,
105                                  int is_add, u32 * stat_index);
106
107 extern u8 *format_ipsec_policy (u8 * s, va_list * args);
108 extern u8 *format_ipsec_policy_action (u8 * s, va_list * args);
109 extern uword unformat_ipsec_policy_action (unformat_input_t * input,
110                                            va_list * args);
111
112
113 extern int ipsec_policy_mk_type (bool is_outbound,
114                                  bool is_ipv6,
115                                  ipsec_policy_action_t action,
116                                  ipsec_spd_policy_type_t * type);
117
118 /* A 5-tuple used to calculate the bihash entry  */
119 typedef union
120 {
121   struct
122   {
123     union
124     {
125       struct
126       {
127         u32 l3_zero_pad[6];
128         ip4_address_t laddr;
129         ip4_address_t raddr;
130       };
131       struct
132       {
133         ip6_address_t ip6_laddr;
134         ip6_address_t ip6_raddr;
135       };
136     };
137
138     u16 lport;
139     u16 rport;
140     u16 protocol;
141     u16 is_ipv6;
142   };
143   /* for ipv6 */
144   clib_bihash_kv_40_8_t kv_40_8;
145   /* for ipv4 */
146   struct
147   {
148     u64 padding_for_kv_16_8[3];
149     clib_bihash_kv_16_8_t kv_16_8;
150   };
151 } ipsec_fp_5tuple_t;
152
153 /*
154  * An element describing a particular policy  mask,
155  * and refcount of policies with same mask.
156  */
157 typedef struct
158 {
159   /** Required for pool_get_aligned */
160   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
161   ipsec_fp_5tuple_t mask;
162   u32 refcount; /* counts how many policies use this mask */
163 } ipsec_fp_mask_type_entry_t;
164
165 /*
166  * Bihash lookup value,
167  * contains an unordered vector of policies indices in policy pool.
168  */
169 typedef union
170 {
171   u64 as_u64;
172   struct
173   {
174     u32 *fp_policies_ids;
175   };
176 } ipsec_fp_lookup_value_t;
177
178 /**
179  *  @brief add or delete a fast path policy
180  */
181 int ipsec_fp_add_del_policy (void *fp_spd, ipsec_policy_t *policy, int is_add,
182                              u32 *stat_index);
183
184 static_always_inline int
185 ipsec_policy_is_equal (ipsec_policy_t *p1, ipsec_policy_t *p2)
186 {
187   if (p1->priority != p2->priority)
188     return 0;
189   if (p1->type != p2->type)
190     return (0);
191   if (p1->policy != p2->policy)
192     return (0);
193   if (p1->sa_id != p2->sa_id)
194     return (0);
195   if (p1->protocol != p2->protocol)
196     return (0);
197   if (p1->lport.start != p2->lport.start)
198     return (0);
199   if (p1->lport.stop != p2->lport.stop)
200     return (0);
201   if (p1->rport.start != p2->rport.start)
202     return (0);
203   if (p1->rport.stop != p2->rport.stop)
204     return (0);
205   if (p1->is_ipv6 != p2->is_ipv6)
206     return (0);
207   if (p2->is_ipv6)
208     {
209       if (p1->laddr.start.ip6.as_u64[0] != p2->laddr.start.ip6.as_u64[0])
210         return (0);
211       if (p1->laddr.start.ip6.as_u64[1] != p2->laddr.start.ip6.as_u64[1])
212         return (0);
213       if (p1->laddr.stop.ip6.as_u64[0] != p2->laddr.stop.ip6.as_u64[0])
214         return (0);
215       if (p1->laddr.stop.ip6.as_u64[1] != p2->laddr.stop.ip6.as_u64[1])
216         return (0);
217       if (p1->raddr.start.ip6.as_u64[0] != p2->raddr.start.ip6.as_u64[0])
218         return (0);
219       if (p1->raddr.start.ip6.as_u64[1] != p2->raddr.start.ip6.as_u64[1])
220         return (0);
221       if (p1->raddr.stop.ip6.as_u64[0] != p2->raddr.stop.ip6.as_u64[0])
222         return (0);
223       if (p1->laddr.stop.ip6.as_u64[1] != p2->laddr.stop.ip6.as_u64[1])
224         return (0);
225     }
226   else
227     {
228       if (p1->laddr.start.ip4.as_u32 != p2->laddr.start.ip4.as_u32)
229         return (0);
230       if (p1->laddr.stop.ip4.as_u32 != p2->laddr.stop.ip4.as_u32)
231         return (0);
232       if (p1->raddr.start.ip4.as_u32 != p2->raddr.start.ip4.as_u32)
233         return (0);
234       if (p1->raddr.stop.ip4.as_u32 != p2->raddr.stop.ip4.as_u32)
235         return (0);
236     }
237   return (1);
238 }
239
240 #endif /* __IPSEC_SPD_POLICY_H__ */
241
242 /*
243  * fd.io coding-style-patch-verification: ON
244  *
245  * Local Variables:
246  * eval: (c-set-style "gnu")
247  * End:
248  */