blob: 4c4ae7e6f07794787651734caa94cfb3b255c054 [file] [log] [blame]
Thomas Wu68250352014-04-02 18:59:40 -07001/*
2 **************************************************************************
Wayne Tan5b7b6e92020-01-21 12:26:44 -08003 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Thomas Wu68250352014-04-02 18:59:40 -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/*
Murat Sezgin5c8c7362014-09-02 17:58:21 -070018 * nss_ipv4.c
Thomas Wu68250352014-04-02 18:59:40 -070019 * NSS IPv4 APIs
20 */
Vijay Dewangan9db18752014-09-15 16:25:01 -070021#include <linux/sysctl.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_ipv4_stats.h"
Wayne Tan5b7b6e92020-01-21 12:26:44 -080024#include "nss_ipv4_strings.h"
Thomas Wu68250352014-04-02 18:59:40 -070025
Stephen Wang0a2756a2016-08-04 15:52:47 -070026#define NSS_IPV4_TX_MSG_TIMEOUT 1000 /* 1 sec timeout for IPv4 messages */
27
28/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070029 * Private data structure for ipv4 configuration
Stephen Wang0a2756a2016-08-04 15:52:47 -070030 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070031struct nss_ipv4_pvt {
32 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_ipv4_pvt;
Stephen Wang0a2756a2016-08-04 15:52:47 -070038
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -070039/*
40 * Private data structure for ipv4 connection information.
41 */
42struct nss_ipv4_conn_table_info {
43 uint32_t ce_table_size; /* Size of connection table entry in NSS FW */
44 uint32_t cme_table_size; /* Size of connection match table entry 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_ipv4_ct_info;
48
pavir099db842018-12-28 14:51:06 +053049int nss_ipv4_conn_cfg = NSS_DEFAULT_NUM_CONN;
Stephen Wang0a2756a2016-08-04 15:52:47 -070050int nss_ipv4_accel_mode_cfg __read_mostly = 1;
51
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
Thomas Wu68250352014-04-02 18:59:40 -070054/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -070055 * Callback for conn_sync_many request message.
56 */
57nss_ipv4_msg_callback_t nss_ipv4_conn_sync_many_msg_cb = NULL;
58
59/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -070060 * nss_ipv4_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_ipv4_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/ipv4cfg/ipv4_dscp_map\n\n");
67 nss_info_always("dscp[0-63] action[0-%u] prio[0-%u]:\n\n",
68 NSS_IPV4_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 Kavy2783c072014-04-05 12:53:13 -070073 * nss_ipv4_rx_msg_handler()
Thomas Wu68250352014-04-02 18:59:40 -070074 * Handle NSS -> HLOS messages for IPv4 bridge/route
75 */
Sol Kavy2783c072014-04-05 12:53:13 -070076static void nss_ipv4_rx_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
Thomas Wu68250352014-04-02 18:59:40 -070077{
78 struct nss_ipv4_msg *nim = (struct nss_ipv4_msg *)ncm;
Sol Kavy57d24b42014-04-05 13:45:36 -070079 nss_ipv4_msg_callback_t cb;
Thomas Wu68250352014-04-02 18:59:40 -070080
81 BUG_ON(ncm->interface != NSS_IPV4_RX_INTERFACE);
82
83 /*
84 * Sanity check the message type
85 */
Murat Sezgin5c8c7362014-09-02 17:58:21 -070086 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) {
Thomas Wu68250352014-04-02 18:59:40 -070087 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
88 return;
89 }
90
Suruchi Agarwalef8a8702016-01-08 12:40:08 -080091 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ipv4_msg)) {
92 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Thomas Wu68250352014-04-02 18:59:40 -070093 return;
94 }
95
Thomas Wu68250352014-04-02 18:59:40 -070096 /*
Suruchi Agarwale3940e72016-07-06 15:56:51 -070097 * Trace messages.
Thomas Wu68250352014-04-02 18:59:40 -070098 */
Suruchi Agarwale3940e72016-07-06 15:56:51 -070099 nss_ipv4_log_rx_msg(nim);
Thomas Wu68250352014-04-02 18:59:40 -0700100
Thomas Wu68250352014-04-02 18:59:40 -0700101 switch (nim->cm.type) {
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700102 case NSS_IPV4_RX_NODE_STATS_SYNC_MSG:
103 /*
Wayne Tan5b7b6e92020-01-21 12:26:44 -0800104 * Update driver statistics on node sync and send statistics notifications to the registered modules.
105 */
Yu Huang8c107082017-07-24 14:58:26 -0700106 nss_ipv4_stats_node_sync(nss_ctx, &nim->msg.node_stats);
Wayne Tan5b7b6e92020-01-21 12:26:44 -0800107 nss_ipv4_stats_notify(nss_ctx);
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700108 break;
109
Thomas Wu68250352014-04-02 18:59:40 -0700110 case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
Sol Kavy57d24b42014-04-05 13:45:36 -0700111 /*
112 * Update driver statistics on connection sync.
113 */
Yu Huang8c107082017-07-24 14:58:26 -0700114 nss_ipv4_stats_conn_sync(nss_ctx, &nim->msg.conn_stats);
Sakthi Vignesh Radhakrishnan515f8c22014-06-21 15:04:19 -0700115 break;
Stephen Wang709f9b52015-07-07 14:48:35 -0700116
117 case NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG:
118 /*
119 * Update driver statistics on connection sync many.
120 */
Yu Huang8c107082017-07-24 14:58:26 -0700121 nss_ipv4_stats_conn_sync_many(nss_ctx, &nim->msg.conn_stats_many);
Stephen Wangaed46332016-12-12 17:29:03 -0800122 ncm->cb = (nss_ptr_t)nss_ipv4_conn_sync_many_msg_cb;
Stephen Wang709f9b52015-07-07 14:48:35 -0700123 break;
Thomas Wu68250352014-04-02 18:59:40 -0700124 }
125
126 /*
Sol Kavy57d24b42014-04-05 13:45:36 -0700127 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
128 * to the same callback/app_data.
Thomas Wu68250352014-04-02 18:59:40 -0700129 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530130 if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800131 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->ipv4_callback;
132 ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->ipv4_ctx;
Sol Kavy57d24b42014-04-05 13:45:36 -0700133 }
Sol Kavy2783c072014-04-05 12:53:13 -0700134
Thomas Wu68250352014-04-02 18:59:40 -0700135 /*
136 * Do we have a callback?
137 */
138 if (!ncm->cb) {
139 return;
140 }
141
142 /*
143 * Callback
144 */
Sol Kavy57d24b42014-04-05 13:45:36 -0700145 cb = (nss_ipv4_msg_callback_t)ncm->cb;
Thomas Wu68250352014-04-02 18:59:40 -0700146 cb((void *)ncm->app_data, nim);
Thomas Wu68250352014-04-02 18:59:40 -0700147}
148
149/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700150 * nss_ipv4_tx_sync_callback()
151 * Callback to handle the completion of synchronous tx messages.
152 */
153static void nss_ipv4_tx_sync_callback(void *app_data, struct nss_ipv4_msg *nim)
154{
155 nss_ipv4_msg_callback_t callback = (nss_ipv4_msg_callback_t)nss_ipv4_pvt.cb;
156 void *data = nss_ipv4_pvt.app_data;
157
158 nss_ipv4_pvt.cb = NULL;
159 nss_ipv4_pvt.app_data = NULL;
160
161 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
162 nss_warning("ipv4 error response %d\n", nim->cm.response);
163 nss_ipv4_pvt.response = NSS_TX_FAILURE;
164 } else {
165 nss_ipv4_pvt.response = NSS_TX_SUCCESS;
166 }
167
168 if (callback) {
169 callback(data, nim);
170 }
171
172 complete(&nss_ipv4_pvt.complete);
173}
174
175/*
176 * nss_ipv4_dscp_action_get()
177 * Gets the action mapped to dscp.
178 */
179enum nss_ipv4_dscp_map_actions nss_ipv4_dscp_action_get(uint8_t dscp)
180{
Sakthi Vignesh Radhakrishnan1f7a66b2017-10-18 09:33:22 -0700181 if (dscp >= NSS_DSCP_MAP_ARRAY_SIZE) {
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700182 nss_warning("dscp:%u invalid\n", dscp);
183 return NSS_IPV4_DSCP_MAP_ACTION_MAX;
184 }
185
186 return mapping[dscp].action;
187}
188EXPORT_SYMBOL(nss_ipv4_dscp_action_get);
189
190/*
191 * nss_ipv4_max_conn_count()
192 * Return the maximum number of IPv4 connections that the NSS acceleration engine supports.
193 */
194int nss_ipv4_max_conn_count(void)
195{
196 return nss_ipv4_conn_cfg;
197}
198EXPORT_SYMBOL(nss_ipv4_max_conn_count);
199
200/*
201 * nss_ipv4_conn_inquiry()
202 * Inquiry if a connection has been established in NSS FW
203 */
204nss_tx_status_t nss_ipv4_conn_inquiry(struct nss_ipv4_5tuple *ipv4_5t_p,
205 nss_ipv4_msg_callback_t cb)
206{
207 nss_tx_status_t nss_tx_status;
208 struct nss_ipv4_msg nim;
209 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[0];
210
211 /*
212 * Initialize inquiry message structure.
213 * This is async message and the result will be returned
214 * to the caller by the msg_callback passed in.
215 */
216 memset(&nim, 0, sizeof(nim));
217 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE,
218 NSS_IPV4_TX_CONN_CFG_INQUIRY_MSG,
219 sizeof(struct nss_ipv4_inquiry_msg),
220 cb, NULL);
221 nim.msg.inquiry.rr.tuple = *ipv4_5t_p;
222 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
223 if (nss_tx_status != NSS_TX_SUCCESS) {
224 nss_warning("%p: Send inquiry message failed\n", ipv4_5t_p);
225 }
226
227 return nss_tx_status;
228}
229EXPORT_SYMBOL(nss_ipv4_conn_inquiry);
230
231/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700232 * nss_ipv4_tx_with_size()
233 * Transmit an ipv4 message to the FW with a specified size.
Thomas Wu68250352014-04-02 18:59:40 -0700234 */
Stephen Wang709f9b52015-07-07 14:48:35 -0700235nss_tx_status_t nss_ipv4_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim, uint32_t size)
Thomas Wu68250352014-04-02 18:59:40 -0700236{
Thomas Wu68250352014-04-02 18:59:40 -0700237 struct nss_cmn_msg *ncm = &nim->cm;
Thomas Wu68250352014-04-02 18:59:40 -0700238
239 /*
240 * Sanity check the message
241 */
242 if (ncm->interface != NSS_IPV4_RX_INTERFACE) {
243 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
244 return NSS_TX_FAILURE;
245 }
246
Murat Sezgin5c8c7362014-09-02 17:58:21 -0700247 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) {
Thomas Wu68250352014-04-02 18:59:40 -0700248 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
249 return NSS_TX_FAILURE;
250 }
251
Suruchi Agarwale3940e72016-07-06 15:56:51 -0700252 /*
253 * Trace messages.
254 */
255 nss_ipv4_log_tx_msg(nim);
256
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700257 return nss_core_send_cmd(nss_ctx, nim, sizeof(*nim), size);
Thomas Wu68250352014-04-02 18:59:40 -0700258}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700259EXPORT_SYMBOL(nss_ipv4_tx_with_size);
Thomas Wu68250352014-04-02 18:59:40 -0700260
261/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700262 * nss_ipv4_tx()
263 * Transmit an ipv4 message to the FW.
264 */
265nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
266{
267 return nss_ipv4_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE);
268}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700269EXPORT_SYMBOL(nss_ipv4_tx);
Stephen Wang709f9b52015-07-07 14:48:35 -0700270
271/*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700272 * nss_ipv4_tx_sync()
273 * Transmit a synchronous ipv4 message to the FW.
274 */
275nss_tx_status_t nss_ipv4_tx_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
276{
277 nss_tx_status_t status;
278 int ret = 0;
279
280 down(&nss_ipv4_pvt.sem);
281 nss_ipv4_pvt.cb = (void *)nim->cm.cb;
282 nss_ipv4_pvt.app_data = (void *)nim->cm.app_data;
283
284 nim->cm.cb = (nss_ptr_t)nss_ipv4_tx_sync_callback;
285 nim->cm.app_data = (nss_ptr_t)NULL;
286
287 status = nss_ipv4_tx(nss_ctx, nim);
288 if (status != NSS_TX_SUCCESS) {
289 nss_warning("%p: nss ipv4 msg tx failed\n", nss_ctx);
290 up(&nss_ipv4_pvt.sem);
291 return status;
292 }
293
294 ret = wait_for_completion_timeout(&nss_ipv4_pvt.complete, msecs_to_jiffies(NSS_IPV4_TX_MSG_TIMEOUT));
295 if (!ret) {
296 nss_warning("%p: IPv4 tx sync failed due to timeout\n", nss_ctx);
297 nss_ipv4_pvt.response = NSS_TX_FAILURE;
298 }
299
300 status = nss_ipv4_pvt.response;
301 up(&nss_ipv4_pvt.sem);
302 return status;
303}
304EXPORT_SYMBOL(nss_ipv4_tx_sync);
305
306/*
Thomas Wu68250352014-04-02 18:59:40 -0700307 **********************************
308 Register/Unregister/Miscellaneous APIs
309 **********************************
310 */
311
312/*
313 * nss_ipv4_notify_register()
314 * Register to received IPv4 events.
315 *
316 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
317 */
318struct nss_ctx_instance *nss_ipv4_notify_register(nss_ipv4_msg_callback_t cb, void *app_data)
319{
320 /*
321 * TODO: We need to have a new array in support of the new API
322 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
323 */
324 nss_top_main.ipv4_callback = cb;
Abhishek Rastogie11f47b2014-04-04 18:43:32 +0530325 nss_top_main.ipv4_ctx = app_data;
Thomas Wu68250352014-04-02 18:59:40 -0700326 return &nss_top_main.nss[nss_top_main.ipv4_handler_id];
327}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700328EXPORT_SYMBOL(nss_ipv4_notify_register);
Thomas Wu68250352014-04-02 18:59:40 -0700329
330/*
331 * nss_ipv4_notify_unregister()
332 * Unregister to received IPv4 events.
333 *
334 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
335 */
336void nss_ipv4_notify_unregister(void)
337{
338 nss_top_main.ipv4_callback = NULL;
339}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700340EXPORT_SYMBOL(nss_ipv4_notify_unregister);
Thomas Wu68250352014-04-02 18:59:40 -0700341
342/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700343 * nss_ipv4_conn_sync_many_notify_register()
344 * Register to receive IPv4 conn_sync_many message response.
345 */
346void nss_ipv4_conn_sync_many_notify_register(nss_ipv4_msg_callback_t cb)
347{
348 nss_ipv4_conn_sync_many_msg_cb = cb;
349}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700350EXPORT_SYMBOL(nss_ipv4_conn_sync_many_notify_register);
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700351
352/*
353 * nss_ipv4_conn_sync_many_notify_unregister()
354 * Unregister to receive IPv4 conn_sync_many message response.
355 */
356void nss_ipv4_conn_sync_many_notify_unregister(void)
357{
358 nss_ipv4_conn_sync_many_msg_cb = NULL;
359}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700360EXPORT_SYMBOL(nss_ipv4_conn_sync_many_notify_unregister);
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700361
362/*
Thomas Wu68250352014-04-02 18:59:40 -0700363 * nss_ipv4_get_mgr()
364 *
365 * TODO: This only suppports a single ipv4, do we ever want to support more?
366 */
367struct nss_ctx_instance *nss_ipv4_get_mgr(void)
368{
369 return (void *)&nss_top_main.nss[nss_top_main.ipv4_handler_id];
370}
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700371EXPORT_SYMBOL(nss_ipv4_get_mgr);
Thomas Wu68250352014-04-02 18:59:40 -0700372
373/*
374 * nss_ipv4_register_handler()
375 * Register our handler to receive messages for this interface
376 */
Sol Kavy2783c072014-04-05 12:53:13 -0700377void nss_ipv4_register_handler(void)
Thomas Wu68250352014-04-02 18:59:40 -0700378{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700379 struct nss_ctx_instance *nss_ctx = nss_ipv4_get_mgr();
380
381 if (nss_core_register_handler(nss_ctx, NSS_IPV4_RX_INTERFACE, nss_ipv4_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
Thomas Wu68250352014-04-02 18:59:40 -0700382 nss_warning("IPv4 handler failed to register");
383 }
Yu Huang8c107082017-07-24 14:58:26 -0700384
385 nss_ipv4_stats_dentry_create();
Wayne Tan5b7b6e92020-01-21 12:26:44 -0800386 nss_ipv4_strings_dentry_create();
Thomas Wu68250352014-04-02 18:59:40 -0700387}
388
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700389/*
390 * nss_ipv4_conn_cfg_process_callback()
391 * Call back function for the ipv4 connection configure process
392 */
393static void nss_ipv4_conn_cfg_process_callback(void *app_data, struct nss_ipv4_msg *nim)
394{
395 struct nss_ipv4_rule_conn_cfg_msg *nirccm = &nim->msg.rule_conn_cfg;
396 struct nss_ctx_instance *nss_ctx __maybe_unused = nss_ipv4_get_mgr();
397
398 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
399 nss_warning("%p: IPv4 connection configuration failed with error: %d\n", nss_ctx, nim->cm.error);
Stephen Wang01433692017-10-30 14:45:11 -0700400 nss_core_update_max_ipv4_conn(NSS_FW_DEFAULT_NUM_CONN);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700401 nss_ipv4_free_conn_tables();
402 return;
403 }
404
405 nss_ipv4_conn_cfg = ntohl(nirccm->num_conn);
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700406 nss_info("%p: IPv4 connection configuration success: %d\n", nss_ctx, nim->cm.error);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700407}
408
Vijay Dewangan9db18752014-09-15 16:25:01 -0700409/*
Tushar Mathura3c18932015-08-24 20:27:21 +0530410 * nss_ipv4_conn_cfg_process()
411 * Process request to configure number of ipv4 connections
412 */
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700413static int nss_ipv4_conn_cfg_process(struct nss_ctx_instance *nss_ctx, int conn)
Tushar Mathura3c18932015-08-24 20:27:21 +0530414{
415 struct nss_ipv4_msg nim;
416 struct nss_ipv4_rule_conn_cfg_msg *nirccm;
417 nss_tx_status_t nss_tx_status;
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700418
419 if ((!nss_ipv4_ct_info.ce_table_size) || (!nss_ipv4_ct_info.cme_table_size)) {
420 nss_warning("%p: connection entry or connection match entry table size not available\n",
421 nss_ctx);
422 return -EINVAL;
423 }
424
425 nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, conn);
426
427 nss_ipv4_ct_info.ce_mem = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
428 get_order(nss_ipv4_ct_info.ce_table_size));
429 if (!nss_ipv4_ct_info.ce_mem) {
430 nss_warning("%p: Memory allocation failed for IPv4 Connections: %d\n",
431 nss_ctx,
432 conn);
433 goto fail;
434 }
435
436 nss_ipv4_ct_info.cme_mem = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
437 get_order(nss_ipv4_ct_info.cme_table_size));
438 if (!nss_ipv4_ct_info.ce_mem) {
439 nss_warning("%p: Memory allocation failed for IPv4 Connections: %d\n",
440 nss_ctx,
441 conn);
442 goto fail;
443 }
444
445 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
446 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_CFG_RULE_MSG,
447 sizeof(struct nss_ipv4_rule_conn_cfg_msg), nss_ipv4_conn_cfg_process_callback, NULL);
448
449 nirccm = &nim.msg.rule_conn_cfg;
450 nirccm->num_conn = htonl(conn);
Suruchi Agarwal8c9e7162017-08-17 15:58:40 -0700451 nirccm->ce_mem = dma_map_single(nss_ctx->dev, (void *)nss_ipv4_ct_info.ce_mem, nss_ipv4_ct_info.ce_table_size, DMA_TO_DEVICE);
452 if (unlikely(dma_mapping_error(nss_ctx->dev, nirccm->ce_mem))) {
453 nss_warning("%p: DMA mapping failed for virtual address = %p", nss_ctx, (void *)nss_ipv4_ct_info.ce_mem);
454 goto fail;
455 }
456
457 nirccm->cme_mem = dma_map_single(nss_ctx->dev, (void *)nss_ipv4_ct_info.cme_mem, nss_ipv4_ct_info.cme_table_size, DMA_TO_DEVICE);
458 if (unlikely(dma_mapping_error(nss_ctx->dev, nirccm->cme_mem))) {
459 nss_warning("%p: DMA mapping failed for virtual address = %p", nss_ctx, (void *)nss_ipv4_ct_info.cme_mem);
460 goto fail;
461 }
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700462
463 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
464 if (nss_tx_status != NSS_TX_SUCCESS) {
465 nss_warning("%p: nss_tx error setting IPv4 Connections: %d\n",
466 nss_ctx,
467 conn);
468 goto fail;
469 }
470
471 return 0;
472
473fail:
474 nss_ipv4_free_conn_tables();
475 return -EINVAL;;
476}
477
478/*
479 * nss_ipv4_update_conn_count_callback()
480 * Callback function for the ipv4 get connection info message.
481 */
482static void nss_ipv4_update_conn_count_callback(void *app_data, struct nss_ipv4_msg *nim)
483{
484 struct nss_ipv4_rule_conn_get_table_size_msg *nircgts = &nim->msg.size;
485 struct nss_ctx_instance *nss_ctx = nss_ipv4_get_mgr();
486
487 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
488 nss_warning("%p: IPv4 fetch connection info failed with error: %d\n", nss_ctx, nim->cm.error);
Stephen Wang01433692017-10-30 14:45:11 -0700489 nss_core_update_max_ipv4_conn(NSS_FW_DEFAULT_NUM_CONN);
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700490 return;
491 }
492
493 nss_info("IPv4 get connection info success\n");
494
495 nss_ipv4_ct_info.ce_table_size = ntohl(nircgts->ce_table_size);
496 nss_ipv4_ct_info.cme_table_size = ntohl(nircgts->cme_table_size);
497
498 if (nss_ipv4_conn_cfg_process(nss_ctx, ntohl(nircgts->num_conn)) != 0) {
499 nss_warning("%p: IPv4 connection entry or connection match entry table size\
500 not available\n", nss_ctx);
501 }
502
503 return;
504}
505
506/*
507 * nss_ipv4_update_conn_count()
508 * Sets the maximum number of IPv4 connections.
509 *
510 * It first gets the connection tables size information from NSS FW
511 * and then configures the connections in NSS FW.
512 */
513int nss_ipv4_update_conn_count(int ipv4_num_conn)
514{
515 struct nss_ctx_instance *nss_ctx = nss_ipv4_get_mgr();
516 struct nss_ipv4_msg nim;
517 struct nss_ipv4_rule_conn_get_table_size_msg *nircgts;
518 nss_tx_status_t nss_tx_status;
Tushar Mathura3c18932015-08-24 20:27:21 +0530519 uint32_t sum_of_conn;
520
521 /*
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700522 * By default, NSS FW is configured with default number of connections.
523 */
Stephen Wang01433692017-10-30 14:45:11 -0700524 if (ipv4_num_conn == NSS_FW_DEFAULT_NUM_CONN) {
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700525 nss_info("%p: Default number of connections (%d) already configured\n", nss_ctx, ipv4_num_conn);
526 return 0;
527 }
528
529 /*
Tushar Mathura3c18932015-08-24 20:27:21 +0530530 * The input should be multiple of 1024.
531 * Input for ipv4 and ipv6 sum together should not exceed 8k
532 * Min. value should be at least 256 connections. This is the
533 * minimum connections we will support for each of them.
534 */
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700535 sum_of_conn = ipv4_num_conn + nss_ipv6_conn_cfg;
536 if ((ipv4_num_conn & NSS_NUM_CONN_QUANTA_MASK) ||
Tushar Mathura3c18932015-08-24 20:27:21 +0530537 (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700538 (ipv4_num_conn < NSS_MIN_NUM_CONN)) {
Tushar Mathura3c18932015-08-24 20:27:21 +0530539 nss_warning("%p: input supported connections (%d) does not adhere\
540 specifications\n1) not multiple of 1024,\n2) is less than \
Cemil Coskun7d9d9b32019-06-28 15:49:39 -0700541 min val: %d, OR\n IPv4/6 total exceeds %d\n",
Tushar Mathura3c18932015-08-24 20:27:21 +0530542 nss_ctx,
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700543 ipv4_num_conn,
Tushar Mathura3c18932015-08-24 20:27:21 +0530544 NSS_MIN_NUM_CONN,
545 NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6);
546 return -EINVAL;
547 }
548
Tushar Mathura3c18932015-08-24 20:27:21 +0530549 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700550 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_TABLE_SIZE_MSG,
551 sizeof(struct nss_ipv4_rule_conn_get_table_size_msg), nss_ipv4_update_conn_count_callback, NULL);
Tushar Mathura3c18932015-08-24 20:27:21 +0530552
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700553 nircgts = &nim.msg.size;
554 nircgts->num_conn = htonl(ipv4_num_conn);
Tushar Mathura3c18932015-08-24 20:27:21 +0530555 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
556
557 if (nss_tx_status != NSS_TX_SUCCESS) {
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700558 nss_warning("%p: Send fetch connection info message failed\n", nss_ctx);
559 return -EINVAL;
Tushar Mathura3c18932015-08-24 20:27:21 +0530560 }
561
562 return 0;
563}
564
Stephen Wang0a2756a2016-08-04 15:52:47 -0700565/*
Suruchi Agarwalcdcb5b42017-07-06 11:08:22 -0700566 * nss_ipv4_free_conn_tables()
567 * Frees memory allocated for connection tables
568 */
569void nss_ipv4_free_conn_tables(void)
570{
571 if (nss_ipv4_ct_info.ce_mem) {
572 free_pages(nss_ipv4_ct_info.ce_mem, get_order(nss_ipv4_ct_info.ce_table_size));
573 }
574
575 if (nss_ipv4_ct_info.cme_mem) {
576 free_pages(nss_ipv4_ct_info.cme_mem, get_order(nss_ipv4_ct_info.cme_table_size));
577 }
578
579 memset(&nss_ipv4_ct_info, 0, sizeof(struct nss_ipv4_conn_table_info));
580 return;
581}
582
583/*
Stephen Wang0a2756a2016-08-04 15:52:47 -0700584 * nss_ipv4_accel_mode_cfg_handler()
585 * Configure acceleration mode for IPv4
586 */
587static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
588{
589 struct nss_top_instance *nss_top = &nss_top_main;
590 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
591 struct nss_ipv4_msg nim;
592 struct nss_ipv4_accel_mode_cfg_msg *nipcm;
593 nss_tx_status_t nss_tx_status;
594 int ret = NSS_FAILURE;
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700595 int current_value;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700596
597 /*
598 * Take snap shot of current value
599 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700600 current_value = nss_ipv4_accel_mode_cfg;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700601
602 /*
603 * Write the variable with user input
604 */
605 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
606 if (ret || (!write)) {
Stephen Wang0a2756a2016-08-04 15:52:47 -0700607 return ret;
608 }
609
610 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
611 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_ACCEL_MODE_CFG_MSG,
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700612 sizeof(struct nss_ipv4_accel_mode_cfg_msg), NULL, NULL);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700613
614 nipcm = &nim.msg.accel_mode_cfg;
615 nipcm->mode = htonl(nss_ipv4_accel_mode_cfg);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700616
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700617 nss_tx_status = nss_ipv4_tx_sync(nss_ctx, &nim);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700618 if (nss_tx_status != NSS_TX_SUCCESS) {
619 nss_warning("%p: Send acceleration mode message failed\n", nss_ctx);
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700620 nss_ipv4_accel_mode_cfg = current_value;
621 return -EIO;
622 }
623
624 return 0;
625}
626
627/*
628 * nss_ipv4_dscp_map_cfg_handler()
629 * Sysctl handler for dscp/pri mappings.
630 */
631static int nss_ipv4_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
632{
633 struct nss_top_instance *nss_top = &nss_top_main;
634 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
635 struct nss_dscp_map_parse out;
636 struct nss_ipv4_msg nim;
637 struct nss_ipv4_dscp2pri_cfg_msg *nipd2p;
638 nss_tx_status_t status;
639 int ret;
640
641 if (!write) {
642 return nss_dscp_map_print(ctl, buffer, lenp, ppos, mapping);
643 }
644
645 ret = nss_dscp_map_parse(ctl, buffer, lenp, ppos, &out);
646 if (ret) {
647 nss_warning("failed to parse dscp mapping:%d\n", ret);
648 nss_ipv4_dscp_map_usage();
649 return ret;
650 }
651
652 if (out.action >= NSS_IPV4_DSCP_MAP_ACTION_MAX) {
653 nss_warning("invalid action value: %d\n", out.action);
654 nss_ipv4_dscp_map_usage();
655 return -EINVAL;
656 }
657
658 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
659 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_DSCP2PRI_CFG_MSG,
660 sizeof(struct nss_ipv4_dscp2pri_cfg_msg), NULL, NULL);
661
662 nipd2p = &nim.msg.dscp2pri_cfg;
663 nipd2p->dscp = out.dscp;
664 nipd2p->priority = out.priority;
665
666 status = nss_ipv4_tx_sync(nss_ctx, &nim);
667 if (status != NSS_TX_SUCCESS) {
668 nss_warning("%p: ipv4 dscp2pri config message failed\n", nss_ctx);
669 return -EFAULT;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700670 }
671
672 /*
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700673 * NSS firmware acknowleged the configuration, so update the mapping
674 * table on HOST side as well.
Stephen Wang0a2756a2016-08-04 15:52:47 -0700675 */
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700676 mapping[out.dscp].action = out.action;
677 mapping[out.dscp].priority = out.priority;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700678
Stephen Wang0a2756a2016-08-04 15:52:47 -0700679 return 0;
Stephen Wang0a2756a2016-08-04 15:52:47 -0700680}
681
Stephen Wang52e6d342016-03-29 15:02:33 -0700682static struct ctl_table nss_ipv4_table[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700683 {
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700684 .procname = "ipv4_accel_mode",
685 .data = &nss_ipv4_accel_mode_cfg,
686 .maxlen = sizeof(int),
687 .mode = 0644,
688 .proc_handler = &nss_ipv4_accel_mode_cfg_handler,
689 },
690 {
691 .procname = "ipv4_dscp_map",
692 .data = &mapping[NSS_DSCP_MAP_ARRAY_SIZE],
693 .maxlen = sizeof(struct nss_dscp_map_entry),
694 .mode = 0644,
695 .proc_handler = &nss_ipv4_dscp_map_cfg_handler,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700696 },
697 { }
698};
699
Stephen Wang52e6d342016-03-29 15:02:33 -0700700static struct ctl_table nss_ipv4_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700701 {
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700702 .procname = "ipv4cfg",
703 .mode = 0555,
704 .child = nss_ipv4_table,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700705 },
706 { }
707};
708
Stephen Wang52e6d342016-03-29 15:02:33 -0700709static struct ctl_table nss_ipv4_root_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700710 {
711 .procname = "nss",
712 .mode = 0555,
713 .child = nss_ipv4_dir,
714 },
715 { }
716};
717
Stephen Wang52e6d342016-03-29 15:02:33 -0700718static struct ctl_table nss_ipv4_root[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700719 {
720 .procname = "dev",
721 .mode = 0555,
722 .child = nss_ipv4_root_dir,
723 },
724 { }
725};
726
727static struct ctl_table_header *nss_ipv4_header;
728
729/*
730 * nss_ipv4_register_sysctl()
731 * Register sysctl specific to ipv4
732 */
733void nss_ipv4_register_sysctl(void)
734{
Sakthi Vignesh Radhakrishnan8d02a2d2017-09-06 14:38:59 -0700735 sema_init(&nss_ipv4_pvt.sem, 1);
736 init_completion(&nss_ipv4_pvt.complete);
Stephen Wang49b474b2016-03-25 10:40:30 -0700737
Vijay Dewangan9db18752014-09-15 16:25:01 -0700738 /*
739 * Register sysctl table.
740 */
741 nss_ipv4_header = register_sysctl_table(nss_ipv4_root);
742}
743
744/*
745 * nss_ipv4_unregister_sysctl()
746 * Unregister sysctl specific to ipv4
747 */
748void nss_ipv4_unregister_sysctl(void)
749{
750 /*
751 * Unregister sysctl table.
752 */
753 if (nss_ipv4_header) {
754 unregister_sysctl_table(nss_ipv4_header);
755 }
756}
757
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700758/*
759 * nss_ipv4_msg_init()
760 * Initialize IPv4 message.
761 */
762void nss_ipv4_msg_init(struct nss_ipv4_msg *nim, uint16_t if_num, uint32_t type, uint32_t len,
Sundarajan Srinivasan30a53d42015-01-30 10:52:08 -0800763 nss_ipv4_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700764{
765 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
766}
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700767EXPORT_SYMBOL(nss_ipv4_msg_init);