Source Routing for p4_16 (Add the routing information at the ingress switch of network): Method 2

[Topology]

Please read http://csie.nqu.edu.tw/smallko/sdn/mysource_routing.htm first.

In this lab, we can set a single rule to indicate the routing information at the ingress switch of network.

h1-s4-s2-s3-s5-h2 (we can indicate the rule as table_add ipv4_lpm   set_path  10.0.5.2/32 => 4 1 3 2 2 0 0 0 0 0)

4 means that we need to pass 4 switches. 1 means the output port of s5, 3 means the output port of s3, 2 means the output port of s2 and 2 means the output port of s4. In this version of p4 code, the packet can be transmitted by the max number of 9 switches.

 

h1-s4-s2-s1-s3-s5-h2(table_add ipv4_lpm set_path  10.0.5.2/32 => 5 1 3 2 1 2 0 0 0 0)

 

[topology.json]

{

    "hosts": [

        "h1",

        "h2"

    ],

    "switches": {

        "s1": { "cli_input" : "s1-commands.txt" },

        "s2": { "cli_input" : "s2-commands.txt" },

        "s3": { "cli_input" : "s3-commands.txt" },

        "s4": { "cli_input" : "s4-commands.txt" },

        "s5": { "cli_input" : "s5-commands.txt" } 

    },

    "links": [

        ["h1", "s4"], ["s4", "s2"], ["s2", "s3", 0, 0.5],

        ["s2", "s1", 0, 0.5], ["s1", "s3"], ["s3", "s5"],

        ["s5", "h2"]

    ]

}

 

s4-command.txt

table_add ipv4_lpm   set_path  10.0.5.2/32 => 4 1 3 2 2 0 0 0 0 0

#table_add ipv4_lpm   set_path  10.0.5.2/32 => 5 1 3 2 1 2 0 0 0 0

table_add ipv4_final dmac 10.0.4.1/32 => 00:00:00:00:04:01

 

s5-command.txt

table_add ipv4_lpm   set_path  10.0.4.1/32 => 4 1 3 2 2 0 0 0 0 0

table_add ipv4_final dmac 10.0.5.2/32 => 00:00:00:00:05:02

 

source_routing.p4

/* -*- P4_16 -*- */

#include <core.p4>

#include <v1model.p4>

 

const bit<16> TYPE_IPV4 = 0x800;

const bit<16> TYPE_SRCROUTING = 0x1234;

 

#define MAX_HOPS 9

 

register<bit<32>>(10) path;

 

