Mininet系列實驗(六):Mininet動態改變轉發規則實驗

一、 實驗目的

熟悉Mininet自定義拓撲腳本的編寫;
熟悉編寫POX腳本動態改變轉發規則

二、實驗原理

在SDN環境中,控制器可以通過對交換機下發流表操作來控制交換機的轉發行爲。在本實驗中,基於Mininet腳本,編寫POX腳本,動態改變交換機的轉發規則。

三、實驗任務

先看一下本次實驗的拓撲圖:

基於Mininet使用POX動態改變轉發規則實驗 圖1

在該環境下,假設H1 ping H4,初始的路由規則是S1-S2-S5,一秒後,路由轉發規則變爲S1-S3-S5,再過一秒,規則變爲S1-S4-S5,然後再回到最初的轉發規則S1-S2-S5。通過這個循環調度的例子動態地改變交換機的轉發規則。

1.1在pox文件裏面創建腳本lab_controller.py

from pox.core import core
 
import pox.openflow.libopenflow_01 as of
 
from pox.lib.util import dpidToStr
 
from pox.lib.addresses import IPAddr, EthAddr
 
from pox.lib.packet.arp import arp
 
from pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST
 
from pox.lib.packet.packet_base import packet_base
 
from pox.lib.packet.packet_utils import *
 
import pox.lib.packet as pkt
 
from pox.lib.recoco import Timer
 
import time
 
 
 
log = core.getLogger()
 
 
 
s1_dpid=0
 
s2_dpid=0
 
s3_dpid=0
 
s4_dpid=0
 
s5_dpid=0
 
 
 
s1_p1=0
 
s1_p4=0
 
s1_p5=0
 
s1_p6=0
 
s2_p1=0
 
s3_p1=0
 
s4_p1=0
 
 
 
pre_s1_p1=0
 
pre_s1_p4=0
 
pre_s1_p5=0
 
pre_s1_p6=0
 
pre_s2_p1=0
 
pre_s3_p1=0
 
pre_s4_p1=0
 
 
 
turn=0
 
 
 
def getTheTime():  #fuction to create a timestamp
 
  flock = time.localtime()
 
  then = "[%s-%s-%s" %(str(flock.tm_year),str(flock.tm_mon),str(flock.tm_mday))
 
 
 
  if int(flock.tm_hour)<10:
 
    hrs = "0%s" % (str(flock.tm_hour))
 
  else:
 
    hrs = str(flock.tm_hour)
 
  if int(flock.tm_min)<10:
 
    mins = str(flock.tm_min)
 
    secs = "0%s" % (str(flock.tm_sec))
 
  else:
 
    secs = str(flock.tm_sec)
 
 
 
  then +="]%s.%s.%s" % (hrs,mins,secs)
 
  return then
 
 
 
 
 
def _timer_func ():
 
  global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid,turn
 
 
 
 
 
  #print getTheTime(), "sent the port stats request to s1_dpid"
 
 
 
  if turn==0:
 
      msg = of.ofp_flow_mod()
 
      msg.command=of.OFPFC_MODIFY_STRICT
 
      msg.priority =100
 
      msg.idle_timeout = 0
 
      msg.hard_timeout = 0
 
      msg.match.dl_type = 0x0800
 
      msg.match.nw_dst = "10.0.0.4"
 
      msg.actions.append(of.ofp_action_output(port = 5))
 
      core.openflow.getConnection(s1_dpid).send(msg)
 
      turn=1
 
      return
 
 
 
  if turn==1:
 
      msg = of.ofp_flow_mod()
 
      msg.command=of.OFPFC_MODIFY_STRICT
 
      msg.priority =100
 
      msg.idle_timeout = 0
 
      msg.hard_timeout = 0
 
      msg.match.dl_type = 0x0800
 
      msg.match.nw_dst = "10.0.0.4"
 
      msg.actions.append(of.ofp_action_output(port = 6))
 
      core.openflow.getConnection(s1_dpid).send(msg)
 
      turn=2
 
      return
 
 
 
  if turn==2:
 
      msg = of.ofp_flow_mod()
 
      msg.command=of.OFPFC_MODIFY_STRICT
 
      msg.priority =100
 
      msg.idle_timeout = 0
 
      msg.hard_timeout = 0
 
      msg.match.dl_type = 0x0800
 
      msg.match.nw_dst = "10.0.0.4"
 
      msg.actions.append(of.ofp_action_output(port = 4))
 
      turn=0
 
      return
 
 
 
