abds

mc.py

from ryu.base import app_manager
from ryu.controller import ofp_event
#from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.controller.handler import 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 import hub
from ryu.lib.dpid import dpid_to_str
from ryu.lib.dpid import str_to_dpid
from ryu.topology import event
from kazoo.client import KazooClient
import abc
import json
from kazoo.recipe.watchers import DataWatch
from ryu.ofproto.ofproto_v1_3 import OFPCR_ROLE_EQUAL
from ryu.ofproto.ofproto_v1_3 import OFPCR_ROLE_MASTER
from ryu.ofproto.ofproto_v1_3 import OFPCR_ROLE_SLAVE
from uuid import uuid4
import random
from slldp import slldp
from slldp import SLLDP_MAC_DST
from slldp import SLLDP_MAC_SRC
from slldp import ETH_TYPE_SLLDP
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.zkConf = {'root':'/multicontroller', 'topo':'/topology',
                       'swtat':'/swtat', 'counter': '/counter'}
        self.zk = KazooClient('127.0.0.1:2181')
        self.zk.start()
        self.ip = '202.201.3.51'#本控制器的IP地址
        self.sws = {}
        self.gid = random.randint(0, 10000)
        self.dps = {}
        self.links = []
        self.interval = 5
        self.role = OFPCR_ROLE_EQUAL
        self.topoThread = hub.spawn(self._topoThread)
        self.linkThread = hub.spawn(self._linkDiscover)
        self.clearLinkThread = hub.spawn(self._cleanLinks)
        self.clearLinkThread = hub.spawn(self._cleanSwitches)

    def _cleanSwitches(self):
        while  True:
            self.sws = {k:self.sws[k] for k in self.sws if self.sws[k]}
            hub.sleep(self.interval)

    def _topoThread(self):
        linkNode = self.zkConf['root'] + self.zkConf['topo'] + self.ip
        if self.zk.exists(linkNode):
            self.zk.set(linkNode, json.dumps(self.links))
        else:
            self.zk.create(linkNode, json.dumps(self.links))
        hub.sleep(self.interval)

    def _linkDiscover(self):
        while True:
            for dpid in self.dps:
                self.sendSlldp(dpid)
            hub.sleep(self.interval)

    def sendSlldp(self, dpid):
        dp = self.dps.get(dpid)
        if dp is None:
            return
        actions = [dp.ofproto_parser.OFPActionOutput(dp.ofproto.OFPP_FLOOD)]
        pkt = packet.Packet()
        pkt.add_protocol(ethernet.ethernet(ethertype=ETH_TYPE_SLLDP,
                        dst=SLLDP_MAC_DST, src=SLLDP_MAC_SRC))
        pkt.add_protocol(slldp(dp.id))
        pkt.serialize()
        slldpPacket = pkt.data
        out = dp.ofproto_parser.OFPPacketOut(
            datapath=dp, in_port=dp.ofproto.OFPP_CONTROLLER,
            buffer_id=dp.ofproto.OFP_NO_BUFFER, actions=actions,
            data=slldpPacket)
        dp.send_msg(out)

    def getLinks(self):
        topoNode = self.zkConf['root'] + self.zkConf['topo']
        ips = self.zk.get_children(topoNode)
        res = []
        for ip in ips:
            links = self.zk.get(topoNode + ip)[0]
            for link in links:
                res.append(link)
        return res

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):

        msg = ev.msg
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]
        dst = eth.dst

        # SLLDP packet
        if dst == SLLDP_MAC_DST:
            self.handleSlldp(ev)
            return
        # process packet_in message in subclass
        self.packet_in_process(ev)

    def handleSlldp(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        dpid = datapath.id
        inPort = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        slldpBuff = pkt.get_protocols(ethernet.ethernet)[2]
        dpidSrc, _ = slldp.parser(slldpBuff)
        self.links.append({'srcdpid': dpidSrc,
            'dst': {'dpid': dpid, 'port': inPort},
            'time': time.time()})

    def _cleanLinks(self):
        while True:
            now = time.time()
            self.links = [l for l in self.links if now - l['time'] < self.interval]
            hub.sleep(self.interval)

    @abc.abstractmethod
    def packet_in_process(self, ev):
        pass

    @set_ev_cls(event.EventSwitchEnter)
    def switch_enter(self, ev):
        dpid = ev.switch.dp.id
        self.sws[dpid] = True
        self.dps[dpid] = ev.switch.dp.id
        dpNode = self.zkConf['root'] + self.zkConf['swtat'] \
                + '/' + dpid_to_str(dpid)
        self.zk.ensure_path(dpNode)
        if self.election(dpid):
            self.role = OFPCR_ROLE_MASTER
        else:
            self.role = OFPCR_ROLE_SLAVE
        self.countUp(dpid)
        self.roleRequest(dpid, self.role)
        mflag = dpNode + '/' + 'master'
        DataWatch(self.zk, mflag, self.masterWatcher)

    def masterWatcher(self, data, stat, ev):
        if ev and ev.type == 'DELETED':
            _, _, dpid, _ = ev.path.split('/')
            dpid = str_to_dpid(dpid)
            if self.sws.get(dpid):
                if self.election(dpid):
                    self.role = OFPCR_ROLE_MASTER
                    self.roleRequest(dpid, self.role)
            return self.sws.get(dpid)

    def election(self, dpid):
        dpNode = self.zkConf['root'] + self.zkConf['swtat'] \
                + '/' + dpid_to_str(dpid)
        mflag = dpNode + '/' + 'master'
        while not self.zk.exists(mflag):
            mlock = self.zk.Lock(dpNode + '/' + 'mlock', self.ip)
            with mlock:
                if not self.zk.exists(mflag):
                    self.zk.create(mflag, self.ip, ephemeral=True)
            if self.zk.exists(mflag):
                if self.zk.get(mflag) == self.ip:
                    return True
                else:
                    return False
            else:
                time.sleep(random.randint(0, 100)/500.0)
        return False

    def roleRequest(self, dp, role):
        msg = dp.ofproto_parser.OFPRoleRequest(dp, role, self.gid)
        dp.send_msg(msg)

    def getCount(self, dpid):
        dpNode =  self.zkConf['root'] + self.zkConf['swtat'] \
                + '/' + dpid_to_str(dpid)
        countNode = dpNode + self.zkConf['counter']
        counters = self.zk.get_children(countNode)
        return len(counters)

    def countUp(self, dpid):
        countNode = self.zkConf['root'] + self.zkConf['swtat'] \
                + '/' + dpid_to_str(dpid) + self.zkConf['counter']
        self.zk.ensure_path(countNode)
        #self.zk.create(countNode+uuid4().hex, 'alive', ephemeral=True)
        self.zk.create(countNode+'/'+self.ip, 'alive', ephemeral=True)

    @set_ev_cls(event.EventSwitchLeave)
    def switch_levave(self, ev):
        dpid = ev.switch.dp.id
        count = self.getCount(dpid)
        self.sws[dpid] = False
        if count == 0:
            dpNode =  self.zkConf['root'] + self.zkConf['swtat'] \
                    + '/' + dpid_to_str(dpid)
        self.zk.delete(dpNode, recursive=True)

 slldp.py

import struct
from ryu.lib.packet import packet_base

SLLDP_MAC_DST = '01:80:c2:00:00:0b'
SLLDP_MAC_SRC = '00:00:00:00:00:00'
ETH_TYPE_SLLDP = 0x88cb

class slldp(packet_base.PacketBase):


    _PACK_STR = '!Q'
    _MIN_LEN = struct.calcsize(_PACK_STR)

    def __init__(self, dpid):
        super(slldp, self).__init__()
        self.dpid = dpid

    @classmethod
    def parser(cls, buf):
        dpid, = struct.unpack_from(cls._PACK_STR, buf)
        return (dpid, buf[slldp._MIN_LEN:],)

    def serialize(self, payload, prev):
        return struct.pack(slldp._PACK_STR, self.dpid)

slldp_demo.py

from slldp import slldp
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from slldp import SLLDP_MAC_DST
from slldp import SLLDP_MAC_SRC
from slldp import ETH_TYPE_SLLDP

pkt = packet.Packet()
pkt.add_protocol(ethernet.ethernet(ethertype=ETH_TYPE_SLLDP,
                dst=SLLDP_MAC_DST, src=SLLDP_MAC_SRC))
pkt.add_protocol(slldp(2))
pkt.serialize()
bin_packet = pkt.data

eth, _, buff = ethernet.ethernet.parser(bin_packet)
dpid,buf = slldp.parser(buff)
print eth
print dpid
print len(buf)

猜你喜欢

转载自my.oschina.net/u/3704723/blog/2248656
ABS
今日推荐