blob: 0dc5bd8f7b117b5a67a4bda7954e50252479d963 [file] [log] [blame]
ratheesh kannoth7af985d2015-06-24 15:08:40 +05301/*
2 **************************************************************************
Wayne Tanbd560072020-01-07 17:45:52 -08003 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
ratheesh kannoth7af985d2015-06-24 15:08:40 +05304 * 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#include <linux/l2tp.h>
18#include <net/sock.h>
19#include "nss_tx_rx_common.h"
Yu Huang8c107082017-07-24 14:58:26 -070020#include "nss_l2tpv2_stats.h"
Sachin Shashidhar015c28a2018-08-06 19:11:00 -070021#include "nss_l2tpv2_log.h"
Wayne Tanbd560072020-01-07 17:45:52 -080022#include "nss_l2tpv2_strings.h"
ratheesh kannoth7af985d2015-06-24 15:08:40 +053023
24/*
25 * Data structures to store l2tpv2 nss debug stats
26 */
27static DEFINE_SPINLOCK(nss_l2tpv2_session_debug_stats_lock);
Yu Huang8c107082017-07-24 14:58:26 -070028static struct nss_l2tpv2_stats_session_debug nss_l2tpv2_session_debug_stats[NSS_MAX_L2TPV2_DYNAMIC_INTERFACES];
ratheesh kannoth7af985d2015-06-24 15:08:40 +053029
30/*
31 * nss_l2tpv2_session_debug_stats_sync
32 * Per session debug stats for l2tpv2
33 */
34void nss_l2tpv2_session_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_l2tpv2_sync_session_stats_msg *stats_msg, uint16_t if_num)
35{
36 int i;
37 spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
38 for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
39 if (nss_l2tpv2_session_debug_stats[i].if_num == if_num) {
Yu Huang8c107082017-07-24 14:58:26 -070040 nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_RX_PPP_LCP_PKTS] += stats_msg->debug_stats.rx_ppp_lcp_pkts;
41 nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_RX_EXP_DATA_PKTS] += stats_msg->debug_stats.rx_exception_data_pkts;
42 nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.encap_pbuf_alloc_fail;
43 nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_DECAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.decap_pbuf_alloc_fail;
Gaurav Pathak40ef4a32019-04-26 12:33:04 +053044 nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_DECAP_L2TPOIPSEC_SRC_ERR] += stats_msg->debug_stats.decap_l2tpoipsec_src_error;
ratheesh kannoth7af985d2015-06-24 15:08:40 +053045 break;
46 }
47 }
48 spin_unlock_bh(&nss_l2tpv2_session_debug_stats_lock);
49}
50
51/*
52 * nss_l2tpv2_global_session_stats_get()
53 * Get session l2tpv2 statitics.
54 */
55void nss_l2tpv2_session_debug_stats_get(void *stats_mem)
56{
Yu Huang8c107082017-07-24 14:58:26 -070057 struct nss_l2tpv2_stats_session_debug *stats = (struct nss_l2tpv2_stats_session_debug *)stats_mem;
ratheesh kannoth7af985d2015-06-24 15:08:40 +053058 int i;
59
60 if (!stats) {
61 nss_warning("No memory to copy l2tpv2 session stats");
62 return;
63 }
64
65 spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
66 for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
67 if (nss_l2tpv2_session_debug_stats[i].valid) {
Yu Huang8c107082017-07-24 14:58:26 -070068 memcpy(stats, &nss_l2tpv2_session_debug_stats[i], sizeof(struct nss_l2tpv2_stats_session_debug));
ratheesh kannoth7af985d2015-06-24 15:08:40 +053069 stats++;
70 }
71 }
72 spin_unlock_bh(&nss_l2tpv2_session_debug_stats_lock);
73}
74
75/*
76 * nss_l2tpv2_handler()
77 * Handle NSS -> HLOS messages for l2tpv2 tunnel
78 */
79
80static void nss_l2tpv2_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
81{
82 struct nss_l2tpv2_msg *ntm = (struct nss_l2tpv2_msg *)ncm;
83 void *ctx;
84
85 nss_l2tpv2_msg_callback_t cb;
86
87 BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_L2TPV2_INTERFACE));
88
89 /*
Sachin Shashidhar015c28a2018-08-06 19:11:00 -070090 * Trace Messages
91 */
92 nss_l2tpv2_log_rx_msg(ntm);
93
94 /*
ratheesh kannoth7af985d2015-06-24 15:08:40 +053095 * Is this a valid request/response packet?
96 */
97 if (ncm->type >= NSS_L2TPV2_MSG_MAX) {
98 nss_warning("%p: received invalid message %d for L2TP interface", nss_ctx, ncm->type);
99 return;
100 }
101
Suruchi Agarwalef8a8702016-01-08 12:40:08 -0800102 if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_l2tpv2_msg)) {
103 nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530104 return;
105 }
106
107 switch (ntm->cm.type) {
108
109 case NSS_L2TPV2_MSG_SYNC_STATS:
110 /*
Wayne Tanbd560072020-01-07 17:45:52 -0800111 * Update session debug stats in session stats msg and send statistics notifications to the registered modules
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530112 */
113 nss_l2tpv2_session_debug_stats_sync(nss_ctx, &ntm->msg.stats, ncm->interface);
Wayne Tanbd560072020-01-07 17:45:52 -0800114 nss_l2tpv2_stats_notify(nss_ctx, ncm->interface);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530115 break;
116 }
117
118 /*
119 * Update the callback and app_data for NOTIFY messages, l2tpv2 sends all notify messages
120 * to the same callback/app_data.
121 */
Suruchi Agarwale4ad24a2018-06-11 12:03:46 +0530122 if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
Stephen Wangaed46332016-12-12 17:29:03 -0800123 ncm->cb = (nss_ptr_t)nss_ctx->nss_top->l2tpv2_msg_callback;
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530124 }
125
126 /*
127 * Log failures
128 */
129 nss_core_log_msg_failures(nss_ctx, ncm);
130
131 /*
132 * Do we have a call back
133 */
134 if (!ncm->cb) {
135 return;
136 }
137
138 /*
139 * callback
140 */
141 cb = (nss_l2tpv2_msg_callback_t)ncm->cb;
Stephen Wang84e0e992016-09-07 12:31:40 -0700142 ctx = nss_ctx->subsys_dp_register[ncm->interface].ndev;
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530143
144 /*
145 * call l2tpv2 tunnel callback
146 */
147 if (!ctx) {
148 nss_warning("%p: Event received for l2tpv2 tunnel interface %d before registration", nss_ctx, ncm->interface);
149 return;
150 }
151
152 cb(ctx, ntm);
153}
154
155/*
156 * nss_l2tpv2_tx()
157 * Transmit a l2tpv2 message to NSS firmware
158 */
159nss_tx_status_t nss_l2tpv2_tx(struct nss_ctx_instance *nss_ctx, struct nss_l2tpv2_msg *msg)
160{
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530161 struct nss_cmn_msg *ncm = &msg->cm;
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530162
163 /*
Sachin Shashidhar015c28a2018-08-06 19:11:00 -0700164 * Trace Messages
165 */
166 nss_l2tpv2_log_tx_msg(msg);
167
168 /*
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530169 * Sanity check the message
170 */
171 if (!nss_is_dynamic_interface(ncm->interface)) {
172 nss_warning("%p: tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
173 return NSS_TX_FAILURE;
174 }
175
176 if (ncm->type > NSS_L2TPV2_MSG_MAX) {
177 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
178 return NSS_TX_FAILURE;
179 }
180
Stephen Wang3e2dbd12018-03-14 17:28:17 -0700181 return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530182}
183
184/*
185 ***********************************
186 * Register/Unregister/Miscellaneous APIs
187 ***********************************
188 */
189
190/*
191 * nss_register_l2tpv2_if()
192 */
193struct nss_ctx_instance *nss_register_l2tpv2_if(uint32_t if_num, nss_l2tpv2_callback_t l2tpv2_callback,
194 nss_l2tpv2_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
195{
Stephen Wang84e0e992016-09-07 12:31:40 -0700196 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.l2tpv2_handler_id];
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530197 int i = 0;
Stephen Wang84e0e992016-09-07 12:31:40 -0700198
199 nss_assert(nss_ctx);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530200 nss_assert(nss_is_dynamic_interface(if_num));
201
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700202 nss_core_register_subsys_dp(nss_ctx, if_num, l2tpv2_callback, NULL, NULL, netdev, features);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530203
204 nss_top_main.l2tpv2_msg_callback = event_callback;
205
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700206 nss_core_register_handler(nss_ctx, if_num, nss_l2tpv2_handler, NULL);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530207
208 spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
209 for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
210 if (!nss_l2tpv2_session_debug_stats[i].valid) {
211 nss_l2tpv2_session_debug_stats[i].valid = true;
212 nss_l2tpv2_session_debug_stats[i].if_num = if_num;
213 nss_l2tpv2_session_debug_stats[i].if_index = netdev->ifindex;
214 break;
215 }
216 }
217 spin_unlock_bh(&nss_l2tpv2_session_debug_stats_lock);
218
Stephen Wang84e0e992016-09-07 12:31:40 -0700219 return nss_ctx;
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530220}
221
222/*
223 * nss_unregister_l2tpv2_if()
224 */
225void nss_unregister_l2tpv2_if(uint32_t if_num)
226{
Stephen Wang84e0e992016-09-07 12:31:40 -0700227 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.l2tpv2_handler_id];
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530228 int i;
Stephen Wang84e0e992016-09-07 12:31:40 -0700229
230 nss_assert(nss_ctx);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530231 nss_assert(nss_is_dynamic_interface(if_num));
232
Jackson Bockus7ca70ec2017-07-17 13:47:29 -0700233 nss_core_unregister_subsys_dp(nss_ctx, if_num);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530234
235 nss_top_main.l2tpv2_msg_callback = NULL;
236
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700237 nss_core_unregister_handler(nss_ctx, if_num);
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530238
239 spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
240 for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
241 if (nss_l2tpv2_session_debug_stats[i].if_num == if_num) {
Yu Huang8c107082017-07-24 14:58:26 -0700242 memset(&nss_l2tpv2_session_debug_stats[i], 0, sizeof(struct nss_l2tpv2_stats_session_debug));
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530243 break;
244 }
245 }
246 spin_unlock_bh(&nss_l2tpv2_session_debug_stats_lock);
247}
248
249/*
250 * nss_get_l2tpv2_context()
251 */
252struct nss_ctx_instance *nss_l2tpv2_get_context()
253{
254 return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.l2tpv2_handler_id];
255}
256
257/*
258 * nss_l2tpv2_msg_init()
Yu Huang8c107082017-07-24 14:58:26 -0700259 * Initialize nss_l2tpv2 msg.
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530260 */
261void nss_l2tpv2_msg_init(struct nss_l2tpv2_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
262{
263 nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
264}
265
266/* nss_l2tpv2_register_handler()
267 * debugfs stats msg handler received on static l2tpv2 interface
268 */
269void nss_l2tpv2_register_handler(void)
270{
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700271 struct nss_ctx_instance *nss_ctx = nss_l2tpv2_get_context();
272
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530273 nss_info("nss_l2tpv2_register_handler");
Thomas Wu91f4bdf2017-06-09 12:03:02 -0700274 nss_core_register_handler(nss_ctx, NSS_L2TPV2_INTERFACE, nss_l2tpv2_handler, NULL);
Yu Huang8c107082017-07-24 14:58:26 -0700275
276 nss_l2tpv2_stats_dentry_create();
Wayne Tanbd560072020-01-07 17:45:52 -0800277 nss_l2tpv2_strings_dentry_create();
ratheesh kannoth7af985d2015-06-24 15:08:40 +0530278}
279
280EXPORT_SYMBOL(nss_l2tpv2_get_context);
281EXPORT_SYMBOL(nss_l2tpv2_tx);
282EXPORT_SYMBOL(nss_unregister_l2tpv2_if);
283EXPORT_SYMBOL(nss_l2tpv2_msg_init);
284EXPORT_SYMBOL(nss_register_l2tpv2_if);