def _handle_portstats_received (event):
 
  global s1_p1,s1_p4, s1_p5, s1_p6, s2_p1, s3_p1, s4_p1
 
  global pre_s1_p1,pre_s1_p4, pre_s1_p5, pre_s1_p6, pre_s2_p1, pre_s3_p1, pre_s4_p1
 
 
 
  if event.connection.dpid==s1_dpid:
 
    for f in event.stats:
 
      if int(f.port_no)<65534:
 
        if f.port_no==1:
 
          pre_s1_p1=s1_p1
 
          s1_p1=f.rx_packets
 
 
        if f.port_no==4:
 
          pre_s1_p4=s1_p4
 
          s1_p4=f.tx_packets
 
          #s1_p4=f.tx_bytes
 
 
        if f.port_no==5:
 
          pre_s1_p5=s1_p5
 
          s1_p5=f.tx_packets
 
        if f.port_no==6:
 
          pre_s1_p6=s1_p6
 
          s1_p6=f.tx_packets
 
 
 
    for f in event.stats:
 
       if int(f.port_no)<65534:
 
         if f.port_no==1:
 
           pre_s2_p1=s2_p1
 
           s2_p1=f.rx_packets
 
           #s2_p1=f.rx_bytes
 
 
  if event.connection.dpid==s3_dpid:
 
     for f in event.stats:
 
       if int(f.port_no)<65534:
 
         if f.port_no==1:
 
           pre_s3_p1=s3_p1
 
           s3_p1=f.rx_packets
 
 
 
 
  if event.connection.dpid==s4_dpid:
 
     for f in event.stats:
 
       if int(f.port_no)<65534:
 
         if f.port_no==1:
 
           pre_s4_p1=s4_p1
 
           s4_p1=f.rx_packets
 
 
 
 
def _handle_ConnectionUp (event):
 
  global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid
 
  print "ConnectionUp: ",dpidToStr(event.connection.dpid)
 
 
 
  #remember the connection dpid for switch
 
  for m in event.connection.features.ports:
 
    if m.name == "s1-eth1":
 
      s1_dpid = event.connection.dpid
 
      print "s1_dpid=", s1_dpid
 
    elif m.name == "s2-eth1":
 
      s2_dpid = event.connection.dpid
 
      print "s2_dpid=", s2_dpid
 
    elif m.name == "s3-eth1":
 
      s3_dpid = event.connection.dpid
 
    elif m.name == "s4-eth1":
 
      s4_dpid = event.connection.dpid
 
      print "s4_dpid=", s4_dpid
 
    elif m.name == "s5-eth1":
 
      s5_dpid = event.connection.dpid
 
      print "s5_dpid=", s5_dpid
 
 
 
  if s1_dpid<>0 and s2_dpid<>0 and s3_dpid<>0 and s4_dpid<>0:
 
    Timer(1, _timer_func, recurring=True)
 
 
 
def _handle_PacketIn(event):
 
  global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid
 
 
 
  packet=event.parsed
 
 
 
 
  if event.connection.dpid==s1_dpid:
 
     a=packet.find('arp')
 
     if a and a.protodst=="10.0.0.4":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=4))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.5":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=5))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.6":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=6))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.1":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=1))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.2":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=2))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.3":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=3))
 
       event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.1"
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.2"
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.3"
 
     msg.actions.append(of.ofp_action_output(port = 3))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 1
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.4"
 
     msg.actions.append(of.ofp_action_output(port = 4))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.5"
 
     msg.actions.append(of.ofp_action_output(port = 5))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.6"
 
     msg.actions.append(of.ofp_action_output(port = 6))
 
     event.connection.send(msg)
 
 
 
  elif event.connection.dpid==s2_dpid:
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
  elif event.connection.dpid==s3_dpid:
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
  elif event.connection.dpid==s4_dpid:
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 1
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0806
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =10
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.in_port = 2
 
     msg.match.dl_type=0x0800
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
  elif event.connection.dpid==s5_dpid:
 
     a=packet.find('arp')
 
     if a and a.protodst=="10.0.0.4":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=4))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.5":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=5))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.6":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=6))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.1":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=1))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.2":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=2))
 
       event.connection.send(msg)
 
 
 
     if a and a.protodst=="10.0.0.3":
 
       msg = of.ofp_packet_out(data=event.ofp)
 
       msg.actions.append(of.ofp_action_output(port=3))
 
       event.connection.send(msg)
 
 
 
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.1"
 
     msg.actions.append(of.ofp_action_output(port = 1))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.2"
 
     msg.actions.append(of.ofp_action_output(port = 2))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.3"
 
     msg.actions.append(of.ofp_action_output(port = 3))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.4"
 
     msg.actions.append(of.ofp_action_output(port = 4))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.5"
 
     msg.actions.append(of.ofp_action_output(port = 5))
 
     event.connection.send(msg)
 
 
 
     msg = of.ofp_flow_mod()
 
     msg.priority =100
 
     msg.idle_timeout = 0
 
     msg.hard_timeout = 0
 
     msg.match.dl_type = 0x0800
 
     msg.match.nw_dst = "10.0.0.6"
 
     msg.actions.append(of.ofp_action_output(port = 6))
 
     event.connection.send(msg)
 
 
 
