def transact_multipart_generator(self, msg, timeout=DEFAULT_TIMEOUT): """ Send a multipart request and yield each entry from the replies """ self.send(msg) finished = False while not finished: reply = self.recv_xid(msg.xid, timeout) if reply is None: raise TransactionError("no reply for %s" % type(msg).__name__, None) elif not isinstance(reply, loxi.protocol(reply.version).message.stats_reply): raise TransactionError("received %s in response to %s" % (type(reply).__name__, type(msg).__name__), reply) for entry in reply.entries: yield entry finished = reply.flags & loxi.protocol(reply.version).OFPSF_REPLY_MORE == 0
def test_toplevel(self): import loxi self.assertTrue(hasattr(loxi, "ProtocolError")) ofp = loxi.protocol(1) self.assertEquals(ofp.OFP_VERSION, 1) self.assertTrue(hasattr(ofp, "action")) self.assertTrue(hasattr(ofp, "common")) self.assertTrue(hasattr(ofp, "const")) self.assertTrue(hasattr(ofp, "message"))
def test_toplevel(self): import loxi self.assertTrue(hasattr(loxi, "ProtocolError")) ofp = loxi.protocol(4) self.assertEquals(ofp.OFP_VERSION, 4) self.assertTrue(hasattr(ofp, "action")) self.assertTrue(hasattr(ofp, "common")) self.assertTrue(hasattr(ofp, "const")) self.assertTrue(hasattr(ofp, "message"))
def test_toplevel(self): import loxi self.assertTrue(hasattr(loxi, "ProtocolError")) self.assertEqual(loxi.version_names[2], "1.1") ofp = loxi.protocol(2) self.assertEqual(ofp.OFP_VERSION, 2) self.assertTrue(hasattr(ofp, "action")) self.assertTrue(hasattr(ofp, "common")) self.assertTrue(hasattr(ofp, "const")) self.assertTrue(hasattr(ofp, "message"))
def test_toplevel(self): import loxi self.assertTrue(hasattr(loxi, "ProtocolError")) self.assertEquals(loxi.version_names[3], "1.2") ofp = loxi.protocol(3) self.assertEquals(ofp.OFP_VERSION, 3) self.assertTrue(hasattr(ofp, "action")) self.assertTrue(hasattr(ofp, "common")) self.assertTrue(hasattr(ofp, "const")) self.assertTrue(hasattr(ofp, "message")) self.assertTrue(hasattr(ofp, "oxm"))
def transact(self, msg, timeout=DEFAULT_TIMEOUT): """ Send a message and return the reply """ self.send(msg) reply = self.recv_xid(msg.xid, timeout) if reply is None: raise TransactionError("no reply for %s" % type(msg).__name__, None) elif isinstance(reply, loxi.protocol(reply.version).message.error_msg): raise TransactionError("received %s in response to %s" % (type(reply).__name__, type(msg).__name__), reply) return reply
def process_read(self): recvd = self.sock.recv(4096) if (len(recvd)) == 0: # this indicates that the other end hang up raise ConnectionClosed() self.logger.debug("Received %d bytes", len(recvd)) buf = self.read_buffer if buf: buf += recvd else: buf = recvd offset = 0 while offset < len(buf): if offset + 8 > len(buf): # Not enough data for the OpenFlow header break # Parse the header to get type hdr_version, hdr_type, hdr_msglen, hdr_xid = loxi.of14.message.parse_header( buf[offset:]) # Use loxi to resolve ofp of matching version ofp = loxi.protocol(hdr_version) # Extract the raw message bytes if (offset + hdr_msglen) > len(buf): # Not enough data for the body break rawmsg = buf[offset:offset + hdr_msglen] offset += hdr_msglen msg = ofp.message.parse_message(rawmsg) if not msg: self.logger.warn("Could not parse message") continue self.logger.debug("Received message %s.%s xid %d length %d", type(msg).__module__, type(msg).__name__, hdr_xid, hdr_msglen) with self.rx_cv: self.rx.append(msg) self.rx_cv.notify_all() if offset == len(buf): self.read_buffer = None else: self.read_buffer = buf[offset:] self.logger.debug("%d bytes remaining", len(self.read_buffer))
def process_read(self): recvd = self.sock.recv(4096) if (len(recvd)) == 0: # this indicates that the other end hang up raise ConnectionClosed() self.logger.debug("Received %d bytes", len(recvd)) buf = self.read_buffer if buf: buf += recvd else: buf = recvd offset = 0 while offset < len(buf): if offset + 8 > len(buf): # Not enough data for the OpenFlow header break # Parse the header to get type hdr_version, hdr_type, hdr_msglen, hdr_xid = loxi.of14.message.parse_header(buf[offset:]) # Use loxi to resolve ofp of matching version ofp = loxi.protocol(hdr_version) # Extract the raw message bytes if (offset + hdr_msglen) > len(buf): # Not enough data for the body break rawmsg = buf[offset : offset + hdr_msglen] offset += hdr_msglen msg = ofp.message.parse_message(rawmsg) if not msg: self.logger.warn("Could not parse message") continue self.logger.debug("Received message %s.%s xid %d length %d", type(msg).__module__, type(msg).__name__, hdr_xid, hdr_msglen) with self.rx_cv: self.rx.append(msg) self.rx_cv.notify_all() if offset == len(buf): self.read_buffer = None else: self.read_buffer = buf[offset:] self.logger.debug("%d bytes remaining", len(self.read_buffer))
def _pkt_handle(self, pkt): """ Check for all packet handling conditions Parse and verify message Check if XID matches something waiting Check if message is being expected for a poll operation Check if keep alive is on and message is an echo request Check if any registered handler wants the packet Enqueue if none of those conditions is met an echo request in case keep_alive is true, followed by registered message handlers. @param pkt The raw packet (string) which may contain multiple OF msgs """ # snag any left over data from last read() pkt = self.buffered_input + pkt self.buffered_input = "" # Process each of the OF msgs inside the pkt offset = 0 while offset < len(pkt): if offset + 8 > len(pkt): break # Parse the header to get type hdr_version, hdr_type, hdr_length, hdr_xid = cfg_ofp.message.parse_header(pkt[offset:]) # Use loxi to resolve to ofp of matching version ofp = loxi.protocol(hdr_version) # Extract the raw message bytes if (offset + hdr_length) > len(pkt): break rawmsg = pkt[offset : offset + hdr_length] offset += hdr_length #if self.filter_packet(rawmsg, hdr): # continue msg = ofp.message.parse_message(rawmsg) if not msg: self.parse_errors += 1 self.logger.warn("Could not parse message") continue self.logger.debug("Msg in: version %d class %s len %d xid %d", hdr_version, type(msg).__name__, hdr_length, hdr_xid) with self.sync: # Check if transaction is waiting with self.xid_cv: if self.xid and hdr_xid == self.xid: self.logger.debug("Matched expected XID " + str(hdr_xid)) self.xid_response = (msg, rawmsg) self.xid = None self.xid_cv.notify() continue # Check if keep alive is set; if so, respond to echo requests if self.keep_alive: if hdr_type == ofp.OFPT_ECHO_REQUEST: self.logger.debug("Responding to echo request") rep = ofp.message.echo_reply() rep.xid = hdr_xid # Ignoring additional data self.message_send(rep) continue # Generalize to counters for all packet types? if msg.type == ofp.OFPT_PACKET_IN: self.packet_in_count += 1 # Log error messages if isinstance(msg, ofp.message.error_msg): #pylint: disable=E1103 if msg.err_type in ofp.ofp_error_type_map: type_str = ofp.ofp_error_type_map[msg.err_type] if msg.err_type == ofp.OFPET_HELLO_FAILED: code_map = ofp.ofp_hello_failed_code_map elif msg.err_type == ofp.OFPET_BAD_REQUEST: code_map = ofp.ofp_bad_request_code_map elif msg.err_type == ofp.OFPET_BAD_ACTION: code_map = ofp.ofp_bad_action_code_map elif msg.err_type == ofp.OFPET_FLOW_MOD_FAILED: code_map = ofp.ofp_flow_mod_failed_code_map elif msg.err_type == ofp.OFPET_PORT_MOD_FAILED: code_map = ofp.ofp_port_mod_failed_code_map elif msg.err_type == ofp.OFPET_QUEUE_OP_FAILED: code_map = ofp.ofp_queue_op_failed_code_map else: code_map = None if code_map and msg.code in code_map: code_str = code_map[msg.code] else: code_str = "unknown" else: type_str = "unknown" code_str = "unknown" self.logger.warn("Received error message: xid=%d type=%s (%d) code=%s (%d)", hdr_xid, type_str, msg.err_type, code_str, msg.code) # Now check for message handlers; preference is given to # handlers for a specific packet handled = False if hdr_type in self.handlers.keys(): handled = self.handlers[hdr_type](self, msg, rawmsg) if not handled and ("all" in self.handlers.keys()): handled = self.handlers["all"](self, msg, rawmsg) if not handled: # Not handled, enqueue with self.packets_cv: if len(self.packets) >= self.max_pkts: self.packets.pop(0) self.packets_expired += 1 self.packets.append((msg, rawmsg)) self.packets_cv.notify_all() self.packets_total += 1 else: self.packets_handled += 1 self.logger.debug("Message handled by callback") # end of 'while offset < len(pkt)' # note that if offset = len(pkt), this is # appends a harmless empty string self.buffered_input += pkt[offset:]
# # Main script # # Setup global configuration (new_config, args) = config_setup() oftest.config.update(new_config) logging_setup(config) xunit_setup(config) logging.info("++++++++ " + time.asctime() + " ++++++++") # Pick an OpenFlow protocol module based on the configured version name_to_version = dict((v,k) for k, v in loxi.version_names.iteritems()) sys.modules["ofp"] = loxi.protocol(name_to_version[config["openflow_version"]]) # HACK: testutils.py imports controller.py, which needs the ofp module import oftest.testutils # Allow tests to import each other sys.path.append(config["test_dir"]) test_specs = args if config["test_spec"] != "": logging.warning("The '--test-spec' option is deprecated.") test_specs += config["test_spec"].split(',') if config["test_file"] != None: with open(config["test_file"], 'r') as f: for line in f: line, _, _ = line.partition('#') # remove comments
def _pkt_handle(self, pkt): """ Check for all packet handling conditions Parse and verify message Check if XID matches something waiting Check if message is being expected for a poll operation Check if keep alive is on and message is an echo request Check if any registered handler wants the packet Enqueue if none of those conditions is met an echo request in case keep_alive is true, followed by registered message handlers. @param pkt The raw packet (string) which may contain multiple OF msgs """ # snag any left over data from last read() pkt = self.buffered_input + pkt self.buffered_input = "" # Process each of the OF msgs inside the pkt offset = 0 while offset < len(pkt): if offset + 8 > len(pkt): break # Parse the header to get type hdr_version, hdr_type, hdr_length, hdr_xid = cfg_ofp.message.parse_header( pkt[offset:]) # Use loxi to resolve to ofp of matching version ofp = loxi.protocol(hdr_version) # Extract the raw message bytes if (offset + hdr_length) > len(pkt): break rawmsg = pkt[offset:offset + hdr_length] offset += hdr_length #if self.filter_packet(rawmsg, hdr): # continue msg = ofp.message.parse_message(rawmsg) if not msg: self.parse_errors += 1 self.logger.warn("Could not parse message") continue self.logger.debug("Msg in: version %d class %s len %d xid %d", hdr_version, type(msg).__name__, hdr_length, hdr_xid) with self.sync: # Check if transaction is waiting with self.xid_cv: if self.xid and hdr_xid == self.xid: self.logger.debug("Matched expected XID " + str(hdr_xid)) self.xid_response = (msg, rawmsg) self.xid = None self.xid_cv.notify() continue # Check if keep alive is set; if so, respond to echo requests if self.keep_alive: if hdr_type == ofp.OFPT_ECHO_REQUEST: self.logger.debug("Responding to echo request") rep = ofp.message.echo_reply() rep.xid = hdr_xid # Ignoring additional data self.message_send(rep) continue # Generalize to counters for all packet types? if msg.type == ofp.OFPT_PACKET_IN: self.packet_in_count += 1 # Log error messages if isinstance(msg, ofp.message.error_msg): #pylint: disable=E1103 if msg.err_type in ofp.ofp_error_type_map: type_str = ofp.ofp_error_type_map[msg.err_type] if msg.err_type == ofp.OFPET_HELLO_FAILED: code_map = ofp.ofp_hello_failed_code_map elif msg.err_type == ofp.OFPET_BAD_REQUEST: code_map = ofp.ofp_bad_request_code_map elif msg.err_type == ofp.OFPET_BAD_ACTION: code_map = ofp.ofp_bad_action_code_map elif msg.err_type == ofp.OFPET_FLOW_MOD_FAILED: code_map = ofp.ofp_flow_mod_failed_code_map elif msg.err_type == ofp.OFPET_PORT_MOD_FAILED: code_map = ofp.ofp_port_mod_failed_code_map elif msg.err_type == ofp.OFPET_QUEUE_OP_FAILED: code_map = ofp.ofp_queue_op_failed_code_map else: code_map = None if code_map and msg.code in code_map: code_str = code_map[msg.code] else: code_str = "unknown" else: type_str = "unknown" code_str = "unknown" self.logger.warn( "Received error message: xid=%d type=%s (%d) code=%s (%d)", hdr_xid, type_str, msg.err_type, code_str, msg.code if code_str != "unknown" else -1) if msg.version >= 4 and isinstance(msg, ofp.message.bsn_error): self.logger.warn("BSN error, msg '%s'", msg.err_msg) # Now check for message handlers; preference is given to # handlers for a specific packet handled = False if hdr_type in self.handlers.keys(): handled = self.handlers[hdr_type](self, msg, rawmsg) if not handled and ("all" in self.handlers.keys()): handled = self.handlers["all"](self, msg, rawmsg) if not handled: # Not handled, enqueue with self.packets_cv: if len(self.packets) >= self.max_pkts: self.packets.pop(0) self.packets_expired += 1 self.packets.append((msg, rawmsg)) self.packets_cv.notify_all() self.packets_total += 1 else: self.packets_handled += 1 self.logger.debug("Message handled by callback") # end of 'while offset < len(pkt)' # note that if offset = len(pkt), this is # appends a harmless empty string self.buffered_input += pkt[offset:]
# # Main script # # Setup global configuration (new_config, args) = config_setup() oftest.config.update(new_config) logging_setup(config) xunit_setup(config) logging.info("++++++++ " + time.asctime() + " ++++++++") # Pick an OpenFlow protocol module based on the configured version name_to_version = dict((v, k) for k, v in loxi.version_names.iteritems()) sys.modules["ofp"] = loxi.protocol(name_to_version[config["openflow_version"]]) # HACK: testutils.py imports controller.py, which needs the ofp module import oftest.testutils # Allow tests to import each other sys.path.append(config["test_dir"]) test_specs = args if config["test_spec"] != "": logging.warning("The '--test-spec' option is deprecated.") test_specs += config["test_spec"].split(',') if config["test_file"] != None: with open(config["test_file"], 'r') as f: for line in f: line, _, _ = line.partition('#') # remove comments