P4 Switch: GRE TUNNEL
CASE 1: All nodes are linux-based nodes, including end host and routers.
H1:End Host (192.168.10.1)----(192.168.10.254) H3:Router (34.1.1.3)---(34.1.1.4) H4:Router (45.1.1.4)---(45.1.1.5) H5:Router (192.168.20.254)---(192.168.20.1)H2:End Host
We will create a GRE tunnel between H3 (12.1.1.1) and H5 (12.1.1.2). Therefore, H1 can communicate with H2.
[mininet script]
#!/usr/bin/python from mininet.net import Mininet from mininet.node
import Controller, RemoteController from mininet.cli
import CLI from mininet.log import setLogLevel from mininet.link
import Link, TCLink def topology(): "Create a
network." net = Mininet() print "*** Creating
nodes" h1 = net.addHost(
'h1', mac='00:00:00:00:00:01', ip='192.168.10.1/24') h2 = net.addHost(
'h2', mac='00:00:00:00:00:02', ip='192.168.20.1/24'
) h3 = net.addHost(
'h3', mac='00:00:00:00:00:03') h4 = net.addHost(
'h4', mac='00:00:00:00:00:04') h5 = net.addHost(
'h5', mac='00:00:00:00:00:05') print "*** Creating
links" Link(h1, h3,
intfName1='h1-eth0', intfName2='h3-eth0') Link(h2, h5,
intfName1='h2-eth0', intfName2='h5-eth0') Link(h3, h4,
intfName1='h3-eth1', intfName2='h4-eth0') Link(h4, h5,
intfName1='h4-eth1', intfName2='h5-eth1') net.build() h3.cmd("sudo ifconfig h3-eth0 0") h3.cmd("sudo ifconfig h3-eth1 0") h4.cmd("sudo ifconfig h4-eth0 0") h4.cmd("sudo ifconfig h4-eth1 0") h5.cmd("sudo ifconfig h5-eth0 0") h5.cmd("sudo ifconfig h5-eth1 0") h3.cmd("sudo echo 1 > /proc/sys/net/ipv4/ip_forward") h4.cmd("sudo echo 1 > /proc/sys/net/ipv4/ip_forward") h5.cmd("sudo echo 1 > /proc/sys/net/ipv4/ip_forward") h3.cmd("sudo ifconfig h3-eth0 192.168.10.254 netmask
255.255.255.0") h5.cmd("sudo ifconfig h5-eth0 192.168.20.254 netmask 255.255.255.0") h3.cmd("sudo ifconfig h3-eth1 34.1.1.3 netmask
255.255.255.0") h4.cmd("sudo ifconfig h4-eth0 34.1.1.4 netmask
255.255.255.0") h4.cmd("sudo ifconfig h4-eth1 45.1.1.4 netmask
255.255.255.0") h5.cmd("sudo ifconfig h5-eth1 45.1.1.5 netmask
255.255.255.0") #configure gre tunnel h3.cmd("sudo ip tunnel add netb mode gre remote 45.1.1.5
local 34.1.1.3 ttl 255") h3.cmd("sudo ip addr
add 12.1.1.1/24 dev netb") h3.cmd("sudo ifconfig netb up") h3.cmd("sudo ip route add 192.168.20.0/24
via 12.1.1.1") h5.cmd("sudo ip tunnel add neta mode gre remote 34.1.1.3
local 45.1.1.5 ttl 255") h5.cmd("sudo ip addr
add 12.1.1.2/24 dev neta") h5.cmd("sudo ifconfig neta up") h5.cmd("sudo ip route add
192.168.10.0/24 via 12.1.1.2") h1.cmd("sudo ip route add default via
192.168.10.254") h2.cmd("sudo ip route add default via
192.168.20.254") h3.cmd("sudo ip route add default via
34.1.1.4") h5.cmd("sudo ip route add default via
45.1.1.4") print "*** Running
CLI" CLI( net ) print "*** Stopping
network" net.stop() if __name__ == '__main__': setLogLevel(
'info' ) topology() |
[execution]
Ping and HTTP can work.
Case 2: All router nodes are replaced by P4 switches.
H1:End Host (192.168.10.1)----(192.168.10.254)
H3:P4 Switch (34.1.1.3)---(34.1.1.4) H4: P4 Switch (45.1.1.4)---(45.1.1.5) H5: P4 Switch (192.168.20.254)---(192.168.20.1)H2:End
Host
We will create a GRE tunnel between H3
(12.1.1.1) and H5 (12.1.1.2). Therefore, H1 can communicate with H2.
[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; } header gre_t { bit<16> flag_ver; bit<16> protocol; } struct metadata { /* empty */ } struct headers { ethernet_t ethernet; ipv4_t
inner_ipv4; gre_t gre; 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 select(hdr.ipv4.protocol) {
0x2f: parse_gre;
default: accept; } } state parse_gre
{ packet.extract(hdr.gre);
transition select(hdr.gre.protocol) {
0x0800: parse_inner_ipv4;
default: accept; } } state parse_inner_ipv4 { packet.extract(hdr.inner_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;
hdr.ipv4.ttl=hdr.ipv4.ttl-1; } action gre_encap(ip4Addr_t
src, ip4Addr_t dst, egressSpec_t port) { standard_metadata.egress_spec = port; hdr.gre.setValid(); hdr.gre.flag_ver=0; hdr.gre.protocol=0x0800;
hdr.inner_ipv4.setValid();
hdr.inner_ipv4.version=hdr.ipv4.version;
hdr.inner_ipv4.ihl=hdr.ipv4.ihl;
hdr.inner_ipv4.diffserv=hdr.ipv4.diffserv;
hdr.inner_ipv4.totalLen=hdr.ipv4.totalLen;
hdr.ipv4.totalLen=hdr.ipv4.totalLen+24; // add one ipv4 header + gre header
hdr.inner_ipv4.identification= hdr.ipv4.identification;
hdr.inner_ipv4.flags=hdr.ipv4.flags;
hdr.inner_ipv4.fragOffset=hdr.ipv4.fragOffset;
hdr.inner_ipv4.ttl=hdr.ipv4.ttl;
hdr.ipv4.ttl=255;
hdr.inner_ipv4.protocol=hdr.ipv4.protocol;
hdr.ipv4.protocol=0x2f;
hdr.inner_ipv4.hdrChecksum=hdr.ipv4.hdrChecksum;
hdr.inner_ipv4.srcAddr=hdr.ipv4.srcAddr;
hdr.inner_ipv4.dstAddr=hdr.ipv4.dstAddr;
hdr.ipv4.srcAddr=src;
hdr.ipv4.dstAddr=dst; } action gre_decap(egressSpec_t port) { standard_metadata.egress_spec = port;
hdr.ipv4.version=hdr.inner_ipv4.version;
hdr.ipv4.ihl=hdr.inner_ipv4.ihl;
hdr.ipv4.diffserv=hdr.inner_ipv4.diffserv;
hdr.ipv4.totalLen=hdr.ipv4.totalLen-24;
hdr.ipv4.identification= hdr.inner_ipv4.identification;
hdr.ipv4.flags=hdr.inner_ipv4.flags;
hdr.ipv4.fragOffset=hdr.inner_ipv4.fragOffset;
hdr.ipv4.ttl=hdr.inner_ipv4.ttl;
hdr.ipv4.protocol=hdr.inner_ipv4.protocol;
hdr.ipv4.hdrChecksum=hdr.inner_ipv4.hdrChecksum;
hdr.ipv4.srcAddr=hdr.inner_ipv4.srcAddr;
hdr.ipv4.dstAddr=hdr.inner_ipv4.dstAddr;
hdr.inner_ipv4.setInvalid(); hdr.gre.setInvalid(); } table ip_forward
{
key = {
hdr.ipv4.dstAddr: lpm; }
actions = {
gre_encap;
forward;
drop; }
size = 1024; default_action = drop(); } table gre_receive
{
key = {
hdr.ipv4.dstAddr: lpm; }
actions = {
gre_decap;
NoAction(); }
size = 1024; default_action = NoAction(); } apply { ip_forward.apply();
if(hdr.gre.isValid()) {
gre_receive.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) { action setDstMac(macAddr_t dst) { hdr.ethernet.dstAddr=dst; } table dstforward
{
key = {
hdr.ipv4.dstAddr: exact; }
actions = { setDstMac;
NoAction; }
size = 1024; default_action = NoAction(); } apply { dstforward.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); packet.emit(hdr.gre); packet.emit(hdr.inner_ipv4); } } /************************************************************************* *********************** S W I T C H ******************************* *************************************************************************/ V1Switch( MyParser(), MyVerifyChecksum(), MyIngress(), MyEgress(), MyComputeChecksum(), MyDeparser() ) main; |
[test_topo.py]
import os from mininet.net import Mininet from mininet.topo
import Topo from mininet.log import setLogLevel, info from mininet.cli
import CLI from mininet.node
import RemoteController from p4_mininet import P4Switch, P4Host import argparse from time import sleep parser = argparse.ArgumentParser(description='Mininet demo') parser.add_argument('--behavioral-exe', help='Path to behavioral executable',
type=str, action="store", required=False, default='simple_switch' ) parser.add_argument('--thrift-port', help='Thrift server port for table updates', type=int,
action="store", default=9090) parser.add_argument('--num-hosts', help='Number of hosts to connect to switch',
type=int, action="store", default=2) parser.add_argument('--mode', choices=['l2', 'l3'], type=str, default='l3') parser.add_argument('--json', help='Path to JSON config file',
type=str, action="store", required=True) parser.add_argument('--pcap-dump', help='Dump packets on
interfaces to pcap files',
type=str, action="store", required=False, default=False) args = parser.parse_args() class SingleSwitchTopo(Topo): def __init__(self,
sw_path, json_path, thrift_port, pcap_dump,
**opts):
Topo.__init__(self, **opts) switch3 = self.addSwitch('s3', sw_path = sw_path, json_path = json_path, thrift_port = thrift_port,cls =
P4Switch ,pcap_dump = pcap_dump)
switch4 = self.addSwitch('s4', sw_path = sw_path, json_path = json_path, thrift_port = thrift_port +
1,cls = P4Switch ,pcap_dump = pcap_dump) switch5 = self.addSwitch('s5', sw_path = sw_path, json_path = json_path, thrift_port = thrift_port + 2,cls = P4Switch ,pcap_dump
= pcap_dump)
host1 = self.addHost('h1', mac =
'00:00:00:00:00:01', ip="192.168.10.1/24") host2
= self.addHost('h2', mac = '00:00:00:00:00:02', ip="192.168.20.1/24") self.addLink(host1, switch3, port1 = 0, port2 = 1) self.addLink(host2, switch5, port1 = 0, port2 = 1) self.addLink(switch3, switch4, port1 = 2, port2 = 1) self.addLink(switch4, switch5, port1 = 2, port2 = 2) def main(): topo = SingleSwitchTopo(args.behavioral_exe, args.json,
args.thrift_port, args.pcap_dump) net = Mininet(topo
= topo, host = P4Host, controller = None) net.start() h1,h2=net.get('h1','h2'); s3,s5=net.get('s3','s5'); h1.cmd("ip route add default via 192.168.10.254") h2.cmd("ip route add default via 192.168.20.254") s3.cmd("ifconfig s3-eth1
down") s3.cmd("ifconfig
s3-eth1 hw ether 00:00:00:00:00:03"); s3.cmd("ifconfig
s3-eth1 up") s5.cmd("ifconfig
s5-eth1 down") s5.cmd("ifconfig
s5-eth1 hw ether 00:00:00:00:00:04"); s5.cmd("ifconfig
s5-eth1 up") h1.cmd("arp -s 192.168.10.254 00:00:00:00:00:03") h2.cmd("arp -s 192.168.20.254 00:00:00:00:00:04")
sleep(1) print('\033[0;32m'), print "Gotcha!" print('\033[0m') CLI(net) try: net.stop() except:
print('\033[0;31m'),
print('Stop error! Trying sudo mn -c')
print('\033[0m') os.system('sudo mn -c')
print('\033[0;32m'),
print ('Stop successfully!')
print('\033[0m') if __name__ == '__main__': setLogLevel('info') main() |
[start_test_topo.py]
import os os.system("sudo python test_topo.py --behavioral-exe /home/user/behavioral-model/targets/simple_switch/simple_switch --json basic.json") |
[cmd_add.py]
import os os.system('sudo
/home/user/behavioral-model/targets/simple_switch/simple_switch_CLI
--thrift-port=9090 < cmd.txt') os.system('sudo
/home/user/behavioral-model/targets/simple_switch/simple_switch_CLI
--thrift-port=9091 < cmd1.txt') os.system('sudo /home/user/behavioral-model/targets/simple_switch/simple_switch_CLI --thrift-port=9092 < cmd2.txt') |
[cmd.txt]
table_add ip_forward forward 0.0.0.0/0 => 2 table_add ip_forward gre_encap
192.168.20.0/24 => 34.1.1.3 45.1.1.5 2 table_add gre_receive gre_decap
34.1.1.3/32 => 1 table_add dstforward setDstMac 192.168.10.1 => 00:00:00:00:00:01 |
[cmd1.txt]
table_add ip_forward forward 34.1.1.0/24 => 1 table_add ip_forward forward 45.1.1.0/24 => 2 |
[cmd2.txt]
table_add ip_forward forward 0.0.0.0/0 => 2 table_add ip_forward gre_encap
192.168.10.0/24 => 45.1.1.5 34.1.1.3 2 table_add gre_receive gre_decap
45.1.1.5/32 => 1 table_add dstforward setDstMac 192.168.20.1 => 00:00:00:00:00:02 |
[p4_mininet.py]
from mininet.net import Mininet from mininet.node
import Switch, Host from mininet.log import setLogLevel, info, error, debug from mininet.moduledeps
import pathCheck from sys import exit import os import tempfile import socket class P4Host(Host): def config(self,
**params): r
= super(Host, self).config(**params) self.defaultIntf().rename("eth0")
for off in ["rx", "tx", "sg"]:
cmd = "/sbin/ethtool --offload eth0 %s off" % off
self.cmd(cmd) #
disable IPv6
self.cmd("sysctl -w
net.ipv6.conf.all.disable_ipv6=1")
self.cmd("sysctl -w
net.ipv6.conf.default.disable_ipv6=1")
self.cmd("sysctl -w
net.ipv6.conf.lo.disable_ipv6=1")
return r def describe(self):
print "**********"
print self.name
print "default interface: %s\t%s\t%s" %(
self.defaultIntf().name,
self.defaultIntf().IP(),
self.defaultIntf().MAC() )
print "**********" class P4Switch(Switch): """P4
virtual switch""" device_id
= 0 def __init__(self,
name, sw_path = None, json_path
= None,
thrift_port = None,
pcap_dump = False,
log_console = True,
verbose = True,
device_id = None,
enable_debugger = False,
**kwargs):
Switch.__init__(self, name, **kwargs)
assert(sw_path)
assert(json_path) #
make sure that the provided sw_path is valid pathCheck(sw_path) #
make sure that the provided JSON file exists if
not os.path.isfile(json_path):
error("Invalid JSON file.\n")
exit(1) self.sw_path = sw_path self.json_path
= json_path self.verbose = verbose
logfile = "/tmp/p4s.{}.log".format(self.name) self.output = open(logfile, 'w') self.thrift_port = thrift_port self.pcap_dump = pcap_dump self.enable_debugger = enable_debugger self.log_console = log_console if
device_id is not None:
self.device_id = device_id
P4Switch.device_id = max(P4Switch.device_id, device_id)
else:
self.device_id = P4Switch.device_id
P4Switch.device_id += 1 self.nanomsg = "ipc:///tmp/bm-{}-log.ipc".format(self.device_id) @classmethod def setup(cls):
pass def check_switch_started(self,
pid):
"""While the process is running (pid
exists), we check if the Thrift
server has been started. If the Thrift server is ready, we assume that
the switch was started successfully. This is only reliable if the
Thrift
server is started at the end of the init
process"""
while True:
if not os.path.exists(os.path.join("/proc",
str(pid))):
return False
sock = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
sock.settimeout(0.5)
result = sock.connect_ex(("localhost",
self.thrift_port))
if result == 0:
return True def start(self,
controllers):
"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]) #wuwzhs edit in 2017/11/10 #args.extend(['-i 3@veth1']) if
self.pcap_dump:
args.append("--pcap")
# args.append("--useFiles") 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)])
P4Switch.device_id += 1 args.append(self.json_path) if
self.enable_debugger:
args.append("--debugger") if
self.log_console:
args.append("--log-console")
logfile = "/tmp/p4s.{}.log".format(self.name)
info(' '.join(args) + "\n") pid = None
with tempfile.NamedTemporaryFile() as f:
# self.cmd(' '.join(args) + ' > /dev/null
2>&1 &') self.cmd('
'.join(args) + ' >' + logfile + ' 2>&1
& echo $! >> ' + f.name)
pid = int(f.read())
debug("P4 switch {} PID is {}.\n".format(self.name,
pid)) if
not self.check_switch_started(pid):
error("P4 switch {} did not start correctly.\n".format(self.name))
exit(1)
info("P4 switch {} has been started.\n".format(self.name)) def stop(self):
"Terminate P4 switch." self.output.flush()
self.cmd('kill %' + self.sw_path)
self.cmd('wait') self.deleteIntfs() def attach(self, intf):
"Connect a data port"
assert(0) def detach(self, intf):
"Disconnect a data port" assert(0) |
[execution]
Ping test can work. We can also capture the packets at s4-eth1. The packets sent by H1 are transmitted with ethernet header--ip header--GRE header--ip header--payload.
Case 3: Mixed Scenario.
H1:End Host (192.168.10.1)----(192.168.10.254)
H3:P4 Switch (34.1.1.3)---(34.1.1.4) H4: Router (45.1.1.4)---(45.1.1.5) H5: Router (192.168.20.254)---(192.168.20.1)H2:End Host
We will create a GRE tunnel between H3
(12.1.1.1) and H5 (12.1.1.2). Therefore, H1 can communicate with H2.
The most files are the same as case 2. I only show the differences in the following file.
[cmd_add.py]
import os os.system('sudo /home/user/behavioral-model/targets/simple_switch/simple_switch_CLI --thrift-port=9090 < cmd.txt') |
[cmd.txt]
table_add ip_forward forward 0.0.0.0/0 => 2 table_add ip_forward gre_encap
192.168.20.0/24 => 34.1.1.3 45.1.1.5 2 table_add gre_receive gre_decap
34.1.1.3/32 => 1 table_add dstforward setDstMac
45.1.1.5 => 00:00:00:00:00:05 table_add dstforward setDstMac 192.168.10.1 => 00:00:00:00:00:01 |
[test_topo.txt]
import os from mininet.net import Mininet from mininet.topo
import Topo from mininet.log import setLogLevel, info from mininet.cli
import CLI from mininet.node
import RemoteController from p4_mininet import P4Switch, P4Host import argparse from time import sleep parser = argparse.ArgumentParser(description='Mininet demo') parser.add_argument('--behavioral-exe', help='Path to behavioral executable',
type=str, action="store", required=False, default='simple_switch' ) parser.add_argument('--thrift-port', help='Thrift server port for table updates',
type=int, action="store", default=9090) parser.add_argument('--num-hosts', help='Number of hosts to connect to switch',
type=int, action="store", default=2) parser.add_argument('--mode', choices=['l2', 'l3'], type=str, default='l3') parser.add_argument('--json', help='Path to JSON config file',
type=str, action="store", required=True) parser.add_argument('--pcap-dump', help='Dump packets on
interfaces to pcap files',
type=str, action="store", required=False, default=False) args = parser.parse_args() class SingleSwitchTopo(Topo): def __init__(self,
sw_path, json_path, thrift_port, pcap_dump, **opts):
Topo.__init__(self, **opts) switch3 = self.addSwitch('s3', sw_path = sw_path, json_path = json_path, thrift_port = thrift_port,cls =
P4Switch ,pcap_dump = pcap_dump)
host1 = self.addHost('h1', mac = '00:00:00:00:00:01',
ip="192.168.10.1/24")
host2 = self.addHost('h2', mac =
'00:00:00:00:00:02', ip="192.168.20.1/24")
host4 = self.addHost('s4')
host5 = self.addHost('s5') self.addLink(host1, switch3, port1 = 0, port2 = 1) self.addLink(host2, host5, port1 = 0, port2 = 0) self.addLink(switch3, host4, port1 = 2, port2 = 0) self.addLink(host4, host5, port1 = 1, port2 = 1) def main(): topo = SingleSwitchTopo(args.behavioral_exe, args.json,
args.thrift_port, args.pcap_dump) net = Mininet(topo
= topo, host = P4Host, controller = None) net.start() h1,h2=net.get('h1','h2'); s4,s5=net.get('s4','s5'); s3=net.get('s3'); h1.cmd("ip route add default via 192.168.10.254") h2.cmd("ip route add default via 192.168.20.254") s3.cmd("ifconfig
s3-eth1 down") s3.cmd("ifconfig
s3-eth1 hw ether 00:00:00:00:00:03") s3.cmd("ifconfig
s3-eth1 up") s3.cmd("ifconfig
s3-eth2 down") s3.cmd("ifconfig
s3-eth2 hw ether 00:00:00:00:00:06") s3.cmd("ifconfig
s3-eth2 up") s5.cmd("ifconfig eth0
down") s5.cmd("ifconfig eth0
hw ether 00:00:00:00:00:04") s5.cmd("ifconfig eth0
up") s4.cmd("ifconfig eth0
down") s4.cmd("ifconfig eth0
hw ether 00:00:00:00:00:05") s4.cmd("ifconfig eth0
up") s4.cmd("ifconfig eth0
0") s4.cmd("ifconfig
h4-eth1 0") s4.cmd("ip addr add 34.1.1.4/24 brd + dev eth0") s4.cmd("ip addr add 45.1.1.4/24 brd + dev s4-eth1") s4.cmd("echo 1 >
/proc/sys/net/ipv4/ip_forward") s4.cmd("arp -s 34.1.1.3 00:00:00:00:00:06") s5.cmd("ifconfig eth0
0") s5.cmd("ifconfig
h5-eth1 0") s5.cmd("ip addr add 192.168.20.254/24 brd + dev eth0") s5.cmd("ip addr add 45.1.1.5/24 brd + dev s5-eth1") s5.cmd("echo 1 >
/proc/sys/net/ipv4/ip_forward") h1.cmd("arp -s 192.168.10.254 00:00:00:00:00:03") h2.cmd("arp -s 192.168.20.254 00:00:00:00:00:04") s5.cmd("ip tunnel add neta mode gre remote 34.1.1.3 local 45.1.1.5 ttl
255") s5.cmd("ip addr add 12.1.1.2/24 dev neta") s5.cmd("ifconfig neta up") s5.cmd("ip route add 192.168.10.0/24 via 12.1.1.2") s5.cmd("ip
route add default via 45.1.1.4")
sleep(1) print('\033[0;32m'), print "Gotcha!" print('\033[0m') CLI(net) try: net.stop() except:
print('\033[0;31m'),
print('Stop error! Trying sudo mn -c')
print('\033[0m') os.system('sudo mn -c')
print('\033[0;32m'),
print ('Stop successfully!')
print('\033[0m') if __name__ == '__main__': setLogLevel('info') main() |
[execution]
Ping and HTTP test can work.
Dr. Chih-Heng Ke (smallko@gmail.com)
Department of Computer Science and Information
Engineering,
National Quemoy University, Kinmen, Taiwan.