blob: b2b9e8aeb70ddc6de8a1881700938246d169bdea [file] [log] [blame]
Thomas Wu68250352014-04-02 18:59:40 -07001/*
2 **************************************************************************
Stephen Wangaed46332016-12-12 17:29:03 -08003 * Copyright (c) 2013-2017, 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>
Thomas Wu68250352014-04-02 18:59:40 -070022#include "nss_tx_rx_common.h"
Thomas Wu68250352014-04-02 18:59:40 -070023
Stephen Wang0a2756a2016-08-04 15:52:47 -070024#define NSS_IPV4_TX_MSG_TIMEOUT 1000 /* 1 sec timeout for IPv4 messages */
25
26/*
27 * Private data structure for ipv4 configure messages
28 */
29struct nss_ipv4_cfg_pvt {
30 struct semaphore sem; /* Semaphore structure */
31 struct completion complete; /* completion structure */
32 int current_value; /* valid entry */
33 int response; /* Response from FW */
34};
35
Vijay Dewangan4861f4e2014-10-14 16:56:35 -070036int nss_ipv4_conn_cfg __read_mostly = NSS_DEFAULT_NUM_CONN;
Stephen Wang0a2756a2016-08-04 15:52:47 -070037int nss_ipv4_accel_mode_cfg __read_mostly = 1;
38
39static struct nss_ipv4_cfg_pvt i4_conn_cfgp;
40static struct nss_ipv4_cfg_pvt i4_accel_mode_cfgp;
Vijay Dewangan9db18752014-09-15 16:25:01 -070041
Thomas Wu68250352014-04-02 18:59:40 -070042/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -070043 * Callback for conn_sync_many request message.
44 */
45nss_ipv4_msg_callback_t nss_ipv4_conn_sync_many_msg_cb = NULL;
46
47/*
Gareth Williams958aa822015-02-04 19:36:39 +000048 * nss_ipv4_max_conn_count()
49 * Return the maximum number of IPv4 connections that the NSS acceleration engine supports.
50 */
51int nss_ipv4_max_conn_count(void)
52{
Tushar Mathur55ba1302015-09-08 13:14:48 +053053 return nss_core_max_ipv4_conn_get();
Gareth Williams958aa822015-02-04 19:36:39 +000054}
55EXPORT_SYMBOL(nss_ipv4_max_conn_count);
56
57/*
Guojun Jin9a1cb282017-07-13 17:32:07 -070058 * nss_ipv4_conn_inquiry()
59 * Inquiry if a connection has been established in NSS FW
60 */
61nss_tx_status_t nss_ipv4_conn_inquiry(struct nss_ipv4_5tuple *ipv4_5t_p,
62 nss_ipv4_msg_callback_t cb)
63{
64 nss_tx_status_t nss_tx_status;
65 struct nss_ipv4_msg nim;
66 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[0];
67
68 /*
69 * Initialize inquiry message structure.
70 * This is async message and the result will be returned
71 * to the caller by the msg_callback passed in.
72 */
73 memset(&nim, 0, sizeof(nim));
74 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE,
75 NSS_IPV4_TX_CONN_CFG_INQUIRY_MSG,
76 sizeof(struct nss_ipv4_inquiry_msg),
77 cb, NULL);
78 nim.msg.inquiry.rr.tuple = *ipv4_5t_p;
79 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
80 if (nss_tx_status != NSS_TX_SUCCESS) {
81 nss_warning("%p: Send inquiry message failed\n", ipv4_5t_p);
82 }
83
84 return nss_tx_status;
85}
86EXPORT_SYMBOL(nss_ipv4_conn_inquiry);
87
88/*
Sol Kavy57d24b42014-04-05 13:45:36 -070089 * nss_ipv4_driver_conn_sync_update()
Thomas Wu68250352014-04-02 18:59:40 -070090 * Update driver specific information from the messsage.
91 */
Murat Sezgin0c0561d2014-04-09 18:55:58 -070092static void nss_ipv4_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs)
Thomas Wu68250352014-04-02 18:59:40 -070093{
Sol Kavy57d24b42014-04-05 13:45:36 -070094 struct nss_top_instance *nss_top = nss_ctx->nss_top;
Sol Kavy57d24b42014-04-05 13:45:36 -070095
Thomas Wu68250352014-04-02 18:59:40 -070096 /*
97 * Update statistics maintained by NSS driver
98 */
99 spin_lock_bh(&nss_top->stats_lock);
Thomas Wu68250352014-04-02 18:59:40 -0700100 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count;
101 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count;
102 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count;
103 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_BYTES] += nirs->flow_tx_byte_count + nirs->return_tx_byte_count;
Thomas Wu68250352014-04-02 18:59:40 -0700104 spin_unlock_bh(&nss_top->stats_lock);
105}
Thomas Wu68250352014-04-02 18:59:40 -0700106
107/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700108 * nss_ipv4_driver_conn_sync_many_update()
109 * Update driver specific information from the conn_sync_many messsage.
110 */
111static void nss_ipv4_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm)
112{
113 int i;
114
115 /*
116 * Sanity check for the stats count
117 */
118 if (nicsm->count * sizeof(struct nss_ipv4_conn_sync) >= nicsm->size) {
119 nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
120 return;
121 }
122
123 for (i = 0; i < nicsm->count; i++) {
124 nss_ipv4_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]);
125 }
126}
127
128/*
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700129 * nss_ipv4_driver_node_sync_update)
130 * Update driver specific information from the messsage.
131 */
132static void nss_ipv4_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins)
133{
134 struct nss_top_instance *nss_top = nss_ctx->nss_top;
135 uint32_t i;
136
137 /*
138 * Update statistics maintained by NSS driver
139 */
140 spin_lock_bh(&nss_top->stats_lock);
141 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
142 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
143 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped;
144 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
145 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
146
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700147 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_REQUESTS] += nins->ipv4_connection_create_requests;
148 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_COLLISIONS] += nins->ipv4_connection_create_collisions;
149 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_connection_create_invalid_interface;
150 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_connection_destroy_requests;
151 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_MISSES] += nins->ipv4_connection_destroy_misses;
152 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_HITS] += nins->ipv4_connection_hash_hits;
153 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_REORDERS] += nins->ipv4_connection_hash_reorders;
154 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_FLUSHES] += nins->ipv4_connection_flushes;
155 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_EVICTIONS] += nins->ipv4_connection_evictions;
Selin Dag60ea2b22014-11-05 09:36:22 -0800156 nss_top->stats_ipv4[NSS_STATS_IPV4_FRAGMENTATIONS] += nins->ipv4_fragmentations;
Kiran Kumar C.S.Kfadf92d2015-06-26 12:48:33 +0530157 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv4_mc_connection_create_requests;
158 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv4_mc_connection_update_requests;
159 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_mc_connection_create_invalid_interface;
160 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests;
161 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses;
162 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes;
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700163
164 for (i = 0; i < NSS_EXCEPTION_EVENT_IPV4_MAX; i++) {
165 nss_top->stats_if_exception_ipv4[i] += nins->exception_events[i];
166 }
167 spin_unlock_bh(&nss_top->stats_lock);
168}
169
170/*
Sol Kavy2783c072014-04-05 12:53:13 -0700171 * nss_ipv4_rx_msg_handler()
Thomas Wu68250352014-04-02 18:59:40 -0700172 * Handle NSS -> HLOS messages for IPv4 bridge/route
173 */
Sol Kavy2783c072014-04-05 12:53:13 -0700174static 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 -0700175{
176 struct nss_ipv4_msg *nim = (struct nss_ipv4_msg *)ncm;
Sol Kavy57d24b42014-04-05 13:45:36 -0700177 nss_ipv4_msg_callback_t cb;
Thomas Wu68250352014-04-02 18:59:40 -0700178
179 BUG_ON(ncm->interface != NSS_IPV4_RX_INTERFACE);
180
181 /*
182 * Sanity check the message type
183 */
Murat Sezgin5c8c7362014-09-02 17:58:21 -0700184 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) {
Thomas Wu68250352014-04-02 18:59:40 -0700185 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
186 return;
187 }
188
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800189 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ipv4_msg)) {
190 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Thomas Wu68250352014-04-02 18:59:40 -0700191 return;
192 }
193
Thomas Wu68250352014-04-02 18:59:40 -0700194 /*
Suruchi Agarwale3940e72016-07-06 15:56:51 -0700195 * Trace messages.
Thomas Wu68250352014-04-02 18:59:40 -0700196 */
Suruchi Agarwale3940e72016-07-06 15:56:51 -0700197 nss_ipv4_log_rx_msg(nim);
Thomas Wu68250352014-04-02 18:59:40 -0700198
Thomas Wu68250352014-04-02 18:59:40 -0700199 switch (nim->cm.type) {
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700200 case NSS_IPV4_RX_NODE_STATS_SYNC_MSG:
201 /*
202 * Update driver statistics on node sync.
203 */
204 nss_ipv4_driver_node_sync_update(nss_ctx, &nim->msg.node_stats);
205 break;
206
Thomas Wu68250352014-04-02 18:59:40 -0700207 case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
Sol Kavy57d24b42014-04-05 13:45:36 -0700208 /*
209 * Update driver statistics on connection sync.
210 */
211 nss_ipv4_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats);
Sakthi Vignesh Radhakrishnan515f8c22014-06-21 15:04:19 -0700212 break;
Stephen Wang709f9b52015-07-07 14:48:35 -0700213
214 case NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG:
215 /*
216 * Update driver statistics on connection sync many.
217 */
218 nss_ipv4_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many);
Stephen Wangaed46332016-12-12 17:29:03 -0800219 ncm->cb = (nss_ptr_t)nss_ipv4_conn_sync_many_msg_cb;
Stephen Wang709f9b52015-07-07 14:48:35 -0700220 break;
Thomas Wu68250352014-04-02 18:59:40 -0700221 }
222
223 /*
Sol Kavy57d24b42014-04-05 13:45:36 -0700224 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
225 * to the same callback/app_data.
Thomas Wu68250352014-04-02 18:59:40 -0700226 */
Sol Kavy57d24b42014-04-05 13:45:36 -0700227 if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800228 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->ipv4_callback;
229 ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->ipv4_ctx;
Sol Kavy57d24b42014-04-05 13:45:36 -0700230 }
Sol Kavy2783c072014-04-05 12:53:13 -0700231
Thomas Wu68250352014-04-02 18:59:40 -0700232 /*
233 * Do we have a callback?
234 */
235 if (!ncm->cb) {
236 return;
237 }
238
239 /*
240 * Callback
241 */
Sol Kavy57d24b42014-04-05 13:45:36 -0700242 cb = (nss_ipv4_msg_callback_t)ncm->cb;
Thomas Wu68250352014-04-02 18:59:40 -0700243 cb((void *)ncm->app_data, nim);
Thomas Wu68250352014-04-02 18:59:40 -0700244}
245
246/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700247 * nss_ipv4_tx_with_size()
248 * Transmit an ipv4 message to the FW with a specified size.
Thomas Wu68250352014-04-02 18:59:40 -0700249 */
Stephen Wang709f9b52015-07-07 14:48:35 -0700250nss_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 -0700251{
252 struct nss_ipv4_msg *nim2;
253 struct nss_cmn_msg *ncm = &nim->cm;
254 struct sk_buff *nbuf;
255 int32_t status;
256
257 NSS_VERIFY_CTX_MAGIC(nss_ctx);
258 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
259 nss_warning("%p: ipv4 msg dropped as core not ready", nss_ctx);
260 return NSS_TX_FAILURE_NOT_READY;
261 }
262
263 /*
264 * Sanity check the message
265 */
266 if (ncm->interface != NSS_IPV4_RX_INTERFACE) {
267 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
268 return NSS_TX_FAILURE;
269 }
270
Murat Sezgin5c8c7362014-09-02 17:58:21 -0700271 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) {
Thomas Wu68250352014-04-02 18:59:40 -0700272 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
273 return NSS_TX_FAILURE;
274 }
275
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800276 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_ipv4_msg)) {
277 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
Thomas Wu68250352014-04-02 18:59:40 -0700278 return NSS_TX_FAILURE;
279 }
280
Stephen Wang709f9b52015-07-07 14:48:35 -0700281 if(size > PAGE_SIZE) {
282 nss_warning("%p: tx request size too large: %u", nss_ctx, size);
283 return NSS_TX_FAILURE;
284 }
285
286 nbuf = dev_alloc_skb(size);
Thomas Wu68250352014-04-02 18:59:40 -0700287 if (unlikely(!nbuf)) {
Sundarajan Srinivasan62fee7e2015-01-22 11:13:10 -0800288 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
Thomas Wu68250352014-04-02 18:59:40 -0700289 nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
290 return NSS_TX_FAILURE;
291 }
292
293 /*
294 * Copy the message to our skb.
295 */
Suruchi Agarwalea2e5232016-09-14 10:32:08 -0700296 nim2 = (struct nss_ipv4_msg *)skb_put(nbuf, size);
Thomas Wu68250352014-04-02 18:59:40 -0700297 memcpy(nim2, nim, sizeof(struct nss_ipv4_msg));
298
Suruchi Agarwale3940e72016-07-06 15:56:51 -0700299 /*
300 * Trace messages.
301 */
302 nss_ipv4_log_tx_msg(nim);
303
Thomas Wu68250352014-04-02 18:59:40 -0700304 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
305 if (status != NSS_CORE_STATUS_SUCCESS) {
Pamidipati, Vijayb6e38842014-09-16 10:26:05 +0530306 dev_kfree_skb_any(nbuf);
Sol Kavycd1bd5c2014-04-04 11:09:44 -0700307 nss_warning("%p: unable to enqueue IPv4 msg\n", nss_ctx);
Thomas Wu68250352014-04-02 18:59:40 -0700308 return NSS_TX_FAILURE;
309 }
310
Stephen Wang90c67de2016-04-26 15:15:59 -0700311 nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
Thomas Wu68250352014-04-02 18:59:40 -0700312
313 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
314 return NSS_TX_SUCCESS;
315}
316
317/*
Stephen Wang709f9b52015-07-07 14:48:35 -0700318 * nss_ipv4_tx()
319 * Transmit an ipv4 message to the FW.
320 */
321nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
322{
323 return nss_ipv4_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE);
324}
325
326/*
Thomas Wu68250352014-04-02 18:59:40 -0700327 **********************************
328 Register/Unregister/Miscellaneous APIs
329 **********************************
330 */
331
332/*
333 * nss_ipv4_notify_register()
334 * Register to received IPv4 events.
335 *
336 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
337 */
338struct nss_ctx_instance *nss_ipv4_notify_register(nss_ipv4_msg_callback_t cb, void *app_data)
339{
340 /*
341 * TODO: We need to have a new array in support of the new API
342 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
343 */
344 nss_top_main.ipv4_callback = cb;
Abhishek Rastogie11f47b2014-04-04 18:43:32 +0530345 nss_top_main.ipv4_ctx = app_data;
Thomas Wu68250352014-04-02 18:59:40 -0700346 return &nss_top_main.nss[nss_top_main.ipv4_handler_id];
347}
348
349/*
350 * nss_ipv4_notify_unregister()
351 * Unregister to received IPv4 events.
352 *
353 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
354 */
355void nss_ipv4_notify_unregister(void)
356{
357 nss_top_main.ipv4_callback = NULL;
358}
359
360/*
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700361 * nss_ipv4_conn_sync_many_notify_register()
362 * Register to receive IPv4 conn_sync_many message response.
363 */
364void nss_ipv4_conn_sync_many_notify_register(nss_ipv4_msg_callback_t cb)
365{
366 nss_ipv4_conn_sync_many_msg_cb = cb;
367}
368
369/*
370 * nss_ipv4_conn_sync_many_notify_unregister()
371 * Unregister to receive IPv4 conn_sync_many message response.
372 */
373void nss_ipv4_conn_sync_many_notify_unregister(void)
374{
375 nss_ipv4_conn_sync_many_msg_cb = NULL;
376}
377
378/*
Thomas Wu68250352014-04-02 18:59:40 -0700379 * nss_ipv4_get_mgr()
380 *
381 * TODO: This only suppports a single ipv4, do we ever want to support more?
382 */
383struct nss_ctx_instance *nss_ipv4_get_mgr(void)
384{
385 return (void *)&nss_top_main.nss[nss_top_main.ipv4_handler_id];
386}
387
388/*
389 * nss_ipv4_register_handler()
390 * Register our handler to receive messages for this interface
391 */
Sol Kavy2783c072014-04-05 12:53:13 -0700392void nss_ipv4_register_handler(void)
Thomas Wu68250352014-04-02 18:59:40 -0700393{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700394 struct nss_ctx_instance *nss_ctx = nss_ipv4_get_mgr();
395
396 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 -0700397 nss_warning("IPv4 handler failed to register");
398 }
399}
400
Vijay Dewangan9db18752014-09-15 16:25:01 -0700401/*
Tushar Mathura3c18932015-08-24 20:27:21 +0530402 * nss_ipv4_conn_cfg_process()
403 * Process request to configure number of ipv4 connections
404 */
405static int nss_ipv4_conn_cfg_process(struct nss_ctx_instance *nss_ctx, int conn,
406 void (*cfg_cb)(void *app_data, struct nss_ipv4_msg *nim))
407{
408 struct nss_ipv4_msg nim;
409 struct nss_ipv4_rule_conn_cfg_msg *nirccm;
410 nss_tx_status_t nss_tx_status;
411 uint32_t sum_of_conn;
412
413 /*
414 * The input should be multiple of 1024.
415 * Input for ipv4 and ipv6 sum together should not exceed 8k
416 * Min. value should be at least 256 connections. This is the
417 * minimum connections we will support for each of them.
418 */
419 sum_of_conn = conn + nss_ipv6_conn_cfg;
420 if ((conn & NSS_NUM_CONN_QUANTA_MASK) ||
421 (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
422 (conn < NSS_MIN_NUM_CONN)) {
423 nss_warning("%p: input supported connections (%d) does not adhere\
424 specifications\n1) not multiple of 1024,\n2) is less than \
425 min val: %d, OR\n IPv4/6 total exceeds %d\n",
426 nss_ctx,
427 conn,
428 NSS_MIN_NUM_CONN,
429 NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6);
430 return -EINVAL;
431 }
432
433 nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, conn);
434
435 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
436 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_CFG_RULE_MSG,
437 sizeof(struct nss_ipv4_rule_conn_cfg_msg), cfg_cb, NULL);
438
439 nirccm = &nim.msg.rule_conn_cfg;
440 nirccm->num_conn = htonl(conn);
441 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
442
443 if (nss_tx_status != NSS_TX_SUCCESS) {
444 nss_warning("%p: nss_tx error setting IPv4 Connections: %d\n",
445 nss_ctx,
446 conn);
447 return -EIO;
448 }
449
450 return 0;
451}
452
453/*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700454 * nss_ipv4_conn_cfg_callback()
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700455 * call back function for the ipv4 connection configuration handler
Vijay Dewangan9db18752014-09-15 16:25:01 -0700456 */
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700457static void nss_ipv4_conn_cfg_callback(void *app_data, struct nss_ipv4_msg *nim)
Vijay Dewangan9db18752014-09-15 16:25:01 -0700458{
459
460 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
461 nss_warning("IPv4 connection configuration failed with error: %d\n", nim->cm.error);
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700462 /*
463 * Error, hence we are not updating the nss_ipv4_conn_cfg
464 * Restore the current_value to its previous state
465 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700466 i4_conn_cfgp.response = NSS_FAILURE;
467 complete(&i4_conn_cfgp.complete);
Vijay Dewangan9db18752014-09-15 16:25:01 -0700468 return;
469 }
470
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700471 /*
472 * Sucess at NSS FW, hence updating nss_ipv4_conn_cfg, with the valid value
473 * saved at the sysctl handler.
474 */
Vijay Dewangan9db18752014-09-15 16:25:01 -0700475 nss_info("IPv4 connection configuration success: %d\n", nim->cm.error);
Stephen Wang0a2756a2016-08-04 15:52:47 -0700476 i4_conn_cfgp.response = NSS_SUCCESS;
477 complete(&i4_conn_cfgp.complete);
Vijay Dewangan9db18752014-09-15 16:25:01 -0700478}
479
480/*
481 * nss_ipv4_conn_cfg_handler()
482 * Sets the number of connections for IPv4
483 */
Stephen Wang52e6d342016-03-29 15:02:33 -0700484static int nss_ipv4_conn_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
Vijay Dewangan9db18752014-09-15 16:25:01 -0700485{
486 struct nss_top_instance *nss_top = &nss_top_main;
487 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
Vijay Dewangan488e5372014-12-29 21:40:11 -0800488 int ret = NSS_FAILURE;
Vijay Dewangan9db18752014-09-15 16:25:01 -0700489
490 /*
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700491 * Acquiring semaphore
492 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700493 down(&i4_conn_cfgp.sem);
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700494
495 /*
496 * Take snap shot of current value
497 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700498 i4_conn_cfgp.current_value = nss_ipv4_conn_cfg;
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700499
500 /*
501 * Write the variable with user input
502 */
503 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
504 if (ret || (!write)) {
Stephen Wang0a2756a2016-08-04 15:52:47 -0700505 up(&i4_conn_cfgp.sem);
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700506 return ret;
507 }
508
509 /*
Tushar Mathura3c18932015-08-24 20:27:21 +0530510 * Process request to change number of IPv4 connections
Vijay Dewangan9db18752014-09-15 16:25:01 -0700511 */
Tushar Mathura3c18932015-08-24 20:27:21 +0530512 ret = nss_ipv4_conn_cfg_process(nss_ctx, nss_ipv4_conn_cfg, nss_ipv4_conn_cfg_callback);
513 if (ret != 0) {
Stephen Wang06761022015-03-03 16:38:42 -0800514 goto failure;
Vijay Dewangan9db18752014-09-15 16:25:01 -0700515 }
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700516
517 /*
518 * Blocking call, wait till we get ACK for this msg.
519 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700520 ret = wait_for_completion_timeout(&i4_conn_cfgp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700521 if (ret == 0) {
522 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
Stephen Wang06761022015-03-03 16:38:42 -0800523 goto failure;
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700524 }
525
526 /*
527 * ACK/NACK received from NSS FW
528 * If ACK: Callback function will update nss_ipv4_conn_cfg with
Stephen Wang0a2756a2016-08-04 15:52:47 -0700529 * i4_conn_cfgp.num_conn_valid, which holds the user input
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700530 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700531 if (NSS_FAILURE == i4_conn_cfgp.response) {
Stephen Wang06761022015-03-03 16:38:42 -0800532 goto failure;
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700533 }
534
Stephen Wang0a2756a2016-08-04 15:52:47 -0700535 up(&i4_conn_cfgp.sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700536 return 0;
Stephen Wang06761022015-03-03 16:38:42 -0800537
538failure:
539 /*
540 * Restore the current_value to its previous state
541 */
Stephen Wang0a2756a2016-08-04 15:52:47 -0700542 nss_ipv4_conn_cfg = i4_conn_cfgp.current_value;
543 up(&i4_conn_cfgp.sem);
Thomas Wu651b3902015-05-12 11:21:09 -0700544 return -EINVAL;
Vijay Dewangan9db18752014-09-15 16:25:01 -0700545}
546
Tushar Mathura3c18932015-08-24 20:27:21 +0530547/*
548 * nss_ipv4_update_conn_count_cb()
549 * call back function for the ipv4 connection count update handler
550 */
551static void nss_ipv4_update_conn_count_cb(void *app_data, struct nss_ipv4_msg *nim)
552{
553 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
554 nss_warning("IPv4 connection count update failed with error: %d\n", nim->cm.error);
555 return;
556 }
557
558 nss_warning("IPv4 connection count update success: %d\n", nim->cm.error);
559}
560
561/*
562 * nss_ipv4_update_conn_count()
563 * Sets the maximum number of connections for IPv4
564 */
565int nss_ipv4_update_conn_count(int ipv4_num_conn)
566{
567 struct nss_top_instance *nss_top = &nss_top_main;
568 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
569 int saved_nss_ipv4_conn_cfg = nss_ipv4_conn_cfg;
570 int ret = 0;
571
572 nss_ipv4_conn_cfg = ipv4_num_conn;
573
574 /*
575 * Process request to change number of IPv4 connections
576 */
577 ret = nss_ipv4_conn_cfg_process(nss_ctx, nss_ipv4_conn_cfg,
578 nss_ipv4_update_conn_count_cb);
579 if (ret != 0) {
580 nss_ipv4_conn_cfg = saved_nss_ipv4_conn_cfg;
581 return ret;
582 }
583
584 return 0;
585}
586
Stephen Wang0a2756a2016-08-04 15:52:47 -0700587/*
588 * nss_ipv4_accel_mode_cfg_callback()
589 * call back function for the ipv4 acceleration mode configurate handler
590 */
591static void nss_ipv4_accel_mode_cfg_callback(void *app_data, struct nss_ipv4_msg *nim)
592{
593 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
594 nss_warning("IPv4 acceleration mode configuration failed with error: %d\n", nim->cm.error);
595 i4_accel_mode_cfgp.response = NSS_FAILURE;
596 complete(&i4_accel_mode_cfgp.complete);
597 return;
598 }
599
600 nss_info("IPv4 acceleration mode configuration success\n");
601 i4_accel_mode_cfgp.response = NSS_SUCCESS;
602 complete(&i4_accel_mode_cfgp.complete);
603}
604
605/*
606 * nss_ipv4_accel_mode_cfg_handler()
607 * Configure acceleration mode for IPv4
608 */
609static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
610{
611 struct nss_top_instance *nss_top = &nss_top_main;
612 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
613 struct nss_ipv4_msg nim;
614 struct nss_ipv4_accel_mode_cfg_msg *nipcm;
615 nss_tx_status_t nss_tx_status;
616 int ret = NSS_FAILURE;
617
618 /*
619 * Acquiring semaphore
620 */
621 down(&i4_accel_mode_cfgp.sem);
622
623 /*
624 * Take snap shot of current value
625 */
626 i4_accel_mode_cfgp.current_value = nss_ipv4_accel_mode_cfg;
627
628 /*
629 * Write the variable with user input
630 */
631 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
632 if (ret || (!write)) {
633 up(&i4_accel_mode_cfgp.sem);
634 return ret;
635 }
636
637 memset(&nim, 0, sizeof(struct nss_ipv4_msg));
638 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_ACCEL_MODE_CFG_MSG,
639 sizeof(struct nss_ipv4_accel_mode_cfg_msg), nss_ipv4_accel_mode_cfg_callback, NULL);
640
641 nipcm = &nim.msg.accel_mode_cfg;
642 nipcm->mode = htonl(nss_ipv4_accel_mode_cfg);
643 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim);
644
645 if (nss_tx_status != NSS_TX_SUCCESS) {
646 nss_warning("%p: Send acceleration mode message failed\n", nss_ctx);
647 goto fail;
648 }
649
650 /*
651 * Blocking call, wait till we get ACK for this msg.
652 */
653 ret = wait_for_completion_timeout(&i4_accel_mode_cfgp.complete, msecs_to_jiffies(NSS_IPV4_TX_MSG_TIMEOUT));
654 if (ret == 0) {
655 nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
656 goto fail;
657 }
658
659 if (NSS_FAILURE == i4_accel_mode_cfgp.response) {
660 nss_warning("%p: accel mode configure failed\n", nss_ctx);
661 goto fail;
662 }
663
664 up(&i4_accel_mode_cfgp.sem);
665 return 0;
666
667fail:
668 nss_ipv4_accel_mode_cfg = i4_accel_mode_cfgp.current_value;
669 up(&i4_accel_mode_cfgp.sem);
670 return -EIO;
671}
672
Stephen Wang52e6d342016-03-29 15:02:33 -0700673static struct ctl_table nss_ipv4_table[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700674 {
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700675 .procname = "ipv4_conn",
676 .data = &nss_ipv4_conn_cfg,
677 .maxlen = sizeof(int),
678 .mode = 0644,
Stephen Wang0a2756a2016-08-04 15:52:47 -0700679 .proc_handler = &nss_ipv4_conn_cfg_handler,
680 },
681 {
682 .procname = "ipv4_accel_mode",
683 .data = &nss_ipv4_accel_mode_cfg,
684 .maxlen = sizeof(int),
685 .mode = 0644,
686 .proc_handler = &nss_ipv4_accel_mode_cfg_handler,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700687 },
688 { }
689};
690
Stephen Wang52e6d342016-03-29 15:02:33 -0700691static struct ctl_table nss_ipv4_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700692 {
Vijay Dewangan4861f4e2014-10-14 16:56:35 -0700693 .procname = "ipv4cfg",
694 .mode = 0555,
695 .child = nss_ipv4_table,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700696 },
697 { }
698};
699
700
Stephen Wang52e6d342016-03-29 15:02:33 -0700701static struct ctl_table nss_ipv4_root_dir[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700702 {
703 .procname = "nss",
704 .mode = 0555,
705 .child = nss_ipv4_dir,
706 },
707 { }
708};
709
Stephen Wang52e6d342016-03-29 15:02:33 -0700710static struct ctl_table nss_ipv4_root[] = {
Vijay Dewangan9db18752014-09-15 16:25:01 -0700711 {
712 .procname = "dev",
713 .mode = 0555,
714 .child = nss_ipv4_root_dir,
715 },
716 { }
717};
718
719static struct ctl_table_header *nss_ipv4_header;
720
721/*
722 * nss_ipv4_register_sysctl()
723 * Register sysctl specific to ipv4
724 */
725void nss_ipv4_register_sysctl(void)
726{
Stephen Wang0a2756a2016-08-04 15:52:47 -0700727 sema_init(&i4_conn_cfgp.sem, 1);
728 init_completion(&i4_conn_cfgp.complete);
729
730 sema_init(&i4_accel_mode_cfgp.sem, 1);
731 init_completion(&i4_accel_mode_cfgp.complete);
Stephen Wang49b474b2016-03-25 10:40:30 -0700732
Vijay Dewangan9db18752014-09-15 16:25:01 -0700733 /*
734 * Register sysctl table.
735 */
736 nss_ipv4_header = register_sysctl_table(nss_ipv4_root);
737}
738
739/*
740 * nss_ipv4_unregister_sysctl()
741 * Unregister sysctl specific to ipv4
742 */
743void nss_ipv4_unregister_sysctl(void)
744{
745 /*
746 * Unregister sysctl table.
747 */
748 if (nss_ipv4_header) {
749 unregister_sysctl_table(nss_ipv4_header);
750 }
751}
752
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700753/*
754 * nss_ipv4_msg_init()
755 * Initialize IPv4 message.
756 */
757void 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 -0800758 nss_ipv4_msg_callback_t cb, void *app_data)
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700759{
760 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data);
761}
762
Thomas Wu68250352014-04-02 18:59:40 -0700763EXPORT_SYMBOL(nss_ipv4_tx);
Stephen Wang709f9b52015-07-07 14:48:35 -0700764EXPORT_SYMBOL(nss_ipv4_tx_with_size);
Thomas Wu68250352014-04-02 18:59:40 -0700765EXPORT_SYMBOL(nss_ipv4_notify_register);
766EXPORT_SYMBOL(nss_ipv4_notify_unregister);
Suruchi Agarwal611ecd02016-08-04 15:54:35 -0700767EXPORT_SYMBOL(nss_ipv4_conn_sync_many_notify_register);
768EXPORT_SYMBOL(nss_ipv4_conn_sync_many_notify_unregister);
Thomas Wu68250352014-04-02 18:59:40 -0700769EXPORT_SYMBOL(nss_ipv4_get_mgr);
Vijay Dewangan9db18752014-09-15 16:25:01 -0700770EXPORT_SYMBOL(nss_ipv4_register_sysctl);
771EXPORT_SYMBOL(nss_ipv4_unregister_sysctl);
Sundarajan Srinivasan02e6c2b2014-10-06 11:51:12 -0700772EXPORT_SYMBOL(nss_ipv4_msg_init);
Tushar Mathura3c18932015-08-24 20:27:21 +0530773EXPORT_SYMBOL(nss_ipv4_update_conn_count);