class Switch(Thread): def __init__(self, dpid, warmup_time_s, upstream_ip, upstream_port, initial_xid, throughput_mode, enable_tls=False): Thread.__init__(self) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.dpid = dpid self.currentXid = initial_xid self.should_stop = self.getCurrentMicroSeconds() + 5000 * 1000000 self.results = [] self.warmup_time_s = warmup_time_s self.upstream_ip = upstream_ip self.upstream_port = upstream_port self.messageGenerator = MessageGenerator() self.last_packetin_sent = self.getCurrentMicroSeconds() self.throughput_mode = throughput_mode self.enable_tls = enable_tls try: self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) except (OSError, NameError): pass self.messages_to_send = [(2, Hello().pack())] def on_message_received(self, data): receive_time = self.getCurrentMicroSeconds() try: msg = unpack_message(data) except: print("received invalid message!") return print("received " + str(msg.header.message_type) + " " + str(msg.header.xid)) if msg.header.message_type == Type.OFPT_PACKET_OUT or msg.header.message_type == Type.OFPT_ECHO_REPLY: if receive_time - self.start_time > self.warmup_time_s * 1000000 and receive_time < self.should_stop: self.results.append([receive_time, msg.header.xid]) if not self.throughput_mode and msg.header.xid == self.currentXid: self.send_next() elif msg.header.message_type == Type.OFPT_FEATURES_REQUEST: self.messages_to_send.insert( 0, (msg.header.xid, self.messageGenerator.generate_features_reply_message( msg.header.xid, self.dpid))) elif msg.header.message_type == Type.OFPT_SET_CONFIG: self.messages_to_send.insert( 0, (msg.header.xid, self.messageGenerator.generate_config_reply_message( msg.header.xid, msg.flags, msg.miss_send_len))) elif msg.header.message_type == Type.OFPT_ECHO_REQUEST: self.messages_to_send.insert( 0, (msg.header.xid, self.messageGenerator.generate_echo_reply_message( msg.header.xid))) elif msg.header.message_type == Type.OFPT_STATS_REQUEST: self.messages_to_send.insert( 0, (msg.header.xid, self.messageGenerator.generate_stats_reply_message())) elif msg.header.message_type == Type.OFPT_VENDOR: self.messages_to_send.insert( 0, (msg.header.xid, self.messageGenerator.generate_vendor_reply_message( msg.header.xid))) if msg.header.message_type != Type.OFPT_PACKET_OUT and msg.header.message_type != Type.OFPT_ECHO_REPLY: print("received " + str(msg.header.message_type) + " after " + str((self.getCurrentMicroSeconds() - self.start_time) / 1000000) + "s") def getCurrentMicroSeconds(self): return int(datetime.timestamp(datetime.now()) * 1000000) def send_next(self): # time to establish openflow channel if self.getCurrentMicroSeconds() - self.start_time < 5 * 1000000: return self.currentXid += 50 self.messages_to_send.append( (self.currentXid, self.messageGenerator.generate_benchmark_message( self.currentXid))) def run(self): if self.enable_tls: context = ssl.SSLContext(ssl.PROTOCOL_TLS) #context.load_cert_chain(certfile="/home/daniel/ma-daniel-geiger/floodlight/tls/client.crt", # keyfile="/home/daniel/ma-daniel-geiger/floodlight/tls/client.key") #context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.CERT_OPTIONAL context.check_hostname = False socket = context.wrap_socket(self.socket, server_hostname=self.upstream_ip) else: socket = self.socket try: socket.connect((self.upstream_ip, self.upstream_port)) print(self.dpid + " connected!") except Exception as e: print("failed to connect: " + str(e)) return socket.setblocking(False) time.sleep(1) self.start_time = self.getCurrentMicroSeconds() while True: ready_to_read, ready_to_write, error = select.select([socket], [socket], [], TIMEOUT_S) if ready_to_read: try: data = socket.recv(BUFFER_SIZE) except ssl.SSLWantReadError: print("SSLWantReadError") continue self.on_message_received(data) elif ready_to_write: if len(self.messages_to_send) > 0: xid, message_to_send = self.messages_to_send.pop(0) if self.last_packetin_sent - self.start_time > self.warmup_time_s * 1000000 and self.last_packetin_sent < self.should_stop: self.results.append( [self.getCurrentMicroSeconds(), xid]) socket.sendall(message_to_send) print("sent " + str(xid)) self.last_packetin_sent = self.getCurrentMicroSeconds() if self.throughput_mode: threading.Thread(target=self.send_next).start() else: print("socket error!") if self.getCurrentMicroSeconds() - self.should_stop > 10000000: break if not self.throughput_mode and self.getCurrentMicroSeconds( ) - self.last_packetin_sent > 2000000: print("timeout!") self.send_next() socket.close() def get_results(self): return self.results def stop(self): self.should_stop = self.getCurrentMicroSeconds()