Esempio n. 1
0
 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
Esempio n. 2
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"))
Esempio n. 3
0
 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"))
Esempio n. 4
0
 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"))
Esempio n. 5
0
 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"))
Esempio n. 6
0
 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
Esempio n. 7
0
    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))
Esempio n. 8
0
    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))
Esempio n. 9
0
    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:]
Esempio n. 10
0
#
# 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
Esempio n. 11
0
    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:]
Esempio n. 12
0
#
# 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