added resubmit example
This commit is contained in:
parent
97b2a77733
commit
6d8a0232dc
@ -13,7 +13,8 @@ included:
|
||||
- `register`: how to use registers in P4 and read / write the state from the
|
||||
control plane
|
||||
- `counter`: how to use counters in P4
|
||||
- `action_profile`: how to use action profiles in P4, using ECMP has support
|
||||
- `action_profile`: how to use action profiles in P4, using ECMP as support
|
||||
- `resubmit`: how to resubmit packets to the ingress pipelines
|
||||
|
||||
All examples are orgranized the same way, with a `p4src` directory containing
|
||||
the P4 source code, and a `README` file describing the P4 program and explaining
|
||||
|
28
examples/resubmit/README.md
Normal file
28
examples/resubmit/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Resubmit
|
||||
|
||||
## Description
|
||||
|
||||
This program illustrates as simply as possible how to use the `resubmit()`
|
||||
primitive. This primitive is used to make a packet go twice through the ingress
|
||||
pipeline. For more information, please refer to the P4 specification.
|
||||
|
||||
The P4 program only consists of an ingress pipeline, with 2 tables:
|
||||
`t_ingress_1` and `t_ingress_2`. When a packet enters the pipeline, the
|
||||
following happens (based on the P4 program and the [commands.txt] (commands.txt)
|
||||
files):
|
||||
- the packet hits `table_ingress_1` and the egress port is set to 2.
|
||||
- the packet hits `table_ingress_2`, `mymeta.f1` is set to 1 and the
|
||||
`resubmit()` primitive is called. Because `mymeta` is resubmitted along with
|
||||
the packet, `mymeta.f1` will now be equal to 1 for the second pass.
|
||||
- the packet hits `table_ingress_1`, this time the egress port is set to 3.
|
||||
- the packet hits `table_ingress_2` which is a no-op.
|
||||
|
||||
### Running the demo
|
||||
|
||||
We provide a small demo to let you test the program. It consists of the
|
||||
following scripts, which you need to run one after the other, in 2 separate
|
||||
terminals:
|
||||
- [run_switch.sh] (run_switch.sh): compile the P4 program and starts the switch,
|
||||
also configures the data plane by running the CLI [commands] (commands.txt).
|
||||
- [send_and_receive.py] (send_and_receive.py): send a packet on port 0 (veth1),
|
||||
wait for the forwarded packet on port 3 (veth7).
|
5
examples/resubmit/commands.txt
Normal file
5
examples/resubmit/commands.txt
Normal file
@ -0,0 +1,5 @@
|
||||
table_set_default t_ingress_1 _nop
|
||||
table_set_default t_ingress_2 _nop
|
||||
table_add t_ingress_1 set_port 0 => 2
|
||||
table_add t_ingress_1 set_port 1 => 3
|
||||
table_add t_ingress_2 _resubmit 0 =>
|
101
examples/resubmit/p4src/resubmit.p4
Normal file
101
examples/resubmit/p4src/resubmit.p4
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
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 intrinsic_metadata_t {
|
||||
fields {
|
||||
mcast_grp : 4;
|
||||
egress_rid : 4;
|
||||
mcast_hash : 16;
|
||||
lf_field_list : 32;
|
||||
resubmit_flag : 16;
|
||||
}
|
||||
}
|
||||
|
||||
header_type mymeta_t {
|
||||
fields {
|
||||
f1 : 8;
|
||||
}
|
||||
}
|
||||
|
||||
header ethernet_t ethernet;
|
||||
metadata intrinsic_metadata_t intrinsic_metadata;
|
||||
metadata mymeta_t mymeta;
|
||||
|
||||
parser start {
|
||||
return parse_ethernet;
|
||||
}
|
||||
|
||||
parser parse_ethernet {
|
||||
extract(ethernet);
|
||||
return ingress;
|
||||
}
|
||||
|
||||
action _drop() {
|
||||
drop();
|
||||
}
|
||||
|
||||
action _nop() {
|
||||
}
|
||||
|
||||
action set_port(port) {
|
||||
modify_field(standard_metadata.egress_spec, port);
|
||||
}
|
||||
|
||||
field_list resubmit_FL {
|
||||
standard_metadata;
|
||||
mymeta;
|
||||
}
|
||||
|
||||
action _resubmit() {
|
||||
modify_field(mymeta.f1, 1);
|
||||
resubmit(resubmit_FL);
|
||||
}
|
||||
|
||||
table t_ingress_1 {
|
||||
reads {
|
||||
mymeta.f1 : exact;
|
||||
}
|
||||
actions {
|
||||
_nop; set_port;
|
||||
}
|
||||
size : 128;
|
||||
}
|
||||
|
||||
table t_ingress_2 {
|
||||
reads {
|
||||
mymeta.f1 : exact;
|
||||
}
|
||||
actions {
|
||||
_nop; _resubmit;
|
||||
}
|
||||
size : 128;
|
||||
}
|
||||
|
||||
control ingress {
|
||||
apply(t_ingress_1);
|
||||
apply(t_ingress_2);
|
||||
}
|
||||
|
||||
control egress {
|
||||
}
|
41
examples/resubmit/run_switch.sh
Executable file
41
examples/resubmit/run_switch.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/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/targets/simple_switch/sswitch_CLI
|
||||
|
||||
# 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/resubmit.p4 --json resubmit.json
|
||||
sudo echo "sudo" > /dev/null
|
||||
sudo $BMV2_PATH/targets/simple_switch/simple_switch resubmit.json \
|
||||
-i 0@veth0 -i 1@veth2 -i 2@veth4 -i 3@veth6 -i 4@veth8 \
|
||||
--nanolog ipc:///tmp/bm-0-log.ipc --log-console \
|
||||
--pcap &
|
||||
sleep 2
|
||||
$CLI_PATH resubmit.json < commands.txt
|
||||
echo "READY!!!"
|
||||
fg
|
29
examples/resubmit/send_and_receive.py
Normal file
29
examples/resubmit/send_and_receive.py
Normal file
@ -0,0 +1,29 @@
|
||||
from scapy.all import *
|
||||
import sys
|
||||
import threading
|
||||
|
||||
|
||||
class Receiver(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def received(self, p):
|
||||
print "Received packet on port 3, exiting"
|
||||
sys.exit(0)
|
||||
|
||||
def run(self):
|
||||
sniff(iface="veth7", prn=lambda x: self.received(x))
|
||||
|
||||
|
||||
def main():
|
||||
Receiver().start()
|
||||
|
||||
p = Ether(src="aa:aa:aa:aa:aa:aa") / IP(dst="10.0.1.10") / TCP() / "aaaaaaaaaaaaaaaaaaa"
|
||||
|
||||
print "Sending packet on port 0, listening on port 3"
|
||||
time.sleep(1)
|
||||
sendp(p, iface="veth1", verbose=0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user