blob: 74f30a25a7efe858757a55dccaf2e6a75299ff8a [file] [log] [blame]
Suruchi Sumanf7e29822019-09-11 11:53:53 +05301/*
2 ***************************************************************************
3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 ***************************************************************************
17 */
18
19/*
20 * nss_match.c
21 */
22
23#include "nss_tx_rx_common.h"
24#include "nss_match_log.h"
25#include "nss_match_stats.h"
26
27#define NSS_MATCH_TX_TIMEOUT 1000 /* 1 Seconds */
28
29/*
30 * Private data structure for match interface
31 */
32static struct nss_match_pvt {
33 struct semaphore sem;
34 struct completion complete;
35 int32_t response;
36} match_pvt;
37
38/*
39 * nss_get_match_context()
40 */
41struct nss_ctx_instance *nss_match_get_context(void)
42{
43 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.match_handler_id];
44}
45EXPORT_SYMBOL(nss_match_get_context);
46
47/*
48 * nss_match_verify_if_num()
49 */
50static bool nss_match_verify_if_num(uint32_t if_num)
51{
52 if (nss_is_dynamic_interface(if_num) == false) {
53 return false;
54 }
55
56 if (nss_dynamic_interface_get_type(nss_match_get_context(), if_num)
57 != NSS_DYNAMIC_INTERFACE_TYPE_MATCH) {
58 return false;
59 }
60
61 return true;
62}
63
64/*
65 * nss_match_msg_sync_callback
66 * Callback to handle the completion of NSS to HLOS messages.
67 */
68static void nss_match_msg_sync_callback(void *app_data, struct nss_match_msg *matchm)
69{
70 match_pvt.response = NSS_TX_SUCCESS;
71
72 if (matchm->cm.response != NSS_CMN_RESPONSE_ACK) {
73 nss_warning("Match Error response %d\n", matchm->cm.response);
74 match_pvt.response = NSS_TX_FAILURE;
75 }
76
77 complete(&match_pvt.complete);
78}
79
80/*
81 * nss_match_msg_tx()
82 * Sends message to NSS.
83 */
84static nss_tx_status_t nss_match_msg_tx(struct nss_ctx_instance *nss_ctx, struct nss_match_msg *matchm)
85{
86 struct nss_cmn_msg *ncm = &matchm->cm;
87
88 NSS_VERIFY_CTX_MAGIC(nss_ctx);
89
90 /*
91 * Trace Messages
92 */
93 nss_match_log_tx_msg(matchm);
94
95 /*
96 * Sanity check the message
97 */
98 if (!nss_match_verify_if_num(ncm->interface)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -060099 nss_warning("%px: Tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530100 return NSS_TX_FAILURE;
101 }
102
103 if (ncm->type > NSS_MATCH_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600104 nss_warning("%px: Message type out of range: %d", nss_ctx, ncm->type);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530105 return NSS_TX_FAILURE;
106 }
107
108 return nss_core_send_cmd(nss_ctx, matchm, sizeof(*matchm), NSS_NBUF_PAYLOAD_SIZE);
109}
110
111/*
112 * nss_match_handler()
113 * Handle NSS to HLOS messages for Match node
114 */
115static void nss_match_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
116{
117 struct nss_match_msg *nem = (struct nss_match_msg *)ncm;
118
119 nss_match_msg_sync_callback_t cb;
120 void *ctx;
121
122 NSS_VERIFY_CTX_MAGIC(nss_ctx);
123 BUG_ON(!nss_match_verify_if_num(ncm->interface));
124
125 /*
126 * Trace Messages
127 */
128 nss_match_log_rx_msg(nem);
129
130 /*
131 * Is this a valid request/response packet?
132 */
133 if (nem->cm.type >= NSS_MATCH_MSG_MAX) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600134 nss_warning("%px: Received invalid message %d for MATCH interface", nss_ctx, nem->cm.type);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530135 return;
136 }
137
138 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_match_msg)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600139 nss_warning("%px: Unexpected message length: %d, on interface: %d",
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530140 nss_ctx, nss_cmn_get_msg_len(ncm), ncm->interface);
141 return;
142 }
143
144 switch (nem->cm.type) {
145 case NSS_MATCH_STATS_SYNC:
146
147 /*
148 * Update common node statistics
149 */
150 nss_match_stats_sync(nss_ctx, nem);
151 }
152
153 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600154 ncm->cb = (nss_ptr_t)nss_core_get_msg_handler(nss_ctx, ncm->interface);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530155 }
156
157 /*
158 * Log failures
159 */
160 nss_core_log_msg_failures(nss_ctx, ncm);
161
162 /*
163 * Do we have a call back
164 */
165 if (!ncm->cb) {
166 return;
167 }
168
169 /*
170 * callback
171 */
172 cb = (nss_match_msg_sync_callback_t)ncm->cb;
173 ctx = (void *)ncm->app_data;
174
175 cb(ctx, nem);
176}
177
178/*
179 * nss_match_msg_tx_sync()
180 * Send a message to match node and wait for the response.
181 */
182nss_tx_status_t nss_match_msg_tx_sync(struct nss_ctx_instance *nss_ctx, struct nss_match_msg *matchm)
183{
184 nss_tx_status_t status;
185 int ret = 0;
186 down(&match_pvt.sem);
187
188 matchm->cm.cb = (nss_ptr_t)nss_match_msg_sync_callback;
189 matchm->cm.app_data = (nss_ptr_t)NULL;
190
191 status = nss_match_msg_tx(nss_ctx, matchm);
192 if (status != NSS_TX_SUCCESS) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600193 nss_warning("%px: nss_match_msg_tx failed\n", nss_ctx);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530194 up(&match_pvt.sem);
195 return status;
196 }
197
198 ret = wait_for_completion_timeout(&match_pvt.complete, msecs_to_jiffies(NSS_MATCH_TX_TIMEOUT));
199 if (!ret) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600200 nss_warning("%px: MATCH tx failed due to timeout\n", nss_ctx);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530201 match_pvt.response = NSS_TX_FAILURE;
202 }
203
204 status = match_pvt.response;
205 up(&match_pvt.sem);
206
207 return status;
208}
209EXPORT_SYMBOL(nss_match_msg_tx_sync);
210
211/*
212 * nss_match_register_instance()
213 * Registers match instance.
214 */
215struct nss_ctx_instance *nss_match_register_instance(int if_num, nss_match_msg_sync_callback_t notify_cb)
216{
217 struct nss_ctx_instance *nss_ctx;
Kyle Swensondd7b2962021-03-16 13:46:32 -0600218 uint32_t status;
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530219
220 nss_ctx = nss_match_get_context();
221 NSS_VERIFY_CTX_MAGIC(nss_ctx);
222
223 if (!nss_match_verify_if_num(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600224 nss_warning("%px: Incorrect interface number: %d", nss_ctx, if_num);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530225 return NULL;
226 }
227
228 nss_core_register_handler(nss_ctx, if_num, nss_match_handler, NULL);
Kyle Swensondd7b2962021-03-16 13:46:32 -0600229 status = nss_core_register_msg_handler(nss_ctx, if_num, (nss_if_rx_msg_callback_t)notify_cb);
230 if (status != NSS_CORE_STATUS_SUCCESS) {
231 nss_warning("%px: Not able to register handler for interface %d with NSS core\n", nss_ctx, if_num);
232 return NULL;
233 }
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530234
235 if (!nss_match_ifnum_add(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600236 nss_warning("%px: Unable to add match inteface : %u\n", nss_ctx, if_num);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530237 nss_core_unregister_handler(nss_ctx, if_num);
Kyle Swensondd7b2962021-03-16 13:46:32 -0600238 nss_core_unregister_msg_handler(nss_ctx, if_num);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530239 return NULL;
240 }
241
242 return nss_ctx;
243}
244EXPORT_SYMBOL(nss_match_register_instance);
245
246/*
247 * nss_match_unregister_instance()
248 * Unregisters match instance.
249 */
250bool nss_match_unregister_instance(int if_num)
251{
252 struct nss_ctx_instance *nss_ctx;
Kyle Swensondd7b2962021-03-16 13:46:32 -0600253 uint32_t status;
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530254
255 nss_ctx = nss_match_get_context();
256 NSS_VERIFY_CTX_MAGIC(nss_ctx);
257
258 if (!nss_match_verify_if_num(if_num)) {
Kyle Swensondd7b2962021-03-16 13:46:32 -0600259 nss_warning("%px: Incorrect interface number: %d", nss_ctx, if_num);
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530260 return false;
261 }
262
263 nss_core_unregister_handler(nss_ctx, if_num);
Kyle Swensondd7b2962021-03-16 13:46:32 -0600264 status = nss_core_unregister_msg_handler(nss_ctx, if_num);
265 if (status != NSS_CORE_STATUS_SUCCESS) {
266 nss_warning("%px: Not able to unregister handler for interface %d with NSS core\n", nss_ctx, if_num);
267 return false;
268 }
269
Suruchi Sumanf7e29822019-09-11 11:53:53 +0530270 nss_match_ifnum_delete(if_num);
271
272 return true;
273}
274EXPORT_SYMBOL(nss_match_unregister_instance);
275
276/*
277 * nss_match_msg_init()
278 * Initialize match message.
279 */
280void nss_match_msg_init(struct nss_match_msg *nmm, uint16_t if_num, uint32_t type, uint32_t len,
281 nss_match_msg_sync_callback_t cb, void *app_data)
282{
283 nss_cmn_msg_init(&nmm->cm, if_num, type, len, (void*)cb, app_data);
284}
285EXPORT_SYMBOL(nss_match_msg_init);
286
287/*
288 * nss_match_init()
289 * Initialize match.
290 */
291void nss_match_init()
292{
293 nss_match_stats_dentry_create();
294 sema_init(&match_pvt.sem, 1);
295 init_completion(&match_pvt.complete);
296}