Hi,
I am adding MPLS flow in a switch using RYU controller. I can add the flow
in switches when topology is linear but when topology is loop structure I
cannot add flow. I have problem with adding flows. the scenario is as
follows:
1. I calculated the link.
2. based on souce and destination address i calculated the shortest path eg
x=[1,2,3,5]
3. but when I try to add the flow I can't reach to final point ie till
swicth id=5.
I don't understand what the problem behind it.
I hereby enclosed my scripts.
I hope I will get good sugestion from all of you.
Thank you
--
Best regards
Sujit Pandey
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib import dpid as dpid_lib
from ryu.lib import stplib
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
_CONTEXTS = {'stplib': stplib.Stp,
}
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
self.mac_to_port = {}
self.stp = kwargs['stplib']
# Sample of stplib config.
# please refer to stplib.Stp.set_config() for details.
config = {dpid_lib.str_to_dpid('0000000000000001'):
{'bridge': {'priority': 0x8000}},
dpid_lib.str_to_dpid('0000000000000002'):
{'bridge': {'priority': 0x9000}},
dpid_lib.str_to_dpid('0000000000000003'):
{'bridge': {'priority': 0xa000}},
dpid_lib.str_to_dpid('0000000000000004'):
{'bridge': {'priority': 0xb000}},
dpid_lib.str_to_dpid('0000000000000005'):
{'bridge': {'priority': 0xc000}},
dpid_lib.str_to_dpid('0000000000000006'):
{'bridge': {'priority': 0xd000}},
dpid_lib.str_to_dpid('0000000000000007'):
{'bridge': {'priority': 0xe000}}}
self.stp.set_config(config)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
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)
def delete_flow(self, datapath):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
for dst in self.mac_to_port[datapath.id].keys():
match = parser.OFPMatch(eth_dst=dst)
mod = parser.OFPFlowMod(datapath, command=ofproto.OFPFC_DELETE,out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY,priority=1, match=match)
datapath.send_msg(mod)
@set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)[0]
dst = eth.dst
src = eth.src
dpid = datapath.id
print "hello i am dpid from stp class",dpid
self.mac_to_port.setdefault(dpid, {})
#self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# learn a mac address to avoid FLOOD next time.
self.mac_to_port[dpid][src] = in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
actions = [parser.OFPActionOutput(out_port)]
# install a flow to avoid packet_in next time
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
self.add_flow(datapath, 1, match, actions)
data = None
if msg.buffer_id == ofproto.OFP_NO_BUFFER:
data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,in_port=in_port, actions=actions, data=data)
datapath.send_msg(out)
@set_ev_cls(stplib.EventTopologyChange, MAIN_DISPATCHER)
def _topology_change_handler(self, ev):
dp = ev.dp
dpid_str = dpid_lib.dpid_to_str(dp.id)
msg = 'Receive topology change event. Flush MAC table.'
self.logger.debug("[dpid=%s] %s", dpid_str, msg)
if dp.id in self.mac_to_port:
self.delete_flow(dp)
del self.mac_to_port[dp.id]
@set_ev_cls(stplib.EventPortStateChange, MAIN_DISPATCHER)
def _port_state_change_handler(self, ev):
dpid_str = dpid_lib.dpid_to_str(ev.dp.id)
of_state = {stplib.PORT_STATE_DISABLE: 'DISABLE',
stplib.PORT_STATE_BLOCK: 'BLOCK',
stplib.PORT_STATE_LISTEN: 'LISTEN',
stplib.PORT_STATE_LEARN: 'LEARN',
stplib.PORT_STATE_FORWARD: 'FORWARD'}
self.logger.debug("[dpid=%s][port=%d] state=%s",dpid_str, ev.port_no, of_state[ev.port_state])
#!/usr/bin/env python
#
# Copyright 2013 cloudysunny14.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import struct, socket
import networkx as nx
import matplotlib.pyplot as plt
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.controller import dpset
from ryu.topology import event
from ryu.controller import ofp_event
from ryu.ofproto import ofproto_v1_3_parser
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.topology import api
from ryu.controller import handler
from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import HANDSHAKE_DISPATCHER
import array
from ryu.lib.packet import packet, ethernet, arp, ipv4
from ryu import utils
import csv
from ryu.lib import stplib
import simple_switch13_stp
from ryu.lib.mac import haddr_to_str
from ryu.lib import addrconv
from ryu.ofproto import ether
LOG = logging.getLogger(__name__)
class SwitchEventHandler(SimpleSwitch13.SimpleSwitch13):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
_CONTEXTS={ 'dpset': dpset.DPSet,
'stplib': stplib.Stp,
}
list={'00:00:00:00:00:01':1,'00:00:00:00:00:02':2,'00:00:00:00:00:03':3,'00:00:00:00:00:04':4,'00:00:00:00:00:00:05':5,'00:00:00:00:00:06':6}
switch_list={'10.0.0.1':1,'10.0.0.2':2,'10.0.0.3':3,'10.0.0.4':4,'10.0.0.5':5,'10.0.0.6':6,'10.0.0.7':7}
port_list={'10.0.0.1':1,'10.0.0.2':1,'10.0.0.3':1,'10.0.0.4':1,'10.0.0.5':1,'10.0.0.6':1,'10.0.0.7':1}
push_label={1:100,2:200,3:300,4:400,5:500,6:600}
s1 = {2: 200, 3: 300}
s2 = {1: 100, 3: 300}
s3 = {1: 100, 4: 400, 2:200}
s4 = {3: 300, 5: 500}
s5 = {6: 600, 7:700, 4:400}
s6 = {5: 500, 7:700}
s7 = {5: 500, 6:600}
pop_label={1:100,2:200,3:300,4:400,6:600}
temp2 = {1:s1, 2:s2, 3:s3, 4:s4, 5:s5, 6:s6, 7:s7}
def __init__(self, *args, **kwargs):
super(SwitchEventHandler, self).__init__(*args, **kwargs)
self.mac_to_port = {}
self.dpset = kwargs['dpset']
self.stp = kwargs['stplib']
self.link_list = []
self.s=[]
self.edges=[]
self.topo=nx.Graph()
self.path=[]
self.x=None
self.y=None
self.z=None
#self.f = open('link1.txt', 'wr')
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# install table-miss flow entry
#
# We specify NO BUFFER to max_len of the output action due to
# OVS bug. At this moment, if we specify a lesser number, e.g.,
# 128, OVS will send Packet-In with invalid buffer_id and
# truncated packet data. In that case, we cannot output packets
# correctly.
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
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)
def add_flow2(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
pkt = packet.Packet(array.array('B', ev.msg.data))
eth = pkt.get_protocols(ethernet.ethernet)[0]
eth_pkt = pkt.get_protocol(ethernet.ethernet)
dst = eth.dst
src = eth.src
dpid = datapath.id
#print "this is call"
self.mac_to_port.setdefault(dpid, {})
#self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# learn a mac address to avoid FLOOD next time.
self.mac_to_port[dpid][src] = in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
#print out_port
actions = [parser.OFPActionOutput(out_port)]
data = None
if msg.buffer_id == ofproto.OFP_NO_BUFFER:
data = msg.data
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
in_port=in_port, actions=actions)
datapath.send_msg(out)
@set_ev_cls(ofp_event.EventOFPErrorMsg, [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
def error_msg_handler(self, ev):
msg = ev.msg
self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x ''message=%s',msg.type, msg.code, utils.hex_array(msg.data))
@handler.set_ev_cls(event.EventLinkAdd)
def link_add_handler(self, ev):
self.link_list.append(ev.link)
#path_list=PathList(self.link_list)
#self.x=path_list.createWholePath(1,3)
#print self.x
src = ev.link.src
dst = ev.link.dst
self.topo.add_edge(src.dpid,dst.dpid)
self.topo[src.dpid][dst.dpid][src.dpid] = src.port_no
self.topo[src.dpid][dst.dpid][dst.dpid] = dst.port_no
#y=self.topo[src.dpid][dst.dpid][src.dpid]
#print "hello"
#print y
self.topo[src.dpid][dst.dpid][dst.dpid] = dst.port_no
"""self.s.append((ev.link.src.dpid,ev.link.src.port_no,ev.link.dst.dpid,ev.link.dst.port_no))
if len(self.s)>=3:
for i in range(len(self.s)):
for j in range(len(self.s)-1):
if self.s[i][0]==self.s[j+1][2] and self.s[i][1]==self.s[j+1][3]:
#b.append(self.link_list[i])
self.s[i]=self.s[j+1]
#print "heheheheheheh"
self.link_list=list(set(self.s))
print self.link_list"""
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
dpid = datapath.id
in_port = msg.match['in_port']
#print in_port
#pkt = packet.Packet(array.array('B', ev.msg.data))
#hwtype, proto, hlen, plen, opcode, src_mac, src_ip, dst_mac, dst_ip=struct.unpack_from('!HHBBH6s4s6s4s', buffer(msg.data), 0)
#eth = pkt.get_protocols(ethernet.ethernet)[0]
#print eth
#ip4_pkt = pkt.get_protocol(ipv4.ipv4)
#print ip4_pkt
pkt = packet.Packet(array.array('B', ev.msg.data))
for p in pkt.protocols:
if p.protocol_name == 'arp':
#print p
#dst_ip = str(self.numToDottedQuad(p.dst_ip))
#src_ip = str(self.numToDottedQuad(p.src_ip))
dst_ip=str(p.dst_ip)
src_ip=str(p.src_ip)
self.add_flow2(ev)
if p.protocol_name=='ipv4':
src=str(p.src)
dst=str(p.dst)
print dpid
self.path=self.select_route(self.switch_list.get(src),self.switch_list.get(dst))
self.define_flow(ev,self.path,src,dst,dpid)
def select_route(self,src,dst):
#print self.topo[src][dst][src]
return nx.shortest_path(self.topo,src,dst)
def define_flow(self,ev,path,src,dst,dpid):
print path
length=len(path)
#print "hi in length",length
for i in range(len(path)):
print "hello I am I",i
if i==0:
print "hi i am in in 0",i
self.push_mpls_flow(ev,src,path[i],path[i+1],i,dpid)
self.pop_mpls_flow(ev,src,path[i],path[i+1],i,dpid)
if i==len(path)-1:
print "hi i am in in last",i
self.push_mpls_flow(ev,dst,path[i],path[i-1],i,dpid)
self.pop_mpls_flow(ev,dst,path[i],path[i-1],i,dpid)
if i!=0 and i!=len(path)-1:
print "hi i am in in swap",i
self.swap_label(ev,path[i-1],path[i],path[i+1],i,dpid)
def push_mpls_flow(self,ev,src,dst,path,i,dpid):
if dpid!=dst:
return
#print "hello im in push",i
#self.port_list.get(src),
msg = ev.msg
#print msg
dp = msg.datapath
in_port=self.port_list.get(src)
if path !=0:
out_port= self.topo[self.switch_list.get(src)][path][self.switch_list.get(src)]
else:
out_port=self.topo[self.switch_list.get(src)][self.switch_list.get(dst)][self.switch_list.get(src)]
s_label = self.temp2[dst][path]
eth_IP = ether.ETH_TYPE_IP
eth_MPLS = ether.ETH_TYPE_MPLS
match = dp.ofproto_parser.OFPMatch()
match.set_in_port(in_port)
match.set_dl_type(eth_IP)
f = dp.ofproto_parser.OFPMatchField.make(dp.ofproto.OXM_OF_MPLS_LABEL, s_label)
actions = [dp.ofproto_parser.OFPActionPushMpls(eth_MPLS),dp.ofproto_parser.OFPActionSetField(f), dp.ofproto_parser.OFPActionOutput(out_port, 0)]
self._add_flow(dp, match, actions)
def pop_mpls_flow(self,ev,src,dst,path,i,dpid):
if dpid!=dst:
return
#print "hello i am in pop",i
msg= ev.msg
#print msg
dp = msg.datapath
ev.msg.datapath.id=dst
in_port=self.port_list.get(src)
if path!=0:
out_port=self.topo[self.switch_list.get(src)][path][self.switch_list.get(src)]
else:
out_port=self.topo[self.switch_list.get(src)][self.switch_list.get(dst)][self.switch_list.get(src)]
eth_IP = ether.ETH_TYPE_IP
eth_MPLS = ether.ETH_TYPE_MPLS
m_label=self.pop_label[dst]
#print "heloooooooooooooooo"
match = dp.ofproto_parser.OFPMatch()
match.set_in_port(out_port)
match.set_dl_type(eth_MPLS)
match.set_mpls_label(m_label)
actions = [dp.ofproto_parser.OFPActionPopMpls(eth_IP),dp.ofproto_parser.OFPActionOutput(in_port, 0)]
self._add_flow(dp, match, actions)
def swap_label(self,ev,src,dst,path,i,dpid):
if dpid!=dst:
return
#print "hello i am in swap",i
msg= ev.msg
dp = msg.datapath
eth_IP = ether.ETH_TYPE_IP
eth_MPLS = ether.ETH_TYPE_MPLS
in_port=self.topo[dst][path][path]
#print in_port
out_port=self.topo[dst][path][dst]
#print out_port
#s_label = self.temp2[dst][path]
s_label = 1000
match = dp.ofproto_parser.OFPMatch()
match.set_in_port(in_port)
match.set_dl_type(eth_MPLS)
f = dp.ofproto_parser.OFPMatchField.make(dp.ofproto.OXM_OF_MPLS_LABEL, s_label)
actions = [dp.ofproto_parser.OFPActionSetField(f),dp.ofproto_parser.OFPActionOutput(out_port, 0)]
self._add_flow(dp, match, actions)
#m_label = self.temp2[dst][src]
m_label = 2000
match = dp.ofproto_parser.OFPMatch()
match.set_in_port(out_port)
match.set_dl_type(eth_MPLS)
f = dp.ofproto_parser.OFPMatchField.make(dp.ofproto.OXM_OF_MPLS_LABEL, m_label)
actions = [dp.ofproto_parser.OFPActionSetField(f),dp.ofproto_parser.OFPActionOutput(in_port, 0)]
self._add_flow(dp, match, actions)
def _add_flow(self, dp, match, actions):
inst = [dp.ofproto_parser.OFPInstructionActions(dp.ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = dp.ofproto_parser.OFPFlowMod(dp, cookie=0, cookie_mask=0, table_id=0,command=dp.ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,priority=0xff, buffer_id=0xffffffff,
out_port=dp.ofproto.OFPP_ANY, out_group=dp.ofproto.OFPG_ANY,flags=0, match=match, instructions=inst)
dp.send_msg(mod)
#!/usr/bin/python
from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSKernelSwitch, OVSLegacyKernelSwitch, UserSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel
from mininet.link import Link, TCLink
def topology():
"Create a network."
net = Mininet( controller=RemoteController, link=TCLink, switch=OVSKernelSwitch )
print "*** Creating nodes"
s1 = net.addSwitch( 's1' )
s2 = net.addSwitch( 's2' )
s3 = net.addSwitch( 's3' )
s4 = net.addSwitch( 's4' )
s5 = net.addSwitch( 's5' )
s6 = net.addSwitch( 's6' )
s7 = net.addSwitch( 's7' )
c0 = net.addController( 'c0', controller=RemoteController )
h1 = net.addHost( 'h1' )
h2 = net.addHost( 'h2' )
h6 = net.addHost( 'h6' ,ip='10.0.0.6')
print "*** Creating links"
net.addLink(s1, s2,2,1)
net.addLink(s2, s3,2,1)
net.addLink(s2, s4,3,1)
net.addLink(s2, s6,4,3)
net.addLink(s3, s4,2,2)
net.addLink(s4, s5,3,1)
net.addLink(s5, s6,2,2)
net.addLink(s5,s7,3,2)
net.addLink(s6, s7,3,2)
net.addLink(h1, s1,0,1)
net.addLink(h2, s2,0,1)
net.addLink(h6, s6,0,1)
net.build()
print "*** Starting network"
net.start()
s1.start( [c0] )
s2.start( [c0] )
s3.start( [c0] )
s4.start( [c0] )
s5.start( [c0] )
s6.start( [c0] )
c0.start()
print "*** Running CLI"
CLI( net )
print "*** Stopping network"
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
topology()
------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel