Swap P4 program at runtime

Based on https://titanwolf.org/Network/Articles/Article?AID=14bf03b7-91f3-407e-b331-26b67139248f#gsc.tab=0, I wrote this lab

 

Before running this lab, you need to modify the file p4_mininet.py, which is located p4-utils/p4utils/mininetlib. Remember to run ./install.sh again.

def start(self, controllers = None):

        """Start up a new P4 switch."""

        info("Starting P4 switch {}.\n".format(self.name))

        args = [self.sw_path]

        for port, intf in self.intfs.items():

            if not intf.IP():

                args.extend(['-i', str(port) + "@" + intf.name])

        if self.pcap_dump:

            if self.pcap_dir:

                args.append("--pcap="+self.pcap_dir)

            else:

                args.append("--pcap")

 

        if self.thrift_port:

            args.extend(['--thrift-port', str(self.thrift_port)])

        if self.nanomsg:

            args.extend(['--nanolog', self.nanomsg])

        args.extend(['--device-id', str(self.device_id)])

 

        args.append(self.json_path)

        #add the following line

        args.append("-- --enable-swap")

        if self.enable_debugger:

            args.append("--debugger")

        if self.log_console:

            args.append("--log-console")

            args.append('>' + self.log_file)

        info(' '.join(args) + "\n")

………

 

[topology]

 

H1----P4Switch---H2

 

In the original p4 program (phy_forward.p4), P4Switch will forward the traffic from port 1 to port 2, and forward the traffic from port 2 to port 1. Then we can use the “load_new_config_file” command in simple_switch_switch to change the p4 program to mac_forward.p4. (mac-layer forward).

 

(phy_forward.p4)

/* -*- P4_16 -*- */

#include <core.p4>

#include <v1model.p4>

 

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

*********************** H E A D E R S  ***********************************

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

struct metadata {

    /* empty */

}

 

struct headers {

}

 

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

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

    }

 

    action forward(bit<9> port) {

        standard_metadata.egress_spec = port;

    }

 

    table phy_forward {

        key = {

            standard_metadata.ingress_port: exact;

        }

 

        actions = {

            forward;

            drop;

        }

        size = 1024;

        default_action = drop();

    }

 

    apply {

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

    apply {  }

}

 

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

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

    }

}

 

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

***********************  D E P A R S E R  *******************************

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

 

control MyDeparser(packet_out packet, in headers hdr) {

    apply {

    }

}

 

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

***********************  S W I T C H  *******************************

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

 

V1Switch(

MyParser(),

MyVerifyChecksum(),

MyIngress(),

MyEgress(),

MyComputeChecksum(),

MyDeparser()

 

) main;

 

(phy_forward-cmd.txt)

table_add phy_forward forward 1 => 2

table_add phy_forward forward 2 => 1

 

(mac_forward.p4)

/* -*- P4_16 -*- */

#include <core.p4>

#include <v1model.p4>

 

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

*********************** H E A D E R S  ***********************************

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

header ethernet_t {

    bit<48> dstAddr;

    bit<48> srcAddr;

    bit<16>   etherType;

}

 

struct metadata {

    /* empty */

}

 

struct headers {

  ethernet_t   ethernet;

}

 

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

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

    }

 

    action forward(bit<9> port) {

        standard_metadata.egress_spec = port;

    }

 

    table mac_forward {

        key = {

            hdr.ethernet.dstAddr: exact;

        }

 

        actions = {

            forward;

            drop;

        }

        size = 1024;

        default_action = drop();

    }

 

    apply {

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

    apply {  }

}

 

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

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

    }

}

 

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

***********************  D E P A R S E R  *******************************

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

control MyDeparser(packet_out packet, in headers hdr) {

    apply {

      packet.emit(hdr.ethernet);

    }

}

 

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

***********************  S W I T C H  *******************************

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

V1Switch(

MyParser(),

MyVerifyChecksum(),

MyIngress(),

MyEgress(),

MyComputeChecksum(),

MyDeparser()

 

) main;

 

(mac_forward-cmd.txt)

table_add mac_forward forward 00:00:0a:00:01:01 => 1

table_add mac_forward forward 00:00:0a:00:01:02 => 2

 

(p4app.json)

{

  "program": "phy_forward.p4",

  "switch": "simple_switch",

  "compiler": "p4c",

  "options": "--target bmv2 --arch v1model --std p4-16",

  "switch_cli": "simple_switch_CLI",

  "cli": true,

  "pcap_dump": false,

  "enable_log": false,

  "topo_module": {

    "file_path": "",

    "module_name": "p4utils.mininetlib.apptopo",

    "object_name": "AppTopoStrategies"

  },

  "controller_module": null,

  "topodb_module": {

    "file_path": "",

    "module_name": "p4utils.utils.topology",

    "object_name": "Topology"

  },

  "mininet_module": {

    "file_path": "",

    "module_name": "p4utils.mininetlib.p4net",

    "object_name": "P4Mininet"

  },

  "topology": {

    "links": [["h1", "s1"], ["h2", "s1"]],

    "hosts": {

      "h1": {

      },

      "h2": {

      }

    },

    "switches": {

      "s1": {

        "cli_input": "phy_forward-cmd.txt",

        "program": "phy_forward.p4"

      }

    }

  }

}

 

[Execution]

Before we run “p4run”, we need to compile the mac_forward.p4 first.

 

Run “p4run”

….. (You need to see -- -- enable-swap at the end)

….

 

Open another terminal and run “simple_switch_CLI

From the above figure, we can see that the current program is “phy_forward.p4”.

 

Now we will change the program to mac_forward.p4. (Run load_new_config_file new.json and swap_configs commands).

 

From the above figure we can see that the program has changed and h1 cannot ping h2. Because no rules in mac_forward table.

 

Add the rules to mac_forward table. And h1 can ping h2.

 

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

Department of Computer Science and Information Engineering,

National Quemoy University, Kinmen, Taiwan.