P4-16 switch: recirculate() example
[Topology]
H1-s1--s2----h2
|_s3_|
|
H3
http://lists.p4.org/pipermail/p4-dev_lists.p4.org/2016-June/002119.html Based on this post, I try to write a recirculate() example.
In this lab, h1 will ping h2 with different tos values. If the packet sent by h1 with TOS value equal to 1 to 10, the switch will decrease the value to 0. So h2 will get the packet with TOS=0. If the packet sent by h1 with other TOS values, the switch will keep the value.
[topology.p4]
|
{ "hosts": [ "h1", "h2", "h3" ], "switches": { "s1": { "cli_input" : "s1-commands.txt" }, "s2": { "cli_input" : "s2-commands.txt" }, "s3": { "cli_input" : "s3-commands.txt" } }, "links": [ ["h1", "s1"], ["s1", "s2"], ["s1", "s3"], ["s3", "s2"], ["s2", "h2"], ["s3", "h3"] ] } |
[s1-commands.txt]
|
table_set_default ipv4_lpm drop table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:00:01:01 1 table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:02:02:00 2 table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:03:03:00 3 |
[s2-commands.txt]
|
table_set_default ipv4_lpm drop table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:01:02:00 2 table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:00:02:02 1 table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:03:03:00 3 |
[s3-commands.txt]
|
table_set_default ipv4_lpm drop table_add ipv4_lpm ipv4_forward 10.0.1.1/32 => 00:00:00:01:03:00 2 table_add ipv4_lpm ipv4_forward 10.0.2.2/32 => 00:00:00:02:03:00 3 table_add ipv4_lpm ipv4_forward 10.0.3.3/32 => 00:00:00:00:03:03 1 |
[basic.p4]
|
/* -*- P4_16 -*-
*/ #include
<core.p4> #include
<v1model.p4> const
bit<16> TYPE_IPV4 = 0x800; /************************************************************************* ***********************
H E A D E R S
*********************************** *************************************************************************/ typedef
bit<9> egressSpec_t; typedef
bit<48> macAddr_t; typedef
bit<32> ip4Addr_t; header
ethernet_t { macAddr_t dstAddr; macAddr_t srcAddr; bit<16> etherType; } header ipv4_t { bit<4> version; bit<4> ihl; bit<8> diffserv; bit<16> totalLen; bit<16> identification; bit<3> flags; bit<13> fragOffset; bit<8> ttl; bit<8> protocol; bit<16> hdrChecksum; ip4Addr_t srcAddr; ip4Addr_t dstAddr; } struct metadata
{ /* empty */ } struct headers { ethernet_t ethernet; ipv4_t ipv4; } /************************************************************************* ***********************
P A R S E R
*********************************** *************************************************************************/ parser
MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) { state start {
transition parse_ethernet; } state parse_ethernet {
packet.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
TYPE_IPV4: parse_ipv4;
default: accept; } } state parse_ipv4 {
packet.extract(hdr.ipv4);
transition accept; } } /************************************************************************* ************ C H E C K S U M V E R I F I C A T I O
N ************* *************************************************************************/ control
MyVerifyChecksum(inout headers hdr, inout metadata meta) { apply { } } /************************************************************************* ************** I N G R E S S P R O C E S S I N G ******************* *************************************************************************/ control
MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) { action drop() {
mark_to_drop(); } action
ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
standard_metadata.egress_spec = port;
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = dstAddr;
hdr.ipv4.ttl = hdr.ipv4.ttl - 1; } table ipv4_lpm {
key = {
hdr.ipv4.dstAddr: lpm; }
actions = {
ipv4_forward;
drop;
NoAction; } size
= 1024;
default_action = NoAction(); } apply { if
(hdr.ipv4.isValid()) {
ipv4_lpm.apply(); } } } /************************************************************************* **************** E G R E S S P R O C E S S I N G ******************* *************************************************************************/ control
MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) { action set_mytos() { hdr.ipv4.diffserv=hdr.ipv4.diffserv-1; recirculate<headers>(hdr); } table set_tos {
key = {
hdr.ipv4.diffserv: range; }
actions = { set_mytos;
NoAction; }
size = 1024;
default_action = NoAction(); const
entries = { 1..10 :
set_mytos(); _
: NoAction(); } } apply {
set_tos.apply(); } } /************************************************************************* ************* C H E C K S U M C O M P U T A T I O N ************** *************************************************************************/ control
MyComputeChecksum(inout headers
hdr, inout metadata meta) { apply { update_checksum( hdr.ipv4.isValid(),
{ hdr.ipv4.version, hdr.ipv4.ihl,
hdr.ipv4.diffserv,
hdr.ipv4.totalLen,
hdr.ipv4.identification,
hdr.ipv4.flags,
hdr.ipv4.fragOffset,
hdr.ipv4.ttl,
hdr.ipv4.protocol,
hdr.ipv4.srcAddr,
hdr.ipv4.dstAddr },
hdr.ipv4.hdrChecksum,
HashAlgorithm.csum16); } } /************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/ control
MyDeparser(packet_out packet, in headers hdr) { apply { packet.emit(hdr.ethernet);
packet.emit(hdr.ipv4); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
[Execution]
If the h1 send the
packets with TOS=11, then

If the h1 send the
packets with TOS=5, then

If the h1 send the
packets with TOS=3, then

Dr. Chih-Heng Ke (smallko@gmail.com)
Department
of Computer Science and Information Engineering,
National
Quemoy University, Kinmen, Taiwan.