GithubHelp home page GithubHelp logo

p4lang / behavioral-model Goto Github PK

View Code? Open in Web Editor NEW
520.0 47.0 327.0 33.25 MB

The reference P4 software switch

License: Apache License 2.0

C 3.51% C++ 83.30% Python 6.86% Thrift 0.97% Shell 0.48% Makefile 1.61% M4 2.77% P4 0.27% Ruby 0.16% Dockerfile 0.07%

behavioral-model's Introduction

BEHAVIORAL MODEL (bmv2)

Build Status

This is the second version of the reference P4 software switch, nicknamed bmv2 (for behavioral model version 2). The software switch is written in C++11. It takes as input a JSON file generated from your P4 program by a P4 compiler and interprets it to implement the packet-processing behavior specified by that P4 program.

This repository contains code for several variations of the behavioral model, e.g. simple_switch, simple_switch_grpc, psa_switch, etc. See here for more details on the differences between these.

bmv2 is not meant to be a production-grade software switch. It is meant to be used as a tool for developing, testing and debugging P4 data planes and control plane software written for them. As such, the performance of bmv2 - in terms of throughput and latency - is significantly less than that of a production-grade software switch like Open vSwitch. For more information about the performance of bmv2, refer to this document.

Installing bmv2

Installing packaged versions of bmv2

bmv2 has package support for several Ubuntu and Debian distributions.

Ubuntu

A bmv2 package is available in the following repositories for Ubuntu 20.04 and newer.

. /etc/os-release
echo "deb http://download.opensuse.org/repositories/home:/p4lang/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/home:p4lang.list
curl -fsSL "https://download.opensuse.org/repositories/home:p4lang/xUbuntu_${VERSION_ID}/Release.key" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_p4lang.gpg > /dev/null
sudo apt update
sudo apt install p4lang-bmv2

Debian

For Debian 11 (Bullseye) it can be installed as follows:

echo 'deb http://download.opensuse.org/repositories/home:/p4lang/Debian_11/ /' | sudo tee /etc/apt/sources.list.d/home:p4lang.list
curl -fsSL https://download.opensuse.org/repositories/home:p4lang/Debian_11/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_p4lang.gpg > /dev/null
sudo apt update
sudo apt install p4lang-bmv2

If you cannot use a repository to install bmv2, you can download the .deb file for your release and install it manually. You need to download a new file each time you want to upgrade bmv2.

  1. Go to https://build.opensuse.org/package/show/home:p4lang/p4lang-bmv2, click on "Download package" and choose your operating system version.

  2. Install bmv2 by running the command below with the corresponding path where the package was downloaded.

sudo dpkg -i /path/to/package.deb

Installing bmv2 from source

  1. Clone the git repository.

    git clone https://github.com/p4lang/behavioral-model.git
  2. Install build dependencies. You can find specific instructions for Ubuntu 20.04 and Fedora below.

    Ubuntu 20.04

    sudo apt-get install -y automake cmake libgmp-dev \
        libpcap-dev libboost-dev libboost-test-dev libboost-program-options-dev \
        libboost-system-dev libboost-filesystem-dev libboost-thread-dev \
        libevent-dev libtool flex bison pkg-config g++ libssl-dev

    You also need to install the following from source. Feel free to use the install scripts under ci/.

    Fedora

    sudo dnf install -y automake cmake gmp-devel libpcap-devel \
        boost-devel boost-system boost-thread boost-filesystem boost-test \
        libevent-devel libtool flex bison pkg-config g++ openssl-devel \
        thrift-devel nanomsg-devel

    To use the CLI, you will need to install the nnpy Python package. Feel free to use ci/install-nnpy.sh.

    To make your life easier, we provide the install_deps.sh script, which will install all the dependencies needed on Ubuntu 20.04.

    Our CI tests now run on Ubuntu 20.04.

    On MacOS you can use the tools/macos/bootstrap_mac.sh script to install all the above dependencies using homebrew. Note that in order to compile the code you need XCode 8 or later.

  3. Building the code

    ./autogen.sh
    ./configure
    make
    sudo make install  # if you need to install bmv2

    In addition, on Linux, you may have to run sudo ldconfig after installing bmv2, to refresh the shared library cache.

    Debug logging is enabled by default. If you want to disable it for performance reasons, you can pass --disable-logging-macros to the configure script.

    In 'debug mode', you probably want to disable compiler optimization and enable symbols in the binary:

     ./configure 'CXXFLAGS=-O0 -g'
    

    The new bmv2 debugger can be enabled by passing --enable-debugger to configure.

Running the tests

To run the unit tests, simply do:

make check

If you get a nanomsg error when running the tests (make check), try running them as sudo

Running your P4 program

To run your own P4 programs in bmv2, you first need to compile the P4 code into a json representation which can be consumed by the software switch. This representation will tell bmv2 which tables to initialize, how to configure the parser, ...

There are currently 2 P4 compilers available for bmv2 on p4lang:

  • p4c includes a bmv2 backend and is the recommended compiler to use, as it supports both P4_14 and P4_16 programs. Refer to the README for information on how to install and use p4c. At the moment, the bmv2 p4c backend supports the v1model architecture, with some tentative support for the PSA architecture. P4_16 programs written for v1model can be executed with the simple_switch binary, while programs written for PSA can be executed with the psa_switch binary. See here for more details on the differences between these.
  • p4c-bm is the legacy compiler for bmv2 (no longer actively maintained) and only supports P4_14 programs.

Assuming you have installed the p4c compiler, you can obtain the json file for a P4_16 v1model program as follows:

p4c --target bmv2 --arch v1model --std p4-16 <prog>.p4

