blob: 7b8a09afa496c7988299dc33843e3f0f1ea51d60 [file] [log] [blame]
Thomas Wu68250352014-04-02 18:59:40 -07001/*
2 **************************************************************************
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 * 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_tx_rx_ipv4.c
19 * NSS IPv4 APIs
20 */
21#include <linux/ppp_channel.h>
22#include "nss_tx_rx_common.h"
23#include "nss_ipv4.h"
24
25extern void nss_rx_metadata_ipv4_rule_establish(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_rule_establish *nire);
26extern void nss_rx_ipv4_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs);
27
28/*
29 * nss_ipv4_driver_update()
30 * Update driver specific information from the messsage.
31 */
32#if 0
Sol Kavy2783c072014-04-05 12:53:13 -070033static void nss_ipv4_driver_conn_update(struct nss_ipv4_msg *nim)
Thomas Wu68250352014-04-02 18:59:40 -070034{
35 /*
36 * Update statistics maintained by NSS driver
37 */
38 spin_lock_bh(&nss_top->stats_lock);
Thomas Wu68250352014-04-02 18:59:40 -070039 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count;
40 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count;
41 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count;
42 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 -070043 spin_unlock_bh(&nss_top->stats_lock);
44}
45#endif
46
47/*
Sol Kavy2783c072014-04-05 12:53:13 -070048 * nss_ipv4_rx_msg_handler()
Thomas Wu68250352014-04-02 18:59:40 -070049 * Handle NSS -> HLOS messages for IPv4 bridge/route
50 */
Sol Kavy2783c072014-04-05 12:53:13 -070051static 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 -070052{
53 struct nss_ipv4_msg *nim = (struct nss_ipv4_msg *)ncm;
Thomas Wu68250352014-04-02 18:59:40 -070054/*
55 * TODO: Turn back on for new APIs
56 */
Sol Kavy2783c072014-04-05 12:53:13 -070057// nss_ipv4_rx_msg_callback_t cb;
Thomas Wu68250352014-04-02 18:59:40 -070058
59 BUG_ON(ncm->interface != NSS_IPV4_RX_INTERFACE);
60
61 /*
62 * Sanity check the message type
63 */
64 if (ncm->type > NSS_IPV4_MAX_MSG_TYPES) {
65 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
66 return;
67 }
68
69 if (ncm->len > sizeof(struct nss_ipv4_msg)) {
70 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
71 return;
72 }
73
Thomas Wu68250352014-04-02 18:59:40 -070074 /*
75 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
76 * to the same callback/app_data.
77 */
78 if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
79 ncm->cb = (uint32_t)nss_ctx->nss_top->ipv4_callback;
Abhishek Rastogie11f47b2014-04-04 18:43:32 +053080 ncm->app_data = (uint32_t)nss_ctx->nss_top->ipv4_ctx;
Thomas Wu68250352014-04-02 18:59:40 -070081 }
82
83 /*
84 * Log failures
85 */
86 nss_core_log_msg_failures(nss_ctx, ncm);
87
88 /*
89 * Handle deprecated messages. Eventually these messages should be removed.
90 */
91 switch (nim->cm.type) {
92 case NSS_IPV4_RX_ESTABLISH_RULE_MSG:
93 return nss_rx_metadata_ipv4_rule_establish(nss_ctx, &nim->msg.rule_establish);
94 break;
95
96 case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
97 return nss_rx_ipv4_sync(nss_ctx, &nim->msg.conn_stats);
98 break;
99 }
100
Sol Kavy2783c072014-04-05 12:53:13 -0700101#if 0
Thomas Wu68250352014-04-02 18:59:40 -0700102 /*
103 * Local driver updates for ipv4.
104 */
Sol Kavy2783c072014-04-05 12:53:13 -0700105 nss_ipv4_driver_update(nim);
106
Thomas Wu68250352014-04-02 18:59:40 -0700107 /*
108 * Do we have a callback?
109 */
110 if (!ncm->cb) {
111 return;
112 }
113
114 /*
115 * Callback
116 */
Sol Kavy2783c072014-04-05 12:53:13 -0700117 cb = (nss_ipv4_rx_msg_callback_t)ncm->cb;
Thomas Wu68250352014-04-02 18:59:40 -0700118 cb((void *)ncm->app_data, nim);
119#endif
120}
121
122/*
123 * nss_ipv4_tx()
124 * Transmit an ipv4 message to the FW.
125 */
126nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
127{
128 struct nss_ipv4_msg *nim2;
129 struct nss_cmn_msg *ncm = &nim->cm;
130 struct sk_buff *nbuf;
131 int32_t status;
132
133 NSS_VERIFY_CTX_MAGIC(nss_ctx);
134 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
135 nss_warning("%p: ipv4 msg dropped as core not ready", nss_ctx);
136 return NSS_TX_FAILURE_NOT_READY;
137 }
138
139 /*
140 * Sanity check the message
141 */
142 if (ncm->interface != NSS_IPV4_RX_INTERFACE) {
143 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
144 return NSS_TX_FAILURE;
145 }
146
147 if (ncm->type > NSS_IPV4_MAX_MSG_TYPES) {
148 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
149 return NSS_TX_FAILURE;
150 }
151
152 if (ncm->len > sizeof(struct nss_ipv4_msg)) {
153 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
154 return NSS_TX_FAILURE;
155 }
156
157 nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
158 if (unlikely(!nbuf)) {
159 spin_lock_bh(&nss_ctx->nss_top->stats_lock);
160 nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
161 spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
162 nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
163 return NSS_TX_FAILURE;
164 }
165
166 /*
167 * Copy the message to our skb.
168 */
169 nim2 = (struct nss_ipv4_msg *)skb_put(nbuf, sizeof(struct nss_ipv4_msg));
170 memcpy(nim2, nim, sizeof(struct nss_ipv4_msg));
171
172 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
173 if (status != NSS_CORE_STATUS_SUCCESS) {
174 dev_kfree_skb_any(nbuf);
Sol Kavycd1bd5c2014-04-04 11:09:44 -0700175 nss_warning("%p: unable to enqueue IPv4 msg\n", nss_ctx);
Thomas Wu68250352014-04-02 18:59:40 -0700176 return NSS_TX_FAILURE;
177 }
178
179 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
180 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
181
182 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
183 return NSS_TX_SUCCESS;
184}
185
186/*
187 **********************************
188 Register/Unregister/Miscellaneous APIs
189 **********************************
190 */
191
192/*
193 * nss_ipv4_notify_register()
194 * Register to received IPv4 events.
195 *
196 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
197 */
198struct nss_ctx_instance *nss_ipv4_notify_register(nss_ipv4_msg_callback_t cb, void *app_data)
199{
200 /*
201 * TODO: We need to have a new array in support of the new API
202 * TODO: If we use a per-context array, we would move the array into nss_ctx based.
203 */
204 nss_top_main.ipv4_callback = cb;
Abhishek Rastogie11f47b2014-04-04 18:43:32 +0530205 nss_top_main.ipv4_ctx = app_data;
Thomas Wu68250352014-04-02 18:59:40 -0700206 return &nss_top_main.nss[nss_top_main.ipv4_handler_id];
207}
208
209/*
210 * nss_ipv4_notify_unregister()
211 * Unregister to received IPv4 events.
212 *
213 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core?
214 */
215void nss_ipv4_notify_unregister(void)
216{
217 nss_top_main.ipv4_callback = NULL;
218}
219
220/*
221 * nss_ipv4_get_mgr()
222 *
223 * TODO: This only suppports a single ipv4, do we ever want to support more?
224 */
225struct nss_ctx_instance *nss_ipv4_get_mgr(void)
226{
227 return (void *)&nss_top_main.nss[nss_top_main.ipv4_handler_id];
228}
229
230/*
231 * nss_ipv4_register_handler()
232 * Register our handler to receive messages for this interface
233 */
Sol Kavy2783c072014-04-05 12:53:13 -0700234void nss_ipv4_register_handler(void)
Thomas Wu68250352014-04-02 18:59:40 -0700235{
Sol Kavy2783c072014-04-05 12:53:13 -0700236 if (nss_core_register_handler(NSS_IPV4_RX_INTERFACE, nss_ipv4_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
Thomas Wu68250352014-04-02 18:59:40 -0700237 nss_warning("IPv4 handler failed to register");
238 }
239}
240
241EXPORT_SYMBOL(nss_ipv4_tx);
242EXPORT_SYMBOL(nss_ipv4_notify_register);
243EXPORT_SYMBOL(nss_ipv4_notify_unregister);
244EXPORT_SYMBOL(nss_ipv4_get_mgr);
245EXPORT_SYMBOL(nss_ipv4_register_handler);