Giter Club home page Giter Club logo

p4rt-ovs's Introduction

P4rt-OVS: Programming Protocol-Independent, Runtime Extensions for Open vSwitch using P4

Table of contents

  1. Overview
  2. Getting started
  3. Contributing
  4. License
  5. Contacts
  6. Acknowledgment

The original Open vSwitch README is available at README-original.rst.

Overview

Open vSwitch (OVS) is a widely adopted high-performance programmable virtual switch. P4rt-OVS is an extension of Open vSwitch that integrates the BPF virtual machine with the userspace datapath of OVS. Hence, P4rt-OVS allows to extend the OVS packet processing pipeline without recompilation by injecting BPF programs at runtime. BPF programs act as programmable actions and they are referenced as a new OVS action (prog) in the OpenFlow tables. Programmable actions are allowed to write to packets as well as read and write to persistent maps (hash tables) to retain information on flows.

Furthermore, a user can use the P4 language to develop new, protocol-independent data plane extensions (BPF programs) for Open vSwitch. P4 provides a high-level and declarative language, so writing a new network features becomes super easy! p4c-ubpf, the uBPF back-end for the P4 compiler, provides the architecture model to write P4 programs making use of wide range of P4 features including stateful registers.

P4rt-OVS is based on Open vSwitch v2.13 and relies on a modified version of the ubpf project to execute BPF programs.

P4rt-OVS was presented during Open vSwitch and OVN Fall 2019 Conference. [ link ]

Getting started

Prerequisites

  • clang-6.0 installed to compile from C to BPF.

How to install?

P4rt-OVS works only with the userspace datapath of OVS. Currently, there are two implementations of userspace datapath: DPDK and AF_XDP. We tested P4rt-OVS with both solutions. However, we recommend AF_XDP as a more lightweight solution.

Note! P4rt-OVS allows to disable BPF verifier, but it is not recommended to do so. Please, use it carefully and only for testing or research purpose. If BPF verifier is disabled it is higly recommended to generate data plane programs from the P4 language, because p4c-ubpf generates verified programs. To disable BPF verifier add --disable-bpf-verifier flag to configuration script:

./configure --disable-bpf-verifier

DPDK

To install P4rt-OVS on top of DPDK, you can follow the usual guidelines to install Open vSwitch-DPDK. No additional dependencies are required.

AF_XDP

Running OVS on top of DPDK requires some configuration effort. Additionally, DPDK is not integrated with veth interfaces.