/*************************************************************************

*********************** 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 srcRoute_t {

    bit<1>    bos;

    bit<15>   port;

}

 

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 {

    bit<4>    num;

    bit<32>   val1;

    bit<32>   val2;     

}

 

struct headers {

    ethernet_t              ethernet;

    srcRoute_t[MAX_HOPS]    srcRoutes;

    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_SRCROUTING: parse_srcRouting;

            TYPE_IPV4: parse_ipv4;

            default: accept;

        }

    }

 

    state parse_srcRouting {

        packet.extract(hdr.srcRoutes.next);

        transition select(hdr.srcRoutes.last.bos) {

            1: parse_ipv4;

            default: parse_srcRouting;

        }

    }

 

    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 srcRoute_nhop() {

        standard_metadata.egress_spec = (bit<9>)hdr.srcRoutes[0].port;

        hdr.srcRoutes.pop_front(1);

    }

 

    action srcRoute_finish() {

        hdr.ethernet.etherType = TYPE_IPV4;

    }

 

    action update_ttl(){

        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;

    }

 

    action AddHeader(bit<15> port, bit<1> flag){

        hdr.ethernet.etherType = TYPE_SRCROUTING;

            hdr.srcRoutes.push_front(1);

            hdr.srcRoutes[0].setValid();

            hdr.srcRoutes[0].port=port; 

        hdr.srcRoutes[0].bos=flag;      

    }

 

    action set_path(bit<4> num, bit<32> port1, bit<32> port2, bit<32> port3, bit<32> port4, bit<32> port5, bit<32> port6, bit<32> port7, bit<32> port8, bit<32> port9) {

      path.write((bit<32>)0, (bit<32>)num);

        path.write((bit<32>)1, (bit<32>)port1);

        path.write((bit<32>)2, (bit<32>)port2);

        path.write((bit<32>)3, (bit<32>)port3);

        path.write((bit<32>)4, (bit<32>)port4);

        path.write((bit<32>)5, (bit<32>)port5);

        path.write((bit<32>)6, (bit<32>)port6);

        path.write((bit<32>)7, (bit<32>)port7);

        path.write((bit<32>)8, (bit<32>)port8);

        path.write((bit<32>)9, (bit<32>)port9);

        meta.num=1;

    }

   

    table ipv4_lpm {

        key = {

            hdr.ipv4.dstAddr: lpm;

        }

        actions = {

            set_path;

            drop;

        }

        size = 1024;

        default_action = drop();

    }

 

    apply {

 

        if (hdr.ethernet.etherType == TYPE_IPV4 && meta.num == 0) {

                   ipv4_lpm.apply();

        }

       

        if(meta.num != (bit<4>)0) {

           path.read(meta.val1, (bit<32>)0);

           //1

           path.read(meta.val2, (bit<32>)meta.num);

           AddHeader((bit<15>)meta.val2, 1);

           if((bit<32>)meta.num != meta.val1){

              meta.num = meta.num + 1;

          } else {             

              meta.num = 15;

           }

 

           //2

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

 

           //3

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {              

               meta.num = 15;

             }

           }

         

           //4

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

         

           //5

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

 

           //6

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

 

           //7

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

 

           //8

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }

       

           //9

           if(meta.num !=15) {

             path.read(meta.val2, (bit<32>)meta.num); 

             AddHeader((bit<15>)meta.val2, 0);

             if((bit<32>)meta.num != meta.val1){

               meta.num = meta.num + 1;

            } else {             

               meta.num = 15;

             }

           }            

        }

       

        if (hdr.srcRoutes[0].isValid()) {

            if (hdr.srcRoutes[0].bos == 1){

                srcRoute_finish();

            }

            srcRoute_nhop();

            if (hdr.ipv4.isValid()){

                update_ttl();

            }

        }

    }

}

 

/*************************************************************************

****************  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) {

 

     register<bit<32>>(256)qdepth;

     action do_add_qdepth(){

        qdepth.write((bit<32>)standard_metadata.egress_port, (bit<32>)standard_metadata.deq_qdepth);

     }                       

     action dmac(macAddr_t dstAddr) {

        hdr.ethernet.dstAddr = dstAddr;

     }   

 

     table ipv4_final {

        key = {

            hdr.ipv4.dstAddr: lpm;

        }

        actions = {

            dmac;

            NoAction;

        }

        size = 1024;

        default_action = NoAction();

    }

 

    apply {

       ipv4_final.apply();

       do_add_qdepth();    

    }

}

 

/*************************************************************************

*************   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.srcRoutes);

        packet.emit(hdr.ipv4);

    }

}

 

/*************************************************************************

***********************  S W I T C H  *******************************

*************************************************************************/

 

V1Switch(

MyParser(),

MyVerifyChecksum(),

MyIngress(),

MyEgress(),

MyComputeChecksum(),

MyDeparser()

) main;

 

 

[Execution]

 

Dr. Chih-Heng Ke (smallko@gmail.com)

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.

 

 

Ping test. (We monitor the packets at the s1-eth2. From the following figure that we can see that Ethernet type is 0x1234 (routing information header). Followed by 12 34, we can see 80 01.

(80 means the last record. If it is not the last record, we can see 00. 01 is the output port for the next switch)

 

Iperf test

 

Dr. Chih-Heng Ke (smallko@gmail.com)

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.