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.