The easiest and fastest way to test P4rt-OVS (without environment's preparation and configuration overhead) is to use AF_XDP interfaces. AF_XDP allows to use veth interfaces with our P4rt-OVS, what makes testing really easy.

To install P4rt-OVS on top of AF_XDP, you can follow the usual guidelines to install Open vSwitch-AFXDP. No additional dependencies are required.

Docker

TBD

How to use?

P4rt-OVS allows to inject a new data plane program to the OVS packet processing pipeline at runtime. The process can be decomposed into two phases: Design (programming data plane module in either P4 or C) and Runtime (using already developed data plane module in Open vSwitch).

Design phase - Writing data plane extensions

Data plane programs for P4rt-OVS can be created in P4 or C. We recommend the former as writing data plane programs in P4 is easier and less error-prone.

P4 (the recommended way)

P4rt-OVS is well-integrated with the uBPF back-end for the P4 compiler. We recommend users to use P4 to develop data plane extensions for Open vSwitch. P4 provides a high-level and declarative programming language, which makes development much easier than using C.

Firstly, you need to install the p4c compiler locally by following the official guide.

Note! As p4c-ubpf is still under review, you should use forked p4c from the P4-Research repository temporarily.

To learn how to write data plane programs for P4rt-OVS in the P4 language refer to the following materials:

C

The data plane extensions for P4rt-OVS can be also developed in the C language.

To find out how to develop data plane programs for P4rt-OVS in C take a look at examples.

Runtime phase - using data plane extensions in OVS

Once a data plane program is ready, we can test it using P4rt-OVS. As P4 is the recommended way to extend the P4rt-OVS pipeline all below examples assume using P4.

Note! We didn't finished the implementation of P4rt-OVS CLI (P4-compatible), so that a user has to use the low-level API of Open vSwitch.

The below snippet shows how to configure ports, install the P4 program, invoke P4 program for the incoming traffic and control the BPF maps that represent Match-Action tables of the P4 program.

We use tunneling.p4 program to show the basic functionality of P4rt-OVS. The tunneling.p4 program implements simple MPLS encapsulation and decapsulation.

# AF_XDP is used in this example. Let's add two veth interfaces as OVS ports.
$ ovs-vsctl add-port br0 peer0 -- set interface peer0 external-ids:iface-id="port0" type="afxdp"
$ ovs-vsctl add-port br0 peer1 -- set interface peer1 external-ids:iface-id="port1" type="afxdp"
$ ovs-vsctl show
e7c40460-0252-4c98-a225-44416c01ead2
  Bridge br0
      datapath_type: netdev
      Port peer1
          Interface peer1
              type: afxdp
      Port br0
          Interface br0
              type: internal
      Port peer0
          Interface peer0
              type: afxdp
# For the demo purpose, tunneling.p4 is used. Compile it from P4 to C.
$ p4c-ubpf -o tunneling.c tunneling.p4
# compile tunneling.c to BPF machine code 
$ clang-6.0 -O2 -target bpf -c tunneling.c -o /tmp/tunneling.o
# Load compiled program to OVS
$ ovs-ofctl load-bpf-prog br0 1 /tmp/tunneling.o
$ ovs-ofctl show-bpf-prog br0 1
NXT_BPF_SHOW_PROG_REPLY (xid=0x4):
The number of BPF programs already loaded: 1
id 2:   loaded_at=2020-02-19 T13:00:52 
    map_ids 0,1
# Setup rules to forward traffic (bidirectional). By default, the BPF program will pass all packets.
$ ovs-ofctl add-flow br0 in_port=2,actions=prog:1,output:1
$ ovs-ofctl add-flow br0 in_port=1,actions=prog:1,output:2
# Install BPF map entry (P4 table entry) to invoke mpls_encap() (value=0) for packets destined to 172.16.0.14 through downstream_tbl (map=1) of the P4 program (prog=1)..
# Template: ovs-ofctl update-bpf-map <BRIDGE> <PROGRAM-ID> <MAP-ID> key <KEY-DATA> value <VALUE-DATA>
$ ovs-ofctl update-bpf-map br0 1 1 key 14 0 16 172 value 0 0 0 0
# Dump content of the downstream_tbl (map=1) of the tunneling.p4 program (prog=1).
$ ovs-ofctl dump-bpf-map br0 1 1 hex
NXT_DUMP_MAP_REPLY (xid=0x4):
The map contains 1 element(s)
Key: 
0e 00 10 ac
Value: 
00 00 00 00

# To delete the above entry:
$ ovs-ofctl delete-bpf-map 1 1 key 14 0 16 172
$ ovs-ofctl dump-bpf-map br0 1 1
NXT_DUMP_MAP_REPLY (xid=0x4):
The map contains 0 element(s)
# Unload the P4 program from OVS:
$ ovs-ofctl unload-bpf-prog 1 1
$ ovs-ofctl show-bpf-prog br0
NXT_BPF_SHOW_PROG_REPLY (xid=0x4):
The number of BPF programs already loaded: 0

Mininet

P4rt-OVS can be also integrated into Mininet. The only modification required is to add datapath = 'user option to addSwitch() function, as follows:

s1 = self.addSwitch('s1', datapath = 'user')

Note! Make sure both ovsdb-server and ovs-vswitchd daemons are started before running Mininet script.

We also developed the wrapper for P4rt-OVS (based on the OVSSwitch class of Mininet) to make loading P4 programs to Mininet's switches more straightforward. The example of Mininet script for P4rt-OVS can be found in utilities/mininet/.

Remember that there are no flow rules configured by default. In the above example (with only one switch in the network) you can configure the following rules to enable communication between hosts:

$ sudo ovs-ofctl add-flow s1 in_port=1,actions=prog:1,output:2
$ sudo ovs-ofctl add-flow s1 in_port=2,actions=prog:1,output:1

Known limitations

  • Data plane modules can only make a decision whether to drop a packet or pass it back to the OVS pipeline. An output port cannot be determined from within a data plane program.

Contributing

The P4rt-OVS project welcomes new contributors. This version of P4rt-OVS is still a research prototype. It may contain serious bugs and should be used only for experimentation and research purposes.

Nevertheless, we are looking forward to your feedback regarding the current functionality or new features. Our goal is to find the best way to bring the P4 support to Open vSwitch in order to make programming data plane programs less complex and leverage OVS in new areas of use cases.

  • To start contributing and get familiar with P4rt-OVS check out Open issues
  • If you will find a bug, please submit the new issue.
  • We are also waiting for your PRs with new features!

License

Except for the lib/bpf/lookup3.c file in the public domain, all new files introduced by Oko compared to Open vSwitch are licensed under Apache 2.0. Modified files from both Open vSwitch and ubpf are also licensed under their original license, Apache 2.0.

Contacts

Tomasz Osiński <[email protected]>

Mateusz Kossakowski <[email protected]>

Paul Chaignon <[email protected]>

Acknowledgment

This work was made in cooperation with Warsaw University of Technology.

p4rt-ovs's People

Contributors

apconole avatar aserdean avatar azhou-nicira avatar blp avatar darball1 avatar ddiproietto avatar drizzt avatar ejj avatar fleitner avatar gvrose8192 avatar hzhou8 avatar igsilya avatar jessegross avatar joestringer avatar jrajahalme avatar justinpettit avatar nithinrajub avatar numansiddique avatar pshelar avatar russellb avatar shettyg avatar shorman-netronome avatar stephenfin avatar svinturis avatar williamtu avatar xpu22 avatar yamt avatar yew011 avatar yifsun avatar yihungwei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

p4rt-ovs's Issues

Segmentation fault in ovs-vswitchd during dump-bpf-map

When I try to dump BPF map, ovs-vswitchd gets SIGSEGV. As a result ovs-vswitchd is terminated.

To trigger this issue, I need to do following steps:

  1. Create test environment - two pairs of interfaces with type veth:
$ ip netns add test0
$ ip link add port0 type veth peer name peer0
$ ip link set port0 netns test0
$ ip link set peer0 up

$ ip netns exec test0 sh << EOF
ip addr add "10.1.1.1/24" dev port0
ip link set port0 up
EOF

$ ip netns add test1
$ ip link add port1 type veth peer name peer1
$ ip link set port1 netns test1
$ ip link set peer1 up

$ ip netns exec test1 sh << EOF
ip addr add "10.1.1.2/24" dev port1
ip link set port1 up
EOF
  1. Create OVS switch with ports of type afxdp:
$ sudo ovs-vsctl -- add-br br0 -- set Bridge br0 datapath_type=netdev
$ sudo ovs-vsctl add-port br0 peer0 -- set interface peer0 type="afxdp"
$ sudo ovs-vsctl add-port br0 peer1 -- set interface peer1 type="afxdp"
  1. Load uBPF program into switch and insert data into (any) map:
$ sudo ovs-ofctl load-bpf-prog br0 1 tunneling.o
$ sudo ovs-ofctl show-bpf-prog br0
NXT_BPF_SHOW_PROG_REPLY (xid=0x4):
The number of BPF programs already loaded: 1
id 1:   loaded_at=2020-03-07 T23:00:43 
	map_ids 0,1
$ sudo ovs-ofctl update-bpf-map br0 1 1 key 14 0 16 172 value 0 0 0 0

I used tunneling.p4 as a uBPF program.

  1. Dump content of the map:
$ sudo ovs-ofctl dump-bpf-map br0 1 1 hex
ovs-ofctl: talking to unix:/usr/local/var/run/openvswitch/br0.mgmt (End of file)

As the result in the terminal, where ovs-vswitchd has been run, I got following logs:

2020-03-07T21:59:02Z|00051|memory|INFO|handlers:1 ports:3 revalidators:1 rules:5
Segmentation fault (core dumped)

When I repeat this scenario with gdb, I got following logs for ovs-vswitchd:

2020-03-08T14:33:57Z|00049|memory|INFO|handlers:1 ports:3 revalidators:1 rules:5

Thread 1 "ovs-vswitchd" received signal SIGSEGV, Segmentation fault.
0x0000555555932d90 in ofpmsg_update_length (buf=buf@entry=0x8ec40)
    at lib/ofp-msgs.c:884
884	    struct ofp_header *oh = ofpbuf_at_assert(buf, 0, sizeof *oh);
(gdb) bt
#0  0x0000555555932d90 in ofpmsg_update_length (buf=buf@entry=0x8ec40)
    at lib/ofp-msgs.c:884
#1  0x0000555555787783 in ofconn_send (ofconn=0x613000001000, 
    counter=0x60600008e100, msg=0x8ec40) at ofproto/connmgr.c:1489
