blob: bee4ca9fecedab211d75515fd09fc9da37520596 [file] [log] [blame]
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +05301/*
2 **************************************************************************
Amit Gupta1fe4d912019-03-19 15:57:10 +05303 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +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_pppoe.c
19 * NSS PPPoE APIs
20 */
21
22#include "nss_tx_rx_common.h"
Yu Huang8c107082017-07-24 14:58:26 -070023#include "nss_pppoe_stats.h"
Sachin Shashidhar626131e2018-08-08 11:29:58 -070024#include "nss_pppoe_log.h"
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053025
Murat Sezgin4abd88c2017-05-24 17:00:59 -070026#define NSS_PPPOE_TX_TIMEOUT 3000 /* 3 Seconds */
27
Amit Gupta1fe4d912019-03-19 15:57:10 +053028int nss_pppoe_br_accel_mode __read_mostly = NSS_PPPOE_BR_ACCEL_MODE_EN_5T;
Murat Sezgin4abd88c2017-05-24 17:00:59 -070029
30/*
31 * Private data structure
32 */
33static struct nss_pppoe_pvt {
34 struct semaphore sem;
35 struct completion complete;
36 int response;
37 void *cb;
38 void *app_data;
39} pppoe_pvt;
40
41/*
Amit Gupta1fe4d912019-03-19 15:57:10 +053042 * nss_pppoe_br_help()
43 * Usage information for pppoe bride accel mode
44 */
45static inline void nss_pppoe_br_help(int mode)
46{
47 printk("Incorrect pppoe bridge accel mode: %d\n", mode);
48 printk("Supported modes\n");
49 printk("%d: pppoe bridge acceleration disable\n", NSS_PPPOE_BR_ACCEL_MODE_DIS);
50 printk("%d: pppoe bridge acceleration enable with 5-tuple\n", NSS_PPPOE_BR_ACCEL_MODE_EN_5T);
51 printk("%d: pppoe bridge acceleration enable with 3-tuple\n", NSS_PPPOE_BR_ACCEL_MODE_EN_3T);
52}
53
54/*
Murat Sezgin4abd88c2017-05-24 17:00:59 -070055 * nss_pppoe_get_context()
56 */
57struct nss_ctx_instance *nss_pppoe_get_context(void)
58{
59 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.pppoe_handler_id];
60}
61EXPORT_SYMBOL(nss_pppoe_get_context);
62
63/*
64 * nss_pppoe_tx_msg()
65 * Transmit a PPPoE message to NSS firmware
66 */
67static nss_tx_status_t nss_pppoe_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *msg)
68{
69 struct nss_cmn_msg *ncm = &msg->cm;
Amit Gupta1fe4d912019-03-19 15:57:10 +053070 enum nss_dynamic_interface_type type;
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053071
72 /*
Sachin Shashidhar626131e2018-08-08 11:29:58 -070073 * Trace Messages
74 */
75 nss_pppoe_log_tx_msg(msg);
76
77 /*
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053078 * Sanity check the message
79 */
Amit Gupta1fe4d912019-03-19 15:57:10 +053080 type = nss_dynamic_interface_get_type(nss_pppoe_get_context(), ncm->interface);
81 if ((ncm->interface != NSS_PPPOE_INTERFACE) && (type != NSS_DYNAMIC_INTERFACE_TYPE_PPPOE)) {
82 nss_warning("%p: tx request for not PPPoE interface: %d type: %d\n",
83 nss_ctx, ncm->interface, type);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053084 return NSS_TX_FAILURE;
85 }
86
Murat Sezgin4abd88c2017-05-24 17:00:59 -070087 if (ncm->type >= NSS_PPPOE_MSG_MAX) {
88 nss_warning("%p: message type out of range: %d\n", nss_ctx, ncm->type);
89 return NSS_TX_FAILURE;
90 }
91
92 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053093}
94
95/*
Murat Sezgin4abd88c2017-05-24 17:00:59 -070096 * nss_pppoe_sync_msg_callback()
97 * Callback to handle the completion of NSS->HLOS messages.
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053098 */
Murat Sezgin4abd88c2017-05-24 17:00:59 -070099static void nss_pppoe_sync_msg_callback(void *app_data, struct nss_pppoe_msg *npm)
100{
101 nss_pppoe_msg_callback_t callback = (nss_pppoe_msg_callback_t)pppoe_pvt.cb;
102 void *data = pppoe_pvt.app_data;
103
104 pppoe_pvt.cb = NULL;
105 pppoe_pvt.app_data = NULL;
106
107 pppoe_pvt.response = NSS_TX_SUCCESS;
108 if (npm->cm.response != NSS_CMN_RESPONSE_ACK) {
109 nss_warning("pppoe Error response %d\n", npm->cm.response);
110 pppoe_pvt.response = NSS_TX_FAILURE;
111 }
112
113 if (callback) {
114 callback(data, npm);
115 }
116
117 complete(&pppoe_pvt.complete);
118}
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530119
120/*
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700121 * nss_pppoe_handler()
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530122 * Handle NSS -> HLOS messages for PPPoE
123 */
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700124static void nss_pppoe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530125{
Murat Sezgincdd23572019-06-27 13:07:23 -0700126 struct nss_pppoe_msg *npm = (struct nss_pppoe_msg *)ncm;
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700127 void *ctx;
128 nss_pppoe_msg_callback_t cb;
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530129
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700130 BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_PPPOE_INTERFACE));
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530131
132 /*
Sachin Shashidhar626131e2018-08-08 11:29:58 -0700133 * Trace Messages
134 */
Murat Sezgincdd23572019-06-27 13:07:23 -0700135 nss_pppoe_log_rx_msg(npm);
Sachin Shashidhar626131e2018-08-08 11:29:58 -0700136
137 /*
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530138 * Sanity check the message type
139 */
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700140 if (ncm->type >= NSS_PPPOE_MSG_MAX) {
141 nss_warning("%p: message type out of range: %d\n", nss_ctx, ncm->type);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530142 return;
143 }
144
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800145 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_pppoe_msg)) {
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700146 nss_warning("%p: message length is invalid: %d\n", nss_ctx, nss_cmn_get_msg_len(ncm));
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530147 return;
148 }
149
150 /*
151 * Log failures
152 */
153 nss_core_log_msg_failures(nss_ctx, ncm);
154
155 /*
156 * Handling PPPoE messages coming from NSS fw.
157 */
Murat Sezgincdd23572019-06-27 13:07:23 -0700158 switch (npm->cm.type) {
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700159 case NSS_PPPOE_MSG_SYNC_STATS:
Murat Sezgincdd23572019-06-27 13:07:23 -0700160 nss_pppoe_stats_sync(nss_ctx, &npm->msg.sync_stats, ncm->interface);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530161 break;
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530162 default:
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700163 nss_warning("%p: Received response %d for type %d, interface %d\n",
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530164 nss_ctx, ncm->response, ncm->type, ncm->interface);
165 }
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700166
167 /*
168 * Update the callback and app_data for NOTIFY messages, pppoe sends all notify messages
169 * to the same callback/app_data.
170 */
171 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
172 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->pppoe_msg_callback;
173 ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
174 }
175
176 /*
177 * Log failures
178 */
179 nss_core_log_msg_failures(nss_ctx, ncm);
180
181 /*
182 * Do we have a call back
183 */
184 if (!ncm->cb) {
185 return;
186 }
187
188 /*
189 * callback
190 */
191 cb = (nss_pppoe_msg_callback_t)ncm->cb;
192 ctx = (void *)ncm->app_data;
193
Murat Sezgincdd23572019-06-27 13:07:23 -0700194 cb(ctx, npm);
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700195}
196
197/*
Amit Gupta1fe4d912019-03-19 15:57:10 +0530198 * nss_pppoe_br_accel_mode_handler()
199 * Enable/disable pppoe bridge acceleration in NSS
200 */
201int nss_pppoe_br_accel_mode_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
202{
203 struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
204 struct nss_pppoe_msg npm;
205 struct nss_pppoe_br_accel_cfg_msg *npbacm;
206 nss_tx_status_t status;
207 int ret;
208 enum nss_pppoe_br_accel_modes current_value, new_val;
209
210 /*
211 * Take snap shot of current value
212 */
213 current_value = nss_pppoe_br_accel_mode;
214
215 /*
216 * Write the variable with user input
217 */
218 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
219 if (ret || (!write)) {
220 return ret;
221 }
222
223 new_val = nss_pppoe_br_accel_mode;
224 if ((new_val < NSS_PPPOE_BR_ACCEL_MODE_DIS) || (new_val >= NSS_PPPOE_BR_ACCEL_MODE_MAX)) {
225 nss_warning("%p: value out of range: %d\n", nss_ctx, new_val);
226 nss_pppoe_br_accel_mode = current_value;
227 nss_pppoe_br_help(new_val);
228 return -EINVAL;
229 }
230
231 memset(&npm, 0, sizeof(struct nss_pppoe_msg));
232 nss_pppoe_msg_init(&npm, NSS_PPPOE_INTERFACE, NSS_PPPOE_MSG_BR_ACCEL_CFG,
233 sizeof(struct nss_pppoe_br_accel_cfg_msg), NULL, NULL);
234
235 npbacm = &npm.msg.br_accel;
236 npbacm->br_accel_cfg = new_val;
237
238 status = nss_pppoe_tx_msg_sync(nss_ctx, &npm);
239 if (status != NSS_TX_SUCCESS) {
240 nss_warning("%p: Send acceleration mode message failed\n", nss_ctx);
241 nss_pppoe_br_accel_mode = current_value;
242 return -EIO;
243 }
244
245 return 0;
246}
247
248/*
249 * nss_pppoe_get_br_accel_mode()
250 * Gets PPPoE bridge acceleration mode
251 */
252enum nss_pppoe_br_accel_modes nss_pppoe_get_br_accel_mode(void)
253{
254 return nss_pppoe_br_accel_mode;
255}
256EXPORT_SYMBOL(nss_pppoe_get_br_accel_mode);
257
258/*
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700259 * nss_pppoe_tx_msg_sync()
260 */
261nss_tx_status_t nss_pppoe_tx_msg_sync(struct nss_ctx_instance *nss_ctx,
262 struct nss_pppoe_msg *msg)
263{
264 nss_tx_status_t status;
265 int ret = 0;
266
267 down(&pppoe_pvt.sem);
268 pppoe_pvt.cb = (void *)msg->cm.cb;
269 pppoe_pvt.app_data = (void *)msg->cm.app_data;
270
271 msg->cm.cb = (nss_ptr_t)nss_pppoe_sync_msg_callback;
272 msg->cm.app_data = (nss_ptr_t)NULL;
273
274 status = nss_pppoe_tx_msg(nss_ctx, msg);
275 if (status != NSS_TX_SUCCESS) {
276 nss_warning("%p: nss_pppoe_tx_msg failed\n", nss_ctx);
277 up(&pppoe_pvt.sem);
278 return status;
279 }
280
281 ret = wait_for_completion_timeout(&pppoe_pvt.complete, msecs_to_jiffies(NSS_PPPOE_TX_TIMEOUT));
282 if (!ret) {
283 nss_warning("%p: PPPoE msg tx failed due to timeout\n", nss_ctx);
284 pppoe_pvt.response = NSS_TX_FAILURE;
285 }
286
287 status = pppoe_pvt.response;
288 up(&pppoe_pvt.sem);
289 return status;
290}
291EXPORT_SYMBOL(nss_pppoe_tx_msg_sync);
292
293/*
294 * nss_register_pppoe_session_if()
295 */
296struct nss_ctx_instance *nss_register_pppoe_session_if(uint32_t if_num,
297 nss_pppoe_msg_callback_t notification_callback,
298 struct net_device *netdev, uint32_t features, void *app_ctx)
299{
300 struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700301
302 nss_assert(nss_ctx);
303 nss_assert(nss_is_dynamic_interface(if_num));
304
Murat Sezgincdd23572019-06-27 13:07:23 -0700305 if (!nss_pppoe_stats_pppoe_session_init(if_num, netdev)) {
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700306 return NULL;
307 }
308
309 nss_core_register_subsys_dp(nss_ctx, if_num, NULL, NULL, app_ctx, netdev, features);
310
311 nss_top_main.pppoe_msg_callback = notification_callback;
312
313 nss_core_register_handler(nss_ctx, if_num, nss_pppoe_handler, NULL);
314
315 return nss_ctx;
316}
317EXPORT_SYMBOL(nss_register_pppoe_session_if);
318
319/*
320 * nss_unregister_pppoe_session_if()
321 */
322void nss_unregister_pppoe_session_if(uint32_t if_num)
323{
324 struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700325
326 nss_assert(nss_ctx);
327 nss_assert(nss_is_dynamic_interface(if_num));
328
Murat Sezgincdd23572019-06-27 13:07:23 -0700329 nss_pppoe_stats_pppoe_session_deinit(if_num);
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700330
331 nss_core_unregister_subsys_dp(nss_ctx, if_num);
332
333 nss_top_main.pppoe_msg_callback = NULL;
334
335 nss_core_unregister_handler(nss_ctx, if_num);
336
337}
338EXPORT_SYMBOL(nss_unregister_pppoe_session_if);
339
Amit Gupta1fe4d912019-03-19 15:57:10 +0530340static struct ctl_table nss_pppoe_table[] = {
341 {
342 .procname = "br_accel_mode",
343 .data = &nss_pppoe_br_accel_mode,
344 .maxlen = sizeof(int),
345 .mode = 0644,
346 .proc_handler = &nss_pppoe_br_accel_mode_handler,
347 },
348 { }
349};
350
351static struct ctl_table nss_pppoe_dir[] = {
352 {
353 .procname = "pppoe",
354 .mode = 0555,
355 .child = nss_pppoe_table,
356 },
357 { }
358};
359
360static struct ctl_table nss_pppoe_root_dir[] = {
361 {
362 .procname = "nss",
363 .mode = 0555,
364 .child = nss_pppoe_dir,
365 },
366 { }
367};
368
369static struct ctl_table nss_pppoe_root[] = {
370 {
371 .procname = "dev",
372 .mode = 0555,
373 .child = nss_pppoe_root_dir,
374 },
375 { }
376};
377
378static struct ctl_table_header *nss_pppoe_header;
379
380/*
381 * nss_pppoe_register_sysctl()
382 * Register sysctl specific to pppoe
383 */
384void nss_pppoe_register_sysctl(void)
385{
386 /*
387 * Register sysctl table.
388 */
389 nss_pppoe_header = register_sysctl_table(nss_pppoe_root);
390}
391
392/*
393 * nss_pppoe_unregister_sysctl()
394 * Unregister sysctl specific to pppoe
395 */
396void nss_pppoe_unregister_sysctl(void)
397{
398 /*
399 * Unregister sysctl table.
400 */
401 if (nss_pppoe_header) {
402 unregister_sysctl_table(nss_pppoe_header);
403 }
404}
405
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700406/*
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530407 * nss_pppoe_register_handler()
408 */
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700409void nss_pppoe_register_handler(void)
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530410{
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700411 nss_info("nss_pppoe_register_handler\n");
412 nss_core_register_handler(nss_pppoe_get_context(), NSS_PPPOE_INTERFACE, nss_pppoe_handler, NULL);
413
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700414 sema_init(&pppoe_pvt.sem, 1);
415 init_completion(&pppoe_pvt.complete);
Yu Huang8c107082017-07-24 14:58:26 -0700416
417 nss_pppoe_stats_dentry_create();
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530418}
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700419
420/*
421 * nss_pppoe_msg_init()
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700422 */
423void nss_pppoe_msg_init(struct nss_pppoe_msg *npm, uint16_t if_num, uint32_t type, uint32_t len,
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700424 void *cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700425{
426 nss_cmn_msg_init(&npm->cm, if_num, type, len, (void *)cb, app_data);
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700427
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700428}
Murat Sezgin4abd88c2017-05-24 17:00:59 -0700429EXPORT_SYMBOL(nss_pppoe_msg_init);