def main_loop(self): global pendingBackAck self.input_list.append(self.server) self.input_list.append(self.broadclient) self.input_list.append(self.operation_server) while True: time.sleep(self.delay) ss = select.select inputready, outputready, exceptready = ss(self.input_list, [], []) senderdata = {} for item in pendingBackAck: if item.sender in senderdata.keys(): senderdata[item.sender] += item.data else: senderdata[item.sender] = item.data for sender in senderdata.keys(): sender.send(senderdata[sender]) del pendingBackAck[:] for self.s in inputready: if self.s == self.server: self.on_accept() else: self.data = self.s.recv(self.buffer_size) if self.s in self.tunnels: if len(self.data) == 0: self.on_close() break else: if self.s not in self.tun2buffer.keys(): self.tun2buffer[self.s] = bytes() self.tun2buffer[self.s] += self.data while True: if len(self.tun2buffer[self.s]) < headerSize: break else: headPack = struct.unpack( '!3I', self.tun2buffer[self.s][:headerSize]) bodySize = headPack[1] if len(self.tun2buffer[ self.s]) < headerSize + bodySize: logger.debug( "not a complicated packet") break else: self.data = self.tun2buffer[ self.s][headerSize:headerSize + bodySize] self.tun2buffer[ self.s] = self.tun2buffer[ self.s][headerSize + bodySize:] self.on_recv() else: if len(self.data) == 0: self.on_close() break else: self.on_recv()
def pop_out_tunnel(self, data): ''' tunnel->of ''' nccontainer = ncctunnel_pb2.nccontainer() nccontainer.ParseFromString(data) data = nccontainer.entry if nccontainer.instruction == "Centralized": # TODO self.echo += 1 ack_fromQueue.append( operation_entry(1, nccontainer.switch, nccontainer.op_id)) # self.checkPending() else: try: of_msg = unpack(data) except: logger.debug("Non OpenFlow Message" + str(len(data))) else: if of_msg.header.message_type == Type.OFPT_FEATURES_REPLY: switch_addr = of_msg.datapath_id.value self.tunnelIndex[switch_addr] = self.s self.tun2idx[self.s] = switch_addr self.ofchannelIndex[switch_addr] = self.tun2ofchannel[ self.s] if self.s in self.tun2idx.keys(): # logger.debug("datapath created id : %s" % self.tun2idx[self.s]) pass try: self.tun2ofchannel[self.s].send(data) except: pass
def on_recv(self): data = self.data # here we can parse and/or modify the data before send forward # logger.debug("Recived %d bytes from %s to %s" % (len(data), self.s.getpeername(), self.s.getsockname())) if self.s in self.ofchannels: logger.debug("Push in tunnel") self.push_in_tunnel(data) else: logger.debug("Pop out tunnel") self.pop_out_tunnel(data)
def main_loop(self): logger.info("start server at %s" % str(self.server.getsockname())) self.input_list.append(self.server) while True: time.sleep(self.delay) ss = select.select inputready, outputready, exceptready = ss(self.input_list, [], []) for self.s in inputready: if self.s == self.server: self.on_accept() else: try: self.data = self.s.recv(self.buffer_size) except: pass else: if self.s in self.tunnels: if len(self.data) == 0: self.on_close() break else: if self.s not in self.tun2buffer.keys(): self.tun2buffer[self.s] = bytes() self.tun2buffer[self.s] += self.data while True: if len(self.tun2buffer[ self.s]) < headerSize: # logger.debug("shorter than headerSize") break else: headPack = struct.unpack( '!3I', self.tun2buffer[self.s] [:headerSize]) bodySize = headPack[1] if len(self.tun2buffer[self.s] ) < headerSize + bodySize: logger.debug( "not a complicated packet") break else: self.data = self.tun2buffer[ self.s][headerSize:headerSize + bodySize] self.tun2buffer[ self.s] = self.tun2buffer[ self.s][headerSize + bodySize:] self.on_recv() else: if len(self.data) == 0: self.on_close() break else: self.on_recv()
async def _on_of_msg(self, of_msg, msg_data): logger = self._connection.logger logger.debug("OpenFlow Message Type: %s" % of_msg.header.message_type) if of_msg.header.message_type == Type.OFPT_FEATURES_REQUEST: logger.info("accept Type.OFPT_FEATURES_REQUEST") elif of_msg.header.message_type == Type.OFPT_ERROR: logger.info(of_msg.error_type) msg = TunnelMsg.construct(TunnelMsg.TYPE_PASS, msg_data) tunnel = self._writer tunnel.write(msg.pack()) await tunnel.drain()
def __send_container_by_sock(self, tun_sock, nccontainer): size = nccontainer.ByteSize() nccontainer = nccontainer.SerializeToString() ver = 1 cmd = 101 header = [ver, size, cmd] headPack = struct.pack("!3I", *header) try: lock = self.tunnelLock[tun_sock] lock.acquire() tun_sock.sendall(headPack + nccontainer) lock.release() except: logger.debug("pipe is deleted")
def encapsulate(self, data): """ encapsulate of_message with container_operation """ # TODO: encapsulate of_message with container_op nccontainer = ncctunnel_pb2.nccontainer() try: of_msg = unpack(data) except UnpackException: # logger.debug("Non OpenFlow Message") pass else: logger.debug("OpenFlow Message Type: %s" % of_msg.header.message_type) if of_msg.header.message_type == Type.OFPT_FLOW_MOD: id = str(random.random()) nccontainer.op_id = id nccontainer.entry = data return nccontainer
def broadcast_ovs2sp(self, switch_addr): logger.debug( "broadcast_ovs2sp %s %s" % (self.server.getsockname()[0], self.server.getsockname()[1])) mapInfo = switch_addr + ' ' + self.host + ' ' + str( self.operation_port) self.update_ovs2sp(mapInfo) network = '<broadcast>' # self.broadserver.sendto(mapInfo.encode('utf-8'), (network,self.broadcast_port)) def period_broadcast(data, addr): while True: self.broadserver.sendto(data, addr) logger.debug("period broadcast") time.sleep(4) threading.Thread(target=period_broadcast, args=(mapInfo.encode('utf-8'), (network, self.broadcast_port))).start()
def pop_out_tunnel(self, tunneldata): """ tunnel -> of """ global pendingBackAck nccontainer = ncctunnel_pb2.nccontainer() nccontainer.ParseFromString(tunneldata) data = nccontainer.entry if nccontainer.instruction == "TEST": self.block = True logger.debug(str(datetime.now())) newcontainer = container(nccontainer.op_id, nccontainer.instruction, nccontainer.switch, nccontainer.entry, nccontainer.ack_from, nccontainer.ack_to) logger.info("new container " + str(newcontainer)) self.pending_container.append(newcontainer) if newcontainer.state: self.__exec(newcontainer) # elif nccontainer.instruction == "Centralized": # size = nccontainer.ByteSize() # nccontainer = nccontainer.SerializeToString() # ver = 1 # cmd = 101 # header = [ver,size, cmd] # headPack = struct.pack("!3I", *header) # # pendingBackAck.append(backAck(self.s,headPack+nccontainer)) # # self.s.send(headPack+nccontainer) else: if self.s in self.senderdata.keys(): self.senderdata[self.s] += data else: self.senderdata[self.s] = data lenth = int.from_bytes(self.senderdata[self.s][2:4], byteorder='big') if lenth > len(self.senderdata[self.s]): logger.debug("not complicated packet") return else: data = self.senderdata[self.s][:lenth] self.senderdata[self.s] = self.senderdata[self.s][ lenth:] # NOTE buffer try: of_msg = unpack(data) except UnpackException: logger.debug("Non OpenFlow Message") self.tun2ofchannel[self.s].send(data) else: self.tun2ofchannel[self.s].send(data)
def on_recv(self): data = self.data if self.s in self.ofchannels: logger.debug("Push in tunnel") self.push_in_tunnel(data) elif self.s == self.broadclient: logger.debug("on_recv update_ovs2sp") self.update_ovs2sp(data.decode('utf-8')) elif self.s == self.operation_server: self.process_operationmsg(data) else: logger.debug("Pop out tunnel") self.pop_out_tunnel(data)
def period_broadcast(data, addr): while True: self.broadserver.sendto(data, addr) logger.debug("period broadcast") time.sleep(4)
def bind_tun_ofchannel(self, of_msg): switch_addr = of_msg.datapath_id.value self.ofchannelIndex[switch_addr] = self.s logger.debug("bind_tun_ofchannel %s" % switch_addr) self.tunnelIndex[switch_addr] = self.ofchannel2tun[self.s] self.tun2IDX[self.ofchannel2tun[self.s]] = switch_addr
def push_in_tunnel(self, data): """ of -> tunnel """ global pendingBackAck if self.s in self.ofchaneldata.keys(): self.ofchaneldata[self.s] += data else: self.ofchaneldata[self.s] = data lenth = int.from_bytes(self.ofchaneldata[self.s][2:4], byteorder='big') if lenth > len(self.ofchaneldata[self.s]): logger.debug("not complicated packet") return else: data = self.ofchaneldata[self.s][:lenth] self.ofchaneldata[self.s] = self.ofchaneldata[self.s][lenth:] try: of_msg = unpack(data) logger.debug("OpenFlow Message Type: %s" % of_msg.header.message_type) if of_msg.header.message_type == Type.OFPT_FEATURES_REPLY: logger.debug("accept Type.OFPT_FEATURES_REPLY") self.bind_tun_ofchannel(of_msg) self.broadcast_ovs2sp(of_msg.datapath_id.value) elif of_msg.header.message_type == Type.OFPT_PORT_STATUS: # self.receievePortStatus(data) logger.debug(" ingore port status ") elif of_msg.header.message_type == Type.OFPT_ERROR: logger.debug(of_msg.error_type) except: logger.debug("Non OpenFlow Message") nccontainer = self.encapsulate(data) self.ofchaneldata[self.s] = bytes() size = nccontainer.ByteSize() nccontainer = nccontainer.SerializeToString() ver = 1 cmd = 101 header = [ver, size, cmd] headPack = struct.pack("!3I", *header) data = headPack + nccontainer if len(pendingBackAck): senderdata = {} for item in pendingBackAck: if item.sender in senderdata.keys(): senderdata[item.sender] += item.data else: senderdata[item.sender] = item.data for sender in senderdata.keys(): if sender == self.ofchannel2tun[self.s]: data += senderdata[sender] pendingBackAck = [ item for item in pendingBackAck if item.sender != self.s ] break self.ofchannel2tun[self.s].send(data)
async def _on_info_msg(self, msg): logger = self._connection.logger logger.debug('get info msg') self._info = msg.body.decode() logger.info(self._info)