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.