Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
0003 
0004 #include <linux/kernel.h>
0005 #include <linux/debugfs.h>
0006 #include "mtk_eth_soc.h"
0007 
0008 struct mtk_flow_addr_info
0009 {
0010     void *src, *dest;
0011     u16 *src_port, *dest_port;
0012     bool ipv6;
0013 };
0014 
0015 static const char *mtk_foe_entry_state_str(int state)
0016 {
0017     static const char * const state_str[] = {
0018         [MTK_FOE_STATE_INVALID] = "INV",
0019         [MTK_FOE_STATE_UNBIND] = "UNB",
0020         [MTK_FOE_STATE_BIND] = "BND",
0021         [MTK_FOE_STATE_FIN] = "FIN",
0022     };
0023 
0024     if (state >= ARRAY_SIZE(state_str) || !state_str[state])
0025         return "UNK";
0026 
0027     return state_str[state];
0028 }
0029 
0030 static const char *mtk_foe_pkt_type_str(int type)
0031 {
0032     static const char * const type_str[] = {
0033         [MTK_PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T",
0034         [MTK_PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T",
0035         [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
0036         [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
0037         [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
0038         [MTK_PPE_PKT_TYPE_IPV6_6RD] = "6RD",
0039     };
0040 
0041     if (type >= ARRAY_SIZE(type_str) || !type_str[type])
0042         return "UNKNOWN";
0043 
0044     return type_str[type];
0045 }
0046 
0047 static void
0048 mtk_print_addr(struct seq_file *m, u32 *addr, bool ipv6)
0049 {
0050     u32 n_addr[4];
0051     int i;
0052 
0053     if (!ipv6) {
0054         seq_printf(m, "%pI4h", addr);
0055         return;
0056     }
0057 
0058     for (i = 0; i < ARRAY_SIZE(n_addr); i++)
0059         n_addr[i] = htonl(addr[i]);
0060     seq_printf(m, "%pI6", n_addr);
0061 }
0062 
0063 static void
0064 mtk_print_addr_info(struct seq_file *m, struct mtk_flow_addr_info *ai)
0065 {
0066     mtk_print_addr(m, ai->src, ai->ipv6);
0067     if (ai->src_port)
0068         seq_printf(m, ":%d", *ai->src_port);
0069     seq_printf(m, "->");
0070     mtk_print_addr(m, ai->dest, ai->ipv6);
0071     if (ai->dest_port)
0072         seq_printf(m, ":%d", *ai->dest_port);
0073 }
0074 
0075 static int
0076 mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
0077 {
0078     struct mtk_ppe *ppe = m->private;
0079     int i;
0080 
0081     for (i = 0; i < MTK_PPE_ENTRIES; i++) {
0082         struct mtk_foe_entry *entry = &ppe->foe_table[i];
0083         struct mtk_foe_mac_info *l2;
0084         struct mtk_flow_addr_info ai = {};
0085         unsigned char h_source[ETH_ALEN];
0086         unsigned char h_dest[ETH_ALEN];
0087         int type, state;
0088         u32 ib2;
0089 
0090 
0091         state = FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1);
0092         if (!state)
0093             continue;
0094 
0095         if (bind && state != MTK_FOE_STATE_BIND)
0096             continue;
0097 
0098         type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
0099         seq_printf(m, "%05x %s %7s", i,
0100                mtk_foe_entry_state_str(state),
0101                mtk_foe_pkt_type_str(type));
0102 
0103         switch (type) {
0104         case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
0105         case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
0106             ai.src_port = &entry->ipv4.orig.src_port;
0107             ai.dest_port = &entry->ipv4.orig.dest_port;
0108             fallthrough;
0109         case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
0110             ai.src = &entry->ipv4.orig.src_ip;
0111             ai.dest = &entry->ipv4.orig.dest_ip;
0112             break;
0113         case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T:
0114             ai.src_port = &entry->ipv6.src_port;
0115             ai.dest_port = &entry->ipv6.dest_port;
0116             fallthrough;
0117         case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T:
0118         case MTK_PPE_PKT_TYPE_IPV6_6RD:
0119             ai.src = &entry->ipv6.src_ip;
0120             ai.dest = &entry->ipv6.dest_ip;
0121             ai.ipv6 = true;
0122             break;
0123         }
0124 
0125         seq_printf(m, " orig=");
0126         mtk_print_addr_info(m, &ai);
0127 
0128         switch (type) {
0129         case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
0130         case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
0131             ai.src_port = &entry->ipv4.new.src_port;
0132             ai.dest_port = &entry->ipv4.new.dest_port;
0133             fallthrough;
0134         case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
0135             ai.src = &entry->ipv4.new.src_ip;
0136             ai.dest = &entry->ipv4.new.dest_ip;
0137             seq_printf(m, " new=");
0138             mtk_print_addr_info(m, &ai);
0139             break;
0140         }
0141 
0142         if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) {
0143             l2 = &entry->ipv6.l2;
0144             ib2 = entry->ipv6.ib2;
0145         } else {
0146             l2 = &entry->ipv4.l2;
0147             ib2 = entry->ipv4.ib2;
0148         }
0149 
0150         *((__be32 *)h_source) = htonl(l2->src_mac_hi);
0151         *((__be16 *)&h_source[4]) = htons(l2->src_mac_lo);
0152         *((__be32 *)h_dest) = htonl(l2->dest_mac_hi);
0153         *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
0154 
0155         seq_printf(m, " eth=%pM->%pM etype=%04x"
0156                   " vlan=%d,%d ib1=%08x ib2=%08x\n",
0157                h_source, h_dest, ntohs(l2->etype),
0158                l2->vlan1, l2->vlan2, entry->ib1, ib2);
0159     }
0160 
0161     return 0;
0162 }
0163 
0164 static int
0165 mtk_ppe_debugfs_foe_show_all(struct seq_file *m, void *private)
0166 {
0167     return mtk_ppe_debugfs_foe_show(m, private, false);
0168 }
0169 
0170 static int
0171 mtk_ppe_debugfs_foe_show_bind(struct seq_file *m, void *private)
0172 {
0173     return mtk_ppe_debugfs_foe_show(m, private, true);
0174 }
0175 
0176 static int
0177 mtk_ppe_debugfs_foe_open_all(struct inode *inode, struct file *file)
0178 {
0179     return single_open(file, mtk_ppe_debugfs_foe_show_all,
0180                inode->i_private);
0181 }
0182 
0183 static int
0184 mtk_ppe_debugfs_foe_open_bind(struct inode *inode, struct file *file)
0185 {
0186     return single_open(file, mtk_ppe_debugfs_foe_show_bind,
0187                inode->i_private);
0188 }
0189 
0190 int mtk_ppe_debugfs_init(struct mtk_ppe *ppe)
0191 {
0192     static const struct file_operations fops_all = {
0193         .open = mtk_ppe_debugfs_foe_open_all,
0194         .read = seq_read,
0195         .llseek = seq_lseek,
0196         .release = single_release,
0197     };
0198 
0199     static const struct file_operations fops_bind = {
0200         .open = mtk_ppe_debugfs_foe_open_bind,
0201         .read = seq_read,
0202         .llseek = seq_lseek,
0203         .release = single_release,
0204     };
0205 
0206     struct dentry *root;
0207 
0208     root = debugfs_create_dir("mtk_ppe", NULL);
0209     debugfs_create_file("entries", S_IRUGO, root, ppe, &fops_all);
0210     debugfs_create_file("bind", S_IRUGO, root, ppe, &fops_bind);
0211 
0212     return 0;
0213 }