P4 (P4-16) switch:  Counter Example--> Get the link bandwidth consumption

[Topology]

H1-s1--s2----h2

    |_s3_|

|

         H3

 

In this example, h1 will send the traffic to h2 via s1 and s2 and send the traffic to h3 via s1 and s3. I will use counter in the switch to record the transmitted bytes for each output port. Then I will write a simple script to get the link bandwidth consumption for s1-s2 and s1-s3 links.

 

[basic.p4]

/* -*- P4_16 -*- */

#include <core.p4>

#include <v1model.p4>

 

const bit<16> TYPE_IPV4 = 0x800;

const bit<4> MAX_PORT = 15;

 

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

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

   

    counter((bit<32>)MAX_PORT, CounterType.bytes) egressPortCounter;

 

    apply {

       egressPortCounter.count((bit<32>)standard_metadata.egress_port);

    }

}

 

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

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

 

[topology.py]

{

    "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

 

[getThr.sh]

#!/bin/bash

 

CLI_PATH=/home/vagrant/behavioral-model/targets/simple_switch/simple_switch_CLI

 

bytes_port2=0

pre_bytes_port2=0

bytes_port3=0

pre_bytes_port3=0

#get current unix time in milliseconds

prev_time=`date +%s%N | cut -b1-13`

 

while true; do

 

  bytes_port2=`echo counter_read egressPortCounter 2 | $CLI_PATH --thrift-port 9090 | grep egressPortCounter | tr '=' ' ' | tr ')' ' ' | awk '{print $6}'`       

  now=`date +%s%N | cut -b1-13`

 

  if [ ! $pre_bytes_port2 -eq 0 ];then

     #echo $now, $pre_time

     #echo $bytes_port2, $pre_bytes_port2

     thr=`echo "scale=2;($bytes_port2-$pre_bytes_port2) * 8.0  / ($now-$pre_time)" | bc -l`

     #echo $tdiff, $bytesdiff

     echo "BW consumption (s1-s2):" $thr "kbps"      

  fi

 

  bytes_port3=`echo counter_read egressPortCounter 3 | $CLI_PATH --thrift-port 9090 | grep egressPortCounter | tr '=' ' ' | tr ')' ' ' | awk '{print $6}'`       

  now=`date +%s%N | cut -b1-13`

 

  if [ ! $pre_bytes_port3 -eq 0 ];then

     thr=`echo "scale=2;($bytes_port3-$pre_bytes_port3) * 8.0   / ($now-$pre_time)" | bc -l`

     echo "BW consumption (s1-s3):" $thr "kbps"      

  fi

 

  pre_bytes_port2=$bytes_port2

  pre_bytes_port3=$bytes_port3

  pre_time=$now

  sleep 1

done

 

[Execution]

 

Open another terminal to calculate the link bw consumption.

 

 

 

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

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.