P4 switch: video streaming (with priority queues)

[Topology]

http://csie.nqu.edu.tw/smallko/sdn/mointorqlenp4.files/image003.png

Based on http://csie.nqu.edu.tw/smallko/sdn/h264_eva1.htm and http://lists.p4.org/pipermail/p4-dev_lists.p4.org/2018-March/003467.html, I wrote this lab. h11 will send the background traffic to h22. H1 will stream the video to h2. The output queue of P4 switches will implement the priority mechanism. 7 is the highest priority while 0 is the lowest priority. The TOS value of 0 will be mapped to the lowest priority queue. The TOS value of 100 (tid=0) will be mapped to the highest priority queue. I will also set the queue limit to 50 packets.

 

[topology.py]

{

    "hosts": [

        "h1",

        "h2",

        "h3",

        "h11",

        "h22",

        "h33",

        "h44"

    ],

    "switches": {

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

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

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

    },

    "links": [

              ["h1", "s1"], ["h11", "s1"], ["s1", "s2", "0", 0.5], ["s1", "s3", "0", 0.8],

              ["s3", "s2"], ["s2", "h2"], ["s2", "h22"], ["s3", "h3"],

              ["h33", "s1"], ["s2", "h44"]

    ]

}

 

[s1-commands.txt]

table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 1

table_add ipv4_lpm ipv4_forward 10.0.1.1/32  => 00:00:00:00:01:01 2

table_add ipv4_lpm ipv4_forward 10.0.1.11/32 => 00:00:00:00:01:0b 1

table_add ipv4_lpm ipv4_forward 10.0.1.33/32 => 00:00:00:00:01:0b 3

table_add ipv4_lpm ipv4_forward 10.0.2.44/32 => 00:00:00:03:02:00 5

table_add ipv4_lpm ipv4_forward 10.0.2.0/24 => 00:00:00:02:03:00 4

table_add ipv4_lpm ipv4_forward 10.0.3.0/24 => 00:00:00:03:02:00 5

 

[s2-commands.txt]

table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 2

table_add ipv4_lpm ipv4_forward 10.0.2.2/32  => 00:00:00:00:02:02 2

table_add ipv4_lpm ipv4_forward 10.0.2.22/32 => 00:00:00:00:02:16 1

table_add ipv4_lpm ipv4_forward 10.0.2.44/32 => 00:00:00:00:02:2c 3

table_add ipv4_lpm ipv4_forward 10.0.1.0/24 => 00:00:00:01:03:00 4

table_add ipv4_lpm ipv4_forward 10.0.3.0/24 => 00:00:00:03:03:00 5

 

[s3-commands.txt]

table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 3

table_add ipv4_lpm ipv4_forward 10.0.3.3/32  => 00:00:00:00:03:01 1

table_add ipv4_lpm ipv4_forward 10.0.1.0/24 => 00:00:00:01:04:00 2

table_add ipv4_lpm ipv4_forward 10.0.2.0/24 => 00:00:00:02:04:00 3

 

[mri.p4]

/* -*- P4_16 -*- */

#include <core.p4>

#include <v1model.p4>

 

const bit<8>  UDP_PROTOCOL = 0x11;

const bit<16> TYPE_IPV4 = 0x800;

const bit<5>  IPV4_OPTION_MRI = 31;

 

#define MAX_HOPS 9

#define qlimit   50

 

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

 

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

*********************** H E A D E R S  ***********************************

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

 

typedef bit<9>  egressSpec_t;

typedef bit<48> macAddr_t;

typedef bit<32> ip4Addr_t;

typedef bit<32> switchID_t;

typedef bit<32> qdepth_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;

}

 

header ipv4_option_t {

    bit<1> copyFlag;

    bit<2> optClass;

    bit<5> option;

    bit<8> optionLength;

}

 

header mri_t {

    bit<16>  count;

}

 

