Пример #1
0
class LocalController(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(LocalController, self).__init__(*args, **kwargs)

        # self.topo = extract_topo(fourswitch())
        self.topo = {}
        self.time = 0
        self.datapaths = {}
        self.eth_to_port = {}
        self.flows_final = False

        self.buffer = dict()

        self.bm = None
        self.conn = None
        self.thread = None
        # self.bm.setDaemon(True)
        self.init_my_bm()
        self.packts_buffed = 0

        # self.queue = Queue()
        # logger.init('buftest' ,logging.INFO)

    def init_my_bm(self):
        self.conn, bm_conn = multiprocessing.Pipe()
        self.bm = BufferManager(name="bm", conn=bm_conn)
        # self.bm = BufferManager(name="bm")

        # self.thread = threading.Thread(target=self.listen_to_my_conn)
        # self.thread.start()
        hub.spawn(self.listen_to_my_conn)

        self.bm.start()

    def listen_to_my_conn(self):
        while (True):
            # print("but in the list" + str(len(self.pkg_to_save)))
            packet_to_me = None
            try:
                packet_to_me = self.conn.recv()
            except Exception as err:
                # print("I'm waiting for your bilibili")
                time.sleep(0.01)
                pass
            if (packet_to_me):
                packet = pickle.loads(packet_to_me)
                # print(packet)
                dpid = packet["dpid"]
                pkg = packet["pkg"]
                in_port = packet["in_port"]
                self.send_back(pkg, dpid, in_port)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def _switch_features_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id
        self.datapaths[dpid] = datapath
        print(self.datapaths)
        print(ofproto.OFPP_CONTROLLER)
        actions = [
            parser.OFPActionOutput(port=ofproto.OFPP_CONTROLLER,
                                   max_len=ofproto.OFPCML_NO_BUFFER)
        ]
        # actions = [parser.OFPActionOutput(port=0 ,max_len=ofproto.OFPCML_NO_BUFFER)]
        inst = [
            parser.OFPInstructionActions(type_=ofproto.OFPIT_APPLY_ACTIONS,
                                         actions=actions)
        ]
        mod = parser.OFPFlowMod(datapath=datapath,
                                priority=0,
                                match=parser.OFPMatch(),
                                instructions=inst)
        datapath.send_msg(mod)
        # buf_match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,ipv4_src="192.168.1.1",ipv4_dst="192.168.1.2")
        # buf_match = parser.OFPMatch(in_port=1)
        # self.send_buf_cmd(self.datapaths[1],buf_match)
        # buf_match = parser.OFPMatch(in_port=2)
        # self.send_buf_cmd(self.datapaths[1],buf_match)
        self.disable_dhcp(datapath)
        # self.install(datapath)

    @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
    def _barrier_reply_handler(self, ev):
        #nononononono   don't
        print(ev.msg)
        print("---------------------------------------------------------")
        datapath = ev.msg.datapath
        cmd_pop = self.make_buf_message(consts.BUF_POP,
                                        src="10.0.0.1",
                                        dst="10.0.0.2",
                                        dst_port=None,
                                        dpid=None,
                                        pkg=None,
                                        in_port=None)
        try:
            self.conn.send(cmd_pop)
        except Exception as e:
            print("Error in barrier!!!!!!!!!!!")
            print(e)
        # if(len(self.buffer)>0):
        #     self.send_back(1,datapath)
        # self.install34(self.datapaths[1])

    def install(self, datapath):
        # time.sleep(2)
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        priority = 2
        buffer_id = ofproto.OFP_NO_BUFFER
        match = parser.OFPMatch(in_port=1)
        actions = [parser.OFPActionOutput(2)]
        inst = [
            parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)
        ]
        mod = parser.OFPFlowMod(datapath=datapath,
                                priority=priority,
                                match=match,
                                instructions=inst)
        datapath.send_msg(mod)
        # time.sleep(10)
        # datapath.send_barrier()
        match = parser.OFPMatch(in_port=2)
        actions = [parser.OFPActionOutput(1)]
        inst = [
            parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)
        ]
        mod = parser.OFPFlowMod(datapath=datapath,
                                priority=priority,
                                match=match,
                                instructions=inst)
        datapath.send_msg(mod)

        # datapath.send_barrier()
        req = parser.OFPBarrierRequest(datapath, xid=1)
        datapath.send_msg(req)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        pkt_in = ev.msg
        datapath = pkt_in.datapath
        ofproto = datapath.ofproto
        in_port = pkt_in.match["in_port"]
        print(in_port)
        src, dst, dst_port, dpid, pkg = self.identify_pkg(pkt_in)
        self.packts_buffed += 1
        if (self.packts_buffed == 100):
            self.install(self.datapaths[1])
        # print(pkg)
        # self.bm.pkg_to_save.append(pkt_in)
        cmd_to_bm = self.make_buf_message(consts.BUF_PUSH,
                                          src,
                                          dst,
                                          dst_port=dst_port,
                                          dpid=dpid,
                                          pkg=pkg,
                                          in_port=in_port)
        try:
            self.conn.send(cmd_to_bm)  #for process
        except Exception as e:
            print("Error!!!!!!!!!!!!!!!!!!!!!!!!!!")
            print(e)
        # ("go and save")

    def make_buf_message(self, msg_type, src, dst, dst_port, dpid, pkg,
                         in_port):
        return pickle.dumps({
            "msg_type": msg_type,
            "src": src,
            "dst": dst,
            "dst_port": dst_port,
            "dpid": dpid,
            "pkg": pkg,
            "in_port": in_port
        })

    def cal_update(self, src, dst, old, new):
        n_buf = new[0]
        match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                ipv4_dst=ipAdd(dst))
        actions_buf = [
            parser.OFPActionOutput(port=ofproto.OFPP_CONTROLLER,
                                   max_len=ofproto.OFPCML_NO_BUFFER)
        ]
        dp_buf = self.datapaths[n_buf]
        self.add_flow(datapath=dp_buf,
                      priority=233,
                      match=match,
                      actions=actions)

        match_remove = parser.OFPMatch(eth_type=ether_types.ETH_TYPEk_IP,
                                       ipv4_dst=ipAdd(dst))
        for node in old:
            dp = self.datapaths[node]
            self.remove_flow(datapath=dp, priority=1, match=match)

        new_reverse = new[::-1]
        for node in new:
            dp = self.datapaths[node]
            actions = [
                parser.OFPActionOutput(port=ofproto.OFPP_CONTROLLER,
                                       max_len=ofproto.OFPCML_NO_BUFFER)
            ]
            self.add_flow(datapath=dp,
                          priority=1,
                          match=match,
                          actions=actions)

    #drop packet for udp 68
    def disable_dhcp(self, datapath):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        match_dhcp = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=in_proto.IPPROTO_UDP,
                                     udp_src=68,
                                     udp_dst=67)
        instruction = [
            parser.OFPInstructionActions(ofproto.OFPIT_CLEAR_ACTIONS, [])
        ]
        mod = parser.OFPFlowMod(datapath,
                                priority=1,
                                match=match_dhcp,
                                instructions=instruction)
        datapath.send_msg(mod)

    def remove_flow(self, datapath, priority, match):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser

        mod = parser.OFPFlowMod(datapath=datapath,
                                command=ofproto.OFPFC_DELETE,
                                out_port=ofproto.OFPP_ANY,
                                out_group=ofproto.OFPG_ANY,
                                match=match,
                                priority=priority)
        datapath.send_msg(mod)

    def send_back(self, pkg, dpid, in_port):
        datapath = self.datapaths[dpid]
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto
        actions = [parser.OFPActionOutput(port=ofproto.OFPP_TABLE)]
        req = parser.OFPPacketOut(datapath,
                                  in_port=in_port,
                                  buffer_id=ofproto.OFP_NO_BUFFER,
                                  actions=actions,
                                  data=pkg)
        datapath.send_msg(req)
        # print("sent back")

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def _features_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        dpid = datapath.id
        self.datapaths[dpid] = datapath
        print("haha" + str(self.datapaths))
        actions = [
            parser.OFPActionOutput(port=ofproto.OFPP_CONTROLLER,
                                   max_len=ofproto.OFPCML_NO_BUFFER)
        ]
        inst = [
            parser.OFPInstructionActions(type_=ofproto.OFPIT_APPLY_ACTIONS,
                                         actions=actions)
        ]
        mod = parser.OFPFlowMod(datapath=datapath,
                                priority=0,
                                match=parser.OFPMatch(),
                                instructions=inst)
        datapath.send_msg(mod)

    def save_to_buffer(self, flow_id, pkg):
        if (pkg.datapath.id):
            flow_id = pkg.datapath.id
        if (not self.buffer.has_key(flow_id)):
            self.buffer[flow_id] = []
        print(flow_id)

        self.buffer[flow_id].append(pkg)
        print(len(self.buffer[flow_id]))

    def identify_pkg(self, pkt_in):
        (src, dst, dst_port, dpid, pkg) = ("", "", None, None, None)
        dpid = pkt_in.datapath.id
        pkg = packet.Packet(pkt_in.data)
        # pkg = pkt_in.data
        ipkg = pkg.get_protocol(ipv4.ipv4)
        if (ipkg):
            src = ipkg.src
            dst = ipkg.dst
            upkg = pkg.get_protocol(udp.udp) or pkg.get_protocol(
                tcp.tcp)  #udp and tcp are not seperated
            if (upkg):
                dst_port = upkg.dst_port
        # print(ipkg)
        return src, dst, dst_port, dpid, pkg

    def add_flow(self, datapath, priority, match):
        pass

    def start_update(self):
        old = [0, 1, 2]
        new = [0, 3, 2]
        src = 0
        dst = 2
        self.cal_update(src, dst, old, new)