P4 switch: Monitor the queue lengths of different output interfaces



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




    "hosts": [









    "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"]





table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 1

table_add ipv4_lpm ipv4_forward  => 00:00:00:00:01:01 2

table_add ipv4_lpm ipv4_forward => 00:00:00:00:01:0b 1

table_add ipv4_lpm ipv4_forward => 00:00:00:00:01:0b 3

table_add ipv4_lpm ipv4_forward => 00:00:00:03:02:00 5

table_add ipv4_lpm ipv4_forward => 00:00:00:02:03:00 4

table_add ipv4_lpm ipv4_forward => 00:00:00:03:02:00 5



table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 2

table_add ipv4_lpm ipv4_forward  => 00:00:00:00:02:02 2

table_add ipv4_lpm ipv4_forward => 00:00:00:00:02:16 1

table_add ipv4_lpm ipv4_forward => 00:00:00:00:02:2c 3

table_add ipv4_lpm ipv4_forward => 00:00:00:01:03:00 4

table_add ipv4_lpm ipv4_forward => 00:00:00:03:03:00 5



table_set_default ipv4_lpm drop

table_set_default swtrace add_swtrace 3

table_add ipv4_lpm ipv4_forward  => 00:00:00:00:03:01 1

table_add ipv4_lpm ipv4_forward => 00:00:00:01:04:00 2

table_add ipv4_lpm ipv4_forward => 00:00:00:02:04:00 3


[receive2.py] (executed at h44)

#!/usr/bin/env python

import sys

import struct


from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr

from scapy.all import Packet, IPOption

from scapy.all import PacketListField, ShortField, IntField, LongField, BitField, FieldListField, FieldLenField

from scapy.all import IP, UDP, Raw

from scapy.layers.inet import _IPOption_HDR


def get_if():



    for i in get_if_list():

        if "eth0" in i:



    if not iface:

        print "Cannot find eth0 interface"


    return iface


class SwitchTrace(Packet):

    fields_desc = [ IntField("swid", 0),

                  IntField("qdepth", 0)]

    def extract_padding(self, p):

                return "", p


class IPOption_MRI(IPOption):

    name = "MRI"

    option = 31

    fields_desc = [ _IPOption_HDR,

                    FieldLenField("length", None, fmt="B",


                                  adjust=lambda pkt,l:l*2+4),

                    ShortField("count", 0),




                                   count_from=lambda pkt:(pkt.count*1)) ]


def handle_pkt(pkt):

    print "got a packet"


#    hexdump(pkt)




def main():

    iface = 'h44-eth0'

    print "sniffing on %s" % iface


    sniff(filter="udp and port 4321", iface = iface,

          prn = lambda x: handle_pkt(x))


if __name__ == '__main__':



For other codes, refer to mri (mri.p4, send.py, receive.py).





Experiment 1: Only link s1-s2 is congested


From the following figure, we can see that the qdepth shown at h2 terminal is 36 and qdepth shown at h44 is 0. Because the link between s1-s2 is congested.


Experiment 2: link s1-s2 and s1-s3 are congested.


Open another two terminal for h33 and h44.


Send traffic through s1-s3-s2 and make link s1-s3 congested.


We can get different qdepth values at h2 and h44.


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

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.