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_tthat 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"];
}](../../../_images/graphviz-29c8787c8ea8cf42d89b8f5fc7187625f32a287a.png)
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
}
}
]
}