This will create a <prog>.json output file which can now be 'fed' to the bmv2 simple_switch binary:

sudo ./simple_switch -i 0@<iface0> -i 1@<iface1> <prog>.json

In this example <iface0> and <iface1> are the interfaces which are bound to the switch (as ports 0 and 1).

Using the CLI to populate tables...

The CLI code can be found at tools/runtime_CLI.py. It can be used like this:

./runtime_CLI.py --thrift-port 9090

The CLI connect to the Thrift RPC server running in each switch process. 9090 is the default value but of course if you are running several devices on your machine, you will need to provide a different port for each. One CLI instance can only connect to one switch device.

The CLI is realized using the Python's cmd module and supports auto-completion. If you inspect the code, you will see that the list of supported commands. This list includes:

- table_set_default <table name> <action name> <action parameters>
- table_add <table name> <action name> <match fields> => <action parameters> [priority]
- table_delete <table name> <entry handle>

The CLI include commands to program the multicast engine. Because we provide 2 different engines (SimplePre and SimplePreLAG), you have to specify which one your target is using when starting the CLI, using the --pre option. Accepted values are: None, SimplePre (default value) and SimplePreLAG. The l2_switch target uses the SimplePre engine, while the simple_switch target uses the SimplePreLAG engine.

You can take a look at the commands.txt file for l2_switch and simple_router to see how the CLI can be used.

Using the debugger

To enable the debugger, make sure that you passed the --enable-debugger flag to configure. You will also need to use the --debugger command line flag when starting the switch.

Use tools/p4dbg.py as follows when the switch is running to attach the debugger to the switch:

sudo ./p4dbg.py [--thrift-port <port>]

Displaying the event logging messages

To enable event logging when starting your switch, use the --nanolog command line option. For example, to use the ipc address ipc:///tmp/bm-log.ipc:

sudo ./simple_switch -i 0@<iface0> -i 1@<iface1> --nanolog ipc:///tmp/bm-log.ipc <path to JSON file>

Use tools/nanomsg_client.py as follows when the switch is running:

sudo ./nanomsg_client.py [--thrift-port <port>]

The script will display events of significance (table hits / misses, parser transitions, ...) for each packet.

Loading shared objects dynamically

Some targets (simple_switch and simple_switch_grpc) let the user load shared libraries dynamically at runtime. This is done by using the target-specific command-line option --load-modules, which takes as a parameter a comma-separated list of shared objects. This functionality is currently only available on systems where dlopen is available. Make sure that the shared objects are visible by the dynamic loader (e.g. by setting LD_LIBRARY_PATH appropriately on Linux). You can control whether this feature is available by using --enable-modules / --disable-modules when configuring bmv2. By default, this feature is enabled when dlopen is available.

Integrating with Mininet

We will provide more information in a separate document. However you can test the Mininet integration right away using our simple_router target.

In a first terminal, type the following:

- cd mininet
- sudo python3 1sw_demo.py --behavioral-exe ../targets/simple_router/simple_router --json ../targets/simple_router/simple_router.json

Then in a second terminal:

- cd targets/simple_router
- ./runtime_CLI < commands.txt

Now the switch is running and the tables have been populated. You can run pingall in Mininet or start a TCP flow with iperf between hosts h1 and h2.

When running a P4 program with simple_switch (instead of simple_router in the above example), just provide the appropriate simple_switch binary to 1sw_demo.py with --behavioral-exe.

FAQ

Why is throughput so low / why are so many packets dropped?

bmv2 is not meant to be a production-grade software switch. For more information on bmv2 performance, please refer to this document.

Why did we replace p4c-behavioral with bmv2?

  • The new C++ code is not auto-generated for each P4 program. This means that it becomes very easy and very fast to change your P4 program and test it again. The whole P4 development process becomes more efficient. Every time you change your P4 program, you simply need to produce the json for it using the p4c compiler and feed it to the bmv2 executable.
  • Because the bmv2 code is not auto-generated, we hope it is easier to understand. We hope this will encourage the community to contribute even more to the P4 software switch.
  • Using the auto-generated PD library (which of course still needs to be recompiled for each P4 program) is now optional. We provide an intuitive CLI which can be used to program the runtime behavior of each switch device.
  • The new code is target independent. While the original p4c-behavioral assumed a fixed abstract switch model with 2 pipelines (ingress and egress), bmv2 makes no such assumption and can be used to represent many switch architectures. Three different -although similar- such architectures can be found in the targets/ directory. If you are a networking company interested in programming your device (parser, match-action pipeline, deparser) with P4, you can use bmv2 to reproduce the behavior of your device.

How do program my own target / switch architecture using bmv2?

You can take a look at the targets/ directory first. We have also started writing some doxygen documentation specifically targetted at programmers who want to implement their own switch model using the bmv2 building blocks. You can generate this documentation yourself (if you have doxygen installed) by running doxygen Doxyfile. The output can be found under the doxygen-out directory. You can also browse this documentation online.

What else is new in bmv2?

  • Arithmetic is now possible on arbitrarily wide fields (no more limited to <= 32-bit fields) and variable-length fields are now supported.
  • We finally have unit tests!
  • While it is still incomplete, we provide a convenient 'event-logger' built on top of nanomsg. Every time a 'significant' event happens (e.g. table hit, parser transition,...) a message is broadcast on a nanomsg channel and any client can consume it.

Are all features supported yet?

At this time, we are aware of the following unsupported P4_14 features:

  • direct registers

If you find more missing features or if you would like to request that a specific feature be added, please send us an email ([email protected]) or submit an issue with the appropriate label on Github. Do not hesitate to contribute code yourself!

