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.理解这个动态拓扑的原理

 

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