blob: 2184bffe6fc8f72889141bf6f006b985cc46ab31 [file] [log] [blame]
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +05301/*
2 **************************************************************************
ratheesh kannoth92467812018-06-25 17:47:36 +05303 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17/*
18 * nss_ipsec.c
19 * NSS IPsec APIs
20 */
21
22#include "nss_tx_rx_common.h"
Murat Sezginea1a4352014-04-15 19:09:51 -070023#include "nss_ipsec.h"
Amit Guptacbab9f42018-04-13 16:11:25 +053024#include "nss_ppe.h"
Sachin Shashidhar19accfa2018-08-06 13:35:28 -070025#include "nss_ipsec_log.h"
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053026
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053027#if defined(NSS_HAL_IPQ806X_SUPPORT)
28#define NSS_IPSEC_ENCAP_INTERFACE_NUM NSS_IPSEC_ENCAP_IF_NUMBER
29#define NSS_IPSEC_DECAP_INTERFACE_NUM NSS_IPSEC_DECAP_IF_NUMBER
30#define NSS_IPSEC_DATA_INTERFACE_NUM NSS_C2C_TX_INTERFACE
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053031
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053032#elif defined(NSS_HAL_FSM9010_SUPPORT)
33#define NSS_IPSEC_ENCAP_INTERFACE_NUM NSS_IPSEC_ENCAP_IF_NUMBER
34#define NSS_IPSEC_DECAP_INTERFACE_NUM NSS_IPSEC_DECAP_IF_NUMBER
ratheesh kannoth92467812018-06-25 17:47:36 +053035#define NSS_IPSEC_DATA_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053036
37#elif defined(NSS_HAL_IPQ807x_SUPPORT)
ratheesh kannoth92467812018-06-25 17:47:36 +053038#define NSS_IPSEC_ENCAP_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
39#define NSS_IPSEC_DECAP_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
40#define NSS_IPSEC_DATA_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053041
Suman Ghosh3f940232018-08-17 20:43:03 +053042#elif defined(NSS_HAL_IPQ60XX_SUPPORT)
ratheesh kannoth92467812018-06-25 17:47:36 +053043#define NSS_IPSEC_ENCAP_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
44#define NSS_IPSEC_DECAP_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
45#define NSS_IPSEC_DATA_INTERFACE_NUM NSS_IPSEC_CMN_INTERFACE
Suman Ghosh3f940232018-08-17 20:43:03 +053046
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053047#else
48#define NSS_IPSEC_ENCAP_INTERFACE_NUM -1
49#define NSS_IPSEC_DECAP_INTERFACE_NUM -1
50#define NSS_IPSEC_DATA_INTERFACE_NUM -1
51
52#endif
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053053
54/*
Vijay Vigneshanb809f422018-04-04 15:04:35 +053055 * Amount time the synchronous message should wait for response from
56 * NSS before the timeout happens. After the timeout the message
57 * response even if it arrives has to be discarded. Typically, the
58 * time needs to be selected based on the worst case time in case of
59 * peak throughput between host & NSS.
60 */
61#define NSS_IPSEC_TX_TIMEO_TICKS msecs_to_jiffies(3000) /* 3 Seconds */
62
63/*
64 * Private data structure to hold state for
65 * the ipsec specific NSS interaction
66 */
67struct nss_ipsec_pvt {
68 struct semaphore sem; /* used for synchronizing 'tx_msg_sync' */
69 struct completion complete; /* completion callback */
70 atomic_t resp; /* Response error type */
71} nss_ipsec;
72
73/*
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053074 * nss_ipsec_get_msg_ctx()
75 * return ipsec message context assoicated with the callback
76 *
77 * Note: certain SOC the decap interface specially programmed
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053078 */
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053079static inline nss_ptr_t nss_ipsec_get_msg_ctx(struct nss_ctx_instance *nss_ctx, uint32_t interface_num)
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053080{
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053081 struct nss_top_instance *nss_top = nss_ctx->nss_top;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053082
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053083 /*
84 * the encap is primary interface
85 */
Sourav Poddareb8cb652017-05-18 12:02:18 +053086 if (interface_num == NSS_IPSEC_ENCAP_INTERFACE_NUM)
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053087 return (nss_ptr_t)nss_top->ipsec_encap_ctx;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053088
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053089 return (nss_ptr_t)nss_top->ipsec_decap_ctx;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053090}
91
92/*
93 * nss_ipsec_get_msg_callback()
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053094 * this gets the message callback handler
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053095 */
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053096static inline nss_ptr_t nss_ipsec_get_msg_callback(struct nss_ctx_instance *nss_ctx, uint32_t interface_num)
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053097{
Sourav Poddarbf8b50c2017-02-15 12:44:44 +053098 struct nss_top_instance *nss_top = nss_ctx->nss_top;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +053099
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530100 /*
101 * the encap is primary interface
102 */
Sourav Poddareb8cb652017-05-18 12:02:18 +0530103 if (interface_num == NSS_IPSEC_ENCAP_INTERFACE_NUM)
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530104 return (nss_ptr_t)nss_top->ipsec_encap_callback;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530105
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530106 return (nss_ptr_t)nss_top->ipsec_decap_callback;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530107}
108
109/*
110 **********************************
111 Rx APIs
112 **********************************
113 */
114
115/*
116 * nss_ipsec_msg_handler()
117 * this handles all the IPsec events and responses
118 */
119static void nss_ipsec_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app_data __attribute((unused)))
120{
121 struct nss_ipsec_msg *nim = (struct nss_ipsec_msg *)ncm;
122 nss_ipsec_msg_callback_t cb = NULL;
123 uint32_t if_num = ncm->interface;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530124
125 /*
Sachin Shashidhar19accfa2018-08-06 13:35:28 -0700126 * Trace messages.
127 */
128 nss_ipsec_log_rx_msg(nim);
129
130 /*
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530131 * Sanity check the message type
132 */
133 if (ncm->type > NSS_IPSEC_MSG_TYPE_MAX) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530134 nss_warning("%p: rx message type out of range: %d", nss_ctx, ncm->type);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530135 return;
136 }
137
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800138 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ipsec_msg)) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530139 nss_warning("%p: rx message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530140 return;
141 }
142
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530143 BUG_ON((if_num != NSS_IPSEC_ENCAP_INTERFACE_NUM) && (if_num != NSS_IPSEC_DECAP_INTERFACE_NUM));
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530144
145 if (ncm->response == NSS_CMN_RESPONSE_LAST) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530146 nss_warning("%p: rx message response for if %d, type %d, is invalid: %d", nss_ctx, ncm->interface,
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530147 ncm->type, ncm->response);
148 return;
149 }
150
151 /*
152 * Is this a notification? if, yes then fill up the callback and app_data from
153 * locally stored state
154 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530155 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530156 ncm->cb = nss_ipsec_get_msg_callback(nss_ctx, if_num);
157 ncm->app_data = nss_ipsec_get_msg_ctx(nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530158 }
159
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530160 nss_core_log_msg_failures(nss_ctx, ncm);
161
162 /*
163 * load, test & call
164 */
165 cb = (nss_ipsec_msg_callback_t)ncm->cb;
166 if (unlikely(!cb)) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530167 nss_trace("%p: rx handler has been unregistered for i/f: %d", nss_ctx, ncm->interface);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530168 return;
169 }
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530170
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530171 cb((void *)ncm->app_data, nim);
172}
173
174/*
175 **********************************
176 Tx APIs
177 **********************************
178 */
179
180/*
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530181 * nss_ipsec_callback()
182 * Callback to handle the completion of NSS->HLOS messages.
183 */
184static void nss_ipsec_callback(void *app_data, struct nss_ipsec_msg *nim)
185{
186 struct nss_cmn_msg *ncm = &nim->cm;
187
188 /*
189 * This callback is for synchronous operation. The caller sends its
190 * response pointer which needs to be loaded with the response
191 * data arriving from the NSS
192 */
193 atomic_t *resp = (atomic_t *)app_data;
194
195 if (ncm->response == NSS_CMN_RESPONSE_ACK) {
196 atomic_set(resp, NSS_IPSEC_ERROR_TYPE_NONE);
197 complete(&nss_ipsec.complete);
198 return;
199 }
200
201 atomic_set(resp, ncm->error);
202 complete(&nss_ipsec.complete);
203}
204
205/*
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530206 * nss_ipsec_tx_msg
207 * Send ipsec rule to NSS.
208 */
209nss_tx_status_t nss_ipsec_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_ipsec_msg *msg)
210{
211 struct nss_cmn_msg *ncm = &msg->cm;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530212
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530213 nss_info("%p: message %d for if %d\n", nss_ctx, ncm->type, ncm->interface);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530214
Tanmay V Jagdalef6b2bce2017-03-03 14:31:07 +0530215 BUILD_BUG_ON(NSS_NBUF_PAYLOAD_SIZE < sizeof(struct nss_ipsec_msg));
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530216
Sachin Shashidhar19accfa2018-08-06 13:35:28 -0700217 /*
218 * Trace messages.
219 */
220 nss_ipsec_log_tx_msg(msg);
221
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530222 if ((ncm->interface != NSS_IPSEC_ENCAP_INTERFACE_NUM) && (ncm->interface != NSS_IPSEC_DECAP_INTERFACE_NUM)) {
223 nss_warning("%p: tx message request for another interface: %d", nss_ctx, ncm->interface);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530224 return NSS_TX_FAILURE;
225 }
226
227 if (ncm->type > NSS_IPSEC_MSG_TYPE_MAX) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530228 nss_warning("%p: tx message type out of range: %d", nss_ctx, ncm->type);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530229 return NSS_TX_FAILURE;
230 }
231
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530232 nss_info("msg params version:%d, interface:%d, type:%d, cb:%p, app_data:%p, len:%d\n",
Stephen Wangaed46332016-12-12 17:29:03 -0800233 ncm->version, ncm->interface, ncm->type, (void *)ncm->cb, (void *)ncm->app_data, ncm->len);
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530234
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700235 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530236}
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530237EXPORT_SYMBOL(nss_ipsec_tx_msg);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530238
239/*
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530240 * nss_ipsec_tx_msg_sync()
241 * Transmit a ipsec message to NSS firmware synchronously.
242 */
243nss_tx_status_t nss_ipsec_tx_msg_sync(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
244 enum nss_ipsec_msg_type type, uint16_t len,
245 struct nss_ipsec_msg *nim, enum nss_ipsec_error_type *resp)
246{
247 struct nss_ipsec_msg nim_local = { {0} };
248 nss_tx_status_t status;
249 int ret;
250
251 /*
252 * Length of the message should be the based on type
253 */
254 if (len > sizeof(nim_local.msg)) {
255 nss_warning("%p: (%u)Bad message length(%u) for type (%d)", nss_ctx, if_num, len, type);
256 return NSS_TX_FAILURE_TOO_LARGE;
257 }
258
259 /*
260 * Response buffer is a required for copying the response for message
261 */
262 if (!resp) {
263 nss_warning("%p: (%u)Response buffer is empty, type(%d)", nss_ctx, if_num, type);
264 return NSS_TX_FAILURE_BAD_PARAM;
265 }
266
267 /*
268 * TODO: this can be removed in future as we need to ensure that the response
269 * memory is only updated when the current outstanding request is waiting.
270 * This can be solved by introducing sequence no. in messages and only completing
271 * the message if the sequence no. matches. For now this is solved by passing
272 * a known memory nss_ipsec.resp
273 */
274 down(&nss_ipsec.sem);
275
276 /*
277 * Initializing it to a fail error type
278 */
279 atomic_set(&nss_ipsec.resp, NSS_IPSEC_ERROR_TYPE_UNHANDLED_MSG);
280
281 /*
282 * We need to copy the message content into the actual message
283 * to be sent to NSS
284 *
285 * Note: Here pass the nss_ipsec.resp as the pointer. Since, the caller
286 * provided pointer is not allocated by us and may go away when this function
287 * returns with failure. The callback is not aware of this and may try to
288 * access the pointer incorrectly potentially resulting in a crash.
289 */
290 nss_ipsec_msg_init(&nim_local, if_num, type, len, nss_ipsec_callback, &nss_ipsec.resp);
291 memcpy(&nim_local.msg, &nim->msg, len);
292
293 status = nss_ipsec_tx_msg(nss_ctx, &nim_local);
294 if (status != NSS_TX_SUCCESS) {
295 nss_warning("%p: ipsec_tx_msg failed", nss_ctx);
296 goto done;
297 }
298
299 ret = wait_for_completion_timeout(&nss_ipsec.complete, NSS_IPSEC_TX_TIMEO_TICKS);
300 if (!ret) {
301 nss_warning("%p: IPsec msg tx failed due to timeout", nss_ctx);
302 status = NSS_TX_FAILURE_NOT_ENABLED;
303 goto done;
304 }
305
306 /*
307 * Read memory barrier
308 */
309 smp_rmb();
310
311 /*
312 * Copy the response received
313 */
314 *resp = atomic_read(&nss_ipsec.resp);
315
316 /*
317 * Only in case of non-error response we will
318 * indicate success
319 */
320 if (*resp != NSS_IPSEC_ERROR_TYPE_NONE)
321 status = NSS_TX_FAILURE;
322
323done:
324 up(&nss_ipsec.sem);
325 return status;
326}
327EXPORT_SYMBOL(nss_ipsec_tx_msg_sync);
328
329/*
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530330 * nss_ipsec_tx_buf
331 * Send data packet for ipsec processing
332 */
Stephen Wang83e48752015-03-03 18:41:40 -0800333nss_tx_status_t nss_ipsec_tx_buf(struct sk_buff *skb, uint32_t if_num)
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530334{
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530335 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.ipsec_handler_id];
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530336
Stephen Wang83e48752015-03-03 18:41:40 -0800337 nss_trace("%p: IPsec If Tx packet, id:%d, data=%p", nss_ctx, if_num, skb->data);
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530338
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700339 return nss_core_send_packet(nss_ctx, skb, if_num, 0);
Radha krishna Simha Jigurud36b1e22014-09-12 15:14:52 +0530340}
341EXPORT_SYMBOL(nss_ipsec_tx_buf);
342
343/*
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530344 **********************************
345 Register APIs
346 **********************************
347 */
348
349/*
Ankit Dhanukaa0e4cae2014-05-26 16:33:10 +0530350 * nss_ipsec_notify_register()
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530351 * register message notifier for the given interface (if_num)
352 */
353struct nss_ctx_instance *nss_ipsec_notify_register(uint32_t if_num, nss_ipsec_msg_callback_t cb, void *app_data)
354{
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530355 struct nss_top_instance *nss_top = &nss_top_main;
356 uint8_t core_id = nss_top->ipsec_handler_id;
357 struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_id];
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530358
359 if (if_num >= NSS_MAX_NET_INTERFACES) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530360 nss_warning("%p: notfiy register received for invalid interface %d", nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530361 return NULL;
362 }
363
Samarjeet Banerjee940e91b2016-03-29 19:23:17 +0530364 /*
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530365 * the encap is primary interface
Samarjeet Banerjee940e91b2016-03-29 19:23:17 +0530366 */
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530367 if (if_num == NSS_IPSEC_ENCAP_INTERFACE_NUM) {
368 nss_top->ipsec_encap_callback = cb;
369 nss_top->ipsec_encap_ctx = app_data;
Samarjeet Banerjee940e91b2016-03-29 19:23:17 +0530370 return nss_ctx;
371 }
372
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530373 nss_top->ipsec_decap_callback = cb;
374 nss_top->ipsec_decap_ctx = app_data;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530375 return nss_ctx;
376}
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530377EXPORT_SYMBOL(nss_ipsec_notify_register);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530378
379/*
Ankit Dhanukaa0e4cae2014-05-26 16:33:10 +0530380 * nss_ipsec_notify_unregister()
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530381 * unregister the IPsec notifier for the given interface number (if_num)
382 */
383void nss_ipsec_notify_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
384{
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530385 struct nss_top_instance *nss_top = nss_ctx->nss_top;
386
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530387 if (if_num >= NSS_MAX_NET_INTERFACES) {
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530388 nss_warning("%p: notify unregister received for invalid interface %d", nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530389 return;
390 }
391
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530392 /*
393 * the encap is primary interface
394 */
395 if (if_num == NSS_IPSEC_ENCAP_INTERFACE_NUM) {
396 nss_top->ipsec_encap_callback = NULL;
397 nss_top->ipsec_encap_ctx = NULL;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530398 return;
399 }
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530400
401 nss_top->ipsec_decap_callback = NULL;
402 nss_top->ipsec_decap_ctx = NULL;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530403}
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530404EXPORT_SYMBOL(nss_ipsec_notify_unregister);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530405
406/*
Ankit Dhanukaa0e4cae2014-05-26 16:33:10 +0530407 * nss_ipsec_data_register()
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530408 * register a data callback routine
409 */
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800410struct nss_ctx_instance *nss_ipsec_data_register(uint32_t if_num, nss_ipsec_buf_callback_t cb, struct net_device *netdev, uint32_t features)
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530411{
Arunkumar T657c4062016-09-21 18:06:48 +0530412 struct nss_ctx_instance *nss_ctx, *nss_ctx0;
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530413
414 nss_ctx = &nss_top_main.nss[nss_top_main.ipsec_handler_id];
415
416 if ((if_num >= NSS_MAX_NET_INTERFACES) && (if_num < NSS_MAX_PHYSICAL_INTERFACES)){
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530417 nss_warning("%p: data register received for invalid interface %d", nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530418 return NULL;
419 }
420
Samarjeet Banerjee940e91b2016-03-29 19:23:17 +0530421 /*
422 * avoid multiple registeration for multiple tunnels
423 */
Stephen Wang84e0e992016-09-07 12:31:40 -0700424 if (nss_ctx->subsys_dp_register[if_num].cb) {
Samarjeet Banerjee940e91b2016-03-29 19:23:17 +0530425 return nss_ctx;
426 }
427
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700428 nss_core_register_subsys_dp(nss_ctx, if_num, cb, NULL, NULL, netdev, features);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530429
Arunkumar T657c4062016-09-21 18:06:48 +0530430 if (nss_top_main.ipsec_handler_id == 1) {
431 nss_ctx0 = &nss_top_main.nss[0];
432
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700433 nss_core_register_subsys_dp(nss_ctx0, if_num, cb, NULL, NULL, netdev, features);
Arunkumar T657c4062016-09-21 18:06:48 +0530434 }
435
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530436 return nss_ctx;
437}
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530438EXPORT_SYMBOL(nss_ipsec_data_register);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530439
440/*
Ankit Dhanukaa0e4cae2014-05-26 16:33:10 +0530441 * nss_ipsec_data_unregister()
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530442 * unregister a data callback routine
443 */
444void nss_ipsec_data_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
445{
Arunkumar T657c4062016-09-21 18:06:48 +0530446 struct nss_ctx_instance *nss_ctx0;
447
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530448 if ((if_num >= NSS_MAX_NET_INTERFACES) && (if_num < NSS_MAX_PHYSICAL_INTERFACES)){
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530449 nss_warning("%p: data unregister received for invalid interface %d", nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530450 return;
451 }
452
Arunkumar T657c4062016-09-21 18:06:48 +0530453 if (nss_top_main.ipsec_handler_id == 1) {
454 nss_ctx0 = &nss_top_main.nss[0];
455
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700456 nss_core_unregister_subsys_dp(nss_ctx0, if_num);
Arunkumar T657c4062016-09-21 18:06:48 +0530457 }
458
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700459 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530460}
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530461EXPORT_SYMBOL(nss_ipsec_data_unregister);
462
463/*
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530464 * nss_ipsec_get_encap_interface()
465 * Get the NSS interface number for encap message
Radha krishna Simha Jigurudb7ad242014-11-19 16:02:23 +0530466 */
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530467int32_t nss_ipsec_get_encap_interface(void)
Radha krishna Simha Jigurudb7ad242014-11-19 16:02:23 +0530468{
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530469 return NSS_IPSEC_ENCAP_INTERFACE_NUM;
Radha krishna Simha Jigurudb7ad242014-11-19 16:02:23 +0530470}
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530471EXPORT_SYMBOL(nss_ipsec_get_encap_interface);
472
473/*
474 * nss_ipsec_get_decap_interface()
475 * Get the NSS interface number for decap message
476 */
477int32_t nss_ipsec_get_decap_interface(void)
478{
479 return NSS_IPSEC_DECAP_INTERFACE_NUM;
480}
481EXPORT_SYMBOL(nss_ipsec_get_decap_interface);
482
483/*
484 * nss_ipsec_get_data_interface()
485 * Get the NSS interface number used for data path
486 */
487int32_t nss_ipsec_get_data_interface(void)
488{
489 return NSS_IPSEC_DATA_INTERFACE_NUM;
490}
491EXPORT_SYMBOL(nss_ipsec_get_data_interface);
Radha krishna Simha Jigurudb7ad242014-11-19 16:02:23 +0530492
493/*
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700494 * nss_ipsec_get_context()
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530495 * Get NSS context instance for IPsec handle
Samarjeet Banerjee77332312014-08-07 14:48:22 +0530496 */
497struct nss_ctx_instance *nss_ipsec_get_context(void)
498{
499 return &nss_top_main.nss[nss_top_main.ipsec_handler_id];
500}
501EXPORT_SYMBOL(nss_ipsec_get_context);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530502
503/*
Sourav Poddarbfca9432018-07-26 18:55:06 +0530504 * nss_ipsec_get_ifnum()
505 * Return IPsec interface number with coreid.
506 */
507int32_t nss_ipsec_get_ifnum(int32_t if_num)
508{
509 struct nss_ctx_instance *nss_ctx = nss_ipsec_get_context();
510
511 NSS_VERIFY_CTX_MAGIC(nss_ctx);
512 return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
513}
514EXPORT_SYMBOL(nss_ipsec_get_ifnum);
515
516/*
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530517 * nss_ipsec_ppe_port_config()
518 * Configure PPE port for IPsec inline
519 */
Vijay Vigneshan2475f412018-05-14 19:49:44 +0530520bool nss_ipsec_ppe_port_config(struct nss_ctx_instance *nss_ctx, struct net_device *netdev,
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530521 uint32_t if_num, uint32_t vsi_num)
522{
523#ifdef NSS_PPE_SUPPORTED
524 if_num = NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
525
Vijay Vigneshan2475f412018-05-14 19:49:44 +0530526 if (nss_ppe_tx_ipsec_config_msg(if_num, vsi_num, netdev->mtu, netdev->mtu) != NSS_TX_SUCCESS) {
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530527 nss_warning("%p: Failed to configure PPE IPsec port", nss_ctx);
528 return false;
529 }
530
531 return true;
532#else
533 return false;
534#endif
535}
536EXPORT_SYMBOL(nss_ipsec_ppe_port_config);
537
538/*
Vijay Vigneshan2475f412018-05-14 19:49:44 +0530539 * nss_ipsec_ppe_mtu_update()
540 * Update PPE MTU for IPsec inline
541 */
542bool nss_ipsec_ppe_mtu_update(struct nss_ctx_instance *nss_ctx, uint32_t if_num, uint16_t mtu, uint16_t mru)
543{
544#ifdef NSS_PPE_SUPPORTED
545 if_num = NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
546
547 if (nss_ppe_tx_ipsec_mtu_msg(if_num, mtu, mru) != NSS_TX_SUCCESS) {
548 nss_warning("%p: Failed to update PPE MTU for IPsec port", nss_ctx);
549 return false;
550 }
551
552 return true;
553#else
554 return false;
555#endif
556}
557EXPORT_SYMBOL(nss_ipsec_ppe_mtu_update);
558
559/*
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530560 * nss_ipsec_register_handler()
561 */
562void nss_ipsec_register_handler()
563{
564 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[nss_top_main.ipsec_handler_id];
565
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530566 BUILD_BUG_ON(NSS_IPSEC_ENCAP_INTERFACE_NUM < 0);
567 BUILD_BUG_ON(NSS_IPSEC_DECAP_INTERFACE_NUM < 0);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530568
Vijay Vigneshanb809f422018-04-04 15:04:35 +0530569 sema_init(&nss_ipsec.sem, 1);
570 init_completion(&nss_ipsec.complete);
571 atomic_set(&nss_ipsec.resp, NSS_IPSEC_ERROR_TYPE_NONE);
572
Sourav Poddarbf8b50c2017-02-15 12:44:44 +0530573 nss_ctx->nss_top->ipsec_encap_callback = NULL;
574 nss_ctx->nss_top->ipsec_decap_callback = NULL;
575
576 nss_ctx->nss_top->ipsec_encap_ctx = NULL;
577 nss_ctx->nss_top->ipsec_decap_ctx = NULL;
578
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700579 nss_core_register_handler(nss_ctx, NSS_IPSEC_ENCAP_INTERFACE_NUM, nss_ipsec_msg_handler, NULL);
580 nss_core_register_handler(nss_ctx, NSS_IPSEC_DECAP_INTERFACE_NUM, nss_ipsec_msg_handler, NULL);
Samarjeet Banerjeed99d9d02014-04-08 18:51:00 +0530581}
582
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700583/*
584 * nss_ipsec_msg_init()
585 * Initialize ipsec message.
586 */
587void nss_ipsec_msg_init(struct nss_ipsec_msg *nim, uint16_t if_num, uint32_t type, uint32_t len,
Sundarajan Srinivasan30a53d42015-01-30 10:52:08 -0800588 nss_ipsec_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700589{
590 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
591}
592EXPORT_SYMBOL(nss_ipsec_msg_init);