Mininet experiment dynamically changing forwarding rules experiment

write in front


Reference for this experiment

  • The POX script sets the forwarding policy of the controller, so just understand the script.
  • The mininet script sets up the topology and related information, so just understand the script.
  • The POX script is basically incomprehensible at present.
  • This experiment I learned: POX controller web interface, the first time I really saw the flow table item.

Experimental topology


image

  • In this environment, assuming H1 pings H4, the initial routing rule is S1-S2-S5, after one second, the routing forwarding rule becomes S1-S3-S5, and after another second, the rule becomes S1-S4-S5, Then go back to the original forwarding rules S1-S2-S5. Dynamically change the forwarding rules of the switch through this example of round-robin scheduling.

Experimental procedure


1. Build the environment

  • A virtual machine with mininet installed.
  • A virtual machine with pox installed.

2. Create a script

  • Create a new file lab_controller.py in the /pox directory and edit its content:
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)
  • This script implements a dynamic forwarding strategy.
  • I guess the basic idea should be to issue flow entries to switch s1 based on time.
  • Create the file mymininet.py in Mininet. Edit it to read:
#!/usr/bin/python

 

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

 

 

class MyTopo(Topo):

    "Single switch connected to n hosts."

    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')

         

        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)

        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) 

        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) 

        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():

    "Create network and run simple performance test"

    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()
  • The script sets up the topology. Basically understandable.

3. Run the script

  • Run the script lab_controller.py in the /pox directory
./pox.py lab_controller
  • Run the script mymininet.py under Mininet
chmod +x mymininet.py
./mymininet.py
  • mininet terminal information

  • POX Controller Terminal Information

  • Now we send packets to h4 through h1 to detect the dynamic forwarding function.
  • Type in the mininet terminal:
h1 ping -i 0.1 h4 #h1每秒向h4发10个包

  • At this time, there is no useful information on the POX interface, but some warning information.

4. Solutions

  • Since I couldn't see the sent details in the terminal, I thought of the web interface. Other controllers have UI interface POX should also have it?
  • I found the implementation of the POX UI interface in a blog: Poxdesk.

Reference blog

  • If you want to use poxdesk when running the POX script, you must add some more parameters. For this experiment, when running lab_controller.py, the command is as follows:
./pox.py lab_controller web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk
  • General order:
./pox.py 要运行的脚本 web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk
  • Enter: http://pox-ip:8000/poxdesk in the browser to access the interface, where pox-ip is the local IP address.
  • After entering the web interface, we open the flowtable window of s1. It can be found that the flow table entry whose destination is 10.0.0.4 (host h4) changes periodically, and the output port switches between 5 and 6 in the action. But without 4 (switch s2), the problem is not solved, it may be a problem with the script itself.

5. Specific connection diagram

  • The detailed information of the topology can be obtained through the net command in mininet. I simply drew a schematic diagram for easy understanding:

There is a problem


  • Why can't I switch to s2 when the port is switched?

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325343669&siteId=291194637