P4

Advanced Tunneling with QoS

Objective

This exercise will extend the basic tunneling protocol to include Quality of Service (QoS) features. You will define a new header type to encapsulate the IP packet, including fields for QoS parameters, and modify the switch code to prioritize packets based on these parameters.

Steps

1. Define the QoS Header

Add a new header type myTunnelQoS_t that includes the following fields:

  • proto_id: 16-bit field indicating the protocol ID.

  • dst_id: 16-bit field indicating the destination ID.

  • qos_level: 8-bit field indicating the QoS level (e.g., 0 for low priority, 1 for medium priority, 2 for high priority).

2. Modify the P4 Program

Update the basic_tunnel.p4 file to include the new myTunnelQoS_t header.

  • Implement logic to parse the myTunnelQoS_t header and prioritize packets based on the qos_level field.

  • Modify the forwarding logic to handle packets with different QoS levels. For example, high-priority packets could be forwarded faster or through a dedicated path.

3. Update Control Plane Rules

Modify the sX-runtime.json files to include rules for the new myTunnelQoS_t header.

  • Ensure that the control plane installs rules that match on the qos_level field and apply appropriate actions.

4. Test the Implementation

Compile the updated P4 program and bring up the Mininet instance using make run.

  • Test the behavior by sending packets with different QoS levels and observing the forwarding behavior.

  • Use tools like ping and iperf to measure the performance and verify that high-priority packets are handled correctly.

digraph P4Program {
   rankdir=TB;
   node [shape=rectangle];

   // Define nodes
   start [label="Start"];
   parse_ethernet [label="Parse Ethernet"];
   parse_ipv4 [label="Parse IPv4"];
   parse_myTunnelQoS [label="Parse myTunnelQoS"];
   accept [label="Accept"];
   ingress [label="Ingress"];
   high_priority [label="High Priority Forwarding"];
   medium_priority [label="Medium Priority Forwarding"];
   low_priority [label="Low Priority Forwarding"];
   normal_forwarding [label="Normal IP Forwarding"];
   deparser [label="Deparser"];
   emit_ethernet [label="Emit Ethernet"];
   emit_ipv4 [label="Emit IPv4"];
   emit_myTunnelQoS [label="Emit myTunnelQoS"];

   // Define edges
   start -> parse_ethernet;
   parse_ethernet -> parse_ipv4 [label="etherType == 0x0800"];
   parse_ethernet -> accept [label="default"];
   parse_ipv4 -> parse_myTunnelQoS [label="protocol == 0x11"];
   parse_ipv4 -> accept [label="default"];
   parse_myTunnelQoS -> accept;

   accept -> ingress;
   ingress -> high_priority [label="qos_level == 2"];
   ingress -> medium_priority [label="qos_level == 1"];
   ingress -> low_priority [label="qos_level == 0"];
   ingress -> normal_forwarding [label="else"];

   high_priority -> deparser;
   medium_priority -> deparser;
   low_priority -> deparser;
   normal_forwarding -> deparser;

   deparser -> emit_ethernet;
   emit_ethernet -> emit_ipv4;
   emit_ipv4 -> emit_myTunnelQoS [label="if myTunnelQoS is valid"];

}

Network Topology with QoS

Template

Here is a template for the P4 program and control plane rules that you can use as a starting point for developing the solution:

P4 Program Template (basic_tunnel_qos.p4)

// Define headers
header ethernet_t {
    bit<48> dstAddr;
    bit<48> 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;
    bit<32> srcAddr;
    bit<32> dstAddr;
}

header myTunnelQoS_t {
    bit<16> proto_id;
    bit<16> dst_id;
    bit<8> qos_level;
}

// Define parsers
parser MyParser(packet_in pkt, out headers hdr) {
    state start {
        pkt.extract(hdr.ethernet);
        transition select(hdr.ethernet.etherType) {
            0x0800: parse_ipv4;
            default: accept;
        }
    }
    state parse_ipv4 {
        pkt.extract(hdr.ipv4);
        transition select(hdr.ipv4.protocol) {
            0x11: parse_myTunnelQoS; // Assuming 0x11 is the protocol ID for tunneling
            default: accept;
        }
    }
    state parse_myTunnelQoS {
        pkt.extract(hdr.myTunnelQoS);
        transition accept;
    }
}

// Define controls
control MyIngress {
    apply {
        if (hdr.myTunnelQoS.isValid()) {
            if (hdr.myTunnelQoS.qos_level == 2) {
                // High priority forwarding
                // Implement high priority forwarding logic here
                standard_metadata.egress_spec = 1; // Example port
            } else if (hdr.myTunnelQoS.qos_level == 1) {
                // Medium priority forwarding
                // Implement medium priority forwarding logic here
                standard_metadata.egress_spec = 2; // Example port
            } else {
                // Low priority forwarding
                // Implement low priority forwarding logic here
                standard_metadata.egress_spec = 3; // Example port
            }
        } else {
            // Normal IP forwarding
            // Implement normal IP forwarding logic here
            standard_metadata.egress_spec = 4; // Example port
        }
    }
}

// Define deparsers
control MyDeparser(packet_out pkt, in headers hdr) {
    apply {
        pkt.emit(hdr.ethernet);
        pkt.emit(hdr.ipv4);
        if (hdr.myTunnelQoS.isValid()) {
            pkt.emit(hdr.myTunnelQoS);
        }
    }
}

// Define the main control block
control MySwitch(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) {
    MyParser() parser;
    MyIngress() ingress;
    MyDeparser() deparser;

    apply {
        parser.apply(hdr);
        ingress.apply();
        deparser.apply(hdr);
    }
}

Control Plane Rules Template (s1-runtime.json)

{
  "table_entries": [
    {
      "table": "MyIngress.qos_table",
      "match": {
        "hdr.myTunnelQoS.qos_level": "2"
      },
      "action_name": "MyIngress.high_priority_action",
      "action_params": {
        "port": 1
      }
    },
    {
      "table": "MyIngress.qos_table",
      "match": {
        "hdr.myTunnelQoS.qos_level": "1"
      },
      "action_name": "MyIngress.medium_priority_action",
      "action_params": {
        "port": 2
      }
    },
    {
      "table": "MyIngress.qos_table",
      "match": {
        "hdr.myTunnelQoS.qos_level": "0"
      },
      "action_name": "MyIngress.low_priority_action",
      "action_params": {
        "port": 3
      }
    }
  ]
}