How do I signal a bug?

Please submit an issue with the appropriate label on Github.

How can I contribute?

See CONTRIBUTING.md.

behavioral-model's People

Contributors

anirudhsk avatar antoninbas avatar blp avatar davidesanvito avatar dependabot[bot] avatar derek-so avatar dkrdzic avatar dushyantarora avatar fruffy avatar hesingh avatar jafingerhut avatar jnfoster avatar liujed avatar matthewtlam avatar mbudiu-bfn avatar naoki9911 avatar omeranson avatar peteli3 avatar polly2014 avatar pudelkom avatar qobilidop avatar r12f avatar rst0git avatar sachinbahadur avatar sethfowler avatar smolkaj avatar sufuf3 avatar theojepsen avatar yunhel avatar yuri91 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

behavioral-model's Issues

Behavioral model does not build with the latest version of thrift

g++ -DHAVE_CONFIG_H -I. -I../.. -DBMLOG_DEBUG_ON -DBMLOG_TRACE_ON -DBMELOG_ON -I../../include -isystem../../third_party/jsoncpp/include -isystem../../third_party/spdlog -I./thrift/src/ -I./gen-cpp -Wall -Werror -Wextra -g -O2 -std=c++11 -MT gen-cpp/bm/simple_switch_constants.lo -MD -MP -MF gen-cpp/bm/.deps/simple_switch_constants.Tpo -c gen-cpp/bm/simple_switch_constants.cpp -o gen-cpp/bm/simple_switch_constants.o >/dev/null 2>&1
gen-cpp/bm/SimpleSwitch.cpp: In member function โ€˜uint32_t sswitch_runtime::SimpleSwitch_mirroring_mapping_add_args::write(apache::thrift::protocol::TProtocol*) constโ€™:
gen-cpp/bm/SimpleSwitch.cpp:66:10: error: โ€˜class apache::thrift::protocol::TProtocolโ€™ has no member named โ€˜incrementRecursionDepthโ€™
oprot->incrementRecursionDepth();

make error Problem

Hi, friends. I'm new P4...I'm sorry to take your time to look my problem.

When I followed the steps of Building the code:

1. ./autogen.sh
2. ./configure
3. make

It turns out:

