Search code examples
pythonmapstracebpfbcc-bpf

python interaction with BPF maps


I'm wondering if there is an easy to to initialize BPF maps from python userspace. For my project, I'll have a scary looking NxN 2d array of floats for each process. For simplicity's sake, lets assume N is constant across processes (say 5). To achieve kernel support for this data, I could do something like:

b = BPF(text = """
    typedef struct
    {
        float transMat[5][5];
    } trans_struct;



    BPF_HASH(trans_mapping, char[16], trans_struct);

    .....
""")

I'm wondering if theres an easy way to initialize this map from python. Something like:

for ele in someDictionary:
    #asume someDitionary has mapping (comm -> 5x5 float matrix)
    b["trans_mapping"].insert(ele, someDictionary[ele])

I suppose at the crux of my confusion is -- 1) are all map methods available to the user, 2) how do we ensure type consistenty when going from python objects to c structures


Solution

  • Solution based on pchaigno's comment -- The key things to note are the use of c_types to ensure type consistency across environments, and extracting the table by indexing the BPF program object. Due to our ability to get maps by indexing, the get_table() function is now considered out of date. This format provides the structure of loading data into the map from the python front-end, but doesn't completely conform with the specifics of my question.

    from time import sleep, strftime
    from bcc import BPF
    from bcc.utils import printb
    from bcc.syscall import syscall_name, syscalls
    from ctypes import *
    
    
        b = BPF(text = """
    
        BPF_HASH(start, u32, u64);
    
    
        TRACEPOINT_PROBE(raw_syscalls, sys_exit)
        {
            u32 syscall_id = args->id;
            u32 key = 1;
            u64 *val;
            u32 uid = bpf_get_current_uid_gid();
    
            if (uid == 0)
            {
                val = start.lookup(&key); //find value associated with key 1
                if (val)
                    bpf_trace_printk("Hello world, I have value %d!\\n", *val);
    
            }
            return 0;
        }
        """)
    
        thisStart = b["start"]
        thisStart[c_int(1)] = c_int(9) #insert key-value part 1->9
    
    
        while 1:
            try:
                (task, pid, cpu, flags, ts, msg) = b.trace_fields()
            except KeyboardInterrupt:
                print("Detaching")
                exit()
            print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))