#2  ofconn_send_reply (ofconn=ofconn@entry=0x613000001000, msg=0x8ec40)
    at ofproto/connmgr.c:1026
#3  0x00005555556e08f4 in handle_dump_map (oh=<optimized out>, 
    ofconn=0x613000001000) at ofproto/ofproto.c:6525
#4  handle_single_part_openflow (type=<optimized out>, oh=<optimized out>, 
    ofconn=0x613000001000) at ofproto/ofproto.c:8892
#5  handle_openflow (ofconn=ofconn@entry=0x613000001000, 
    msgs=msgs@entry=0x7fffffffd280) at ofproto/ofproto.c:9077
#6  0x0000555555787f33 in ofconn_run (
    handle_openflow=0x5555556d9b80 <handle_openflow>, ofconn=0x613000001000)
    at ofproto/connmgr.c:1321
#7  connmgr_run (mgr=<optimized out>, 
    handle_openflow=handle_openflow@entry=0x5555556d9b80 <handle_openflow>)
    at ofproto/connmgr.c:356
#8  0x00005555556c5f47 in ofproto_run (p=<optimized out>)
    at ofproto/ofproto.c:1894
#9  0x000055555568ae16 in bridge_run__ () at vswitchd/bridge.c:3246
#10 0x000055555569de55 in bridge_run () at vswitchd/bridge.c:3305
#11 0x000055555567d934 in main (argc=<optimized out>, argv=<optimized out>)
    at vswitchd/ovs-vswitchd.c:127

OFPT_ERROR (xid=0x4): OFPBRC_BAD_SUBTYPE

Hi
I am new to OVS and P4. When I load a bpf program to switch using following command
$ sudo ovs-ofctl load-bpf-prog br0 1 test.o
I get
OFPT_ERROR (xid=0x4): OFPBRC_BAD_SUBTYPE
NXT_BPF_LOAD_PROG (xid=0x4):

Any help will be highly appreciated

Segmentation fault in dump-bpf-map

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.

Pings fail in mininet with test-tunneling.p4.

When running the mininet script test_topo.py with the test_tunneling.p4 loaded, I am getting a Destination Host Unreachable error when attempting to ping h2 from h1.

This error occurs even after insertion of flow rules using the commands sudo ovs-ofctl add-flow s1 in_port=1,actions=prog:1,output:2 and sudo ovs-ofctl add-flow s1 in_port=2,actions=prog:1,output:1 as instructed in the README.

I am getting the same error when using other programs also (such as vlan.c) and my own P4 program that trivially extracts the ethernet header, passes the packet and deparses the ethernet header again. All of these programs show the same behaviour when compiled with either clang-6.0 or clang-10.

I have tested the pings without loading any bpf program and they work just fine. The only way that I can seem to get the pings to work is by editing the C code of each program to trivially return 1 as seen with vlan.c below where I have commented out most of the entry function:

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

