How can I use the enum tcp mib definitions in a kprobe program?

116 views Asked by At

Here, I tried to write a program(kprobe) to include the enum tcp mib like @tcp_states in the book BPF Performance Tools bpftrace. The enum tcp mib is in '/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);
}
      

And when I tried to run it the output was:

the index 94779518808448 is out of bounds for array of size 16

Then I tried to instead of TCP_MIB_MAX, to put specific array positions e.g 5, (I modify the above code):

$mib_s = $ib->mibs[5];

And when I tried to run it, the output was:

...

-----------------------------
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:

...

Why does not show TCP mib? and shows nothing in the output? How can I use the array properly to show @mib?

1

There are 1 answers

0
Qeole On

TCP_MIB_MAX and __TCP_MIB_MAX are equal to 16, which is equal to the size of the struct tcp_mib in the kernel:

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

and

#define TCP_MIB_MAX __TCP_MIB_MAX
struct tcp_mib {
    unsigned long   mibs[TCP_MIB_MAX];
};

(include/uapi/linux/snmp.h and include/net/snmp.h)

But because arrays are indexed from 0, you can go only up to TCP_MIB_MAX - 1 when indexing $ib->mibs. This is why you get a complaint about the out-of-bound index.

Then when you select a smaller index, you can access to the array item as expected. But I'm not sure what you are trying to do with:

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

To me it looks like you are reading the value from the MIB ($ib->mibs[TCP_MIB_ACTIVEOPENS]), which may supply any value, possibly big, and likely null (I suspect this is the case here). Then you use that value as... an index in @mib? So if the counter is at 10k, you try to take the 10,000th cell of a 16-sized array? I suppose in your case the value is 0, so you are doing $mib_str = @mib[0], which is likely an empty string because you never set a value for @mib[0].

To fix all of this I would start by using the correct indices (from 0 to 15) for the @mib array, to avoid any confusion. Then you probably need to rethink what you are trying to print exactly, but I'm not sure that the two lines above is what you want.