用于迷你网的循环 Ryu 控制器

问题描述 投票:0回答:1

Fat tree topology

我已经成功地在 mininet 中生成了拓扑,但我正在努力创建一个在所有可用链路上使用循环负载平衡来发送数据包的控制器。

这是我的拓扑文件:

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.log import setLogLevel
from mininet.cli import CLI
from mininet.node import RemoteController

class MyTopo(Topo):
    def __init__(self):
        super(MyTopo, self).__init__()

        switches = []
        for i in range(1, 20 + 1):
            switch = self.addSwitch('s{}'.format(i))
            switches.append(switch)

        hosts = []
        for i in range(1, 16 + 1):
            host = self.addHost('h{}'.format(i))
            hosts.append(host)

        # Connect the first 8 switches to the first 16 hosts
        for i, switch in enumerate(switches[:8]):
            self.addLink(switch, hosts[i * 2])
            self.addLink(switch, hosts[i * 2 + 1])

        # Connect switches 9-16 to switches 1-8
        for i in range(4):
            for j in range(2):
                self.addLink(switches[i * 2 + j], switches[i * 2 + 8])
                self.addLink(switches[i * 2 + j], switches[i * 2 + 9])

        # Connect switches 17-20 to switches 9-16
        for i in range(2):
            for j in range(4):
                self.addLink(switches[16 + i], switches[2 * j + 8])
            for j in range(4):
                self.addLink(switches[18 + i], switches[2 * j + 9])

def main():
    setLogLevel('info')

    topo = MyTopo()
    net = Mininet(topo=topo, controller=RemoteController) 

    net.start()

    CLI(net)

    net.stop()

if __name__ == '__main__':
    main()

尝试编辑预先存在的 SimpleSwitch13,但这可能是令人厌恶的:

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.lib.packet import ether_types

class SimpleSwitch13RR(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SimpleSwitch13RR, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
        self.port_round_robin = {}

    @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
        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 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]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP or eth.ethertype == ether_types.ETH_TYPE_IPV6:
            return
        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)

        # Round Robin logic
        available_ports = [port.port_no for port in datapath.ports.values() 
                           if port.port_no not in [ofproto.OFPP_LOCAL, ofproto.OFPP_CONTROLLER]]

        if (src, dst) not in self.port_round_robin:
            self.port_round_robin[(src, dst)] = iter(available_ports)

        try:
            out_port = next(self.port_round_robin[(src, dst)])
        except StopIteration:
            self.port_round_robin[(src, dst)] = iter(available_ports)
            out_port = next(self.port_round_robin[(src, dst)])

        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, eth_src=src)
            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)
python networking mininet topology ryu
1个回答
-1
投票

我也遇到了同样的问题,你找到解决办法了吗?

© www.soinside.com 2019 - 2024. All rights reserved.