#define ___constant_swab16(x) ((uint16_t)(             \
    (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |          \
    (((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))

#define ___constant_swab32(x) ((uint32_t)(             \
    (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) |        \
    (((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) |        \
    (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) |        \
    (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))

#define bpf_htons(d) (___constant_swab16((d)))
#define bpf_htonl(d) (___constant_swab32((d)))

#define VLAN_HDR_LEN 4
#define ETH_ADDR_LEN 6

static void (*ubpf_printf)(const char *fmt, ...) = (void *)7;
static void *(*ubpf_packet_data)(const void *) = (void *)9;
static void *(*ubpf_adjust_head)(const void *, uint64_t) = (void *)8;

void* memmove(void* dest, const void* src, size_t len);

struct vlan_eth {
    u_int8_t  ether_dhost[6];   /* destination eth addr */
    u_int8_t  ether_shost[6];   /* source ether addr    */
    uint16_t h_vlan_ethtype;
    uint16_t h_vlan_TCI;
    uint16_t ethtype;
};

/*
 * The example shows VLAN tagging. The BPF program replaces Ethernet header with VLAN-tagged L2 header.
 */
uint64_t entry(void *ctx, uint64_t pkt_len)
{
    bool pass = true;

//    void *pkt = ubpf_packet_data(ctx);
//    if (pkt_len < sizeof(struct ether_header) + sizeof(struct iphdr)) {
//        return 1;
//    }

//    pkt = ubpf_adjust_head(ctx, VLAN_HDR_LEN);
//    struct vlan_eth *veh = (void *) pkt;
//    memmove(veh, (char *)veh + VLAN_HDR_LEN, 2 * ETH_ADDR_LEN);

//    veh->h_vlan_TCI = bpf_htons(20); // set VLAN TCI=20
//    veh->h_vlan_ethtype = bpf_htons(0x8100); // set EtherType to VLAN

    return pass;
}

I realise that this is unlikely to be a bug, but I would appreciate if anyone had some idea as to what I have done wrong, as I believe I have followed all of the installation steps correctly. I you require any more details, I am happy to provide them.

Assertion failed error message on ovs-vswitchd stop

When I stop ovs-vswitchd with ovs-ctl, I get the following message in the logs. ovs-vswitchd doesn't always stop when I ask it too, but I don't know if that's related.

2020-01-22T10:26:02.184Z|01911|bridge|INFO|bridge br0: deleted interface br0 on port 65534
2020-01-22T10:26:02.233Z|01912|util|EMER|ofproto/ofproto.c:1625: assertion hmap_is_empty(&ofproto->ubpf_vms) failed in ofproto_destroy__()
2020-01-22T10:26:03.504Z|00002|daemon_unix(monitor)|ERR|1 crashes: pid 57648 died, killed (Aborted), core dumped, restarting

It looks like ofproto->ubpf_vms is not properly emptied on shutdown.

Ovs-vswitchd aborted during mininet shutdown (assertion failed)

When I shutdown mininet, ovs-vswitchd gets signal SIGABRT. Mininet also stops on deleting switches, but restart of ovs-vswitchd allows to continue mininet execution.

To trigger this issue, I need to do following steps:

  1. Run my network in mininet
    To launch my network, I used script demo_net.py in which:
  • changed switch to OVSSwitch;
  • passed option datapath='user' to switch (compare with this Readme).
  1. Load uBPF program into switch
    I used tunneling.p4 as a uBPF program. I load it into one of the four switches:
$ sudo ovs-ofctl load-bpf-prog s3 1 tunneling.o
$ sudo ovs-ofctl show-bpf-prog s3
NXT_BPF_SHOW_PROG_REPLY (xid=0x4):
The number of BPF programs already loaded: 1
id 1:   loaded_at=2020-03-07 T22:14:25 
	map_ids 0,1

I do not insert data into created maps.

  1. Shutdown mininet
    Mininet stops at this state:
mininet> exit
*** Stopping 0 controllers

*** Stopping 11 links
...........
*** Stopping 4 switches

As the result in the terminal, where ovs-vswitchd has been run, I got following logs:

2020-03-07T21:15:19Z|00096|bridge|INFO|bridge s3: deleted interface s3-eth4 on port 4
ovs-vswitchd(urcu3): ofproto/ofproto.c:1682: assertion hmap_is_empty(&ofproto->ubpf_vms) failed in ofproto_destroy__()
Aborted (core dumped)

When I repeat this scenario with gdb, I got following logs for ovs-vswitchd:

2020-03-08T14:11:29Z|00096|bridge|INFO|bridge s3: deleted interface s3-eth4 on port 4
[Thread 0x7ffff0131700 (LWP 5769) exited]
[Thread 0x7fffef930700 (LWP 5770) exited]
[New Thread 0x7fffef930700 (LWP 5791)]
[New Thread 0x7ffff0131700 (LWP 5792)]
ovs-vswitchd(urcu2): ofproto/ofproto.c:1682: assertion hmap_is_empty(&ofproto->ubpf_vms) failed in ofproto_destroy__()

Thread 3 "urcu2" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff19fe700 (LWP 5647)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff5502801 in __GI_abort () at abort.c:79
#2  0x0000555555a12d53 in ovs_abort_valist (err_no=err_no@entry=0, 
    format=format@entry=0x555555c16ba0 "%s: assertion %s failed in %s()", 
    args=args@entry=0x7ffff19fd850) at lib/util.c:419
#3  0x0000555555a25489 in vlog_abort_valist (
    module_=module_@entry=0x555555f956c0 <this_module>, 
    message=message@entry=0x555555c16ba0 "%s: assertion %s failed in %s()", 
    args=args@entry=0x7ffff19fd850) at lib/vlog.c:1227
#4  0x0000555555a2558c in vlog_abort (
    module=module@entry=0x555555f956c0 <this_module>, 
    message=message@entry=0x555555c16ba0 "%s: assertion %s failed in %s()")
    at lib/vlog.c:1241
