linux/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
<<
>>
Prefs
   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_BRIDGE] = "L2",
  36                [MTK_PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
  37                [MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
  38                [MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
  39                [MTK_PPE_PKT_TYPE_IPV6_6RD] = "6RD",
  40        };
  41
  42        if (type >= ARRAY_SIZE(type_str) || !type_str[type])
  43                return "UNKNOWN";
  44
  45        return type_str[type];
  46}
  47
  48static void
  49mtk_print_addr(struct seq_file *m, u32 *addr, bool ipv6)
  50{
  51        u32 n_addr[4];
  52        int i;
  53
  54        if (!ipv6) {
  55                seq_printf(m, "%pI4h", addr);
  56                return;
  57        }
  58
  59        for (i = 0; i < ARRAY_SIZE(n_addr); i++)
  60                n_addr[i] = htonl(addr[i]);
  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 = &ppe->foe_table[i];
  84                struct mtk_foe_mac_info *l2;
  85                struct mtk_flow_addr_info ai = {};
  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                type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
 100                seq_printf(m, "%05x %s %7s", i,
 101                           mtk_foe_entry_state_str(state),
 102                           mtk_foe_pkt_type_str(type));
 103
 104                switch (type) {
 105                case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
 106                case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
 107                        ai.src_port = &entry->ipv4.orig.src_port;
 108                        ai.dest_port = &entry->ipv4.orig.dest_port;
 109                        fallthrough;
 110                case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
 111                        ai.src = &entry->ipv4.orig.src_ip;
 112                        ai.dest = &entry->ipv4.orig.dest_ip;
 113                        break;
 114                case MTK_PPE_PKT_TYPE_IPV6_ROUTE_5T:
 115                        ai.src_port = &entry->ipv6.src_port;
 116                        ai.dest_port = &entry->ipv6.dest_port;
 117                        fallthrough;
 118                case MTK_PPE_PKT_TYPE_IPV6_ROUTE_3T:
 119                case MTK_PPE_PKT_TYPE_IPV6_6RD:
 120                        ai.src = &entry->ipv6.src_ip;
 121                        ai.dest = &entry->ipv6.dest_ip;
 122                        ai.ipv6 = true;
 123                        break;
 124                }
 125
 126                seq_printf(m, " orig=");
 127                mtk_print_addr_info(m, &ai);
 128
 129                switch (type) {
 130                case MTK_PPE_PKT_TYPE_IPV4_HNAPT:
 131                case MTK_PPE_PKT_TYPE_IPV4_DSLITE:
 132                        ai.src_port = &entry->ipv4.new.src_port;
 133                        ai.dest_port = &entry->ipv4.new.dest_port;
 134                        fallthrough;
 135                case MTK_PPE_PKT_TYPE_IPV4_ROUTE:
 136                        ai.src = &entry->ipv4.new.src_ip;
 137                        ai.dest = &entry->ipv4.new.dest_ip;
 138                        seq_printf(m, " new=");
 139                        mtk_print_addr_info(m, &ai);
 140                        break;
 141                }
 142
 143                if (type >= MTK_PPE_PKT_TYPE_IPV4_DSLITE) {
 144                        l2 = &entry->ipv6.l2;
 145                        ib2 = entry->ipv6.ib2;
 146                } else {
 147                        l2 = &entry->ipv4.l2;
 148                        ib2 = entry->ipv4.ib2;
 149                }
 150
 151                *((__be32 *)h_source) = htonl(l2->src_mac_hi);
 152                *((__be16 *)&h_source[4]) = htons(l2->src_mac_lo);
 153                *((__be32 *)h_dest) = htonl(l2->dest_mac_hi);
 154                *((__be16 *)&h_dest[4]) = htons(l2->dest_mac_lo);
 155
 156                seq_printf(m, " eth=%pM->%pM etype=%04x"
 157                              " vlan=%d,%d ib1=%08x ib2=%08x\n",
 158                           h_source, h_dest, ntohs(l2->etype),
 159                           l2->vlan1, l2->vlan2, entry->ib1, ib2);
 160        }
 161
 162        return 0;
 163}
 164
 165static int
 166mtk_ppe_debugfs_foe_show_all(struct seq_file *m, void *private)
 167{
 168        return mtk_ppe_debugfs_foe_show(m, private, false);
 169}
 170
 171static int
 172mtk_ppe_debugfs_foe_show_bind(struct seq_file *m, void *private)
 173{
 174        return mtk_ppe_debugfs_foe_show(m, private, true);
 175}
 176
 177static int
 178mtk_ppe_debugfs_foe_open_all(struct inode *inode, struct file *file)
 179{
 180        return single_open(file, mtk_ppe_debugfs_foe_show_all,
 181                           inode->i_private);
 182}
 183
 184static int
 185mtk_ppe_debugfs_foe_open_bind(struct inode *inode, struct file *file)
 186{
 187        return single_open(file, mtk_ppe_debugfs_foe_show_bind,
 188                           inode->i_private);
 189}
 190
 191int mtk_ppe_debugfs_init(struct mtk_ppe *ppe)
 192{
 193        static const struct file_operations fops_all = {
 194                .open = mtk_ppe_debugfs_foe_open_all,
 195                .read = seq_read,
 196                .llseek = seq_lseek,
 197                .release = single_release,
 198        };
 199
 200        static const struct file_operations fops_bind = {
 201                .open = mtk_ppe_debugfs_foe_open_bind,
 202                .read = seq_read,
 203                .llseek = seq_lseek,
 204                .release = single_release,
 205        };
 206
 207        struct dentry *root;
 208
 209        root = debugfs_create_dir("mtk_ppe", NULL);
 210        if (!root)
 211                return -ENOMEM;
 212
 213        debugfs_create_file("entries", S_IRUGO, root, ppe, &fops_all);
 214        debugfs_create_file("bind", S_IRUGO, root, ppe, &fops_bind);
 215
 216        return 0;
 217}
 218