mtk_ppe_debugfs.c 4.8 KB

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