#5  0x0000555555a1291b in ovs_assert_failure (
    where=where@entry=0x555555b7bfc0 "ofproto/ofproto.c:1682", 
    function=function@entry=0x555555b7fde0 <__func__.24577> "ofproto_destroy__", condition=condition@entry=0x555555b7bf60 "hmap_is_empty(&ofproto->ubpf_vms)")
    at lib/util.c:86
#6  0x00005555556bc1cf in ofproto_destroy__ (ofproto=0x61b00000cba0)
    at ofproto/ofproto.c:1682
#7  0x0000555555979a99 in ovsrcu_call_postponed () at lib/ovs-rcu.c:342
#8  0x0000555555979c94 in ovsrcu_postpone_thread (arg=<optimized out>)
    at lib/ovs-rcu.c:357
#9  0x000055555597feea in ovsthread_wrapper (aux_=<optimized out>)
    at lib/ovs-thread.c:383
#10 0x00007ffff5e606db in start_thread (arg=0x7ffff19fe700)
    at pthread_create.c:463
#11 0x00007ffff55e388f in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

It seems to be connected with the issue #3

verifier: Invalid access to map value

While loading test.c program (with refactored packet size's check) I'm getting the following debug message:

2020-02-03T09:39:58.645Z|24443|verifier|INFO|PC=176, class=0x5, opcode=0x5
2020-02-03T09:39:58.645Z|24444|verifier|INFO|	unconditional jump from PC 176 to PC 212
2020-02-03T09:39:58.645Z|24445|verifier|INFO|PC=212, class=0x3, opcode=0x7b
2020-02-03T09:39:58.645Z|24446|verifier|INFO|	Spilled R8 to stack offset 888
2020-02-03T09:39:58.645Z|24447|verifier|INFO|PC=213, class=0x1, opcode=0x79
2020-02-03T09:39:58.645Z|24448|verifier|INFO|	Loaded R8 from stack offset 872
2020-02-03T09:39:58.645Z|24449|verifier|INFO|PC=214, class=0x7, opcode=0x7
2020-02-03T09:39:58.645Z|24450|verifier|INFO|	R8 (t=4) has updated range [304;304] U [304;304]
2020-02-03T09:39:58.645Z|24451|verifier|INFO|PC=215, class=0x7, opcode=0xb7
2020-02-03T09:39:58.645Z|24452|verifier|INFO|	R1 now has type 0x4, range [38;38] U [38;38]
2020-02-03T09:39:58.645Z|24453|verifier|INFO|PC=216, class=0x7, opcode=0xbf
2020-02-03T09:39:58.645Z|24454|verifier|INFO|	R9 now has type 0x4, range [0;0] U [0;0]
2020-02-03T09:39:58.645Z|24455|verifier|INFO|PC=217, class=0x5, opcode=0x55
2020-02-03T09:39:58.645Z|24456|verifier|INFO|	R3 (t=4) may have updated range [0;0] U [0;0]
2020-02-03T09:39:58.645Z|24457|verifier|INFO|PC=218, class=0x7, opcode=0xb7
2020-02-03T09:39:58.645Z|24458|verifier|INFO|	R1 now has type 0x4, range [34;34] U [34;34]
2020-02-03T09:39:58.645Z|24459|verifier|INFO|PC=219, class=0x0, opcode=0x18
2020-02-03T09:39:58.645Z|24460|bpf|WARN|Failed to load code: invalid access to map value (0 + 8 > 4) at PC 219

test.c

/* Automatically generated by p4c-ubpf from ../examples/tunneling.p4 on Fri Jan 31 15:04:18 2020
 */
#include "test.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "ubpf_common.h"

#define BPF_MASK(t, w) ((((t)(1)) << (w)) - (t)1)
#define BYTES(w) ((w) / 8)

void* memcpy(void* dest, const void* src, size_t num);

static void *(*ubpf_map_lookup)(const void *, const void *) = (void *)1;
static int (*ubpf_map_update)(void *, const void *, void *) = (void *)2;
static int (*ubpf_map_delete)(void *, const void *) = (void *)3;
static int (*ubpf_map_add)(void *, const void *) = (void *)4;
static uint64_t (*ubpf_time_get_ns)() = (void *)5;
static uint32_t (*ubpf_hash)(const void *, uint64_t) = (void *)6;
static void (*ubpf_printf)(const char *fmt, ...) = (void *)7;
static void *(*ubpf_packet_data)(const void *) = (void *)9;
static void *(*ubpf_adjust_head)(const void *, uint64_t) = (void *)8;


#define write_partial(a, w, s, v) do { *((uint8_t*)a) = ((*((uint8_t*)a)) & ~(BPF_MASK(uint8_t, w) << s)) | (v << s) ; } while (0)
#define write_byte(base, offset, v) do { *(uint8_t*)((base) + (offset)) = (v); } while (0)

static uint32_t
bpf_htonl(uint32_t val) {
    return htonl(val);
}
static uint16_t
bpf_htons(uint16_t val) {
    return htons(val);
}
static uint64_t
bpf_htonll(uint64_t val) {
    return htonll(val);
}

uint64_t entry(void *ctx, uint64_t pkt_len){
    void *pkt = ubpf_packet_data(ctx);
    struct Headers_t headers = {
        .ethernet = {
            .ebpf_valid = 0
        },
        .mpls = {
            .ebpf_valid = 0
        },
        .ipv4 = {
            .ebpf_valid = 0
        },
    };
    struct metadata meta = {
    };
    int packetOffsetInBits = 0;
    uint8_t pass = 1;
    unsigned char ebpf_byte;

    goto start;
    start: {
        /* extract(headers.ethernet)*/
        if (pkt_len < BYTES(packetOffsetInBits + 112)) {
            goto reject;
        }
        
        headers.ethernet.dstAddr = (uint64_t)((load_dword(pkt, BYTES(packetOffsetInBits)) >> 16) & BPF_MASK(uint64_t, 48));
        packetOffsetInBits += 48;

        headers.ethernet.srcAddr = (uint64_t)((load_dword(pkt, BYTES(packetOffsetInBits)) >> 16) & BPF_MASK(uint64_t, 48));
        packetOffsetInBits += 48;

        headers.ethernet.etherType = (uint16_t)((load_half(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 16;

        headers.ethernet.ebpf_valid = 1;
        switch (headers.ethernet.etherType) {
            case 0x800: goto ipv4;
            case 0x8847: goto mpls;
            default: goto reject;
        }
    }
    mpls: {
        /* extract(headers.mpls)*/
        if (pkt_len < BYTES(packetOffsetInBits + 32)) {
            goto reject;
        }
        
        headers.mpls.label = (uint32_t)((load_word(pkt, BYTES(packetOffsetInBits)) >> 12) & BPF_MASK(uint32_t, 20));
        packetOffsetInBits += 20;

        headers.mpls.tc = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits)) >> 1) & BPF_MASK(uint8_t, 3));
        packetOffsetInBits += 3;

        headers.mpls.stack = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))) & BPF_MASK(uint8_t, 1));
        packetOffsetInBits += 1;

        headers.mpls.ttl = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 8;

        headers.mpls.ebpf_valid = 1;
        goto ipv4;
    }
    ipv4: {
        /* extract(headers.ipv4)*/
        if (pkt_len < BYTES(packetOffsetInBits + 160)) {
            goto reject;
        }
        
        headers.ipv4.version = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits)) >> 4) & BPF_MASK(uint8_t, 4));
        packetOffsetInBits += 4;

        headers.ipv4.ihl = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))) & BPF_MASK(uint8_t, 4));
        packetOffsetInBits += 4;

        headers.ipv4.diffserv = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 8;

        headers.ipv4.totalLen = (uint16_t)((load_half(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 16;

        headers.ipv4.identification = (uint16_t)((load_half(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 16;

        headers.ipv4.flags = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits)) >> 5) & BPF_MASK(uint8_t, 3));
        packetOffsetInBits += 3;

        headers.ipv4.fragOffset = (uint16_t)((load_half(pkt, BYTES(packetOffsetInBits))) & BPF_MASK(uint16_t, 13));
        packetOffsetInBits += 13;

        headers.ipv4.ttl = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 8;

        headers.ipv4.protocol = (uint8_t)((load_byte(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 8;

        headers.ipv4.hdrChecksum = (uint16_t)((load_half(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 16;

        headers.ipv4.srcAddr = (uint32_t)((load_word(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 32;

        headers.ipv4.dstAddr = (uint32_t)((load_word(pkt, BYTES(packetOffsetInBits))));
        packetOffsetInBits += 32;

        headers.ipv4.ebpf_valid = 1;
        goto accept;
    }

    reject: { return 0; }

    accept:
    {
        {

            if (headers.mpls.ebpf_valid) {
                {
                    /* construct key */
                    struct pipe_upstream_tbl_key key = {};
                    key.headers_mpls_label = headers.mpls.label;
                    /* value */
                    struct pipe_upstream_tbl_value *value = NULL;
                    /* perform lookup */
                    value = ubpf_map_lookup(&pipe_upstream_tbl, &key);

                    if (value != NULL) {
                        /* run action */
                        switch (value->action) {
                            case pipe_mpls_decap: 
                            {
                                                                headers.mpls.ebpf_valid = false;
headers.ethernet.etherType = 0x800;
                            }
                            break;
                            case pipe_upstream_tbl_NoAction: 
                            {
                                
                            }
                            break;
                            default: return 0;
                        }
                    }
                    else return 0;
                }
;
            } else {
                {
                    /* construct key */
                    struct pipe_downstream_tbl_key key = {};
                    key.headers_ipv4_dstAddr = headers.ipv4.dstAddr;
                    /* value */
                    struct pipe_downstream_tbl_value *value = NULL;
                    /* perform lookup */
                    value = ubpf_map_lookup(&pipe_downstream_tbl, &key);

                    if (value != NULL) {
                        /* run action */
                        switch (value->action) {
                            case pipe_mpls_encap: 
                            {
                                                                headers.mpls.ebpf_valid = true;
headers.ethernet.etherType = 0x8847;headers.mpls.label = 20;headers.mpls.tc = 5;headers.mpls.stack = 1;headers.mpls.ttl = 64;
                            }
                            break;
                            case pipe_downstream_tbl_NoAction: 
                            {
                                
                            }
                            break;
                            default: return 0;
                        }
                    }
                    else return 0;
                }
;
            }

        }    }
    deparser:
    {
        int outHeaderLength = 0;
        if (headers.ethernet.ebpf_valid) 
        outHeaderLength += 112;
if (headers.mpls.ebpf_valid) 
        outHeaderLength += 32;
if (headers.ipv4.ebpf_valid) 
        outHeaderLength += 160;

        int outHeaderOffset = BYTES(packetOffsetInBits) - BYTES(outHeaderLength);
        pkt = ubpf_adjust_head(ctx, outHeaderOffset);
        pkt_len += outHeaderOffset;
        packetOffsetInBits = 0;
        if (headers.ethernet.ebpf_valid) {
            if (pkt_len < BYTES(packetOffsetInBits + 112)) {
                goto reject;
            }
            
            headers.ethernet.dstAddr = htonll(headers.ethernet.dstAddr << 16);
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[2];
            write_byte(pkt, BYTES(packetOffsetInBits) + 2, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[3];
            write_byte(pkt, BYTES(packetOffsetInBits) + 3, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[4];
            write_byte(pkt, BYTES(packetOffsetInBits) + 4, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.dstAddr))[5];
            write_byte(pkt, BYTES(packetOffsetInBits) + 5, (ebpf_byte));
            packetOffsetInBits += 48;

            headers.ethernet.srcAddr = htonll(headers.ethernet.srcAddr << 16);
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[2];
            write_byte(pkt, BYTES(packetOffsetInBits) + 2, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[3];
            write_byte(pkt, BYTES(packetOffsetInBits) + 3, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[4];
            write_byte(pkt, BYTES(packetOffsetInBits) + 4, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.srcAddr))[5];
            write_byte(pkt, BYTES(packetOffsetInBits) + 5, (ebpf_byte));
            packetOffsetInBits += 48;

            headers.ethernet.etherType = bpf_htons(headers.ethernet.etherType);
            ebpf_byte = ((char*)(&headers.ethernet.etherType))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ethernet.etherType))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            packetOffsetInBits += 16;

        }
;        if (headers.mpls.ebpf_valid) {
            if (pkt_len < BYTES(packetOffsetInBits + 32)) {
                goto reject;
            }
            
            headers.mpls.label = htonl(headers.mpls.label << 12);
            ebpf_byte = ((char*)(&headers.mpls.label))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.mpls.label))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.mpls.label))[2];
            write_partial(pkt + BYTES(packetOffsetInBits) + 2, 4, 4, (ebpf_byte >> 4));
            packetOffsetInBits += 20;

            ebpf_byte = ((char*)(&headers.mpls.tc))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 3, 1, (ebpf_byte >> 0));
            packetOffsetInBits += 3;

            ebpf_byte = ((char*)(&headers.mpls.stack))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 1, 0, (ebpf_byte >> 0));
            packetOffsetInBits += 1;

            ebpf_byte = ((char*)(&headers.mpls.ttl))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            packetOffsetInBits += 8;

        }
;        if (headers.ipv4.ebpf_valid) {
            if (pkt_len < BYTES(packetOffsetInBits + 160)) {
                goto reject;
            }
            
            ebpf_byte = ((char*)(&headers.ipv4.version))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 4, 4, (ebpf_byte >> 0));
            packetOffsetInBits += 4;

            ebpf_byte = ((char*)(&headers.ipv4.ihl))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 4, 0, (ebpf_byte >> 0));
            packetOffsetInBits += 4;

            ebpf_byte = ((char*)(&headers.ipv4.diffserv))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            packetOffsetInBits += 8;

            headers.ipv4.totalLen = bpf_htons(headers.ipv4.totalLen);
            ebpf_byte = ((char*)(&headers.ipv4.totalLen))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.totalLen))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            packetOffsetInBits += 16;

            headers.ipv4.identification = bpf_htons(headers.ipv4.identification);
            ebpf_byte = ((char*)(&headers.ipv4.identification))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.identification))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            packetOffsetInBits += 16;

            ebpf_byte = ((char*)(&headers.ipv4.flags))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 3, 5, (ebpf_byte >> 0));
            packetOffsetInBits += 3;

            headers.ipv4.fragOffset = bpf_htons(headers.ipv4.fragOffset << 3);
            ebpf_byte = ((char*)(&headers.ipv4.fragOffset))[0];
            write_partial(pkt + BYTES(packetOffsetInBits) + 0, 5, 0, (ebpf_byte >> 3));
            write_partial(pkt + BYTES(packetOffsetInBits) + 0 + 1, 3, 5, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.fragOffset))[1];
            write_partial(pkt + BYTES(packetOffsetInBits) + 1, 5, 0, (ebpf_byte >> 3));
            packetOffsetInBits += 13;

            ebpf_byte = ((char*)(&headers.ipv4.ttl))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            packetOffsetInBits += 8;

            ebpf_byte = ((char*)(&headers.ipv4.protocol))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            packetOffsetInBits += 8;

            headers.ipv4.hdrChecksum = bpf_htons(headers.ipv4.hdrChecksum);
            ebpf_byte = ((char*)(&headers.ipv4.hdrChecksum))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.hdrChecksum))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            packetOffsetInBits += 16;

            headers.ipv4.srcAddr = htonl(headers.ipv4.srcAddr);
            ebpf_byte = ((char*)(&headers.ipv4.srcAddr))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.srcAddr))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.srcAddr))[2];
            write_byte(pkt, BYTES(packetOffsetInBits) + 2, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.srcAddr))[3];
            write_byte(pkt, BYTES(packetOffsetInBits) + 3, (ebpf_byte));
            packetOffsetInBits += 32;

            headers.ipv4.dstAddr = htonl(headers.ipv4.dstAddr);
            ebpf_byte = ((char*)(&headers.ipv4.dstAddr))[0];
            write_byte(pkt, BYTES(packetOffsetInBits) + 0, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.dstAddr))[1];
            write_byte(pkt, BYTES(packetOffsetInBits) + 1, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.dstAddr))[2];
            write_byte(pkt, BYTES(packetOffsetInBits) + 2, (ebpf_byte));
            ebpf_byte = ((char*)(&headers.ipv4.dstAddr))[3];
            write_byte(pkt, BYTES(packetOffsetInBits) + 3, (ebpf_byte));
            packetOffsetInBits += 32;

        }
