blob: 7e8ce33e80d71bc502281b18b9a4ae191be7b6a1 [file] [log] [blame]
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001/*
2 **************************************************************************
Suruchi Sumanbff35fd2019-05-16 15:42:45 +05303 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
Saurabh Misra09dddeb2014-09-30 16:38:07 -07004 * 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 /*
Yu Huang8c107082017-07-24 14:58:26 -070018 * nss_capwap.c
Saurabh Misra09dddeb2014-09-30 16:38:07 -070019 * NSS CAPWAP driver interface APIs
20 */
21#include "nss_core.h"
Saurabh Misra09dddeb2014-09-30 16:38:07 -070022#include "nss_capwap.h"
Stephen Wang1f6ad492016-01-27 23:42:06 -080023#include "nss_cmn.h"
24#include "nss_tx_rx_common.h"
Yu Huang8c107082017-07-24 14:58:26 -070025#include "nss_capwap_stats.h"
Sachin Shashidhare6babc52018-05-29 15:20:40 -070026#include "nss_capwap_log.h"
Saurabh Misra09dddeb2014-09-30 16:38:07 -070027
28/*
29 * Spinlock for protecting tunnel operations colliding with a tunnel destroy
30 */
31DEFINE_SPINLOCK(nss_capwap_spinlock);
32
33/*
34 * Array of pointer for NSS CAPWAP handles. Each handle has per-tunnel
35 * stats based on the if_num which is an index.
36 *
37 * Per CAPWAP tunnel/interface number instance.
38 */
39struct nss_capwap_handle {
40 atomic_t refcnt; /**< Reference count on the tunnel */
Saurabh Misraf4a05632015-02-27 17:49:41 -080041 uint32_t if_num; /**< Interface number */
Saurabh Misra09dddeb2014-09-30 16:38:07 -070042 uint32_t tunnel_status; /**< 0=disable, 1=enabled */
43 struct nss_ctx_instance *ctx; /**< Pointer to context */
44 nss_capwap_msg_callback_t msg_callback; /**< Msg callback */
45 void *app_data; /**< App data (argument) */
46 struct nss_capwap_tunnel_stats stats; /**< Stats per-interface number */
47};
48static struct nss_capwap_handle *nss_capwap_hdl[NSS_MAX_DYNAMIC_INTERFACES];
49
50/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -070051 * nss_capwap_verify_if_num()
52 * Verify if_num passed to us.
53 */
54static bool nss_capwap_verify_if_num(uint32_t if_num)
55{
56 if (nss_is_dynamic_interface(if_num) == false) {
57 return false;
58 }
59
Stephen Wange8b8d0d2017-02-24 17:05:22 -080060 if (nss_dynamic_interface_get_type(nss_capwap_get_ctx(), if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -070061 return false;
62 }
63
64 return true;
65}
66
67/*
68 * nss_capwap_refcnt_inc()
69 * Increments refcnt on the tunnel.
70 */
71static void nss_capwap_refcnt_inc(int32_t if_num)
72{
73 if_num = if_num - NSS_DYNAMIC_IF_START;
74 atomic_inc(&nss_capwap_hdl[if_num]->refcnt);
75 nss_assert(atomic_read(&nss_capwap_hdl[if_num]->refcnt) > 0);
76}
77
78/*
79 * nss_capwap_refcnt_dec()
80 * Decrements refcnt on the tunnel.
81 */
82static void nss_capwap_refcnt_dec(int32_t if_num)
83{
84 if_num = if_num - NSS_DYNAMIC_IF_START;
85 nss_assert(atomic_read(&nss_capwap_hdl[if_num]->refcnt) > 0);
86 atomic_dec(&nss_capwap_hdl[if_num]->refcnt);
87}
88
89/*
Saurabh Misraf4a05632015-02-27 17:49:41 -080090 * nss_capwap_refcnt()
Saurabh Misra09dddeb2014-09-30 16:38:07 -070091 * Get refcnt on the tunnel.
92 */
Saurabh Misraf4a05632015-02-27 17:49:41 -080093static uint32_t nss_capwap_refcnt(int32_t if_num)
Saurabh Misra09dddeb2014-09-30 16:38:07 -070094{
95 if_num = if_num - NSS_DYNAMIC_IF_START;
96 return atomic_read(&nss_capwap_hdl[if_num]->refcnt);
97}
98
99/*
100 * nss_capwap_set_msg_callback()
101 * This sets the message callback handler and its associated context
102 */
103static void nss_capwap_set_msg_callback(int32_t if_num, nss_capwap_msg_callback_t cb, void *app_data)
104{
105 struct nss_capwap_handle *h;
106
107 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
108 if (!h) {
109 return;
110 }
111
112 h->app_data = app_data;
113 h->msg_callback = cb;
114}
115
116/*
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700117 * nss_capwap_get_msg_callback()
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700118 * This gets the message callback handler and its associated context
119 */
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700120static nss_capwap_msg_callback_t nss_capwap_get_msg_callback(int32_t if_num, void **app_data)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700121{
122 struct nss_capwap_handle *h;
123
124 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
125 if (!h) {
126 *app_data = NULL;
127 return NULL;
128 }
129
130 *app_data = h->app_data;
131 return h->msg_callback;
132}
133
134/*
135 * nss_capwapmgr_update_stats()
136 * Update per-tunnel stats for each CAPWAP interface.
137 */
138static void nss_capwapmgr_update_stats(struct nss_capwap_handle *handle, struct nss_capwap_stats_msg *fstats)
139{
140 struct nss_capwap_tunnel_stats *stats;
141
142 stats = &handle->stats;
143
144 stats->rx_segments += fstats->rx_segments;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700145 stats->dtls_pkts += fstats->dtls_pkts;
Saurabh Misra6db99b52014-12-08 10:33:08 -0800146
147 stats->rx_dup_frag += fstats->rx_dup_frag;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700148 stats->rx_oversize_drops += fstats->rx_oversize_drops;
149 stats->rx_frag_timeout_drops += fstats->rx_frag_timeout_drops;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700150 stats->rx_queue_full_drops += fstats->rx_queue_full_drops;
151 stats->rx_n2h_queue_full_drops += fstats->rx_n2h_queue_full_drops;
152 stats->rx_mem_failure_drops += fstats->rx_mem_failure_drops;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700153 stats->rx_csum_drops += fstats->rx_csum_drops;
154 stats->rx_malformed += fstats->rx_malformed;
155 stats->rx_frag_gap_drops += fstats->rx_frag_gap_drops;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700156
Saurabh Misra3f66e872015-04-03 11:30:42 -0700157 stats->tx_segments += fstats->tx_segments;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700158 stats->tx_queue_full_drops += fstats->tx_queue_full_drops;
159 stats->tx_mem_failure_drops += fstats->tx_mem_failure_drops;
Saurabh Misra3f66e872015-04-03 11:30:42 -0700160 stats->tx_dropped_sg_ref += fstats->tx_dropped_sg_ref;
161 stats->tx_dropped_ver_mis += fstats->tx_dropped_ver_mis;
162 stats->tx_dropped_hroom += fstats->tx_dropped_hroom;
163 stats->tx_dropped_dtls += fstats->tx_dropped_dtls;
164 stats->tx_dropped_nwireless += fstats->tx_dropped_nwireless;
Saurabh Misra6db99b52014-12-08 10:33:08 -0800165
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700166 /*
167 * add pnode stats now.
168 */
169 stats->pnode_stats.rx_packets += fstats->pnode_stats.rx_packets;
170 stats->pnode_stats.rx_bytes += fstats->pnode_stats.rx_bytes;
ratheesh kannoth89948ff2017-10-03 08:59:02 +0530171 stats->pnode_stats.rx_dropped += nss_cmn_rx_dropped_sum(&fstats->pnode_stats);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700172 stats->pnode_stats.tx_packets += fstats->pnode_stats.tx_packets;
173 stats->pnode_stats.tx_bytes += fstats->pnode_stats.tx_bytes;
Sakthi Vignesh Radhakrishnanab1f1922018-10-01 10:52:32 -0700174
175 /*
176 * Set to 1 when the tunnel is operating in fast memory.
177 */
178 stats->fast_mem = fstats->fast_mem;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700179}
180
181/*
182 * nss_capwap_handler()
Sakthi Vignesh Radhakrishnanab1f1922018-10-01 10:52:32 -0700183 * Handle NSS -> HLOS messages for CAPWAP
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700184 */
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700185static void nss_capwap_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700186{
187 struct nss_capwap_msg *ntm = (struct nss_capwap_msg *)ncm;
188 nss_capwap_msg_callback_t cb;
189
190 /*
191 * Is this a valid request/response packet?
192 */
193 if (ncm->type > NSS_CAPWAP_MSG_TYPE_MAX) {
194 nss_warning("%p: received invalid message %d for CAPWAP interface", nss_ctx, ncm->type);
195 return;
196 }
197
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800198 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_capwap_msg)) {
199 nss_warning("%p: Length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700200 return;
201 }
202
203 nss_core_log_msg_failures(nss_ctx, ncm);
204
Sachin Shashidhare6babc52018-05-29 15:20:40 -0700205 /*
206 * Trace messages.
207 */
208 nss_capwap_log_rx_msg(ntm);
209
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700210 switch (ntm->cm.type) {
211 case NSS_CAPWAP_MSG_TYPE_SYNC_STATS: {
212 uint32_t if_num;
213
214 if_num = ncm->interface - NSS_DYNAMIC_IF_START;
215 if (nss_capwap_hdl[if_num] != NULL) {
216 nss_capwapmgr_update_stats(nss_capwap_hdl[if_num], &ntm->msg.stats);
217 }
218 }
219 }
220
221 /*
222 * Update the callback and app_data for NOTIFY messages.
223 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530224 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800225 ncm->cb = (nss_ptr_t)nss_capwap_get_msg_callback(ncm->interface, (void **)&ncm->app_data);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700226 }
227
228 /*
229 * Do we have a callback
230 */
231 if (!ncm->cb) {
232 nss_trace("%p: cb is null for interface %d", nss_ctx, ncm->interface);
233 return;
234 }
235
236 cb = (nss_capwap_msg_callback_t)ncm->cb;
Saurabh Misra3e9f8b02015-03-16 13:30:57 -0700237 cb((void *)ncm->app_data, ntm);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700238}
239
240/*
241 * nss_capwap_instance_alloc()
242 * Allocate CAPWAP tunnel instance
243 */
244static bool nss_capwap_instance_alloc(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
245{
246 struct nss_capwap_handle *h;
247
248 /*
249 * Allocate a handle
250 */
251 h = kmalloc(sizeof(struct nss_capwap_handle), GFP_ATOMIC);
252 if (h == NULL) {
253 nss_warning("%p: no memory for allocating CAPWAP instance for interface : %d", nss_ctx, if_num);
254 return false;
255 }
Saurabh Misraf4a05632015-02-27 17:49:41 -0800256
257 memset(h, 0, sizeof(struct nss_capwap_handle));
258 h->if_num = if_num;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700259
260 spin_lock(&nss_capwap_spinlock);
261 if (nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] != NULL) {
262 spin_unlock(&nss_capwap_spinlock);
263 kfree(h);
264 nss_warning("%p: Another thread is already allocated instance for :%d", nss_ctx, if_num);
265 return false;
266 }
267
268 nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] = h;
269 spin_unlock(&nss_capwap_spinlock);
270
271 return true;
272}
273
274/*
275 * nss_capwap_tx_msg()
276 * Transmit a CAPWAP message to NSS FW. Don't call this from softirq/interrupts.
277 */
278nss_tx_status_t nss_capwap_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_capwap_msg *msg)
279{
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700280 struct nss_cmn_msg *ncm = &msg->cm;
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700281 int32_t status;
282 int32_t if_num;
283
284 BUG_ON(in_interrupt());
285 BUG_ON(in_softirq());
286 BUG_ON(in_serving_softirq());
287
288 if (nss_capwap_verify_if_num(msg->cm.interface) == false) {
289 return NSS_TX_FAILURE_BAD_PARAM;
290 }
291
292 if (ncm->type >= NSS_CAPWAP_MSG_TYPE_MAX) {
293 return NSS_TX_FAILURE_BAD_PARAM;
294 }
295
296 if_num = msg->cm.interface - NSS_DYNAMIC_IF_START;
297 spin_lock(&nss_capwap_spinlock);
298 if (!nss_capwap_hdl[if_num]) {
299 spin_unlock(&nss_capwap_spinlock);
300 nss_warning("%p: capwap tunnel if_num is not there: %d", nss_ctx, msg->cm.interface);
301 return NSS_TX_FAILURE_BAD_PARAM;
302 }
303 nss_capwap_refcnt_inc(msg->cm.interface);
304 spin_unlock(&nss_capwap_spinlock);
305
Sachin Shashidhare6babc52018-05-29 15:20:40 -0700306 /*
307 * Trace messages.
308 */
309 nss_capwap_log_tx_msg(msg);
310
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700311 status = nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700312 nss_capwap_refcnt_dec(msg->cm.interface);
313 return status;
314}
315EXPORT_SYMBOL(nss_capwap_tx_msg);
316
317/*
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800318 * nss_capwap_tx_buf()
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700319 * Transmit data buffer (skb) to a NSS interface number
320 */
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800321nss_tx_status_t nss_capwap_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf, uint32_t if_num)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700322{
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800323 BUG_ON(!nss_capwap_verify_if_num(if_num));
324
Aniruddha Paul38d72f42019-08-20 16:51:31 +0530325 return nss_core_send_packet(nss_ctx, os_buf, if_num, H2N_BIT_FLAG_VIRTUAL_BUFFER | H2N_BIT_FLAG_BUFFER_REUSABLE);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700326}
Stephen Wangcf9c21c2016-02-18 17:54:16 -0800327EXPORT_SYMBOL(nss_capwap_tx_buf);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700328
329/*
330 ***********************************
331 * Register/Unregister/Miscellaneous APIs
332 ***********************************
333 */
334
335/*
336 * nss_capwap_get_stats()
337 * API for getting stats from a CAPWAP tunnel interface stats
338 */
339bool nss_capwap_get_stats(uint32_t if_num, struct nss_capwap_tunnel_stats *stats)
340{
341 if (nss_capwap_verify_if_num(if_num) == false) {
342 return false;
343 }
344
345 if_num = if_num - NSS_DYNAMIC_IF_START;
346 spin_lock(&nss_capwap_spinlock);
347 if (nss_capwap_hdl[if_num] == NULL) {
348 spin_unlock(&nss_capwap_spinlock);
349 return false;
350 }
351
352 memcpy(stats, &nss_capwap_hdl[if_num]->stats, sizeof(struct nss_capwap_tunnel_stats));
353 spin_unlock(&nss_capwap_spinlock);
354 return true;
355}
356EXPORT_SYMBOL(nss_capwap_get_stats);
357
358/*
359 * nss_capwap_notify_register()
360 * Registers a message notifier with NSS FW. It should not be called from
361 * softirq or interrupts.
362 */
363struct nss_ctx_instance *nss_capwap_notify_register(uint32_t if_num, nss_capwap_msg_callback_t cb, void *app_data)
364{
365 struct nss_ctx_instance *nss_ctx;
366
367 nss_ctx = &nss_top_main.nss[nss_top_main.capwap_handler_id];
368
369 if (nss_capwap_verify_if_num(if_num) == false) {
370 nss_warning("%p: notfiy register received for invalid interface %d", nss_ctx, if_num);
371 return NULL;
372 }
373
374 spin_lock(&nss_capwap_spinlock);
375 if (nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] != NULL) {
376 spin_unlock(&nss_capwap_spinlock);
377 nss_warning("%p: notfiy register tunnel already exists for interface %d", nss_ctx, if_num);
378 return NULL;
379 }
380 spin_unlock(&nss_capwap_spinlock);
381
382 return nss_ctx;
383}
384EXPORT_SYMBOL(nss_capwap_notify_register);
385
386/*
387 * nss_capwap_notify_unregister()
388 * unregister the CAPWAP notifier for the given interface number (if_num).
389 * It shouldn't be called from softirq or interrupts.
390 */
391nss_tx_status_t nss_capwap_notify_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
392{
393 struct nss_top_instance *nss_top;
394 int index;
395
396 if (nss_capwap_verify_if_num(if_num) == false) {
397 nss_warning("%p: notify unregister received for invalid interface %d", nss_ctx, if_num);
398 return NSS_TX_FAILURE_BAD_PARAM;
399 }
400
401 nss_top = nss_ctx->nss_top;
402 if (nss_top == NULL) {
403 nss_warning("%p: notify unregister received for invalid nss_top %d", nss_ctx, if_num);
404 return NSS_TX_FAILURE_BAD_PARAM;
405 }
406
407 index = if_num - NSS_DYNAMIC_IF_START;
408 spin_lock(&nss_capwap_spinlock);
409 if (nss_capwap_hdl[index] == NULL) {
410 spin_unlock(&nss_capwap_spinlock);
411 nss_warning("%p: notify unregister received for unallocated if_num: %d", nss_ctx, if_num);
412 return NSS_TX_FAILURE_BAD_PARAM;
413 }
414
415 /*
416 * It's the responsibility of caller to wait and call us again. We return failure saying
417 * that we can't remove msg handler now.
418 */
Saurabh Misraf4a05632015-02-27 17:49:41 -0800419 if (nss_capwap_refcnt(if_num) != 0) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700420 spin_unlock(&nss_capwap_spinlock);
421 nss_warning("%p: notify unregister tunnel %d: has reference", nss_ctx, if_num);
422 return NSS_TX_FAILURE_QUEUE;
423 }
424
425 nss_capwap_set_msg_callback(if_num, NULL, NULL);
426 spin_unlock(&nss_capwap_spinlock);
427
428 return NSS_TX_SUCCESS;
429}
430EXPORT_SYMBOL(nss_capwap_notify_unregister);
431
432/*
433 * nss_capwap_data_register()
434 * Registers a data packet notifier with NSS FW.
435 */
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800436struct nss_ctx_instance *nss_capwap_data_register(uint32_t if_num, nss_capwap_buf_callback_t cb, struct net_device *netdev, uint32_t features)
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700437{
438 struct nss_ctx_instance *nss_ctx;
439 int core_status;
440
441 nss_ctx = nss_capwap_get_ctx();
442 if (nss_capwap_verify_if_num(if_num) == false) {
443 nss_warning("%p: data register received for invalid interface %d", nss_ctx, if_num);
444 return NULL;
445 }
446
447 spin_lock(&nss_capwap_spinlock);
Stephen Wang84e0e992016-09-07 12:31:40 -0700448 if (nss_ctx->subsys_dp_register[if_num].ndev != NULL) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700449 spin_unlock(&nss_capwap_spinlock);
450 return NULL;
451 }
452 spin_unlock(&nss_capwap_spinlock);
453
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700454 core_status = nss_core_register_handler(nss_ctx, if_num, nss_capwap_msg_handler, NULL);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700455 if (core_status != NSS_CORE_STATUS_SUCCESS) {
456 nss_warning("%p: nss core register handler failed for if_num:%d with error :%d", nss_ctx, if_num, core_status);
457 return NULL;
458 }
459
460 if (nss_capwap_instance_alloc(nss_ctx, if_num) == false) {
461 nss_warning("%p: couldn't allocate tunnel instance for if_num:%d", nss_ctx, if_num);
462 return NULL;
463 }
464
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700465 nss_core_register_subsys_dp(nss_ctx, if_num, cb, NULL, NULL, netdev, features);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700466
467 return nss_ctx;
468}
469EXPORT_SYMBOL(nss_capwap_data_register);
470
471/*
472 * nss_capwap_data_unregister()
473 * Unregister a data packet notifier with NSS FW
474 */
475bool nss_capwap_data_unregister(uint32_t if_num)
476{
477 struct nss_ctx_instance *nss_ctx;
478 struct nss_capwap_handle *h;
479
480 nss_ctx = nss_capwap_get_ctx();
481 if (nss_capwap_verify_if_num(if_num) == false) {
482 nss_warning("%p: data unregister received for invalid interface %d", nss_ctx, if_num);
483 return false;
484 }
485
486 spin_lock(&nss_capwap_spinlock);
487 /*
488 * It's the responsibility of caller to wait and call us again.
489 */
Saurabh Misraf4a05632015-02-27 17:49:41 -0800490 if (nss_capwap_refcnt(if_num) != 0) {
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700491 spin_unlock(&nss_capwap_spinlock);
492 nss_warning("%p: notify unregister tunnel %d: has reference", nss_ctx, if_num);
493 return false;
494 }
495 h = nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START];
496 nss_capwap_hdl[if_num - NSS_DYNAMIC_IF_START] = NULL;
497 spin_unlock(&nss_capwap_spinlock);
498
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700499 (void) nss_core_unregister_handler(nss_ctx, if_num);
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700500
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700501 nss_core_unregister_subsys_dp(nss_ctx, if_num);
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800502
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700503 kfree(h);
504 return true;
505}
506EXPORT_SYMBOL(nss_capwap_data_unregister);
507
508/*
509 * nss_capwap_get_ctx()
510 * Return a CAPWAP NSS context.
511 */
512struct nss_ctx_instance *nss_capwap_get_ctx()
513{
514 struct nss_ctx_instance *nss_ctx;
515
516 nss_ctx = &nss_top_main.nss[nss_top_main.capwap_handler_id];
517 return nss_ctx;
518}
519EXPORT_SYMBOL(nss_capwap_get_ctx);
520
521/*
Stephen Wang1f6ad492016-01-27 23:42:06 -0800522 * nss_capwap_ifnum_with_core_id()
523 * Append core id to capwap interface num
524 */
525int nss_capwap_ifnum_with_core_id(int if_num)
526{
527 struct nss_ctx_instance *nss_ctx = nss_capwap_get_ctx();
528
529 NSS_VERIFY_CTX_MAGIC(nss_ctx);
530 if (nss_is_dynamic_interface(if_num) == false) {
531 nss_info("%p: Invalid if_num: %d, must be a dynamic interface\n", nss_ctx, if_num);
532 return 0;
533 }
534 return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
535}
536EXPORT_SYMBOL(nss_capwap_ifnum_with_core_id);
537
538/*
Sundarajan Srinivasan40bea952014-12-02 13:19:34 -0800539 * nss_capwap_get_max_buf_size()
540 * Return a CAPWAP NSS max_buf_size.
541 */
542uint32_t nss_capwap_get_max_buf_size(struct nss_ctx_instance *nss_ctx)
543{
544 return nss_core_get_max_buf_size(nss_ctx);
545}
546EXPORT_SYMBOL(nss_capwap_get_max_buf_size);
547
548/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700549 * nss_capwap_init()
550 * Initializes CAPWAP. Gets called from nss_init.c
551 */
552void nss_capwap_init()
553{
554 memset(&nss_capwap_hdl, 0, sizeof(nss_capwap_hdl));
Yu Huang8c107082017-07-24 14:58:26 -0700555 nss_capwap_stats_dentry_create();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700556}
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700557
558/*
559 * nss_capwap_msg_init()
560 * Initialize capwap message.
561 */
562void nss_capwap_msg_init(struct nss_capwap_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len,
Sundarajan Srinivasan30a53d42015-01-30 10:52:08 -0800563 nss_capwap_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700564{
565 nss_cmn_msg_init(&ncm->cm, if_num, type, len, (void*)cb, app_data);
566}
567EXPORT_SYMBOL(nss_capwap_msg_init);