g++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.8/README.Bugs> for instructions.
make[3]: *** [packet.lo] Error 1
make[3]: Leaving directory `/home/wasdns/behavioral-model/src/bm_sim'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/home/wasdns/behavioral-model/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/wasdns/behavioral-model'
make: *** [all] Error 2

I tried to fix the problem. I found the place: /behavioral-model/src/bm_sim/packet.cpp
I changed the content :

#include </home/wasdns/behavioral-model/include/bm/bm_sim/packet.h>

run gcc packet.cpp, it solved "header file not found" problem, but it turns out a lot of other problems:

ยทยทยทยทยทยท
/home/wasdns/behavioral-model/include/bm/bm_sim/phv.h:95:32:   required from here
/usr/include/c++/4.8/bits/stl_construct.h:83:7: error: use of deleted function โ€˜bm::Header::Header(const bm::Header&)โ€™
       ::new(static_cast<void*>(__p)) _T1(__value);
       ^
In file included from /home/wasdns/behavioral-model/include/bm/bm_sim/phv.h:38:0,
                 from /home/wasdns/behavioral-model/include/bm/bm_sim/phv_source.h:26,
                 from /home/wasdns/behavioral-model/include/bm/bm_sim/packet.h:39,
                 from packet.cpp:21:
/home/wasdns/behavioral-model/include/bm/bm_sim/headers.h:259:3: error: declared here
   Header(const Header &other) = delete;
   ^

It must be wrong. But I have no idea about it. I added "sudo" but it didn't work.

Thank you for watching my problem !

Install all utilities as a part of "make install"

The current "make install" only installs model executables, but doesn't install the CLI utilities, nanomsg logger or p4dbg.py

I think all these need to be installed. In fact, it would also make sense to install other tools, e.g. veth setup scripts.

MAC learning

Hi,

I am trying to set up an P4 Switch with MAC learning support. My P4 program is based on your behavioral-model 2 and your l2_switch implementation https://github.com/p4lang/behavioral-model/tree/master/targets/l2_switch
I guess this switch support MAC learning by calling the method generate_digest(). But actually it doesn't work. Source and destination MACs are not recognized for incoming packets. I checked via runtime_CLI if all tables and default actions are installed correctly - seems to be fine.

Is the learning functionality still under development?

Best regards,
Christian

simple_switch_CLI cannot be properly executed

simple_switch_CLI is installed in $(bindir) as an executable file.

It is a Python program, but, unfortunately, it lacks the first line, e.g.

!/usr/bin/env python

As a result it can't be run directly.

Add entries at run time without using runtime CLI(with c++)

I am implementing a protocol that learns how to forward packet when communicating with other switches. Therefore, I need to add entries at run time without using runtime CLI.
But I have some problem when implementing this.
I have started trying to make the action work for ECMP example first. Then, implement my own protocol next.

Eg. I want to do the following action in C++
table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00

I have tried to use C++ to implement this.
I have tried to view the source code and tried writing the following code.

//Connect to thrift
    boost::shared_ptr<TTransport> tsocket(new TSocket("localhost", 9090));
    boost::shared_ptr<TTransport> transport(new TBufferedTransport(tsocket));
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    boost::shared_ptr<TMultiplexedProtocol> standard_protocol(
            new TMultiplexedProtocol(protocol, "standard"));
    bm_client = boost::shared_ptr<bm_runtime::standard::StandardClient>(
            new bm_runtime::standard::StandardClient(standard_protocol));
    assert(bm_client);
    transport->open();


//Set table entries data
    runtime::BmMatchParam match_param;
    match_param.type = runtime::BmMatchParamType::type::EXACT;
    runtime::BmMatchParamExact match_param_exact;
    match_param_exact.key = std::string("1");
    match_param.__set_exact(match_param_exact);
    runtime::BmAddEntryOptions options;
    std::vector<std::string> my_action_data = { std::string("00:aa:bb:00:00:00") };
//Add to entry
    bm_client->bm_mt_add_entry(0, "send_frame", { match_param },"rewrite_mac", std::move(my_action_data), options);

But when my codes call to add table entry. The following exception occurs,

[22:49:27.508] [bmv2] [T] [thread 3784] bm_table_add_entry
[22:49:27.508] [bmv2] [E] [thread 3784] Error when trying to add entry to table 'send_frame'
terminate called after throwing an instance of 'bm_runtime::standard::InvalidTableOperation'
  what():  Default TException.

I am not sure how should I implement this.
Would any one please give me some tips for solving this problem?
Or are there any better ways to do this?
Thank you very much.

ERROR: Table '_____' is invoked multiple times.

I face to a problem that when I am going to do the same thing in different switch role I defined.
I have read the following and know that applying a table multiple times is normally not allowed.
http://lists.p4.org/pipermail/p4-dev_lists.p4.org/2016-June/000388.html

But in my case I will only invoke a table for once for different switch role.
Would there be any solution for my case to reduce duplication of P4 code and switch commands?

P4 Code:

    if(user_metadata.switch_role==0){ //ECMP
	if(valid(ipv4) and ipv4.ttl > 0) {

	    apply(ecmp_group);
	    apply(forward);

	}
    }else if(user_metadata.switch_role==1){//Expeditus-ToR
    	
        //the counter show P4 recgonized SYN
        if(tcp.ctrl==TCP_SYN){ 
    	    apply(increment_SYN_table);
            apply(expeditus_header_table);
            apply(ecmp_group);
            apply(forward);
    	}

    }

Error:
ERROR: Table 'ecmp_group' is invoked multiple times.

Add show_ports command

Please, add a "show_ports" command to the CLI (and the corresponding API and thrift to BMI) that will allow one to see the list of ports available on a running model as well as the corresponding mappings, such as

RuntimeCLI: show_ports

Port #               Interface        Pcap File
----------------------------------------------------
0                      veth0            veth0.pcap
1                      eth3
64                    veth250        veth250.pcap

Obviously, if one uses another mechanism (like nanomsg), the contents should be different (e.g. the name of nanomsg socket)

gcov reporting off

gcov report started including some third-party headers which decreased coverage significantly, needs to be fixed

bmi_port_interface_add

when I run ./behavioral-model ,I got an error like this .who can tell me why?
bmi_port_interface_add(port_mgr, veth_name, n_veth, pcap_filename): ERROR -1 at main.c:430

compilation issue in calculations.cpp

I am getting the following compilation error with gcc 5.2.1, which can be suppressed by ./configure CXXFLAGS="-Wno-error"

libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I../.. -DBMELOG_ON -I../../modules/bf_lpm_trie/include -isystem../../third_party/jsoncpp/include -isystem../../third_party/spdlog/include -I../../modules/BMI/include -I./include/ -DBMDEBUG_ON -Wall -Werror -Wextra -g -O2 -std=c++11 -MT src/calculations.lo -MD -MP -MF src/.deps/calculations.Tpo -c src/calculations.cpp  -fPIC -DPIC -o src/.libs/calculations.o
In file included from src/calculations.cpp:26:0:
src/calculations.cpp:68:15: error: 'bm::{anonymous}::xxh64_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(xxh64);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:88:15: error: 'bm::{anonymous}::crc16_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(crc16);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:102:15: error: 'bm::{anonymous}::crc32_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(crc32);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:116:15: error: 'bm::{anonymous}::crcCCITT_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(crcCCITT);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:164:15: error: 'bm::{anonymous}::cksum16_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(cksum16);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:172:15: error: 'bm::{anonymous}::csum16_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(csum16);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^
src/calculations.cpp:185:15: error: 'bm::{anonymous}::identity_create_' defined but not used [-Werror=unused-variable]
 REGISTER_HASH(identity);
               ^
./include/bm_sim/calculations.h:400:8: note: in definition of macro 'REGISTER_HASH'
   bool hash_name##_create_ =                                            \
        ^

bmv2 crashed during TCP connections

Hi all,

I am trying to implement a P4 program about modifying TCP fields.
However when I start the bmv2 and set up a TCP connection by using iperf, there is an error shows up.
lt-simple_switch: ../../include/bm/bm_sim/stateful.h:116: const bm::Register& bm::RegisterArray::operator[](size_t) const: Assertionidx < size()' failed.`
My topology like this :
+------+ +------------+ +------+
| PC1 | - - -| P4 Switch | - - - | PC2 |
+------+ +------------+ +------+

Does anyone have same problem?

Best regards,
Peter

modify_field doesn't work with metadata header

Hi Antonin,

There is possibly a bug in modify_field with metadata header type in bmv2.
Taking the router example below, after matched on ip_lookup table, the field next_hop of the metadata header is 0 while matching in the neighbor table.

// FILE: router.p4

header_type ethernet_t {
    fields {
        dl_dst : 48;
        dl_src : 48;
        dl_type : 16;
    }
}


header_type ipv4_t {
    fields {
        version : 4;
        ihl : 4;
        diffserv : 8;
        totalLen : 16;
        identification : 16;
        flags : 3;
        fragOffset : 13;
        ttl : 8;
        protocol : 8;
        hdrChecksum : 16;
        srcAddr : 32;
        dstAddr: 32;
    }
}


