Search code examples
mininetsdnryu

Mininet pingall fails when there is loop in topo


I am using Ryu as my SDN controller to control a topo that has a loop.

I am using a learning switch technique to route packets. My main functions/handlers are:

@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
    msg = ev.msg
    self.logger.info('OFPSwitchFeatures received: '
                     '\n\tdatapath_id=0x%016x n_buffers=%d '
                     '\n\tn_tables=%d auxiliary_id=%d '
                     '\n\tcapabilities=0x%08x',
                     msg.datapath_id, msg.n_buffers, msg.n_tables,
                     msg.auxiliary_id, msg.capabilities)

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

"""
This is called when Ryu receives an OpenFlow packet_in message. The trick is set_ev_cls decorator. This decorator
tells Ryu when the decorated function should be called.
"""
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
    #print(self.mac_to_port)
    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("\tpacket 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)

I need to have loop in my topo. Does any one know how to properly configure the topo/controller so that loops are pingable?

My full controller code: https://github.com/Ehsan70/RyuApps/blob/master/topo_learner.py My topo code: https://github.com/Ehsan70/RyuApps/blob/master/Pkt_Topo_with_loop.py


Solution

  • Ok so after some digging, apparently, ideal networks should not have loops. But in real world design they do. So to cope with that and kinda break the loop, Spanning Tree Algorithm is used. The algorithm finds out the minimum set of edges where you can reach every node.

    See this link for info on how to use Ryu's STP. Also clone this repo for some tutorials and sample code.