Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
  3
  4#include <linux/kernel.h>
  5#include <linux/debugfs.h>
  6#include "mtk_eth_soc.h"
  7
  8struct mtk_flow_addr_info
  9{
 10	void *src, *dest;
 11	u16 *src_port, *dest_port;
 12	bool ipv6;
 13};
 14
 15static const char *mtk_foe_entry_state_str(int state)
 16{
 17	static const char * const state_str[] = {
 18		[MTK_FOE_STATE_INVALID] = "INV",
 19		[MTK_FOE_STATE_UNBIND] = "UNB",
 20		[MTK_FOE_STATE_BIND] = "BND",
 21		[MTK_FOE_STATE_FIN] = "FIN",
 22	};
 23
 24	if (state >= ARRAY_SIZE(state_str) || !state_str[state])
 25		return "UNK";
 26
 27	return state_str[state];
 28}
 29
 30static const char *mtk_foe_pkt_type_str(int type)
 31{
 32	static const char * const type_str[] = {
 33		[MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T",
 34		[MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T",
 35		[MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
 36		[MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
 37		[MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
 38		[MTK_PPE_PKT_TYPE_IPV6_6RD] = "6RD",
 39	};
 40
 41	if (type >= ARRAY_SIZE(type_str) || !type_str[type])
 42		return "UNKNOWN";
 43
 44	return type_str[type];
 45}
 46
 47static void
 48mtk_print_addr(struct seq_file *m, u32 *addr, bool ipv6)
 49{
 50	__be32 n_addr[4];
 51	int i;
 52
 53	if (!ipv6) {
 54		seq_printf(m, "%pI4h", addr);
 55		return;
 56	}
 57
 58	for (i = 0; i < ARRAY_SIZE(n_addr); i++)
 59		n_addr[i] = htonl(addr[i]);
 60	seq_printf(m, "%pI6", n_addr);
 61}
 62
 63static void
 64mtk_print_addr_info(struct seq_file *m, struct mtk_flow_addr_info *ai)
 65{
 66	mtk_print_addr(m, ai->src, ai->ipv6);
 67	if (ai->src_port)
 68		seq_printf(m, ":%d", *ai->src_port);
 69	seq_printf(m, "->");
 70	mtk_print_addr(m, ai->dest, ai->ipv6);
 71	if (ai->dest_port)
 72		seq_printf(m, ":%d", *ai->dest_port);
 73}
 74
 75static int
 76mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
 77{
 78	struct mtk_ppe *ppe = m->private;
 79	int i;
 80
 81	for (i = 0; i < MTK_PPE_ENTRIES; i++) {
 82		struct mtk_foe_entry *entry = mtk_foe_get_entry(ppe, i);
 83		struct mtk_foe_mac_info *l2;
 84		struct mtk_flow_addr_info ai = {};
 85		struct mtk_foe_accounting *acct;
 86		unsigned char h_source[ETH_ALEN];
 87		unsigned char h_dest[ETH_ALEN];
 88		int type, state;
 89		u32 ib2;
 90
 91
 92		state = FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1);
 93		if (!state)
 94			continue;
 95
 96		if (bind && state != MTK_FOE_STATE_BIND)
 97			continue;
 98
 99		acct = mtk_foe_entry_get_mib(ppe, i, NULL);
100
101		type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1);
102		seq_printf(m, "%05x %s %7s", i,
103			   mtk_foe_entry_state_str(state),
104			   mtk_foe_pkt_type_str(type));
105
106		switch (type) {
107		case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
108		case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
109			ai.src_port = &entry->ipv4.orig.src_port;
110			ai.dest_port = &entry->ipv4.orig.dest_port;
111			fallthrough;
112		case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
113			ai.src = &entry->ipv4.orig.src_ip;
114			ai.dest = &entry->ipv4.orig.dest_ip;
115			break;
116		case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T:
117			ai.src_port = &entry->ipv6.src_port;
118			ai.dest_port = &entry->ipv6.dest_port;
119			fallthrough;
120		case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T:
121		case MTK_PPE_PKT_TYPE_IPV6_6RD:
122			ai.src = &entry->ipv6.src_ip;
123			ai.dest = &entry->ipv6.dest_ip;
124			ai.ipv6 = true;
125			break;
126		}
127
128		seq_printf(m, " orig=");
129		mtk_print_addr_info(m, &ai);
130
131		switch (type) {
132		case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
133		case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
134			ai.src_port = &entry->ipv4.new.src_port;
135			ai.dest_port = &entry->ipv4.new.dest_port;
136			fallthrough;
137		case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
138			ai.src = &entry->ipv4.new.src_ip;
139			ai.dest = &entry->ipv4.new.dest_ip;
140			seq_printf(m, " new=");
141			mtk_print_addr_info(m, &ai);
142			break;
143		}
144
145		if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) {
146			l2 = &entry->ipv6.l2;
147			ib2 = entry->ipv6.ib2;
148		} else {
149			l2 = &entry->ipv4.l2;
150			ib2 = entry->ipv4.ib2;
151		}
152
153		*((__be32 *)h_source) = htonl(l2->src_mac_hi);
154		*((__be16 *)&h_source[4]) = htons(l2->src_mac_lo);
155		*((__be32 *)h_dest) = htonl(l2->dest_mac_hi);
156		*((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
157
158		seq_printf(m, " eth=%pM->%pM etype=%04x"
159			      " vlan=%d,%d ib1=%08x ib2=%08x"
160			      " packets=%llu bytes=%llu\n",
161			   h_source, h_dest, ntohs(l2->etype),
162			   l2->vlan1, l2->vlan2, entry->ib1, ib2,
163			   acct ? acct->packets : 0, acct ? acct->bytes : 0);
164	}
165
166	return 0;
167}
168
169static int
170mtk_ppe_debugfs_foe_all_show(struct seq_file *m, void *private)
171{
172	return mtk_ppe_debugfs_foe_show(m, private, false);
173}
174DEFINE_SHOW_ATTRIBUTE(mtk_ppe_debugfs_foe_all);
175
176static int
177mtk_ppe_debugfs_foe_bind_show(struct seq_file *m, void *private)
178{
179	return mtk_ppe_debugfs_foe_show(m, private, true);
180}
181DEFINE_SHOW_ATTRIBUTE(mtk_ppe_debugfs_foe_bind);
182
183int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index)
184{
185	struct dentry *root;
186
187	snprintf(ppe->dirname, sizeof(ppe->dirname), "ppe%d", index);
188
189	root = debugfs_create_dir(ppe->dirname, NULL);
190	debugfs_create_file("entries", S_IRUGO, root, ppe, &mtk_ppe_debugfs_foe_all_fops);
191	debugfs_create_file("bind", S_IRUGO, root, ppe, &mtk_ppe_debugfs_foe_bind_fops);
192
193	return 0;
194}