header switch_t {

    switchID_t  swid;

    qdepth_t    qdepth;

}

 

struct ingress_metadata_t {

    bit<16>  count;

}

 

struct parser_metadata_t {

    bit<16>  remaining;

}

 

struct metadata {

    ingress_metadata_t   ingress_metadata;

    parser_metadata_t   parser_metadata;             

}

 

struct headers {

    ethernet_t         ethernet;

    ipv4_t             ipv4;

    ipv4_option_t      ipv4_option;

    mri_t              mri;

    switch_t[MAX_HOPS] swtraces;

}

 

error { IPHeaderTooShort }

 

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

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

        verify(hdr.ipv4.ihl >= 5, error.IPHeaderTooShort);

        transition select(hdr.ipv4.ihl) {

            5             : accept;

            default       : parse_ipv4_option;

        }

    }

 

    state parse_ipv4_option {

        packet.extract(hdr.ipv4_option);

        transition select(hdr.ipv4_option.option) {

            IPV4_OPTION_MRI: parse_mri;

            default: accept;

        }

    }

 

    state parse_mri {

        packet.extract(hdr.mri);

        meta.parser_metadata.remaining = hdr.mri.count;

        transition select(meta.parser_metadata.remaining) {

            0 : accept;

            default: parse_swtrace;

        }

    }

 

    state parse_swtrace {

        packet.extract(hdr.swtraces.next);

        meta.parser_metadata.remaining = meta.parser_metadata.remaining  - 1;

        transition select(meta.parser_metadata.remaining) {

            0 : accept;

            default: parse_swtrace;

        }

    }   

}

 

 

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

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

        }      

 

        if(hdr.ipv4.diffserv==100){

              standard_metadata.priority=(bit<3>)7;

            }else if(hdr.ipv4.diffserv==110){

              standard_metadata.priority=(bit<3>)6;

            }else if(hdr.ipv4.diffserv==120){

              standard_metadata.priority=(bit<3>)5;

            }else {

              standard_metadata.priority=(bit<3>)0;

            }

    }

}

 

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

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

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

    }

 

    action drop() {

        mark_to_drop();

    }

 

    action add_swtrace(switchID_t swid) {

        hdr.mri.count = hdr.mri.count + 1;

        hdr.swtraces.push_front(1);

        hdr.swtraces[0].swid = swid;

        hdr.swtraces[0].qdepth = (qdepth_t)standard_metadata.deq_qdepth;

 

        hdr.ipv4.ihl = hdr.ipv4.ihl + 2;

        hdr.ipv4_option.optionLength = hdr.ipv4_option.optionLength + 8;

        hdr.ipv4.totalLen = hdr.ipv4.totalLen + 8;

    }

 

    table swtrace {

        actions = {

            add_swtrace;

            NoAction;

        }

        default_action = NoAction();     

    }

   

    apply {

        if (hdr.mri.isValid()) {

            swtrace.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.ipv4);

        packet.emit(hdr.ipv4_option);

        packet.emit(hdr.mri);

        packet.emit(hdr.swtraces);                

    }

}

 

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

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

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

 

V1Switch(

MyParser(),

MyVerifyChecksum(),

MyIngress(),

MyEgress(),

MyComputeChecksum(),

MyDeparser()

) main;

 

[Execution]

1.      Please refer to http://csie.nqu.edu.tw/smallko/sdn/myEvalSVC-Mininet.htm and http://csie.nqu.edu.tw/smallko/sdn/h264_eva1.htm to setup the video streaming evaluation framework over mininet environment.

 

Open another terminal and use simple_switch_CLI to set the queue limit to 50 for s1 switch (port 9090)

 

Start the background traffic

 

Start the video streaming

 

 

Delivered video quality evaluation

 

 

p.s. you can use single queue for the performance evaluation.

 

Dr. Chih-Heng Ke

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

Email: smallko@gmail.com / smallko@nqu.edu.tw