P4 switch: Monitor the queue lengths of different output interfaces (Method 2)

[Topology]

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

 

The bandwidth of link s1-s2 is set to 0.5 Mbps. The bandwidth of link s1-s3 is set to 0.8 Mbps. H1 will send the traffic to h2 via s1-s2. H11 will send the traffic to h22 via s1-s2. H33 will send the traffic to h44 via s1-s3-s2.

The following code was based on multi-hop route inspection (mri).

 

p.s. This method is to use registers to record the queue lengths of different output interfaces. Then use simple_switch_CLI to get the values.

[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

 

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

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

        }

    }

}

 

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

****************  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, (qdepth_t)standard_metadata.deq_qdepth);

    }

       

    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]

Use xterm to open terminals for h11, h22,h33,h44. (h11—s1-s2—h22, h33-s1-s3-s2-h44)

 

Use iperf to send traffic.

 

Open another terminal and use “simple_switch_CLI” to connect s1 (port 9090).

 

Use register_read qdepth to get the values in qdepth. 17 is the queue length for output 4 (s1-s2) and 12 is the queue length for output 5 (s1-s5)

 

 

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

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.