0

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

byrnesj1
  • 189
  • 1
  • 14
  • 2
    When using bcc, you can write to maps by writing into the BPF map like you would for a regular Python data structure. I'm not sure for the type part though; BPF doesn't have any specific support for floats (no floating-point arithmetic is allowed) or 128-bit integers. You can find an example of the BPF map writing from Python [here](https://github.com/iovisor/bcc/blob/d2e8ea47352e36f63a9dda281c00fadeb87e890a/examples/networking/dns_matching/dns_matching.py#L68). – pchaigno Apr 23 '20 at 17:21
  • Thanks for your input, and sorry for the confusion on the key -- it shouldve been char[16] as this is the structure of comm. I don't know why I put u128. Regarding floating-point arithetmic, for my example all the values will be weights (in range of [0,1]), so I can treat the numbers as X / 10^d, and simply do arithmetic on X. That link was what I needed -- thanks! – byrnesj1 Apr 23 '20 at 17:48

1 Answers1

0

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))
byrnesj1
  • 189
  • 1
  • 14