;    }
    if (pass)
        return 1;
    else
        return 0;
}

test.h

/* Automatically generated by p4c-ubpf from ../examples/tunneling.p4 on Fri Jan 31 15:04:18 2020
 */
#ifndef _P4_GEN_HEADER_
#define _P4_GEN_HEADER_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "ubpf_common.h"


struct Ethernet_h {
    uint64_t dstAddr; /* EthernetAddress */
    uint64_t srcAddr; /* EthernetAddress */
    uint16_t etherType; /* bit<16> */
    uint8_t ebpf_valid;
};

struct IPv4_h {
    uint8_t version; /* bit<4> */
    uint8_t ihl; /* bit<4> */
    uint8_t diffserv; /* bit<8> */
    uint16_t totalLen; /* bit<16> */
    uint16_t identification; /* bit<16> */
    uint8_t flags; /* bit<3> */
    uint16_t fragOffset; /* bit<13> */
    uint8_t ttl; /* bit<8> */
    uint8_t protocol; /* bit<8> */
    uint16_t hdrChecksum; /* bit<16> */
    uint32_t srcAddr; /* IPv4Address */
    uint32_t dstAddr; /* IPv4Address */
    uint8_t ebpf_valid;
};

struct mpls_h {
    uint32_t label; /* bit<20> */
    uint8_t tc; /* bit<3> */
    uint8_t stack; /* bit<1> */
    uint8_t ttl; /* bit<8> */
    uint8_t ebpf_valid;
};

