Search code examples
ebpfbpfxdp-bpfxdp-ebpflibbpf

Unable to fetch data using bpf_map_lookup_elem()


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

Solution

  • 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.