blob: dd31560004c94d3d1678f278a91e9656af6e6f53 [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
831 if (hnat_priv->data->version == MTK_HNAT_V5) {
832 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
1301 if (sscanf(line, "%s %d", name, &enable) != 2)
1302 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 }
1316 } else {
1317 pr_info("no such device!\n");
1318 }
1319
1320 size = strlen(line);
1321 *offset += size;
1322
1323 return length;
1324}
1325
1326
developerfd40db22021-04-29 10:08:25 +08001327static const struct file_operations hnat_whnat_fops = {
1328 .open = hnat_whnat_open,
1329 .read = seq_read,
1330 .llseek = seq_lseek,
developerf0345dc2022-03-11 16:53:08 +08001331 .write = hnat_whnat_write,
developerfd40db22021-04-29 10:08:25 +08001332 .release = single_release,
1333};
1334
1335int cpu_reason_read(struct seq_file *m, void *private)
1336{
1337 int i;
1338
1339 pr_info("============ CPU REASON =========\n");
1340 pr_info("(2)IPv4(IPv6) TTL(hop limit) = %u\n", dbg_cpu_reason_cnt[0]);
1341 pr_info("(3)Ipv4(IPv6) has option(extension) header = %u\n",
1342 dbg_cpu_reason_cnt[1]);
1343 pr_info("(7)No flow is assigned = %u\n", dbg_cpu_reason_cnt[2]);
1344 pr_info("(8)IPv4 HNAT doesn't support IPv4 /w fragment = %u\n",
1345 dbg_cpu_reason_cnt[3]);
1346 pr_info("(9)IPv4 HNAPT/DS-Lite doesn't support IPv4 /w fragment = %u\n",
1347 dbg_cpu_reason_cnt[4]);
1348 pr_info("(10)IPv4 HNAPT/DS-Lite can't find TCP/UDP sport/dport = %u\n",
1349 dbg_cpu_reason_cnt[5]);
1350 pr_info("(11)IPv6 5T-route/6RD can't find TCP/UDP sport/dport = %u\n",
1351 dbg_cpu_reason_cnt[6]);
1352 pr_info("(12)Ingress packet is TCP fin/syn/rst = %u\n",
1353 dbg_cpu_reason_cnt[7]);
1354 pr_info("(13)FOE Un-hit = %u\n", dbg_cpu_reason_cnt[8]);
1355 pr_info("(14)FOE Hit unbind = %u\n", dbg_cpu_reason_cnt[9]);
1356 pr_info("(15)FOE Hit unbind & rate reach = %u\n",
1357 dbg_cpu_reason_cnt[10]);
1358 pr_info("(16)Hit bind PPE TCP FIN entry = %u\n",
1359 dbg_cpu_reason_cnt[11]);
1360 pr_info("(17)Hit bind PPE entry and TTL(hop limit) = 1 and TTL(hot limit) - 1 = %u\n",
1361 dbg_cpu_reason_cnt[12]);
1362 pr_info("(18)Hit bind and VLAN replacement violation = %u\n",
1363 dbg_cpu_reason_cnt[13]);
1364 pr_info("(19)Hit bind and keep alive with unicast old-header packet = %u\n",
1365 dbg_cpu_reason_cnt[14]);
1366 pr_info("(20)Hit bind and keep alive with multicast new-header packet = %u\n",
1367 dbg_cpu_reason_cnt[15]);
1368 pr_info("(21)Hit bind and keep alive with duplicate old-header packet = %u\n",
1369 dbg_cpu_reason_cnt[16]);
1370 pr_info("(22)FOE Hit bind & force to CPU = %u\n",
1371 dbg_cpu_reason_cnt[17]);
1372 pr_info("(28)Hit bind and exceed MTU =%u\n", dbg_cpu_reason_cnt[18]);
1373 pr_info("(24)Hit bind multicast packet to CPU = %u\n",
1374 dbg_cpu_reason_cnt[19]);
1375 pr_info("(25)Hit bind multicast packet to GMAC & CPU = %u\n",
1376 dbg_cpu_reason_cnt[20]);
1377 pr_info("(26)Pre bind = %u\n", dbg_cpu_reason_cnt[21]);
1378
1379 for (i = 0; i < 22; i++)
1380 dbg_cpu_reason_cnt[i] = 0;
1381 return 0;
1382}
1383
1384static int cpu_reason_open(struct inode *inode, struct file *file)
1385{
1386 return single_open(file, cpu_reason_read, file->private_data);
1387}
1388
1389ssize_t cpu_reason_write(struct file *file, const char __user *buffer,
1390 size_t count, loff_t *data)
1391{
1392 char buf[32];
1393 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001394 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001395 long arg0 = 0, arg1 = 0;
1396 char *p_token = NULL;
1397 char *p_delimiter = " \t";
1398 int ret;
1399
1400 if (len >= sizeof(buf)) {
1401 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001402 return -1;
1403 }
1404
1405 if (copy_from_user(buf, buffer, len))
1406 return -EFAULT;
1407
1408 buf[len] = '\0';
1409
1410 p_buf = buf;
1411 p_token = strsep(&p_buf, p_delimiter);
1412 if (!p_token)
1413 arg0 = 0;
1414 else
1415 ret = kstrtol(p_token, 10, &arg0);
1416
1417 switch (arg0) {
1418 case 0:
1419 case 1:
1420 p_token = strsep(&p_buf, p_delimiter);
1421 if (!p_token)
1422 arg1 = 0;
1423 else
1424 ret = kstrtol(p_token, 10, &arg1);
1425 break;
1426 default:
1427 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1428 arg0 = 0;
1429 arg1 = 0;
1430 break;
1431 }
1432
1433 (*hnat_set_func[arg0])(arg1);
1434
1435 return len;
1436}
1437
1438static const struct file_operations cpu_reason_fops = {
1439 .open = cpu_reason_open,
1440 .read = seq_read,
1441 .llseek = seq_lseek,
1442 .write = cpu_reason_write,
1443 .release = single_release,
1444};
1445
1446void dbg_dump_entry(struct seq_file *m, struct foe_entry *entry,
1447 uint32_t index)
1448{
1449 __be32 saddr, daddr, nsaddr, ndaddr;
1450
1451 saddr = htonl(entry->ipv4_hnapt.sip);
1452 daddr = htonl(entry->ipv4_hnapt.dip);
1453 nsaddr = htonl(entry->ipv4_hnapt.new_sip);
1454 ndaddr = htonl(entry->ipv4_hnapt.new_dip);
1455
1456 if (IS_IPV4_HNAPT(entry)) {
1457 seq_printf(m,
1458 "NAPT(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d\n",
1459 index, &saddr, entry->ipv4_hnapt.sport, &daddr,
1460 entry->ipv4_hnapt.dport, &nsaddr,
1461 entry->ipv4_hnapt.new_sport, &ndaddr,
1462 entry->ipv4_hnapt.new_dport);
1463 } else if (IS_IPV4_HNAT(entry)) {
1464 seq_printf(m, "NAT(%d): %pI4->%pI4 => %pI4->%pI4\n",
1465 index, &saddr, &daddr, &nsaddr, &ndaddr);
1466 }
1467
1468 if (IS_IPV4_DSLITE(entry)) {
1469 seq_printf(m,
1470 "IPv4 Ds-Lite(%d): %pI4:%d->%pI4:%d => %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1471 index, &saddr, entry->ipv4_dslite.sport, &daddr,
1472 entry->ipv4_dslite.dport,
1473 entry->ipv4_dslite.tunnel_sipv6_0,
1474 entry->ipv4_dslite.tunnel_sipv6_1,
1475 entry->ipv4_dslite.tunnel_sipv6_2,
1476 entry->ipv4_dslite.tunnel_sipv6_3,
1477 entry->ipv4_dslite.tunnel_dipv6_0,
1478 entry->ipv4_dslite.tunnel_dipv6_1,
1479 entry->ipv4_dslite.tunnel_dipv6_2,
1480 entry->ipv4_dslite.tunnel_dipv6_3);
developerd35bbcc2022-09-28 22:46:01 +08001481#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
developerfd40db22021-04-29 10:08:25 +08001482 } else if (IS_IPV4_MAPE(entry)) {
developerd35bbcc2022-09-28 22:46:01 +08001483 nsaddr = htonl(entry->ipv4_mape.new_sip);
1484 ndaddr = htonl(entry->ipv4_mape.new_dip);
developerfd40db22021-04-29 10:08:25 +08001485
1486 seq_printf(m,
1487 "IPv4 MAP-E(%d): %pI4:%d->%pI4:%d => %pI4:%d->%pI4:%d | Tunnel=%08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X\n",
1488 index, &saddr, entry->ipv4_dslite.sport,
1489 &daddr, entry->ipv4_dslite.dport,
developerd35bbcc2022-09-28 22:46:01 +08001490 &nsaddr, entry->ipv4_mape.new_sport,
1491 &ndaddr, entry->ipv4_mape.new_dport,
developerfd40db22021-04-29 10:08:25 +08001492 entry->ipv4_dslite.tunnel_sipv6_0,
1493 entry->ipv4_dslite.tunnel_sipv6_1,
1494 entry->ipv4_dslite.tunnel_sipv6_2,
1495 entry->ipv4_dslite.tunnel_sipv6_3,
1496 entry->ipv4_dslite.tunnel_dipv6_0,
1497 entry->ipv4_dslite.tunnel_dipv6_1,
1498 entry->ipv4_dslite.tunnel_dipv6_2,
1499 entry->ipv4_dslite.tunnel_dipv6_3);
1500#endif
1501 } else if (IS_IPV6_3T_ROUTE(entry)) {
1502 seq_printf(m,
1503 "IPv6_3T(%d): %08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X (Prot=%d)\n",
1504 index, entry->ipv6_3t_route.ipv6_sip0,
1505 entry->ipv6_3t_route.ipv6_sip1,
1506 entry->ipv6_3t_route.ipv6_sip2,
1507 entry->ipv6_3t_route.ipv6_sip3,
1508 entry->ipv6_3t_route.ipv6_dip0,
1509 entry->ipv6_3t_route.ipv6_dip1,
1510 entry->ipv6_3t_route.ipv6_dip2,
1511 entry->ipv6_3t_route.ipv6_dip3,
1512 entry->ipv6_3t_route.prot);
1513 } else if (IS_IPV6_5T_ROUTE(entry)) {
1514 seq_printf(m,
1515 "IPv6_5T(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1516 index, entry->ipv6_5t_route.ipv6_sip0,
1517 entry->ipv6_5t_route.ipv6_sip1,
1518 entry->ipv6_5t_route.ipv6_sip2,
1519 entry->ipv6_5t_route.ipv6_sip3,
1520 entry->ipv6_5t_route.sport,
1521 entry->ipv6_5t_route.ipv6_dip0,
1522 entry->ipv6_5t_route.ipv6_dip1,
1523 entry->ipv6_5t_route.ipv6_dip2,
1524 entry->ipv6_5t_route.ipv6_dip3,
1525 entry->ipv6_5t_route.dport);
1526 } else if (IS_IPV6_6RD(entry)) {
1527 seq_printf(m,
1528 "IPv6_6RD(%d): %08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d\n",
1529 index, entry->ipv6_6rd.ipv6_sip0,
1530 entry->ipv6_6rd.ipv6_sip1, entry->ipv6_6rd.ipv6_sip2,
1531 entry->ipv6_6rd.ipv6_sip3, entry->ipv6_6rd.sport,
1532 entry->ipv6_6rd.ipv6_dip0, entry->ipv6_6rd.ipv6_dip1,
1533 entry->ipv6_6rd.ipv6_dip2, entry->ipv6_6rd.ipv6_dip3,
1534 entry->ipv6_6rd.dport);
developer5ffc5f12022-10-25 18:51:46 +08001535#if defined(CONFIG_MEDIATEK_NETSYS_V3)
1536 } else if (IS_IPV6_HNAPT(entry)) {
1537 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1538 seq_printf(m,
1539 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1540 index, entry->ipv6_hnapt.ipv6_sip0,
1541 entry->ipv6_hnapt.ipv6_sip1,
1542 entry->ipv6_hnapt.ipv6_sip2,
1543 entry->ipv6_hnapt.ipv6_sip3,
1544 entry->ipv6_hnapt.sport,
1545 entry->ipv6_hnapt.ipv6_dip0,
1546 entry->ipv6_hnapt.ipv6_dip1,
1547 entry->ipv6_hnapt.ipv6_dip2,
1548 entry->ipv6_hnapt.ipv6_dip3,
1549 entry->ipv6_hnapt.dport,
1550 entry->ipv6_hnapt.new_ipv6_ip0,
1551 entry->ipv6_hnapt.new_ipv6_ip1,
1552 entry->ipv6_hnapt.new_ipv6_ip2,
1553 entry->ipv6_hnapt.new_ipv6_ip3,
1554 entry->ipv6_hnapt.new_sport,
1555 entry->ipv6_hnapt.ipv6_dip0,
1556 entry->ipv6_hnapt.ipv6_dip1,
1557 entry->ipv6_hnapt.ipv6_dip2,
1558 entry->ipv6_hnapt.ipv6_dip3,
1559 entry->ipv6_hnapt.new_dport);
1560 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1561 seq_printf(m,
1562 "IPv6_HNAPT(%d): %08X:%08X:%08X:%08X:%d->%08X:%08X:%08X:%08X:%d => %08X:%08X:%08X:%08X:%d -> %08X:%08X:%08X:%08X:%d\n",
1563 index, entry->ipv6_hnapt.ipv6_sip0,
1564 entry->ipv6_hnapt.ipv6_sip1,
1565 entry->ipv6_hnapt.ipv6_sip2,
1566 entry->ipv6_hnapt.ipv6_sip3,
1567 entry->ipv6_hnapt.sport,
1568 entry->ipv6_hnapt.ipv6_dip0,
1569 entry->ipv6_hnapt.ipv6_dip1,
1570 entry->ipv6_hnapt.ipv6_dip2,
1571 entry->ipv6_hnapt.ipv6_dip3,
1572 entry->ipv6_hnapt.dport,
1573 entry->ipv6_hnapt.ipv6_sip0,
1574 entry->ipv6_hnapt.ipv6_sip1,
1575 entry->ipv6_hnapt.ipv6_sip2,
1576 entry->ipv6_hnapt.ipv6_sip3,
1577 entry->ipv6_hnapt.new_sport,
1578 entry->ipv6_hnapt.new_ipv6_ip0,
1579 entry->ipv6_hnapt.new_ipv6_ip1,
1580 entry->ipv6_hnapt.new_ipv6_ip2,
1581 entry->ipv6_hnapt.new_ipv6_ip3,
1582 entry->ipv6_hnapt.new_dport);
1583 }
1584 } else if (IS_IPV6_HNAT(entry)) {
1585 if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_SNAT) {
1586 seq_printf(m,
1587 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1588 index, entry->ipv6_hnapt.ipv6_sip0,
1589 entry->ipv6_hnapt.ipv6_sip1,
1590 entry->ipv6_hnapt.ipv6_sip2,
1591 entry->ipv6_hnapt.ipv6_sip3,
1592 entry->ipv6_hnapt.ipv6_dip0,
1593 entry->ipv6_hnapt.ipv6_dip1,
1594 entry->ipv6_hnapt.ipv6_dip2,
1595 entry->ipv6_hnapt.ipv6_dip3,
1596 entry->ipv6_hnapt.new_ipv6_ip0,
1597 entry->ipv6_hnapt.new_ipv6_ip1,
1598 entry->ipv6_hnapt.new_ipv6_ip2,
1599 entry->ipv6_hnapt.new_ipv6_ip3,
1600 entry->ipv6_hnapt.ipv6_dip0,
1601 entry->ipv6_hnapt.ipv6_dip1,
1602 entry->ipv6_hnapt.ipv6_dip2,
1603 entry->ipv6_hnapt.ipv6_dip3);
1604 } else if (entry->ipv6_hnapt.eg_ipv6_dir == IPV6_DNAT) {
1605 seq_printf(m,
1606 "IPv6_HNAT(%d): %08X:%08X:%08X:%08X->%08X:%08X:%08X:%08X => %08X:%08X:%08X:%08X -> %08X:%08X:%08X:%08X\n",
1607 index, entry->ipv6_hnapt.ipv6_sip0,
1608 entry->ipv6_hnapt.ipv6_sip1,
1609 entry->ipv6_hnapt.ipv6_sip2,
1610 entry->ipv6_hnapt.ipv6_sip3,
1611 entry->ipv6_hnapt.ipv6_dip0,
1612 entry->ipv6_hnapt.ipv6_dip1,
1613 entry->ipv6_hnapt.ipv6_dip2,
1614 entry->ipv6_hnapt.ipv6_dip3,
1615 entry->ipv6_hnapt.ipv6_sip0,
1616 entry->ipv6_hnapt.ipv6_sip1,
1617 entry->ipv6_hnapt.ipv6_sip2,
1618 entry->ipv6_hnapt.ipv6_sip3,
1619 entry->ipv6_hnapt.new_ipv6_ip0,
1620 entry->ipv6_hnapt.new_ipv6_ip1,
1621 entry->ipv6_hnapt.new_ipv6_ip2,
1622 entry->ipv6_hnapt.new_ipv6_ip3);
1623 }
1624#endif
developerfd40db22021-04-29 10:08:25 +08001625 }
1626}
1627
developer4c32b7a2021-11-13 16:46:43 +08001628int __hnat_entry_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001629{
1630 struct mtk_hnat *h = hnat_priv;
1631 struct foe_entry *entry, *end;
1632 int hash_index;
1633 int cnt;
1634
developer4c32b7a2021-11-13 16:46:43 +08001635 if (ppe_id >= CFG_PPE_NUM)
1636 return -EINVAL;
1637
developerfd40db22021-04-29 10:08:25 +08001638 hash_index = 0;
1639 cnt = 0;
developer471f6562021-05-10 20:48:34 +08001640 entry = h->foe_table_cpu[ppe_id];
1641 end = h->foe_table_cpu[ppe_id] + hnat_priv->foe_etry_num;
1642
1643 seq_printf(m, "============================\n");
1644 seq_printf(m, "PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001645
1646 while (entry < end) {
1647 if (entry->bfib1.state == dbg_entry_state) {
1648 cnt++;
1649 dbg_dump_entry(m, entry, hash_index);
1650 }
1651 hash_index++;
1652 entry++;
1653 }
1654
1655 seq_printf(m, "Total State = %s cnt = %d\n",
1656 dbg_entry_state == 0 ?
1657 "Invalid" : dbg_entry_state == 1 ?
1658 "Unbind" : dbg_entry_state == 2 ?
1659 "BIND" : dbg_entry_state == 3 ?
1660 "FIN" : "Unknown", cnt);
1661
1662 return 0;
1663}
1664
developer471f6562021-05-10 20:48:34 +08001665int hnat_entry_read(struct seq_file *m, void *private)
1666{
1667 int i;
1668
1669 for (i = 0; i < CFG_PPE_NUM; i++)
1670 __hnat_entry_read(m, private, i);
1671
1672 return 0;
1673}
1674
developerfd40db22021-04-29 10:08:25 +08001675ssize_t hnat_entry_write(struct file *file, const char __user *buffer,
1676 size_t count, loff_t *data)
1677{
1678 char buf[32];
1679 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001680 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001681 long arg0 = 0, arg1 = 0;
1682 char *p_token = NULL;
1683 char *p_delimiter = " \t";
1684 int ret;
1685
1686 if (len >= sizeof(buf)) {
1687 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001688 return -1;
1689 }
1690
1691 if (copy_from_user(buf, buffer, len))
1692 return -EFAULT;
1693
1694 buf[len] = '\0';
1695
1696 p_buf = buf;
1697 p_token = strsep(&p_buf, p_delimiter);
1698 if (!p_token)
1699 arg0 = 0;
1700 else
1701 ret = kstrtol(p_token, 10, &arg0);
1702
1703 switch (arg0) {
1704 case 0:
1705 case 1:
1706 case 2:
1707 case 3:
developer471f6562021-05-10 20:48:34 +08001708 case 4:
1709 case 5:
developerfd40db22021-04-29 10:08:25 +08001710 p_token = strsep(&p_buf, p_delimiter);
1711 if (!p_token)
1712 arg1 = 0;
1713 else
1714 ret = kstrtol(p_token, 10, &arg1);
1715 break;
1716 default:
1717 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1718 arg0 = 0;
1719 arg1 = 0;
1720 break;
1721 }
1722
1723 (*entry_set_func[arg0])(arg1);
1724
1725 return len;
1726}
1727
1728static int hnat_entry_open(struct inode *inode, struct file *file)
1729{
1730 return single_open(file, hnat_entry_read, file->private_data);
1731}
1732
1733static const struct file_operations hnat_entry_fops = {
1734 .open = hnat_entry_open,
1735 .read = seq_read,
1736 .llseek = seq_lseek,
1737 .write = hnat_entry_write,
1738 .release = single_release,
1739};
1740
developer4c32b7a2021-11-13 16:46:43 +08001741int __hnat_setting_read(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001742{
1743 struct mtk_hnat *h = hnat_priv;
1744 int i;
1745 int cr_max;
1746
developer4c32b7a2021-11-13 16:46:43 +08001747 if (ppe_id >= CFG_PPE_NUM)
1748 return -EINVAL;
1749
developerfd40db22021-04-29 10:08:25 +08001750 cr_max = 319 * 4;
1751 for (i = 0; i < cr_max; i = i + 0x10) {
1752 pr_info("0x%p : 0x%08x 0x%08x 0x%08x 0x%08x\n",
developer471f6562021-05-10 20:48:34 +08001753 (void *)h->foe_table_dev[ppe_id] + i,
1754 readl(h->ppe_base[ppe_id] + i),
1755 readl(h->ppe_base[ppe_id] + i + 4),
1756 readl(h->ppe_base[ppe_id] + i + 8),
1757 readl(h->ppe_base[ppe_id] + i + 0xc));
developerfd40db22021-04-29 10:08:25 +08001758 }
1759
1760 return 0;
1761}
1762
developer471f6562021-05-10 20:48:34 +08001763int hnat_setting_read(struct seq_file *m, void *private)
1764{
1765 int i;
1766
1767 for (i = 0; i < CFG_PPE_NUM; i++)
1768 __hnat_setting_read(m, private, i);
1769
1770 return 0;
1771}
1772
developerfd40db22021-04-29 10:08:25 +08001773static int hnat_setting_open(struct inode *inode, struct file *file)
1774{
1775 return single_open(file, hnat_setting_read, file->private_data);
1776}
1777
1778ssize_t hnat_setting_write(struct file *file, const char __user *buffer,
1779 size_t count, loff_t *data)
1780{
1781 char buf[32];
1782 char *p_buf;
developer4c32b7a2021-11-13 16:46:43 +08001783 u32 len = count;
developerfd40db22021-04-29 10:08:25 +08001784 long arg0 = 0, arg1 = 0;
1785 char *p_token = NULL;
1786 char *p_delimiter = " \t";
1787 int ret;
1788
1789 if (len >= sizeof(buf)) {
1790 pr_info("input handling fail!\n");
developerfd40db22021-04-29 10:08:25 +08001791 return -1;
1792 }
1793
1794 if (copy_from_user(buf, buffer, len))
1795 return -EFAULT;
1796
1797 buf[len] = '\0';
1798
1799 p_buf = buf;
1800 p_token = strsep(&p_buf, p_delimiter);
1801 if (!p_token)
1802 arg0 = 0;
1803 else
1804 ret = kstrtol(p_token, 10, &arg0);
1805
1806 switch (arg0) {
1807 case 0:
1808 case 1:
1809 case 2:
1810 case 3:
1811 case 4:
1812 case 5:
1813 case 6:
developer30a47682021-11-02 17:06:14 +08001814 case 7:
developerfd40db22021-04-29 10:08:25 +08001815 p_token = strsep(&p_buf, p_delimiter);
1816 if (!p_token)
1817 arg1 = 0;
1818 else
1819 ret = kstrtol(p_token, 10, &arg1);
1820 break;
1821 default:
1822 pr_info("no handler defined for command id(0x%08lx)\n\r", arg0);
1823 arg0 = 0;
1824 arg1 = 0;
1825 break;
1826 }
1827
1828 (*cr_set_func[arg0])(arg1);
1829
1830 return len;
1831}
1832
1833static const struct file_operations hnat_setting_fops = {
1834 .open = hnat_setting_open,
1835 .read = seq_read,
1836 .llseek = seq_lseek,
1837 .write = hnat_setting_write,
1838 .release = single_release,
1839};
1840
developer4c32b7a2021-11-13 16:46:43 +08001841int __mcast_table_dump(struct seq_file *m, void *private, u32 ppe_id)
developerfd40db22021-04-29 10:08:25 +08001842{
1843 struct mtk_hnat *h = hnat_priv;
1844 struct ppe_mcast_h mcast_h;
1845 struct ppe_mcast_l mcast_l;
1846 u8 i, max;
1847 void __iomem *reg;
1848
developer4c32b7a2021-11-13 16:46:43 +08001849 if (ppe_id >= CFG_PPE_NUM)
1850 return -EINVAL;
1851
developerfd40db22021-04-29 10:08:25 +08001852 if (!h->pmcast)
1853 return 0;
1854
1855 max = h->pmcast->max_entry;
developer471f6562021-05-10 20:48:34 +08001856 pr_info("============================\n");
1857 pr_info("PPE_ID = %d\n", ppe_id);
developerfd40db22021-04-29 10:08:25 +08001858 pr_info("MAC | VID | PortMask | QosPortMask\n");
1859 for (i = 0; i < max; i++) {
1860 if (i < 0x10) {
developer471f6562021-05-10 20:48:34 +08001861 reg = h->ppe_base[ppe_id] + PPE_MCAST_H_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001862 mcast_h.u.value = readl(reg);
developer471f6562021-05-10 20:48:34 +08001863 reg = h->ppe_base[ppe_id] + PPE_MCAST_L_0 + i * 8;
developerfd40db22021-04-29 10:08:25 +08001864 mcast_l.addr = readl(reg);
1865 } else {
1866 reg = h->fe_base + PPE_MCAST_H_10 + (i - 0x10) * 8;
1867 mcast_h.u.value = readl(reg);
1868 reg = h->fe_base + PPE_MCAST_L_10 + (i - 0x10) * 8;
1869 mcast_l.addr = readl(reg);
1870 }
1871 pr_info("%08x %d %c%c%c%c %c%c%c%c (QID=%d, mc_mpre_sel=%d)\n",
1872 mcast_l.addr,
1873 mcast_h.u.info.mc_vid,
1874 (mcast_h.u.info.mc_px_en & 0x08) ? '1' : '-',
1875 (mcast_h.u.info.mc_px_en & 0x04) ? '1' : '-',
1876 (mcast_h.u.info.mc_px_en & 0x02) ? '1' : '-',
1877 (mcast_h.u.info.mc_px_en & 0x01) ? '1' : '-',
1878 (mcast_h.u.info.mc_px_qos_en & 0x08) ? '1' : '-',
1879 (mcast_h.u.info.mc_px_qos_en & 0x04) ? '1' : '-',
1880 (mcast_h.u.info.mc_px_qos_en & 0x02) ? '1' : '-',
1881 (mcast_h.u.info.mc_px_qos_en & 0x01) ? '1' : '-',
1882 mcast_h.u.info.mc_qos_qid +
1883 ((mcast_h.u.info.mc_qos_qid54) << 4),
1884 mcast_h.u.info.mc_mpre_sel);
1885 }
1886
1887 return 0;
1888}
1889
developer471f6562021-05-10 20:48:34 +08001890int mcast_table_dump(struct seq_file *m, void *private)
1891{
1892 int i;
1893
1894 for (i = 0; i < CFG_PPE_NUM; i++)
1895 __mcast_table_dump(m, private, i);
1896
1897 return 0;
1898}
1899
developerfd40db22021-04-29 10:08:25 +08001900static int mcast_table_open(struct inode *inode, struct file *file)
1901{
1902 return single_open(file, mcast_table_dump, file->private_data);
1903}
1904
1905static const struct file_operations hnat_mcast_fops = {
1906 .open = mcast_table_open,
1907 .read = seq_read,
1908 .llseek = seq_lseek,
1909 .release = single_release,
1910};
1911
1912static int hnat_ext_show(struct seq_file *m, void *private)
1913{
1914 int i;
1915 struct extdev_entry *ext_entry;
1916
1917 for (i = 0; i < MAX_EXT_DEVS && hnat_priv->ext_if[i]; i++) {
1918 ext_entry = hnat_priv->ext_if[i];
1919 if (ext_entry->dev)
1920 seq_printf(m, "ext devices [%d] = %s (dev=%p, ifindex=%d)\n",
1921 i, ext_entry->name, ext_entry->dev,
1922 ext_entry->dev->ifindex);
1923 }
1924
1925 return 0;
1926}
1927
1928static int hnat_ext_open(struct inode *inode, struct file *file)
1929{
1930 return single_open(file, hnat_ext_show, file->private_data);
1931}
1932
1933static const struct file_operations hnat_ext_fops = {
1934 .open = hnat_ext_open,
1935 .read = seq_read,
1936 .llseek = seq_lseek,
1937 .release = single_release,
1938};
1939
1940static ssize_t hnat_sched_show(struct file *file, char __user *user_buf,
1941 size_t count, loff_t *ppos)
1942{
1943 long id = (long)file->private_data;
1944 struct mtk_hnat *h = hnat_priv;
1945 u32 qdma_tx_sch;
1946 int enable;
1947 int scheduling;
1948 int max_rate;
1949 char *buf;
1950 unsigned int len = 0, buf_len = 1500;
1951 ssize_t ret_cnt;
1952 int scheduler, i;
1953 u32 sch_reg;
1954
1955 buf = kzalloc(buf_len, GFP_KERNEL);
1956 if (!buf)
1957 return -ENOMEM;
1958
1959 if (hnat_priv->data->num_of_sch == 4)
1960 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
1961 else
1962 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
1963
1964 if (id & 0x1)
1965 qdma_tx_sch >>= 16;
1966 qdma_tx_sch &= 0xffff;
1967 enable = !!(qdma_tx_sch & BIT(11));
1968 scheduling = !!(qdma_tx_sch & BIT(15));
1969 max_rate = ((qdma_tx_sch >> 4) & 0x7f);
1970 qdma_tx_sch &= 0xf;
1971 while (qdma_tx_sch--)
1972 max_rate *= 10;
1973
1974 len += scnprintf(buf + len, buf_len - len,
1975 "EN\tScheduling\tMAX\tQueue#\n%d\t%s%16d\t", enable,
1976 (scheduling == 1) ? "WRR" : "SP", max_rate);
1977
1978 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
1979 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE,
1980 (i / NUM_OF_Q_PER_PAGE));
1981 sch_reg = readl(h->fe_base + QTX_SCH(i % NUM_OF_Q_PER_PAGE));
1982 if (hnat_priv->data->num_of_sch == 4)
1983 scheduler = (sch_reg >> 30) & 0x3;
1984 else
1985 scheduler = !!(sch_reg & BIT(31));
1986 if (id == scheduler)
1987 len += scnprintf(buf + len, buf_len - len, "%d ", i);
1988 }
1989
1990 len += scnprintf(buf + len, buf_len - len, "\n");
1991 if (len > buf_len)
1992 len = buf_len;
1993
1994 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1995
1996 kfree(buf);
1997 return ret_cnt;
1998}
1999
2000static ssize_t hnat_sched_write(struct file *file, const char __user *buf,
2001 size_t length, loff_t *offset)
2002{
2003 long id = (long)file->private_data;
2004 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002005 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002006 int enable, rate, exp = 0, shift = 0;
2007 char scheduling[32];
2008 size_t size;
2009 u32 qdma_tx_sch;
2010 u32 val = 0;
2011
developerc316c852021-07-09 11:23:40 +08002012 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002013 return -EINVAL;
2014
2015 if (copy_from_user(line, buf, length))
2016 return -EFAULT;
2017
2018 if (sscanf(line, "%d %s %d", &enable, scheduling, &rate) != 3)
2019 return -EFAULT;
2020
2021 while (rate > 127) {
2022 rate /= 10;
2023 exp++;
2024 }
2025
developerc316c852021-07-09 11:23:40 +08002026 line[length] = '\0';
2027
developerfd40db22021-04-29 10:08:25 +08002028 if (enable)
2029 val |= BIT(11);
2030 if (strcmp(scheduling, "sp") != 0)
2031 val |= BIT(15);
2032 val |= (rate & 0x7f) << 4;
2033 val |= exp & 0xf;
2034 if (id & 0x1)
2035 shift = 16;
2036
2037 if (hnat_priv->data->num_of_sch == 4)
2038 qdma_tx_sch = readl(h->fe_base + QDMA_TX_4SCH_BASE(id));
2039 else
2040 qdma_tx_sch = readl(h->fe_base + QDMA_TX_2SCH_BASE);
2041
2042 qdma_tx_sch &= ~(0xffff << shift);
2043 qdma_tx_sch |= val << shift;
2044 if (hnat_priv->data->num_of_sch == 4)
2045 writel(qdma_tx_sch, h->fe_base + QDMA_TX_4SCH_BASE(id));
2046 else
2047 writel(qdma_tx_sch, h->fe_base + QDMA_TX_2SCH_BASE);
2048
2049 size = strlen(line);
2050 *offset += size;
2051
2052 return length;
2053}
2054
2055static const struct file_operations hnat_sched_fops = {
2056 .open = simple_open,
2057 .read = hnat_sched_show,
2058 .write = hnat_sched_write,
2059 .llseek = default_llseek,
2060};
2061
2062static ssize_t hnat_queue_show(struct file *file, char __user *user_buf,
2063 size_t count, loff_t *ppos)
2064{
2065 struct mtk_hnat *h = hnat_priv;
2066 long id = (long)file->private_data;
2067 u32 qtx_sch;
2068 u32 qtx_cfg;
2069 int scheduler;
2070 int min_rate_en;
2071 int min_rate;
2072 int min_rate_exp;
2073 int max_rate_en;
2074 int max_weight;
2075 int max_rate;
2076 int max_rate_exp;
2077 char *buf;
2078 unsigned int len = 0, buf_len = 1500;
2079 ssize_t ret_cnt;
2080
2081 buf = kzalloc(buf_len, GFP_KERNEL);
2082 if (!buf)
2083 return -ENOMEM;
2084
2085 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
2086 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2087 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2088 if (hnat_priv->data->num_of_sch == 4)
2089 scheduler = (qtx_sch >> 30) & 0x3;
2090 else
2091 scheduler = !!(qtx_sch & BIT(31));
2092 min_rate_en = !!(qtx_sch & BIT(27));
2093 min_rate = (qtx_sch >> 20) & 0x7f;
2094 min_rate_exp = (qtx_sch >> 16) & 0xf;
2095 max_rate_en = !!(qtx_sch & BIT(11));
2096 max_weight = (qtx_sch >> 12) & 0xf;
2097 max_rate = (qtx_sch >> 4) & 0x7f;
2098 max_rate_exp = qtx_sch & 0xf;
2099 while (min_rate_exp--)
2100 min_rate *= 10;
2101
2102 while (max_rate_exp--)
2103 max_rate *= 10;
2104
2105 len += scnprintf(buf + len, buf_len - len,
2106 "scheduler: %d\nhw resv: %d\nsw resv: %d\n", scheduler,
2107 (qtx_cfg >> 8) & 0xff, qtx_cfg & 0xff);
2108
2109 if (hnat_priv->data->version != MTK_HNAT_V1) {
2110 /* Switch to debug mode */
2111 cr_set_field(h->fe_base + QTX_MIB_IF, MIB_ON_QTX_CFG, 1);
2112 cr_set_field(h->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 1);
2113 qtx_cfg = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2114 qtx_sch = readl(h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2115 len += scnprintf(buf + len, buf_len - len,
2116 "packet count: %u\n", qtx_cfg);
2117 len += scnprintf(buf + len, buf_len - len,
2118 "packet drop: %u\n\n", qtx_sch);
2119
2120 /* Recover to normal mode */
2121 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF,
2122 MIB_ON_QTX_CFG, 0);
2123 cr_set_field(hnat_priv->fe_base + QTX_MIB_IF, VQTX_MIB_EN, 0);
2124 }
2125
2126 len += scnprintf(buf + len, buf_len - len,
2127 " EN RATE WEIGHT\n");
2128 len += scnprintf(buf + len, buf_len - len,
2129 "----------------------------\n");
2130 len += scnprintf(buf + len, buf_len - len,
2131 "max%5d%9d%9d\n", max_rate_en, max_rate, max_weight);
2132 len += scnprintf(buf + len, buf_len - len,
2133 "min%5d%9d -\n", min_rate_en, min_rate);
2134
2135 if (len > buf_len)
2136 len = buf_len;
2137
2138 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
2139
2140 kfree(buf);
2141 return ret_cnt;
2142}
2143
2144static ssize_t hnat_queue_write(struct file *file, const char __user *buf,
2145 size_t length, loff_t *offset)
2146{
2147 long id = (long)file->private_data;
2148 struct mtk_hnat *h = hnat_priv;
developer4c32b7a2021-11-13 16:46:43 +08002149 char line[64] = {0};
developerfd40db22021-04-29 10:08:25 +08002150 int max_enable, max_rate, max_exp = 0;
2151 int min_enable, min_rate, min_exp = 0;
2152 int weight;
2153 int resv;
2154 int scheduler;
2155 size_t size;
developer04f0ec82021-12-30 13:59:10 +08002156 u32 qtx_sch = 0;
developerfd40db22021-04-29 10:08:25 +08002157
2158 cr_set_field(h->fe_base + QDMA_PAGE, QTX_CFG_PAGE, (id / NUM_OF_Q_PER_PAGE));
developerc316c852021-07-09 11:23:40 +08002159 if (length >= sizeof(line))
developerfd40db22021-04-29 10:08:25 +08002160 return -EINVAL;
2161
2162 if (copy_from_user(line, buf, length))
2163 return -EFAULT;
2164
2165 if (sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate,
2166 &max_enable, &max_rate, &weight, &resv) != 7)
2167 return -EFAULT;
2168
developerc316c852021-07-09 11:23:40 +08002169 line[length] = '\0';
2170
developer577ad2f2022-11-28 10:33:36 +08002171#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2172 if (max_rate > 100000000 || max_rate < 0 ||
2173 min_rate > 100000000 || min_rate < 0)
2174#else
2175 if (max_rate > 10000000 || max_rate < 0 ||
2176 min_rate > 10000000 || min_rate < 0)
2177#endif
2178 return -EINVAL;
2179
developerfd40db22021-04-29 10:08:25 +08002180 while (max_rate > 127) {
2181 max_rate /= 10;
2182 max_exp++;
2183 }
2184
2185 while (min_rate > 127) {
2186 min_rate /= 10;
2187 min_exp++;
2188 }
2189
developerfd40db22021-04-29 10:08:25 +08002190 if (hnat_priv->data->num_of_sch == 4)
2191 qtx_sch |= (scheduler & 0x3) << 30;
2192 else
2193 qtx_sch |= (scheduler & 0x1) << 31;
2194 if (min_enable)
2195 qtx_sch |= BIT(27);
2196 qtx_sch |= (min_rate & 0x7f) << 20;
2197 qtx_sch |= (min_exp & 0xf) << 16;
2198 if (max_enable)
2199 qtx_sch |= BIT(11);
2200 qtx_sch |= (weight & 0xf) << 12;
2201 qtx_sch |= (max_rate & 0x7f) << 4;
2202 qtx_sch |= max_exp & 0xf;
2203 writel(qtx_sch, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2204
2205 resv &= 0xff;
2206 qtx_sch = readl(h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2207 qtx_sch &= 0xffff0000;
2208 qtx_sch |= (resv << 8) | resv;
2209 writel(qtx_sch, h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2210
2211 size = strlen(line);
2212 *offset += size;
2213
2214 return length;
2215}
2216
2217static const struct file_operations hnat_queue_fops = {
2218 .open = simple_open,
2219 .read = hnat_queue_show,
2220 .write = hnat_queue_write,
2221 .llseek = default_llseek,
2222};
2223
2224static ssize_t hnat_ppd_if_write(struct file *file, const char __user *buffer,
2225 size_t count, loff_t *data)
2226{
2227 char buf[IFNAMSIZ];
2228 struct net_device *dev;
2229 char *p, *tmp;
2230
2231 if (count >= IFNAMSIZ)
2232 return -EFAULT;
2233
2234 memset(buf, 0, IFNAMSIZ);
2235 if (copy_from_user(buf, buffer, count))
2236 return -EFAULT;
2237
2238 tmp = buf;
2239 p = strsep(&tmp, "\n\r ");
2240 dev = dev_get_by_name(&init_net, p);
2241
2242 if (dev) {
2243 if (hnat_priv->g_ppdev)
2244 dev_put(hnat_priv->g_ppdev);
2245 hnat_priv->g_ppdev = dev;
2246
developer4c32b7a2021-11-13 16:46:43 +08002247 strncpy(hnat_priv->ppd, p, IFNAMSIZ - 1);
developerfd40db22021-04-29 10:08:25 +08002248 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2249 } else {
2250 pr_info("no such device!\n");
2251 }
2252
2253 return count;
2254}
2255
2256static int hnat_ppd_if_read(struct seq_file *m, void *private)
2257{
2258 pr_info("hnat_priv ppd = %s\n", hnat_priv->ppd);
2259
2260 if (hnat_priv->g_ppdev) {
2261 pr_info("hnat_priv g_ppdev name = %s\n",
2262 hnat_priv->g_ppdev->name);
2263 } else {
2264 pr_info("hnat_priv g_ppdev is null!\n");
2265 }
2266
2267 return 0;
2268}
2269
2270static int hnat_ppd_if_open(struct inode *inode, struct file *file)
2271{
2272 return single_open(file, hnat_ppd_if_read, file->private_data);
2273}
2274
2275static const struct file_operations hnat_ppd_if_fops = {
2276 .open = hnat_ppd_if_open,
2277 .read = seq_read,
2278 .llseek = seq_lseek,
2279 .write = hnat_ppd_if_write,
2280 .release = single_release,
2281};
2282
2283static int hnat_mape_toggle_read(struct seq_file *m, void *private)
2284{
2285 pr_info("value=%d, %s is enabled now!\n", mape_toggle, (mape_toggle) ? "mape" : "ds-lite");
2286
2287 return 0;
2288}
2289
2290static int hnat_mape_toggle_open(struct inode *inode, struct file *file)
2291{
2292 return single_open(file, hnat_mape_toggle_read, file->private_data);
2293}
2294
2295static ssize_t hnat_mape_toggle_write(struct file *file, const char __user *buffer,
2296 size_t count, loff_t *data)
2297{
developer4c32b7a2021-11-13 16:46:43 +08002298 char buf = 0;
developer25fc8c02022-05-06 16:24:02 +08002299 int i;
2300 u32 ppe_cfg;
2301
2302 if ((count < 1) || copy_from_user(&buf, buffer, sizeof(buf)))
developerfd40db22021-04-29 10:08:25 +08002303 return -EFAULT;
2304
developer25fc8c02022-05-06 16:24:02 +08002305 if (buf == '1') {
developerfd40db22021-04-29 10:08:25 +08002306 pr_info("mape is going to be enabled, ds-lite is going to be disabled !\n");
2307 mape_toggle = 1;
developer25fc8c02022-05-06 16:24:02 +08002308 } else if (buf == '0') {
developerfd40db22021-04-29 10:08:25 +08002309 pr_info("ds-lite is going to be enabled, mape is going to be disabled !\n");
2310 mape_toggle = 0;
developer25fc8c02022-05-06 16:24:02 +08002311 } else {
2312 pr_info("Invalid parameter.\n");
2313 return -EFAULT;
2314 }
2315
2316 for (i = 0; i < CFG_PPE_NUM; i++) {
2317 ppe_cfg = readl(hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
2318
2319 if (mape_toggle)
2320 ppe_cfg &= ~BIT_IPV4_DSL_EN;
2321 else
2322 ppe_cfg |= BIT_IPV4_DSL_EN;
2323
2324 writel(ppe_cfg, hnat_priv->ppe_base[i] + PPE_FLOW_CFG);
developerfd40db22021-04-29 10:08:25 +08002325 }
2326
developer25fc8c02022-05-06 16:24:02 +08002327 return count;
developerfd40db22021-04-29 10:08:25 +08002328}
2329
2330static const struct file_operations hnat_mape_toggle_fops = {
2331 .open = hnat_mape_toggle_open,
2332 .read = seq_read,
2333 .llseek = seq_lseek,
2334 .write = hnat_mape_toggle_write,
2335 .release = single_release,
2336};
2337
2338static int hnat_hook_toggle_read(struct seq_file *m, void *private)
2339{
2340 pr_info("value=%d, hook is %s now!\n", hook_toggle, (hook_toggle) ? "enabled" : "disabled");
2341
2342 return 0;
2343}
2344
2345static int hnat_hook_toggle_open(struct inode *inode, struct file *file)
2346{
2347 return single_open(file, hnat_hook_toggle_read, file->private_data);
2348}
2349
2350static ssize_t hnat_hook_toggle_write(struct file *file, const char __user *buffer,
2351 size_t count, loff_t *data)
2352{
developer4c32b7a2021-11-13 16:46:43 +08002353 char buf[8] = {0};
developerfd40db22021-04-29 10:08:25 +08002354 int len = count;
developer70cdf6e2021-12-07 18:58:35 +08002355 u32 id;
developerfd40db22021-04-29 10:08:25 +08002356
2357 if ((len > 8) || copy_from_user(buf, buffer, len))
2358 return -EFAULT;
2359
2360 if (buf[0] == '1' && !hook_toggle) {
2361 pr_info("hook is going to be enabled !\n");
2362 hnat_enable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002363
2364 if (IS_PPPQ_MODE) {
2365 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2366 hnat_qos_shaper_ebl(id, 1);
2367 }
developerfd40db22021-04-29 10:08:25 +08002368 } else if (buf[0] == '0' && hook_toggle) {
2369 pr_info("hook is going to be disabled !\n");
2370 hnat_disable_hook();
developer70cdf6e2021-12-07 18:58:35 +08002371
2372 if (IS_PPPQ_MODE) {
2373 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
2374 hnat_qos_shaper_ebl(id, 0);
2375 }
developerfd40db22021-04-29 10:08:25 +08002376 }
2377
2378 return len;
2379}
2380
2381static const struct file_operations hnat_hook_toggle_fops = {
2382 .open = hnat_hook_toggle_open,
2383 .read = seq_read,
2384 .llseek = seq_lseek,
2385 .write = hnat_hook_toggle_write,
2386 .release = single_release,
2387};
2388
developer47545a32022-11-15 16:06:58 +08002389static void hnat_qos_toggle_usage(void)
2390{
2391 pr_info("\nHQoS toggle Command Usage:\n");
2392 pr_info("Show HQoS mode:\n");
2393 pr_info(" cat /sys/kernel/debug/hnat/qos_toggle\n");
2394 pr_info("Disable HQoS mode:\n");
2395 pr_info(" echo 0 > /sys/kernel/debug/hnat/qos_toggle\n");
2396 pr_info("Enable HQoS on bidirection:\n");
2397 pr_info(" echo 1 > /sys/kernel/debug/hnat/qos_toggle\n");
2398 pr_info("Enable HQoS on uplink only:\n");
2399 pr_info(" echo 1 uplink > /sys/kernel/debug/hnat/qos_toggle\n");
2400 pr_info("Enable HQoS on downlink only:\n");
2401 pr_info(" echo 1 downlink > /sys/kernel/debug/hnat/qos_toggle\n");
2402 pr_info("Enable Per-port-per-queue mode:\n");
2403 pr_info(" echo 2 > /sys/kernel/debug/hnat/qos_toggle\n");
2404 pr_info("Show HQoS toggle usage:\n");
2405 pr_info(" echo 3 > /sys/kernel/debug/hnat/qos_toggle\n\n");
2406}
2407
developeraf07fad2021-11-19 17:53:42 +08002408static int hnat_qos_toggle_read(struct seq_file *m, void *private)
2409{
developer47545a32022-11-15 16:06:58 +08002410 if (qos_toggle == 0) {
2411 pr_info("HQoS is disabled now!\n");
2412 } else if (qos_toggle == 1) {
2413 pr_info("HQoS is enabled now!\n");
2414 pr_info("HQoS uplink is %s now!\n",
2415 qos_ul_toggle ? "enabled" : "disabled");
2416 pr_info("HQoS downlink is %s now!\n",
2417 qos_dl_toggle ? "enabled" : "disabled");
2418 } else if (qos_toggle == 2) {
2419 pr_info("Per-port-per-queue mode is enabled!\n");
2420 }
developeraf07fad2021-11-19 17:53:42 +08002421
2422 return 0;
2423}
2424
2425static int hnat_qos_toggle_open(struct inode *inode, struct file *file)
2426{
2427 return single_open(file, hnat_qos_toggle_read, file->private_data);
2428}
2429
developer70cdf6e2021-12-07 18:58:35 +08002430void hnat_qos_shaper_ebl(u32 id, u32 enable)
2431{
2432 struct mtk_hnat *h = hnat_priv;
2433 u32 cfg;
2434
2435 if (enable) {
2436 cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
2437 cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
2438 (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
2439 (25 << QTX_SCH_MAX_RATE_MAN_OFFSET) |
2440 (5 << QTX_SCH_MAX_RATE_EXP_OFFSET) |
2441 (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
2442
2443 writel(cfg, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2444 } else {
2445 writel(0, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
2446 }
2447}
2448
2449static void hnat_qos_disable(void)
2450{
2451 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002452 u32 id, cfg;
developer70cdf6e2021-12-07 18:58:35 +08002453
2454 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2455 hnat_qos_shaper_ebl(id, 0);
developer34028fb2022-01-11 13:51:29 +08002456 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2457 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2458 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
developer70cdf6e2021-12-07 18:58:35 +08002459 }
2460
developer34028fb2022-01-11 13:51:29 +08002461 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002462 for (id = 0; id < h->data->num_of_sch; id += 2) {
2463 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002464 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002465 else
developer34028fb2022-01-11 13:51:29 +08002466 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer70cdf6e2021-12-07 18:58:35 +08002467 }
2468}
2469
developer24948202021-11-24 17:38:27 +08002470static void hnat_qos_pppq_enable(void)
2471{
developer70cdf6e2021-12-07 18:58:35 +08002472 struct mtk_hnat *h = hnat_priv;
developer34028fb2022-01-11 13:51:29 +08002473 u32 id, cfg;
developer24948202021-11-24 17:38:27 +08002474
developer70cdf6e2021-12-07 18:58:35 +08002475 for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
2476 if (hook_toggle)
2477 hnat_qos_shaper_ebl(id, 1);
2478 else
2479 hnat_qos_shaper_ebl(id, 0);
developer24948202021-11-24 17:38:27 +08002480
developer70cdf6e2021-12-07 18:58:35 +08002481 writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
2482 (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
2483 h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
2484 }
developer24948202021-11-24 17:38:27 +08002485
developer34028fb2022-01-11 13:51:29 +08002486 cfg = (QDMA_TX_SCH_WFQ_EN) | (QDMA_TX_SCH_WFQ_EN << 16);
developer70cdf6e2021-12-07 18:58:35 +08002487 for (id = 0; id < h->data->num_of_sch; id+= 2) {
2488 if (h->data->num_of_sch == 4)
developer34028fb2022-01-11 13:51:29 +08002489 writel(cfg, h->fe_base + QDMA_TX_4SCH_BASE(id));
developer70cdf6e2021-12-07 18:58:35 +08002490 else
developer34028fb2022-01-11 13:51:29 +08002491 writel(cfg, h->fe_base + QDMA_TX_2SCH_BASE);
developer24948202021-11-24 17:38:27 +08002492 }
2493}
2494
developeraf07fad2021-11-19 17:53:42 +08002495static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffer,
2496 size_t count, loff_t *data)
2497{
developer577ad2f2022-11-28 10:33:36 +08002498 char buf[32] = {0}, tmp[32];
developeraf07fad2021-11-19 17:53:42 +08002499 int len = count;
developer47545a32022-11-15 16:06:58 +08002500 char *p_buf = NULL, *p_token = NULL;
developeraf07fad2021-11-19 17:53:42 +08002501
developer47545a32022-11-15 16:06:58 +08002502 if (len >= sizeof(buf))
2503 return -EFAULT;
2504
2505 if (copy_from_user(buf, buffer, len))
developeraf07fad2021-11-19 17:53:42 +08002506 return -EFAULT;
2507
developer47545a32022-11-15 16:06:58 +08002508 buf[len] = '\0';
2509
developer24948202021-11-24 17:38:27 +08002510 if (buf[0] == '0') {
developer47545a32022-11-15 16:06:58 +08002511 pr_info("HQoS is going to be disabled!\n");
developeraf07fad2021-11-19 17:53:42 +08002512 qos_toggle = 0;
developer47545a32022-11-15 16:06:58 +08002513 qos_dl_toggle = 0;
2514 qos_ul_toggle = 0;
developer70cdf6e2021-12-07 18:58:35 +08002515 hnat_qos_disable();
developer24948202021-11-24 17:38:27 +08002516 } else if (buf[0] == '1') {
developer47545a32022-11-15 16:06:58 +08002517 p_buf = buf;
2518 p_token = strsep(&p_buf, " \t");
2519 if (p_buf) {
2520 memcpy(tmp, p_buf, strlen(p_buf));
2521 tmp[len] = '\0';
2522 if (!strncmp(tmp, "uplink", 6)) {
2523 qos_dl_toggle = 0;
2524 qos_ul_toggle = 1;
2525 } else if (!strncmp(tmp, "downlink", 8)) {
2526 qos_ul_toggle = 0;
2527 qos_dl_toggle = 1;
2528 } else {
2529 pr_info("Direction should be uplink or downlink.\n");
2530 hnat_qos_toggle_usage();
2531 return len;
2532 }
2533 } else {
2534 qos_ul_toggle = 1;
2535 qos_dl_toggle = 1;
2536 }
2537 pr_info("HQoS mode is going to be enabled!\n");
2538 pr_info("HQoS uplink is going to be %s!\n",
2539 qos_ul_toggle ? "enabled" : "disabled");
2540 pr_info("HQoS downlink is going to be %s!\n",
2541 qos_dl_toggle ? "enabled" : "disabled");
developeraf07fad2021-11-19 17:53:42 +08002542 qos_toggle = 1;
developer24948202021-11-24 17:38:27 +08002543 } else if (buf[0] == '2') {
developer47545a32022-11-15 16:06:58 +08002544 pr_info("Per-port-per-queue mode is going to be enabled!\n");
developerafff5662022-06-29 10:09:56 +08002545 pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
developeraf07fad2021-11-19 17:53:42 +08002546 qos_toggle = 2;
developer934756a2022-11-18 14:51:34 +08002547 qos_dl_toggle = 1;
2548 qos_ul_toggle = 1;
developer24948202021-11-24 17:38:27 +08002549 hnat_qos_pppq_enable();
developer47545a32022-11-15 16:06:58 +08002550 } else if (buf[0] == '3') {
2551 hnat_qos_toggle_usage();
2552 } else {
2553 pr_info("Input error!\n");
2554 hnat_qos_toggle_usage();
developeraf07fad2021-11-19 17:53:42 +08002555 }
2556
2557 return len;
2558}
2559
2560static const struct file_operations hnat_qos_toggle_fops = {
2561 .open = hnat_qos_toggle_open,
2562 .read = seq_read,
2563 .llseek = seq_lseek,
2564 .write = hnat_qos_toggle_write,
2565 .release = single_release,
2566};
2567
developerfd40db22021-04-29 10:08:25 +08002568static int hnat_version_read(struct seq_file *m, void *private)
2569{
2570 pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
2571
2572 return 0;
2573}
2574
2575static int hnat_version_open(struct inode *inode, struct file *file)
2576{
2577 return single_open(file, hnat_version_read, file->private_data);
2578}
2579
2580static const struct file_operations hnat_version_fops = {
2581 .open = hnat_version_open,
2582 .read = seq_read,
2583 .llseek = seq_lseek,
2584 .release = single_release,
2585};
2586
developeraeafc442022-10-14 09:10:50 +08002587static u32 hnat_get_ppe_hash(u32 sip, u32 dip, u32 sport, u32 dport)
2588{
2589 u32 hv1 = sport << 16 | dport;
2590 u32 hv2 = dip;
2591 u32 hv3 = sip;
2592 u32 hash;
2593
2594 hash = (hv1 & hv2) | ((~hv1) & hv3);
2595 hash = (hash >> 24) | ((hash & 0xffffff) << 8);
2596 hash ^= hv1 ^ hv2 ^ hv3;
2597 hash ^= hash >> 16;
2598 hash <<= 2;
2599 hash &= hnat_priv->foe_etry_num - 1;
2600
2601 return hash;
2602}
2603
2604static u32 hnat_char2hex(const char c)
2605{
2606 switch (c) {
2607 case '0'...'9':
2608 return 0x0 + (c - '0');
2609 case 'a'...'f':
2610 return 0xa + (c - 'a');
2611 case 'A'...'F':
2612 return 0xa + (c - 'A');
2613 default:
2614 pr_info("MAC format error\n");
2615 return 0;
2616 }
2617}
2618
2619static void hnat_parse_mac(char *str, char *mac)
2620{
2621 int i;
2622
2623 for (i = 0; i < ETH_ALEN; i++) {
2624 mac[i] = (hnat_char2hex(str[i * 3]) << 4) +
2625 (hnat_char2hex(str[i * 3 + 1]));
2626 }
2627}
2628
2629static void hnat_static_entry_help(void)
2630{
2631 pr_info("-------------------- Usage --------------------\n");
2632#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2633 pr_info("echo $0 $1 $2 ... $15 > /sys/kernel/debug/hnat/static_entry\n\n");
2634#else
2635 pr_info("echo $0 $1 $2 ... $12 > /sys/kernel/debug/hnat/static_entry\n\n");
2636#endif
2637
2638 pr_info("-------------------- Parameters --------------------\n");
2639 pr_info("$0: HASH OCT\n");
2640 pr_info("$1: INFO1 HEX\n");
2641 pr_info("$2: ING SIPv4 HEX\n");
2642 pr_info("$3: ING DIPv4 HEX\n");
2643 pr_info("$4: ING SP HEX\n");
2644 pr_info("$5: ING DP HEX\n");
2645 pr_info("$6: INFO2 HEX\n");
2646 pr_info("$7: EG SIPv4 HEX\n");
2647 pr_info("$8: EG DIPv4 HEX\n");
2648 pr_info("$9: EG SP HEX\n");
2649 pr_info("$10: EG DP HEX\n");
2650 pr_info("$11: DMAC STR (00:11:22:33:44:55)\n");
2651 pr_info("$12: SMAC STR (00:11:22:33:44:55)\n");
2652#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2653 pr_info("$13: TPORT IDX HEX\n");
2654 pr_info("$14: TOPS ENTRY HEX\n");
2655 pr_info("$15: CDRT IDX HEX\n");
2656#endif
2657}
2658
2659static int hnat_static_entry_read(struct seq_file *m, void *private)
2660{
2661 hnat_static_entry_help();
2662
2663 return 0;
2664}
2665
2666static int hnat_static_entry_open(struct inode *inode, struct file *file)
2667{
2668 return single_open(file, hnat_static_entry_read, file->private_data);
2669}
2670
2671static ssize_t hnat_static_entry_write(struct file *file,
2672 const char __user *buffer,
2673 size_t count, loff_t *data)
2674{
2675 struct foe_entry *foe, entry = { 0 };
2676 char buf[256], dmac_str[18], smac_str[18], dmac[6], smac[6];
2677 int len = count, hash, coll = 0;
2678 u32 ppe_id = 0;
2679#if defined(CONFIG_MEDIATEK_NETSYS_V3)
2680 u32 tport_id, tops_entry, cdrt_id;
2681#endif
2682
2683 if (len >= sizeof(buf) || copy_from_user(buf, buffer, len)) {
2684 pr_info("Input handling fail!\n");
2685 len = sizeof(buf) - 1;
2686 return -EFAULT;
2687 }
2688
2689 buf[len] = '\0';
2690#if defined(CONFIG_MEDIATEK_NETSYS_V3)
developer577ad2f2022-11-28 10:33:36 +08002691 if (sscanf(buf, "%d %x %x %x %hx %hx %x %x %x %hx %hx %s %s %x %x %x",
2692 &hash,
2693 &entry.ipv4_hnapt.info_blk1,
2694 &entry.ipv4_hnapt.sip,
2695 &entry.ipv4_hnapt.dip,
2696 &entry.ipv4_hnapt.sport,
2697 &entry.ipv4_hnapt.dport,
2698 &entry.ipv4_hnapt.info_blk2,
2699 &entry.ipv4_hnapt.new_sip,
2700 &entry.ipv4_hnapt.new_dip,
2701 &entry.ipv4_hnapt.new_sport,
2702 &entry.ipv4_hnapt.new_dport,
2703 dmac_str, smac_str, &tport_id, &tops_entry, &cdrt_id) != 16)
2704 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002705
2706 entry.ipv4_hnapt.tport_id = tport_id;
2707 entry.ipv4_hnapt.tops_entry = tops_entry;
2708 entry.ipv4_hnapt.cdrt_id = cdrt_id;
2709
developer577ad2f2022-11-28 10:33:36 +08002710 if ((hash >= hnat_priv->foe_etry_num) || (hash < -1) ||
developeraeafc442022-10-14 09:10:50 +08002711 (tport_id > 16) || (tport_id < 0) ||
2712 (tops_entry > 64) || (tops_entry < 0) ||
2713 (cdrt_id > 255) || (cdrt_id < 0) ||
2714 (entry.ipv4_hnapt.sport > 65535) ||
2715 (entry.ipv4_hnapt.sport < 0) ||
2716 (entry.ipv4_hnapt.dport > 65535) ||
2717 (entry.ipv4_hnapt.dport < 0) ||
2718 (entry.ipv4_hnapt.new_sport > 65535) ||
2719 (entry.ipv4_hnapt.new_sport < 0) ||
2720 (entry.ipv4_hnapt.new_dport > 65535) ||
2721 (entry.ipv4_hnapt.new_dport < 0)) {
2722 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002723 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002724 }
2725#else
developer577ad2f2022-11-28 10:33:36 +08002726 if (sscanf(buf, "%d %x %x %x %hx %hx %x %x %x %hx %hx %s %s",
2727 &hash,
2728 &entry.ipv4_hnapt.info_blk1,
2729 &entry.ipv4_hnapt.sip,
2730 &entry.ipv4_hnapt.dip,
2731 &entry.ipv4_hnapt.sport,
2732 &entry.ipv4_hnapt.dport,
2733 &entry.ipv4_hnapt.info_blk2,
2734 &entry.ipv4_hnapt.new_sip,
2735 &entry.ipv4_hnapt.new_dip,
2736 &entry.ipv4_hnapt.new_sport,
2737 &entry.ipv4_hnapt.new_dport,
2738 dmac_str, smac_str) != 13)
2739 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002740
developer577ad2f2022-11-28 10:33:36 +08002741 if ((hash >= hnat_priv->foe_etry_num) || (hash < -1) ||
developeraeafc442022-10-14 09:10:50 +08002742 (entry.ipv4_hnapt.sport > 65535) ||
2743 (entry.ipv4_hnapt.sport < 0) ||
2744 (entry.ipv4_hnapt.dport > 65535) ||
2745 (entry.ipv4_hnapt.dport < 0) ||
2746 (entry.ipv4_hnapt.new_sport > 65535) ||
2747 (entry.ipv4_hnapt.new_sport < 0) ||
2748 (entry.ipv4_hnapt.new_dport > 65535) ||
2749 (entry.ipv4_hnapt.new_dport < 0)) {
2750 hnat_static_entry_help();
developer577ad2f2022-11-28 10:33:36 +08002751 return -EFAULT;
developeraeafc442022-10-14 09:10:50 +08002752 }
2753#endif
2754
2755 hnat_parse_mac(smac_str, smac);
2756 hnat_parse_mac(dmac_str, dmac);
2757 entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)dmac));
2758 entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&dmac[4]));
2759 entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)smac));
2760 entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&smac[4]));
2761
2762 if (hash == -1) {
2763 hash = hnat_get_ppe_hash(entry.ipv4_hnapt.sip,
2764 entry.ipv4_hnapt.dip,
2765 entry.ipv4_hnapt.sport,
2766 entry.ipv4_hnapt.dport);
2767 }
2768
2769 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
2770 while ((foe->ipv4_hnapt.bfib1.state == BIND) && (coll < 4)) {
2771 hash++;
2772 coll++;
2773 foe = &hnat_priv->foe_table_cpu[ppe_id][hash];
2774 };
2775 memcpy(foe, &entry, sizeof(entry));
2776
2777 debug_level = 7;
2778 entry_detail(ppe_id, hash);
2779
2780 return len;
2781}
2782
2783static const struct file_operations hnat_static_fops = {
2784 .open = hnat_static_entry_open,
2785 .read = seq_read,
2786 .llseek = seq_lseek,
2787 .write = hnat_static_entry_write,
2788 .release = single_release,
2789};
2790
developer4c32b7a2021-11-13 16:46:43 +08002791int get_ppe_mib(u32 ppe_id, int index, u64 *pkt_cnt, u64 *byte_cnt)
developerfd40db22021-04-29 10:08:25 +08002792{
2793 struct mtk_hnat *h = hnat_priv;
developer30a47682021-11-02 17:06:14 +08002794 struct hnat_accounting *acct;
developerfd40db22021-04-29 10:08:25 +08002795 struct foe_entry *entry;
2796
developer471f6562021-05-10 20:48:34 +08002797 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08002798 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08002799
developerc6227322021-07-09 10:52:53 +08002800 if (index < 0 || index >= h->foe_etry_num) {
2801 pr_info("Invalid entry index\n");
2802 return -EINVAL;
2803 }
2804
developer30a47682021-11-02 17:06:14 +08002805 acct = hnat_get_count(h, ppe_id, index, NULL);
developer471f6562021-05-10 20:48:34 +08002806 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08002807
developer30a47682021-11-02 17:06:14 +08002808 if (!acct)
developerfd40db22021-04-29 10:08:25 +08002809 return -1;
2810
2811 if (entry->bfib1.state != BIND)
2812 return -1;
2813
developer30a47682021-11-02 17:06:14 +08002814 *pkt_cnt = acct->packets;
2815 *byte_cnt = acct->bytes;
developerfd40db22021-04-29 10:08:25 +08002816
2817 return 0;
2818}
2819EXPORT_SYMBOL(get_ppe_mib);
2820
developer4c32b7a2021-11-13 16:46:43 +08002821int is_entry_binding(u32 ppe_id, int index)
developerfd40db22021-04-29 10:08:25 +08002822{
developer580e6fd2021-07-11 09:55:20 +08002823 struct mtk_hnat *h = hnat_priv;
developerfd40db22021-04-29 10:08:25 +08002824 struct foe_entry *entry;
2825
developer471f6562021-05-10 20:48:34 +08002826 if (ppe_id >= CFG_PPE_NUM)
developer4c32b7a2021-11-13 16:46:43 +08002827 return -EINVAL;
developer471f6562021-05-10 20:48:34 +08002828
developerc6227322021-07-09 10:52:53 +08002829 if (index < 0 || index >= h->foe_etry_num) {
2830 pr_info("Invalid entry index\n");
2831 return -EINVAL;
2832 }
2833
developer471f6562021-05-10 20:48:34 +08002834 entry = hnat_priv->foe_table_cpu[ppe_id] + index;
developerfd40db22021-04-29 10:08:25 +08002835
2836 return entry->bfib1.state == BIND;
2837}
2838EXPORT_SYMBOL(is_entry_binding);
2839
2840#define dump_register(nm) \
2841 { \
2842 .name = __stringify(nm), .offset = PPE_##nm, \
2843 }
2844
2845static const struct debugfs_reg32 hnat_regs[] = {
2846 dump_register(GLO_CFG), dump_register(FLOW_CFG),
2847 dump_register(IP_PROT_CHK), dump_register(IP_PROT_0),
2848 dump_register(IP_PROT_1), dump_register(IP_PROT_2),
2849 dump_register(IP_PROT_3), dump_register(TB_CFG),
2850 dump_register(TB_BASE), dump_register(TB_USED),
2851 dump_register(BNDR), dump_register(BIND_LMT_0),
2852 dump_register(BIND_LMT_1), dump_register(KA),
2853 dump_register(UNB_AGE), dump_register(BND_AGE_0),
2854 dump_register(BND_AGE_1), dump_register(HASH_SEED),
2855 dump_register(DFT_CPORT), dump_register(MCAST_PPSE),
2856 dump_register(MCAST_L_0), dump_register(MCAST_H_0),
2857 dump_register(MCAST_L_1), dump_register(MCAST_H_1),
2858 dump_register(MCAST_L_2), dump_register(MCAST_H_2),
2859 dump_register(MCAST_L_3), dump_register(MCAST_H_3),
2860 dump_register(MCAST_L_4), dump_register(MCAST_H_4),
2861 dump_register(MCAST_L_5), dump_register(MCAST_H_5),
2862 dump_register(MCAST_L_6), dump_register(MCAST_H_6),
2863 dump_register(MCAST_L_7), dump_register(MCAST_H_7),
2864 dump_register(MCAST_L_8), dump_register(MCAST_H_8),
2865 dump_register(MCAST_L_9), dump_register(MCAST_H_9),
2866 dump_register(MCAST_L_A), dump_register(MCAST_H_A),
2867 dump_register(MCAST_L_B), dump_register(MCAST_H_B),
2868 dump_register(MCAST_L_C), dump_register(MCAST_H_C),
2869 dump_register(MCAST_L_D), dump_register(MCAST_H_D),
2870 dump_register(MCAST_L_E), dump_register(MCAST_H_E),
2871 dump_register(MCAST_L_F), dump_register(MCAST_H_F),
2872 dump_register(MTU_DRP), dump_register(MTU_VLYR_0),
2873 dump_register(MTU_VLYR_1), dump_register(MTU_VLYR_2),
2874 dump_register(VPM_TPID), dump_register(VPM_TPID),
2875 dump_register(CAH_CTRL), dump_register(CAH_TAG_SRH),
2876 dump_register(CAH_LINE_RW), dump_register(CAH_WDATA),
2877 dump_register(CAH_RDATA),
2878};
2879
2880int hnat_init_debugfs(struct mtk_hnat *h)
2881{
2882 int ret = 0;
2883 struct dentry *root;
2884 struct dentry *file;
2885 long i;
2886 char name[16];
2887
2888 root = debugfs_create_dir("hnat", NULL);
2889 if (!root) {
2890 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2891 ret = -ENOMEM;
2892 goto err0;
2893 }
2894 h->root = root;
developerfd40db22021-04-29 10:08:25 +08002895
developer471f6562021-05-10 20:48:34 +08002896 for (i = 0; i < CFG_PPE_NUM; i++) {
2897 h->regset[i] = kzalloc(sizeof(*h->regset[i]), GFP_KERNEL);
2898 if (!h->regset[i]) {
2899 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2900 ret = -ENOMEM;
2901 goto err1;
2902 }
2903 h->regset[i]->regs = hnat_regs;
2904 h->regset[i]->nregs = ARRAY_SIZE(hnat_regs);
2905 h->regset[i]->base = h->ppe_base[i];
2906
developer577ad2f2022-11-28 10:33:36 +08002907 ret = snprintf(name, sizeof(name), "regdump%ld", i);
2908 if (ret != strlen(name)) {
2909 ret = -ENOMEM;
2910 goto err1;
2911 }
developeraeafc442022-10-14 09:10:50 +08002912 file = debugfs_create_regset32(name, 0444,
developer471f6562021-05-10 20:48:34 +08002913 root, h->regset[i]);
2914 if (!file) {
2915 dev_notice(h->dev, "%s:err at %d\n", __func__, __LINE__);
2916 ret = -ENOMEM;
2917 goto err1;
2918 }
developerfd40db22021-04-29 10:08:25 +08002919 }
developer471f6562021-05-10 20:48:34 +08002920
developeraeafc442022-10-14 09:10:50 +08002921 debugfs_create_file("all_entry", 0444, root, h, &hnat_debug_fops);
2922 debugfs_create_file("external_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002923 &hnat_ext_fops);
developeraeafc442022-10-14 09:10:50 +08002924 debugfs_create_file("whnat_interface", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002925 &hnat_whnat_fops);
developeraeafc442022-10-14 09:10:50 +08002926 debugfs_create_file("cpu_reason", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002927 &cpu_reason_fops);
developeraeafc442022-10-14 09:10:50 +08002928 debugfs_create_file("hnat_entry", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002929 &hnat_entry_fops);
developeraeafc442022-10-14 09:10:50 +08002930 debugfs_create_file("hnat_setting", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002931 &hnat_setting_fops);
developeraeafc442022-10-14 09:10:50 +08002932 debugfs_create_file("mcast_table", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002933 &hnat_mcast_fops);
developeraeafc442022-10-14 09:10:50 +08002934 debugfs_create_file("hook_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002935 &hnat_hook_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002936 debugfs_create_file("mape_toggle", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002937 &hnat_mape_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002938 debugfs_create_file("qos_toggle", 0444, root, h,
developeraf07fad2021-11-19 17:53:42 +08002939 &hnat_qos_toggle_fops);
developeraeafc442022-10-14 09:10:50 +08002940 debugfs_create_file("hnat_version", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002941 &hnat_version_fops);
developeraeafc442022-10-14 09:10:50 +08002942 debugfs_create_file("hnat_ppd_if", 0444, root, h,
developerfd40db22021-04-29 10:08:25 +08002943 &hnat_ppd_if_fops);
developeraeafc442022-10-14 09:10:50 +08002944 debugfs_create_file("static_entry", 0444, root, h,
2945 &hnat_static_fops);
developerfd40db22021-04-29 10:08:25 +08002946
2947 for (i = 0; i < hnat_priv->data->num_of_sch; i++) {
developer577ad2f2022-11-28 10:33:36 +08002948 ret = snprintf(name, sizeof(name), "qdma_sch%ld", i);
2949 if (ret != strlen(name)) {
2950 ret = -ENOMEM;
2951 goto err1;
2952 }
developeraeafc442022-10-14 09:10:50 +08002953 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08002954 &hnat_sched_fops);
2955 }
2956
2957 for (i = 0; i < MTK_QDMA_TX_NUM; i++) {
developer577ad2f2022-11-28 10:33:36 +08002958 ret = snprintf(name, sizeof(name), "qdma_txq%ld", i);
2959 if (ret != strlen(name)) {
2960 ret = -ENOMEM;
2961 goto err1;
2962 }
developeraeafc442022-10-14 09:10:50 +08002963 debugfs_create_file(name, 0444, root, (void *)i,
developerfd40db22021-04-29 10:08:25 +08002964 &hnat_queue_fops);
2965 }
2966
2967 return 0;
2968
2969err1:
2970 debugfs_remove_recursive(root);
2971err0:
2972 return ret;
2973}
2974
2975void hnat_deinit_debugfs(struct mtk_hnat *h)
2976{
developer4c32b7a2021-11-13 16:46:43 +08002977 int i;
2978
developerfd40db22021-04-29 10:08:25 +08002979 debugfs_remove_recursive(h->root);
2980 h->root = NULL;
developer4c32b7a2021-11-13 16:46:43 +08002981
2982 for (i = 0; i < CFG_PPE_NUM; i++)
2983 kfree(h->regset[i]);
developerfd40db22021-04-29 10:08:25 +08002984}