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