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
|
- `register`: how to use registers in P4 and read / write the state from the
|
||||||
control plane
|
control plane
|
||||||
- `counter`: how to use counters in P4
|
- `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
|
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
|
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