1

I am trying to write a code for XDP where a user space program will populate a bpf map and then later the Kernel will look into the map. For creating the map I have added a SEC(".maps") in the bpf_obj file that will get loaded into the kernel. Regarding this I have a bunch of questions:

  1. If user space is supposed to be the one writing data into the map, should I create the map from the user space itself? Or, the way I am doing currently is ok?
  2. In the user space I have 2 functions. Insert() and Fetch(), which will Insert data into the map and other function will fetch the data from the map respectively. In the Insert() I do bpf_map_update_elem() which will enter the data and in the Fetch() I use bpf_map_lookup_elem() to fetch the data. However, the problem arises in the Fetch() where it is unable to fetch the data. The only workaround I noticed is that, if in the Insert() I do bpf_map_lookup_elem() right after I had done bpf_map_update_elem(), then in the Fetch() I can fetch the data.

Is the bpf_map_lookup_elem() somehow making the data persistent in the map after bpf_map_update_elem() in the Insert()?

Edit: (Here is a snippet of code)

Insert(struct my_key key, struct my_val value){
  map_fd = find_map_fd(bpf_obj, "my_map");
  if(map_fd < 0)
    xdp_link_detach(config.ifindex, config.xdp_flags,0);

  bpf_map_update_elem(map_fd, &key, &value, BPF_ANY);
}

Fetch(struct my_key key){
  struct my_val value;
  map_fd = find_map_fd(bpf_obj, "my_map");
  if(map_fd < 0)
    xdp_link_detach(config.ifindex, config.xdp_flags,0);

  if(bpf_map_lookup_elem(map_fd, &key, &value) == 0)
    printf("Found key");
  else
    printf("Key not found");

}

int main(){
  // Defined key and value
  Insert(key, value);
  Fetch(key);  // This call is failing to fetch
  return 0;
}

However if I change my Insert() then above program works:

Insert(struct my_key key, struct my_val val){
  map_fd = find_map_fd(bpf_obj, "my_map");
  if(map_fd < 0)
    xdp_link_detach(config.ifindex, config.xdp_flags,0);

  bpf_map_update_elem(map_fd, &key, &val, BPF_ANY);

  //Immediately fetch the value
  struct my_val value;
  bpf_map_lookup_elem(map_fd, &key, &value);
  
}
Rishab
  • 73
  • 4
  • 1
    Point 2 is likely a bug in your user space program, please add the source code of your program to the question. Or make an example with the described issue https://stackoverflow.com/help/minimal-reproducible-example – Dylan Reimerink Apr 04 '22 at 10:46
  • 1. Whoever writes to the map, they are always created by a user space process (when you use `SEC(...)`, the user space program you use to load the eBPF programs creates the maps first. It needs them to update the eBPF programs to point to them). 2. Hard to debug with no more context. What error do you get? Did you run `strace` on your program? What happens between your calls to the two functions? Are they from the same process? How do you get a reference to the map from which you want to look up values? – Qeole Apr 04 '22 at 14:54

1 Answers1

2

Actually, I found the issue. I had to change my key definition from:

struct Key {
    uint32_t srcIP;
    uint16_t srcPort;
};

to:

struct Key {
    uint32_t IP;
    uint32_t port;
};

This has something to do with how kernel creates boundaries. It was probably doing some padding to the port that I write. I used strace to look into the bpf calls, where I noticed that the key that I ask for and the key that is written in the bpf_map were off by 32 decimals.

Rishab
  • 73
  • 4