struct Headers_t {
    struct Ethernet_h ethernet; /* Ethernet_h */
    struct mpls_h mpls; /* mpls_h */
    struct IPv4_h ipv4; /* IPv4_h */
};

struct metadata {
};


enum ubpf_map_type {
    UBPF_MAP_TYPE_HASHMAP = 4,
};
struct ubpf_map_def {
    enum ubpf_map_type type;
    unsigned int key_size;
    unsigned int value_size;
    unsigned int max_entries;
    unsigned int nb_hash_functions;
};

struct pipe_downstream_tbl_key {
    uint32_t headers_ipv4_dstAddr; /* headers.ipv4.dstAddr */
};
enum downstream_tbl_0_actions {
    pipe_mpls_encap,
    pipe_downstream_tbl_NoAction,
};
struct pipe_downstream_tbl_value {
    enum downstream_tbl_0_actions action;
    union {
        struct {
        } pipe_mpls_encap;
        struct {
        } pipe_downstream_tbl_NoAction;
    } u;
};
struct pipe_upstream_tbl_key {
    uint32_t headers_mpls_label; /* headers.mpls.label */
};
enum upstream_tbl_0_actions {
    pipe_mpls_decap,
    pipe_upstream_tbl_NoAction,
};
struct pipe_upstream_tbl_value {
    enum upstream_tbl_0_actions action;
    union {
        struct {
        } pipe_mpls_decap;
        struct {
        } pipe_upstream_tbl_NoAction;
    } u;
};

