Hi
I have designed a simple multipath topology, and its supporting ryu controller.
All of these codes are attached here.
topology: topo.py
controller Ryuryu02.py
operation note: Notes
________________ switch 3_____________
|
|
h1------switch 1
switch 4-------- h2
|_________________ switch 5____________|
Now after running "python topo.py", and then using "xterm h1 h2", I put mac
addresses in both switches,
in h1: sudo arp -s 10.0.0.2 20:00:00:00:20:20
in h2: sudo arp -s 10.0.0.1 10:00:00:00:10:10
after that I run the ryu controller < ryu-manager Ryuryu02.py
--ofp-tcp-listen-port 6653 > and then send the udp data packet flow using the
following command,
in h1: iperf -c 10.0.0.2 -u -p 5555 -b 10k -i 2 -t 2000
in h2: iperf -s -u -p 5555 -i 2 -t 2000
I found that the flow is not splitting, but it is passing through only one link.
(1) am I missing something ?
(2) How to do load balancing ?
from operator import attrgetter
from ryu.base import app_manager
from ryu.lib.pack_utils import msg_pack_into
from ryu import utils
from ryu.controller.handler import HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER, DEAD_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3, ether
from ryu.lib import hub
from ryu.topology import event
from ryu.lib.packet import packet, ethernet, arp, icmp, ipv4, ipv6
from ryu.lib.packet import ether_types
from ryu.topology.switches import LLDPPacket
from ryu.app.wsgi import ControllerBase, WSGIApplication, route
from webob import Response
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.lib import dpid as dpid_lib
import os
import time
class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
self.mac_to_port = {}
self.datapaths = {}
# variables to maintain the execution sequence of different EVENTS
self.ResetFlow = 0
self.PingFlow = False
self.FlowDel = False
# time to hold both the old rule and the new rule (2 sec). It is set once
self.present_time = 2*1000
# Set time in sec to start the main rule insertion/deletion function execution
self.monitor_thread = hub.spawn_after(1, self._monitor)
#....................................................... switch_in_handler ...................................................
# pro-active rules in Switches
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
dpid = datapath.id
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# send all flows: Switch --> Controller
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
self.logger.debug( "pro-active rules for cellular network" )
if datapath.id == 1:
self.group_mod01(datapath)
actions = [parser.OFPActionSetField(ip_dscp = 1), parser.OFPActionGroup(group_id = 1)]
priority = 100
match = parser.OFPMatch(in_port= 1, eth_type=0x0800, ipv4_src='10.0.0.1', ipv4_dst='10.0.0.2', ip_proto=17, udp_dst=5555 )
self.add_flow(datapath, priority , match, actions)
match = parser.OFPMatch(in_port= 2, eth_type=0x0800)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, priority, match, actions)
match = parser.OFPMatch(in_port= 4, eth_type=0x0800)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, priority, match, actions)
if datapath.id == 3:
priority = 100
match = parser.OFPMatch(in_port= 2, eth_type=0x0800, ipv4_src='10.0.0.1', ipv4_dst='10.0.0.2', ip_dscp = 1, ip_proto=17, udp_dst=5555)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, priority, match, actions)
match = parser.OFPMatch(in_port= 1, eth_type=0x0800)
actions = [parser.OFPActionOutput(2)]
self.add_flow(datapath, priority, match, actions)
if datapath.id == 4:
priority = 100
match = parser.OFPMatch(in_port= 2, eth_type=0x0800, ipv4_src='10.0.0.1', ipv4_dst='10.0.0.2', ip_dscp = 1, ip_proto=17, udp_dst=5555)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, priority, match, actions)
match = parser.OFPMatch(in_port= 4, eth_type=0x0800, ipv4_src='10.0.0.1', ipv4_dst='10.0.0.2', ip_dscp = 1, ip_proto=17, udp_dst=5555)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 22, match, actions)
self.group_mod02(datapath)
actions = [parser.OFPActionGroup(group_id = 1)]
priority = 100
match = parser.OFPMatch(in_port= 1, eth_type=0x0800)
self.add_flow(datapath, priority , match, actions)
if datapath.id == 5:
priority = 100
match = parser.OFPMatch(in_port= 1, eth_type=0x0800, ipv4_src='10.0.0.1', ipv4_dst='10.0.0.2', ip_dscp = 1, ip_proto=17, udp_dst=5555)
actions = [parser.OFPActionOutput(2)]
self.add_flow(datapath, priority, match, actions)
match = parser.OFPMatch(in_port= 2, eth_type=0x0800)
actions = [parser.OFPActionOutput(1)]
self.add_flow(datapath, priority, match, actions)
#.............................................................................................................................
#...........................................................add_flow..........................................................
def add_flow(self, datapath, priority, match, actions):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst)
datapath.send_msg(mod)
#.............................................................................................................................
#....................................................... send_group_mod .....................................................
# applicable in Swicth-1 (shared switch/AP)
def group_mod01(self, datapath):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
group_id = 1
action01 = [parser.OFPActionOutput(2)] # output port 2 of switch 1 for switch 3
action02 = [parser.OFPActionOutput(4)] # output port 4 for switch 1 for switch 5
weight01 = 50 # % of the total data packets of a flow
weight02 = 50 # % of the total data packets of a flow
watch_port = ofproto_v1_3.OFPP_ANY
watch_group = ofproto_v1_3.OFPQ_ALL
buckets = [parser.OFPBucket(weight01, watch_port, watch_group, action01), parser.OFPBucket(weight02, watch_port, watch_group, action02)]
req = parser.OFPGroupMod(datapath, ofproto.OFPFC_ADD, ofproto.OFPGT_SELECT, group_id, buckets)
datapath.send_msg(req)
def group_mod02(self, datapath):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
group_id = 2
action01 = [parser.OFPActionOutput(2)] # output port 2 of switch 1 for switch 3
action02 = [parser.OFPActionOutput(4)] # output port 4 for switch 1 for switch 5
weight01 = 50 # % of the total data packets of a flow
weight02 = 50 # % of the total data packets of a flow
watch_port = ofproto_v1_3.OFPP_ANY
watch_group = ofproto_v1_3.OFPQ_ALL
buckets = [parser.OFPBucket(weight01, watch_port, watch_group, action01), parser.OFPBucket(weight02, watch_port, watch_group, action02)]
req = parser.OFPGroupMod(datapath, ofproto.OFPFC_ADD, ofproto.OFPGT_SELECT, group_id, buckets)
datapath.send_msg(req)
#.............................................................................................................................
#....................................................... packet_in_handler ...................................................
# reactive rules in Switches
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
dpid = datapath.id
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
eth_pkt = pkt.get_protocol(ethernet.ethernet)
arp_pkt = pkt.get_protocol(arp.arp)
ip_pkt = pkt.get_protocol(ipv4.ipv4)
if self.ResetFlow == 0 and arp_pkt != None:
self.logger.debug("ARP processing in WiFi network")
if dpid == 1:
self.group_mod01(datapath)
action = [parser.OFPActionGroup(group_id = 1)]
match = parser.OFPMatch(in_port= 1, eth_type=0x0806)
self.add_flow(datapath, 1, match, action)
match = parser.OFPMatch(in_port= 2, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
match = parser.OFPMatch(in_port= 4, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
if dpid == 3:
match = parser.OFPMatch(in_port= 1, eth_type=0x0806)
action = [parser.OFPActionOutput(2)]
self.add_flow(datapath, 1, match, action)
match = parser.OFPMatch(in_port= 2, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
if dpid == 4:
match = parser.OFPMatch(in_port= 4, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
match = parser.OFPMatch(in_port= 2, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
self.group_mod02(datapath)
action = [parser.OFPActionGroup(group_id = 2)]
match = parser.OFPMatch(in_port= 1, eth_type=0x0806)
self.add_flow(datapath, 1, match, action)
if dpid == 5:
match = parser.OFPMatch(in_port= 1, eth_type=0x0806)
action = [parser.OFPActionOutput(2)]
self.add_flow(datapath, 1, match, action)
match = parser.OFPMatch(in_port= 2, eth_type=0x0806)
action = [parser.OFPActionOutput(1)]
self.add_flow(datapath, 1, match, action)
#.............................................................................................................................
#....................................................... Flow status request/response ........................................
def request_stats(self, datapath):
dpid = datapath.id
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
if self.ResetFlow == 1 and dpid == 4:
req = parser.OFPFlowStatsRequest(datapath)
datapath.send_msg(req)
@set_ev_cls(ofp_event.EventOFPFlowStatsReply, [MAIN_DISPATCHER, CONFIG_DISPATCHER])
def _flow_stats_reply_handler(self, ev):
body = ev.msg.body
datapath = ev.msg.datapath
dpid = datapath.id
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
flow = []
print "\n\n"
self.logger.debug('datapath IP-DSCP '
' IP4-src IP4-dst '
'out-port packets bytes priority duration(s) duration(ns)')
self.logger.debug('---------------- -------- '
'----------------- ----------------- '
'-------- -------- -------- -------- ----------------- ----------------- ')
for stat in sorted([flow for flow in body if flow.priority == 11], key=lambda flow: (flow.match['ipv4_src'], flow.match['ipv4_dst'], flow.match['ip_dscp'])):
self.logger.debug('%016x %8x %17s %17s %8x %8d %8d %8d %17d %17d',
ev.msg.datapath.id, stat.match['ip_dscp'],
stat.match['ipv4_src'], stat.match['ipv4_dst'],
stat.instructions[0].actions[0].port,
stat.packet_count, stat.byte_count, stat.priority, stat.duration_sec, stat.duration_nsec)
if (stat.packet_count > 0) :
self.PingFlow = True
self.logger.info("number of pkt: %s PingFlow: %s ", stat.packet_count, self.PingFlow)
print "\n"
self.logger.info('datapath IP-DSCP '
' IP4-src IP4-dst '
'out-port packets bytes priority duration(s) duration(ns)')
self.logger.info('---------------- -------- '
'----------------- ----------------- '
'-------- -------- -------- -------- ----------------- ----------------- ')
for stat in sorted([flow for flow in body if flow.priority == 22], key=lambda flow: (flow.match['ipv4_src'], flow.match['ipv4_dst'], flow.match['ip_dscp'])):
self.logger.info('%016x %8x %17s %17s %8x %8d %8d %8d %17d %17d',
ev.msg.datapath.id, stat.match['ip_dscp'],
stat.match['ipv4_src'], stat.match['ipv4_dst'],
stat.instructions[0].actions[0].port,
stat.packet_count, stat.byte_count, stat.priority, stat.duration_sec, stat.duration_nsec)
if (stat.packet_count > 0) :
self.PingFlow = False
self.FlowDel = True
self.logger.info("number of pkt: %s ResetFlow: %s PingFlow: %s ", stat.packet_count, self.ResetFlow, self.PingFlow)
#.....................................................................................................................................
#....................................................... Cycelic Network Control .....................................................
@set_ev_cls(ofp_event.EventOFPStateChange, [MAIN_DISPATCHER, DEAD_DISPATCHER])
def _state_change_handler(self, ev):
datapath = ev.datapath
if ev.state == MAIN_DISPATCHER:
if not datapath.id in self.datapaths:
self.logger.debug('register datapath: %016x', datapath.id)
self.datapaths[datapath.id] = datapath
elif ev.state == DEAD_DISPATCHER:
if datapath.id in self.datapaths:
self.logger.debug('deregister datapath: %016x', datapath.id)
del self.datapaths[datapath.id]
def _monitor(self):
while True:
for datapath in self.datapaths.values():
self.request_stats(datapath)
hub.sleep(2)
if self.ResetFlow == 0:
pres_time = ( time.time() * 1000 )
self.logger.debug( "Data pkt flow through Cellular network" )
self.logger.debug("present time: %s millisec", pres_time)
# self.logger.info("Do you want to change the network? [y/n]")
# Result1 = raw_input(": ")
# if (Result1 == 'y'):
# self.ResetFlow = 1
# pres_time = ( time.time() * 1000 )
# self.logger.info( "Trigger time: %s millisec", pres_time )
# else:
# print "Skip..............."
elif self.ResetFlow == 1:
pres_time = ( time.time() * 1000 )
self.logger.debug( "Action Start: Data pkt flow through WiFi network" )
self.logger.debug("present time: %s millisec", pres_time)
#.............................................................................................................................
from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSKernelSwitch, IVSSwitch, UserSwitch, Ryu, OVSSwitch
from mininet.link import Link, TCLink, Intf
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from subprocess import call
from mininet.node import CPULimitedHost, Host, Node
from mininet.util import dumpNodeConnections
def topology():
"Create a network."
net = Mininet(controller=RemoteController, link=TCLink, switch=OVSKernelSwitch)
info( '*** Adding controller\n' )
c0=net.addController(name='c0', controller=RemoteController, ip='127.0.0.1',port=6653)
info( '*** Adding switches\n' )
s1 = net.addSwitch( 's1', cls=OVSKernelSwitch, dpid='1', protocols='OpenFlow13', mac='00:00:00:00:00:01')
s2 = net.addSwitch( 's2', cls=OVSKernelSwitch, dpid='2', protocols='OpenFlow13', mac='00:00:00:00:00:02')
s3 = net.addSwitch( 's3', cls=OVSKernelSwitch, dpid='3', protocols='OpenFlow13', mac='00:00:00:00:00:03')
s4 = net.addSwitch( 's4', cls=OVSKernelSwitch, dpid='4', protocols='OpenFlow13', mac='00:00:00:00:00:04')
s5 = net.addSwitch( 's5', cls=OVSKernelSwitch, dpid='5', protocols='OpenFlow13', mac='00:00:00:00:00:05')
info( '*** Add hosts\n')
h1 = net.addHost('h1', cls=Host, mac='10:00:00:00:10:10', ip='10.0.0.1/8')
h2 = net.addHost('h2', cls=Host, mac='20:00:00:00:20:20', ip='10.0.0.2/8')
info( '*** Add links\n')
net.addLink(h1, s1, port1=0, port2=1, cls=TCLink)
net.addLink(s1, s2, port1=3, port2=2, cls=TCLink)
net.addLink(s1, s3, port1=2, port2=2, cls=TCLink)
net.addLink(s1, s5, port1=4, port2=1, cls=TCLink)
net.addLink(s3, s4, port1=1, port2=2, cls=TCLink)
net.addLink(s2, s4, port1=1, port2=3, cls=TCLink)
net.addLink(s4, s5, port1=4, port2=2, cls=TCLink)
net.addLink(s4, h2, port1=1, port2=0, cls=TCLink)
net.build()
info( '*** Starting controllers\n')
c0.start()
info( '*** Starting switches\n')
s1.start( [c0] )
s2.start( [c0] )
s3.start( [c0] )
s4.start( [c0] )
s5.start( [c0] )
print "*** Running CLI"
CLI( net )
print "*** Stopping network"
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
topology()
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel