a94dd6821af0ca87712b3263bbbd415bca6d81b9
[vpp.git] / src / plugins / dpdk / ipsec / ipsec.h
1 /*
2  * Copyright (c) 2016 Intel 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 __DPDK_IPSEC_H__
16 #define __DPDK_IPSEC_H__
17
18 #include <vnet/vnet.h>
19
20 #undef always_inline
21 #include <rte_config.h>
22 #include <rte_crypto.h>
23 #include <rte_cryptodev.h>
24
25 #if CLIB_DEBUG > 0
26 #define always_inline static inline
27 #else
28 #define always_inline static inline __attribute__ ((__always_inline__))
29 #endif
30
31
32 #define MAX_QP_PER_LCORE 16
33
34 typedef struct
35 {
36   u32 salt;
37   u32 iv[2];
38   u32 cnt;
39 } dpdk_gcm_cnt_blk;
40
41 typedef struct
42 {
43   dpdk_gcm_cnt_blk cb;
44   union
45   {
46     u8 aad[12];
47     u8 icv[64];
48   };
49 } dpdk_cop_priv_t;
50
51 typedef struct
52 {
53   u8 cipher_algo;
54   u8 auth_algo;
55   u8 is_outbound;
56   u8 is_aead;
57 } crypto_worker_qp_key_t;
58
59 typedef struct
60 {
61   u16 dev_id;
62   u16 qp_id;
63   u16 is_outbound;
64   i16 inflights;
65   u32 bi[VLIB_FRAME_SIZE];
66   struct rte_crypto_op *cops[VLIB_FRAME_SIZE];
67   struct rte_crypto_op **free_cops;
68 } crypto_qp_data_t;
69
70 typedef struct
71 {
72   u8 qp_index;
73   void *sess;
74 } crypto_sa_session_t;
75
76 typedef struct
77 {
78   crypto_sa_session_t *sa_sess_d[2];
79   crypto_qp_data_t *qp_data;
80   uword *algo_qp_map;
81 } crypto_worker_main_t;
82
83 typedef struct
84 {
85   struct rte_mempool **sess_h_pools;
86   struct rte_mempool **sess_pools;
87   struct rte_mempool **cop_pools;
88   crypto_worker_main_t *workers_main;
89   u8 enabled;
90 } dpdk_crypto_main_t;
91
92 dpdk_crypto_main_t dpdk_crypto_main;
93
94 extern vlib_node_registration_t dpdk_crypto_input_node;
95
96 #define CRYPTO_N_FREE_COPS (VLIB_FRAME_SIZE * 3)
97
98 static_always_inline void
99 crypto_alloc_cops ()
100 {
101   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
102   u32 thread_index = vlib_get_thread_index ();
103   crypto_worker_main_t *cwm = &dcm->workers_main[thread_index];
104   unsigned socket_id = rte_socket_id ();
105   crypto_qp_data_t *qpd;
106
107   /* *INDENT-OFF* */
108   vec_foreach (qpd, cwm->qp_data)
109     {
110       u32 l = vec_len (qpd->free_cops);
111
112       if (PREDICT_FALSE (l < VLIB_FRAME_SIZE))
113         {
114           u32 n_alloc;
115
116           if (PREDICT_FALSE (!qpd->free_cops))
117             vec_alloc (qpd->free_cops, CRYPTO_N_FREE_COPS);
118
119           n_alloc = rte_crypto_op_bulk_alloc (dcm->cop_pools[socket_id],
120                                               RTE_CRYPTO_OP_TYPE_SYMMETRIC,
121                                               &qpd->free_cops[l],
122                                               CRYPTO_N_FREE_COPS - l - 1);
123
124           _vec_len (qpd->free_cops) = l + n_alloc;
125         }
126     }
127   /* *INDENT-ON* */
128 }
129
130 static_always_inline void
131 crypto_free_cop (crypto_qp_data_t * qpd, struct rte_crypto_op **cops, u32 n)
132 {
133   u32 l = vec_len (qpd->free_cops);
134
135   if (l + n >= CRYPTO_N_FREE_COPS)
136     {
137       l -= VLIB_FRAME_SIZE;
138       rte_mempool_put_bulk (cops[0]->mempool,
139                             (void **) &qpd->free_cops[l], VLIB_FRAME_SIZE);
140     }
141   clib_memcpy (&qpd->free_cops[l], cops, sizeof (*cops) * n);
142
143   _vec_len (qpd->free_cops) = l + n;
144 }
145
146 static_always_inline int
147 check_algo_is_supported (const struct rte_cryptodev_capabilities *cap,
148                          char *name)
149 {
150   struct
151   {
152     enum rte_crypto_sym_xform_type type;
153     union
154     {
155       enum rte_crypto_auth_algorithm auth;
156       enum rte_crypto_cipher_algorithm cipher;
157 #if ! DPDK_NO_AEAD
158       enum rte_crypto_aead_algorithm aead;
159 #endif
160     };
161     char *name;
162   } supported_algo[] =
163   {
164     {
165     .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher =
166         RTE_CRYPTO_CIPHER_NULL,.name = "NULL"},
167     {
168     .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher =
169         RTE_CRYPTO_CIPHER_AES_CBC,.name = "AES_CBC"},
170 #if DPDK_NO_AEAD
171     {
172     .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher =
173         RTE_CRYPTO_CIPHER_AES_GCM,.name = "AES-GCM"},
174 #else
175     {
176     .type = RTE_CRYPTO_SYM_XFORM_AEAD,.aead =
177         RTE_CRYPTO_AEAD_AES_GCM,.name = "AES-GCM"},
178 #endif
179     {
180     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
181         RTE_CRYPTO_AUTH_NULL,.name = "NULL"},
182     {
183     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
184         RTE_CRYPTO_AUTH_SHA1_HMAC,.name = "HMAC-SHA1"},
185     {
186     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
187         RTE_CRYPTO_AUTH_SHA256_HMAC,.name = "HMAC-SHA256"},
188     {
189     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
190         RTE_CRYPTO_AUTH_SHA384_HMAC,.name = "HMAC-SHA384"},
191     {
192     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
193         RTE_CRYPTO_AUTH_SHA512_HMAC,.name = "HMAC-SHA512"},
194 #if DPDK_NO_AEAD
195     {
196     .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth =
197         RTE_CRYPTO_AUTH_AES_GCM,.name = "AES-GCM"},
198 #endif
199     {
200       /* tail */
201     .type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED}
202   };
203
204   uint32_t i = 0;
205
206   if (cap->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
207     return -1;
208
209   while (supported_algo[i].type != RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED)
210     {
211       if (cap->sym.xform_type == supported_algo[i].type)
212         {
213           if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
214                cap->sym.cipher.algo == supported_algo[i].cipher) ||
215 #if ! DPDK_NO_AEAD
216               (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD &&
217                cap->sym.aead.algo == supported_algo[i].aead) ||
218 #endif
219               (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH &&
220                cap->sym.auth.algo == supported_algo[i].auth))
221             {
222               if (name)
223                 strcpy (name, supported_algo[i].name);
224               return 0;
225             }
226         }
227
228       i++;
229     }
230
231   return -1;
232 }
233
234 #endif /* __DPDK_IPSEC_H__ */
235
236 /*
237  * fd.io coding-style-patch-verification: ON
238  *
239  * Local Variables:
240  * eval: (c-set-style "gnu")
241  * End:
242  */