From 82d764a2baf31e149522aebdca7e8d6703e77c70 Mon Sep 17 00:00:00 2001 From: Antonin Bas Date: Sat, 12 Mar 2016 11:31:47 -0800 Subject: [PATCH] added simple_nat example --- SIGCOMM_2015/source_routing/cleanup | 3 +- examples/README.md | 1 + examples/simple_nat/README.md | 62 ++++ examples/simple_nat/cleanup.sh | 27 ++ examples/simple_nat/commands.txt | 17 + examples/simple_nat/nat_app.py | 77 +++++ examples/simple_nat/p4src/simple_nat.p4 | 364 +++++++++++++++++++++ examples/simple_nat/resources/topo.graphml | 306 +++++++++++++++++ examples/simple_nat/resources/topo.png | Bin 0 -> 15545 bytes examples/simple_nat/run_demo.sh | 53 +++ examples/simple_nat/sswitch_CLI.sh | 9 + examples/simple_nat/topo.py | 113 +++++++ 12 files changed, 1030 insertions(+), 2 deletions(-) create mode 100644 examples/simple_nat/README.md create mode 100755 examples/simple_nat/cleanup.sh create mode 100644 examples/simple_nat/commands.txt create mode 100644 examples/simple_nat/nat_app.py create mode 100644 examples/simple_nat/p4src/simple_nat.p4 create mode 100644 examples/simple_nat/resources/topo.graphml create mode 100644 examples/simple_nat/resources/topo.png create mode 100755 examples/simple_nat/run_demo.sh create mode 100755 examples/simple_nat/sswitch_CLI.sh create mode 100644 examples/simple_nat/topo.py diff --git a/SIGCOMM_2015/source_routing/cleanup b/SIGCOMM_2015/source_routing/cleanup index 4035587..a155edf 100755 --- a/SIGCOMM_2015/source_routing/cleanup +++ b/SIGCOMM_2015/source_routing/cleanup @@ -1,2 +1 @@ -sudo killall simple_switch -redis-cli FLUSHDB \ No newline at end of file +sudo killall lt-simple_switch diff --git a/examples/README.md b/examples/README.md index dfe3a08..660d2bb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,6 +15,7 @@ included: - `counter`: how to use counters in P4 - `action_profile`: how to use action profiles in P4, using ECMP as support - `resubmit`: how to resubmit packets to the ingress pipelines +- `simple_nat`: a basic implementation of a full-cone NAT for TCP traffic All examples are orgranized the same way, with a `p4src` directory containing the P4 source code, and a `README` file describing the P4 program and explaining diff --git a/examples/simple_nat/README.md b/examples/simple_nat/README.md new file mode 100644 index 0000000..9abbfac --- /dev/null +++ b/examples/simple_nat/README.md @@ -0,0 +1,62 @@ +# Simple NAT + +## Description + +This program implements a very basic full-cone NAT for TCP traffic (over +IPv4). According to [Wikipedia] +(https://en.wikipedia.org/wiki/Network_address_translation#Methods_of_translation), +a full-cone NAT is defined as follows: + +Once an internal address (iAddr:iPort) is mapped to an external address +(eAddr:ePort), any packets from iAddr:iPort are sent through eAddr:ePort. Any +external host can send packets to iAddr:iPort by sending packets to eAddr:ePort. + +Note that this program was built on top of the simple_router P4 program, so you +will find some similarities. + +This program was added to illustrate two things: +- how to re-compute a TCP checksum after having modified the TCP header (which +is required for a TCP NAT) +- how to write a simple app that receives and emits "CPU packets" + +This program is slightly more advanced than most others in this repository, so +we recommend that you become familiar with the copy_to_cpu example before +studying this one. + +The program implements very basic funtionality only. For example it supports +only one internal interface, even though we may extend this in the future. The +Mininet topology used for the demo is the following: + +![Simple NAT topology](resources/topo.png) + +The program in a nutshell: +- non-TCP traffic is dropped. +- when a TCP packet is received on the external interface, for which there is no +mapping, the packet is dropped. +- when a TCP packet is received on the internal interface, for which there is no +mapping, the packet is sent to CPU and 2 new rules are added to the `nat` table +to allow translation and forwarding of TCP packets in both directions. The +packet is then re-injected in the dataplane (to avoid dropping the SYN packet). +- when a TCP packet is received on the either interface, for which there is a +mapping, the appropriate rewrites are executed for the IPv4 and TCP headers and +the packet is forwarded appropriately. + +The most important part of the program is the `nat` table. If you understand +what this table is doing, the rest of the program is mostly IPv4 forwarding. You +should also take a long look at [nat_app.py] (nat_app.py), which manages the +mappings and dynamically adds rules to the `nat` table. + +We use 11 as the CPU port. There is a special CPU veth pair (`cpu-veth-0` / +`cpu-veth-1`), which is use by the switch / the app to send and receive CPU +packets. The veth pair is created by `run_demo.sh` and can be destroyed with +`cleanup.sh`. + +### Running the demo + +To run the demo: +- start the 1-switch Mininet topo with `sudo ./run_demo.sh`. +- start the app with `sudo python nat_app.py`. +- create a TCP flow in Mininet from `h1` (internal host) to `h2` (external host) + - `h2 iperf -s&` + - `h1 iperf -c h2` +- you can cleanup the demo with `sudo ./cleanup.sh` diff --git a/examples/simple_nat/cleanup.sh b/examples/simple_nat/cleanup.sh new file mode 100755 index 0000000..095b66f --- /dev/null +++ b/examples/simple_nat/cleanup.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi + +killall lt-simple_switch &> /dev/null +mn -c &> /dev/null +intf="cpu-veth-0" +if ip link show $intf &> /dev/null; then + ip link delete $intf type veth +fi diff --git a/examples/simple_nat/commands.txt b/examples/simple_nat/commands.txt new file mode 100644 index 0000000..c4d73f0 --- /dev/null +++ b/examples/simple_nat/commands.txt @@ -0,0 +1,17 @@ +table_set_default if_info _drop +table_add if_info set_if_info 1 => 10.0.0.1 00:aa:bb:00:00:04 0 +table_add if_info set_if_info 2 => 192.168.0.1 00:aa:bb:00:00:05 1 +table_set_default nat _drop +table_add nat nat_miss_ext_to_int 1 1 1 0.0.0.0&&&0.0.0.0 0.0.0.0&&&0.0.0.0 0&&&0 0&&&0 => 99 +table_add nat nat_miss_int_to_ext 0 1 1 0.0.0.0&&&0.0.0.0 0.0.0.0&&&0.0.0.0 0&&&0 0&&&0 => 99 +table_set_default ipv4_lpm _drop +table_add ipv4_lpm set_nhop 10.0.0.10/32 => 10.0.0.10 1 +table_add ipv4_lpm set_nhop 192.168.0.10/32 => 192.168.0.10 2 +table_set_default forward _drop +table_add forward set_dmac 10.0.0.10 => 00:04:00:00:00:10 +table_add forward set_dmac 192.168.0.10 => 00:05:00:00:00:10 +table_set_default send_frame _drop +table_add send_frame do_rewrites 1 => 00:aa:bb:00:00:04 +table_add send_frame do_rewrites 2 => 00:aa:bb:00:00:05 +mirroring_add 250 11 +table_set_default send_to_cpu do_cpu_encap diff --git a/examples/simple_nat/nat_app.py b/examples/simple_nat/nat_app.py new file mode 100644 index 0000000..882fa92 --- /dev/null +++ b/examples/simple_nat/nat_app.py @@ -0,0 +1,77 @@ +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from scapy.all import * +import subprocess +import os + +CLI_PATH = None + +EXTERN_IP = "192.168.0.1" + +current_nat_port = 1025 +nat_mappings = {} + +def send_to_CLI(cmd): + this_dir = os.path.dirname(os.path.realpath(__file__)) + p = Popen(os.path.join(this_dir, 'sswitch_CLI.sh'), stdout=PIPE, stdin=PIPE) + output = p.communicate(input=cmd)[0] + # print output + +# This is a very basic implementation of a full-cone NAT for TCP traffic +# We do not maintain a state machine for each connection, so we are not able to +# cleanup the port mappings, but this is sufficient for demonstration purposes +def process_cpu_pkt(p): + global current_nat_port + global EXTERN_IP + + p_str = str(p) + # 0-7 : preamble + # 8 : device + # 9 : reason + # 10 : iface + # 11- : data packet (TCP) + if p_str[:8] != '\x00' * 8 or p_str[8] != '\x00' or p_str[9] != '\xab': + return + ip_hdr = None + tcp_hdr = None + try: + p2 = Ether(p_str[11:]) + ip_hdr = p2['IP'] + tcp_hdr = p2['TCP'] + except: + return + print "Packet received" + print p2.summary() + if (ip_hdr.src, tcp_hdr.sport) not in nat_mappings: + ext_port = current_nat_port + current_nat_port += 1 + print "Allocating external port", ext_port + nat_mappings[(ip_hdr.src, tcp_hdr.sport)] = ext_port + # internal to external rule for this mapping + send_to_CLI("table_add nat nat_hit_int_to_ext 0 1 1 %s&&&255.255.255.255 0.0.0.0&&&0.0.0.0 %d&&&0xffff 0&&&0 => %s %d 1" %\ + (ip_hdr.src, tcp_hdr.sport, EXTERN_IP, ext_port)) + # external to internal rule for this mapping + send_to_CLI("table_add nat nat_hit_ext_to_int 1 1 1 0.0.0.0&&&0.0.0.0 %s&&&255.255.255.255 0&&&0 %d&&&0xffff => %s %d 1" %\ + (EXTERN_IP, ext_port, ip_hdr.src, tcp_hdr.sport)) + # a little bit hacky, this essentially ensures that the packet we re-inject + # in the CPU iface will not be processed again by this method + new_p = p_str[:9] + '\xac' + p_str[10:] + sendp(new_p, iface="cpu-veth-0", verbose=0) + +def main(): + sniff(iface="cpu-veth-0", prn=lambda x: process_cpu_pkt(x)) + +if __name__ == '__main__': + main() diff --git a/examples/simple_nat/p4src/simple_nat.p4 b/examples/simple_nat/p4src/simple_nat.p4 new file mode 100644 index 0000000..904c134 --- /dev/null +++ b/examples/simple_nat/p4src/simple_nat.p4 @@ -0,0 +1,364 @@ +/* +Copyright 2013-present Barefoot Networks, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +header_type ethernet_t { + fields { + dstAddr : 48; + srcAddr : 48; + etherType : 16; + } +} + +header_type ipv4_t { + fields { + version : 4; + ihl : 4; + diffserv : 8; + totalLen : 16; + identification : 16; + flags : 3; + fragOffset : 13; + ttl : 8; + protocol : 8; + hdrChecksum : 16; + srcAddr : 32; + dstAddr: 32; + } +} + +parser start { + set_metadata(meta.if_index, standard_metadata.ingress_port); + return select(current(0, 64)) { + 0 : parse_cpu_header; // dummy transition + default: parse_ethernet; + } +} + +header_type cpu_header_t { + fields { + preamble: 64; + device: 8; + reason: 8; + if_index: 8; + } +} + +header cpu_header_t cpu_header; + +parser parse_cpu_header { + extract(cpu_header); + set_metadata(meta.if_index, cpu_header.if_index); + return parse_ethernet; +} + +#define ETHERTYPE_IPV4 0x0800 + +header ethernet_t ethernet; + +parser parse_ethernet { + extract(ethernet); + return select(latest.etherType) { + ETHERTYPE_IPV4 : parse_ipv4; + default: ingress; + } +} + +header ipv4_t ipv4; + +field_list ipv4_checksum_list { + ipv4.version; + ipv4.ihl; + ipv4.diffserv; + ipv4.totalLen; + ipv4.identification; + ipv4.flags; + ipv4.fragOffset; + ipv4.ttl; + ipv4.protocol; + ipv4.srcAddr; + ipv4.dstAddr; +} + +field_list_calculation ipv4_checksum { + input { + ipv4_checksum_list; + } + algorithm : csum16; + output_width : 16; +} + +calculated_field ipv4.hdrChecksum { + verify ipv4_checksum; + update ipv4_checksum; +} + +#define IP_PROT_TCP 0x06 + +parser parse_ipv4 { + extract(ipv4); + set_metadata(meta.ipv4_sa, ipv4.srcAddr); + set_metadata(meta.ipv4_da, ipv4.dstAddr); + set_metadata(meta.tcpLength, ipv4.totalLen - 20); + return select(ipv4.protocol) { + IP_PROT_TCP : parse_tcp; + default : ingress; + } +} + +header_type tcp_t { + fields { + srcPort : 16; + dstPort : 16; + seqNo : 32; + ackNo : 32; + dataOffset : 4; + res : 4; + flags : 8; + window : 16; + checksum : 16; + urgentPtr : 16; + } +} + +header tcp_t tcp; + +parser parse_tcp { + extract(tcp); + set_metadata(meta.tcp_sp, tcp.srcPort); + set_metadata(meta.tcp_dp, tcp.dstPort); + return ingress; +} + +field_list tcp_checksum_list { + ipv4.srcAddr; + ipv4.dstAddr; + 8'0; + ipv4.protocol; + meta.tcpLength; + tcp.srcPort; + tcp.dstPort; + tcp.seqNo; + tcp.ackNo; + tcp.dataOffset; + tcp.res; + tcp.flags; + tcp.window; + tcp.urgentPtr; + payload; +} + +field_list_calculation tcp_checksum { + input { + tcp_checksum_list; + } + algorithm : csum16; + output_width : 16; +} + +calculated_field tcp.checksum { + verify tcp_checksum if(valid(tcp)); + update tcp_checksum if(valid(tcp)); +} + +action _drop() { + drop(); +} + +header_type intrinsic_metadata_t { + fields { + mcast_grp : 4; + egress_rid : 4; + mcast_hash : 16; + lf_field_list: 32; + } +} + +metadata intrinsic_metadata_t intrinsic_metadata; + +header_type meta_t { + fields { + do_forward : 1; + ipv4_sa : 32; + ipv4_da : 32; + tcp_sp : 16; + tcp_dp : 16; + nhop_ipv4 : 32; + if_ipv4_addr : 32; + if_mac_addr : 48; + is_ext_if : 1; + tcpLength : 16; + if_index : 8; + } +} + +metadata meta_t meta; + +action set_if_info(ipv4_addr, mac_addr, is_ext) { + modify_field(meta.if_ipv4_addr, ipv4_addr); + modify_field(meta.if_mac_addr, mac_addr); + modify_field(meta.is_ext_if, is_ext); +} + +table if_info { + reads { + meta.if_index : exact; + } + actions { + _drop; + set_if_info; + } +} + +action nat_miss_ext_to_int() { + modify_field(meta.do_forward, 0); + drop(); +} + +#define CPU_MIRROR_SESSION_ID 250 + +field_list copy_to_cpu_fields { + standard_metadata; +} + +action nat_miss_int_to_ext() { + clone_ingress_pkt_to_egress(CPU_MIRROR_SESSION_ID, copy_to_cpu_fields); +} + +action nat_hit_int_to_ext(srcAddr, srcPort) { + modify_field(meta.do_forward, 1); + modify_field(meta.ipv4_sa, srcAddr); + modify_field(meta.tcp_sp, srcPort); +} + +action nat_hit_ext_to_int(dstAddr, dstPort) { + modify_field(meta.do_forward, 1); + modify_field(meta.ipv4_da, dstAddr); + modify_field(meta.tcp_dp, dstPort); +} + +action nat_no_nat() { + modify_field(meta.do_forward, 1); +} + +table nat { + reads { + meta.is_ext_if : exact; + ipv4 : valid; + tcp : valid; + ipv4.srcAddr : ternary; + ipv4.dstAddr : ternary; + tcp.srcPort : ternary; + tcp.dstPort : ternary; + } + actions { + _drop; + nat_miss_int_to_ext; + nat_miss_ext_to_int; + nat_hit_int_to_ext; + nat_hit_ext_to_int; + nat_no_nat; // for debugging + } + size : 128; +} + +action set_nhop(nhop_ipv4, port) { + modify_field(meta.nhop_ipv4, nhop_ipv4); + modify_field(standard_metadata.egress_spec, port); + add_to_field(ipv4.ttl, -1); +} + +table ipv4_lpm { + reads { + meta.ipv4_da : lpm; + } + actions { + set_nhop; + _drop; + } + size: 1024; +} + +action set_dmac(dmac) { + modify_field(ethernet.dstAddr, dmac); +} + +table forward { + reads { + meta.nhop_ipv4 : exact; + } + actions { + set_dmac; + _drop; + } + size: 512; +} + +action do_rewrites(smac) { + // in case packet was injected by CPU + remove_header(cpu_header); + modify_field(ethernet.srcAddr, smac); + modify_field(ipv4.srcAddr, meta.ipv4_sa); + modify_field(ipv4.dstAddr, meta.ipv4_da); + modify_field(tcp.srcPort, meta.tcp_sp); + modify_field(tcp.dstPort, meta.tcp_dp); +} + +table send_frame { + reads { + standard_metadata.egress_port: exact; + } + actions { + do_rewrites; + _drop; + } + size: 256; +} + +action do_cpu_encap() { + add_header(cpu_header); + modify_field(cpu_header.preamble, 0); + modify_field(cpu_header.device, 0); + modify_field(cpu_header.reason, 0xab); // does not mean anything + modify_field(cpu_header.if_index, meta.if_index); +} + +table send_to_cpu { + actions { do_cpu_encap; } + size : 0; +} + +control ingress { + // retrieve information on the ingress interface + apply(if_info); + // determine what to do with the packet and which rewrites to apply + // depending on direction (int -> ext or ext -> int) and existing nat rules + apply(nat); + // forward packet + if (meta.do_forward == 1 and ipv4.ttl > 0) { + apply(ipv4_lpm); + apply(forward); + } +} + +control egress { + if (standard_metadata.instance_type == 0) { + // regular packet: execute rewrites + apply(send_frame); + } else { + // cpu packet: encap + apply(send_to_cpu); + } +} diff --git a/examples/simple_nat/resources/topo.graphml b/examples/simple_nat/resources/topo.graphml new file mode 100644 index 0000000..e937c3e --- /dev/null +++ b/examples/simple_nat/resources/topo.graphml @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + s1 + + + + + + + + + + + + + + + + + + h2 + + + + + + + + + + + + + + + + + + h1 + + + + + + + + + + + + + + + + + + nat_app.py + + + + + + + + + + + + + + + + + + cpu-veth-0 + + + + + + + + + + + + + + + + + + cpu-veth-1, port 11 + + + + + + + + + + + + + + + + + + port 1 +00:aa:bb:00:00:04 +10.0.0.1 + + + + + + + + + + + + + + + + + + port 2 +00:aa:bb:00:00:05 +192.168.0.1 + + + + + + + + + + + + + + + + + + 00:04:00:00:00:10 +10.0.0.10 + + + + + + + + + + + + + + + + + + 00:05:00:00:00:10 +192.168.0.10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Internal + + + + + + + + + + + + + + + + + + External + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/simple_nat/resources/topo.png b/examples/simple_nat/resources/topo.png new file mode 100644 index 0000000000000000000000000000000000000000..443b374a1b426b6d66897f92f8144d4836a8551e GIT binary patch literal 15545 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 Kp#@S8U;RJ&q+eqI literal 0 HcmV?d00001 diff --git a/examples/simple_nat/run_demo.sh b/examples/simple_nat/run_demo.sh new file mode 100755 index 0000000..d87a509 --- /dev/null +++ b/examples/simple_nat/run_demo.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [[ $EUID -ne 0 ]]; then + echo "This script should be run using sudo or as the root user" + exit 1 +fi + +THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +source $THIS_DIR/../env.sh + +P4C_BM_SCRIPT=$P4C_BM_PATH/p4c_bm/__main__.py + +SWITCH_PATH=$BMV2_PATH/targets/simple_switch/simple_switch + +CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI + +# create CPU port +intf0="cpu-veth-0" +intf1="cpu-veth-1" +if ! ip link show $intf0 &> /dev/null; then + ip link add name $intf0 type veth peer name $intf1 + ip link set dev $intf0 up + ip link set dev $intf1 up + TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash" + for TOE_OPTION in $TOE_OPTIONS; do + /sbin/ethtool --offload $intf0 "$TOE_OPTION" off + /sbin/ethtool --offload $intf1 "$TOE_OPTION" off + done +fi +sysctl net.ipv6.conf.$intf0.disable_ipv6=1 +sysctl net.ipv6.conf.$intf1.disable_ipv6=1 + +$P4C_BM_SCRIPT p4src/simple_nat.p4 --json simple_nat.json +PYTHONPATH=$PYTHONPATH:$BMV2_PATH/mininet/ python topo.py \ + --behavioral-exe $BMV2_PATH/targets/simple_switch/simple_switch \ + --json simple_nat.json \ + --cli $CLI_PATH \ + --thrift-port 22222 diff --git a/examples/simple_nat/sswitch_CLI.sh b/examples/simple_nat/sswitch_CLI.sh new file mode 100755 index 0000000..da3c710 --- /dev/null +++ b/examples/simple_nat/sswitch_CLI.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +source $THIS_DIR/../env.sh + +CLI_PATH=$BMV2_PATH/targets/simple_switch/sswitch_CLI + +$CLI_PATH simple_nat.json 22222 diff --git a/examples/simple_nat/topo.py b/examples/simple_nat/topo.py new file mode 100644 index 0000000..6586068 --- /dev/null +++ b/examples/simple_nat/topo.py @@ -0,0 +1,113 @@ +#!/usr/bin/python + +# Copyright 2013-present Barefoot Networks, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from mininet.net import Mininet +from mininet.topo import Topo +from mininet.log import setLogLevel, info +from mininet.cli import CLI +from mininet.link import TCLink, Intf + +from p4_mininet import P4Switch, P4Host + +import argparse +from time import sleep +import os +import subprocess + +parser = argparse.ArgumentParser(description='Mininet demo') +parser.add_argument('--behavioral-exe', help='Path to behavioral executable', + type=str, action="store", required=True) +parser.add_argument('--json', help='Path to JSON config file', + type=str, action="store", required=True) +parser.add_argument('--cli', help='Path to BM CLI', + type=str, action="store", required=True) +parser.add_argument('--thrift-port', help='Thrift server port for table updates', + type=int, action="store", required=True) + +args = parser.parse_args() + +class MyTopo(Topo): + def __init__(self, sw_path, json_path, thrift_port, **opts): + # Initialize topology and default options + Topo.__init__(self, **opts) + + switch = self.addSwitch('s1', + sw_path = sw_path, + json_path = json_path, + thrift_port = thrift_port, + pcap_dump = True) + + # internal host + h1 = self.addHost('h1', + ip = "10.0.0.10", + mac = "00:04:00:00:00:10") + self.addLink(h1, switch) + + # external host + h2 = self.addHost('h2', + ip = "192.168.0.10", + mac = "00:05:00:00:00:10") + self.addLink(h2, switch) + +def main(): + topo = MyTopo(args.behavioral_exe, + args.json, + args.thrift_port) + + net = Mininet(topo = topo, + host = P4Host, + switch = P4Switch, + controller = None) + + cpu_intf = Intf("cpu-veth-1", net.get('s1'), 11) + + net.start() + + sw_macs = ["00:aa:bb:00:00:04", "00:aa:bb:00:00:05"] + + sw_addrs = ["10.0.0.1", "192.168.0.1"] + + for n in xrange(2): + h = net.get('h%d' % (n + 1)) + h.setARP(sw_addrs[n], sw_macs[n]) + h.setDefaultRoute("dev eth0 via %s" % sw_addrs[n]) + + for n in xrange(2): + h = net.get('h%d' % (n + 1)) + h.describe() + + sleep(1) + + cmd = [args.cli, args.json, str(args.thrift_port)] + with open("commands.txt", "r") as f: + print " ".join(cmd) + try: + output = subprocess.check_output(cmd, stdin = f) + print output + except subprocess.CalledProcessError as e: + print e + print e.output + + sleep(1) + + print "Ready !" + + CLI( net ) + net.stop() + +if __name__ == '__main__': + setLogLevel( 'info' ) + main()