Orange-OpenSource / p4rt-ovs

Programming runtime extensions for Open vSwitch with P4
Apache License 2.0
24 stars 9 forks source link

Segmentation fault in dump-bpf-map #1

Open pchaigno opened 4 years ago

pchaigno commented 4 years ago

I'm getting a segmentation fault when I try to dump the content of the single map of my BPF program:

$ ovs-ofctl dump-bpf-map br0 1 0
Segmentation fault
$ gdb ovs-ofctl
[...]
(gdb) r dump-bpf-map br0 1 0
Starting program: /usr/local/bin/ovs-ofctl dump-bpf-map br0 1 0
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
vconn_transact__ (vconn=0x555555b0d460, request=0x55b0d4b0, replyp=0x7fffffffe318, errors=0x0) at lib/vconn.c:814
814     ovs_be32 send_xid = ((struct ofp_header *) request->data)->xid;
(gdb) bt
#0  vconn_transact__ (vconn=0x555555b0d460, request=0x55b0d4b0, replyp=0x7fffffffe318, errors=0x0) at lib/vconn.c:814
#1  0x00005555555820a9 in ofctl_dump_bpf_map (ctx=<optimized out>) at utilities/ovs-ofctl.c:5179
#2  0x000055555558b2f7 in ovs_cmdl_run_command__ (ctx=0x7fffffffe3c0, commands=<optimized out>, read_only=<optimized out>) at lib/command-line.c:223
#3  0x000055555557a573 in main (argc=<optimized out>, argv=<optimized out>) at utilities/ovs-ofctl.c:180

The BPF program is as follows:

#include <stdint.h>
#include <inttypes.h>
#include <stddef.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

enum bpf_map_type {
    BPF_MAP_TYPE_ARRAY = 1,
    BPF_MAP_TYPE_BLOOMFILTER = 2,
    BPF_MAP_TYPE_COUNTMIN = 3,
    BPF_MAP_TYPE_HASHMAP = 4,
};

struct bpf_map_def {
    enum bpf_map_type type;
    unsigned int key_size;
    unsigned int value_size;
    unsigned int max_entries;
    unsigned int nb_hash_functions;
};

static void *(*ubpf_map_lookup)(const void *, const void *) = (void *)1;
static void *(*ubpf_packet_data)(const void *) = (void *)9;

struct bpf_map_def reg = {
    .type = BPF_MAP_TYPE_HASHMAP,
    .key_size = sizeof(uint16_t),
    .value_size = sizeof(uint32_t),
    .max_entries = 1000,
    .nb_hash_functions = 0,
};

uint64_t entry(void *ctx, uint64_t pkt_len) {
    if (sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct udphdr) < pkt_len) {
        return 1;
    }

    void *pkt = ubpf_packet_data(ctx);
    struct ether_header *ether_header = (void *)pkt;
    struct iphdr *iphdr = (void *)(ether_header + 1);
    struct udphdr *udphdr = (void *)(iphdr + 1);

    uint16_t dst = udphdr->dest;
    uint32_t *pass = NULL;
    pass = ubpf_map_lookup(&reg, &dst);
    return (pass && *pass) || !pass;
}

I installed it with the following steps:

clang -O2 -target bpf -c examples/pass.c -o examples/pass.o
ovs-ofctl load-bpf-prog br0 1 examples/pass.o
ovs-ofctl add-flow br0 priority=1,actions=prog:1,in_port

It doesn't contain any entry.