/* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Copyright (C) 2014-2016 Sean Wang * Copyright (C) 2016-2017 John Crispin * Copyright (C) 2020 Felix Fietkau */ #include #include #include "mtk_eth_soc.h" static const char *mtk_foe_entry_state_str[] = { "INVALID", "UNBIND", "BIND", "FIN" }; static const char *mtk_foe_packet_type_str[] = { "IPV4_HNAPT", "IPV4_HNAT", "IPV6_1T_ROUTE", "IPV4_DSLITE", "IPV6_3T_ROUTE", "IPV6_5T_ROUTE", "IPV6_6RD", }; #define es(entry) (mtk_foe_entry_state_str[FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1)]) //#define ei(entry, end) (MTK_PPE_TBL_SZ - (int)(end - entry)) #define pt(entry) (mtk_foe_packet_type_str[FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1)]) static int mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private) { struct mtk_ppe *ppe = m->private; int i, count; for (i = 0, count = 0; i < MTK_PPE_ENTRIES; i++) { struct mtk_foe_entry *entry = &ppe->foe_table[i]; if (!FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1)) continue; if (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1) == MTK_PPE_PKT_TYPE_IPV4_HNAPT) { struct mtk_foe_ipv4 *ip4 = &entry->ipv4; struct mtk_foe_mac_info *l2 = &ip4->l2; __be32 saddr = htonl(ip4->orig.src_ip); __be32 daddr = htonl(ip4->orig.dest_ip); __be32 nsaddr = htonl(ip4->new.src_ip); __be32 ndaddr = htonl(ip4->new.dest_ip); unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; *((__be32 *) h_source) = htonl(l2->src_mac_hi); *((__be16*) &h_source[4]) = htons(l2->src_mac_lo); *((__be32*) h_dest) = htonl(l2->dest_mac_hi); *((__be16*) &h_dest[4]) = htons(l2->dest_mac_lo); seq_printf(m, "(%x)0x%05x|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", count, i, es(entry), pt(entry), &saddr, ip4->orig.src_port, &daddr, ip4->orig.dest_port, &nsaddr, ip4->new.src_port, &ndaddr, ip4->new.dest_port, h_source, h_dest, ntohs(l2->etype), entry->ib1, ip4->ib2, l2->vlan1, l2->vlan2); count++; } else seq_printf(m, "0x%05x state=%s\n", count, es(entry)); } return 0; } static int mtk_ppe_debugfs_foe_open(struct inode *inode, struct file *file) { return single_open(file, mtk_ppe_debugfs_foe_show, inode->i_private); } static const struct file_operations mtk_ppe_debugfs_foe_fops = { .open = mtk_ppe_debugfs_foe_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; int mtk_ppe_debugfs_init(struct mtk_ppe *ppe) { struct dentry *root; root = debugfs_create_dir("mtk_ppe", NULL); if (!root) return -ENOMEM; debugfs_create_file("entries", S_IRUGO, root, ppe, &mtk_ppe_debugfs_foe_fops); return 0; }