问题描述
在这里,我试图编写一个程序(kprobe)以在BPF Performance Tools bpftrace一书中包含枚举tcp mib(如@tcp_states)。枚举tcp mib位于'/include/uapi/linux/snmp.h'中:
#!/usr/local/bin/bpftrace
#include <net/net_namespace.h>
#include <net/netns/mib.h>
#include <net/snmp.h>
#include <uapi/linux/snmp.h>
#define TCP_MIB_MAX __TCP_MIB_MAX
kprobe:sk_alloc
{
$net = (struct net *)arg0;
$mi = (struct netns_mib *)$net->mib;
$ib = (struct tcp_mib *)$mi;
@mib[1] = "TCP_MIB_NUM";
@mib[2] = "TCP_MIB_RTOALGORITHM";
@mib[3] = "TCP_MIB_RTOMIN";
@mib[4] = "TCP_MIB_RTOMAX;
@mib[5] = "TCP_MIB_MAXCONN";
@mib[6] = "TCP_MIB_ACTIVEOPENS";
@mib[7] = "TCP_MIB_PASSIVEOPENS";
@mib[8] = "TCP_MIB_ATTEMPTFAILS";
@mib[9] = "TCP_MIB_ESTABRESETS";
@mib[10] = "TCP_MIB_CURRESTAB";
@mib[11] = "TCP_MIB_INSEGS";
@mib[12] = "TCP_MIB_OUTSEGS";
@mib[13] = "TCP_MIB_RETRANSSEGS";
@mib[14] = "TCP_MIB_INERRS";
@mib[15] = "TCP_MIB_OUTRSTS";
@mib[16] = "TCP_MIB_CSUMERRORS";
printf("-------------------------------\n");
time();
printf("sk_alloc: %s pid: %d\n",comm,pid);
printf("\n");
printf("$ib: %u\n",$ib->miss[6]);
$mib_s = $ib->mibs[TCP_MIB_MAX];
$mib_str = @mib[$mib_s];
printf("TCP mib is: %s\n",$mib_str);
clear(@mib);
}
当我尝试运行它时,输出为:
the index 94779518808448 is out of bounds for array of size 16
然后我尝试代替TCP_MIB_MAX放置特定的数组位置,例如5,(我修改了上面的代码):
$mib_s = $ib->mibs[5];
当我尝试运行它时,输出为:
...
-----------------------------
21:40:15
sk_alloc: systemd-logind pid: 920
$ib: 1516359680
TCP mib is:
-----------------------------
21:40:15
sk_alloc: systemd-logind pid: 920
$ib: 1516359680
TCP mib is:
...
为什么不显示TCP mib?并在输出中什么也不显示? 如何正确使用数组显示@mib?
解决方法
TCP_MIB_MAX
和__TCP_MIB_MAX
等于16,等于内核中struct tcp_mib
的大小:
enum
{
TCP_MIB_NUM = 0,TCP_MIB_RTOALGORITHM,/* RtoAlgorithm */
TCP_MIB_RTOMIN,/* RtoMin */
TCP_MIB_RTOMAX,/* RtoMax */
TCP_MIB_MAXCONN,/* MaxConn */
TCP_MIB_ACTIVEOPENS,/* ActiveOpens */
TCP_MIB_PASSIVEOPENS,/* PassiveOpens */
TCP_MIB_ATTEMPTFAILS,/* AttemptFails */
TCP_MIB_ESTABRESETS,/* EstabResets */
TCP_MIB_CURRESTAB,/* CurrEstab */
TCP_MIB_INSEGS,/* InSegs */
TCP_MIB_OUTSEGS,/* OutSegs */
TCP_MIB_RETRANSSEGS,/* RetransSegs */
TCP_MIB_INERRS,/* InErrs */
TCP_MIB_OUTRSTS,/* OutRsts */
TCP_MIB_CSUMERRORS,/* InCsumErrors */ // == 15
__TCP_MIB_MAX // == 16
};
和
#define TCP_MIB_MAX __TCP_MIB_MAX
struct tcp_mib {
unsigned long mibs[TCP_MIB_MAX];
};
(include / uapi / linux / snmp.h和include / net / snmp.h)
但是,由于数组是从0开始索引的,因此在索引TCP_MIB_MAX - 1
时只能上移到$ib->mibs
。这就是为什么您抱怨越界索引的原因。
然后,当您选择较小的索引时,可以按预期访问数组项。但我不确定您要做什么:
$mib_s = $ib->mibs[5];
$mib_str = @mib[$mib_s];
在我看来,您似乎正在从MIB($ib->mibs[TCP_MIB_ACTIVEOPENS]
)中读取值,该值可能提供任何值,可能很大,并且可能为null(我怀疑这里就是这种情况)。然后您将该值用作...在@mib
中的索引?因此,如果计数器为10k,则尝试获取16个大小的数组的第10,000个单元格?我想在您的情况下,该值为0,所以您正在做$mib_str = @mib[0]
,这很可能是空字符串,因为您从未为@mib[0]
设置值。
要解决所有这些问题,我将从为@mib
数组使用正确的索引(从0到15)开始,以避免任何混乱。然后,您可能需要重新考虑要打印的内容,但是我不确定上面的两行是您想要的。