How to run p4 bmv2 docker in mininet ?
In this lab, I will show how to run p4 bmv2 in a docker host in mininet. Refer to https://github.com/cslev/p4-bmv2-docker and https://hub.docker.com/r/cslev/p4-bmv2-p4runtime, I put this docker in my “P4 Switch + Mininet + Docker Host” environment.
[Topology]
[basic.p4]
/* -*- P4_16 -*- */ #include <core.p4> #include <v1model.p4> const bit<16> TYPE_IPV4 = 0x800; /************************************************************************* *********************** H E A D E R
S
*********************************** *************************************************************************/ typedef bit<9> egressSpec_t; typedef bit<48> macAddr_t; typedef bit<32> ip4Addr_t; header ethernet_t
{ macAddr_t
dstAddr; macAddr_t
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; ip4Addr_t srcAddr; ip4Addr_t dstAddr; } struct metadata { /* empty */ } struct headers { ethernet_t ethernet; ipv4_t ipv4; } /************************************************************************* *********************** 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 select(hdr.ethernet.etherType) {
TYPE_IPV4: parse_ipv4;
default: accept; } } state parse_ipv4 { packet.extract(hdr.ipv4);
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(); } action forward(egressSpec_t 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 { update_checksum( hdr.ipv4.isValid(),
{ hdr.ipv4.version, hdr.ipv4.ihl,
hdr.ipv4.diffserv,
hdr.ipv4.totalLen,
hdr.ipv4.identification,
hdr.ipv4.flags,
hdr.ipv4.fragOffset,
hdr.ipv4.ttl,
hdr.ipv4.protocol,
hdr.ipv4.srcAddr,
hdr.ipv4.dstAddr },
hdr.ipv4.hdrChecksum,
HashAlgorithm.csum16); } } /************************************************************************* *********************** D E P A R S E R ******************************* *************************************************************************/ control MyDeparser(packet_out packet, in headers hdr)
{ apply { packet.emit(hdr.ethernet); packet.emit(hdr.ipv4); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
[cmd.txt]
table_add phy_forward forward 1 => 2 table_add phy_forward forward 2 => 1 |
[dockerhost2.py]
#!/usr/bin/python from mininet.net import Containernet from mininet.node
import Controller, Docker, OVSSwitch from mininet.cli
import CLI from mininet.log import setLogLevel, info from mininet.link
import TCLink, Link def topology(): "Create a network
with some docker containers acting as hosts." net = Containernet(controller=Controller) info('*** Adding hosts\n') h1 = net.addHost('h1',
ip="192.168.1.1/24") h2 = net.addHost('h2',
ip="192.168.1.2/24") info('*** Adding docker
containers\n') d1 = net.addDocker('d1',
dimage="cslev/p4-bmv2-p4runtime:full") info('*** Creating
links\n') net.addLink(h1,
d1) net.addLink(h2,
d1) info('*** Starting
network\n') net.start() info('*** Running CLI\n') CLI(net) info('*** Stopping
network') net.stop() if __name__ == '__main__': setLogLevel('info') topology() |
[execution]
1. Download the p4 bmv4 docker image.
2. Compile the basic.p4
3. Run the mininet script
4. Open another terminal and go into the d1 docker host (p4 bmv2).
5. Install openssh-client and use scp to copy the basic.json into the docker.
6. Run the simple_switch with basic.json
7. Open another terminal and set the p4 switch rules through thrift protocol
8. Test ping
Dr. Chih-Heng Ke (smallko@gmail.com)
Department of Computer Science and Information
Engineering,
National Quemoy University, Kinmen, Taiwan.