blob: 9c0d691b35c3e32396afec1e52c7e88d472123f9 [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001/* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License
4 *
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
9 *
10 * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
11 * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/dma-mapping.h>
17#include <linux/netdevice.h>
18#include <linux/iopoll.h>
19
20#include "hnat.h"
21#include "nf_hnat_mtk.h"
22#include "../mtk_eth_soc.h"
23
24int dbg_entry_state = BIND;
25typedef int (*debugfs_write_func)(int par1);
26int debug_level;
27int dbg_cpu_reason;
28int hook_toggle;
29int mape_toggle;
developeraf07fad2021-11-19 17:53:42 +080030int qos_toggle;
developer47545a32022-11-15 16:06:58 +080031int qos_dl_toggle = 1;
32int qos_ul_toggle = 1;
developerfd40db22021-04-29 10:08:25 +080033unsigned int dbg_cpu_reason_cnt[MAX_CRSN_NUM];
34
35static const char * const entry_state[] = { "INVALID", "UNBIND", "BIND", "FIN" };
36
37static const char * const packet_type[] = {
38 "IPV4_HNAPT", "IPV4_HNAT", "IPV6_1T_ROUTE", "IPV4_DSLITE",
39 "IPV6_3T_ROUTE", "IPV6_5T_ROUTE", "REV", "IPV6_6RD",
developer5ffc5f12022-10-25 18:51:46 +080040 "IPV4_MAP_T", "IPV4_MAP_E", "IPV6_HNAPT", "IPV6_HNAT",
developerfd40db22021-04-29 10:08:25 +080041};
42
43static uint8_t *show_cpu_reason(struct sk_buff *skb)
44{
45 static u8 buf[32];
developer577ad2f2022-11-28 10:33:36 +080046 int ret;
developerfd40db22021-04-29 10:08:25 +080047
48 switch (skb_hnat_reason(skb)) {
49 case TTL_0:
50 return "IPv4(IPv6) TTL(hop limit)\n";
51 case HAS_OPTION_HEADER:
52 return "Ipv4(IPv6) has option(extension) header\n";
53 case NO_FLOW_IS_ASSIGNED:
54 return "No flow is assigned\n";
55 case IPV4_WITH_FRAGMENT:
56 return "IPv4 HNAT doesn't support IPv4 /w fragment\n";
57 case IPV4_HNAPT_DSLITE_WITH_FRAGMENT:
58 return "IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment\n";
59 case IPV4_HNAPT_DSLITE_WITHOUT_TCP_UDP:
60 return "IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport\n";
61 case IPV6_5T_6RD_WITHOUT_TCP_UDP:
62 return "IPv6 5T-route/6RD can't find TCP/UDP sport/dport\n";
63 case TCP_FIN_SYN_RST:
64 return "Ingress packet is TCP fin/syn/rst\n";
65 case UN_HIT:
66 return "FOE Un-hit\n";
67 case HIT_UNBIND:
68 return "FOE Hit unbind\n";
69 case HIT_UNBIND_RATE_REACH:
70 return "FOE Hit unbind & rate reach\n";
71 case HIT_BIND_TCP_FIN:
72 return "Hit bind PPE TCP FIN entry\n";
73 case HIT_BIND_TTL_1:
74 return "Hit bind PPE entry and TTL(hop limit) = 1 and TTL(hot limit) - 1\n";
75 case HIT_BIND_WITH_VLAN_VIOLATION:
76 return "Hit bind and VLAN replacement violation\n";
77 case HIT_BIND_KEEPALIVE_UC_OLD_HDR:
78 return "Hit bind and keep alive with unicast old-header packet\n";
79 case HIT_BIND_KEEPALIVE_MC_NEW_HDR:
80 return "Hit bind and keep alive with multicast new-header packet\n";
81 case HIT_BIND_KEEPALIVE_DUP_OLD_HDR:
82 return "Hit bind and keep alive with duplicate old-header packet\n";
83 case HIT_BIND_FORCE_TO_CPU:
84 return "FOE Hit bind & force to CPU\n";
85 case HIT_BIND_EXCEED_MTU:
86 return "Hit bind and exceed MTU\n";
87 case HIT_BIND_MULTICAST_TO_CPU:
88 return "Hit bind multicast packet to CPU\n";
89 case HIT_BIND_MULTICAST_TO_GMAC_CPU:
90 return "Hit bind multicast packet to GMAC & CPU\n";
91 case HIT_PRE_BIND:
92 return "Pre bind\n";
93 }
94
developer577ad2f2022-11-28 10:33:36 +080095 ret = snprintf(buf, sizeof(buf), "CPU Reason Error - %X\n",
96 skb_hnat_entry(skb));
97 if (ret == strlen(buf))
98 return buf;
99 else
100 return "CPU Reason Error\n";
developerfd40db22021-04-29 10:08:25 +0800101}
102
103uint32_t foe_dump_pkt(struct sk_buff *skb)
104{
105 struct foe_entry *entry;
106
developer79359642021-07-27 14:29:10 +0800107 if (skb_hnat_entry(skb) >= hnat_priv->foe_etry_num ||
108 skb_hnat_ppe(skb) >= CFG_PPE_NUM)
109 return 1;
110
developer471f6562021-05-10 20:48:34 +0800111 entry = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
developerfd40db22021-04-29 10:08:25 +0800112 pr_info("\nRx===<FOE_Entry=%d>=====\n", skb_hnat_entry(skb));
113 pr_info("RcvIF=%s\n", skb->dev->name);
developer471f6562021-05-10 20:48:34 +0800114 pr_info("PPE_ID=%d\n", skb_hnat_ppe(skb));
developerfd40db22021-04-29 10:08:25 +0800115 pr_info("FOE_Entry=%d\n", skb_hnat_entry(skb));
116 pr_info("CPU Reason=%s", show_cpu_reason(skb));
117 pr_info("ALG=%d\n", skb_hnat_alg(skb));
118 pr_info("SP=%d\n", skb_hnat_sport(skb));
119
120 /* some special alert occurred, so entry_num is useless (just skip it) */
121 if (skb_hnat_entry(skb) == 0x3fff)
122 return 1;
123
124 /* PPE: IPv4 packet=IPV4_HNAT IPv6 packet=IPV6_ROUTE */
125 if (IS_IPV4_GRP(entry)) {
126 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
127 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
128
129 pr_info("Information Block 1=%x\n",
130 entry->ipv4_hnapt.info_blk1);
131 pr_info("SIP=%pI4\n", &saddr);
132 pr_info("DIP=%pI4\n", &daddr);
133 pr_info("SPORT=%d\n", entry->ipv4_hnapt.sport);
134 pr_info("DPORT=%d\n", entry->ipv4_hnapt.dport);
135 pr_info("Information Block 2=%x\n",
136 entry->ipv4_hnapt.info_blk2);
137 pr_info("State = %s, proto = %s\n", entry->bfib1.state == 0 ?
138 "Invalid" : entry->bfib1.state == 1 ?
139 "Unbind" : entry->bfib1.state == 2 ?
140 "BIND" : entry->bfib1.state == 3 ?
141 "FIN" : "Unknown",
142 entry->ipv4_hnapt.bfib1.udp == 0 ?
143 "TCP" : entry->ipv4_hnapt.bfib1.udp == 1 ?
144 "UDP" : "Unknown");
145 } else if (IS_IPV6_GRP(entry)) {
146 pr_info("Information Block 1=%x\n",
147 entry->ipv6_5t_route.info_blk1);
148 pr_info("IPv6_SIP=%08X:%08X:%08X:%08X\n",
149 entry->ipv6_5t_route.ipv6_sip0,
150 entry->ipv6_5t_route.ipv6_sip1,
151 entry->ipv6_5t_route.ipv6_sip2,
152 entry->ipv6_5t_route.ipv6_sip3);
153 pr_info("IPv6_DIP=%08X:%08X:%08X:%08X\n",
154 entry->ipv6_5t_route.ipv6_dip0,
155 entry->ipv6_5t_route.ipv6_dip1,
156 entry->ipv6_5t_route.ipv6_dip2,
157 entry->ipv6_5t_route.ipv6_dip3);
158 pr_info("SPORT=%d\n", entry->ipv6_5t_route.sport);
159 pr_info("DPORT=%d\n", entry->ipv6_5t_route.dport);
160 pr_info("Information Block 2=%x\n",
161 entry->ipv6_5t_route.info_blk2);
162 pr_info("State = %s, proto = %s\n", entry->bfib1.state == 0 ?
163 "Invalid" : entry->bfib1.state == 1 ?
164 "Unbind" : entry->bfib1.state == 2 ?
165 "BIND" : entry->bfib1.state == 3 ?
166 "FIN" : "Unknown",
167 entry->ipv6_5t_route.bfib1.udp == 0 ?
168 "TCP" : entry->ipv6_5t_route.bfib1.udp == 1 ?
169 "UDP" : "Unknown");
170 } else {
171 pr_info("unknown Pkt_type=%d\n", entry->bfib1.pkt_type);
172 }
173
174 pr_info("==================================\n");
175 return 1;
176}
177
178uint32_t hnat_cpu_reason_cnt(struct sk_buff *skb)
179{
180 switch (skb_hnat_reason(skb)) {
181 case TTL_0:
182 dbg_cpu_reason_cnt[0]++;
183 return 0;
184 case HAS_OPTION_HEADER:
185 dbg_cpu_reason_cnt[1]++;
186 return 0;
187 case NO_FLOW_IS_ASSIGNED:
188 dbg_cpu_reason_cnt[2]++;
189 return 0;
190 case IPV4_WITH_FRAGMENT:
191 dbg_cpu_reason_cnt[3]++;
192 return 0;
193 case IPV4_HNAPT_DSLITE_WITH_FRAGMENT:
194 dbg_cpu_reason_cnt[4]++;
195 return 0;
196 case IPV4_HNAPT_DSLITE_WITHOUT_TCP_UDP:
197 dbg_cpu_reason_cnt[5]++;
198 return 0;
199 case IPV6_5T_6RD_WITHOUT_TCP_UDP:
200 dbg_cpu_reason_cnt[6]++;
201 return 0;
202 case TCP_FIN_SYN_RST:
203 dbg_cpu_reason_cnt[7]++;
204 return 0;
205 case UN_HIT:
206 dbg_cpu_reason_cnt[8]++;
207 return 0;
208 case HIT_UNBIND:
209 dbg_cpu_reason_cnt[9]++;
210 return 0;
211 case HIT_UNBIND_RATE_REACH:
212 dbg_cpu_reason_cnt[10]++;
213 return 0;
214 case HIT_BIND_TCP_FIN:
215 dbg_cpu_reason_cnt[11]++;
216 return 0;
217 case HIT_BIND_TTL_1:
218 dbg_cpu_reason_cnt[12]++;
219 return 0;
220 case HIT_BIND_WITH_VLAN_VIOLATION:
221 dbg_cpu_reason_cnt[13]++;
222 return 0;
223 case HIT_BIND_KEEPALIVE_UC_OLD_HDR:
224 dbg_cpu_reason_cnt[14]++;
225 return 0;
226 case HIT_BIND_KEEPALIVE_MC_NEW_HDR:
227 dbg_cpu_reason_cnt[15]++;
228 return 0;
229 case HIT_BIND_KEEPALIVE_DUP_OLD_HDR:
230 dbg_cpu_reason_cnt[16]++;
231 return 0;
232 case HIT_BIND_FORCE_TO_CPU:
233 dbg_cpu_reason_cnt[17]++;
234 return 0;
235 case HIT_BIND_EXCEED_MTU:
236 dbg_cpu_reason_cnt[18]++;
237 return 0;
238 case HIT_BIND_MULTICAST_TO_CPU:
239 dbg_cpu_reason_cnt[19]++;
240 return 0;
241 case HIT_BIND_MULTICAST_TO_GMAC_CPU:
242 dbg_cpu_reason_cnt[20]++;
243 return 0;
244 case HIT_PRE_BIND:
245 dbg_cpu_reason_cnt[21]++;
246 return 0;
247 }
248
249 return 0;
250}
251
252int hnat_set_usage(int level)
253{
254 debug_level = level;
255 pr_info("Read cpu_reason count: cat /sys/kernel/debug/hnat/cpu_reason\n\n");
256 pr_info("====================Advanced Settings====================\n");
257 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/cpu_reason\n\n");
258 pr_info("Commands: [type] [option]\n");
259 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
260 debug_level);
261 pr_info(" 1 cpu_reason Track entries of the set cpu_reason\n");
262 pr_info(" Set type=1 will change debug_level=7\n");
263 pr_info("cpu_reason list:\n");
264 pr_info(" 2 IPv4(IPv6) TTL(hop limit) = 0\n");
265 pr_info(" 3 IPv4(IPv6) has option(extension) header\n");
266 pr_info(" 7 No flow is assigned\n");
267 pr_info(" 8 IPv4 HNAT doesn't support IPv4 /w fragment\n");
268 pr_info(" 9 IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment\n");
269 pr_info(" 10 IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport\n");
270 pr_info(" 11 IPv6 5T-route/6RD can't find TCP/UDP sport/dport\n");
271 pr_info(" 12 Ingress packet is TCP fin/syn/rst\n");
272 pr_info(" 13 FOE Un-hit\n");
273 pr_info(" 14 FOE Hit unbind\n");
274 pr_info(" 15 FOE Hit unbind & rate reach\n");
275 pr_info(" 16 Hit bind PPE TCP FIN entry\n");
276 pr_info(" 17 Hit bind PPE entry and TTL(hop limit) = 1\n");
277 pr_info(" 18 Hit bind and VLAN replacement violation\n");
278 pr_info(" 19 Hit bind and keep alive with unicast old-header packet\n");
279 pr_info(" 20 Hit bind and keep alive with multicast new-header packet\n");
280 pr_info(" 21 Hit bind and keep alive with duplicate old-header packet\n");
281 pr_info(" 22 FOE Hit bind & force to CPU\n");
282 pr_info(" 23 HIT_BIND_WITH_OPTION_HEADER\n");
283 pr_info(" 24 Switch clone multicast packet to CPU\n");
284 pr_info(" 25 Switch clone multicast packet to GMAC1 & CPU\n");
285 pr_info(" 26 HIT_PRE_BIND\n");
286 pr_info(" 27 HIT_BIND_PACKET_SAMPLING\n");
287 pr_info(" 28 Hit bind and exceed MTU\n");
288
289 return 0;
290}
291
292int hnat_cpu_reason(int cpu_reason)
293{
294 dbg_cpu_reason = cpu_reason;
295 debug_level = 7;
296 pr_info("show cpu reason = %d\n", cpu_reason);
297
298 return 0;
299}
300
301int entry_set_usage(int level)
302{
303 debug_level = level;
304 pr_info("Show all entries(default state=bind): cat /sys/kernel/debug/hnat/hnat_entry\n\n");
305 pr_info("====================Advanced Settings====================\n");
306 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/hnat_entry\n\n");
307 pr_info("Commands: [type] [option]\n");
308 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
309 debug_level);
310 pr_info(" 1 0~3 Change tracking state\n");
311 pr_info(" (0:invalid; 1:unbind; 2:bind; 3:fin)\n");
developer471f6562021-05-10 20:48:34 +0800312 pr_info(" 2 <entry_idx> Show PPE0 specific foe entry info. of assigned <entry_idx>\n");
313 pr_info(" 3 <entry_idx> Delete PPE0 specific foe entry of assigned <entry_idx>\n");
314 pr_info(" 4 <entry_idx> Show PPE1 specific foe entry info. of assigned <entry_idx>\n");
315 pr_info(" 5 <entry_idx> Delete PPE1 specific foe entry of assigned <entry_idx>\n");
developer3fb8d472021-11-16 15:46:38 +0800316 pr_info(" When entry_idx is -1, clear all entries\n");
developerfd40db22021-04-29 10:08:25 +0800317
318 return 0;
319}
320
321int entry_set_state(int state)
322{
323 dbg_entry_state = state;
324 pr_info("ENTRY STATE = %s\n", dbg_entry_state == 0 ?
325 "Invalid" : dbg_entry_state == 1 ?
326 "Unbind" : dbg_entry_state == 2 ?
327 "BIND" : dbg_entry_state == 3 ?
328 "FIN" : "Unknown");
329 return 0;
330}
331
developer471f6562021-05-10 20:48:34 +0800332int wrapped_ppe0_entry_detail(int index) {
333 entry_detail(0, index);
334 return 0;
335}
336
337int wrapped_ppe1_entry_detail(int index) {
338 entry_detail(1, index);
339 return 0;
340}
341
developer4c32b7a2021-11-13 16:46:43 +0800342int entry_detail(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +0800343{
344 struct foe_entry *entry;
345 struct mtk_hnat *h = hnat_priv;
346 u32 *p;
347 u32 i = 0;
348 u32 print_cnt;
349 unsigned char h_dest[ETH_ALEN];
350 unsigned char h_source[ETH_ALEN];
351 __be32 saddr, daddr, nsaddr, ndaddr;
352
developer471f6562021-05-10 20:48:34 +0800353 if (ppe_id >= CFG_PPE_NUM)
354 return -EINVAL;
355
developerc6227322021-07-09 10:52:53 +0800356 if (index < 0 || index >= h->foe_etry_num) {
357 pr_info("Invalid entry index\n");
358 return -EINVAL;
359 }
360
developer471f6562021-05-10 20:48:34 +0800361 entry = h->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +0800362 saddr = htonl(entry->ipv4_hnapt.sip);
363 daddr = htonl(entry->ipv4_hnapt.dip);
364 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
365 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
366 p = (uint32_t *)entry;
developer471f6562021-05-10 20:48:34 +0800367 pr_info("==========<PPE_ID=%d, Flow Table Entry=%d (%p)>===============\n",
368 ppe_id, index, entry);
developerfd40db22021-04-29 10:08:25 +0800369 if (debug_level >= 2) {
370 print_cnt = 20;
371 for (i = 0; i < print_cnt; i++)
372 pr_info("%02d: %08X\n", i, *(p + i));
373 }
374 pr_info("-----------------<Flow Info>------------------\n");
375 pr_info("Information Block 1: %08X\n", entry->ipv4_hnapt.info_blk1);
376
377 if (IS_IPV4_HNAPT(entry)) {
378 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
379 entry->ipv4_hnapt.info_blk2,
380 entry->ipv4_hnapt.iblk2.dp,
381 entry->ipv4_hnapt.iblk2.fqos,
382 entry->ipv4_hnapt.iblk2.qid);
383 pr_info("Create IPv4 HNAPT entry\n");
384 pr_info("IPv4 Org IP/Port: %pI4:%d->%pI4:%d\n", &saddr,
385 entry->ipv4_hnapt.sport, &daddr,
386 entry->ipv4_hnapt.dport);
387 pr_info("IPv4 New IP/Port: %pI4:%d->%pI4:%d\n", &nsaddr,
388 entry->ipv4_hnapt.new_sport, &ndaddr,
389 entry->ipv4_hnapt.new_dport);
390 } else if (IS_IPV4_HNAT(entry)) {
391 pr_info("Information Block 2: %08X\n",
392 entry->ipv4_hnapt.info_blk2);
393 pr_info("Create IPv4 HNAT entry\n");
394 pr_info("IPv4 Org IP: %pI4->%pI4\n", &saddr, &daddr);
395 pr_info("IPv4 New IP: %pI4->%pI4\n", &nsaddr, &ndaddr);
396 } else if (IS_IPV4_DSLITE(entry)) {
397 pr_info("Information Block 2: %08X\n",
398 entry->ipv4_dslite.info_blk2);
399 pr_info("Create IPv4 Ds-Lite entry\n");
400 pr_info("IPv4 Ds-Lite: %pI4:%d->%pI4:%d\n", &saddr,
401 entry->ipv4_dslite.sport, &daddr,
402 entry->ipv4_dslite.dport);
403 pr_info("EG DIPv6: %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
404 entry->ipv4_dslite.tunnel_sipv6_0,
405 entry->ipv4_dslite.tunnel_sipv6_1,
406 entry->ipv4_dslite.tunnel_sipv6_2,
407 entry->ipv4_dslite.tunnel_sipv6_3,
408 entry->ipv4_dslite.tunnel_dipv6_0,
409 entry->ipv4_dslite.tunnel_dipv6_1,
410 entry->ipv4_dslite.tunnel_dipv6_2,
411 entry->ipv4_dslite.tunnel_dipv6_3);
developerd35bbcc2022-09-28 22:46:01 +0800412#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +0800413 } else if (IS_IPV4_MAPE(entry)) {
developerd35bbcc2022-09-28 22:46:01 +0800414 nsaddr = htonl(entry->ipv4_mape.new_sip);
415 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +0800416
417 pr_info("Information Block 2: %08X\n",
418 entry->ipv4_dslite.info_blk2);
419 pr_info("Create IPv4 MAP-E entry\n");
420 pr_info("IPv4 MAP-E Org IP/Port: %pI4:%d->%pI4:%d\n",
421 &saddr, entry->ipv4_dslite.sport,
422 &daddr, entry->ipv4_dslite.dport);
423 pr_info("IPv4 MAP-E New IP/Port: %pI4:%d->%pI4:%d\n",
developerd35bbcc2022-09-28 22:46:01 +0800424 &nsaddr, entry->ipv4_mape.new_sport,
425 &ndaddr, entry->ipv4_mape.new_dport);
developerfd40db22021-04-29 10:08:25 +0800426 pr_info("EG DIPv6: %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
427 entry->ipv4_dslite.tunnel_sipv6_0,
428 entry->ipv4_dslite.tunnel_sipv6_1,
429 entry->ipv4_dslite.tunnel_sipv6_2,
430 entry->ipv4_dslite.tunnel_sipv6_3,
431 entry->ipv4_dslite.tunnel_dipv6_0,
432 entry->ipv4_dslite.tunnel_dipv6_1,
433 entry->ipv4_dslite.tunnel_dipv6_2,
434 entry->ipv4_dslite.tunnel_dipv6_3);
435#endif
436 } else if (IS_IPV6_3T_ROUTE(entry)) {
437 pr_info("Information Block 2: %08X\n",
438 entry->ipv6_3t_route.info_blk2);
439 pr_info("Create IPv6 3-Tuple entry\n");
440 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X-> %08X:%08X:%08X:%08X (Prot=%d)\n",
441 entry->ipv6_3t_route.ipv6_sip0,
442 entry->ipv6_3t_route.ipv6_sip1,
443 entry->ipv6_3t_route.ipv6_sip2,
444 entry->ipv6_3t_route.ipv6_sip3,
445 entry->ipv6_3t_route.ipv6_dip0,
446 entry->ipv6_3t_route.ipv6_dip1,
447 entry->ipv6_3t_route.ipv6_dip2,
448 entry->ipv6_3t_route.ipv6_dip3,
449 entry->ipv6_3t_route.prot);
450 } else if (IS_IPV6_5T_ROUTE(entry)) {
451 pr_info("Information Block 2: %08X\n",
452 entry->ipv6_5t_route.info_blk2);
453 pr_info("Create IPv6 5-Tuple entry\n");
454 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X:%d-> %08X:%08X:%08X:%08X:%d\n",
455 entry->ipv6_5t_route.ipv6_sip0,
456 entry->ipv6_5t_route.ipv6_sip1,
457 entry->ipv6_5t_route.ipv6_sip2,
458 entry->ipv6_5t_route.ipv6_sip3,
459 entry->ipv6_5t_route.sport,
460 entry->ipv6_5t_route.ipv6_dip0,
461 entry->ipv6_5t_route.ipv6_dip1,
462 entry->ipv6_5t_route.ipv6_dip2,
463 entry->ipv6_5t_route.ipv6_dip3,
464 entry->ipv6_5t_route.dport);
465 } else if (IS_IPV6_6RD(entry)) {
466 pr_info("Information Block 2: %08X\n",
467 entry->ipv6_6rd.info_blk2);
468 pr_info("Create IPv6 6RD entry\n");
469 pr_info("ING SIPv6->DIPv6: %08X:%08X:%08X:%08X:%d-> %08X:%08X:%08X:%08X:%d\n",
470 entry->ipv6_6rd.ipv6_sip0, entry->ipv6_6rd.ipv6_sip1,
471 entry->ipv6_6rd.ipv6_sip2, entry->ipv6_6rd.ipv6_sip3,
472 entry->ipv6_6rd.sport, entry->ipv6_6rd.ipv6_dip0,
473 entry->ipv6_6rd.ipv6_dip1, entry->ipv6_6rd.ipv6_dip2,
474 entry->ipv6_6rd.ipv6_dip3, entry->ipv6_6rd.dport);
developer5ffc5f12022-10-25 18:51:46 +0800475#if defined(CONFIG_MEDIATEK_NETSYS_V3)
476 } else if (IS_IPV6_HNAPT(entry)) {
477 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
478 entry->ipv6_hnapt.info_blk2,
479 entry->ipv6_hnapt.iblk2.dp,
480 entry->ipv6_hnapt.iblk2.fqos,
481 entry->ipv6_hnapt.iblk2.qid);
482 pr_info("Create IPv6 HNAPT entry\n");
483 pr_info("IPv6 Org IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d",
484 entry->ipv6_hnapt.ipv6_sip0,
485 entry->ipv6_hnapt.ipv6_sip1,
486 entry->ipv6_hnapt.ipv6_sip2,
487 entry->ipv6_hnapt.ipv6_sip3,
488 entry->ipv6_hnapt.sport,
489 entry->ipv6_hnapt.ipv6_dip0,
490 entry->ipv6_hnapt.ipv6_dip1,
491 entry->ipv6_hnapt.ipv6_dip2,
492 entry->ipv6_hnapt.ipv6_dip3,
493 entry->ipv6_hnapt.dport);
494
495 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
496 pr_info("IPv6 New IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
497 entry->ipv6_hnapt.new_ipv6_ip0,
498 entry->ipv6_hnapt.new_ipv6_ip1,
499 entry->ipv6_hnapt.new_ipv6_ip2,
500 entry->ipv6_hnapt.new_ipv6_ip3,
501 entry->ipv6_hnapt.new_sport,
502 entry->ipv6_hnapt.ipv6_dip0,
503 entry->ipv6_hnapt.ipv6_dip1,
504 entry->ipv6_hnapt.ipv6_dip2,
505 entry->ipv6_hnapt.ipv6_dip3,
506 entry->ipv6_hnapt.new_dport);
507 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
508 pr_info("IPv6 New IP/Port: %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
509 entry->ipv6_hnapt.ipv6_sip0,
510 entry->ipv6_hnapt.ipv6_sip1,
511 entry->ipv6_hnapt.ipv6_sip2,
512 entry->ipv6_hnapt.ipv6_sip3,
513 entry->ipv6_hnapt.new_sport,
514 entry->ipv6_hnapt.new_ipv6_ip0,
515 entry->ipv6_hnapt.new_ipv6_ip1,
516 entry->ipv6_hnapt.new_ipv6_ip2,
517 entry->ipv6_hnapt.new_ipv6_ip3,
518 entry->ipv6_hnapt.new_dport);
519 }
520 } else if (IS_IPV6_HNAT(entry)) {
521 pr_info("Information Block 2: %08X (FP=%d FQOS=%d QID=%d)",
522 entry->ipv6_hnapt.info_blk2,
523 entry->ipv6_hnapt.iblk2.dp,
524 entry->ipv6_hnapt.iblk2.fqos,
525 entry->ipv6_hnapt.iblk2.qid);
526 pr_info("Create IPv6 HNAT entry\n");
527 pr_info("IPv6 Org IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X",
528 entry->ipv6_hnapt.ipv6_sip0,
529 entry->ipv6_hnapt.ipv6_sip1,
530 entry->ipv6_hnapt.ipv6_sip2,
531 entry->ipv6_hnapt.ipv6_sip3,
532 entry->ipv6_hnapt.ipv6_dip0,
533 entry->ipv6_hnapt.ipv6_dip1,
534 entry->ipv6_hnapt.ipv6_dip2,
535 entry->ipv6_hnapt.ipv6_dip3);
536
537 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
538 pr_info("IPv6 New IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
539 entry->ipv6_hnapt.new_ipv6_ip0,
540 entry->ipv6_hnapt.new_ipv6_ip1,
541 entry->ipv6_hnapt.new_ipv6_ip2,
542 entry->ipv6_hnapt.new_ipv6_ip3,
543 entry->ipv6_hnapt.ipv6_dip0,
544 entry->ipv6_hnapt.ipv6_dip1,
545 entry->ipv6_hnapt.ipv6_dip2,
546 entry->ipv6_hnapt.ipv6_dip3);
547 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
548 pr_info("IPv6 New IP: %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
549 entry->ipv6_hnapt.ipv6_sip0,
550 entry->ipv6_hnapt.ipv6_sip1,
551 entry->ipv6_hnapt.ipv6_sip2,
552 entry->ipv6_hnapt.ipv6_sip3,
553 entry->ipv6_hnapt.new_ipv6_ip0,
554 entry->ipv6_hnapt.new_ipv6_ip1,
555 entry->ipv6_hnapt.new_ipv6_ip2,
556 entry->ipv6_hnapt.new_ipv6_ip3);
557 }
558#endif
developerfd40db22021-04-29 10:08:25 +0800559 }
developer5ffc5f12022-10-25 18:51:46 +0800560
developerfd40db22021-04-29 10:08:25 +0800561 if (IS_IPV4_HNAPT(entry) || IS_IPV4_HNAT(entry)) {
562 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
563 *((u16 *)&h_source[4]) = swab16(entry->ipv4_hnapt.smac_lo);
564 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
565 *((u16 *)&h_dest[4]) = swab16(entry->ipv4_hnapt.dmac_lo);
566 pr_info("SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
567 pr_info("State = %s, ", entry->bfib1.state == 0 ?
568 "Invalid" : entry->bfib1.state == 1 ?
569 "Unbind" : entry->bfib1.state == 2 ?
570 "BIND" : entry->bfib1.state == 3 ?
571 "FIN" : "Unknown");
572 pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
573 pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
574 entry->ipv4_hnapt.etype, entry->ipv4_hnapt.vlan1,
575 entry->ipv4_hnapt.vlan2);
576 pr_info("multicast = %d, pppoe = %d, proto = %s\n",
577 entry->ipv4_hnapt.iblk2.mcast,
578 entry->ipv4_hnapt.bfib1.psn,
579 entry->ipv4_hnapt.bfib1.udp == 0 ?
580 "TCP" : entry->ipv4_hnapt.bfib1.udp == 1 ?
581 "UDP" : "Unknown");
developerd35bbcc2022-09-28 22:46:01 +0800582#if defined(CONFIG_MEDIATEK_NETSYS_V3)
583 pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
584 entry->ipv4_hnapt.tport_id,
585 entry->ipv4_hnapt.tops_entry,
586 entry->ipv4_hnapt.cdrt_id);
587#endif
developerfd40db22021-04-29 10:08:25 +0800588 pr_info("=========================================\n\n");
589 } else {
590 *((u32 *)h_source) = swab32(entry->ipv6_5t_route.smac_hi);
591 *((u16 *)&h_source[4]) = swab16(entry->ipv6_5t_route.smac_lo);
592 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
593 *((u16 *)&h_dest[4]) = swab16(entry->ipv6_5t_route.dmac_lo);
594 pr_info("SMAC=%pM => DMAC=%pM\n", h_source, h_dest);
595 pr_info("State = %s, ", entry->bfib1.state == 0 ?
596 "Invalid" : entry->bfib1.state == 1 ?
597 "Unbind" : entry->bfib1.state == 2 ?
598 "BIND" : entry->bfib1.state == 3 ?
599 "FIN" : "Unknown");
600
601 pr_info("Vlan_Layer = %u, ", entry->bfib1.vlan_layer);
602 pr_info("Eth_type = 0x%x, Vid1 = 0x%x, Vid2 = 0x%x\n",
603 entry->ipv6_5t_route.etype, entry->ipv6_5t_route.vlan1,
604 entry->ipv6_5t_route.vlan2);
605 pr_info("multicast = %d, pppoe = %d, proto = %s\n",
606 entry->ipv6_5t_route.iblk2.mcast,
607 entry->ipv6_5t_route.bfib1.psn,
608 entry->ipv6_5t_route.bfib1.udp == 0 ?
609 "TCP" : entry->ipv6_5t_route.bfib1.udp == 1 ?
610 "UDP" : "Unknown");
developerd35bbcc2022-09-28 22:46:01 +0800611#if defined(CONFIG_MEDIATEK_NETSYS_V3)
612 pr_info("tport_id = %d, tops_entry = %d, cdrt_id = %d\n",
613 entry->ipv6_5t_route.tport_id,
614 entry->ipv6_5t_route.tops_entry,
615 entry->ipv6_5t_route.cdrt_id);
616#endif
developerfd40db22021-04-29 10:08:25 +0800617 pr_info("=========================================\n\n");
618 }
619 return 0;
620}
621
developer471f6562021-05-10 20:48:34 +0800622int wrapped_ppe0_entry_delete(int index) {
623 entry_delete(0, index);
624 return 0;
625}
626
627int wrapped_ppe1_entry_delete(int index) {
628 entry_delete(1, index);
629 return 0;
630}
631
developer4c32b7a2021-11-13 16:46:43 +0800632int entry_delete(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +0800633{
634 struct foe_entry *entry;
635 struct mtk_hnat *h = hnat_priv;
636
developer471f6562021-05-10 20:48:34 +0800637 if (ppe_id >= CFG_PPE_NUM)
638 return -EINVAL;
639
developer3fb8d472021-11-16 15:46:38 +0800640 if (index < -1 || index >= (int)h->foe_etry_num) {
developerc6227322021-07-09 10:52:53 +0800641 pr_info("Invalid entry index\n");
642 return -EINVAL;
643 }
644
developer3fb8d472021-11-16 15:46:38 +0800645 if (index == -1) {
646 memset(h->foe_table_cpu[ppe_id], 0, h->foe_etry_num * sizeof(struct foe_entry));
647 pr_info("clear all foe entry\n");
648 } else {
649
650 entry = h->foe_table_cpu[ppe_id] + index;
651 memset(entry, 0, sizeof(struct foe_entry));
652 pr_info("delete ppe id = %d, entry idx = %d\n", ppe_id, index);
653 }
developerfd40db22021-04-29 10:08:25 +0800654
655 /* clear HWNAT cache */
656 hnat_cache_ebl(1);
657
developerfd40db22021-04-29 10:08:25 +0800658 return 0;
659}
660EXPORT_SYMBOL(entry_delete);
661
662int cr_set_usage(int level)
663{
664 debug_level = level;
665 pr_info("Dump hnat CR: cat /sys/kernel/debug/hnat/hnat_setting\n\n");
666 pr_info("====================Advanced Settings====================\n");
667 pr_info("Usage: echo [type] [option] > /sys/kernel/debug/hnat/hnat_setting\n\n");
668 pr_info("Commands: [type] [option]\n");
669 pr_info(" 0 0~7 Set debug_level(0~7), current debug_level=%d\n",
670 debug_level);
671 pr_info(" 1 0~65535 Set binding threshold\n");
672 pr_info(" 2 0~65535 Set TCP bind lifetime\n");
673 pr_info(" 3 0~65535 Set FIN bind lifetime\n");
674 pr_info(" 4 0~65535 Set UDP bind lifetime\n");
675 pr_info(" 5 0~255 Set TCP keep alive interval\n");
676 pr_info(" 6 0~255 Set UDP keep alive interval\n");
developer30a47682021-11-02 17:06:14 +0800677 pr_info(" 7 0~1 Set hnat counter update to nf_conntrack\n");
developerfd40db22021-04-29 10:08:25 +0800678
679 return 0;
680}
681
682int binding_threshold(int threshold)
683{
developer471f6562021-05-10 20:48:34 +0800684 int i;
685
developerfd40db22021-04-29 10:08:25 +0800686 pr_info("Binding Threshold =%d\n", threshold);
developer471f6562021-05-10 20:48:34 +0800687
688 for (i = 0; i < CFG_PPE_NUM; i++)
689 writel(threshold, hnat_priv->ppe_base[i] + PPE_BNDR);
690
developerfd40db22021-04-29 10:08:25 +0800691 return 0;
692}
693
694int tcp_bind_lifetime(int tcp_life)
695{
developer471f6562021-05-10 20:48:34 +0800696 int i;
697
developerfd40db22021-04-29 10:08:25 +0800698 pr_info("tcp_life = %d\n", tcp_life);
developer471f6562021-05-10 20:48:34 +0800699
developerfd40db22021-04-29 10:08:25 +0800700 /* set Delta time for aging out an bind TCP FOE entry */
developer471f6562021-05-10 20:48:34 +0800701 for (i = 0; i < CFG_PPE_NUM; i++)
702 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_1,
703 TCP_DLTA, tcp_life);
developerfd40db22021-04-29 10:08:25 +0800704
705 return 0;
706}
707
708int fin_bind_lifetime(int fin_life)
709{
developer471f6562021-05-10 20:48:34 +0800710 int i;
711
developerfd40db22021-04-29 10:08:25 +0800712 pr_info("fin_life = %d\n", fin_life);
developer471f6562021-05-10 20:48:34 +0800713
developerfd40db22021-04-29 10:08:25 +0800714 /* set Delta time for aging out an bind TCP FIN FOE entry */
developer471f6562021-05-10 20:48:34 +0800715 for (i = 0; i < CFG_PPE_NUM; i++)
716 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_1,
717 FIN_DLTA, fin_life);
developerfd40db22021-04-29 10:08:25 +0800718
719 return 0;
720}
721
722int udp_bind_lifetime(int udp_life)
723{
developer471f6562021-05-10 20:48:34 +0800724 int i;
725
developerfd40db22021-04-29 10:08:25 +0800726 pr_info("udp_life = %d\n", udp_life);
developer471f6562021-05-10 20:48:34 +0800727
developerfd40db22021-04-29 10:08:25 +0800728 /* set Delta time for aging out an bind UDP FOE entry */
developer471f6562021-05-10 20:48:34 +0800729 for (i = 0; i < CFG_PPE_NUM; i++)
730 cr_set_field(hnat_priv->ppe_base[i] + PPE_BND_AGE_0,
731 UDP_DLTA, udp_life);
developerfd40db22021-04-29 10:08:25 +0800732
733 return 0;
734}
735
736int tcp_keep_alive(int tcp_interval)
737{
developer471f6562021-05-10 20:48:34 +0800738 int i;
739
developerfd40db22021-04-29 10:08:25 +0800740 if (tcp_interval > 255) {
741 tcp_interval = 255;
742 pr_info("TCP keep alive max interval = 255\n");
743 } else {
744 pr_info("tcp_interval = %d\n", tcp_interval);
745 }
developer471f6562021-05-10 20:48:34 +0800746
developerfd40db22021-04-29 10:08:25 +0800747 /* Keep alive time for bind FOE TCP entry */
developer471f6562021-05-10 20:48:34 +0800748 for (i = 0; i < CFG_PPE_NUM; i++)
749 cr_set_field(hnat_priv->ppe_base[i] + PPE_KA,
750 TCP_KA, tcp_interval);
developerfd40db22021-04-29 10:08:25 +0800751
752 return 0;
753}
754
755int udp_keep_alive(int udp_interval)
756{
developer471f6562021-05-10 20:48:34 +0800757 int i;
758
developerfd40db22021-04-29 10:08:25 +0800759 if (udp_interval > 255) {
760 udp_interval = 255;
761 pr_info("TCP/UDP keep alive max interval = 255\n");
762 } else {
763 pr_info("udp_interval = %d\n", udp_interval);
764 }
developer471f6562021-05-10 20:48:34 +0800765
developerfd40db22021-04-29 10:08:25 +0800766 /* Keep alive timer for bind FOE UDP entry */
developer471f6562021-05-10 20:48:34 +0800767 for (i = 0; i < CFG_PPE_NUM; i++)
768 cr_set_field(hnat_priv->ppe_base[i] + PPE_KA,
769 UDP_KA, udp_interval);
developerfd40db22021-04-29 10:08:25 +0800770
771 return 0;
772}
773
developer30a47682021-11-02 17:06:14 +0800774int set_nf_update_toggle(int toggle)
775{
776 struct mtk_hnat *h = hnat_priv;
777
778 if (toggle == 1)
779 pr_info("Enable hnat counter update to nf_conntrack\n");
780 else if (toggle == 0)
781 pr_info("Disable hnat counter update to nf_conntrack\n");
782 else
783 pr_info("input error\n");
784 h->nf_stat_en = toggle;
785
786 return 0;
787}
788
developerfd40db22021-04-29 10:08:25 +0800789static const debugfs_write_func hnat_set_func[] = {
790 [0] = hnat_set_usage,
791 [1] = hnat_cpu_reason,
792};
793
794static const debugfs_write_func entry_set_func[] = {
795 [0] = entry_set_usage,
796 [1] = entry_set_state,
developer471f6562021-05-10 20:48:34 +0800797 [2] = wrapped_ppe0_entry_detail,
798 [3] = wrapped_ppe0_entry_delete,
799 [4] = wrapped_ppe1_entry_detail,
800 [5] = wrapped_ppe1_entry_delete,
developerfd40db22021-04-29 10:08:25 +0800801};
802
803static const debugfs_write_func cr_set_func[] = {
804 [0] = cr_set_usage, [1] = binding_threshold,
805 [2] = tcp_bind_lifetime, [3] = fin_bind_lifetime,
806 [4] = udp_bind_lifetime, [5] = tcp_keep_alive,
developer30a47682021-11-02 17:06:14 +0800807 [6] = udp_keep_alive, [7] = set_nf_update_toggle,
developerfd40db22021-04-29 10:08:25 +0800808};
809
developer4c32b7a2021-11-13 16:46:43 +0800810int read_mib(struct mtk_hnat *h, u32 ppe_id,
developer30a47682021-11-02 17:06:14 +0800811 u32 index, u64 *bytes, u64 *packets)
developerfd40db22021-04-29 10:08:25 +0800812{
developer30a47682021-11-02 17:06:14 +0800813 int ret;
developerd35bbcc2022-09-28 22:46:01 +0800814 u32 val, cnt_r0, cnt_r1, cnt_r2, cnt_r3;
developer4c32b7a2021-11-13 16:46:43 +0800815
816 if (ppe_id >= CFG_PPE_NUM)
817 return -EINVAL;
818
developer471f6562021-05-10 20:48:34 +0800819 writel(index | (1 << 16), h->ppe_base[ppe_id] + PPE_MIB_SER_CR);
developer30a47682021-11-02 17:06:14 +0800820 ret = readx_poll_timeout_atomic(readl, h->ppe_base[ppe_id] + PPE_MIB_SER_CR, val,
821 !(val & BIT_MIB_BUSY), 20, 10000);
822
developerfd40db22021-04-29 10:08:25 +0800823 if (ret < 0) {
developer30a47682021-11-02 17:06:14 +0800824 pr_notice("mib busy, please check later\n");
825 return ret;
developerfd40db22021-04-29 10:08:25 +0800826 }
developer471f6562021-05-10 20:48:34 +0800827 cnt_r0 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R0);
828 cnt_r1 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R1);
829 cnt_r2 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R2);
developerd35bbcc2022-09-28 22:46:01 +0800830
developer4164cfe2022-12-01 11:27:41 +0800831 if (hnat_priv->data->version == MTK_HNAT_V3) {
developerd35bbcc2022-09-28 22:46:01 +0800832 cnt_r3 = readl(h->ppe_base[ppe_id] + PPE_MIB_SER_R3);
833 *bytes = cnt_r0 + ((u64)cnt_r1 << 32);
834 *packets = cnt_r2 + ((u64)cnt_r3 << 32);
835 } else {
836 *bytes = cnt_r0 + ((u64)(cnt_r1 & 0xffff) << 32);
developer577ad2f2022-11-28 10:33:36 +0800837 *packets = ((cnt_r1 & 0xffff0000) >> 16) +
838 ((u64)(cnt_r2 & 0xffffff) << 16);
developerd35bbcc2022-09-28 22:46:01 +0800839 }
developerfd40db22021-04-29 10:08:25 +0800840
developer30a47682021-11-02 17:06:14 +0800841 return 0;
842
843}
844
developer4c32b7a2021-11-13 16:46:43 +0800845struct hnat_accounting *hnat_get_count(struct mtk_hnat *h, u32 ppe_id,
developer30a47682021-11-02 17:06:14 +0800846 u32 index, struct hnat_accounting *diff)
847
848{
849 u64 bytes, packets;
850
developer4c32b7a2021-11-13 16:46:43 +0800851 if (ppe_id >= CFG_PPE_NUM)
852 return NULL;
853
developer577ad2f2022-11-28 10:33:36 +0800854 if (index >= hnat_priv->foe_etry_num)
855 return NULL;
856
developer30a47682021-11-02 17:06:14 +0800857 if (!hnat_priv->data->per_flow_accounting)
858 return NULL;
859
860 if (read_mib(h, ppe_id, index, &bytes, &packets))
861 return NULL;
862
863 h->acct[ppe_id][index].bytes += bytes;
864 h->acct[ppe_id][index].packets += packets;
developer577ad2f2022-11-28 10:33:36 +0800865
developer30a47682021-11-02 17:06:14 +0800866 if (diff) {
867 diff->bytes = bytes;
868 diff->packets = packets;
869 }
870
871 return &h->acct[ppe_id][index];
developerfd40db22021-04-29 10:08:25 +0800872}
developer30a47682021-11-02 17:06:14 +0800873EXPORT_SYMBOL(hnat_get_count);
developerfd40db22021-04-29 10:08:25 +0800874
developer30a47682021-11-02 17:06:14 +0800875#define PRINT_COUNT(m, acct) {if (acct) \
developerfd40db22021-04-29 10:08:25 +0800876 seq_printf(m, "bytes=%llu|packets=%llu|", \
developer30a47682021-11-02 17:06:14 +0800877 acct->bytes, acct->packets); }
developer4c32b7a2021-11-13 16:46:43 +0800878static int __hnat_debug_show(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +0800879{
880 struct mtk_hnat *h = hnat_priv;
881 struct foe_entry *entry, *end;
882 unsigned char h_dest[ETH_ALEN];
883 unsigned char h_source[ETH_ALEN];
developer30a47682021-11-02 17:06:14 +0800884 struct hnat_accounting *acct;
developerfd40db22021-04-29 10:08:25 +0800885 u32 entry_index = 0;
886
developer4c32b7a2021-11-13 16:46:43 +0800887 if (ppe_id >= CFG_PPE_NUM)
888 return -EINVAL;
889
developer471f6562021-05-10 20:48:34 +0800890 entry = h->foe_table_cpu[ppe_id];
891 end = h->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
developerfd40db22021-04-29 10:08:25 +0800892 while (entry < end) {
893 if (!entry->bfib1.state) {
894 entry++;
895 entry_index++;
896 continue;
897 }
developer30a47682021-11-02 17:06:14 +0800898 acct = hnat_get_count(h, ppe_id, entry_index, NULL);
developerfd40db22021-04-29 10:08:25 +0800899 if (IS_IPV4_HNAPT(entry)) {
900 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
901 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
902 __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
903 __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
904
905 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
906 *((u16 *)&h_source[4]) =
907 swab16(entry->ipv4_hnapt.smac_lo);
908 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
909 *((u16 *)&h_dest[4]) =
910 swab16(entry->ipv4_hnapt.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800911 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800912 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800913 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
914 entry, ppe_id, ei(entry, end),
915 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +0800916 entry->ipv4_hnapt.sport, &daddr,
917 entry->ipv4_hnapt.dport, &nsaddr,
918 entry->ipv4_hnapt.new_sport, &ndaddr,
919 entry->ipv4_hnapt.new_dport, h_source, h_dest,
920 ntohs(entry->ipv4_hnapt.etype),
921 entry->ipv4_hnapt.info_blk1,
922 entry->ipv4_hnapt.info_blk2,
923 entry->ipv4_hnapt.vlan1,
924 entry->ipv4_hnapt.vlan2);
925 } else if (IS_IPV4_HNAT(entry)) {
926 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
927 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
928 __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
929 __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
930
931 *((u32 *)h_source) = swab32(entry->ipv4_hnapt.smac_hi);
932 *((u16 *)&h_source[4]) =
933 swab16(entry->ipv4_hnapt.smac_lo);
934 *((u32 *)h_dest) = swab32(entry->ipv4_hnapt.dmac_hi);
935 *((u16 *)&h_dest[4]) =
936 swab16(entry->ipv4_hnapt.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800937 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800938 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800939 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|%pI4->%pI4=>%pI4->%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
940 entry, ppe_id, ei(entry, end),
941 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +0800942 &daddr, &nsaddr, &ndaddr, h_source, h_dest,
943 ntohs(entry->ipv4_hnapt.etype),
944 entry->ipv4_hnapt.info_blk1,
945 entry->ipv4_hnapt.info_blk2,
946 entry->ipv4_hnapt.vlan1,
947 entry->ipv4_hnapt.vlan2);
948 } else if (IS_IPV6_5T_ROUTE(entry)) {
949 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
950 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
951 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
952 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
953 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
954 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
955 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
956 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
957
958 *((u32 *)h_source) =
959 swab32(entry->ipv6_5t_route.smac_hi);
960 *((u16 *)&h_source[4]) =
961 swab16(entry->ipv6_5t_route.smac_lo);
962 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
963 *((u16 *)&h_dest[4]) =
964 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800965 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800966 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800967 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
968 entry, ppe_id, ei(entry, end), es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +0800969 ipv6_sip1, ipv6_sip2, ipv6_sip3,
970 entry->ipv6_5t_route.sport, ipv6_dip0,
971 ipv6_dip1, ipv6_dip2, ipv6_dip3,
972 entry->ipv6_5t_route.dport, h_source, h_dest,
973 ntohs(entry->ipv6_5t_route.etype),
974 entry->ipv6_5t_route.info_blk1,
975 entry->ipv6_5t_route.info_blk2);
976 } else if (IS_IPV6_3T_ROUTE(entry)) {
977 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
978 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
979 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
980 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
981 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
982 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
983 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
984 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
985
986 *((u32 *)h_source) =
987 swab32(entry->ipv6_5t_route.smac_hi);
988 *((u16 *)&h_source[4]) =
989 swab16(entry->ipv6_5t_route.smac_lo);
990 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
991 *((u16 *)&h_dest[4]) =
992 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +0800993 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +0800994 seq_printf(m,
developer471f6562021-05-10 20:48:34 +0800995 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
996 entry, ppe_id, ei(entry, end),
997 es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +0800998 ipv6_sip1, ipv6_sip2, ipv6_sip3, ipv6_dip0,
999 ipv6_dip1, ipv6_dip2, ipv6_dip3, h_source,
1000 h_dest, ntohs(entry->ipv6_5t_route.etype),
1001 entry->ipv6_5t_route.info_blk1,
1002 entry->ipv6_5t_route.info_blk2);
1003 } else if (IS_IPV6_6RD(entry)) {
1004 u32 ipv6_sip0 = entry->ipv6_3t_route.ipv6_sip0;
1005 u32 ipv6_sip1 = entry->ipv6_3t_route.ipv6_sip1;
1006 u32 ipv6_sip2 = entry->ipv6_3t_route.ipv6_sip2;
1007 u32 ipv6_sip3 = entry->ipv6_3t_route.ipv6_sip3;
1008 u32 ipv6_dip0 = entry->ipv6_3t_route.ipv6_dip0;
1009 u32 ipv6_dip1 = entry->ipv6_3t_route.ipv6_dip1;
1010 u32 ipv6_dip2 = entry->ipv6_3t_route.ipv6_dip2;
1011 u32 ipv6_dip3 = entry->ipv6_3t_route.ipv6_dip3;
1012 __be32 tsaddr = htonl(entry->ipv6_6rd.tunnel_sipv4);
1013 __be32 tdaddr = htonl(entry->ipv6_6rd.tunnel_dipv4);
1014
1015 *((u32 *)h_source) =
1016 swab32(entry->ipv6_5t_route.smac_hi);
1017 *((u16 *)&h_source[4]) =
1018 swab16(entry->ipv6_5t_route.smac_lo);
1019 *((u32 *)h_dest) = swab32(entry->ipv6_5t_route.dmac_hi);
1020 *((u16 *)&h_dest[4]) =
1021 swab16(entry->ipv6_5t_route.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001022 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001023 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001024 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|TSIP=%pI4->TDIP=%pI4|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1025 entry, ppe_id, ei(entry, end),
1026 es(entry), pt(entry), ipv6_sip0,
developerfd40db22021-04-29 10:08:25 +08001027 ipv6_sip1, ipv6_sip2, ipv6_sip3,
1028 entry->ipv6_5t_route.sport, ipv6_dip0,
1029 ipv6_dip1, ipv6_dip2, ipv6_dip3,
1030 entry->ipv6_5t_route.dport, &tsaddr, &tdaddr,
1031 h_source, h_dest,
1032 ntohs(entry->ipv6_5t_route.etype),
1033 entry->ipv6_5t_route.info_blk1,
1034 entry->ipv6_5t_route.info_blk2);
developer5ffc5f12022-10-25 18:51:46 +08001035#if defined(CONFIG_MEDIATEK_NETSYS_V3)
1036 } else if (IS_IPV6_HNAPT(entry)) {
1037 u32 ipv6_sip0 = entry->ipv6_hnapt.ipv6_sip0;
1038 u32 ipv6_sip1 = entry->ipv6_hnapt.ipv6_sip1;
1039 u32 ipv6_sip2 = entry->ipv6_hnapt.ipv6_sip2;
1040 u32 ipv6_sip3 = entry->ipv6_hnapt.ipv6_sip3;
1041 u32 ipv6_dip0 = entry->ipv6_hnapt.ipv6_dip0;
1042 u32 ipv6_dip1 = entry->ipv6_hnapt.ipv6_dip1;
1043 u32 ipv6_dip2 = entry->ipv6_hnapt.ipv6_dip2;
1044 u32 ipv6_dip3 = entry->ipv6_hnapt.ipv6_dip3;
1045 u32 new_ipv6_ip0 = entry->ipv6_hnapt.new_ipv6_ip0;
1046 u32 new_ipv6_ip1 = entry->ipv6_hnapt.new_ipv6_ip1;
1047 u32 new_ipv6_ip2 = entry->ipv6_hnapt.new_ipv6_ip2;
1048 u32 new_ipv6_ip3 = entry->ipv6_hnapt.new_ipv6_ip3;
1049
1050 *((u32 *)h_source) = swab32(entry->ipv6_hnapt.smac_hi);
1051 *((u16 *)&h_source[4]) =
1052 swab16(entry->ipv6_hnapt.smac_lo);
1053 *((u32 *)h_dest) = swab32(entry->ipv6_hnapt.dmac_hi);
1054 *((u16 *)&h_dest[4]) =
1055 swab16(entry->ipv6_hnapt.dmac_lo);
1056 PRINT_COUNT(m, acct);
1057
1058 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1059 seq_printf(m,
1060 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1061 entry, ppe_id, ei(entry, end),
1062 es(entry), pt(entry),
1063 ipv6_sip0, ipv6_sip1,
1064 ipv6_sip2, ipv6_sip3,
1065 entry->ipv6_hnapt.sport,
1066 ipv6_dip0, ipv6_dip1,
1067 ipv6_dip2, ipv6_dip3,
1068 entry->ipv6_hnapt.dport,
1069 new_ipv6_ip0, new_ipv6_ip1,
1070 new_ipv6_ip2, new_ipv6_ip3,
1071 entry->ipv6_hnapt.new_sport,
1072 ipv6_dip0, ipv6_dip1,
1073 ipv6_dip2, ipv6_dip3,
1074 entry->ipv6_hnapt.new_dport,
1075 h_source, h_dest,
1076 ntohs(entry->ipv6_hnapt.etype),
1077 entry->ipv6_hnapt.info_blk1,
1078 entry->ipv6_hnapt.info_blk2,
1079 entry->ipv6_hnapt.vlan1,
1080 entry->ipv6_hnapt.vlan2);
1081 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1082 seq_printf(m,
1083 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x(sp=%d)->DIP=%08x:%08x:%08x:%08x(dp=%d)|NEW_SIP=%08x:%08x:%08x:%08x(sp=%d)->NEW_DIP=%08x:%08x:%08x:%08x(dp=%d)|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1084 entry, ppe_id, ei(entry, end),
1085 es(entry), pt(entry),
1086 ipv6_sip0, ipv6_sip1,
1087 ipv6_sip2, ipv6_sip3,
1088 entry->ipv6_hnapt.sport,
1089 ipv6_dip0, ipv6_dip1,
1090 ipv6_dip2, ipv6_dip3,
1091 entry->ipv6_hnapt.dport,
1092 ipv6_sip0, ipv6_sip1,
1093 ipv6_sip2, ipv6_sip3,
1094 entry->ipv6_hnapt.new_sport,
1095 new_ipv6_ip0, new_ipv6_ip1,
1096 new_ipv6_ip2, new_ipv6_ip3,
1097 entry->ipv6_hnapt.new_dport,
1098 h_source, h_dest,
1099 ntohs(entry->ipv6_hnapt.etype),
1100 entry->ipv6_hnapt.info_blk1,
1101 entry->ipv6_hnapt.info_blk2,
1102 entry->ipv6_hnapt.vlan1,
1103 entry->ipv6_hnapt.vlan2);
1104 }
1105 } else if (IS_IPV6_HNAT(entry)) {
1106 u32 ipv6_sip0 = entry->ipv6_hnapt.ipv6_sip0;
1107 u32 ipv6_sip1 = entry->ipv6_hnapt.ipv6_sip1;
1108 u32 ipv6_sip2 = entry->ipv6_hnapt.ipv6_sip2;
1109 u32 ipv6_sip3 = entry->ipv6_hnapt.ipv6_sip3;
1110 u32 ipv6_dip0 = entry->ipv6_hnapt.ipv6_dip0;
1111 u32 ipv6_dip1 = entry->ipv6_hnapt.ipv6_dip1;
1112 u32 ipv6_dip2 = entry->ipv6_hnapt.ipv6_dip2;
1113 u32 ipv6_dip3 = entry->ipv6_hnapt.ipv6_dip3;
1114 u32 new_ipv6_ip0 = entry->ipv6_hnapt.new_ipv6_ip0;
1115 u32 new_ipv6_ip1 = entry->ipv6_hnapt.new_ipv6_ip1;
1116 u32 new_ipv6_ip2 = entry->ipv6_hnapt.new_ipv6_ip2;
1117 u32 new_ipv6_ip3 = entry->ipv6_hnapt.new_ipv6_ip3;
1118
1119 *((u32 *)h_source) = swab32(entry->ipv6_hnapt.smac_hi);
1120 *((u16 *)&h_source[4]) =
1121 swab16(entry->ipv6_hnapt.smac_lo);
1122 *((u32 *)h_dest) = swab32(entry->ipv6_hnapt.dmac_hi);
1123 *((u16 *)&h_dest[4]) =
1124 swab16(entry->ipv6_hnapt.dmac_lo);
1125 PRINT_COUNT(m, acct);
1126
1127 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1128 seq_printf(m,
1129 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1130 entry, ppe_id, ei(entry, end),
1131 es(entry), pt(entry),
1132 ipv6_sip0, ipv6_sip1,
1133 ipv6_sip2, ipv6_sip3,
1134 ipv6_dip0, ipv6_dip1,
1135 ipv6_dip2, ipv6_dip3,
1136 new_ipv6_ip0, new_ipv6_ip1,
1137 new_ipv6_ip2, new_ipv6_ip3,
1138 ipv6_dip0, ipv6_dip1,
1139 ipv6_dip2, ipv6_dip3,
1140 h_source, h_dest,
1141 ntohs(entry->ipv6_hnapt.etype),
1142 entry->ipv6_hnapt.info_blk1,
1143 entry->ipv6_hnapt.info_blk2,
1144 entry->ipv6_hnapt.vlan1,
1145 entry->ipv6_hnapt.vlan2);
1146 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1147 seq_printf(m,
1148 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%08x:%08x:%08x:%08x->DIP=%08x:%08x:%08x:%08x|NEW_SIP=%08x:%08x:%08x:%08x->NEW_DIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n",
1149 entry, ppe_id, ei(entry, end),
1150 es(entry), pt(entry),
1151 ipv6_sip0, ipv6_sip1,
1152 ipv6_sip2, ipv6_sip3,
1153 ipv6_dip0, ipv6_dip1,
1154 ipv6_dip2, ipv6_dip3,
1155 ipv6_sip0, ipv6_sip1,
1156 ipv6_sip2, ipv6_sip3,
1157 new_ipv6_ip0, new_ipv6_ip1,
1158 new_ipv6_ip2, new_ipv6_ip3,
1159 h_source, h_dest,
1160 ntohs(entry->ipv6_hnapt.etype),
1161 entry->ipv6_hnapt.info_blk1,
1162 entry->ipv6_hnapt.info_blk2,
1163 entry->ipv6_hnapt.vlan1,
1164 entry->ipv6_hnapt.vlan2);
1165 }
1166#endif
developerfd40db22021-04-29 10:08:25 +08001167 } else if (IS_IPV4_DSLITE(entry)) {
1168 __be32 saddr = htonl(entry->ipv4_hnapt.sip);
1169 __be32 daddr = htonl(entry->ipv4_hnapt.dip);
1170 u32 ipv6_tsip0 = entry->ipv4_dslite.tunnel_sipv6_0;
1171 u32 ipv6_tsip1 = entry->ipv4_dslite.tunnel_sipv6_1;
1172 u32 ipv6_tsip2 = entry->ipv4_dslite.tunnel_sipv6_2;
1173 u32 ipv6_tsip3 = entry->ipv4_dslite.tunnel_sipv6_3;
1174 u32 ipv6_tdip0 = entry->ipv4_dslite.tunnel_dipv6_0;
1175 u32 ipv6_tdip1 = entry->ipv4_dslite.tunnel_dipv6_1;
1176 u32 ipv6_tdip2 = entry->ipv4_dslite.tunnel_dipv6_2;
1177 u32 ipv6_tdip3 = entry->ipv4_dslite.tunnel_dipv6_3;
1178
1179 *((u32 *)h_source) = swab32(entry->ipv4_dslite.smac_hi);
1180 *((u16 *)&h_source[4]) =
1181 swab16(entry->ipv4_dslite.smac_lo);
1182 *((u32 *)h_dest) = swab32(entry->ipv4_dslite.dmac_hi);
1183 *((u16 *)&h_dest[4]) =
1184 swab16(entry->ipv4_dslite.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001185 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001186 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001187 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4->DIP=%pI4|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1188 entry, ppe_id, ei(entry, end),
1189 es(entry), pt(entry), &saddr,
developerfd40db22021-04-29 10:08:25 +08001190 &daddr, ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
1191 ipv6_tsip3, ipv6_tdip0, ipv6_tdip1, ipv6_tdip2,
1192 ipv6_tdip3, h_source, h_dest,
1193 ntohs(entry->ipv6_5t_route.etype),
1194 entry->ipv6_5t_route.info_blk1,
1195 entry->ipv6_5t_route.info_blk2);
developerd35bbcc2022-09-28 22:46:01 +08001196#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +08001197 } else if (IS_IPV4_MAPE(entry)) {
1198 __be32 saddr = htonl(entry->ipv4_dslite.sip);
1199 __be32 daddr = htonl(entry->ipv4_dslite.dip);
developerd35bbcc2022-09-28 22:46:01 +08001200 __be32 nsaddr = htonl(entry->ipv4_mape.new_sip);
1201 __be32 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +08001202 u32 ipv6_tsip0 = entry->ipv4_dslite.tunnel_sipv6_0;
1203 u32 ipv6_tsip1 = entry->ipv4_dslite.tunnel_sipv6_1;
1204 u32 ipv6_tsip2 = entry->ipv4_dslite.tunnel_sipv6_2;
1205 u32 ipv6_tsip3 = entry->ipv4_dslite.tunnel_sipv6_3;
1206 u32 ipv6_tdip0 = entry->ipv4_dslite.tunnel_dipv6_0;
1207 u32 ipv6_tdip1 = entry->ipv4_dslite.tunnel_dipv6_1;
1208 u32 ipv6_tdip2 = entry->ipv4_dslite.tunnel_dipv6_2;
1209 u32 ipv6_tdip3 = entry->ipv4_dslite.tunnel_dipv6_3;
1210
1211 *((u32 *)h_source) = swab32(entry->ipv4_dslite.smac_hi);
1212 *((u16 *)&h_source[4]) =
1213 swab16(entry->ipv4_dslite.smac_lo);
1214 *((u32 *)h_dest) = swab32(entry->ipv4_dslite.dmac_hi);
1215 *((u16 *)&h_dest[4]) =
1216 swab16(entry->ipv4_dslite.dmac_lo);
developer30a47682021-11-02 17:06:14 +08001217 PRINT_COUNT(m, acct);
developerfd40db22021-04-29 10:08:25 +08001218 seq_printf(m,
developer471f6562021-05-10 20:48:34 +08001219 "addr=0x%p|ppe=%d|index=%d|state=%s|type=%s|SIP=%pI4:%d->DIP=%pI4:%d|NSIP=%pI4:%d->NDIP=%pI4:%d|TSIP=%08x:%08x:%08x:%08x->TDIP=%08x:%08x:%08x:%08x|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x\n",
1220 entry, ppe_id, ei(entry, end),
1221 es(entry), pt(entry),
developerfd40db22021-04-29 10:08:25 +08001222 &saddr, entry->ipv4_dslite.sport,
1223 &daddr, entry->ipv4_dslite.dport,
developerd35bbcc2022-09-28 22:46:01 +08001224 &nsaddr, entry->ipv4_mape.new_sport,
1225 &ndaddr, entry->ipv4_mape.new_dport,
developerfd40db22021-04-29 10:08:25 +08001226 ipv6_tsip0, ipv6_tsip1, ipv6_tsip2,
1227 ipv6_tsip3, ipv6_tdip0, ipv6_tdip1,
1228 ipv6_tdip2, ipv6_tdip3, h_source, h_dest,
1229 ntohs(entry->ipv6_5t_route.etype),
1230 entry->ipv6_5t_route.info_blk1,
1231 entry->ipv6_5t_route.info_blk2);
1232#endif
1233 } else
developer471f6562021-05-10 20:48:34 +08001234 seq_printf(m, "addr=0x%p|ppe=%d|index=%d state=%s\n", entry, ppe_id, ei(entry, end),
developerfd40db22021-04-29 10:08:25 +08001235 es(entry));
1236 entry++;
1237 entry_index++;
1238 }
1239
1240 return 0;
1241}
1242
developer471f6562021-05-10 20:48:34 +08001243static int hnat_debug_show(struct seq_file *m, void *private)
1244{
1245 int i;
1246
1247 for (i = 0; i < CFG_PPE_NUM; i++)
1248 __hnat_debug_show(m, private, i);
1249
1250 return 0;
1251}
1252
developerfd40db22021-04-29 10:08:25 +08001253static int hnat_debug_open(struct inode *inode, struct file *file)
1254{
1255 return single_open(file, hnat_debug_show, file->private_data);
1256}
1257
1258static const struct file_operations hnat_debug_fops = {
1259 .open = hnat_debug_open,
1260 .read = seq_read,
1261 .llseek = seq_lseek,
1262 .release = single_release,
1263};
1264
1265static int hnat_whnat_show(struct seq_file *m, void *private)
1266{
1267 int i;
1268 struct net_device *dev;
1269
1270 for (i = 0; i < MAX_IF_NUM; i++) {
1271 dev = hnat_priv->wifi_hook_if[i];
1272 if (dev)
1273 seq_printf(m, "%d:%s\n", i, dev->name);
1274 else
1275 continue;
1276 }
1277
1278 return 0;
1279}
1280
1281static int hnat_whnat_open(struct inode *inode, struct file *file)
1282{
1283 return single_open(file, hnat_whnat_show, file->private_data);
1284}
1285
developerf0345dc2022-03-11 16:53:08 +08001286static ssize_t hnat_whnat_write(struct file *file, const char __user *buf,
1287 size_t length, loff_t *offset)
1288{
1289 char line[64] = {0};
1290 struct net_device *dev;
1291 int enable;
1292 char name[32];
1293 size_t size;
1294
1295 if (length >= sizeof(line))
1296 return -EINVAL;
1297
1298 if (copy_from_user(line, buf, length))
1299 return -EFAULT;
1300
developer659fdeb2022-12-01 23:03:07 +08001301 if (sscanf(line, "%15s %1d", name, &enable) != 2)
developerf0345dc2022-03-11 16:53:08 +08001302 return -EFAULT;
1303
1304 line[length] = '\0';
1305
1306 dev = dev_get_by_name(&init_net, name);
1307
1308 if (dev) {
1309 if (enable) {
1310 mtk_ppe_dev_register_hook(dev);
1311 pr_info("register wifi extern if = %s\n", dev->name);
1312 } else {
1313 mtk_ppe_dev_unregister_hook(dev);
1314 pr_info("unregister wifi extern if = %s\n", dev->name);
1315 }
developera7e6c242022-12-05 13:52:40 +08001316 dev_put(dev);
developerf0345dc2022-03-11 16:53:08 +08001317 } else {
1318 pr_info("no such device!\n");
1319 }
1320
1321 size = strlen(line);
1322 *offset += size;
1323
1324 return length;
1325}
1326
1327
developerfd40db22021-04-29 10:08:25 +08001328static const struct file_operations hnat_whnat_fops = {
1329 .open = hnat_whnat_open,
1330 .read = seq_read,
1331 .llseek = seq_lseek,
developerf0345dc2022-03-11 16:53:08 +08001332 .write = hnat_whnat_write,
developerfd40db22021-04-29 10:08:25 +08001333 .release = single_release,
1334};
1335
1336int cpu_reason_read(struct seq_file *m, void *private)
1337{
1338 int i;
1339
1340 pr_info("============ CPU REASON =========\n");
1341 pr_info("(2)IPv4(IPv6) TTL(hop limit) = %u\n", dbg_cpu_reason_cnt[0]);
1342 pr_info("(3)Ipv4(IPv6) has option(extension) header = %u\n",
1343 dbg_cpu_reason_cnt[1]);
1344 pr_info("(7)No flow is assigned = %u\n", dbg_cpu_reason_cnt[2]);
1345 pr_info("(8)IPv4 HNAT doesn't support IPv4 /w fragment = %u\n",
1346 dbg_cpu_reason_cnt[3]);
1347 pr_info("(9)IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment = %u\n",
1348 dbg_cpu_reason_cnt[4]);
1349 pr_info("(10)IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport = %u\n",
1350 dbg_cpu_reason_cnt[5]);
1351 pr_info("(11)IPv6 5T-route/6RD can't find TCP/UDP sport/dport = %u\n",
1352 dbg_cpu_reason_cnt[6]);
1353 pr_info("(12)Ingress packet is TCP fin/syn/rst = %u\n",
1354 dbg_cpu_reason_cnt[7]);
1355 pr_info("(13)FOE Un-hit = %u\n", dbg_cpu_reason_cnt[8]);
1356 pr_info("(14)FOE Hit unbind = %u\n", dbg_cpu_reason_cnt[9]);
1357 pr_info("(15)FOE Hit unbind & rate reach = %u\n",
1358 dbg_cpu_reason_cnt[10]);
1359 pr_info("(16)Hit bind PPE TCP FIN entry = %u\n",
1360 dbg_cpu_reason_cnt[11]);
1361 pr_info("(17)Hit bind PPE entry and TTL(hop limit) = 1 and TTL(hot limit) - 1 = %u\n",
1362 dbg_cpu_reason_cnt[12]);
1363 pr_info("(18)Hit bind and VLAN replacement violation = %u\n",
1364 dbg_cpu_reason_cnt[13]);
1365 pr_info("(19)Hit bind and keep alive with unicast old-header packet = %u\n",
1366 dbg_cpu_reason_cnt[14]);
1367 pr_info("(20)Hit bind and keep alive with multicast new-header packet = %u\n",
1368 dbg_cpu_reason_cnt[15]);
1369 pr_info("(21)Hit bind and keep alive with duplicate old-header packet = %u\n",
1370 dbg_cpu_reason_cnt[16]);
1371 pr_info("(22)FOE Hit bind & force to CPU = %u\n",
1372 dbg_cpu_reason_cnt[17]);
1373 pr_info("(28)Hit bind and exceed MTU =%u\n", dbg_cpu_reason_cnt[18]);
1374 pr_info("(24)Hit bind multicast packet to CPU = %u\n",
1375 dbg_cpu_reason_cnt[19]);
1376 pr_info("(25)Hit bind multicast packet to GMAC & CPU = %u\n",
1377 dbg_cpu_reason_cnt[20]);
1378 pr_info("(26)Pre bind = %u\n", dbg_cpu_reason_cnt[21]);
1379
1380 for (i = 0; i < 22; i++)
1381 dbg_cpu_reason_cnt[i] = 0;
1382 return 0;
1383}
1384
1385static int cpu_reason_open(struct inode *inode, struct file *file)
1386{
1387 return single_open(file, cpu_reason_read, file->private_data);
1388}
1389
1390ssize_t cpu_reason_write(struct file *file, const char __user *buffer,
1391 size_t count, loff_t *data)
1392{
1393 char buf[32];
1394 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001395 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001396 long arg0 = 0, arg1 = 0;
1397 char *p_token = NULL;
1398 char *p_delimiter = " \t";
1399 int ret;
1400
1401 if (len >= sizeof(buf)) {
1402 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001403 return -1;
1404 }
1405
1406 if (copy_from_user(buf, buffer, len))
1407 return -EFAULT;
1408
1409 buf[len] = '\0';
1410
1411 p_buf = buf;
1412 p_token = strsep(&p_buf, p_delimiter);
1413 if (!p_token)
1414 arg0 = 0;
1415 else
1416 ret = kstrtol(p_token, 10, &arg0);
1417
1418 switch (arg0) {
1419 case 0:
1420 case 1:
1421 p_token = strsep(&p_buf, p_delimiter);
1422 if (!p_token)
1423 arg1 = 0;
1424 else
1425 ret = kstrtol(p_token, 10, &arg1);
1426 break;
1427 default:
1428 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1429 arg0 = 0;
1430 arg1 = 0;
1431 break;
1432 }
1433
1434 (*hnat_set_func[arg0])(arg1);
1435
1436 return len;
1437}
1438
1439static const struct file_operations cpu_reason_fops = {
1440 .open = cpu_reason_open,
1441 .read = seq_read,
1442 .llseek = seq_lseek,
1443 .write = cpu_reason_write,
1444 .release = single_release,
1445};
1446
1447void dbg_dump_entry(struct seq_file *m, struct foe_entry *entry,
1448 uint32_t index)
1449{
1450 __be32 saddr, daddr, nsaddr, ndaddr;
1451
1452 saddr = htonl(entry->ipv4_hnapt.sip);
1453 daddr = htonl(entry->ipv4_hnapt.dip);
1454 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
1455 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
1456
1457 if (IS_IPV4_HNAPT(entry)) {
1458 seq_printf(m,
1459 "NAPT(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d\n",
1460 index, &saddr, entry->ipv4_hnapt.sport, &daddr,
1461 entry->ipv4_hnapt.dport, &nsaddr,
1462 entry->ipv4_hnapt.new_sport, &ndaddr,
1463 entry->ipv4_hnapt.new_dport);
1464 } else if (IS_IPV4_HNAT(entry)) {
1465 seq_printf(m, "NAT(%d): %pI4->%pI4 => %pI4->%pI4\n",
1466 index, &saddr, &daddr, &nsaddr, &ndaddr);
1467 }
1468
1469 if (IS_IPV4_DSLITE(entry)) {
1470 seq_printf(m,
1471 "IPv4 Ds-Lite(%d): %pI4:%d->%pI4:%d => %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1472 index, &saddr, entry->ipv4_dslite.sport, &daddr,
1473 entry->ipv4_dslite.dport,
1474 entry->ipv4_dslite.tunnel_sipv6_0,
1475 entry->ipv4_dslite.tunnel_sipv6_1,
1476 entry->ipv4_dslite.tunnel_sipv6_2,
1477 entry->ipv4_dslite.tunnel_sipv6_3,
1478 entry->ipv4_dslite.tunnel_dipv6_0,
1479 entry->ipv4_dslite.tunnel_dipv6_1,
1480 entry->ipv4_dslite.tunnel_dipv6_2,
1481 entry->ipv4_dslite.tunnel_dipv6_3);
developerd35bbcc2022-09-28 22:46:01 +08001482#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +08001483 } else if (IS_IPV4_MAPE(entry)) {
developerd35bbcc2022-09-28 22:46:01 +08001484 nsaddr = htonl(entry->ipv4_mape.new_sip);
1485 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +08001486
1487 seq_printf(m,
1488 "IPv4 MAP-E(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d | Tunnel=%08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1489 index, &saddr, entry->ipv4_dslite.sport,
1490 &daddr, entry->ipv4_dslite.dport,
developerd35bbcc2022-09-28 22:46:01 +08001491 &nsaddr, entry->ipv4_mape.new_sport,
1492 &ndaddr, entry->ipv4_mape.new_dport,
developerfd40db22021-04-29 10:08:25 +08001493 entry->ipv4_dslite.tunnel_sipv6_0,
1494 entry->ipv4_dslite.tunnel_sipv6_1,
1495 entry->ipv4_dslite.tunnel_sipv6_2,
1496 entry->ipv4_dslite.tunnel_sipv6_3,
1497 entry->ipv4_dslite.tunnel_dipv6_0,
1498 entry->ipv4_dslite.tunnel_dipv6_1,
1499 entry->ipv4_dslite.tunnel_dipv6_2,
1500 entry->ipv4_dslite.tunnel_dipv6_3);
1501#endif
1502 } else if (IS_IPV6_3T_ROUTE(entry)) {
1503 seq_printf(m,
1504 "IPv6_3T(%d): %08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X (Prot=%d)\n",
1505 index, entry->ipv6_3t_route.ipv6_sip0,
1506 entry->ipv6_3t_route.ipv6_sip1,
1507 entry->ipv6_3t_route.ipv6_sip2,
1508 entry->ipv6_3t_route.ipv6_sip3,
1509 entry->ipv6_3t_route.ipv6_dip0,
1510 entry->ipv6_3t_route.ipv6_dip1,
1511 entry->ipv6_3t_route.ipv6_dip2,
1512 entry->ipv6_3t_route.ipv6_dip3,
1513 entry->ipv6_3t_route.prot);
1514 } else if (IS_IPV6_5T_ROUTE(entry)) {
1515 seq_printf(m,
1516 "IPv6_5T(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1517 index, entry->ipv6_5t_route.ipv6_sip0,
1518 entry->ipv6_5t_route.ipv6_sip1,
1519 entry->ipv6_5t_route.ipv6_sip2,
1520 entry->ipv6_5t_route.ipv6_sip3,
1521 entry->ipv6_5t_route.sport,
1522 entry->ipv6_5t_route.ipv6_dip0,
1523 entry->ipv6_5t_route.ipv6_dip1,
1524 entry->ipv6_5t_route.ipv6_dip2,
1525 entry->ipv6_5t_route.ipv6_dip3,
1526 entry->ipv6_5t_route.dport);
1527 } else if (IS_IPV6_6RD(entry)) {
1528 seq_printf(m,
1529 "IPv6_6RD(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1530 index, entry->ipv6_6rd.ipv6_sip0,
1531 entry->ipv6_6rd.ipv6_sip1, entry->ipv6_6rd.ipv6_sip2,
1532 entry->ipv6_6rd.ipv6_sip3, entry->ipv6_6rd.sport,
1533 entry->ipv6_6rd.ipv6_dip0, entry->ipv6_6rd.ipv6_dip1,
1534 entry->ipv6_6rd.ipv6_dip2, entry->ipv6_6rd.ipv6_dip3,
1535 entry->ipv6_6rd.dport);
developer5ffc5f12022-10-25 18:51:46 +08001536#if defined(CONFIG_MEDIATEK_NETSYS_V3)
1537 } else if (IS_IPV6_HNAPT(entry)) {
1538 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1539 seq_printf(m,
1540 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1541 index, entry->ipv6_hnapt.ipv6_sip0,
1542 entry->ipv6_hnapt.ipv6_sip1,
1543 entry->ipv6_hnapt.ipv6_sip2,
1544 entry->ipv6_hnapt.ipv6_sip3,
1545 entry->ipv6_hnapt.sport,
1546 entry->ipv6_hnapt.ipv6_dip0,
1547 entry->ipv6_hnapt.ipv6_dip1,
1548 entry->ipv6_hnapt.ipv6_dip2,
1549 entry->ipv6_hnapt.ipv6_dip3,
1550 entry->ipv6_hnapt.dport,
1551 entry->ipv6_hnapt.new_ipv6_ip0,
1552 entry->ipv6_hnapt.new_ipv6_ip1,
1553 entry->ipv6_hnapt.new_ipv6_ip2,
1554 entry->ipv6_hnapt.new_ipv6_ip3,
1555 entry->ipv6_hnapt.new_sport,
1556 entry->ipv6_hnapt.ipv6_dip0,
1557 entry->ipv6_hnapt.ipv6_dip1,
1558 entry->ipv6_hnapt.ipv6_dip2,
1559 entry->ipv6_hnapt.ipv6_dip3,
1560 entry->ipv6_hnapt.new_dport);
1561 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1562 seq_printf(m,
1563 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1564 index, entry->ipv6_hnapt.ipv6_sip0,
1565 entry->ipv6_hnapt.ipv6_sip1,
1566 entry->ipv6_hnapt.ipv6_sip2,
1567 entry->ipv6_hnapt.ipv6_sip3,
1568 entry->ipv6_hnapt.sport,
1569 entry->ipv6_hnapt.ipv6_dip0,
1570 entry->ipv6_hnapt.ipv6_dip1,
1571 entry->ipv6_hnapt.ipv6_dip2,
1572 entry->ipv6_hnapt.ipv6_dip3,
1573 entry->ipv6_hnapt.dport,
1574 entry->ipv6_hnapt.ipv6_sip0,
1575 entry->ipv6_hnapt.ipv6_sip1,
1576 entry->ipv6_hnapt.ipv6_sip2,
1577 entry->ipv6_hnapt.ipv6_sip3,
1578 entry->ipv6_hnapt.new_sport,
1579 entry->ipv6_hnapt.new_ipv6_ip0,
1580 entry->ipv6_hnapt.new_ipv6_ip1,
1581 entry->ipv6_hnapt.new_ipv6_ip2,
1582 entry->ipv6_hnapt.new_ipv6_ip3,
1583 entry->ipv6_hnapt.new_dport);
1584 }
1585 } else if (IS_IPV6_HNAT(entry)) {
1586 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1587 seq_printf(m,
1588 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1589 index, entry->ipv6_hnapt.ipv6_sip0,
1590 entry->ipv6_hnapt.ipv6_sip1,
1591 entry->ipv6_hnapt.ipv6_sip2,
1592 entry->ipv6_hnapt.ipv6_sip3,
1593 entry->ipv6_hnapt.ipv6_dip0,
1594 entry->ipv6_hnapt.ipv6_dip1,
1595 entry->ipv6_hnapt.ipv6_dip2,
1596 entry->ipv6_hnapt.ipv6_dip3,
1597 entry->ipv6_hnapt.new_ipv6_ip0,
1598 entry->ipv6_hnapt.new_ipv6_ip1,
1599 entry->ipv6_hnapt.new_ipv6_ip2,
1600 entry->ipv6_hnapt.new_ipv6_ip3,
1601 entry->ipv6_hnapt.ipv6_dip0,
1602 entry->ipv6_hnapt.ipv6_dip1,
1603 entry->ipv6_hnapt.ipv6_dip2,
1604 entry->ipv6_hnapt.ipv6_dip3);
1605 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1606 seq_printf(m,
1607 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1608 index, entry->ipv6_hnapt.ipv6_sip0,
1609 entry->ipv6_hnapt.ipv6_sip1,
1610 entry->ipv6_hnapt.ipv6_sip2,
1611 entry->ipv6_hnapt.ipv6_sip3,
1612 entry->ipv6_hnapt.ipv6_dip0,
1613 entry->ipv6_hnapt.ipv6_dip1,
1614 entry->ipv6_hnapt.ipv6_dip2,
1615 entry->ipv6_hnapt.ipv6_dip3,
1616 entry->ipv6_hnapt.ipv6_sip0,
1617 entry->ipv6_hnapt.ipv6_sip1,
1618 entry->ipv6_hnapt.ipv6_sip2,
1619 entry->ipv6_hnapt.ipv6_sip3,
1620 entry->ipv6_hnapt.new_ipv6_ip0,
1621 entry->ipv6_hnapt.new_ipv6_ip1,
1622 entry->ipv6_hnapt.new_ipv6_ip2,
1623 entry->ipv6_hnapt.new_ipv6_ip3);
1624 }
1625#endif
developerfd40db22021-04-29 10:08:25 +08001626 }
1627}
1628
developer4c32b7a2021-11-13 16:46:43 +08001629int __hnat_entry_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001630{
1631 struct mtk_hnat *h = hnat_priv;
1632 struct foe_entry *entry, *end;
1633 int hash_index;
1634 int cnt;
1635
developer4c32b7a2021-11-13 16:46:43 +08001636 if (ppe_id >= CFG_PPE_NUM)
1637 return -EINVAL;
1638
developerfd40db22021-04-29 10:08:25 +08001639 hash_index = 0;
1640 cnt = 0;
developer471f6562021-05-10 20:48:34 +08001641 entry = h->foe_table_cpu[ppe_id];
1642 end = h->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
1643
1644 seq_printf(m, "============================\n");
1645 seq_printf(m, "PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001646
1647 while (entry < end) {
1648 if (entry->bfib1.state == dbg_entry_state) {
1649 cnt++;
1650 dbg_dump_entry(m, entry, hash_index);
1651 }
1652 hash_index++;
1653 entry++;
1654 }
1655
1656 seq_printf(m, "Total State = %s cnt = %d\n",
1657 dbg_entry_state == 0 ?
1658 "Invalid" : dbg_entry_state == 1 ?
1659 "Unbind" : dbg_entry_state == 2 ?
1660 "BIND" : dbg_entry_state == 3 ?
1661 "FIN" : "Unknown", cnt);
1662
1663 return 0;
1664}
1665
developer471f6562021-05-10 20:48:34 +08001666int hnat_entry_read(struct seq_file *m, void *private)
1667{
1668 int i;
1669
1670 for (i = 0; i < CFG_PPE_NUM; i++)
1671 __hnat_entry_read(m, private, i);
1672
1673 return 0;
1674}
1675
developerfd40db22021-04-29 10:08:25 +08001676ssize_t hnat_entry_write(struct file *file, const char __user *buffer,
1677 size_t count, loff_t *data)
1678{
1679 char buf[32];
1680 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001681 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001682 long arg0 = 0, arg1 = 0;
1683 char *p_token = NULL;
1684 char *p_delimiter = " \t";
1685 int ret;
1686
1687 if (len >= sizeof(buf)) {
1688 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001689 return -1;
1690 }
1691
1692 if (copy_from_user(buf, buffer, len))
1693 return -EFAULT;
1694
1695 buf[len] = '\0';
1696
1697 p_buf = buf;
1698 p_token = strsep(&p_buf, p_delimiter);
1699 if (!p_token)
1700 arg0 = 0;
1701 else
1702 ret = kstrtol(p_token, 10, &arg0);
1703
1704 switch (arg0) {
1705 case 0:
1706 case 1:
1707 case 2:
1708 case 3:
developer471f6562021-05-10 20:48:34 +08001709 case 4:
1710 case 5:
developerfd40db22021-04-29 10:08:25 +08001711 p_token = strsep(&p_buf, p_delimiter);
1712 if (!p_token)
1713 arg1 = 0;
1714 else
1715 ret = kstrtol(p_token, 10, &arg1);
1716 break;
1717 default:
1718 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1719 arg0 = 0;
1720 arg1 = 0;
1721 break;
1722 }
1723
1724 (*entry_set_func[arg0])(arg1);
1725
1726 return len;
1727}
1728
1729static int hnat_entry_open(struct inode *inode, struct file *file)
1730{
1731 return single_open(file, hnat_entry_read, file->private_data);
1732}
1733
1734static const struct file_operations hnat_entry_fops = {
1735 .open = hnat_entry_open,
1736 .read = seq_read,
1737 .llseek = seq_lseek,
1738 .write = hnat_entry_write,
1739 .release = single_release,
1740};
1741
developer4c32b7a2021-11-13 16:46:43 +08001742int __hnat_setting_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001743{
1744 struct mtk_hnat *h = hnat_priv;
1745 int i;
1746 int cr_max;
1747
developer4c32b7a2021-11-13 16:46:43 +08001748 if (ppe_id >= CFG_PPE_NUM)
1749 return -EINVAL;
1750
developerfd40db22021-04-29 10:08:25 +08001751 cr_max = 319 * 4;
1752 for (i = 0; i < cr_max; i = i + 0x10) {
1753 pr_info("0x%p : 0x%08x 0x%08x 0x%08x 0x%08x\n",
developer471f6562021-05-10 20:48:34 +08001754 (void *)h->foe_table_dev[ppe_id] + i,
1755 readl(h->ppe_base[ppe_id] + i),
1756 readl(h->ppe_base[ppe_id] + i + 4),
1757 readl(h->ppe_base[ppe_id] + i + 8),
1758 readl(h->ppe_base[ppe_id] + i + 0xc));
developerfd40db22021-04-29 10:08:25 +08001759 }
1760
1761 return 0;
1762}
1763
developer471f6562021-05-10 20:48:34 +08001764int hnat_setting_read(struct seq_file *m, void *private)
1765{
1766 int i;
1767
1768 for (i = 0; i < CFG_PPE_NUM; i++)
1769 __hnat_setting_read(m, private, i);
1770
1771 return 0;
1772}
1773
developerfd40db22021-04-29 10:08:25 +08001774static int hnat_setting_open(struct inode *inode, struct file *file)
1775{
1776 return single_open(file, hnat_setting_read, file->private_data);
1777}
1778
1779ssize_t hnat_setting_write(struct file *file, const char __user *buffer,
1780 size_t count, loff_t *data)
1781{
1782 char buf[32];
1783 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001784 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001785 long arg0 = 0, arg1 = 0;
1786 char *p_token = NULL;
1787 char *p_delimiter = " \t";
1788 int ret;
1789
1790 if (len >= sizeof(buf)) {
1791 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001792 return -1;
1793 }
1794
1795 if (copy_from_user(buf, buffer, len))
1796 return -EFAULT;
1797
1798 buf[len] = '\0';
1799
1800 p_buf = buf;
1801 p_token = strsep(&p_buf, p_delimiter);
1802 if (!p_token)
1803 arg0 = 0;
1804 else
1805 ret = kstrtol(p_token, 10, &arg0);
1806
1807 switch (arg0) {
1808 case 0:
1809 case 1:
1810 case 2:
1811 case 3:
1812 case 4:
1813 case 5:
1814 case 6:
developer30a47682021-11-02 17:06:14 +08001815 case 7:
developerfd40db22021-04-29 10:08:25 +08001816 p_token = strsep(&p_buf, p_delimiter);
1817 if (!p_token)
1818 arg1 = 0;
1819 else
1820 ret = kstrtol(p_token, 10, &arg1);
1821 break;
1822 default:
1823 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1824 arg0 = 0;
1825 arg1 = 0;
1826 break;
1827 }
1828
1829 (*cr_set_func[arg0])(arg1);
1830
1831 return len;
1832}
1833
1834static const struct file_operations hnat_setting_fops = {
1835 .open = hnat_setting_open,
1836 .read = seq_read,
1837 .llseek = seq_lseek,
1838 .write = hnat_setting_write,
1839 .release = single_release,
1840};
1841
developer4c32b7a2021-11-13 16:46:43 +08001842int __mcast_table_dump(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001843{
1844 struct mtk_hnat *h = hnat_priv;
1845 struct ppe_mcast_h mcast_h;
1846 struct ppe_mcast_l mcast_l;
1847 u8 i, max;
1848 void __iomem *reg;
1849
developer4c32b7a2021-11-13 16:46:43 +08001850 if (ppe_id >= CFG_PPE_NUM)
1851 return -EINVAL;
1852
developerfd40db22021-04-29 10:08:25 +08001853 if (!h->pmcast)
1854 return 0;
1855
1856 max = h->pmcast->max_entry;
developer471f6562021-05-10 20:48:34 +08001857 pr_info("============================\n");
1858 pr_info("PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001859 pr_info("MAC | VID | PortMask | QosPortMask\n");
1860 for (i = 0; i < max; i++) {
1861 if (i < 0x10) {
developer471f6562021-05-10 20:48:34 +08001862 reg = h->ppe_base[ppe_id] + PPE_MCAST_H_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001863 mcast_h.u.value = readl(reg);
developer471f6562021-05-10 20:48:34 +08001864 reg = h->ppe_base[ppe_id] + PPE_MCAST_L_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001865 mcast_l.addr = readl(reg);
1866 } else {
1867 reg = h->fe_base + PPE_MCAST_H_10 + (i - 0x10) * 8;
1868 mcast_h.u.value = readl(reg);
1869 reg = h->fe_base + PPE_MCAST_L_10 + (i - 0x10) * 8;
1870 mcast_l.addr = readl(reg);
1871 }
1872 pr_info("%08x %d %c%c%c%c %c%c%c%c (QID=%d, mc_mpre_sel=%d)\n",
1873 mcast_l.addr,
1874 mcast_h.u.info.mc_vid,
1875 (mcast_h.u.info.mc_px_en & 0x08) ? '1' : '-',
1876 (mcast_h.u.info.mc_px_en & 0x04) ? '1' : '-',
1877 (mcast_h.u.info.mc_px_en & 0x02) ? '1' : '-',
1878 (mcast_h.u.info.mc_px_en & 0x01) ? '1' : '-',
1879 (mcast_h.u.info.mc_px_qos_en & 0x08) ? '1' : '-',
1880 (mcast_h.u.info.mc_px_qos_en & 0x04) ? '1' : '-',
1881 (mcast_h.u.info.mc_px_qos_en & 0x02) ? '1' : '-',
1882 (mcast_h.u.info.mc_px_qos_en & 0x01) ? '1' : '-',
1883 mcast_h.u.info.mc_qos_qid +
1884 ((mcast_h.u.info.mc_qos_qid54) << 4),
1885 mcast_h.u.info.mc_mpre_sel);
1886 }
1887
1888 return 0;
1889}
1890
developer471f6562021-05-10 20:48:34 +08001891int mcast_table_dump(struct seq_file *m, void *private)
1892{
1893 int i;
1894
1895 for (i = 0; i < CFG_PPE_NUM; i++)
1896 __mcast_table_dump(m, private, i);
1897
1898 return 0;
1899}
1900
developerfd40db22021-04-29 10:08:25 +08001901static int mcast_table_open(struct inode *inode, struct file *file)
1902{
1903 return single_open(file, mcast_table_dump, file->private_data);
1904}
1905
1906static const struct file_operations hnat_mcast_fops = {
1907 .open = mcast_table_open,
1908 .read = seq_read,
1909 .llseek = seq_lseek,
1910 .release = single_release,
1911};
1912
1913static int hnat_ext_show(struct seq_file *m, void *private)
1914{
1915 int i;
1916 struct extdev_entry *ext_entry;
1917
1918 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
1919 ext_entry = hnat_priv->ext_if[i];
1920 if (ext_entry->dev)
1921 seq_printf(m, "ext devices [%d] = %s (dev=%p, ifindex=%d)\n",
1922 i, ext_entry->name, ext_entry->dev,
1923 ext_entry->dev->ifindex);
1924 }
1925
1926 return 0;
1927}
1928
1929static int hnat_ext_open(struct inode *inode, struct file *file)
1930{
1931 return single_open(file, hnat_ext_show, file->private_data);
1932}
1933
1934static const struct file_operations hnat_ext_fops = {
1935 .open = hnat_ext_open,
1936 .read = seq_read,
1937 .llseek = seq_lseek,
1938 .release = single_release,
1939};
1940
1941static ssize_t hnat_sched_show(struct file *file, char __user *user_buf,
1942 size_t count, loff_t *ppos)
1943{
1944 long id = (long)file->private_data;
1945 struct mtk_hnat *h = hnat_priv;
1946 u32 qdma_tx_sch;
1947 int enable;
1948 int scheduling;
1949 int max_rate;
1950 char *buf;
1951 unsigned int len = 0, buf_len = 1500;
1952 ssize_t ret_cnt;
1953 int scheduler, i;
1954 u32 sch_reg;
1955
1956 buf = kzalloc(buf_len, GFP_KERNEL);
1957 if (!buf)
1958 return -ENOMEM;
1959
1960 if (hnat_priv->data->num_of_sch == 4)
1961 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
1962 else
1963 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
1964
1965 if (id & 0x1)
1966 qdma_tx_sch >>= 16;
1967 qdma_tx_sch &= 0xffff;
1968 enable = !!(qdma_tx_sch & BIT(11));
1969 scheduling = !!(qdma_tx_sch & BIT(15));
1970 max_rate = ((qdma_tx_sch >> 4) & 0x7f);
1971 qdma_tx_sch &= 0xf;
1972 while (qdma_tx_sch--)
1973 max_rate *= 10;
1974
1975 len += scnprintf(buf + len, buf_len - len,
1976 "EN\tScheduling\tMAX\tQueue#\n%d\t%s%16d\t", enable,
1977 (scheduling == 1) ? "WRR" : "SP", max_rate);
1978
1979 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
1980 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE,
1981 (i / NUM_OF_Q_PER_PAGE));
1982 sch_reg = readl(h->fe_base + QTX_SCH(i % NUM_OF_Q_PER_PAGE));
1983 if (hnat_priv->data->num_of_sch == 4)
1984 scheduler = (sch_reg >> 30) & 0x3;
1985 else
1986 scheduler = !!(sch_reg & BIT(31));
1987 if (id == scheduler)
1988 len += scnprintf(buf + len, buf_len - len, "%d ", i);
1989 }
1990
1991 len += scnprintf(buf + len, buf_len - len, "\n");
1992 if (len > buf_len)
1993 len = buf_len;
1994
1995 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1996
1997 kfree(buf);
1998 return ret_cnt;
1999}
2000
2001static ssize_t hnat_sched_write(struct file *file, const char __user *buf,
2002 size_t length, loff_t *offset)
2003{
2004 long id = (long)file->private_data;
2005 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002006 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002007 int enable, rate, exp = 0, shift = 0;
2008 char scheduling[32];
2009 size_t size;
2010 u32 qdma_tx_sch;
2011 u32 val = 0;
2012
developerc316c852021-07-09 11:23:40 +08002013 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002014 return -EINVAL;
2015
2016 if (copy_from_user(line, buf, length))
2017 return -EFAULT;
2018
developer659fdeb2022-12-01 23:03:07 +08002019 if (sscanf(line, "%1d %3s %9d", &enable, scheduling, &rate) != 3)
developerfd40db22021-04-29 10:08:25 +08002020 return -EFAULT;
2021
developer659fdeb2022-12-01 23:03:07 +08002022#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2023 if (rate > 100000000 || rate < 0 ||
2024 rate > 100000000 || rate < 0)
2025#else
2026 if (rate > 10000000 || rate < 0 ||
2027 rate > 10000000 || rate < 0)
2028#endif
2029 return -EINVAL;
2030
developerfd40db22021-04-29 10:08:25 +08002031 while (rate > 127) {
2032 rate /= 10;
2033 exp++;
2034 }
2035
developerc316c852021-07-09 11:23:40 +08002036 line[length] = '\0';
2037
developerfd40db22021-04-29 10:08:25 +08002038 if (enable)
2039 val |= BIT(11);
2040 if (strcmp(scheduling, "sp") != 0)
2041 val |= BIT(15);
2042 val |= (rate & 0x7f) << 4;
2043 val |= exp & 0xf;
2044 if (id & 0x1)
2045 shift = 16;
2046
2047 if (hnat_priv->data->num_of_sch == 4)
2048 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
2049 else
2050 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
2051
2052 qdma_tx_sch &= ~(0xffff << shift);
2053 qdma_tx_sch |= val << shift;
2054 if (hnat_priv->data->num_of_sch == 4)
2055 writel(qdma_tx_sch, h->fe_base + QDMA_TX_4SCH_BASE(id));
2056 else
2057 writel(qdma_tx_sch, h->fe_base + QDMA_TX_2SCH_BASE);
2058
2059 size = strlen(line);
2060 *offset += size;
2061
2062 return length;
2063}
2064
2065static const struct file_operations hnat_sched_fops = {
2066 .open = simple_open,
2067 .read = hnat_sched_show,
2068 .write = hnat_sched_write,
2069 .llseek = default_llseek,
2070};
2071
2072static ssize_t hnat_queue_show(struct file *file, char __user *user_buf,
2073 size_t count, loff_t *ppos)
2074{
2075 struct mtk_hnat *h = hnat_priv;
2076 long id = (long)file->private_data;
2077 u32 qtx_sch;
2078 u32 qtx_cfg;
2079 int scheduler;
2080 int min_rate_en;
2081 int min_rate;
2082 int min_rate_exp;
2083 int max_rate_en;
2084 int max_weight;
2085 int max_rate;
2086 int max_rate_exp;
2087 char *buf;
2088 unsigned int len = 0, buf_len = 1500;
2089 ssize_t ret_cnt;
2090
2091 buf = kzalloc(buf_len, GFP_KERNEL);
2092 if (!buf)
2093 return -ENOMEM;
2094
2095 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
2096 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2097 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2098 if (hnat_priv->data->num_of_sch == 4)
2099 scheduler = (qtx_sch >> 30) & 0x3;
2100 else
2101 scheduler = !!(qtx_sch & BIT(31));
2102 min_rate_en = !!(qtx_sch & BIT(27));
2103 min_rate = (qtx_sch >> 20) & 0x7f;
2104 min_rate_exp = (qtx_sch >> 16) & 0xf;
2105 max_rate_en = !!(qtx_sch & BIT(11));
2106 max_weight = (qtx_sch >> 12) & 0xf;
2107 max_rate = (qtx_sch >> 4) & 0x7f;
2108 max_rate_exp = qtx_sch & 0xf;
2109 while (min_rate_exp--)
2110 min_rate *= 10;
2111
2112 while (max_rate_exp--)
2113 max_rate *= 10;
2114
2115 len += scnprintf(buf + len, buf_len - len,
2116 "scheduler: %d\nhw resv: %d\nsw resv: %d\n", scheduler,
2117 (qtx_cfg >> 8) & 0xff, qtx_cfg & 0xff);
2118
developer4164cfe2022-12-01 11:27:41 +08002119 if (hnat_priv->data->version != MTK_HNAT_V1_1) {
developerfd40db22021-04-29 10:08:25 +08002120 /* Switch to debug mode */
2121 cr_set_field(h->fe_base + QTX_MIB_IF, MIB_ON_QTX_CFG, 1);
2122 cr_set_field(h->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 1);
2123 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2124 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2125 len += scnprintf(buf + len, buf_len - len,
2126 "packet count: %u\n", qtx_cfg);
2127 len += scnprintf(buf + len, buf_len - len,
2128 "packet drop: %u\n\n", qtx_sch);
2129
2130 /* Recover to normal mode */
2131 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF,
2132 MIB_ON_QTX_CFG, 0);
2133 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 0);
2134 }
2135
2136 len += scnprintf(buf + len, buf_len - len,
2137 " EN RATE WEIGHT\n");
2138 len += scnprintf(buf + len, buf_len - len,
2139 "----------------------------\n");
2140 len += scnprintf(buf + len, buf_len - len,
2141 "max%5d%9d%9d\n", max_rate_en, max_rate, max_weight);
2142 len += scnprintf(buf + len, buf_len - len,
2143 "min%5d%9d -\n", min_rate_en, min_rate);
2144
2145 if (len > buf_len)
2146 len = buf_len;
2147
2148 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2149
2150 kfree(buf);
2151 return ret_cnt;
2152}
2153
2154static ssize_t hnat_queue_write(struct file *file, const char __user *buf,
2155 size_t length, loff_t *offset)
2156{
2157 long id = (long)file->private_data;
2158 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002159 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002160 int max_enable, max_rate, max_exp = 0;
2161 int min_enable, min_rate, min_exp = 0;
2162 int weight;
2163 int resv;
2164 int scheduler;
2165 size_t size;
developer04f0ec82021-12-30 13:59:10 +08002166 u32 qtx_sch = 0;
developerfd40db22021-04-29 10:08:25 +08002167
2168 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
developerc316c852021-07-09 11:23:40 +08002169 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002170 return -EINVAL;
2171
2172 if (copy_from_user(line, buf, length))
2173 return -EFAULT;
2174
2175 if (sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate,
2176 &max_enable, &max_rate, &weight, &resv) != 7)
2177 return -EFAULT;
2178
developerc316c852021-07-09 11:23:40 +08002179 line[length] = '\0';
2180
developer577ad2f2022-11-28 10:33:36 +08002181#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2182 if (max_rate > 100000000 || max_rate < 0 ||
2183 min_rate > 100000000 || min_rate < 0)
2184#else
2185 if (max_rate > 10000000 || max_rate < 0 ||
2186 min_rate > 10000000 || min_rate < 0)
2187#endif
2188 return -EINVAL;
2189
developerfd40db22021-04-29 10:08:25 +08002190 while (max_rate > 127) {
2191 max_rate /= 10;
2192 max_exp++;
2193 }
2194
2195 while (min_rate > 127) {
2196 min_rate /= 10;
2197 min_exp++;
2198 }
2199
developerfd40db22021-04-29 10:08:25 +08002200 if (hnat_priv->data->num_of_sch == 4)
2201 qtx_sch |= (scheduler & 0x3) << 30;
2202 else
2203 qtx_sch |= (scheduler & 0x1) << 31;
2204 if (min_enable)
2205 qtx_sch |= BIT(27);
2206 qtx_sch |= (min_rate & 0x7f) << 20;
2207 qtx_sch |= (min_exp & 0xf) << 16;
2208 if (max_enable)
2209 qtx_sch |= BIT(11);
2210 qtx_sch |= (weight & 0xf) << 12;
2211 qtx_sch |= (max_rate & 0x7f) << 4;
2212 qtx_sch |= max_exp & 0xf;
2213 writel(qtx_sch, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2214
2215 resv &= 0xff;
2216 qtx_sch = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2217 qtx_sch &= 0xffff0000;
2218 qtx_sch |= (resv << 8) | resv;
2219 writel(qtx_sch, h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2220
2221 size = strlen(line);
2222 *offset += size;
2223
2224 return length;
2225}
2226
2227static const struct file_operations hnat_queue_fops = {
2228 .open = simple_open,
2229 .read = hnat_queue_show,
2230 .write = hnat_queue_write,
2231 .llseek = default_llseek,
2232};
2233
2234static ssize_t hnat_ppd_if_write(struct file *file, const char __user *buffer,
2235 size_t count, loff_t *data)
2236{
2237 char buf[IFNAMSIZ];
2238 struct net_device *dev;
2239 char *p, *tmp;
2240
2241 if (count >= IFNAMSIZ)
2242 return -EFAULT;
2243
2244 memset(buf, 0, IFNAMSIZ);
2245 if (copy_from_user(buf, buffer, count))
2246 return -EFAULT;
2247
2248 tmp = buf;
2249 p = strsep(&tmp, "\n\r ");
2250 dev = dev_get_by_name(&init_net, p);
2251
2252 if (dev) {
2253 if (hnat_priv->g_ppdev)
2254 dev_put(hnat_priv->g_ppdev);
2255 hnat_priv->g_ppdev = dev;
2256
developer4c32b7a2021-11-13 16:46:43 +08002257 strncpy(hnat_priv->ppd, p, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +08002258 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2259 } else {
2260 pr_info("no such device!\n");
2261 }
2262
2263 return count;
2264}
2265
2266static int hnat_ppd_if_read(struct seq_file *m, void *private)
2267{
2268 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2269
2270 if (hnat_priv->g_ppdev) {
2271 pr_info("hnat_priv g_ppdev name = %s\n",
2272 hnat_priv->g_ppdev->name);
2273 } else {
2274 pr_info("hnat_priv g_ppdev is null!\n");
2275 }
2276
2277 return 0;
2278}
2279
2280static int hnat_ppd_if_open(struct inode *inode, struct file *file)
2281{
2282 return single_open(file, hnat_ppd_if_read, file->private_data);
2283}
2284
2285static const struct file_operations hnat_ppd_if_fops = {
2286 .open = hnat_ppd_if_open,
2287 .read = seq_read,
2288 .llseek = seq_lseek,
2289 .write = hnat_ppd_if_write,
2290 .release = single_release,
2291};
2292
2293static int hnat_mape_toggle_read(struct seq_file *m, void *private)
2294{
2295 pr_info("value=%d, %s is enabled now!\n", mape_toggle, (mape_toggle) ? "mape" : "ds-lite");
2296
2297 return 0;
2298}
2299
2300static int hnat_mape_toggle_open(struct inode *inode, struct file *file)
2301{
2302 return single_open(file, hnat_mape_toggle_read, file->private_data);
2303}
2304
2305static ssize_t hnat_mape_toggle_write(struct file *file, const char __user *buffer,
2306 size_t count, loff_t *data)
2307{
developer4c32b7a2021-11-13 16:46:43 +08002308 char buf = 0;
developer25fc8c02022-05-06 16:24:02 +08002309 int i;
2310 u32 ppe_cfg;
2311
2312 if ((count < 1) || copy_from_user(&buf, buffer, sizeof(buf)))
developerfd40db22021-04-29 10:08:25 +08002313 return -EFAULT;
2314
developer25fc8c02022-05-06 16:24:02 +08002315 if (buf == '1') {
developerfd40db22021-04-29 10:08:25 +08002316 pr_info("mape is going to be enabled, ds-lite is going to be disabled !\n");
2317 mape_toggle = 1;
developer25fc8c02022-05-06 16:24:02 +08002318 } else if (buf == '0') {
developerfd40db22021-04-29 10:08:25 +08002319 pr_info("ds-lite is going to be enabled, mape is going to be disabled !\n");
2320 mape_toggle = 0;
developer25fc8c02022-05-06 16:24:02 +08002321 } else {
2322 pr_info("Invalid parameter.\n");
2323 return -EFAULT;
2324 }
2325
2326 for (i = 0; i < CFG_PPE_NUM; i++) {
2327 ppe_cfg = readl(hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
2328
2329 if (mape_toggle)
2330 ppe_cfg &= ~BIT_IPV4_DSL_EN;
2331 else
2332 ppe_cfg |= BIT_IPV4_DSL_EN;
2333
2334 writel(ppe_cfg, hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
developerfd40db22021-04-29 10:08:25 +08002335 }
2336
developer25fc8c02022-05-06 16:24:02 +08002337 return count;
developerfd40db22021-04-29 10:08:25 +08002338}
2339
2340static const struct file_operations hnat_mape_toggle_fops = {
2341 .open = hnat_mape_toggle_open,
2342 .read = seq_read,
2343 .llseek = seq_lseek,
2344 .write = hnat_mape_toggle_write,
2345 .release = single_release,
2346};
2347
2348static int hnat_hook_toggle_read(struct seq_file *m, void *private)
2349{
2350 pr_info("value=%d, hook is %s now!\n", hook_toggle, (hook_toggle) ? "enabled" : "disabled");
2351
2352 return 0;
2353}
2354
2355static int hnat_hook_toggle_open(struct inode *inode, struct file *file)
2356{
2357 return single_open(file, hnat_hook_toggle_read, file->private_data);
2358}
2359
2360static ssize_t hnat_hook_toggle_write(struct file *file, const char __user *buffer,
2361 size_t count, loff_t *data)
2362{
developer4c32b7a2021-11-13 16:46:43 +08002363 char buf[8] = {0};
developerfd40db22021-04-29 10:08:25 +08002364 int len = count;
developer70cdf6e2021-12-07 18:58:35 +08002365 u32 id;
developerfd40db22021-04-29 10:08:25 +08002366
2367 if ((len > 8) || copy_from_user(buf, buffer, len))
2368 return -EFAULT;
2369
2370 if (buf[0] == '1' && !hook_toggle) {
2371 pr_info("hook is going to be enabled !\n");
2372 hnat_enable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002373
2374 if (IS_PPPQ_MODE) {
2375 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2376 hnat_qos_shaper_ebl(id, 1);
2377 }
developerfd40db22021-04-29 10:08:25 +08002378 } else if (buf[0] == '0' && hook_toggle) {
2379 pr_info("hook is going to be disabled !\n");
2380 hnat_disable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002381
2382 if (IS_PPPQ_MODE) {
2383 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2384 hnat_qos_shaper_ebl(id, 0);
2385 }
developerfd40db22021-04-29 10:08:25 +08002386 }
2387
2388 return len;
2389}
2390
2391static const struct file_operations hnat_hook_toggle_fops = {
2392 .open = hnat_hook_toggle_open,
2393 .read = seq_read,
2394 .llseek = seq_lseek,
2395 .write = hnat_hook_toggle_write,
2396 .release = single_release,
2397};
2398
developer47545a32022-11-15 16:06:58 +08002399static void hnat_qos_toggle_usage(void)
2400{
2401 pr_info("\nHQoS toggle Command Usage:\n");
2402 pr_info("Show HQoS mode:\n");
2403 pr_info(" cat /sys/kernel/debug/hnat/qos_toggle\n");
2404 pr_info("Disable HQoS mode:\n");
2405 pr_info(" echo 0 > /sys/kernel/debug/hnat/qos_toggle\n");
2406 pr_info("Enable HQoS on bidirection:\n");
2407 pr_info(" echo 1 > /sys/kernel/debug/hnat/qos_toggle\n");
2408 pr_info("Enable HQoS on uplink only:\n");
2409 pr_info(" echo 1 uplink > /sys/kernel/debug/hnat/qos_toggle\n");
2410 pr_info("Enable HQoS on downlink only:\n");
2411 pr_info(" echo 1 downlink > /sys/kernel/debug/hnat/qos_toggle\n");
2412 pr_info("Enable Per-port-per-queue mode:\n");
2413 pr_info(" echo 2 > /sys/kernel/debug/hnat/qos_toggle\n");
2414 pr_info("Show HQoS toggle usage:\n");
2415 pr_info(" echo 3 > /sys/kernel/debug/hnat/qos_toggle\n\n");
2416}
2417
developeraf07fad2021-11-19 17:53:42 +08002418static int hnat_qos_toggle_read(struct seq_file *m, void *private)
2419{
developer47545a32022-11-15 16:06:58 +08002420 if (qos_toggle == 0) {
2421 pr_info("HQoS is disabled now!\n");
2422 } else if (qos_toggle == 1) {
2423 pr_info("HQoS is enabled now!\n");
2424 pr_info("HQoS uplink is %s now!\n",
2425 qos_ul_toggle ? "enabled" : "disabled");
2426 pr_info("HQoS downlink is %s now!\n",
2427 qos_dl_toggle ? "enabled" : "disabled");
2428 } else if (qos_toggle == 2) {
2429 pr_info("Per-port-per-queue mode is enabled!\n");
2430 }
developeraf07fad2021-11-19 17:53:42 +08002431
2432 return 0;
2433}
2434
2435static int hnat_qos_toggle_open(struct inode *inode, struct file *file)
2436{
2437 return single_open(file, hnat_qos_toggle_read, file->private_data);
2438}
2439
developer70cdf6e2021-12-07 18:58:35 +08002440void hnat_qos_shaper_ebl(u32 id, u32 enable)
2441{
2442 struct mtk_hnat *h = hnat_priv;
2443 u32 cfg;
2444
2445 if (enable) {
2446 cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
2447 cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
2448 (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
2449 (25 << QTX_SCH_MAX_RATE_MAN_OFFSET) |
2450 (5 << QTX_SCH_MAX_RATE_EXP_OFFSET) |
2451 (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
2452
2453 writel(cfg, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2454 } else {
2455 writel(0, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2456 }
2457}
2458
2459static void hnat_qos_disable(void)
2460{
2461 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002462 u32 id, cfg;
developer70cdf6e2021-12-07 18:58:35 +08002463
2464 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2465 hnat_qos_shaper_ebl(id, 0);
developer34028fb2022-01-11 13:51:29 +08002466 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2467 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2468 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
developer70cdf6e2021-12-07 18:58:35 +08002469 }
2470
developer34028fb2022-01-11 13:51:29 +08002471 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002472 for (id = 0; id < h->data->num_of_sch; id += 2) {
2473 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002474 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002475 else
developer34028fb2022-01-11 13:51:29 +08002476 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer70cdf6e2021-12-07 18:58:35 +08002477 }
2478}
2479
developer24948202021-11-24 17:38:27 +08002480static void hnat_qos_pppq_enable(void)
2481{
developer70cdf6e2021-12-07 18:58:35 +08002482 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002483 u32 id, cfg;
developer24948202021-11-24 17:38:27 +08002484
developer70cdf6e2021-12-07 18:58:35 +08002485 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2486 if (hook_toggle)
2487 hnat_qos_shaper_ebl(id, 1);
2488 else
2489 hnat_qos_shaper_ebl(id, 0);
developer24948202021-11-24 17:38:27 +08002490
developer70cdf6e2021-12-07 18:58:35 +08002491 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2492 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2493 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2494 }
developer24948202021-11-24 17:38:27 +08002495
developer34028fb2022-01-11 13:51:29 +08002496 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002497 for (id = 0; id < h->data->num_of_sch; id+= 2) {
2498 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002499 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002500 else
developer34028fb2022-01-11 13:51:29 +08002501 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer24948202021-11-24 17:38:27 +08002502 }
2503}
2504
developeraf07fad2021-11-19 17:53:42 +08002505static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffer,
2506 size_t count, loff_t *data)
2507{
developer577ad2f2022-11-28 10:33:36 +08002508 char buf[32] = {0}, tmp[32];
developeraf07fad2021-11-19 17:53:42 +08002509 int len = count;
developer47545a32022-11-15 16:06:58 +08002510 char *p_buf = NULL, *p_token = NULL;
developeraf07fad2021-11-19 17:53:42 +08002511
developer47545a32022-11-15 16:06:58 +08002512 if (len >= sizeof(buf))
2513 return -EFAULT;
2514
2515 if (copy_from_user(buf, buffer, len))
developeraf07fad2021-11-19 17:53:42 +08002516 return -EFAULT;
2517
developer47545a32022-11-15 16:06:58 +08002518 buf[len] = '\0';
2519
developer24948202021-11-24 17:38:27 +08002520 if (buf[0] == '0') {
developer47545a32022-11-15 16:06:58 +08002521 pr_info("HQoS is going to be disabled!\n");
developeraf07fad2021-11-19 17:53:42 +08002522 qos_toggle = 0;
developer47545a32022-11-15 16:06:58 +08002523 qos_dl_toggle = 0;
2524 qos_ul_toggle = 0;
developer70cdf6e2021-12-07 18:58:35 +08002525 hnat_qos_disable();
developer24948202021-11-24 17:38:27 +08002526 } else if (buf[0] == '1') {
developer47545a32022-11-15 16:06:58 +08002527 p_buf = buf;
2528 p_token = strsep(&p_buf, " \t");
2529 if (p_buf) {
2530 memcpy(tmp, p_buf, strlen(p_buf));
2531 tmp[len] = '\0';
2532 if (!strncmp(tmp, "uplink", 6)) {
2533 qos_dl_toggle = 0;
2534 qos_ul_toggle = 1;
2535 } else if (!strncmp(tmp, "downlink", 8)) {
2536 qos_ul_toggle = 0;
2537 qos_dl_toggle = 1;
2538 } else {
2539 pr_info("Direction should be uplink or downlink.\n");
2540 hnat_qos_toggle_usage();
2541 return len;
2542 }
2543 } else {
2544 qos_ul_toggle = 1;
2545 qos_dl_toggle = 1;
2546 }
2547 pr_info("HQoS mode is going to be enabled!\n");
2548 pr_info("HQoS uplink is going to be %s!\n",
2549 qos_ul_toggle ? "enabled" : "disabled");
2550 pr_info("HQoS downlink is going to be %s!\n",
2551 qos_dl_toggle ? "enabled" : "disabled");
developeraf07fad2021-11-19 17:53:42 +08002552 qos_toggle = 1;
developer24948202021-11-24 17:38:27 +08002553 } else if (buf[0] == '2') {
developer47545a32022-11-15 16:06:58 +08002554 pr_info("Per-port-per-queue mode is going to be enabled!\n");
developerafff5662022-06-29 10:09:56 +08002555 pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
developeraf07fad2021-11-19 17:53:42 +08002556 qos_toggle = 2;
developer934756a2022-11-18 14:51:34 +08002557 qos_dl_toggle = 1;
2558 qos_ul_toggle = 1;
developer24948202021-11-24 17:38:27 +08002559 hnat_qos_pppq_enable();
developer47545a32022-11-15 16:06:58 +08002560 } else if (buf[0] == '3') {
2561 hnat_qos_toggle_usage();
2562 } else {
2563 pr_info("Input error!\n");
2564 hnat_qos_toggle_usage();
developeraf07fad2021-11-19 17:53:42 +08002565 }
2566
2567 return len;
2568}
2569
2570static const struct file_operations hnat_qos_toggle_fops = {
2571 .open = hnat_qos_toggle_open,
2572 .read = seq_read,
2573 .llseek = seq_lseek,
2574 .write = hnat_qos_toggle_write,
2575 .release = single_release,
2576};
2577
developerfd40db22021-04-29 10:08:25 +08002578static int hnat_version_read(struct seq_file *m, void *private)
2579{
2580 pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
2581
2582 return 0;
2583}
2584
2585static int hnat_version_open(struct inode *inode, struct file *file)
2586{
2587 return single_open(file, hnat_version_read, file->private_data);
2588}
2589
2590static const struct file_operations hnat_version_fops = {
2591 .open = hnat_version_open,
2592 .read = seq_read,
2593 .llseek = seq_lseek,
2594 .release = single_release,
2595};
2596
developeraeafc442022-10-14 09:10:50 +08002597static u32 hnat_get_ppe_hash(u32 sip, u32 dip, u32 sport, u32 dport)
2598{
2599 u32 hv1 = sport << 16 | dport;
2600 u32 hv2 = dip;
2601 u32 hv3 = sip;
2602 u32 hash;
2603
2604 hash = (hv1 & hv2) | ((~hv1) & hv3);
2605 hash = (hash >> 24) | ((hash & 0xffffff) << 8);
2606 hash ^= hv1 ^ hv2 ^ hv3;
2607 hash ^= hash >> 16;
2608 hash <<= 2;
2609 hash &= hnat_priv->foe_etry_num - 1;
2610
2611 return hash;
2612}
2613
2614static u32 hnat_char2hex(const char c)
2615{
2616 switch (c) {
2617 case '0'...'9':
2618 return 0x0 + (c - '0');
2619 case 'a'...'f':
2620 return 0xa + (c - 'a');
2621 case 'A'...'F':
2622 return 0xa + (c - 'A');
2623 default:
2624 pr_info("MAC format error\n");
2625 return 0;
2626 }
2627}
2628
2629static void hnat_parse_mac(char *str, char *mac)
2630{
2631 int i;
2632
2633 for (i = 0; i < ETH_ALEN; i++) {
2634 mac[i] = (hnat_char2hex(str[i * 3]) << 4) +
2635 (hnat_char2hex(str[i * 3 + 1]));
2636 }
2637}
2638
2639static void hnat_static_entry_help(void)
2640{
2641 pr_info("-------------------- Usage --------------------\n");
2642#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2643 pr_info("echo $0 $1 $2 ... $15 > /sys/kernel/debug/hnat/static_entry\n\n");
2644#else
2645 pr_info("echo $0 $1 $2 ... $12 > /sys/kernel/debug/hnat/static_entry\n\n");
2646#endif
2647
2648 pr_info("-------------------- Parameters --------------------\n");
2649 pr_info("$0: HASH OCT\n");
2650 pr_info("$1: INFO1 HEX\n");
2651 pr_info("$2: ING SIPv4 HEX\n");
2652 pr_info("$3: ING DIPv4 HEX\n");
2653 pr_info("$4: ING SP HEX\n");
2654 pr_info("$5: ING DP HEX\n");
2655 pr_info("$6: INFO2 HEX\n");
2656 pr_info("$7: EG SIPv4 HEX\n");
2657 pr_info("$8: EG DIPv4 HEX\n");
2658 pr_info("$9: EG SP HEX\n");
2659 pr_info("$10: EG DP HEX\n");
2660 pr_info("$11: DMAC STR (00:11:22:33:44:55)\n");
2661 pr_info("$12: SMAC STR (00:11:22:33:44:55)\n");
2662#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2663 pr_info("$13: TPORT IDX HEX\n");
2664 pr_info("$14: TOPS ENTRY HEX\n");
2665 pr_info("$15: CDRT IDX HEX\n");
2666#endif
2667}
2668
2669static int hnat_static_entry_read(struct seq_file *m, void *private)
2670{
2671 hnat_static_entry_help();
2672
2673 return 0;
2674}
2675
2676static int hnat_static_entry_open(struct inode *inode, struct file *file)
2677{
2678 return single_open(file, hnat_static_entry_read, file->private_data);
2679}
2680
2681static ssize_t hnat_static_entry_write(struct file *file,
2682 const char __user *buffer,
2683 size_t count, loff_t *data)
2684{
2685 struct foe_entry *foe, entry = { 0 };
2686 char buf[256], dmac_str[18], smac_str[18], dmac[6], smac[6];
2687 int len = count, hash, coll = 0;
2688 u32 ppe_id = 0;
2689#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2690 u32 tport_id, tops_entry, cdrt_id;
2691#endif
2692
2693 if (len >= sizeof(buf) || copy_from_user(buf, buffer, len)) {
2694 pr_info("Input handling fail!\n");
2695 len = sizeof(buf) - 1;
2696 return -EFAULT;
2697 }
2698
2699 buf[len] = '\0';
2700#if defined(CONFIG_MEDIATEK_NETSYS_V3)
developer659fdeb2022-12-01 23:03:07 +08002701 if (sscanf(buf,
2702 "%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s %4x %4x %4x",
developer577ad2f2022-11-28 10:33:36 +08002703 &hash,
2704 &entry.ipv4_hnapt.info_blk1,
2705 &entry.ipv4_hnapt.sip,
2706 &entry.ipv4_hnapt.dip,
2707 &entry.ipv4_hnapt.sport,
2708 &entry.ipv4_hnapt.dport,
2709 &entry.ipv4_hnapt.info_blk2,
2710 &entry.ipv4_hnapt.new_sip,
2711 &entry.ipv4_hnapt.new_dip,
2712 &entry.ipv4_hnapt.new_sport,
2713 &entry.ipv4_hnapt.new_dport,
2714 dmac_str, smac_str, &tport_id, &tops_entry, &cdrt_id) != 16)
2715 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002716
developer659fdeb2022-12-01 23:03:07 +08002717 if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1) ||
2718 (TPORT_ID(tport_id) != tport_id) ||
2719 (TOPS_ENTRY(tops_entry) != tops_entry) ||
2720 (CDRT_ID(cdrt_id) != cdrt_id)) {
developeraeafc442022-10-14 09:10:50 +08002721 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002722 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002723 }
developer659fdeb2022-12-01 23:03:07 +08002724
2725 entry.ipv4_hnapt.tport_id = tport_id;
2726 entry.ipv4_hnapt.tops_entry = tops_entry;
2727 entry.ipv4_hnapt.cdrt_id = cdrt_id;
developeraeafc442022-10-14 09:10:50 +08002728#else
developer659fdeb2022-12-01 23:03:07 +08002729 if (sscanf(buf,
2730 "%5d %8x %8x %8x %hx %hx %8x %8x %8x %hx %hx %18s %18s",
developer577ad2f2022-11-28 10:33:36 +08002731 &hash,
2732 &entry.ipv4_hnapt.info_blk1,
2733 &entry.ipv4_hnapt.sip,
2734 &entry.ipv4_hnapt.dip,
2735 &entry.ipv4_hnapt.sport,
2736 &entry.ipv4_hnapt.dport,
2737 &entry.ipv4_hnapt.info_blk2,
2738 &entry.ipv4_hnapt.new_sip,
2739 &entry.ipv4_hnapt.new_dip,
2740 &entry.ipv4_hnapt.new_sport,
2741 &entry.ipv4_hnapt.new_dport,
2742 dmac_str, smac_str) != 13)
2743 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002744
developer659fdeb2022-12-01 23:03:07 +08002745 if ((hash >= (int)hnat_priv->foe_etry_num) || (hash < -1)) {
developeraeafc442022-10-14 09:10:50 +08002746 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002747 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002748 }
2749#endif
2750
2751 hnat_parse_mac(smac_str, smac);
2752 hnat_parse_mac(dmac_str, dmac);
2753 entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)dmac));
2754 entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&dmac[4]));
2755 entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)smac));
2756 entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&smac[4]));
2757
2758 if (hash == -1) {
2759 hash = hnat_get_ppe_hash(entry.ipv4_hnapt.sip,
2760 entry.ipv4_hnapt.dip,
2761 entry.ipv4_hnapt.sport,
2762 entry.ipv4_hnapt.dport);
2763 }
2764
2765 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
2766 while ((foe->ipv4_hnapt.bfib1.state == BIND) && (coll < 4)) {
2767 hash++;
2768 coll++;
2769 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
2770 };
2771 memcpy(foe, &entry, sizeof(entry));
2772
2773 debug_level = 7;
2774 entry_detail(ppe_id, hash);
2775
2776 return len;
2777}
2778
2779static const struct file_operations hnat_static_fops = {
2780 .open = hnat_static_entry_open,
2781 .read = seq_read,
2782 .llseek = seq_lseek,
2783 .write = hnat_static_entry_write,
2784 .release = single_release,
2785};
2786
developer4c32b7a2021-11-13 16:46:43 +08002787int get_ppe_mib(u32 ppe_id, int index, u64 *pkt_cnt, u64 *byte_cnt)
developerfd40db22021-04-29 10:08:25 +08002788{
2789 struct mtk_hnat *h = hnat_priv;
developer30a47682021-11-02 17:06:14 +08002790 struct hnat_accounting *acct;
developerfd40db22021-04-29 10:08:25 +08002791 struct foe_entry *entry;
2792
developer471f6562021-05-10 20:48:34 +08002793 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08002794 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08002795
developerc6227322021-07-09 10:52:53 +08002796 if (index < 0 || index >= h->foe_etry_num) {
2797 pr_info("Invalid entry index\n");
2798 return -EINVAL;
2799 }
2800
developer30a47682021-11-02 17:06:14 +08002801 acct = hnat_get_count(h, ppe_id, index, NULL);
developer471f6562021-05-10 20:48:34 +08002802 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08002803
developer30a47682021-11-02 17:06:14 +08002804 if (!acct)
developerfd40db22021-04-29 10:08:25 +08002805 return -1;
2806
2807 if (entry->bfib1.state != BIND)
2808 return -1;
2809
developer30a47682021-11-02 17:06:14 +08002810 *pkt_cnt = acct->packets;
2811 *byte_cnt = acct->bytes;
developerfd40db22021-04-29 10:08:25 +08002812
2813 return 0;
2814}
2815EXPORT_SYMBOL(get_ppe_mib);
2816
developer4c32b7a2021-11-13 16:46:43 +08002817int is_entry_binding(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +08002818{
developer580e6fd2021-07-11 09:55:20 +08002819 struct mtk_hnat *h = hnat_priv;
developerfd40db22021-04-29 10:08:25 +08002820 struct foe_entry *entry;
2821
developer471f6562021-05-10 20:48:34 +08002822 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08002823 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08002824
developerc6227322021-07-09 10:52:53 +08002825 if (index < 0 || index >= h->foe_etry_num) {
2826 pr_info("Invalid entry index\n");
2827 return -EINVAL;
2828 }
2829
developer471f6562021-05-10 20:48:34 +08002830 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08002831
2832 return entry->bfib1.state == BIND;
2833}
2834EXPORT_SYMBOL(is_entry_binding);
2835
2836#define dump_register(nm) \
2837 { \
2838 .name = __stringify(nm), .offset = PPE_##nm, \
2839 }
2840
2841static const struct debugfs_reg32 hnat_regs[] = {
2842 dump_register(GLO_CFG), dump_register(FLOW_CFG),
2843 dump_register(IP_PROT_CHK), dump_register(IP_PROT_0),
2844 dump_register(IP_PROT_1), dump_register(IP_PROT_2),
2845 dump_register(IP_PROT_3), dump_register(TB_CFG),
2846 dump_register(TB_BASE), dump_register(TB_USED),
2847 dump_register(BNDR), dump_register(BIND_LMT_0),
2848 dump_register(BIND_LMT_1), dump_register(KA),
2849 dump_register(UNB_AGE), dump_register(BND_AGE_0),
2850 dump_register(BND_AGE_1), dump_register(HASH_SEED),
2851 dump_register(DFT_CPORT), dump_register(MCAST_PPSE),
2852 dump_register(MCAST_L_0), dump_register(MCAST_H_0),
2853 dump_register(MCAST_L_1), dump_register(MCAST_H_1),
2854 dump_register(MCAST_L_2), dump_register(MCAST_H_2),
2855 dump_register(MCAST_L_3), dump_register(MCAST_H_3),
2856 dump_register(MCAST_L_4), dump_register(MCAST_H_4),
2857 dump_register(MCAST_L_5), dump_register(MCAST_H_5),
2858 dump_register(MCAST_L_6), dump_register(MCAST_H_6),
2859 dump_register(MCAST_L_7), dump_register(MCAST_H_7),
2860 dump_register(MCAST_L_8), dump_register(MCAST_H_8),
2861 dump_register(MCAST_L_9), dump_register(MCAST_H_9),
2862 dump_register(MCAST_L_A), dump_register(MCAST_H_A),
2863 dump_register(MCAST_L_B), dump_register(MCAST_H_B),
2864 dump_register(MCAST_L_C), dump_register(MCAST_H_C),
2865 dump_register(MCAST_L_D), dump_register(MCAST_H_D),
2866 dump_register(MCAST_L_E), dump_register(MCAST_H_E),
2867 dump_register(MCAST_L_F), dump_register(MCAST_H_F),
2868 dump_register(MTU_DRP), dump_register(MTU_VLYR_0),
2869 dump_register(MTU_VLYR_1), dump_register(MTU_VLYR_2),
2870 dump_register(VPM_TPID), dump_register(VPM_TPID),
2871 dump_register(CAH_CTRL), dump_register(CAH_TAG_SRH),
2872 dump_register(CAH_LINE_RW), dump_register(CAH_WDATA),
2873 dump_register(CAH_RDATA),
2874};
2875
2876int hnat_init_debugfs(struct mtk_hnat *h)
2877{
2878 int ret = 0;
2879 struct dentry *root;
2880 struct dentry *file;
2881 long i;
2882 char name[16];
2883
2884 root = debugfs_create_dir("hnat", NULL);
2885 if (!root) {
2886 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2887 ret = -ENOMEM;
2888 goto err0;
2889 }
2890 h->root = root;
developerfd40db22021-04-29 10:08:25 +08002891
developer471f6562021-05-10 20:48:34 +08002892 for (i = 0; i < CFG_PPE_NUM; i++) {
2893 h->regset[i] = kzalloc(sizeof(*h->regset[i]), GFP_KERNEL);
2894 if (!h->regset[i]) {
2895 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2896 ret = -ENOMEM;
2897 goto err1;
2898 }
2899 h->regset[i]->regs = hnat_regs;
2900 h->regset[i]->nregs = ARRAY_SIZE(hnat_regs);
2901 h->regset[i]->base = h->ppe_base[i];
2902
developer577ad2f2022-11-28 10:33:36 +08002903 ret = snprintf(name, sizeof(name), "regdump%ld", i);
2904 if (ret != strlen(name)) {
2905 ret = -ENOMEM;
2906 goto err1;
2907 }
developeraeafc442022-10-14 09:10:50 +08002908 file = debugfs_create_regset32(name, 0444,
developer471f6562021-05-10 20:48:34 +08002909 root, h->regset[i]);
2910 if (!file) {
2911 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2912 ret = -ENOMEM;
2913 goto err1;
2914 }
developerfd40db22021-04-29 10:08:25 +08002915 }
developer471f6562021-05-10 20:48:34 +08002916
developeraeafc442022-10-14 09:10:50 +08002917 debugfs_create_file("all_entry", 0444, root, h, &hnat_debug_fops);
2918 debugfs_create_file("external_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002919 &hnat_ext_fops);
developeraeafc442022-10-14 09:10:50 +08002920 debugfs_create_file("whnat_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002921 &hnat_whnat_fops);
developeraeafc442022-10-14 09:10:50 +08002922 debugfs_create_file("cpu_reason", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002923 &cpu_reason_fops);
developeraeafc442022-10-14 09:10:50 +08002924 debugfs_create_file("hnat_entry", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002925 &hnat_entry_fops);
developeraeafc442022-10-14 09:10:50 +08002926 debugfs_create_file("hnat_setting", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002927 &hnat_setting_fops);
developeraeafc442022-10-14 09:10:50 +08002928 debugfs_create_file("mcast_table", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002929 &hnat_mcast_fops);
developeraeafc442022-10-14 09:10:50 +08002930 debugfs_create_file("hook_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002931 &hnat_hook_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002932 debugfs_create_file("mape_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002933 &hnat_mape_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002934 debugfs_create_file("qos_toggle", 0444, root, h,
developeraf07fad2021-11-19 17:53:42 +08002935 &hnat_qos_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002936 debugfs_create_file("hnat_version", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002937 &hnat_version_fops);
developeraeafc442022-10-14 09:10:50 +08002938 debugfs_create_file("hnat_ppd_if", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002939 &hnat_ppd_if_fops);
developeraeafc442022-10-14 09:10:50 +08002940 debugfs_create_file("static_entry", 0444, root, h,
2941 &hnat_static_fops);
developerfd40db22021-04-29 10:08:25 +08002942
2943 for (i = 0; i < hnat_priv->data->num_of_sch; i++) {
developer577ad2f2022-11-28 10:33:36 +08002944 ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
2945 if (ret != strlen(name)) {
2946 ret = -ENOMEM;
2947 goto err1;
2948 }
developeraeafc442022-10-14 09:10:50 +08002949 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08002950 &hnat_sched_fops);
2951 }
2952
2953 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
developer577ad2f2022-11-28 10:33:36 +08002954 ret = snprintf(name, sizeof(name), "qdma_txq%ld", i);
2955 if (ret != strlen(name)) {
2956 ret = -ENOMEM;
2957 goto err1;
2958 }
developeraeafc442022-10-14 09:10:50 +08002959 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08002960 &hnat_queue_fops);
2961 }
2962
2963 return 0;
2964
2965err1:
2966 debugfs_remove_recursive(root);
2967err0:
2968 return ret;
2969}
2970
2971void hnat_deinit_debugfs(struct mtk_hnat *h)
2972{
developer4c32b7a2021-11-13 16:46:43 +08002973 int i;
2974
developerfd40db22021-04-29 10:08:25 +08002975 debugfs_remove_recursive(h->root);
2976 h->root = NULL;
developer4c32b7a2021-11-13 16:46:43 +08002977
2978 for (i = 0; i < CFG_PPE_NUM; i++)
2979 kfree(h->regset[i]);
developerfd40db22021-04-29 10:08:25 +08002980}