File Index
Files and directories
Sign in
FILE

airoha_ppe_debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2025 AIROHA Inc
  4 * Author: Lorenzo Bianconi <lorenzo@kernel.org>
  5 */
  6
  7#include "airoha_eth.h"
  8
  9static void airoha_debugfs_ppe_print_tuple(struct seq_file *m,
 10					   void *src_addr, void *dest_addr,
 11					   u16 *src_port, u16 *dest_port,
 12					   bool ipv6)
 13{
 14	__be32 n_addr[IPV6_ADDR_WORDS];
 15
 16	if (ipv6) {
 17		ipv6_addr_cpu_to_be32(n_addr, src_addr);
 18		seq_printf(m, "%pI6", n_addr);
 19	} else {
 20		seq_printf(m, "%pI4h", src_addr);
 21	}
 22	if (src_port)
 23		seq_printf(m, ":%d", *src_port);
 24
 25	seq_puts(m, "->");
 26
 27	if (ipv6) {
 28		ipv6_addr_cpu_to_be32(n_addr, dest_addr);
 29		seq_printf(m, "%pI6", n_addr);
 30	} else {
 31		seq_printf(m, "%pI4h", dest_addr);
 32	}
 33	if (dest_port)
 34		seq_printf(m, ":%d", *dest_port);
 35}
 36
 37static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
 38				       bool bind)
 39{
 40	static const char *const ppe_type_str[] = {
 41		[PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T",
 42		[PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T",
 43		[PPE_PKT_TYPE_BRIDGE] = "L2B",
 44		[PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
 45		[PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
 46		[PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
 47		[PPE_PKT_TYPE_IPV6_6RD] = "6RD",
 48	};
 49	static const char *const ppe_state_str[] = {
 50		[AIROHA_FOE_STATE_INVALID] = "INV",
 51		[AIROHA_FOE_STATE_UNBIND] = "UNB",
 52		[AIROHA_FOE_STATE_BIND] = "BND",
 53		[AIROHA_FOE_STATE_FIN] = "FIN",
 54	};
 55	struct airoha_ppe *ppe = m->private;
 56	u32 ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
 57	int i;
 58
 59	for (i = 0; i < ppe_num_entries; i++) {
 60		const char *state_str, *type_str = "UNKNOWN";
 61		void *src_addr = NULL, *dest_addr = NULL;
 62		u16 *src_port = NULL, *dest_port = NULL;
 63		struct airoha_foe_mac_info_common *l2;
 64		unsigned char h_source[ETH_ALEN] = {};
 65		struct airoha_foe_stats64 stats = {};
 66		unsigned char h_dest[ETH_ALEN];
 67		struct airoha_foe_entry *hwe;
 68		u32 type, state, ib2, data;
 69		bool ipv6 = false;
 70
 71		hwe = airoha_ppe_foe_get_entry(ppe, i);
 72		if (!hwe)
 73			continue;
 74
 75		state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
 76		if (!state)
 77			continue;
 78
 79		if (bind && state != AIROHA_FOE_STATE_BIND)
 80			continue;
 81
 82		state_str = ppe_state_str[state % ARRAY_SIZE(ppe_state_str)];
 83		type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
 84		if (type < ARRAY_SIZE(ppe_type_str) && ppe_type_str[type])
 85			type_str = ppe_type_str[type];
 86
 87		seq_printf(m, "%05x %s %7s", i, state_str, type_str);
 88
 89		switch (type) {
 90		case PPE_PKT_TYPE_IPV4_HNAPT:
 91		case PPE_PKT_TYPE_IPV4_DSLITE:
 92			src_port = &hwe->ipv4.orig_tuple.src_port;
 93			dest_port = &hwe->ipv4.orig_tuple.dest_port;
 94			fallthrough;
 95		case PPE_PKT_TYPE_IPV4_ROUTE:
 96			src_addr = &hwe->ipv4.orig_tuple.src_ip;
 97			dest_addr = &hwe->ipv4.orig_tuple.dest_ip;
 98			break;
 99		case PPE_PKT_TYPE_IPV6_ROUTE_5T:
100			src_port = &hwe->ipv6.src_port;
101			dest_port = &hwe->ipv6.dest_port;
102			fallthrough;
103		case PPE_PKT_TYPE_IPV6_ROUTE_3T:
104		case PPE_PKT_TYPE_IPV6_6RD:
105			src_addr = &hwe->ipv6.src_ip;
106			dest_addr = &hwe->ipv6.dest_ip;
107			ipv6 = true;
108			break;
109		default:
110			break;
111		}
112
113		if (src_addr && dest_addr) {
114			seq_puts(m, " orig=");
115			airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
116						       src_port, dest_port, ipv6);
117		}
118
119		switch (type) {
120		case PPE_PKT_TYPE_IPV4_HNAPT:
121		case PPE_PKT_TYPE_IPV4_DSLITE:
122			src_port = &hwe->ipv4.new_tuple.src_port;
123			dest_port = &hwe->ipv4.new_tuple.dest_port;
124			fallthrough;
125		case PPE_PKT_TYPE_IPV4_ROUTE:
126			src_addr = &hwe->ipv4.new_tuple.src_ip;
127			dest_addr = &hwe->ipv4.new_tuple.dest_ip;
128			seq_puts(m, " new=");
129			airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
130						       src_port, dest_port,
131						       ipv6);
132			break;
133		default:
134			break;
135		}
136
137		if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
138			data = hwe->ipv6.data;
139			ib2 = hwe->ipv6.ib2;
140			l2 = &hwe->ipv6.l2;
141		} else {
142			data = hwe->ipv4.data;
143			ib2 = hwe->ipv4.ib2;
144			l2 = &hwe->ipv4.l2.common;
145			*((__be16 *)&h_source[4]) =
146				cpu_to_be16(hwe->ipv4.l2.src_mac_lo);
147		}
148
149		airoha_ppe_foe_entry_get_stats(ppe, i, &stats);
150
151		*((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi);
152		*((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo);
153		*((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi);
154
155		seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x"
156			      " vlan=%d,%d ib1=%08x ib2=%08x"
157			      " packets=%llu bytes=%llu\n",
158			   h_source, h_dest, l2->etype, data,
159			   l2->vlan1, l2->vlan2, hwe->ib1, ib2,
160			   stats.packets, stats.bytes);
161	}
162
163	return 0;
164}
165
166static int airoha_ppe_debugfs_foe_all_show(struct seq_file *m, void *private)
167{
168	return airoha_ppe_debugfs_foe_show(m, private, false);
169}
170DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_all);
171
172static int airoha_ppe_debugfs_foe_bind_show(struct seq_file *m, void *private)
173{
174	return airoha_ppe_debugfs_foe_show(m, private, true);
175}
176DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_bind);
177
178int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
179{
180	ppe->debugfs_dir = debugfs_create_dir("ppe", NULL);
181	debugfs_create_file("entries", 0444, ppe->debugfs_dir, ppe,
182			    &airoha_ppe_debugfs_foe_all_fops);
183	debugfs_create_file("bind", 0444, ppe->debugfs_dir, ppe,
184			    &airoha_ppe_debugfs_foe_bind_fops);
185
186	return 0;
187}
~/ Read-only file preview.