blob: 46cd72c71ec100f9dd4539260d4f6150b9932adc [file] [log] [blame]
ratheesh kannotheb2a0a82017-05-04 09:20:17 +05301/*
2 **************************************************************************
Kyle Swensonab36fae2021-05-21 08:38:22 -06003 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
ratheesh kannotheb2a0a82017-05-04 09:20:17 +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#include "nss_tx_rx_common.h"
Yu Huang8c107082017-07-24 14:58:26 -070018#include "nss_gre_stats.h"
Sachin Shashidhar159a64a2018-07-31 16:16:51 -070019#include "nss_gre_log.h"
Kyle Swensonab36fae2021-05-21 08:38:22 -060020#include "nss_gre_strings.h"
ratheesh kannotheb2a0a82017-05-04 09:20:17 +053021
22#define NSS_GRE_TX_TIMEOUT 3000 /* 3 Seconds */
23
24/*
25 * Private data structure
26 */
27static struct {
28 struct semaphore sem;
29 struct completion complete;
30 int response;
31 void *cb;
32 void *app_data;
33} nss_gre_pvt;
34
Suruchi Sumane93a7e82019-06-10 17:31:25 +053035/*
36 * TODO: Register separate callbacks for inner and outer GRE nodes.
37 */
ratheesh kannoth7746db22017-05-16 14:16:43 +053038static atomic64_t pkt_cb_addr = ATOMIC64_INIT(0);
39
40/*
Suman Ghoshb2faf662018-07-13 17:34:12 +053041 * nss_gre_inner_rx_handler()
42 * GRE inner rx handler.
ratheesh kannoth7746db22017-05-16 14:16:43 +053043 */
Suman Ghoshb2faf662018-07-13 17:34:12 +053044static void nss_gre_inner_rx_handler(struct net_device *dev, struct sk_buff *skb,
ratheesh kannoth7746db22017-05-16 14:16:43 +053045 __attribute__((unused)) struct napi_struct *napi)
46{
47 nss_gre_data_callback_t cb;
48
49 nss_gre_pkt_callback_t scb = (nss_gre_pkt_callback_t)(unsigned long)atomic64_read(&pkt_cb_addr);
50 if (unlikely(scb)) {
51 struct nss_gre_info *info = (struct nss_gre_info *)netdev_priv(dev);
Suruchi Sumane93a7e82019-06-10 17:31:25 +053052 if (likely(info->next_dev_inner)) {
53 scb(info->next_dev_inner, skb);
ratheesh kannoth7746db22017-05-16 14:16:43 +053054 }
55 }
56
Suman Ghoshb2faf662018-07-13 17:34:12 +053057 cb = nss_top_main.gre_inner_data_callback;
58 cb(dev, skb, 0);
59}
60
61/*
62 * nss_gre_outer_rx_handler()
63 * GRE outer rx handler.
64 */
65static void nss_gre_outer_rx_handler(struct net_device *dev, struct sk_buff *skb,
66 __attribute__((unused)) struct napi_struct *napi)
67{
68 nss_gre_data_callback_t cb;
69
70 nss_gre_pkt_callback_t scb = (nss_gre_pkt_callback_t)(unsigned long)atomic64_read(&pkt_cb_addr);
71 if (unlikely(scb)) {
72 struct nss_gre_info *info = (struct nss_gre_info *)netdev_priv(dev);
Suruchi Sumane93a7e82019-06-10 17:31:25 +053073 if (likely(info->next_dev_outer)) {
74 scb(info->next_dev_outer, skb);
Suman Ghoshb2faf662018-07-13 17:34:12 +053075 }
76 }
77
78 cb = nss_top_main.gre_outer_data_callback;
ratheesh kannoth7746db22017-05-16 14:16:43 +053079 cb(dev, skb, 0);
80}
81
ratheesh kannotheb2a0a82017-05-04 09:20:17 +053082/*
ratheesh kannotheb2a0a82017-05-04 09:20:17 +053083 * nss_gre_msg_handler()
84 * Handle NSS -> HLOS messages for GRE
85 */
86static void nss_gre_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
87{
88 struct nss_gre_msg *ntm = (struct nss_gre_msg *)ncm;
89 void *ctx;
90
91 nss_gre_msg_callback_t cb;
92
93 NSS_VERIFY_CTX_MAGIC(nss_ctx);
94 BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_GRE_INTERFACE));
95
96 /*
Sachin Shashidhar159a64a2018-07-31 16:16:51 -070097 * Trace Messages
98 */
99 nss_gre_log_rx_msg(ntm);
100
101 /*
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530102 * Is this a valid request/response packet?
103 */
104 if (ncm->type >= NSS_GRE_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600105 nss_warning("%px: received invalid message %d for GRE STD interface", nss_ctx, ncm->type);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530106 return;
107 }
108
109 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_gre_msg)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600110 nss_warning("%px: tx request for another interface: %d", nss_ctx, ncm->interface);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530111 return;
112 }
113
114 switch (ntm->cm.type) {
115 case NSS_GRE_MSG_SESSION_STATS:
116 /*
117 * debug stats embedded in stats msg
118 */
Kyle Swensonab36fae2021-05-21 08:38:22 -0600119 nss_gre_stats_session_sync(nss_ctx, &ntm->msg.sstats, ncm->interface);
120 nss_gre_stats_session_notify(nss_ctx, ncm->interface);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530121 break;
122
123 case NSS_GRE_MSG_BASE_STATS:
Kyle Swensonab36fae2021-05-21 08:38:22 -0600124 nss_gre_stats_base_sync(nss_ctx, &ntm->msg.bstats);
125 nss_gre_stats_base_notify(nss_ctx);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530126 break;
127
128 default:
129 break;
130
131 }
132
133 /*
134 * Update the callback and app_data for NOTIFY messages, gre sends all notify messages
135 * to the same callback/app_data.
136 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530137 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530138 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->gre_msg_callback;
139 ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
140 }
141
142 /*
143 * Log failures
144 */
145 nss_core_log_msg_failures(nss_ctx, ncm);
146
147 /*
148 * callback
149 */
150 cb = (nss_gre_msg_callback_t)ncm->cb;
151 ctx = (void *)ncm->app_data;
152
153 /*
154 * call gre-std callback
155 */
156 if (!cb) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600157 nss_warning("%px: No callback for gre-std interface %d",
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530158 nss_ctx, ncm->interface);
159 return;
160 }
161
162 cb(ctx, ntm);
163}
164
165/*
166 * nss_gre_callback()
167 * Callback to handle the completion of HLOS-->NSS messages.
168 */
169static void nss_gre_callback(void *app_data, struct nss_gre_msg *nim)
170{
171 nss_gre_msg_callback_t callback = (nss_gre_msg_callback_t)nss_gre_pvt.cb;
172 void *data = nss_gre_pvt.app_data;
173
174 nss_gre_pvt.cb = NULL;
175 nss_gre_pvt.app_data = NULL;
176
177 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
178 nss_warning("gre Error response %d\n", nim->cm.response);
179 nss_gre_pvt.response = NSS_TX_FAILURE;
180 } else {
181 nss_gre_pvt.response = NSS_TX_SUCCESS;
182 }
183
184 if (callback) {
185 callback(data, nim);
186 }
187
188 complete(&nss_gre_pvt.complete);
189}
190
191/*
ratheesh kannoth7746db22017-05-16 14:16:43 +0530192 * nss_gre_register_pkt_callback()
193 * Register for data callback.
194 */
195void nss_gre_register_pkt_callback(nss_gre_pkt_callback_t cb)
196{
197 atomic64_set(&pkt_cb_addr, (unsigned long)cb);
198}
199EXPORT_SYMBOL(nss_gre_register_pkt_callback);
200
201/*
202 * nss_gre_unregister_pkt_callback()
203 * Unregister for data callback.
204 */
205void nss_gre_unregister_pkt_callback()
206{
207 atomic64_set(&pkt_cb_addr, 0);
208}
209EXPORT_SYMBOL(nss_gre_unregister_pkt_callback);
210
211/*
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530212 * nss_gre_tx_msg()
213 * Transmit a GRE message to NSS firmware
214 */
215nss_tx_status_t nss_gre_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg)
216{
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530217 struct nss_cmn_msg *ncm = &msg->cm;
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530218
219 /*
220 * Sanity check the message
221 */
222 if (!nss_is_dynamic_interface(ncm->interface)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600223 nss_warning("%px: tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530224 return NSS_TX_FAILURE;
225 }
226
227 if (ncm->type > NSS_GRE_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600228 nss_warning("%px: message type out of range: %d", nss_ctx, ncm->type);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530229 return NSS_TX_FAILURE;
230 }
231
Sachin Shashidhar159a64a2018-07-31 16:16:51 -0700232 /*
233 * Trace Messages
234 */
235 nss_gre_log_tx_msg(msg);
236
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700237 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530238}
239EXPORT_SYMBOL(nss_gre_tx_msg);
240
241/*
242 * nss_gre_tx_msg_sync()
243 * Transmit a GRE message to NSS firmware synchronously.
244 */
245nss_tx_status_t nss_gre_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg)
246{
247 nss_tx_status_t status;
248 int ret = 0;
249
250 down(&nss_gre_pvt.sem);
251 nss_gre_pvt.cb = (void *)msg->cm.cb;
252 nss_gre_pvt.app_data = (void *)msg->cm.app_data;
253
254 msg->cm.cb = (nss_ptr_t)nss_gre_callback;
255 msg->cm.app_data = (nss_ptr_t)NULL;
256
257 status = nss_gre_tx_msg(nss_ctx, msg);
258 if (status != NSS_TX_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600259 nss_warning("%px: gre_tx_msg failed\n", nss_ctx);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530260 up(&nss_gre_pvt.sem);
261 return status;
262 }
263 ret = wait_for_completion_timeout(&nss_gre_pvt.complete, msecs_to_jiffies(NSS_GRE_TX_TIMEOUT));
264
265 if (!ret) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600266 nss_warning("%px: GRE STD tx sync failed due to timeout\n", nss_ctx);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530267 nss_gre_pvt.response = NSS_TX_FAILURE;
268 }
269
270 status = nss_gre_pvt.response;
271 up(&nss_gre_pvt.sem);
272 return status;
273}
274EXPORT_SYMBOL(nss_gre_tx_msg_sync);
275
276/*
277 * nss_gre_tx_buf()
278 * Send packet to GRE interface owned by NSS
279 */
280nss_tx_status_t nss_gre_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num, struct sk_buff *skb)
281{
Aniruddha Paul38d72f42019-08-20 16:51:31 +0530282 return nss_core_send_packet(nss_ctx, skb, if_num, H2N_BIT_FLAG_VIRTUAL_BUFFER | H2N_BIT_FLAG_BUFFER_REUSABLE);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530283}
284EXPORT_SYMBOL(nss_gre_tx_buf);
285
286/*
287 ***********************************
288 * Register/Unregister/Miscellaneous APIs
289 ***********************************
290 */
291
292/*
293 * nss_gre_register_if()
294 * Register data and message handlers for GRE.
295 */
Suman Ghoshb2faf662018-07-13 17:34:12 +0530296struct nss_ctx_instance *nss_gre_register_if(uint32_t if_num, uint32_t type, nss_gre_data_callback_t data_callback,
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530297 nss_gre_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
298{
299 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530300
301 nss_assert(nss_ctx);
302 nss_assert(nss_is_dynamic_interface(if_num));
303
Suman Ghoshb2faf662018-07-13 17:34:12 +0530304 switch (type) {
305 case NSS_DYNAMIC_INTERFACE_TYPE_GRE_INNER:
306 nss_core_register_subsys_dp(nss_ctx, if_num, nss_gre_inner_rx_handler, NULL, netdev, netdev, features);
307 nss_top_main.gre_inner_data_callback = data_callback;
308 break;
309
310 case NSS_DYNAMIC_INTERFACE_TYPE_GRE_OUTER:
311 nss_core_register_subsys_dp(nss_ctx, if_num, nss_gre_outer_rx_handler, NULL, netdev, netdev, features);
312 nss_top_main.gre_outer_data_callback = data_callback;
313 break;
314
315 default:
Kyle Swensondd7b2962021-03-16 13:46:32 -0600316 nss_warning("%px: Unable to register. Wrong interface type %d\n", nss_ctx, type);
Suman Ghoshb2faf662018-07-13 17:34:12 +0530317 return NULL;
318 }
319
320 nss_core_set_subsys_dp_type(nss_ctx, netdev, if_num, type);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530321
322 nss_top_main.gre_msg_callback = event_callback;
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530323
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700324 nss_core_register_handler(nss_ctx, if_num, nss_gre_msg_handler, NULL);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530325
Yu Huang8c107082017-07-24 14:58:26 -0700326 nss_gre_stats_session_register(if_num, netdev);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530327
328 return nss_ctx;
329}
330EXPORT_SYMBOL(nss_gre_register_if);
331
332/*
333 * nss_gre_unregister_if()
334 * Unregister data and message handler.
335 */
336void nss_gre_unregister_if(uint32_t if_num)
337{
338 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
Suman Ghoshb2faf662018-07-13 17:34:12 +0530339 struct net_device *dev;
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530340
341 nss_assert(nss_ctx);
342 nss_assert(nss_is_dynamic_interface(if_num));
343
Suman Ghoshb2faf662018-07-13 17:34:12 +0530344 dev = nss_cmn_get_interface_dev(nss_ctx, if_num);
345 if (!dev) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600346 nss_warning("%px: Unable to find net device for the interface %d\n", nss_ctx, if_num);
Suman Ghoshb2faf662018-07-13 17:34:12 +0530347 return;
348 }
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530349
Suman Ghoshb2faf662018-07-13 17:34:12 +0530350 nss_core_unregister_subsys_dp(nss_ctx, if_num);
351 nss_core_set_subsys_dp_type(nss_ctx, dev, if_num, NSS_DYNAMIC_INTERFACE_TYPE_NONE);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530352 nss_top_main.gre_msg_callback = NULL;
353
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700354 nss_core_unregister_handler(nss_ctx, if_num);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530355
Yu Huang8c107082017-07-24 14:58:26 -0700356 nss_gre_stats_session_unregister(if_num);
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530357}
358EXPORT_SYMBOL(nss_gre_unregister_if);
359
360/*
361 * nss_get_gre_context()
362 */
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700363struct nss_ctx_instance *nss_gre_get_context(void)
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530364{
365 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
366}
367EXPORT_SYMBOL(nss_gre_get_context);
368
369/*
Suruchi Sumane93a7e82019-06-10 17:31:25 +0530370 * nss_gre_ifnum_with_core_id()
371 * Append core id to GRE interface num.
372 */
373int nss_gre_ifnum_with_core_id(int if_num)
374{
375 struct nss_ctx_instance *nss_ctx = nss_gre_get_context();
376
377 NSS_VERIFY_CTX_MAGIC(nss_ctx);
378 if (!nss_is_dynamic_interface(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600379 nss_warning("%px: Invalid if_num: %d, must be a dynamic interface\n", nss_ctx, if_num);
Suruchi Sumane93a7e82019-06-10 17:31:25 +0530380 return 0;
381 }
382
383 return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
384}
385EXPORT_SYMBOL(nss_gre_ifnum_with_core_id);
386
387/*
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530388 * nss_gre_msg_init()
389 * Initialize nss_gre msg.
390 */
391void nss_gre_msg_init(struct nss_gre_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
392{
393 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
394}
395EXPORT_SYMBOL(nss_gre_msg_init);
396
397/*
398 * nss_gre_register_handler()
399 * debugfs stats msg handler received on static gre interface
400 */
401void nss_gre_register_handler(void)
402{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700403 struct nss_ctx_instance *nss_ctx = nss_gre_get_context();
404
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530405 nss_info("nss_gre_register_handler");
406 sema_init(&nss_gre_pvt.sem, 1);
407 init_completion(&nss_gre_pvt.complete);
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700408 nss_core_register_handler(nss_ctx, NSS_GRE_INTERFACE, nss_gre_msg_handler, NULL);
Yu Huang8c107082017-07-24 14:58:26 -0700409 nss_gre_stats_dentry_create();
Kyle Swensonab36fae2021-05-21 08:38:22 -0600410 nss_gre_strings_dentry_create();
ratheesh kannotheb2a0a82017-05-04 09:20:17 +0530411}