def launch ():
 
  global start_time
 
  core.openflow.addListenerByName("PortStatsReceived",_handle_portstats_received)
 
  core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
 
  core.openflow.addListenerByName("PacketIn",_handle_PacketIn)

1.2查看流表項(做完步驟2再回來)

./pox.py lab_controller web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk

然後再火狐裏面搜索:http://pox-ip:8000/poxdesk然後點擊TableViewer選擇s1即00-00-00-00-01就會跳出下圖(其中深藍色的交換機的output的端口就是在5,6的切換,時而還會出現不存在(個人是這認爲ox腳本的bug)說明了只有兩種切換方式,而另一種(連向4的)不通,說明了網絡運行的時候在s1的OUTPUT:4處出現了問題,這個待我日後分析lab_controller.py再說吧。

2.1在mininet文件夾裏面創建腳本文件rulemininet.py

#!/usr/bin/python
 
# coding:utf -8 
 
from mininet.topo import Topo
 
from mininet.net import Mininet
 
from mininet.node import CPULimitedHost
 
from mininet.link import TCLink
 
from mininet.util import dumpNodeConnections
 
from mininet.log import setLogLevel
 
from mininet.node import Controller 
 
from mininet.cli import CLI
 
from functools import partial
 
from mininet.node import RemoteController
 
import os
 
 
 # 創建一個基於拓撲類的MyTopo類使得多交換機連接多個主機和交換機的複雜拓撲
 
class MyTopo(Topo):
 
    "Single switch connected to n hosts."
    # 構造函數創建5個交換機和6個主機
 
    def __init__(self):
 
        Topo.__init__(self)
 
        s1=self.addSwitch('s1')
 
        s2=self.addSwitch('s2')
 
        s3=self.addSwitch('s3')
 
        s4=self.addSwitch('s4')
 
        s5=self.addSwitch('s5') 
 
        h1=self.addHost('h1')
 
        h2=self.addHost('h2')
 
        h3=self.addHost('h3')
 
        h4=self.addHost('h4')
 
        h5=self.addHost('h5')
 
        h6=self.addHost('h6')
 
        # 主機1,2,3連接s1
 
        self.addLink(h1, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)
 
        self.addLink(h2, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(h3, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)
 
        # 交換機2,3,4連接s1,所以說s1有6個接口

        self.addLink(s1, s2, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(s1, s3, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(s1, s4, bw=1, delay='10ms', loss=0, max_queue_size=1000,use_htb=True)

          # 交換機2,3,4連接s5,所以說s5也有6個接口,2,3,4各兩個
 
        self.addLink(s2, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(s3, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)  
 
        self.addLink(s4, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 

        # 主機4,5,6連接s5
 
        self.addLink(s5, h4, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(s5, h5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
        self.addLink(s5, h6, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
 
 
 
def perfTest():
 
    # 創建網絡並運行簡單性能測試
 
    topo = MyTopo()
 
 
    net = Mininet(topo=topo, host=CPULimitedHost, link=TCLink, controller=partial(RemoteController, ip='10.0.0.13', port=6633))
 
    net.start()
 
    print "Dumping host connections"
 
    dumpNodeConnections(net.hosts)
 
    h1,h2,h3=net.get('h1','h2','h3')
 
    h4,h5,h6=net.get('h4','h5','h6')
 
    h1.setMAC("0:0:0:0:0:1")
 
    h2.setMAC("0:0:0:0:0:2")
 
    h3.setMAC("0:0:0:0:0:3")
 
    h4.setMAC("0:0:0:0:0:4")
 
    h5.setMAC("0:0:0:0:0:5")
 
    h6.setMAC("0:0:0:0:0:6")
 
    CLI(net)
 
    net.stop()
 
 
 
if __name__ == '__main__':
 
    setLogLevel('info')
 
    perfTest()

2.2 先打開腳本文件lab_controller.py然後打開rulemininet.py ,分別用兩個程序

cd pox
./pox.py lab_controller
cd mininet
./rulemininet.py
h1 ping -i 0.1 h4

rulemininet.py腳本的顯示情況:

然而,pox理論上應當顯示的是:

基於Mininet使用POX動態改變轉發規則實驗 圖12

而我的是。。

所以這應當是pox的腳本問題,於是我才使用查看流表項的方式來分析。

總結:

1.學會了使用查看流表項

2.理解這個動態拓撲的原理

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章