Merge pull request #8 from p4lang/workshop-05-16
added ECMP exercise for May 2016 P4 workshop
This commit is contained in:
commit
dd4c556be5
2
SIGCOMM_2015/.gitignore → .gitignore
vendored
2
SIGCOMM_2015/.gitignore → .gitignore
vendored
@ -10,4 +10,4 @@
|
|||||||
*.pcap
|
*.pcap
|
||||||
|
|
||||||
# Extracted solutions
|
# Extracted solutions
|
||||||
solution/
|
solution*/
|
@ -80,9 +80,9 @@ like this:
|
|||||||
|
|
||||||
You need to tell us where you cloned the `bmv2` and `p4c-bm` repositories
|
You need to tell us where you cloned the `bmv2` and `p4c-bm` repositories
|
||||||
:). Please update the values of the shell variables `BMV2_PATH` and
|
:). Please update the values of the shell variables `BMV2_PATH` and
|
||||||
`P4C_BM_PATH` in the `env.sh` file - located in this directory. Note that if you
|
`P4C_BM_PATH` in the `env.sh` file - located in the root directory of this
|
||||||
cloned both repositories in the same directory as this one (`tutorials`), you
|
repository. Note that if you cloned both repositories in the same directory as
|
||||||
will not need to change the value of the variables.
|
this one (`tutorials`), you will not need to change the value of the variables.
|
||||||
|
|
||||||
That's all :)
|
That's all :)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/simple_router.p4 --json simple_router.json
|
$P4C_BM_SCRIPT p4src/simple_router.p4 --json simple_router.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch simple_router.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH simple_router.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -25,7 +25,9 @@ SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch
|
|||||||
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
||||||
|
|
||||||
$P4C_BM_SCRIPT p4src/source_routing.p4 --json source_routing.json
|
$P4C_BM_SCRIPT p4src/source_routing.p4 --json source_routing.json
|
||||||
|
# This gives libtool the opportunity to "warm-up"
|
||||||
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
sudo PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
sudo PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
||||||
--behavioral-exe $BMV2_PATH/targets/simple_switch/simple_switch \
|
--behavioral-exe $SWITCH_PATH \
|
||||||
--json source_routing.json \
|
--json source_routing.json \
|
||||||
--cli $CLI_PATH
|
--cli $CLI_PATH
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
# ---------------- EDIT THIS ------------------
|
# ---------------- EDIT THIS ------------------
|
||||||
BMV2_PATH=$THIS_DIR/../../bmv2
|
BMV2_PATH=$THIS_DIR/../bmv2
|
||||||
# e.g. BMV2_PATH=$THIS_DIR/../bmv2
|
# e.g. BMV2_PATH=$THIS_DIR/../bmv2
|
||||||
P4C_BM_PATH=$THIS_DIR/../../p4c-bmv2
|
P4C_BM_PATH=$THIS_DIR/../p4c-bmv2
|
||||||
# e.g P4C_BM_PATH=$THIS_DIR/../p4c-bm
|
# e.g P4C_BM_PATH=$THIS_DIR/../p4c-bm
|
||||||
# ---------------- END ------------------
|
# ---------------- END ------------------
|
10
examples/.gitignore
vendored
10
examples/.gitignore
vendored
@ -1,10 +0,0 @@
|
|||||||
# Python byte code
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Emacs
|
|
||||||
*~
|
|
||||||
|
|
||||||
# Compiled JSON
|
|
||||||
*.json
|
|
||||||
|
|
||||||
*.pcap
|
|
@ -55,9 +55,9 @@ build the code once all the dependencies have been installed:
|
|||||||
|
|
||||||
You need to tell us where you cloned the `bmv2` and `p4c-bm` repositories
|
You need to tell us where you cloned the `bmv2` and `p4c-bm` repositories
|
||||||
:). Please update the values of the shell variables `BMV2_PATH` and
|
:). Please update the values of the shell variables `BMV2_PATH` and
|
||||||
`P4C_BM_PATH` in the `env.sh` file - located in this directory. Note that if you
|
`P4C_BM_PATH` in the `env.sh` file - located in the root directory of this
|
||||||
cloned both repositories in the same directory as this one (`tutorials`), you
|
repository. Note that if you cloned both repositories in the same directory as
|
||||||
will not need to change the value of the variables.
|
this one (`tutorials`), you will not need to change the value of the variables.
|
||||||
|
|
||||||
You will also need to run the `veth_setup.sh` script included in this directory
|
You will also need to run the `veth_setup.sh` script included in this directory
|
||||||
as `sudo` to setup the veth interfaces needed by the switch.
|
as `sudo` to setup the veth interfaces needed by the switch.
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/TLV_parsing.p4 --json TLV_parsing.json
|
$P4C_BM_SCRIPT p4src/TLV_parsing.p4 --json TLV_parsing.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch TLV_parsing.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH TLV_parsing.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/action_profile.p4 --json action_profile.json
|
$P4C_BM_SCRIPT p4src/action_profile.p4 --json action_profile.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch action_profile.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH action_profile.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -25,7 +25,9 @@ SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch
|
|||||||
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
||||||
|
|
||||||
$P4C_BM_SCRIPT p4src/axon.p4 --json axon.json
|
$P4C_BM_SCRIPT p4src/axon.p4 --json axon.json
|
||||||
|
# This gives libtool the opportunity to "warm-up"
|
||||||
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
sudo PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
sudo PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
||||||
--behavioral-exe $BMV2_PATH/targets/simple_switch/simple_switch \
|
--behavioral-exe $SWITCH_PATH \
|
||||||
--json axon.json \
|
--json axon.json \
|
||||||
--cli $CLI_PATH
|
--cli $CLI_PATH
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/copy_to_cpu.p4 --json copy_to_cpu.json
|
$P4C_BM_SCRIPT p4src/copy_to_cpu.p4 --json copy_to_cpu.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch copy_to_cpu.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH copy_to_cpu.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/counter.p4 --json counter.json
|
$P4C_BM_SCRIPT p4src/counter.p4 --json counter.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch counter.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH counter.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
|
||||||
|
|
||||||
# ---------------- EDIT THIS ------------------
|
|
||||||
BMV2_PATH=$THIS_DIR/../../bmv2
|
|
||||||
# e.g. BMV2_PATH=$THIS_DIR/../bmv2
|
|
||||||
P4C_BM_PATH=$THIS_DIR/../../p4c-bmv2
|
|
||||||
# e.g P4C_BM_PATH=$THIS_DIR/../p4c-bm
|
|
||||||
# ---------------- END ------------------
|
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/meter.p4 --json meter.json
|
$P4C_BM_SCRIPT p4src/meter.p4 --json meter.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch meter.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH meter.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/register.p4 --json register.json
|
$P4C_BM_SCRIPT p4src/register.p4 --json register.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch register.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH register.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc \
|
--nanolog ipc:///tmp/bm-0-log.ipc \
|
||||||
--pcap
|
--pcap
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -30,8 +30,9 @@ CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
|||||||
# process back in the foreground
|
# process back in the foreground
|
||||||
set -m
|
set -m
|
||||||
$P4C_BM_SCRIPT p4src/resubmit.p4 --json resubmit.json
|
$P4C_BM_SCRIPT p4src/resubmit.p4 --json resubmit.json
|
||||||
sudo echo "sudo" > /dev/null
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch resubmit.json \
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH resubmit.json \
|
||||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
--nanolog ipc:///tmp/bm-0-log.ipc --log-console \
|
--nanolog ipc:///tmp/bm-0-log.ipc --log-console \
|
||||||
--pcap &
|
--pcap &
|
||||||
|
@ -21,7 +21,7 @@ fi
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
@ -46,8 +46,10 @@ sysctl net.ipv6.conf.$intf0.disable_ipv6=1
|
|||||||
sysctl net.ipv6.conf.$intf1.disable_ipv6=1
|
sysctl net.ipv6.conf.$intf1.disable_ipv6=1
|
||||||
|
|
||||||
$P4C_BM_SCRIPT p4src/simple_nat.p4 --json simple_nat.json
|
$P4C_BM_SCRIPT p4src/simple_nat.p4 --json simple_nat.json
|
||||||
|
# This gives libtool the opportunity to "warm-up"
|
||||||
|
$SWITCH_PATH >/dev/null 2>&1
|
||||||
PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \
|
||||||
--behavioral-exe $BMV2_PATH/targets/simple_switch/simple_switch \
|
--behavioral-exe $SWITCH_PATH \
|
||||||
--json simple_nat.json \
|
--json simple_nat.json \
|
||||||
--cli $CLI_PATH \
|
--cli $CLI_PATH \
|
||||||
--thrift-port 22222
|
--thrift-port 22222
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
source $THIS_DIR/../env.sh
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI
|
||||||
|
|
||||||
|
6
workshop_05_2016/ecmp/.starter_code/commands.txt
Normal file
6
workshop_05_2016/ecmp/.starter_code/commands.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
table_set_default send_frame _drop
|
||||||
|
table_set_default forward _drop
|
||||||
|
table_set_default ipv4_lpm _drop
|
||||||
|
table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00
|
||||||
|
table_add forward set_dmac 10.0.1.1 => 00:04:00:00:00:00
|
||||||
|
table_add ipv4_lpm set_nhop 10.0.0.1/32 => 10.0.1.1 1
|
190
workshop_05_2016/ecmp/.starter_code/p4src/simple_router.p4
Normal file
190
workshop_05_2016/ecmp/.starter_code/p4src/simple_router.p4
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/* Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header_type ethernet_t {
|
||||||
|
fields {
|
||||||
|
dstAddr : 48;
|
||||||
|
srcAddr : 48;
|
||||||
|
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;
|
||||||
|
srcAddr : 32;
|
||||||
|
dstAddr: 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type tcp_t {
|
||||||
|
fields {
|
||||||
|
srcPort : 16;
|
||||||
|
dstPort : 16;
|
||||||
|
seqNo : 32;
|
||||||
|
ackNo : 32;
|
||||||
|
dataOffset : 4;
|
||||||
|
res : 3;
|
||||||
|
ecn : 3;
|
||||||
|
ctrl : 6;
|
||||||
|
window : 16;
|
||||||
|
checksum : 16;
|
||||||
|
urgentPtr : 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser start {
|
||||||
|
return parse_ethernet;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ETHERTYPE_IPV4 0x0800
|
||||||
|
|
||||||
|
header ethernet_t ethernet;
|
||||||
|
|
||||||
|
parser parse_ethernet {
|
||||||
|
extract(ethernet);
|
||||||
|
return select(latest.etherType) {
|
||||||
|
ETHERTYPE_IPV4 : parse_ipv4;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header ipv4_t ipv4;
|
||||||
|
|
||||||
|
field_list ipv4_checksum_list {
|
||||||
|
ipv4.version;
|
||||||
|
ipv4.ihl;
|
||||||
|
ipv4.diffserv;
|
||||||
|
ipv4.totalLen;
|
||||||
|
ipv4.identification;
|
||||||
|
ipv4.flags;
|
||||||
|
ipv4.fragOffset;
|
||||||
|
ipv4.ttl;
|
||||||
|
ipv4.protocol;
|
||||||
|
ipv4.srcAddr;
|
||||||
|
ipv4.dstAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_list_calculation ipv4_checksum {
|
||||||
|
input {
|
||||||
|
ipv4_checksum_list;
|
||||||
|
}
|
||||||
|
algorithm : csum16;
|
||||||
|
output_width : 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculated_field ipv4.hdrChecksum {
|
||||||
|
verify ipv4_checksum;
|
||||||
|
update ipv4_checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IP_PROTOCOLS_TCP 6
|
||||||
|
|
||||||
|
parser parse_ipv4 {
|
||||||
|
extract(ipv4);
|
||||||
|
return select(latest.protocol) {
|
||||||
|
IP_PROTOCOLS_TCP : parse_tcp;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header tcp_t tcp;
|
||||||
|
|
||||||
|
parser parse_tcp {
|
||||||
|
extract(tcp);
|
||||||
|
return ingress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
action _drop() {
|
||||||
|
drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type routing_metadata_t {
|
||||||
|
fields {
|
||||||
|
nhop_ipv4 : 32;
|
||||||
|
// TODO: if you need extra metadata for ECMP, define it here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata routing_metadata_t routing_metadata;
|
||||||
|
|
||||||
|
action set_nhop(nhop_ipv4, port) {
|
||||||
|
modify_field(routing_metadata.nhop_ipv4, nhop_ipv4);
|
||||||
|
modify_field(standard_metadata.egress_spec, port);
|
||||||
|
add_to_field(ipv4.ttl, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table ipv4_lpm {
|
||||||
|
reads {
|
||||||
|
ipv4.dstAddr : lpm;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
set_nhop;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
action set_dmac(dmac) {
|
||||||
|
modify_field(ethernet.dstAddr, dmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table forward {
|
||||||
|
reads {
|
||||||
|
routing_metadata.nhop_ipv4 : exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
set_dmac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
action rewrite_mac(smac) {
|
||||||
|
modify_field(ethernet.srcAddr, smac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table send_frame {
|
||||||
|
reads {
|
||||||
|
standard_metadata.egress_port: exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
rewrite_mac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
control ingress {
|
||||||
|
if(valid(ipv4) and ipv4.ttl > 0) {
|
||||||
|
// TODO: implement ECMP here
|
||||||
|
apply(ipv4_lpm);
|
||||||
|
apply(forward);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
control egress {
|
||||||
|
apply(send_frame);
|
||||||
|
}
|
98
workshop_05_2016/ecmp/README.md
Normal file
98
workshop_05_2016/ecmp/README.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# Implementing ECMP on top of simple_router.p4
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
simple_router.p4 is a very simple P4 program which does L3 routing. All the P4
|
||||||
|
code can be found in the [p4src/simple_router.p4] (p4src/simple_router.p4)
|
||||||
|
file. In this exercise we will try to build ECMP on top of the starter code. We
|
||||||
|
will be assuming the following network topology:
|
||||||
|
|
||||||
|
```
|
||||||
|
--------------------------------- nhop-0 10.0.1.1
|
||||||
|
| 00:04:00:00:00:00
|
||||||
|
1 - 00:aa:bb:00:00:00
|
||||||
|
|
|
||||||
|
-------- 3--sw
|
||||||
|
|
|
||||||
|
2 - 00:aa:bb:00:00:01
|
||||||
|
|
|
||||||
|
--------------------------------- nhop-1 10.0.2.1
|
||||||
|
00:04:00:00:00:01
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that we do not assign IPv4 addresses to the 3 switch interfaces, we do not
|
||||||
|
need to for this exercise.
|
||||||
|
We will be sending test packets on interface `3` of the switch. These packets
|
||||||
|
will have destination IP `10.0.0.1`. We will assume that both `nhop-0` and
|
||||||
|
`nhop-1` have a path to `10.0.0.1`, which is the final destination of our test
|
||||||
|
packets.
|
||||||
|
|
||||||
|
## Running the starter code
|
||||||
|
|
||||||
|
*Before starting make sure that you run `sudo ./veth_setup.sh` to create the
|
||||||
|
veth pairs required for the demo.*
|
||||||
|
|
||||||
|
To compile and run the starter code, simply use `./run_demo.sh`. The
|
||||||
|
[run_demo.sh] (run_demo.sh) script will run the P4 compiler (for bmv2), start
|
||||||
|
the switch and populate the tables using the CLI commands from [commands.txt]
|
||||||
|
(commands.txt).
|
||||||
|
|
||||||
|
When the switch is running, you can send test packets with `sudo
|
||||||
|
./run_test.py`. Note that this script will take a few seconds to complete. The
|
||||||
|
test sends a few hundred identical TCP packets through the switch, in bursts,
|
||||||
|
on port 3. If you take a look at the P4 code and at commands.txt, you will see
|
||||||
|
that each TCP packet is forwarded out of port 1; since we do not have ECMP
|
||||||
|
working yet.
|
||||||
|
|
||||||
|
## What you need to do
|
||||||
|
|
||||||
|
1. In this exercise, you need to update the provided [P4 program]
|
||||||
|
(p4src/simple_router.p4) to perform ECMP. When you are done, each incoming TCP
|
||||||
|
test packet should be forwarded to either port 1 or port 2, based on the result
|
||||||
|
of a crc16 hash computation performed on the TCP 5-tuple (`ipv4.srcAddr`,
|
||||||
|
`ipv4.dstAddr`, `ipv4.protocol`, `tcp.srcPort`, `tcp.dstPort`). You will need to
|
||||||
|
refer to the [P4 spec] (http://p4.org/wp-content/uploads/2015/04/p4-latest.pdf)
|
||||||
|
to familiarize yourself with the P4 constructs you will need.
|
||||||
|
|
||||||
|
2. Once you are done with the P4 code, you will need to update [commands.txt]
|
||||||
|
(commands.txt) to configure your new tables.
|
||||||
|
|
||||||
|
3. After that you can run the above test again. Once again, you will observe
|
||||||
|
that all packets go to the same egress port. Don't panic :)! This is because all
|
||||||
|
packets are identical and therefore are forwarded in the same way, If you add
|
||||||
|
`--random-dport` when running `sudo ./run_test.py`, you should observe an even
|
||||||
|
distribution for the ports. This option assigns a random destination port to
|
||||||
|
each test TCP packet (the 5-tuple is different, so the hash is likely to be
|
||||||
|
different).
|
||||||
|
|
||||||
|
## Hints and directions
|
||||||
|
|
||||||
|
1. You can easily check the syntax of your P4 program with `p4-validate <path to
|
||||||
|
simple_router.p4>`.
|
||||||
|
|
||||||
|
2. There are 2 major ways of implementing ECMP on top of simple_router.p4. The
|
||||||
|
first one requires 2 tables and the use of the
|
||||||
|
`modify_field_with_hash_based_offset` primitive. The second one uses a single
|
||||||
|
table with an action profile. You can read about
|
||||||
|
`modify_field_with_hash_based_offset` and action profiles in the [P4 spec]
|
||||||
|
(http://p4.org/wp-content/uploads/2015/04/p4-latest.pdf).
|
||||||
|
|
||||||
|
3. If you choose to use the first way (with 2 tables), your first table will
|
||||||
|
match on the destination IP address and be in charge of computing an index
|
||||||
|
(using `modify_field_with_hash_based_offset`), while the second table will match
|
||||||
|
on this computed index to obtain the outgoing interface. This is a high level
|
||||||
|
view of what needs to be implemented in P4.
|
||||||
|
```
|
||||||
|
T1
|
||||||
|
IP_prefix_1 ---> "random" index in [0, 1] using modify_field_with_hash_based_offset
|
||||||
|
IP_prefix_2 ---> "random" index in [2, 4] ...
|
||||||
|
...
|
||||||
|
|
||||||
|
T2
|
||||||
|
index(0) ---> nhop A
|
||||||
|
index(1) ---> nhop B
|
||||||
|
index(2) ---> nhop C
|
||||||
|
index(3) ---> nhop D
|
||||||
|
index(4) ---> nhop E
|
||||||
|
```
|
||||||
|
Remember that `T1` and `T2`'s entries will come from your modified commands.txt.
|
6
workshop_05_2016/ecmp/commands.txt
Normal file
6
workshop_05_2016/ecmp/commands.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
table_set_default send_frame _drop
|
||||||
|
table_set_default forward _drop
|
||||||
|
table_set_default ipv4_lpm _drop
|
||||||
|
table_add send_frame rewrite_mac 1 => 00:aa:bb:00:00:00
|
||||||
|
table_add forward set_dmac 10.0.1.1 => 00:04:00:00:00:00
|
||||||
|
table_add ipv4_lpm set_nhop 10.0.0.1/32 => 10.0.1.1 1
|
190
workshop_05_2016/ecmp/p4src/simple_router.p4
Normal file
190
workshop_05_2016/ecmp/p4src/simple_router.p4
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/* Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
header_type ethernet_t {
|
||||||
|
fields {
|
||||||
|
dstAddr : 48;
|
||||||
|
srcAddr : 48;
|
||||||
|
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;
|
||||||
|
srcAddr : 32;
|
||||||
|
dstAddr: 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type tcp_t {
|
||||||
|
fields {
|
||||||
|
srcPort : 16;
|
||||||
|
dstPort : 16;
|
||||||
|
seqNo : 32;
|
||||||
|
ackNo : 32;
|
||||||
|
dataOffset : 4;
|
||||||
|
res : 3;
|
||||||
|
ecn : 3;
|
||||||
|
ctrl : 6;
|
||||||
|
window : 16;
|
||||||
|
checksum : 16;
|
||||||
|
urgentPtr : 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser start {
|
||||||
|
return parse_ethernet;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ETHERTYPE_IPV4 0x0800
|
||||||
|
|
||||||
|
header ethernet_t ethernet;
|
||||||
|
|
||||||
|
parser parse_ethernet {
|
||||||
|
extract(ethernet);
|
||||||
|
return select(latest.etherType) {
|
||||||
|
ETHERTYPE_IPV4 : parse_ipv4;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header ipv4_t ipv4;
|
||||||
|
|
||||||
|
field_list ipv4_checksum_list {
|
||||||
|
ipv4.version;
|
||||||
|
ipv4.ihl;
|
||||||
|
ipv4.diffserv;
|
||||||
|
ipv4.totalLen;
|
||||||
|
ipv4.identification;
|
||||||
|
ipv4.flags;
|
||||||
|
ipv4.fragOffset;
|
||||||
|
ipv4.ttl;
|
||||||
|
ipv4.protocol;
|
||||||
|
ipv4.srcAddr;
|
||||||
|
ipv4.dstAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_list_calculation ipv4_checksum {
|
||||||
|
input {
|
||||||
|
ipv4_checksum_list;
|
||||||
|
}
|
||||||
|
algorithm : csum16;
|
||||||
|
output_width : 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculated_field ipv4.hdrChecksum {
|
||||||
|
verify ipv4_checksum;
|
||||||
|
update ipv4_checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IP_PROTOCOLS_TCP 6
|
||||||
|
|
||||||
|
parser parse_ipv4 {
|
||||||
|
extract(ipv4);
|
||||||
|
return select(latest.protocol) {
|
||||||
|
IP_PROTOCOLS_TCP : parse_tcp;
|
||||||
|
default: ingress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header tcp_t tcp;
|
||||||
|
|
||||||
|
parser parse_tcp {
|
||||||
|
extract(tcp);
|
||||||
|
return ingress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
action _drop() {
|
||||||
|
drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
header_type routing_metadata_t {
|
||||||
|
fields {
|
||||||
|
nhop_ipv4 : 32;
|
||||||
|
// TODO: if you need extra metadata for ECMP, define it here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata routing_metadata_t routing_metadata;
|
||||||
|
|
||||||
|
action set_nhop(nhop_ipv4, port) {
|
||||||
|
modify_field(routing_metadata.nhop_ipv4, nhop_ipv4);
|
||||||
|
modify_field(standard_metadata.egress_spec, port);
|
||||||
|
add_to_field(ipv4.ttl, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
table ipv4_lpm {
|
||||||
|
reads {
|
||||||
|
ipv4.dstAddr : lpm;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
set_nhop;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
action set_dmac(dmac) {
|
||||||
|
modify_field(ethernet.dstAddr, dmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table forward {
|
||||||
|
reads {
|
||||||
|
routing_metadata.nhop_ipv4 : exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
set_dmac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
action rewrite_mac(smac) {
|
||||||
|
modify_field(ethernet.srcAddr, smac);
|
||||||
|
}
|
||||||
|
|
||||||
|
table send_frame {
|
||||||
|
reads {
|
||||||
|
standard_metadata.egress_port: exact;
|
||||||
|
}
|
||||||
|
actions {
|
||||||
|
rewrite_mac;
|
||||||
|
_drop;
|
||||||
|
}
|
||||||
|
size: 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
control ingress {
|
||||||
|
if(valid(ipv4) and ipv4.ttl > 0) {
|
||||||
|
// TODO: implement ECMP here
|
||||||
|
apply(ipv4_lpm);
|
||||||
|
apply(forward);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
control egress {
|
||||||
|
apply(send_frame);
|
||||||
|
}
|
49
workshop_05_2016/ecmp/run_demo.sh
Executable file
49
workshop_05_2016/ecmp/run_demo.sh
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
|
|
||||||
|
source $THIS_DIR/../../env.sh
|
||||||
|
|
||||||
|
P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py
|
||||||
|
|
||||||
|
SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch
|
||||||
|
|
||||||
|
CLI_PATH=$BMV2_PATH/tools/runtime_CLI.py
|
||||||
|
|
||||||
|
# Probably not very elegant but it works nice here: we enable interactive mode
|
||||||
|
# to be able to use fg. We start the switch in the background, sleep for 2
|
||||||
|
# minutes to give it time to start, then add the entries and put the switch
|
||||||
|
# process back in the foreground
|
||||||
|
set -m
|
||||||
|
$P4C_BM_SCRIPT p4src/simple_router.p4 --json simple_router.json
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "p4 compilation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# This gets root permissions, and gives libtool the opportunity to "warm-up"
|
||||||
|
sudo $SWITCH_PATH >/dev/null 2>&1
|
||||||
|
sudo $SWITCH_PATH simple_router.json \
|
||||||
|
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||||
|
--log-console \
|
||||||
|
--pcap &
|
||||||
|
sleep 2
|
||||||
|
echo "**************************************"
|
||||||
|
echo "Sending commands to switch through CLI"
|
||||||
|
echo "**************************************"
|
||||||
|
$CLI_PATH --json simple_router.json < commands.txt
|
||||||
|
echo "READY!!!"
|
||||||
|
fg
|
147
workshop_05_2016/ecmp/run_test.py
Executable file
147
workshop_05_2016/ecmp/run_test.py
Executable file
@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Copyright 2013-present Barefoot Networks, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
NUM_PACKETS = 500
|
||||||
|
|
||||||
|
import random
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import threading
|
||||||
|
from scapy.all import sniff
|
||||||
|
from scapy.all import Ether, IP, IPv6, TCP
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='run_test.py')
|
||||||
|
parser.add_argument('--random-dport',
|
||||||
|
help='Use a random TCP dest port for each packet',
|
||||||
|
action="store_true", default=False)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
class PacketQueue:
|
||||||
|
def __init__(self):
|
||||||
|
self.pkts = []
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
self.ifaces = set()
|
||||||
|
|
||||||
|
def add_iface(self, iface):
|
||||||
|
self.ifaces.add(iface)
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
self.lock.acquire()
|
||||||
|
if not self.pkts:
|
||||||
|
self.lock.release()
|
||||||
|
return None, None
|
||||||
|
pkt = self.pkts.pop(0)
|
||||||
|
self.lock.release()
|
||||||
|
return pkt
|
||||||
|
|
||||||
|
def add(self, iface, pkt):
|
||||||
|
if iface not in self.ifaces:
|
||||||
|
return
|
||||||
|
self.lock.acquire()
|
||||||
|
self.pkts.append( (iface, pkt) )
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
|
queue = PacketQueue()
|
||||||
|
|
||||||
|
def pkt_handler(pkt, iface):
|
||||||
|
if IPv6 in pkt:
|
||||||
|
return
|
||||||
|
queue.add(iface, pkt)
|
||||||
|
|
||||||
|
class SnifferThread(threading.Thread):
|
||||||
|
def __init__(self, iface, handler = pkt_handler):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.iface = iface
|
||||||
|
self.handler = handler
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
sniff(
|
||||||
|
iface = self.iface,
|
||||||
|
prn = lambda x: self.handler(x, self.iface)
|
||||||
|
)
|
||||||
|
|
||||||
|
class PacketDelay:
|
||||||
|
def __init__(self, bsize, bdelay, imin, imax, num_pkts = 100):
|
||||||
|
self.bsize = bsize
|
||||||
|
self.bdelay = bdelay
|
||||||
|
self.imin = imin
|
||||||
|
self.imax = imax
|
||||||
|
self.num_pkts = num_pkts
|
||||||
|
self.current = 1
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if self.num_pkts <= 0:
|
||||||
|
raise StopIteration
|
||||||
|
self.num_pkts -= 1
|
||||||
|
if self.current == self.bsize:
|
||||||
|
self.current = 1
|
||||||
|
return random.randint(self.imin, self.imax)
|
||||||
|
else:
|
||||||
|
self.current += 1
|
||||||
|
return self.bdelay
|
||||||
|
|
||||||
|
|
||||||
|
pkt = Ether()/IP(dst='10.0.0.1', ttl=64)/TCP()
|
||||||
|
|
||||||
|
port_map = {
|
||||||
|
1: "veth3",
|
||||||
|
2: "veth5",
|
||||||
|
3: "veth7"
|
||||||
|
}
|
||||||
|
|
||||||
|
iface_map = {}
|
||||||
|
for p, i in port_map.items():
|
||||||
|
iface_map[i] = p
|
||||||
|
|
||||||
|
queue.add_iface("veth3")
|
||||||
|
queue.add_iface("veth5")
|
||||||
|
|
||||||
|
for p, iface in port_map.items():
|
||||||
|
t = SnifferThread(iface)
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
send_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
|
||||||
|
socket.htons(0x03))
|
||||||
|
send_socket.bind((port_map[3], 0))
|
||||||
|
|
||||||
|
delays = PacketDelay(10, 5, 25, 100, NUM_PACKETS)
|
||||||
|
ports = []
|
||||||
|
print "Sending", NUM_PACKETS, "packets ..."
|
||||||
|
for d in delays:
|
||||||
|
# sendp is too slow...
|
||||||
|
# sendp(pkt, iface=port_map[3], verbose=0)
|
||||||
|
if args.random_dport:
|
||||||
|
pkt["TCP"].dport = random.randint(1025, 65535)
|
||||||
|
send_socket.send(str(pkt))
|
||||||
|
time.sleep(d / 1000.)
|
||||||
|
time.sleep(1)
|
||||||
|
iface, pkt = queue.get()
|
||||||
|
while pkt:
|
||||||
|
ports.append(iface_map[iface])
|
||||||
|
iface, pkt = queue.get()
|
||||||
|
print ports
|
||||||
|
print "DISTRIBUTION..."
|
||||||
|
for p in port_map:
|
||||||
|
c = ports.count(p)
|
||||||
|
print "port {}: {:>3} [ {:>5}% ]".format(p, c, 100. * c / NUM_PACKETS)
|
BIN
workshop_05_2016/ecmp/solution_1.tar.gz
Normal file
BIN
workshop_05_2016/ecmp/solution_1.tar.gz
Normal file
Binary file not shown.
BIN
workshop_05_2016/ecmp/solution_2.tar.gz
Normal file
BIN
workshop_05_2016/ecmp/solution_2.tar.gz
Normal file
Binary file not shown.
26
workshop_05_2016/ecmp/veth_setup.sh
Executable file
26
workshop_05_2016/ecmp/veth_setup.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
noOfVeths=18
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
noOfVeths=$1
|
||||||
|
fi
|
||||||
|
echo "No of Veths is $noOfVeths"
|
||||||
|
idx=0
|
||||||
|
let "vethpairs=$noOfVeths/2"
|
||||||
|
while [ $idx -lt $vethpairs ]
|
||||||
|
do
|
||||||
|
intf0="veth$(($idx*2))"
|
||||||
|
intf1="veth$(($idx*2+1))"
|
||||||
|
idx=$((idx + 1))
|
||||||
|
if ! ip link show $intf0 &> /dev/null; then
|
||||||
|
ip link add name $intf0 type veth peer name $intf1
|
||||||
|
ip link set dev $intf0 up
|
||||||
|
ip link set dev $intf1 up
|
||||||
|
TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash"
|
||||||
|
for TOE_OPTION in $TOE_OPTIONS; do
|
||||||
|
/sbin/ethtool --offload $intf0 "$TOE_OPTION" off
|
||||||
|
/sbin/ethtool --offload $intf1 "$TOE_OPTION" off
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
sysctl net.ipv6.conf.$intf0.disable_ipv6=1
|
||||||
|
sysctl net.ipv6.conf.$intf1.disable_ipv6=1
|
||||||
|
done
|
Loading…
x
Reference in New Issue
Block a user