Как я могу использовать определения enum tcp mib в программе kprobe?

#tcp #mib #kprobe #bcc-bpf

#tcp #МиБ #kprobe #bcc-bpf

Вопрос:

Здесь я попытался написать программу (kprobe) для включения enum tcp mib, например @tcp_states, в книге BPF Performance Tools bpftrace. Перечисляемый mib tcp находится в / 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: %dn", comm, pid);
        printf("n");
        printf("$ib: %un", $ib->miss[6]);

        $mib_s = $ib->mibs[TCP_MIB_MAX];
        $mib_str = @mib[$mib_s];

        printf("TCP mib is: %sn", $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?

Ответ №1:

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];
};
  

(включить /uapi/linux/snmp.h и включить /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 ? Итак, если счетчик равен 10 кб, вы пытаетесь взять 10000-ю ячейку массива размером 16? Я полагаю, в вашем случае значение равно 0, поэтому вы делаете $mib_str = @mib[0] , что, вероятно, является пустой строкой, потому что вы никогда не устанавливали значение @mib[0] .

Чтобы исправить все это, я бы начал с использования правильных индексов (от 0 до 15) для @mib массива, чтобы избежать путаницы. Тогда вам, вероятно, нужно переосмыслить то, что вы пытаетесь точно напечатать, но я не уверен, что две строки выше — это то, что вы хотите.