blob: e2a6b3b2b2a77973f9dfbbbc079593e2116efae9 [file] [log] [blame]
Sol Kavy879eb8b2014-04-07 19:11:31 -07001/*
2 **************************************************************************
Wayne Tanade9bcf2020-01-07 16:04:08 -08003 * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
Sol Kavy879eb8b2014-04-07 19:11:31 -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/*
18 * nss_ipv6.c
19 * NSS IPv6 APIs
20 */
Sakthi Vignesh Radhakrishnan120a2a62019-08-12 17:24:32 -070021#include <nss_core.h>
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070022#include "nss_dscp_map.h"
Yu Huang8c107082017-07-24 14:58:26 -070023#include "nss_ipv6_stats.h"
Wayne Tanade9bcf2020-01-07 16:04:08 -080024#include "nss_ipv6_strings.h"
Sol Kavy879eb8b2014-04-07 19:11:31 -070025
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070026#define NSS_IPV6_TX_MSG_TIMEOUT 1000 /* 1 sec timeout for IPv6 messages */
Stephen Wang0a2756a2016-08-04 15:52:47 -070027
28/*
29 * Private data structure for ipv6 configure messages
30 */
31struct nss_ipv6_cfg_pvt {
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070032 struct semaphore sem; /* Semaphore structure */
33 struct completion complete; /* Completion structure */
34 int response; /* Response from FW */
35 void *cb; /* Original cb for sync msgs */
36 void *app_data; /* Original app_data for sync msgs */
37} nss_ipv6_pvt;
Stephen Wang0a2756a2016-08-04 15:52:47 -070038
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -070039/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070040 * Private data structure for ipv6 connection information.
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -070041 */
42struct nss_ipv6_conn_table_info {
43 uint32_t ce_table_size; /* Size of connection entry table in NSS FW */
44 uint32_t cme_table_size; /* Size of connection match entry table in NSS FW */
45 unsigned long ce_mem; /* Start address for connection entry table */
46 unsigned long cme_mem; /* Start address for connection match entry table */
47} nss_ipv6_ct_info;
Stephen Wang0a2756a2016-08-04 15:52:47 -070048
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -070049int nss_ipv6_conn_cfg = NSS_DEFAULT_NUM_CONN;
Stephen Wangf6a9acb2017-08-23 10:35:39 -070050int nss_ipv6_accel_mode_cfg __read_mostly = 1;
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -070051
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070052static struct nss_dscp_map_entry mapping[NSS_DSCP_MAP_ARRAY_SIZE];
Vijay Dewangan9db18752014-09-15 16:25:01 -070053
Sol Kavy879eb8b2014-04-07 19:11:31 -070054/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -070055 * Callback for conn_sync_many request message.
56 */
57nss_ipv6_msg_callback_t nss_ipv6_conn_sync_many_msg_cb = NULL;
58
59/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070060 * nss_ipv6_dscp_map_usage()
61 * Help function shows the usage of the command.
Gareth Williams958aa822015-02-04 19:36:39 +000062 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070063static inline void nss_ipv6_dscp_map_usage(void)
Gareth Williams958aa822015-02-04 19:36:39 +000064{
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070065 nss_info_always("\nUsage:\n");
66 nss_info_always("echo <dscp> <action> <prio> > /proc/sys/dev/nss/ipv6cfg/ipv6_dscp_map\n\n");
67 nss_info_always("dscp[0-63] action[0-%u] prio[0-%u]:\n\n",
68 NSS_IPV6_DSCP_MAP_ACTION_MAX - 1,
69 NSS_DSCP_MAP_PRIORITY_MAX - 1);
Gareth Williams958aa822015-02-04 19:36:39 +000070}
Guojun Jin9a1cb282017-07-13 17:32:07 -070071
72/*
Sol Kavy879eb8b2014-04-07 19:11:31 -070073 * nss_ipv6_rx_msg_handler()
74 * Handle NSS -> HLOS messages for IPv6 bridge/route
75 */
76static void nss_ipv6_rx_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
77{
78 struct nss_ipv6_msg *nim = (struct nss_ipv6_msg *)ncm;
79 nss_ipv6_msg_callback_t cb;
80
81 BUG_ON(ncm->interface != NSS_IPV6_RX_INTERFACE);
82
83 /*
84 * Is this a valid request/response packet?
85 */
Murat Sezgin5c8c7362014-09-02 17:58:21 -070086 if (ncm->type >= NSS_IPV6_MAX_MSG_TYPES) {
Sol Kavy879eb8b2014-04-07 19:11:31 -070087 nss_warning("%p: received invalid message %d for IPv6 interface", nss_ctx, nim->cm.type);
88 return;
89 }
90
Suruchi Agarwalef8a8702016-01-08 12:40:08 -080091 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ipv6_msg)) {
92 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Sol Kavy879eb8b2014-04-07 19:11:31 -070093 return;
94 }
95
96 /*
Suruchi Agarwale3940e72016-07-06 15:56:51 -070097 * Trace messages.
Sol Kavy879eb8b2014-04-07 19:11:31 -070098 */
Suruchi Agarwale3940e72016-07-06 15:56:51 -070099 nss_ipv6_log_rx_msg(nim);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700100
101 /*
Stephen Wang0a2756a2016-08-04 15:52:47 -0700102 * Handle deprecated messages. Eventually these messages should be removed.
Sol Kavy879eb8b2014-04-07 19:11:31 -0700103 */
104 switch (nim->cm.type) {
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700105 case NSS_IPV6_RX_NODE_STATS_SYNC_MSG:
106 /*
Wayne Tanade9bcf2020-01-07 16:04:08 -0800107 * Update driver statistics on node sync and send statistics notifications to the registered modules.
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700108 */
Yu Huang8c107082017-07-24 14:58:26 -0700109 nss_ipv6_stats_node_sync(nss_ctx, &nim->msg.node_stats);
Wayne Tanade9bcf2020-01-07 16:04:08 -0800110 nss_ipv6_stats_notify(nss_ctx);
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700111 break;
112
Sol Kavy879eb8b2014-04-07 19:11:31 -0700113 case NSS_IPV6_RX_CONN_STATS_SYNC_MSG:
114 /*
115 * Update driver statistics on connection sync.
116 */
Yu Huang8c107082017-07-24 14:58:26 -0700117 nss_ipv6_stats_conn_sync(nss_ctx, &nim->msg.conn_stats);
Sakthi Vignesh Radhakrishnan515f8c22014-06-21 15:04:19 -0700118 break;
Stephen Wang709f9b52015-07-07 14:48:35 -0700119
120 case NSS_IPV6_TX_CONN_STATS_SYNC_MANY_MSG:
121 /*
122 * Update driver statistics on connection sync many.
123 */
Yu Huang8c107082017-07-24 14:58:26 -0700124 nss_ipv6_stats_conn_sync_many(nss_ctx, &nim->msg.conn_stats_many);
Stephen Wangaed46332016-12-12 17:29:03 -0800125 ncm->cb = (nss_ptr_t)nss_ipv6_conn_sync_many_msg_cb;
Stephen Wang709f9b52015-07-07 14:48:35 -0700126 break;
Sol Kavy879eb8b2014-04-07 19:11:31 -0700127 }
Abhishek Rastogi55f39452014-05-08 19:23:29 +0530128
Sol Kavy879eb8b2014-04-07 19:11:31 -0700129 /*
130 * Update the callback and app_data for NOTIFY messages, IPv6 sends all notify messages
131 * to the same callback/app_data.
132 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530133 if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800134 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->ipv6_callback;
135 ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->ipv6_ctx;
Sol Kavy879eb8b2014-04-07 19:11:31 -0700136 }
137
138 /*
139 * Do we have a callback?
140 */
141 if (!ncm->cb) {
142 return;
143 }
144
145 /*
146 * Callback
147 */
148 cb = (nss_ipv6_msg_callback_t)ncm->cb;
149 cb((void *)ncm->app_data, nim);
150}
151
152/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700153 * nss_ipv6_tx_sync_callback()
154 * Callback to handle the completion of synchronous tx messages.
155 */
156static void nss_ipv6_tx_sync_callback(void *app_data, struct nss_ipv6_msg *nim)
157{
158 nss_ipv6_msg_callback_t callback = (nss_ipv6_msg_callback_t)nss_ipv6_pvt.cb;
159 void *data = nss_ipv6_pvt.app_data;
160
161 nss_ipv6_pvt.cb = NULL;
162 nss_ipv6_pvt.app_data = NULL;
163
164 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
165 nss_warning("ipv6 error response %d\n", nim->cm.response);
166 nss_ipv6_pvt.response = NSS_TX_FAILURE;
167 } else {
168 nss_ipv6_pvt.response = NSS_TX_SUCCESS;
169 }
170
171 if (callback) {
172 callback(data, nim);
173 }
174
175 complete(&nss_ipv6_pvt.complete);
176}
177
178/*
179 * nss_ipv6_dscp_action_get()
180 * Gets the action mapped to dscp.
181 */
182enum nss_ipv6_dscp_map_actions nss_ipv6_dscp_action_get(uint8_t dscp)
183{
Sakthi Vignesh Radhakrishnan1f7a66b2017-10-18 09:33:22 -0700184 if (dscp >= NSS_DSCP_MAP_ARRAY_SIZE) {
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700185 nss_warning("dscp:%u invalid\n", dscp);
186 return NSS_IPV6_DSCP_MAP_ACTION_MAX;
187 }
188
189 return mapping[dscp].action;
190}
191EXPORT_SYMBOL(nss_ipv6_dscp_action_get);
192
193/*
194 * nss_ipv6_max_conn_count()
195 * Return the maximum number of IPv6 connections that the NSS acceleration engine supports.
196 */
197int nss_ipv6_max_conn_count(void)
198{
199 return nss_ipv6_conn_cfg;
200}
201EXPORT_SYMBOL(nss_ipv6_max_conn_count);
202
203/*
204 * nss_ipv6_conn_inquiry()
205 * Inquiry if a connection has been established in NSS FW
206 */
207nss_tx_status_t nss_ipv6_conn_inquiry(struct nss_ipv6_5tuple *ipv6_5t_p,
208 nss_ipv6_msg_callback_t cb)
209{
210 nss_tx_status_t nss_tx_status;
211 struct nss_ipv6_msg nim;
212 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[0];
213
214 /*
215 * Initialize inquiry message structure.
216 * This is async message and the result will be returned
217 * to the caller by the msg_callback passed in.
218 */
219 memset(&nim, 0, sizeof(nim));
220 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE,
221 NSS_IPV6_TX_CONN_CFG_INQUIRY_MSG,
222 sizeof(struct nss_ipv6_inquiry_msg),
223 cb, NULL);
224 nim.msg.inquiry.rr.tuple = *ipv6_5t_p;
225 nss_tx_status = nss_ipv6_tx(nss_ctx, &nim);
226 if (nss_tx_status != NSS_TX_SUCCESS) {
227 nss_warning("%p: Send inquiry message failed\n", ipv6_5t_p);
228 }
229
230 return nss_tx_status;
231}
232EXPORT_SYMBOL(nss_ipv6_conn_inquiry);
233
234/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700235 * nss_ipv6_tx_with_size()
236 * Transmit an ipv6 message to the FW with a specified size.
Sol Kavy879eb8b2014-04-07 19:11:31 -0700237 */
Stephen Wang709f9b52015-07-07 14:48:35 -0700238nss_tx_status_t nss_ipv6_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim, uint32_t size)
Sol Kavy879eb8b2014-04-07 19:11:31 -0700239{
Sol Kavy879eb8b2014-04-07 19:11:31 -0700240 struct nss_cmn_msg *ncm = &nim->cm;
Sol Kavy879eb8b2014-04-07 19:11:31 -0700241
242 /*
243 * Sanity check the message
244 */
245 if (ncm->interface != NSS_IPV6_RX_INTERFACE) {
246 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
247 return NSS_TX_FAILURE;
248 }
249
Murat Sezgin5c8c7362014-09-02 17:58:21 -0700250 if (ncm->type >= NSS_IPV6_MAX_MSG_TYPES) {
Sol Kavy879eb8b2014-04-07 19:11:31 -0700251 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
252 return NSS_TX_FAILURE;
253 }
254
Suruchi Agarwale3940e72016-07-06 15:56:51 -0700255 /*
256 * Trace messages.
257 */
258 nss_ipv6_log_tx_msg(nim);
259
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700260 return nss_core_send_cmd(nss_ctx, nim, sizeof(*nim), size);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700261}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700262EXPORT_SYMBOL(nss_ipv6_tx_with_size);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700263
264/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700265 * nss_ipv6_tx()
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700266 * Transmit an ipv6 message to the FW.
Stephen Wang709f9b52015-07-07 14:48:35 -0700267 */
268nss_tx_status_t nss_ipv6_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim)
269{
270 return nss_ipv6_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE);
271}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700272EXPORT_SYMBOL(nss_ipv6_tx);
Stephen Wang709f9b52015-07-07 14:48:35 -0700273
274/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700275 * nss_ipv6_tx_sync()
276 * Transmit a synchronous ipv6 message to the FW.
277 */
278nss_tx_status_t nss_ipv6_tx_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim)
279{
280 nss_tx_status_t status;
281 int ret = 0;
282
283 down(&nss_ipv6_pvt.sem);
284 nss_ipv6_pvt.cb = (void *)nim->cm.cb;
285 nss_ipv6_pvt.app_data = (void *)nim->cm.app_data;
286
287 nim->cm.cb = (nss_ptr_t)nss_ipv6_tx_sync_callback;
288 nim->cm.app_data = (nss_ptr_t)NULL;
289
290 status = nss_ipv6_tx(nss_ctx, nim);
291 if (status != NSS_TX_SUCCESS) {
292 nss_warning("%p: nss ipv6 msg tx failed\n", nss_ctx);
293 up(&nss_ipv6_pvt.sem);
294 return status;
295 }
296
297 ret = wait_for_completion_timeout(&nss_ipv6_pvt.complete, msecs_to_jiffies(NSS_IPV6_TX_MSG_TIMEOUT));
298 if (!ret) {
299 nss_warning("%p: IPv6 tx sync failed due to timeout\n", nss_ctx);
300 nss_ipv6_pvt.response = NSS_TX_FAILURE;
301 }
302
303 status = nss_ipv6_pvt.response;
304 up(&nss_ipv6_pvt.sem);
305 return status;
306}
307EXPORT_SYMBOL(nss_ipv6_tx_sync);
308
309/*
Sol Kavy879eb8b2014-04-07 19:11:31 -0700310 **********************************
311 Register/Unregister/Miscellaneous APIs
312 **********************************
313 */
314
315/*
316 * nss_ipv6_notify_register()
317 * Register to received IPv6 events.
318 *
319 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv6 on any core?
320 */
321struct nss_ctx_instance *nss_ipv6_notify_register(nss_ipv6_msg_callback_t cb, void *app_data)
322{
323 /*
324 * TODO: We need to have a new array in support of the new API
325 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
326 */
327 nss_top_main.ipv6_callback = cb;
328 nss_top_main.ipv6_ctx = app_data;
329 return &nss_top_main.nss[nss_top_main.ipv6_handler_id];
330}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700331EXPORT_SYMBOL(nss_ipv6_notify_register);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700332
333/*
334 * nss_ipv6_notify_unregister()
335 * Unregister to received IPv6 events.
336 *
337 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv6 on any core?
338 */
339void nss_ipv6_notify_unregister(void)
340{
341 nss_top_main.ipv6_callback = NULL;
342}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700343EXPORT_SYMBOL(nss_ipv6_notify_unregister);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700344
345/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700346 * nss_ipv6_conn_sync_many_notify_register()
347 * Register to receive IPv6 conn_sync_many message response.
348 */
349void nss_ipv6_conn_sync_many_notify_register(nss_ipv6_msg_callback_t cb)
350{
351 nss_ipv6_conn_sync_many_msg_cb = cb;
352}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700353EXPORT_SYMBOL(nss_ipv6_conn_sync_many_notify_register);
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700354
355/*
356 * nss_ipv6_conn_sync_many_notify_unregister()
357 * Unregister to receive IPv6 conn_sync_many message response.
358 */
359void nss_ipv6_conn_sync_many_notify_unregister(void)
360{
361 nss_ipv6_conn_sync_many_msg_cb = NULL;
362}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700363EXPORT_SYMBOL(nss_ipv6_conn_sync_many_notify_unregister);
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700364
365/*
Sol Kavy879eb8b2014-04-07 19:11:31 -0700366 * nss_ipv6_get_mgr()
367 *
368 * TODO: This only suppports a single ipv6, do we ever want to support more?
369 */
370struct nss_ctx_instance *nss_ipv6_get_mgr(void)
371{
372 return (void *)&nss_top_main.nss[nss_top_main.ipv6_handler_id];
373}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700374EXPORT_SYMBOL(nss_ipv6_get_mgr);
Sol Kavy879eb8b2014-04-07 19:11:31 -0700375
376/*
377 * nss_ipv6_register_handler()
378 * Register our handler to receive messages for this interface
379 */
380void nss_ipv6_register_handler()
381{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700382 struct nss_ctx_instance *nss_ctx = nss_ipv6_get_mgr();
383
384 if (nss_core_register_handler(nss_ctx, NSS_IPV6_RX_INTERFACE, nss_ipv6_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
Sol Kavy879eb8b2014-04-07 19:11:31 -0700385 nss_warning("IPv6 handler failed to register");
386 }
Yu Huang8c107082017-07-24 14:58:26 -0700387
388 nss_ipv6_stats_dentry_create();
Wayne Tanade9bcf2020-01-07 16:04:08 -0800389 nss_ipv6_strings_dentry_create();
Sol Kavy879eb8b2014-04-07 19:11:31 -0700390}
391
Vijay Dewangan9db18752014-09-15 16:25:01 -0700392/*
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700393 * nss_ipv6_conn_cfg_process_callback()
394 * Call back function for the ipv6 connection configuration process.
395 */
396static void nss_ipv6_conn_cfg_process_callback(void *app_data, struct nss_ipv6_msg *nim)
397{
398 struct nss_ipv6_rule_conn_cfg_msg *nirccm = &nim->msg.rule_conn_cfg;
399 struct nss_ctx_instance *nss_ctx __maybe_unused = nss_ipv6_get_mgr();
400
401 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
402 nss_warning("%p: IPv6 connection configuration failed with error: %d\n", nss_ctx, nim->cm.error);
Stephen Wang01433692017-10-30 14:45:11 -0700403 nss_core_update_max_ipv6_conn(NSS_FW_DEFAULT_NUM_CONN);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700404 nss_ipv6_free_conn_tables();
405 return;
406 }
407
408 nss_ipv6_conn_cfg = ntohl(nirccm->num_conn);
409
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700410 nss_info("%p: IPv6 connection configuration success: %d\n", nss_ctx, nim->cm.error);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700411}
412
413/*
Tushar Mathura3c18932015-08-24 20:27:21 +0530414 * nss_ipv6_conn_cfg_process()
415 * Process request to configure number of ipv6 connections
416 */
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700417static int nss_ipv6_conn_cfg_process(struct nss_ctx_instance *nss_ctx, int conn)
Tushar Mathura3c18932015-08-24 20:27:21 +0530418{
419 struct nss_ipv6_msg nim;
420 struct nss_ipv6_rule_conn_cfg_msg *nirccm;
421 nss_tx_status_t nss_tx_status;
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700422
423 if ((!nss_ipv6_ct_info.ce_table_size) || (!nss_ipv6_ct_info.cme_table_size)) {
424 nss_warning("%p: connection entry or connection match entry table size not available\n",
425 nss_ctx);
426 return -EINVAL;
427 }
428
429 nss_info("%p: IPv6 supported connections: %d\n", nss_ctx, conn);
430
431 nss_ipv6_ct_info.ce_mem = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
432 get_order(nss_ipv6_ct_info.ce_table_size));
433 if (!nss_ipv6_ct_info.ce_mem) {
434 nss_warning("%p: Memory allocation failed for IPv6 Connections: %d\n",
435 nss_ctx,
436 conn);
437 goto fail;
438 }
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700439 nss_info("%p: CE Memory allocated for IPv6 Connections: %d\n",
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700440 nss_ctx,
441 conn);
442
443 nss_ipv6_ct_info.cme_mem = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
444 get_order(nss_ipv6_ct_info.cme_table_size));
445 if (!nss_ipv6_ct_info.cme_mem) {
446 nss_warning("%p: Memory allocation failed for IPv6 Connections: %d\n",
447 nss_ctx,
448 conn);
449 goto fail;
450 }
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700451 nss_info("%p: CME Memory allocated for IPv6 Connections: %d\n",
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700452 nss_ctx,
453 conn);
454
455 memset(&nim, 0, sizeof(struct nss_ipv6_msg));
456 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CONN_CFG_RULE_MSG,
457 sizeof(struct nss_ipv6_rule_conn_cfg_msg), nss_ipv6_conn_cfg_process_callback, NULL);
458
459 nirccm = &nim.msg.rule_conn_cfg;
460 nirccm->num_conn = htonl(conn);
Suruchi Agarwal8c9e7162017-08-17 15:58:40 -0700461 nirccm->ce_mem = dma_map_single(nss_ctx->dev, (void *)nss_ipv6_ct_info.ce_mem, nss_ipv6_ct_info.ce_table_size, DMA_TO_DEVICE);
462 if (unlikely(dma_mapping_error(nss_ctx->dev, nirccm->ce_mem))) {
463 nss_warning("%p: DMA mapping failed for virtual address = %p", nss_ctx, (void *)nss_ipv6_ct_info.ce_mem);
464 goto fail;
465 }
466
467 nirccm->cme_mem = dma_map_single(nss_ctx->dev, (void *)nss_ipv6_ct_info.cme_mem, nss_ipv6_ct_info.cme_table_size, DMA_TO_DEVICE);
468 if (unlikely(dma_mapping_error(nss_ctx->dev, nirccm->cme_mem))) {
469 nss_warning("%p: DMA mapping failed for virtual address = %p", nss_ctx, (void *)nss_ipv6_ct_info.cme_mem);
470 goto fail;
471 }
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700472
473 nss_tx_status = nss_ipv6_tx(nss_ctx, &nim);
474 if (nss_tx_status != NSS_TX_SUCCESS) {
475 nss_warning("%p: nss_tx error setting IPv6 Connections: %d\n",
476 nss_ctx,
477 conn);
478 goto fail;
479 }
480
481 return 0;
482
483fail:
484 nss_ipv6_free_conn_tables();
485 return -EINVAL;
486}
487
488/*
489 * nss_ipv6_update_conn_count_callback()
490 * Call back function for the ipv6 get connection info message.
491 */
492static void nss_ipv6_update_conn_count_callback(void *app_data, struct nss_ipv6_msg *nim)
493{
494 struct nss_ipv6_rule_conn_get_table_size_msg *nircgts = &nim->msg.size;
495 struct nss_ctx_instance *nss_ctx = nss_ipv6_get_mgr();
496
497 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
498 nss_warning("%p: IPv6 fetch connection info failed with error: %d\n", nss_ctx, nim->cm.error);
Stephen Wang01433692017-10-30 14:45:11 -0700499 nss_core_update_max_ipv6_conn(NSS_FW_DEFAULT_NUM_CONN);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700500 return;
501 }
502
503 nss_info("IPv6 get connection info success\n");
504
505 nss_ipv6_ct_info.ce_table_size = ntohl(nircgts->ce_table_size);
506 nss_ipv6_ct_info.cme_table_size = ntohl(nircgts->cme_table_size);
507
508 if (nss_ipv6_conn_cfg_process(nss_ctx, ntohl(nircgts->num_conn)) != 0) {
509 nss_warning("%p: IPv6 connection entry or connection match entry table size\
510 not available\n", nss_ctx);
511 }
512
513 return;
514}
515
516/*
517 * nss_ipv6_update_conn_count()
518 * Sets the maximum number of IPv6 connections.
519 *
520 * It first gets the connection tables size information from NSS FW
521 * and then configures the connections in NSS FW.
522 */
523int nss_ipv6_update_conn_count(int ipv6_num_conn)
524{
525 struct nss_ctx_instance *nss_ctx = nss_ipv6_get_mgr();
526 struct nss_ipv6_msg nim;
527 struct nss_ipv6_rule_conn_get_table_size_msg *nircgts;
528 nss_tx_status_t nss_tx_status;
Tushar Mathura3c18932015-08-24 20:27:21 +0530529 uint32_t sum_of_conn;
530
531 /*
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700532 * By default, NSS FW is configured with default number of connections.
533 */
Stephen Wang01433692017-10-30 14:45:11 -0700534 if (ipv6_num_conn == NSS_FW_DEFAULT_NUM_CONN) {
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700535 nss_info("%p: Default number of connections (%d) already configured\n", nss_ctx, ipv6_num_conn);
536 return 0;
537 }
538
539 /*
Tushar Mathura3c18932015-08-24 20:27:21 +0530540 * Specifications for input
541 * 1) The input should be power of 2.
542 * 2) Input for ipv4 and ipv6 sum togther should not exceed 8k
543 * 3) Min. value should be at leat 256 connections. This is the
544 * minimum connections we will support for each of them.
545 */
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700546 sum_of_conn = nss_ipv4_conn_cfg + ipv6_num_conn;
547 if ((ipv6_num_conn & NSS_NUM_CONN_QUANTA_MASK) ||
Tushar Mathura3c18932015-08-24 20:27:21 +0530548 (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700549 (ipv6_num_conn < NSS_MIN_NUM_CONN)) {
Tushar Mathura3c18932015-08-24 20:27:21 +0530550 nss_warning("%p: input supported connections (%d) does not adhere\
551 specifications\n1) not power of 2,\n2) is less than \
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700552 min val: %d, OR\n IPv4/6 total exceeds %d\n",
Tushar Mathura3c18932015-08-24 20:27:21 +0530553 nss_ctx,
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700554 ipv6_num_conn,
Tushar Mathura3c18932015-08-24 20:27:21 +0530555 NSS_MIN_NUM_CONN,
556 NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6);
557 return -EINVAL;
558 }
559
Tushar Mathura3c18932015-08-24 20:27:21 +0530560 memset(&nim, 0, sizeof(struct nss_ipv6_msg));
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700561 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CONN_TABLE_SIZE_MSG,
562 sizeof(struct nss_ipv6_rule_conn_get_table_size_msg), nss_ipv6_update_conn_count_callback, NULL);
Tushar Mathura3c18932015-08-24 20:27:21 +0530563
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700564 nircgts = &nim.msg.size;
565 nircgts->num_conn = htonl(ipv6_num_conn);
Tushar Mathura3c18932015-08-24 20:27:21 +0530566 nss_tx_status = nss_ipv6_tx(nss_ctx, &nim);
Tushar Mathura3c18932015-08-24 20:27:21 +0530567 if (nss_tx_status != NSS_TX_SUCCESS) {
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700568 nss_warning("%p: Send acceleration mode message failed\n", nss_ctx);
569 return -EINVAL;
Tushar Mathura3c18932015-08-24 20:27:21 +0530570 }
571
572 return 0;
573}
574
575/*
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700576 * nss_ipv6_free_conn_tables()
577 * Frees memory allocated for connection tables
Vijay Dewangan9db18752014-09-15 16:25:01 -0700578 */
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700579void nss_ipv6_free_conn_tables(void)
Vijay Dewangan9db18752014-09-15 16:25:01 -0700580{
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700581 if (nss_ipv6_ct_info.ce_mem) {
582 free_pages(nss_ipv6_ct_info.ce_mem, get_order(nss_ipv6_ct_info.ce_table_size));
Vijay Dewangan9db18752014-09-15 16:25:01 -0700583 }
584
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700585 if (nss_ipv6_ct_info.cme_mem) {
586 free_pages(nss_ipv6_ct_info.cme_mem, get_order(nss_ipv6_ct_info.cme_table_size));
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700587 }
Vijay Dewangan9db18752014-09-15 16:25:01 -0700588
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700589 memset(&nss_ipv6_ct_info, 0, sizeof(struct nss_ipv6_conn_table_info));
590 return;
Tushar Mathura3c18932015-08-24 20:27:21 +0530591}
592
Stephen Wang0a2756a2016-08-04 15:52:47 -0700593/*
Stephen Wang0a2756a2016-08-04 15:52:47 -0700594 * nss_ipv6_accel_mode_cfg_handler()
595 * Configure acceleration mode for IPv6
596 */
597static int nss_ipv6_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
598{
599 struct nss_top_instance *nss_top = &nss_top_main;
600 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
601 struct nss_ipv6_msg nim;
602 struct nss_ipv6_accel_mode_cfg_msg *nipcm;
603 nss_tx_status_t nss_tx_status;
604 int ret = NSS_FAILURE;
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700605 int current_value;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700606
607 /*
608 * Take snap shot of current value
609 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700610 current_value = nss_ipv6_accel_mode_cfg;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700611
612 /*
613 * Write the variable with user input
614 */
615 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
616 if (ret || (!write)) {
Stephen Wang0a2756a2016-08-04 15:52:47 -0700617 return ret;
618 }
619
620 memset(&nim, 0, sizeof(struct nss_ipv6_msg));
621 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_ACCEL_MODE_CFG_MSG,
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700622 sizeof(struct nss_ipv6_accel_mode_cfg_msg), NULL, NULL);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700623
624 nipcm = &nim.msg.accel_mode_cfg;
625 nipcm->mode = htonl(nss_ipv6_accel_mode_cfg);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700626
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700627 nss_tx_status = nss_ipv6_tx_sync(nss_ctx, &nim);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700628 if (nss_tx_status != NSS_TX_SUCCESS) {
629 nss_warning("%p: Send acceleration mode message failed\n", nss_ctx);
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700630 nss_ipv6_accel_mode_cfg = current_value;
631 return -EIO;
632 }
633
634 return 0;
635}
636
637/*
638 * nss_ipv6_dscp_map_cfg_handler()
639 * Sysctl handler for dscp/pri mappings.
640 */
641static int nss_ipv6_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
642{
643 struct nss_top_instance *nss_top = &nss_top_main;
644 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
645 struct nss_dscp_map_parse out;
646 struct nss_ipv6_msg nim;
647 struct nss_ipv6_dscp2pri_cfg_msg *nipd2p;
648 nss_tx_status_t status;
649 int ret;
650
651 if (!write) {
652 return nss_dscp_map_print(ctl, buffer, lenp, ppos, mapping);
653 }
654
655 ret = nss_dscp_map_parse(ctl, buffer, lenp, ppos, &out);
656 if (ret) {
657 nss_warning("failed to parse dscp mapping:%d\n", ret);
658 return ret;
659 }
660
661 if (out.action >= NSS_IPV6_DSCP_MAP_ACTION_MAX) {
662 nss_warning("invalid action value: %d\n", out.action);
663 nss_ipv6_dscp_map_usage();
664 return -EINVAL;
665 }
666
667 memset(&nim, 0, sizeof(struct nss_ipv6_msg));
668 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_DSCP2PRI_CFG_MSG,
669 sizeof(struct nss_ipv6_dscp2pri_cfg_msg), NULL, NULL);
670
671 nipd2p = &nim.msg.dscp2pri_cfg;
672 nipd2p->dscp = out.dscp;
673 nipd2p->priority = out.priority;
674
675 status = nss_ipv6_tx_sync(nss_ctx, &nim);
676 if (status != NSS_TX_SUCCESS) {
677 nss_warning("%p: ipv6 dscp2pri config message failed\n", nss_ctx);
678 return -EFAULT;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700679 }
680
681 /*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700682 * NSS firmware acknowleged the configuration, so update the mapping
683 * table on HOST side as well.
Stephen Wang0a2756a2016-08-04 15:52:47 -0700684 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700685 mapping[out.dscp].action = out.action;
686 mapping[out.dscp].priority = out.priority;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700687
Stephen Wang0a2756a2016-08-04 15:52:47 -0700688 return 0;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700689}
690
Stephen Wang52e6d342016-03-29 15:02:33 -0700691static struct ctl_table nss_ipv6_table[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700692 {
Stephen Wang0a2756a2016-08-04 15:52:47 -0700693 .procname = "ipv6_accel_mode",
694 .data = &nss_ipv6_accel_mode_cfg,
695 .maxlen = sizeof(int),
696 .mode = 0644,
697 .proc_handler = &nss_ipv6_accel_mode_cfg_handler,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700698 },
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700699 {
700 .procname = "ipv6_dscp_map",
701 .data = &mapping[NSS_DSCP_MAP_ARRAY_SIZE],
702 .maxlen = sizeof(struct nss_dscp_map_entry),
703 .mode = 0644,
704 .proc_handler = &nss_ipv6_dscp_map_cfg_handler,
705 },
Vijay Dewangan9db18752014-09-15 16:25:01 -0700706 { }
707};
708
Stephen Wang52e6d342016-03-29 15:02:33 -0700709static struct ctl_table nss_ipv6_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700710 {
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700711 .procname = "ipv6cfg",
712 .mode = 0555,
713 .child = nss_ipv6_table,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700714 },
715 { }
716};
717
Stephen Wang52e6d342016-03-29 15:02:33 -0700718static struct ctl_table nss_ipv6_root_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700719 {
720 .procname = "nss",
721 .mode = 0555,
722 .child = nss_ipv6_dir,
723 },
724 { }
725};
726
Stephen Wang52e6d342016-03-29 15:02:33 -0700727static struct ctl_table nss_ipv6_root[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700728 {
729 .procname = "dev",
730 .mode = 0555,
731 .child = nss_ipv6_root_dir,
732 },
733 { }
734};
735
736static struct ctl_table_header *nss_ipv6_header;
737
738/*
739 * nss_ipv6_register_sysctl()
Kiran Kumar C.S.Kfadf92d2015-06-26 12:48:33 +0530740 * Register sysctl specific to ipv6
Vijay Dewangan9db18752014-09-15 16:25:01 -0700741 */
742void nss_ipv6_register_sysctl(void)
743{
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700744 sema_init(&nss_ipv6_pvt.sem, 1);
745 init_completion(&nss_ipv6_pvt.complete);
Stephen Wang49b474b2016-03-25 10:40:30 -0700746
Vijay Dewangan9db18752014-09-15 16:25:01 -0700747 /*
748 * Register sysctl table.
749 */
750 nss_ipv6_header = register_sysctl_table(nss_ipv6_root);
751}
752
753/*
754 * nss_ipv6_unregister_sysctl()
Kiran Kumar C.S.Kfadf92d2015-06-26 12:48:33 +0530755 * Unregister sysctl specific to ipv6
Vijay Dewangan9db18752014-09-15 16:25:01 -0700756 */
757void nss_ipv6_unregister_sysctl(void)
758{
759 /*
760 * Unregister sysctl table.
761 */
762 if (nss_ipv6_header) {
763 unregister_sysctl_table(nss_ipv6_header);
764 }
765}
766
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700767/*
768 * nss_ipv6_msg_init()
Stephen Wang0a2756a2016-08-04 15:52:47 -0700769 * Initialize IPv6 message.
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700770 */
771void nss_ipv6_msg_init(struct nss_ipv6_msg *nim, uint16_t if_num, uint32_t type, uint32_t len,
Sundarajan Srinivasan30a53d42015-01-30 10:52:08 -0800772 nss_ipv6_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700773{
774 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
775}
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700776EXPORT_SYMBOL(nss_ipv6_msg_init);