Hi All,

I am using mininet and ryu to do some research work. Unfortunately, it seems the link down events are not stable in the RYU source code.  I have simply added the following block to simple_switch_13 to see the link down events. 

    @set_ev_cls(event.EventLinkDelete, MAIN_DISPATCHER)
    def linkDeleteHandler(self, ev):
        link_list = get_link(self.topology_api_app, None)        
        self.logger.info("New Link Delete %s", ev.link)
        for link in link_list:
            self.logger.info("\tCurrent links After Deletion %s", link)

I am receiving numerous link down events for the links that exist while the topology is the same before and after such events. To reproduce this issue, please do the following:

1) sudo mn --topo linear,3 --mac --controller remote --switch ovsk
2) sudo ovs-vsctl set bridge s1 protocols=OpenFlow13
3) sudo ovs-vsctl set bridge s2 protocols=OpenFlow13
4) sudo ovs-vsctl set bridge s3 protocols=OpenFlow13
5) ryu-manager --observe-links   simple_switch-bug.py (attached)

You can see the following block continuously in the output. You have received a link down events
for the link that exist in the self.topology_api_app.

New Link Delete Link: Port<dpid=3, port_no=2, LIVE> to Port<dpid=2, port_no=3, LIVE>
Current links After Deletion Link: Port<dpid=2, port_no=3, LIVE> to Port<dpid=3, port_no=2, LIVE>
Current links After Deletion Link: Port<dpid=3, port_no=2, LIVE> to Port<dpid=2, port_no=3, LIVE>
Current links After Deletion Link: Port<dpid=3, port_no=2, LIVE> to Port<dpid=1, port_no=2, LIVE>
Current links After Deletion Link: Port<dpid=2, port_no=2, LIVE> to Port<dpid=1, port_no=2, LIVE>
Current links After Deletion Link: Port<dpid=1, port_no=2, LIVE> to Port<dpid=3, port_no=2, LIVE>
Current links After Deletion Link: Port<dpid=1, port_no=2, LIVE> to Port<dpid=2, port_no=2, LIVE>
# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
#
# 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.

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.packet import packet
from ryu.lib.packet import ethernet
from ryu.topology import switches, event
from ryu.topology.api import  get_switch, get_link

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.topology_api_app = self

    @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.  The bug has been fixed in OVS v2.1.0.
        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, buffer_id=None):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
                                    priority=priority, match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
                                    match=match, instructions=inst)
        datapath.send_msg(mod)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        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
        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)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                self.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                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(event.EventLinkDelete, MAIN_DISPATCHER)
    def linkDeleteHandler(self, ev):
        link_list = get_link(self.topology_api_app, None)        
        self.logger.info("New Link Delete %s", ev.link)
        
        for link in link_list:
            self.logger.info("\tCurrent links After Deletion %s", link)
        
    
    
    
Best Regards
—Mehrdad

------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to