Linux Audio

Check our new training course

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