Multipath Transmission for P4

[topology]

 

Single path transmission: if h1 sends the packets via s1-s2 to h2, h2 can get at most around 500kbps.

Multipath transmission: if h1 sends 50% traffic via s1-s2 to h2 and 50% traffic via s1-s3-s2 to h2, h2 can get at most around 1000kbps.

 

[topology.json]

{

    "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", "0", 0.5], ["s1", "s3", "0", 0.5],

        ["s3", "s2", "0", 0.5], ["s2", "h2"], ["s3", "h3"]

    ]

}

 

[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 {

    macAddr_t dstAddr;

    egressSpec_t port;

    bit<8>  lower;

    bit<8>  upper;      

    bit<8>  result;

    bit<1>  final;

}

 

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 {

        meta.result=127;

        meta.final=0;

        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();

    }

 

    action myforward(){

        standard_metadata.egress_spec = meta.port;

        hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;

        hdr.ethernet.dstAddr = meta.dstAddr;

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

        meta.final=1;

    }      

 

    action set_param1(bit<8> lower, bit<8> upper, macAddr_t dstAddr, egressSpec_t port) {

        random(meta.result, (bit<8>)0,(bit<8>)100);

        meta.lower=lower;

            meta.upper=upper;

            meta.dstAddr=dstAddr;

        meta.port=port;

    }

 

    action set_param2(bit<8> lower, bit<8> upper, macAddr_t dstAddr, egressSpec_t port) {

        meta.lower=lower;

            meta.upper=upper;

        meta.dstAddr=dstAddr;

        meta.port=port;

    }

 

    action set_param3(bit<8> lower, bit<8> upper, macAddr_t dstAddr, egressSpec_t port) {

        meta.lower=lower;

            meta.upper=upper;

            meta.dstAddr=dstAddr;

        meta.port=port;

    }

 

    table ipv4_lpm2 {

        key = {

            hdr.ipv4.dstAddr: lpm;

            meta.final: exact;

        }

        actions = {

            set_param1;

            drop;

            NoAction;

        }

        size = 1024;

        default_action = NoAction();

    }

 

    table ipv4_lpm3 {

        key = {

            hdr.ipv4.dstAddr: lpm;

            meta.final: exact;

        }

        actions = {

            set_param2;

            drop;

            NoAction;

        }

        size = 1024;

        default_action = NoAction();

    }

 

    table ipv4_lpm4 {

        key = {

            hdr.ipv4.dstAddr: lpm;

            meta.final: exact;

        }

        actions = {

            set_param3;

            drop;

            NoAction;

        }

        size = 1024;

        default_action = NoAction();

    }

   

    apply {

        if (hdr.ipv4.isValid()) {

            ipv4_lpm2.apply();

            if (meta.result >= meta.lower && meta.result <= meta.upper){

                myforward();

            }

           

            if (meta.final==0){

                ipv4_lpm3.apply();

                if (meta.result >= meta.lower && meta.result <= meta.upper){

                  myforward();

                }

            }

 

            if (meta.final==0){

                ipv4_lpm4.apply();

                if (meta.result >= meta.lower && meta.result <= meta.upper){

                  myforward();

                }

            }

        }

       

        if (hdr.ipv4.isValid() && meta.result==127) {

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

    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;

 

[s1-commands.txt –single path]

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

#table_add ipv4_lpm2 set_param1 10.0.2.2/32 0 => 0   49 00:00:00:02:02:00 2

#table_add ipv4_lpm3 set_param2 10.0.2.2/32 0 => 50 100 00:00:00:03:03:00 3

 

[s1-commands.txt –multipath]

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

table_add ipv4_lpm2 set_param1 10.0.2.2/32 0 => 0   49 00:00:00:02:02:00 2

table_add ipv4_lpm3 set_param2 10.0.2.2/32 0 => 50 100 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

 

[Execution]

 

Single path transmission

 

Multipath transmission

 

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com