GithubHelp home page GithubHelp logo

p4lang / behavioral-model Goto Github PK

View Code? Open in Web Editor NEW
525.0 46.0 326.0 33.27 MB

The reference P4 software switch

License: Apache License 2.0

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

behavioral-model's Issues

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,


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 !

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?

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.

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?

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.

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

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_ =                                            \
        ^

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.

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.

gcov reporting off

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

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.

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?

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.

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.

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?

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

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.

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.

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

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

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

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 - 

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

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.

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.

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

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

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.

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?

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)

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

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.