header_type routing_metadata_t {
    fields {
        next_hop : 32;
    }
}

#define IP_PROTOCOL 0x800

parser start {
    return parse_ethernet;
}

header ethernet_t eth;

parser parse_ethernet {
    extract(eth);
    return select(latest.dl_type) {
        IP_PROTOCOL : parse_ipv4;
        default : ingress;
    }
}


header ipv4_t ipv4;

parser parse_ipv4 {
    extract(ipv4);
    return ingress;
}

header routing_metadata_t routing;

action _drop() {
    drop();
}

action _nop() {

}

action set_outgoing_interface(port) {
    modify_field(standard_metadata.egress_spec, port);
}

action forward(port, next_hop) {
    set_outgoing_interface(port);
    modify_field(routing.next_hop, next_hop);
    modify_field(ipv4.ttl, ipv4.ttl-1);
}


table ip_lookup {
    reads {
        ipv4.dstAddr : lpm;
    } actions {
        forward;
        _drop;
    }
}

action rewrite_l2(dl_src, dl_dst) {
    modify_field(eth.dl_src, dl_src);
    modify_field(eth.dl_dst, dl_dst);
}

table neighbor {
    reads {
        routing.next_hop : exact;
    } actions {
        rewrite_l2;
        _nop;
    }
}

control ingress {
    apply(ip_lookup);
    apply(neighbor);
}
// Commands.txt
table_set_default ip_lookup _drop
table_set_default neighbor _nop
table_add ip_lookup forward 10.0.0.0/24 => 1 10.0.0.1
table_add neighbor rewrite_l2 10.0.0.1  => 1a:2b:3c:4d:5e:6f 6a:5b:4c:3d:2e:1f
// Bmv2 log