struct ubpf_map_def pipe_downstream_tbl = {
    .type = UBPF_MAP_TYPE_HASHMAP,
    .key_size = sizeof(struct pipe_downstream_tbl_key),
    .value_size = sizeof(struct pipe_downstream_tbl_value),
    .max_entries = 65535,
    .nb_hash_functions = 0,
};
struct ubpf_map_def pipe_upstream_tbl = {
    .type = UBPF_MAP_TYPE_HASHMAP,
    .key_size = sizeof(struct pipe_upstream_tbl_key),
    .value_size = sizeof(struct pipe_upstream_tbl_value),
    .max_entries = 65535,
    .nb_hash_functions = 0,
};
#endif

\cc @pchaigno

could not add network device dpdk1 to ofproto (Invalid argument).

Hey,firends
I got this error while testing,i don't know why , and i don't know how to fix it.Has anyone encountered such a problem? How did you solve it?

$ ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:02:06.0
$ ovs-vsctl: Error detected while setting up 'dpdk1': could not add network device dpdk1 to ofproto (Invalid argument). See ovs-vswitchd log for details.

Here is some information about the driver:
Network devices using DPDK-compatible driver

0000:02:06.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=igb_uio unused=e1000,vfio-pci
0000:02:07.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' drv=igb_uio unused=e1000,vfio-pci

Network devices using kernel driver

0000:02:01.0 '82545EM Gigabit Ethernet Controller (Copper) 100f' if=ens33 drv=e1000 unused=igb_uio,vfio-pci Active

How to install?

Hey,friends!
How do I install and use p4rt-ovs on ubuntu?
I am new to p4rt-ovs and p4c-ubpf,i don't know how to install it,my ubuntu version is 18.04.

verifier: Program with ubpf_printf() is rejected by the BPF verifier

I'm trying to test programs with ubpf_printf(). However, verifier rejects them. I use mpls.c from exmaples/ as the reference program.

If I put ubpf_printf() before ubpf_packet_data() I'm getting the following message:

|bpf|WARN|Failed to load code: uninitialized register 0 at PC 2

If I put ubpf_printf() after ubpf_packet_data() I'm getting the following message:

|bpf|WARN|Failed to load code: invalid access to packet (0 + 8 > 0) at PC 4

The latter is quite strange for me, as ubpf_printf() does not impact the actual packet.

@pchaigno Would you be able to take a look at it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.