commit
f9ccd265f3
@ -1,2 +1 @@
|
||||
sudo killall simple_switch
|
||||
redis-cli FLUSHDB
|
||||
sudo killall lt-simple_switch
|
||||
|
@ -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
|
||||
|
62
examples/simple_nat/README.md
Normal file
62
examples/simple_nat/README.md
Normal file
@ -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:
|
||||
|
||||

|
||||
|
||||
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`
|
27
examples/simple_nat/cleanup.sh
Executable file
27
examples/simple_nat/cleanup.sh
Executable file
@ -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
|
17
examples/simple_nat/commands.txt
Normal file
17
examples/simple_nat/commands.txt
Normal file
@ -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
|
77
examples/simple_nat/nat_app.py
Normal file
77
examples/simple_nat/nat_app.py
Normal file
@ -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()
|
364
examples/simple_nat/p4src/simple_nat.p4
Normal file
364
examples/simple_nat/p4src/simple_nat.p4
Normal file
@ -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);
|
||||
}
|
||||
}
|
306
examples/simple_nat/resources/topo.graphml
Normal file
306
examples/simple_nat/resources/topo.graphml
Normal file
@ -0,0 +1,306 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
|
||||
<!--Created by yEd 3.14-->
|
||||
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
|
||||
<key for="port" id="d1" yfiles.type="portgraphics"/>
|
||||
<key for="port" id="d2" yfiles.type="portgeometry"/>
|
||||
<key for="port" id="d3" yfiles.type="portuserdata"/>
|
||||
<key attr.name="url" attr.type="string" for="node" id="d4"/>
|
||||
<key attr.name="description" attr.type="string" for="node" id="d5"/>
|
||||
<key for="node" id="d6" yfiles.type="nodegraphics"/>
|
||||
<key for="graphml" id="d7" yfiles.type="resources"/>
|
||||
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
|
||||
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
|
||||
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
|
||||
<graph edgedefault="directed" id="G">
|
||||
<data key="d0"/>
|
||||
<node id="n0">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="107.0" width="144.0" x="685.0" y="215.0"/>
|
||||
<y:Fill color="#FFCC00" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="20.201171875" x="61.8994140625" y="43.3515625">s1<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n1">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="107.0" width="104.078125" x="969.0" y="215.0"/>
|
||||
<y:Fill color="#FF9900" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="21.7802734375" x="41.14892578125" y="43.3515625">h2<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="ellipse"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n2">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="107.0" width="104.078125" x="440.921875" y="215.0"/>
|
||||
<y:Fill color="#FF9900" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="21.7802734375" x="41.14892578125" y="43.3515625">h1<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="ellipse"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n3">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="47.0" width="144.0" x="685.0" y="426.0"/>
|
||||
<y:Fill color="#FF00FF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="81.916015625" x="31.0419921875" y="13.3515625">nat_app.py<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="roundrectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n4">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="30.0" width="153.0" x="680.5" y="402.5"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="79.728515625" x="36.6357421875" y="4.8515625">cpu-veth-0<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n5">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="30.0" width="153.0" x="680.5" y="322.0"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.296875" modelName="custom" textColor="#000000" visible="true" width="139.5908203125" x="6.70458984375" y="4.8515625">cpu-veth-1, port 11<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n6">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="61.0" width="153.0" x="581.0" y="179.5"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="52.890625" modelName="custom" textColor="#000000" visible="true" width="133.7734375" x="9.61328125" y="4.0546875">port 1
|
||||
00:aa:bb:00:00:04
|
||||
10.0.0.1<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n7">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="61.0" width="153.0" x="776.0" y="179.5"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="52.890625" modelName="custom" textColor="#000000" visible="true" width="133.7734375" x="9.61328125" y="4.0546875">port 2
|
||||
00:aa:bb:00:00:05
|
||||
192.168.0.1<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n8">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="45.5" width="153.0" x="486.5" y="276.5"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.59375" modelName="custom" textColor="#000000" visible="true" width="134.470703125" x="9.2646484375" y="4.453125">00:04:00:00:00:10
|
||||
10.0.0.10<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n9">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="45.5" width="153.0" x="872.5000000000001" y="276.5"/>
|
||||
<y:Fill color="#FFFFFF" transparent="false"/>
|
||||
<y:BorderStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="14" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.59375" modelName="custom" textColor="#000000" visible="true" width="134.470703125" x="9.2646484375" y="4.453125">00:05:00:00:00:10
|
||||
192.168.0.10<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n10">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="61.0" width="58.0" x="728.0" y="51.0"/>
|
||||
<y:Fill hasColor="false" transparent="false"/>
|
||||
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="custom" textColor="#000000" visible="true" width="4.0" x="27.0" y="28.5">
|
||||
<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n11">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="61.0" width="83.0" x="620.0" y="82.5"/>
|
||||
<y:Fill hasColor="false" transparent="false"/>
|
||||
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="22.625" modelName="custom" textColor="#000000" visible="true" width="65.9453125" x="8.52734375" y="19.1875">Internal<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<node id="n12">
|
||||
<data key="d5"/>
|
||||
<data key="d6">
|
||||
<y:ShapeNode>
|
||||
<y:Geometry height="61.0" width="83.0" x="811.0" y="82.5"/>
|
||||
<y:Fill hasColor="false" transparent="false"/>
|
||||
<y:BorderStyle hasColor="false" type="line" width="1.0"/>
|
||||
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="16" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="22.625" modelName="custom" textColor="#000000" visible="true" width="70.6640625" x="6.16796875" y="19.1875">External<y:LabelModel>
|
||||
<y:SmartNodeLabelModel distance="4.0"/>
|
||||
</y:LabelModel>
|
||||
<y:ModelParameter>
|
||||
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
|
||||
</y:ModelParameter>
|
||||
</y:NodeLabel>
|
||||
<y:Shape type="rectangle"/>
|
||||
</y:ShapeNode>
|
||||
</data>
|
||||
</node>
|
||||
<edge id="e0" source="n2" target="n0">
|
||||
<data key="d9"/>
|
||||
<data key="d10">
|
||||
<y:PolyLineEdge>
|
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
||||
<y:LineStyle color="#000000" type="line" width="2.0"/>
|
||||
<y:Arrows source="none" target="none"/>
|
||||
<y:BendStyle smoothed="false"/>
|
||||
</y:PolyLineEdge>
|
||||
</data>
|
||||
</edge>
|
||||
<edge id="e1" source="n0" target="n1">
|
||||
<data key="d9"/>
|
||||
<data key="d10">
|
||||
<y:PolyLineEdge>
|
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
||||
<y:LineStyle color="#000000" type="line" width="2.0"/>
|
||||
<y:Arrows source="none" target="none"/>
|
||||
<y:BendStyle smoothed="false"/>
|
||||
</y:PolyLineEdge>
|
||||
</data>
|
||||
</edge>
|
||||
<edge id="e2" source="n0" target="n3">
|
||||
<data key="d9"/>
|
||||
<data key="d10">
|
||||
<y:PolyLineEdge>
|
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
||||
<y:LineStyle color="#000000" type="line" width="1.0"/>
|
||||
<y:Arrows source="none" target="none"/>
|
||||
<y:BendStyle smoothed="false"/>
|
||||
</y:PolyLineEdge>
|
||||
</data>
|
||||
</edge>
|
||||
<edge id="e3" source="n10" target="n0">
|
||||
<data key="d9"/>
|
||||
<data key="d10">
|
||||
<y:PolyLineEdge>
|
||||
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
|
||||
<y:LineStyle color="#000000" type="dashed" width="2.0"/>
|
||||
<y:Arrows source="none" target="none"/>
|
||||
<y:BendStyle smoothed="false"/>
|
||||
</y:PolyLineEdge>
|
||||
</data>
|
||||
</edge>
|
||||
</graph>
|
||||
<data key="d7">
|
||||
<y:Resources/>
|
||||
</data>
|
||||
</graphml>
|
BIN
examples/simple_nat/resources/topo.png
Normal file
BIN
examples/simple_nat/resources/topo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
53
examples/simple_nat/run_demo.sh
Executable file
53
examples/simple_nat/run_demo.sh
Executable file
@ -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
|
9
examples/simple_nat/sswitch_CLI.sh
Executable file
9
examples/simple_nat/sswitch_CLI.sh
Executable file
@ -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
|
113
examples/simple_nat/topo.py
Normal file
113
examples/simple_nat/topo.py
Normal file
@ -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()
|
Loading…
x
Reference in New Issue
Block a user