
mininet(一)实验环境搭建
mininet(二)简单的路由实验
mininet(三)简单的NAT实验
本次实验拓扑图如下:
假设 Openvswitch switch1是一个带有NAT功能的路由器,H1 的IP地址为 192.168.1.10,MAC地址为:00:00:00:00:00:01, H2 的IP地址为 10.0.0.1 MAC 地址为 00:00:00:00:00:02。私有网络的默认网关为: 192.168.1.1。公网默认网关为: 10.0.0.2。 在H1发送IP报文给H2的时候首先会发送ARP报文查询192.168.1.1的MAC地址,需要OpenVswitch发送 ARP回复报文给H1,H1收到网关的MAC后会将报文发送给switch。
nat.py
#!/usr/bin/python
from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSKernelSwitch
from mininet.link import Link, TCLink
from mininet.cli import CLI
from mininet.log import setLogLevel
def topology():
net = Mininet( controller=RemoteController, link=TCLink, switch=OVSKernelSwitch )
print "*** Creating nodes"
h1 = net.addHost( 'h1', mac='00:00:00:00:00:01', ip='192.168.1.10/24' )
h2 = net.addHost( 'h2', mac='00:00:00:00:00:02', ip='10.0.0.1/24' )
s1 = net.addSwitch( 's1', protocols='OpenFlow10', listenPort=6673)
c1 = net.addController( 'c1', ip='127.0.0.1', port=6633 )
print "*** Creating links"
net.addLink(h1, s1)
net.addLink(h2, s1)
print "*** Starting network"
net.build()
c1.start()
s1.start( [c1] )
print "*** Running CLI"
h1.cmd("ip route add default via 192.168.1.1 dev h1-eth0")
h2.cmd("ip route add default via 10.0.0.2 dev h2-eth0")
CLI( net )
print "*** Stopping network"
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
topology()
mypox.py
#!/usr/bin/python
from pox.core import core
from pox.lib.addresses import IPAddr
from pox.lib.addresses import EthAddr
import pox.openflow.libopenflow_01 as of
from pox.lib.util import dpid_to_str, str_to_bool
from pox.lib.packet.arp import arp
from pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST
log = core.getLogger()
#flow2:
switch2 = 0000000000000001
flow2msg = of.ofp_flow_mod(command=0) #add flow rules
flow2msg.cookie = 0
flow2msg.match.in_port = 1 # match in port,the index of the switch
flow2msg.match.dl_type = 0x0800 # match ipv4 protcol
flow2msg.match.nw_src = IPAddr("192.168.1.10") # match src ip 192.168.1.10
# ACTIONS---------------------------------
flow2out = of.ofp_action_output (port = 2)
flow2srcIP = of.ofp_action_nw_addr.set_src(IPAddr("10.0.0.2")) # set src ip to 10.0.0.2
flow2srcMAC = of.ofp_action_dl_addr.set_src(EthAddr("00:00:00:00:00:04")) # set src mac 00.**.04
flow2dstMAC = of.ofp_action_dl_addr.set_dst(EthAddr("00:00:00:00:00:02")) # set dst mac 00.**.01 host2
flow2msg.actions = [flow2srcIP, flow2srcMAC, flow2dstMAC, flow2out]
#flow3:
switch3 = 0000000000000001
flow3msg = of.ofp_flow_mod(command=0)#add flow rules
flow3msg.cookie = 0
flow3msg.match.in_port = 2 # match in port,the index of the switch
flow3msg.match.dl_type = 0x0800
flow3msg.match.nw_dst = IPAddr("10.0.0.2") # match dst ip 10.0.0.2
# ACTIONS---------------------------------
flow3out = of.ofp_action_output (port = 1)
flow3dstIP = of.ofp_action_nw_addr.set_dst(IPAddr("192.168.1.10")) # set dst ip to 192.168.1.10
flow3srcMAC = of.ofp_action_dl_addr.set_src(EthAddr("00:00:00:00:00:03")) # #set src mac to 00.**.03
flow3dstMAC = of.ofp_action_dl_addr.set_dst(EthAddr("00:00:00:00:00:01")) # set dst mac to 00.**.01
flow3msg.actions = [flow3dstIP, flow3srcMAC, flow3dstMAC, flow3out]
def install_flows():
log.info(" *** Installing static flows... ***")
# Push flows to switches
core.openflow.sendToDPID(switch2, flow2msg)
core.openflow.sendToDPID(switch3, flow3msg)
log.info(" *** Static flows installed. ***")
def _handle_ConnectionUp (event):
log.info("*** install flows ***")
install_flows()
def _handle_PacketIn (event):
#log.info("*** _handle_PacketIn... ***")
dpid = event.connection.dpid
inport = event.port
packet = event.parsed
if not packet.parsed:
log.warning("%i %i ignoring unparsed packet", dpid, inport)
return
a = packet.find('arp')
if not a: return
log.info("%s ARP %s %s => %s", dpid_to_str(dpid),
{arp.REQUEST:"request",arp.REPLY:"reply"}.get(a.opcode,
'op:%i' % (a.opcode,)), str(a.protosrc), str(a.protodst))
if a.prototype == arp.PROTO_TYPE_IP and a.hwtype == arp.HW_TYPE_ETHERNET and a.opcode == arp.REQUEST:
r = arp()
r.hwtype = a.hwtype
r.prototype = a.prototype
r.hwlen = a.hwlen
r.protolen = a.protolen
r.opcode = arp.REPLY
r.hwdst = a.hwsrc
r.protodst = a.protosrc
r.protosrc = a.protodst
if str(a.protodst)=="192.168.1.1":
r.hwsrc = EthAddr("00:00:00:00:00:03")
if str(a.protodst)=="10.0.0.2":
r.hwsrc = EthAddr("00:00:00:00:00:04")
e = ethernet(type=packet.type, src=r.hwsrc,
dst=a.hwsrc)
e.payload = r
log.info("%s answering ARP for %s" % (dpid_to_str(dpid),
str(r.protosrc)))
msg = of.ofp_packet_out()
msg.data = e.pack()
msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
msg.in_port = inport
event.connection.send(msg)
def launch ():
log.info("*** Starting... ***")
log.info("*** Waiting for switches to connect.. ***")
core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
core.openflow.addListenerByName("PacketIn", _handle_PacketIn)
两条规则说明
1、从交换机1口进,并且源ip为 192.168.1.10,将报文的源ip修改为10.0.0.2,源mac修改为00:00:00:00:00:04,修改目的为00:00:00:00:00:02(主机h2的mac)
2、从交换机2口进,并且目的ip为10.0.0.2,将报文的目的ip修改为192.168.1.10,源mac修改为00:00:00:00:00:03,修改目的为00:00:00:00:00:01(主机h1的mac)
实验结果:
mininet@mininet-vm:~/pox$ ./pox.py mypox
POX 0.2.0 (carp) / Copyright 2011-2013 James McCauley, et al.
INFO:mypox:*** Starting... ***
INFO:mypox:*** Waiting for switches to connect.. ***
INFO:core:POX 0.2.0 (carp) is up.
INFO:openflow.of_01:[None 1] closed
INFO:openflow.of_01:[00-00-00-00-00-01 2] connected
INFO:mypox:*** install flows ***
INFO:mypox: *** Installing static flows... ***
INFO:mypox: *** Static flows installed. ***
INFO:openflow.of_01:[00-00-00-00-00-02 3] connected
INFO:mypox:*** install flows ***
INFO:mypox: *** Installing static flows... ***
INFO:mypox: *** Static flows installed. ***
INFO:mypox:00-00-00-00-00-01 ARP request 192.168.1.10 => 192.168.1.1
INFO:mypox:00-00-00-00-00-01 answering ARP for 192.168.1.1
INFO:mypox:00-00-00-00-00-01 ARP request 10.0.0.1 => 10.0.0.2
INFO:mypox:00-00-00-00-00-01 answering ARP for 10.0.0.2
mininet@mininet-vm:~$ sudo python nat.py
*** Creating nodes
*** Creating links
*** Starting network
*** Configuring hosts
h1 h2
*** Running CLI
*** Starting CLI:
mininet> h1 ping h2 -c 4
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=39.6 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.063 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.055 ms
--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3074ms
rtt min/avg/max/mdev = 0.055/9.960/39.643/17.137 ms
在h1上面抓包可以看到的是192.168.1.10 -> 10.0.0.1
在h2上面抓包可以看到的是 10.0.0.2 -> 10.0.0.1