[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Pipeline 'ingress': start
[13:57:13.489] [bmv2] [T] [thread 19302] [0.0] [cxt 0] Applying table 'ip_lookup'
[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Looking up key:
* ipv4.dstAddr        : 0a000002

[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Table 'ip_lookup': hit with handle 0
[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Dumping entry 0
Match key:
* ipv4.dstAddr        : LPM       0a000000/24
Action entry: forward - 1,a000001,

[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Action entry is forward - 1,a000001,
[13:57:13.489] [bmv2] [T] [thread 19302] [0.0] [cxt 0] Applying table 'neighbor'
[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Looking up key:
* routing.next_hop    : 00000000

[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Table 'neighbor': miss
[13:57:13.489] [bmv2] [D] [thread 19302] [0.0] [cxt 0] Action entry is _nop - 

make error

When I run the following scripts,

1. ./autogen.sh 2. ./configure 3. make

it reports like this:

collect2: error: ld returned 1 exit status
Makefile:371: recipe for target 'simple_router' failed
make[3]: *** [simple_router] Error 1
make[3]: Leaving directory '/home/jy/sdn/p4/old/bmv2/targets/simple_router'
Makefile:364: recipe for target 'all-recursive' failed
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory '/home/jy/sdn/p4/old/bmv2/targets'
Makefile:436: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/home/jy/sdn/p4/old/bmv2'
Makefile:365: recipe for target 'all' failed
make: *** [all] Error 2

I have no idea what is wrong.
How can I fix it?

modify_field semantics: takes effect even when src or dest parent header invalid

According to the spec, modify_field should behave like this: "If the parent header instance of dest is not valid, the action has no effect. If value is a field reference and its parent header is not valid, the operation has no effect."

The attached files demonstrate that modify_field does have an effect when the parent header of dest is not valid, which by itself would not be a big problem (what's the harm in writing to an invalid header?), except that modify_field also has an effect when the parent header of the value parameter (the 'source') is not valid.

modify_field_test.txt
commands.txt
nano_out.txt

Why simple_switch target doesn't have p4 file?

I studied the targets directory in this repository.

And I notice that l2_switch target has a file named "l2_switch.p4",

simple_router target also has a file named "simple_router.p4".

But simple_switch target does not have any p4 file.

Any one can explain this? Thanks in advance.

Failed to 'fed' json file to bmv2

I was following the instruction on behavioral-model-repository, and built the code and passed the unit tests. But I had problems on running P4 program, i.e. the step where json file being 'fed' to bmv2:

sudo ./simple_switch -i 0@<iface0> -i 1@<iface1> <path to JSON file>

For simplicity to show the problem, I typed as follows:

sudo simple_switch

and the command line didn't recognized this command

Then I tried:

make install
sudo simple_switch

Output:

simple_switch: error while loading shared libraries: libruntimestubs.so.0: cannot open shared object file: No such file or directory

Interestingly, I also download the VM provided in 2015 P4 Bootcamp Labs Guild, and under the directory ~/bmv2, which seems to be very similar to behavioral-model-repository, I tried:

sudo simple_switch

it immediately prompted for usage info:

Usage: SWITCH_NAME [options] <path to JSON config file>
Options:
(neglected for simplicity)

It seems that I got some installation issue on my original VM, but what did I miss?

Also, how "simple_switch" being recognized as a command?

Besides, before running the 'feeding', veth pairs should be setup in advance, my veth pair setup is done through the script tools/veth_setup.sh. But the instruction doesn't mention about it, which can be tricky for beginners. Additionally related information is recommended.

add get_config command to CLI

From the perspective of a controller that dynamically discovers a network of bmv2-based targets (e.g. in mininet), it would be helpful to have a command to retrieve the currently running model configuration as a json formatted string.

Thanks,
Carmelo

pop semantics: bottom fields not invalidated

When popping from a header stack, the bottom-most fields that had nothing shifted into them should be invalidated, according to both language specs 1.0.2 and 1.1.0, but it appears this is not happening. The attached files demonstrate code (pop_test.txt) that checks whether both elements of a two-element header stack are valid, both before and after popping one element from the header stack. Nano output shows that even after the pop, both elements are valid, though only the first element should be valid.
commands.txt
nano_out.txt
pop_test.txt

I performed this test after pulling the latest repos for behavioral-model and p4c-bm and performing all setup steps for each per the README for each repo.

Scheduler// Timer

I need a "very quick" and regularly looping timer for doing some actions continuous calculation.

The following is the properties I need:

  • doing things regularly and accurately
    (eg .do somethings exactly every 100 microsecond (1.0 ร— 10-6 seconds )without pausing between)
    (Could be slower if not possible)

I have read the documents ,but seems that what I need cannot be fulfilled with "Match + action" model.
Is there any solution to do this with P4?

As I did not find solution, I have tried creating a thread in C++ to loop very quickly. Every iteration can be done in 100 microsecond. But seems that due to CPU scheduling, the process/ thread will be paused for while.

For example:

For every 100 microsecond
      do action
For evey second
      Display number of time of action

Normally I should get about 10000 times action, but due to CPU scheduling, I only get about 4 thousand times action.

Could I have any better way to do it in P4?

syntax error in runtime_CLI.py

I'm following the instructions in the README, trying to run the simple_router target. The first step works OK:

# bash run.sh
Thrift port was not specified, will use 9090
Adding interface veth1 as port 0
Adding interface veth3 as port 1
Adding interface veth5 as port 2
Adding interface veth7 as port 3
Thrift server was started

But runtime_CLI.py throws an error:

# ./runtime_CLI --json simple_router.json < commands.txt
Traceback (most recent call last):
  File "./runtime_CLI", line 38, in <module>
    from bm_runtime.standard import Standard
  File "/mnt/home/vmhome/bmv2/tools/bm_runtime/standard/Standard.py", line 368
    def bm_register_write_range(self, cxt_id, register_array_name, from, to, value):
                                                                      ^
SyntaxError: invalid syntax

This seems to be due to 483373e, which added bm_register_write_range. It has a from parameter, and that is obviously reserved in python. Rename the parameter?

SIGABRT in get_control_node

simple_switch crashes on the following input (note, the program has been trimmed down to demonstrate the bug)

header_type intrinsic_metadata_t {
    fields {
        mgid : 4;
    }
}

header_type eth_t {
    fields {
        dstAddr : 48;
        srcAddr : 48;
        etherType : 16;
    }
}

header_type vlan_tag_t {
    fields {
        tag : 16;
        etherType : 16;
    }
}

header_type ipv4_t {
    fields {
        version : 4;
        ihl : 4;
        diffserv : 8;
        totalLen : 16;
        identification : 16;
        flags : 3;
        fragOffset : 13;
        ttl : 8;
        protocol : 8;
        hdrChecksum : 16;
        src_ip3 : 8;
        src_ip2 : 8;
        src_ip1 : 8;
        src_ip0 : 8;
        dst_ip3 : 8;
        dst_ip2 : 8;
        dst_ip1 : 8;
        dst_ip0 : 8;
    }
}

metadata intrinsic_metadata_t intrinsic_metadata;
header eth_t eth;
header vlan_tag_t vlan;
header ipv4_t ip4;

parser start {
    return parse_ethernet;
}

#define ETHERTYPE_VLAN 0x8100, 0x9100, 0x9200, 0x9300
#define ETHERTYPE_IPV4 0x0800


parser parse_vlan {
    extract(vlan);
    return select(latest.etherType) {
        ETHERTYPE_IPV4 : parse_ipv4;
    }
}

parser parse_ethernet {
    extract(eth);
    return select(latest.etherType) {
        ETHERTYPE_VLAN : parse_vlan;
        ETHERTYPE_IPV4 : parse_ipv4;
    }
}

parser parse_ipv4 {
    extract(ip4);
    return ingress;
}

action a_set4() {
}
table set4 {
    actions {a_set4;}
}

control ingress {
        if (valid(vlan)) {
                apply(set4);
                if (valid(vlan)) {
                }
        }
        }

The problem seems to be triggered by the nested valid() checks in the control program and is related to some violated assumption about control flow graph structure in the compiler. Here is the stack trace:

Core was generated by `/home/l.ryzhyk/projects/cocoon/p4/bmv2/targets/simple_switch/.libs/lt-simple_sw'.
Program terminated with signal SIGABRT, Aborted.
#0  0x00007f77072e5418 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
[Current thread is 1 (Thread 0x7f7709bba9c0 (LWP 23718))]
(gdb) bt
#0  0x00007f77072e5418 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007f77072e701a in __GI_abort () at abort.c:89
#2  0x00007f7707c2784d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007f7707c256b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007f7707c25701 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007f7707c25919 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007f7707c4e2bf in std::__throw_out_of_range(char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00000000004d9615 in std::__detail::_Map_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, bm::ControlFlowNode*>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, bm::ControlFlowNode*> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>, true>::at (this=0x236f348, __k="_condition_1")
    at /usr/include/c++/5/bits/hashtable_policy.h:665
#8  0x00000000004cf01d in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bm::ControlFlowNode*, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, bm::ControlFlowNode*> > >::at (this=0x236f348, __k="_condition_1") at /usr/include/c++/5/bits/unordered_map.h:689
#9  0x00000000004ca5d4 in bm::P4Objects::get_control_node (this=0x236f130, name="_condition_1") at ../../include/bm/bm_sim/P4Objects.h:131
#10 0x00000000004bae8c in bm::P4Objects::<lambda(const Json::Value&)>::operator()(const Json::Value &) const (__closure=0x7ffc4268d280, cfg_next_node=...) at P4Objects.cpp:853
#11 0x00000000004c0faa in bm::P4Objects::init_objects (this=0x236f130, is=0x7ffc4268daa0, lookup_factory=0x956530 <bm::SwitchWContexts::default_lookup_factory>, device_id=27, cxt_id=0, 
    notifications_transport=std::shared_ptr (count 5, weak 0) 0x2375110, required_fields=std::set with 5 elements = {...}, arith_fields=std::set with 15 elements = {...}) at P4Objects.cpp:885
#12 0x000000000051f194 in bm::Context::init_objects (this=0x236ef60, is=0x7ffc4268daa0, lookup_factory=0x956530 <bm::SwitchWContexts::default_lookup_factory>, required_fields=std::set with 5 elements = {...}, 
    arith_fields=std::set with 15 elements = {...}) at context.cpp:512
#13 0x00000000005cacf1 in bm::SwitchWContexts::init_objects (this=0x236ea30, json_path="f10/f10.s27.json", dev_id=27, transport=std::shared_ptr (empty) 0x0) at switch.cpp:92
#14 0x00000000005cb041 in bm::SwitchWContexts::init_from_command_line_options (this=0x236ea30, argc=24, argv=0x7ffc4268e0b8) at switch.cpp:128
#15 0x000000000044b4b7 in main (argc=24, argv=0x7ffc4268e0b8) at main.cpp:34

retrieve link status in p4

Is there a way to retrieve information about the links connected to a device?

I want to simulate a link failure and wondered if there is some kind of data telling me if a link is down?

Right now i have a additional table to indicate a simulated link failure.
Is there another way to do this? Like when i remove a link in mininet the device gets some kind of information about that?

connecting eth0 to bmv2

Hi ,
I have attached a eth0 (real netdev interface of nic ) to the bmv2(c++) switch. I did that by passing the eth0 as a parameter along with the json file to the switch, while configuring the switch with the compiled p4 program. Now I want to know in which port in the bmv2 switch will receive the packets. I mean is there a mapping like the following. I assumed this kind of mapping as I saw something similar in one of the tutorial slide.

app switch(bmv2)
veth0-->veth1 (port0)
veth2-->veth3 (port1)
veth4-->veth5 (port2)
veth6-->veth7 (port3)

Also could someone point me to the source code file where veth1, veth3, veth5 are instantiated in the bmv2 switch.

How to build docker image

I need to build a docker image of bmv2 .Could someone help me.

Hi Vladimir,
I have a question, hope you will be able to answer. I want to run many docker containers of a p4 switch in a multi core server.My aim is to distribute the traffic(say real traffic from a 10 G NIC) to all these containers so that the processing is faster. Say I have calculating some hash values on the incoming traffic and I want to do it faster by running many instances of the p4 switch and distribute the traffic to all these containers.
Do you think it can be done ? I am looking forward for your reply.

Incorrect bitvector slicing behavior

[Using P4-16] Assigning to a bitvector slice produces an incorrect result when run on bmv2.

To reproduce:

register<bit<8>>(1) debug;
apply {
    bit<8> n = 8w0b11111111;
    n[7:4] = 4w0;
    debug.write(0, n);
}

Send a single packet through the switch. From the thrift CLI, run

>> register_read debug 0
debug[0] = 0

Expected: 15 ( = 0b00001111).

I'm attaching the source file for reference, which is a barebones switch containing the above snippet.
basic.p4.txt

Other comments:

  • If n = 8w0 and is rewritten with n[7:5] = ~4w0, the above problem doesn't occur. debug[1] is as expected in both cases. Seems to only be a problem if the original bits are non-zero and the replaced bits are 0.
  • This bug also occurs if the LSBs are reset.
  • This works for other bit widths (I also tried 32 and 64 with the same result).
  • Strangely, I observe the correct behavior if I write n to a register before resetting its MSBs:
register<bit<8>>(32w2) debug;
apply {
    bit<8> n = ~8w0;  // All 1s
    debug.write(0, n);
    n[7:4] = 4w0;
    debug.write(1, n);
}
>> register_read debug 0
debug[0] = 255
>> register_read debug 1
debug[1] = 15

which is expected.

is P4 really device independent?

Hi everyone,
I am new to P4. I was trying to understand how P4 works. So, I started reading the code as well some PDF files on the workshops. I found out that P4 is compiled by p4c-mbv2 and converted to a Json file. This Json file later is fed to bmv2 which is bunch of c++ codes. So whenever I want to run a P4 program, I pick up a target, like simple_switch, and then I can run it through the following command:
simple_switch test.json "some other parameters"
As a result, I guess P4 is just a kind of data coding more comfortable for switch programmers which in deed gets converted to Json coding to be used later by bmv2.
My question is now that how can we claim bmv2 is device independent since it is only bunch of c++ codes and we know c++ compiler is not machine independent? In other words, how is it possible to to run P4 simultaneously on CPUs , GPUs or even FPGAs since P4 compiler (bmv2) is written in c++?

Regards,
Alireza.

Cannot connect and not forward properly after adding switch role(with mininet)

I am adding a switch_role metadata in switch to let administrator to change role in run time CLI making switches perform differently for different role.

I was trying to use ECMP example to test it. However, after implemented, I test it in mininet. I find it make the switch not working.
(Before adding the code it work correctly in both mininet and localhost)
(After adding the code it seems perform correctly when running localhost as switch.
eg. switch role=0 , it work as ecmp,
eg. switch role =1, it do not perform actions(I will implement other role later
But not perform properly in mininet(cannot connect runtime CLI and not forward properly))

I loaded some commands into switch. It show commands are successfully loaded for the first time.
But the switch do not performs properly to forward the packets.
Then I run the run time CLI again it will shows the following error message

Could not connect to thrift client on port 9094
Make sure the switch is running and that you have the right port

The following is the code I added in ECMP example to try adding the switch role.
(I just using the register for tracking the whether switch role is set correctly)

header_type intrinsic_metadata_t {
    fields {
        switch_role : 4;
    }
}
metadata intrinsic_metadata_t intrinsic_metadata;


action init_switch_role(role_number){
    register_write(switch_role,1,role_number);  
    modify_field(intrinsic_metadata.switch_role,role_number);
}


register switch_role{
    width:32;
    static:switch_role_table;
    instance_count:16384 ;
}

table switch_role_table {
    actions {
        init_switch_role;
    }
    size : 16384;
}
control ingress {
    apply(switch_role_table);//get switch role
    if(intrinsic_metadata.switch_role==0){ //ECMP
        if(valid(ipv4) and ipv4.ttl > 0) {
            apply(ecmp_group);
            apply(forward);
        }
    }
}

control egress {
    if(intrinsic_metadata.switch_role==0){ //ECMP
        apply(send_frame);
    }
}

infinite recursion in pcap_file.cpp

There is a bug in the implementation of src/bm_sim/pcap_file.cpp.

In particular there is an infinite recursion chain of these functions:

PcapFilesReader::scan() -> PcapFilesReader::schedulePacket() -> PcapFilesReader::timerFired() -> PcapFilesReader::scan()

The recursion ends only when the pcap file reaches EOF.

A simple solution would be to add a loop in scan() and remove the recursive call to it in timerFired():

--- pcap_file.cpp   2016-05-20 18:55:33.376173690 +0200
+++ new.cpp 2016-05-20 18:56:19.229550733 +0200
@@ -184,6 +184,7 @@

 void
 PcapFilesReader::scan() {
+  while (true) {
   if (nonEmptyFiles == 0) {
     BMLOG_DEBUG("Pcap reader: end of all input files");
     // notifyAllEnd();
@@ -237,6 +238,7 @@

   schedulePacket((unsigned)earliest_index, &delay);
 }
+}


 void PcapFilesReader::timerFired() {
@@ -251,7 +253,6 @@
   bool success = file->moveNext();
   if (!success)
     nonEmptyFiles--;
-  scan();
 }

See more logging detail of switches in mininet

I know that I can see logs of switches in mininet with following tool.
./tools/nanomsg_client.py --thrift-port 9094

However,for switches in mininet, is there any way to show more details like --log-console with directly running the switch in localhost?
eg1.
What command is added with parameters

RuntimeCmd: Adding entry to exact match table send_frame
match key:           EXACT-00:01
action:              rewrite_mac
runtime data:        00:0c:00:00:00:12


eg2.
What data is being looked up

[08:42:32.275] [bmv2] [D] [thread 25179] [499.0] [cxt 0] Looking up key:
* ipv4.dstAddr        : 0a000001

eg3.
What condition is being matched

[08:42:32.275] [bmv2] [D] [thread 25179] [499.0] [cxt 0] Dumping entry 0
Match key:
* ipv4.dstAddr        : LPM       0a000001/32
Index: group(0)
Group members:
  mbr 1: set_nhop - a000101,1,
  mbr 2: set_nhop - a000201,2,


1sw_demo.py

  1. File executable bit not set
  2. No error on wrong --behavioral-exe and --json parameters, log looks same...
  3. simple_switch is installed as bmv2 engine, maybe it valuable to install mininet script as well?

Cascading Switch Instances

Is there any way to run and interconnect multiple instances of the software switch? I want to simulate a network that consists of two or more switch instances.

Activating Queue Function failed

Hi all,

I am trying to active the queue module in bmv2 by using the method mentioned from this link.
(http://lists.p4.org/pipermail/p4-dev_lists.p4.org/2016-May/000314.html)

The simple_switch bmv2 target supports multiple egress queues per port with
strict priority scheduling (only algorithm available at this time).
However, this cannot be activated at runtime yet. You will need to
uncomment this line in the simple_switch target implementation and
recompile:
https://github.com/p4lang/behavioral-model/blob/master/targets/simple_switch/simple_switch.h#L42.

However, when I used command "make check" and its failed. The error log is down below:

FAIL: test_packet_redirect
../../../test-driver: line 107: 19708 Aborted "$@" > $log_file 2>&1
FAIL: test_truncate
../../../test-driver: line 107: 19737 Aborted "$@" > $log_file 2>&1
FAIL: test_swap
../../../test-driver: line 107: 19766 Aborted "$@" > $log_file 2>&1
FAIL: test_queueing

Then I ran 2 sample codes (meter and simple nat), but it also failed and showed this error message:

terminate called after throwing an instance of 'std::out_of_range'
what(): _Map_base::at

How can I enable the queuing function in bmv2?

increase performance of bmv2 / simple_switch

Even though this is not the primary design goal of bmv2, the following ideas can be investigated:

  1. use a stack allocator in appropriate cases for class ByteContainer
  2. use a custom allocator for libgmp, could also speed up the phv::reset() operation used by simple_switch
  3. investigate replacement for libpcap to speed up I/O
  4. cache header and field ids in simple_switch instead of always looking up fields by name
  5. exact match cache for ternary match lookup

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.