Skip to content
Yoshihiro Kaneko edited this page Apr 11, 2013 · 55 revisions

OpenFlow in Ryu

Work in progress

The communication processing and a handling of the foundational OpenFlow protocol, e.g. hello, echo, is implemented in Ryu framework. A user Ryu application can implement a handling of necessary OpenFlow event.

An event handler is called with an event object as an argument. The event object is representation of the OpenFlow message which Ryu received from OpenFlow switch. The object is a subclass of ryu.controller.ofp_event.EventOFPMsgBase class.

class EventOFPMsgBase(event.EventBase):
    def __init__(self, msg):
        super(EventOFPMsgBase, self).__init__()
        self.msg = msg

Each event class is created dynamically from the corresponding OpenFlow message class. Because of that, you cannot find the code of an event class explicitly.

The name of event class is 'Event' + corresponding message class name. For example, the event class for OFPPacketIn message is EventOFPPacketIn.

The msg attribute of the event class holds the message class instance which created it.

Each OpenFlow message class is a subclass of ryu.ofproto.ofproto_parser.MsgBase class. The MsgBase class is defined as follows, so every OpenFlow message class have those attributes.

class MsgBase(object):
    def __init__(self, datapath):
        self.datapath = datapath
        self.version = None
        self.msg_type = None
        self.msg_len = None
        self.xid = None
        self.buf = None
Attribute Description
datapath A ryu.controller.controller.Datapath instance associated with the OpenFlow switch
version OpenFlow protocol version
msg_type Type of OpenFlow message
msg_len Length of the message
xid Transaction id
buf Raw data

The following example is handling EventOFPPacketIn and sending OFPPacketOut.

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls


class MySwitch(app_manager.RyuApp):
    def __init__(self, *args, **kwargs):
        super(MySwitch, self).__init__(*args, **kwargs)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        ofp_parser = dp.ofproto_parser

        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
        out = ofp_parser.OFPPacketOut(
            datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
            actions=actions)
        dp.send_msg(out)

Symmetric Messages

Symmetric messages are sent from both of the switch and the controller. Ryu application can handle them as an event, and also send them to the switch.

OFPHello

[OF1.0, OF1.2, OF1.3]

This message is exchanged between the switch and controller upon connection startup.
OFPHello message is handled by Ryu framework, so Ryu application does not need to process it typically.

This class has no special attribute.

Example:

    @set_ev_cls(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER)
    def hello_handler(self, ev):
        self.logger.debug('OFPHello received: OF version=0x%02x', msg.version)

OFPEchoRequest

[OF1.0, OF1.2, OF1.3]

This message is sent to request an echo reply.
OFPEchoRequest message is handled by Ryu framework, so Ryu application does not need to process it typically.

Attribute Description
data An arbitrary length data

Example:

    @set_ev_cls(ofp_event.EventOFPEchoRequest,
                [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
    def echo_request_handler(self, ev):
        msg = ev.msg
        
        self.logger.debug('OFPEchoRequest received: data=%s',
                          utils.hex_array(msg.data))

OFPEchoReply

[OF1.0, OF1.2, OF1.3]

When an echo request is received, you must return an echo reply.

attribute description
data The unmodified data of an echo request message

Example:

    @set_ev_cls(ofp_event.EventOFPEchoReply,
                [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
    def echo_reply_handler(self, ev):
        msg = ev.msg

        self.logger.debug('OFPEchoReply received: data=%s',
                          utils.hex_array(msg.data))

OFPErrorMsg

[OF1.0, OF1.2, OF1.3]

The switch notifies controller of problems by this message.

Attribute Description
type High level type of error
code Details depending on the type
data Variable length data depending on the type and code

Types and codes are defined in ryu.ofproto.ofproto_v1_0, ryu.ofproto.ofproto_v1_2, ryu.ofproto.ofproto_v1_3.

Type Code
OFPET_HELLO_FAILED OFPHFC_INCOMPATIBLE
OFPHFC_EPERM
OFPET_BAD_REQUEST [OF1.0]
OFPBRC_BAD_VERSION
OFPBRC_BAD_TYPE
OFPBRC_BAD_STAT
OFPBRC_BAD_VENDOR
OFPBRC_BAD_SUBTYPE
OFPBRC_EPERM
OFPBRC_BAD_LEN
OFPBRC_BUFFER_EMPTY
OFPBRC_BUFFER_UNKNOWN
[OF1.2]
OFPBRC_BAD_VERSION
OFPBRC_BAD_TYPE
OFPBRC_BAD_STAT
OFPBRC_BAD_EXPERIMENTER
OFPBRC_BAD_EXT_TYPE
OFPBRC_EPERM
OFPBRC_BAD_LEN
OFPBRC_BUFFER_EMPTY
OFPBRC_BUFFER_UNKNOWN
OFPBRC_BAD_TABLE_ID
OFPBRC_IS_SLAVE
OFPBRC_BAD_PORT
OFPBRC_BAD_PACKET
[OF1.3]
OFPBRC_BAD_VERSION
OFPBRC_BAD_TYPE
OFPBRC_BAD_MULTIPART
OFPBRC_BAD_EXPERIMENTER
OFPBRC_BAD_EXT_TYPE
OFPBRC_EPERM
OFPBRC_BAD_LEN
OFPBRC_BUFFER_EMPTY
OFPBRC_BUFFER_UNKNOWN
OFPBRC_BAD_TABLE_ID
OFPBRC_IS_SLAVE
OFPBRC_BAD_PORT
OFPBRC_BAD_PACKET
OFPBRC_MULTIPART_BUFFER_OVERFLOW
OFPET_BAD_ACTION [OF1.0]
OFPBAC_BAD_TYPE
OFPBAC_BAD_LEN
OFPBAC_BAD_VENDOR
OFPBAC_BAD_VENDOR_TYPE
OFPBAC_BAD_OUT_PORT
OFPBAC_BAD_ARGUMENT
OFPBAC_EPERM
OFPBAC_TOO_MANY
OFPBAC_BAD_QUEUE
[OF1.2, OF1.3]
OFPBAC_BAD_TYPE
OFPBAC_BAD_LEN
OFPBAC_BAD_EXPERIMENTER
OFPBAC_BAD_EXP_TYPE
OFPBAC_BAD_OUT_PORT
OFPBAC_BAD_ARGUMENT
OFPBAC_EPERM
OFPBAC_TOO_MANY
OFPBAC_BAD_QUEUE
OFPBAC_BAD_OUT_GROUP
OFPBAC_MATCH_INCONSISTENT
OFPBAC_UNSUPPORTED_ORDER
OFPBAC_BAD_TAG
OFPBAC_BAD_SET_TYPE
OFPBAC_BAD_SET_LEN
OFPBAC_BAD_SET_ARGUMENT
[OF1.2, OF1.3]
OFPET_BAD_INSTRUCTION
OFPBIC_UNKNOWN_INST
OFPBIC_UNSUP_INST
OFPBIC_BAD_TABLE_ID
OFPBIC_UNSUP_METADATA
OFPBIC_UNSUP_METADATA_MASK
OFPBIC_BAD_EXPERIMENTER
OFPBIC_BAD_EXP_TYPE
OFPBIC_BAD_LEN
OFPBIC_EPERM
[OF1.2, OF1.3]
OFPET_BAD_MATCH
OFPBMC_BAD_TYPE
OFPBMC_BAD_LEN
OFPBMC_BAD_TAG
OFPBMC_BAD_DL_ADDR_MASK
OFPBMC_BAD_NW_ADDR_MASK
OFPBMC_BAD_WILDCARDS
OFPBMC_BAD_FIELD
OFPBMC_BAD_VALUE
OFPBMC_BAD_MASK
OFPBMC_BAD_PREREQ
OFPBMC_DUP_FIELD
OFPBMC_EPERM
OFPET_FLOW_MOD_FAILED [OF1.0]
OFPFMFC_ALL_TABLES_FULL
OFPFMFC_OVERLAP
OFPFMFC_EPERM
OFPFMFC_BAD_EMERG_TIMEOUT
OFPFMFC_BAD_COMMAND
OFPFMFC_UNSUPPORTED
[OF1.2, OF1.3]
OFPFMFC_UNKNOWN
OFPFMFC_TABLE_FULL
OFPFMFC_BAD_TABLE_ID
OFPFMFC_OVERLAP
OFPFMFC_EPERM
OFPFMFC_BAD_TIMEOUT
OFPFMFC_BAD_COMMAND
OFPFMFC_BAD_FLAGS
[OF1.2, OF1.3]
OFPET_GROUP_MOD_FAILED
OFPGMFC_GROUP_EXISTS
OFPGMFC_INVALID_GROUP
OFPGMFC_WEIGHT_UNSUPPORTED
OFPGMFC_OUT_OF_GROUPS
OFPGMFC_OUT_OF_BUCKETS
OFPGMFC_CHAINING_UNSUPPORTED
OFPGMFC_WATCH_UNSUPPORTED
OFPGMFC_LOOP
OFPGMFC_UNKNOWN_GROUP
OFPGMFC_CHAINED_GROUP
OFPGMFC_BAD_TYPE
OFPGMFC_BAD_COMMAND
OFPGMFC_BAD_BUCKET
OFPGMFC_BAD_WATCH
OFPGMFC_EPERM
OFPET_PORT_MOD_FAILED [OF1.0]
OFPPMFC_BAD_PORT
OFPPMFC_BAD_HW_ADDR
[OF1.2, OF1.3]
OFPPMFC_BAD_PORT
OFPPMFC_BAD_HW_ADDR
OFPPMFC_BAD_CONFIG
OFPPMFC_BAD_ADVERTISE
OFPPMFC_EPERM
[OF1.2, OF1.3]
OFPET_TABLE_MOD_FAILED
OFPTMFC_BAD_TABLE
OFPTMFC_BAD_CONFIG
OFPTMFC_EPERM
OFPET_QUEUE_OP_FAILED OFPQOFC_BAD_PORT
OFPQOFC_BAD_QUEUE
OFPQOFC_EPERM
[OF1.2, OF1.3]
OFPET_SWITCH_CONFIG_FAILED
OFPSCFC_BAD_FLAGS
OFPSCFC_BAD_LEN
OFPQCFC_EPERM
[OF1.2, OF1.3]
OFPET_ROLE_REQUEST_FAILED
OFPRRFC_STALE
OFPRRFC_UNSUP
OFPRRFC_BAD_ROLE
[OF1.3]
OFPET_METER_MOD_FAILED
OFPMMFC_UNKNOWN
OFPMMFC_METER_EXISTS
OFPMMFC_INVALID_METER
OFPMMFC_UNKNOWN_METER
OFPMMFC_BAD_COMMAND
OFPMMFC_BAD_FLAGS
OFPMMFC_BAD_RATE
OFPMMFC_BAD_BURST
OFPMMFC_BAD_BAND
OFPMMFC_BAD_BAND_VALUE
OFPMMFC_OUT_OF_METERS
OFPMMFC_OUT_OF_BANDS
[OF1.3]
OFPET_TABLE_FEATURES_FAILED
OFPTFFC_BAD_TABLE
OFPTFFC_BAD_METADATA
OFPTFFC_BAD_TYPE
OFPTFFC_BAD_LEN
OFPTFFC_BAD_ARGUMENT
OFPTFFC_EPERM
[OF1.2, OF1.3]
OFPET_EXPERIMENTER
N/A

For more details, see section of 5.4.4 (OF1.0), A.4.4 (OF1.2, OF1.3) of the OpenFlow spec.

Example:

    @set_ev_cls(ofp_event.EventOFPErrorMsg,
                [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
    def error_msg_handler(self, ev):
        msg = ev.msg
        
        self.logger.debug('OFPErrorMsg received: type=0x%02x code=0x%02x '
                          'message=%s',
                          msg.type, msg.code, utils.hex_array(msg.data))

Asymmetric Messages

These messages are sent from the switch, and Ryu application can handle these as an event.

OFPSwitchFeatures

[OF1.0, OF1.2, OF1.3]

A features reply that specifies the capabilities supported by the switch.

attribute description
datapath_id Datapath unique ID (64bit integer)
n_buffers Max packets buffered at once
n_tables Number of tables supported by datapath
capabilities Bitmap of supported features
[OF1.0]
OFPC_FLOW_STATS
OFPC_TABLE_STATS
OFPC_PORT_STATS
OFPC_STP
OFPC_RESERVED
OFPC_IP_REASM
OFPC_QUEUE_STATS
OFPC_ARP_MATCH_IP
[OF1.2, OF1.3]
OFPC_FLOW_STATS
OFPC_TABLE_STATS
OFPC_PORT_STATS
OFPC_GROUP_STATS
OFPC_IP_REASM
OFPC_QUEUE_STATS
OFPC_PORT_BLOCKED
[OF1.0]
actions
Bitmap of supported actions uses the following values as the number of bits to shift left
OFPAT_OUTPUT
OFPAT_SET_VLAN_VID
OFPAT_SET_VLAN_PCP
OFPAT_STRIP_VLAN
OFPAT_SET_DL_SRC
OFPAT_SET_DL_DST
OFPAT_SET_NW_SRC
OFPAT_SET_NW_DST
OFPAT_SET_NW_TOS
OFPAT_SET_TP_SRC
OFPAT_SET_TP_DST
OFPAT_ENQUEUE
[OF1.2, OF1.3]
reserved
N/A
[OF1.0, OF1.2]
ports
An array of OFPPhyPort[OF1.0], OFPPort[OF1.2] to describe all the physical ports

For more details, see section of 5.3.1 (OF1.0), A.3.1 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        msg = ev.msg

        ports = []
        for _port_no, port in msg.ports.items():
            ports.append('no=%s name=%s' % (port.port_no,
                                            port.name.rstrip("\\0")))

        self.logger.debug('OFPSwitchFeatures received: '
                          'datapath_id = %016x n_buffers = %d '
                          'n_tables = %d capabilities = %08x '
                          'actions = %08x ports = %s',
                          msg.datapath_id, msg.n_buffers, msg.n_tables,
                          msg.capabilities, msg.actions, ports)

OFPPortStatus

[OF1.0, OF1.2, OF1.3]

The switch notifies controller of change of physical ports.

attribute description
reason One of the following values
OFPPR_ADD
OFPPR_DELETE
OFPPR_MODIFY
desc An instance of OFPPhyPort (OF1.0), OFPPort (OF1.2, OF1.3)

Example:

    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def port_status_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto

        if msg.reason == ofp.OFPPR_ADD:
            self.logger.debug('OFPPortStatus received: port add: %s',
                              msg.desc)
        elif msg.reason == ofp.OFPPR_DELETE:
            self.logger.debug('OFPPortStatus received: port delete: %s',
                              msg.desc)
        elif msg.reason == ofp.OFPPR_MODIFY:
            self.logger.debug('OFPPortStatus received: port modify: %s',
                              msg.desc)
        else:
            self.logger.debug('OFPPortStatus received: unknown reason: %s',
                              msg.desc)

OFPPacketIn

[OF1.0, OF1.2, OF1.3]

The switch sends the packet that received to the controller by this message.

attribute description
buffer_id ID assigned by datapath
total_len Full length of frame
[OF1.0]
in_port
Port on which frame was received
reason Reason packet is being sent
[OF1.0]
OFPR_NO_MATCH
OFPR_ACTION
[OF1.2, OF1.3]
OFPR_NO_MATCH
OFPR_ACTION
OFPR_INVALID_TTL
[OF1.2, OF1.3]
table_id
ID of the table that was looked up
[OF1.2, OF1.3]
match
Instance of OFPMatch
data Ethernet frame

For more details, see section of 5.4.1 (OF1.0), A.4.1 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto

        if msg.reason == ofp.OFPR_NO_MATCH:
            reason = 'NO MATCH'
        elif msg.reason == ofp.OFPR_ACTION:
            reason = 'ACTION'
        else:
            reason = 'unknown'

        self.logger.debug('OFPPacketIn received: '
                          'buffer_id=%x len=%d in_port=%d reason=%s data=%s',
                          msg.buffer_id, msg.total_len, msg.in_port, reason,
                          utils.hex_array(msg.data))

OFPGetConfigReply

[OF1.0, OF1.2, OF1.3]

The switch responds to a configuration request with this message.

attribute description
flags One of the following configuration flags
[OF1.0]
OFPC_FRAG_NORMAL
OFPC_FRAG_DROP
OFPC_FRAG_REASM
OFPC_FRAG_NX_MATCH
OFPC_FRAG_MASK
[OF1.2]
OFPC_FRAG_NORMAL
OFPC_FRAG_DROP
OFPC_FRAG_REASM
OFPC_FRAG_MASK
OFPC_INVALID_TTL_TO_CONTROLLER
[OF1.3]
OFPC_FRAG_NORMAL
OFPC_FRAG_DROP
OFPC_FRAG_REASM
OFPC_FRAG_MASK
miss_send_len Max bytes of new flow that datapath should send to the controller

For more details, see section of 5.3.2 (OF1.0), A.3.2 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
    def get_config_reply_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto

        if msg.flags == ofp.OFPC_FRAG_NORMAL:
            flags = 'NORMAL'
        elif msg.flags == ofp.OFPC_FRAG_DROP:
            flags = 'DROP'
        elif msg.flags == ofp.OFPC_FRAG_REASM:
            flags = 'REASM'
        elif msg.flags == ofp.OFPC_FRAG_NX_MATCH:
            flags = 'NX MATCH'
        elif msg.flags == ofp.OFPC_FRAG_MASK:
            flags = 'MASK'
        else:
            flags = 'unknown'
        self.logger.debug('OFPGetConfigReply received: '
                          'flags=%s miss_send_len=%d',
                          flags, msg.miss_send_len)

OFPBarrierReply

[OF1.0, OF1.2, OF1.3]

The switch responds to a barrier request with this message with the xid of the request, when a processing of all previously received messages was finished.

This class has no special attribute.

Example:

    @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
    def barrier_reply_handler(self, ev):
        self.logger.debug('OFPBarrierReply received')

OFPFlowRemoved

[OF1.0, OF1.2, OF1.3]

When flows time out, the switch notifies controller with this message.

attribute description
cookie Opaque controller-issued identifier
priority Priority level of flow entry
reason One of the following values
[OF1.0]
OFPRR_IDLE_TIMEOUT
OFPRR_HARD_TIMEOUT
OFPRR_DELETE
[OF1.2, OF1.3]
OFPRR_IDLE_TIMEOUT
OFPRR_HARD_TIMEOUT
OFPRR_DELETE
OFPRR_GROUP_DELETE
[OF1.2, OF1.3]
table_id
ID of the table
duration_sec Time flow was alive in seconds
duration_nsec Time flow was alive in nanoseconds beyond duration_sec
idle_timeout Idle timeout from original flow mod
[OF1.2, OF1.3]
hard_timeout
Hard timeout from original flow mod
packet_count Number of packets that was associated with the flow
byte_count Number of bytes that was associated with the flow
match Instance of OFPMatch

For more details, see section of 5.4.2 (OF1.0), A.4.2 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
    def flow_removed_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto

        if msg.reason == ofp.OFPRR_IDLE_TIMEOUT:
            reason = 'IDLE TIMEOUT'
        elif msg.reason == ofp.OFPRR_HARD_TIMEOUT:
            reason = 'HARD TIMEOUT'
        elif msg.reason == ofp.OFPRR_DELETE:
            reason = 'DELETE'
        else:
            reason = 'unknown'
        self.logger.debug('OFPFlowRemoved received: '
                          'match=%s cookie=%d priority=%d reason=%s '
                          'duration_sec=%d duration_nsec=%d '
                          'idle_timeout=%d packet_count=%d byte_count=%d',
                          msg.match, msg.cookie, msg.priority, reason,
                          msg.duration_sec, msg.duration_nsec,
                          msg.idle_timeout, msg.packet_count, msg.byte_count)

OFPQueueGetConfigReply

[OF1.0, OF1.2, OF1.3]

The switch responds to a queue configuration request with this message.

attribute description
port Port which was queried
queues An array of OFPPacketQueue

For more details, see section of 5.3.4 (OF1.0), A.3.4 (OF1.2, OF1.3) of the OpenFlow spec.

Example:

    @set_ev_cls(ofp_event.EventOFPQueueGetConfigReply, MAIN_DISPATCHER)
    def queue_get_config_reply_handler(self, ev):
        msg = ev.msg

        self.logger.debug('OFPQueueGetConfigReply received: port=%s queues=%s',
                          msg.port, msg.queues)

OFPDescStatsReply

[OF1.0, OF1.2, OF1.3]

Description of the OpenFlow switch.

attribute description
body Instance of OFPDescStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.1 (OF1.2, OF1.3) of the OpenFlow spec.

Example:

    @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
    def desc_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body

        self.logger.debug('OFPDescStatsReply received: '
                          'mfr_desc=%s hw_desc=%s sw_desc=%s '
                          'serial_num=%s dp_desc=%s',
                          body.mfr_desc, body.hw_desc, body.sw_desc,
                          body.serial_num, body.dp_desc)

OFPFlowStatsReply

[OF1.0, OF1.2, OF1.3]

Individual flow statistics.

attribute description
body Instance of OFPFlowStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.2 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
    def flow_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body

        stats = []
        for stat in body:
            stats.append('length=%d table_id=%d match=%s '
                         'duration_sec=%d duration_nsec=%d '
                         'priority=%d idle_timeout=%d hard_timeout=%d '
                         'cookie=%d packet_count=%d byte_count=%d '
                         'actions=%s' % (stat.length, stat.table_id,
                                         stat.match, stat.duration_sec,
                                         stat.duration_nsec, stat.priority,
                                         stat.idle_timeout, stat.hard_timeout,
                                         stat.cookie, stat.packet_count,
                                         stat.byte_count, stat.actions))
        self.logger.debug('OFPFlowStatsReply received: body=%s', stats)

OFPAggregateStatsReply

[OF1.0, OF1.2, OF1.3]

Aggregate flow statistics.

attribute description
body Instance of OFPAggregateStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.3 (OF1.2, OF1.3) of the OpenFlow spec.

Example:

    @set_ev_cls(ofp_event.EventOFPAggregateStatsReply, MAIN_DISPATCHER)
    def aggregate_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body
        
        stats = []
        for stat in body:
            stats.append('packet_count=%d byte_count=%d flow_count=%d' %
                         (stat.packet_count, stat.byte_count, stat.flow_count))
        self.logger.debug('OFPAggregateStatsReply received: body=%s', stats)

OFPTableStatsReply

[OF1.0, OF1.2, OF1.3]

Flow table statistics.

attribute description
body Instance of OFPTableStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.4 (OF1.2, OF1.3) of the OpenFlow spec.

Example [OF1.0]:

    @set_ev_cls(ofp_event.EventOFPTableStatsReply, MAIN_DISPATCHER)
    def table_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body

        stats = []
        for stat in body:
            stats.append('table_id=%d name=%s wildcards=0x%08x max_entries=%d '
                         'active_count=%d lookup_count=%d matched_count=%d' %
                         (stat.table_id, stat.name.rstrip("\\0"),
                          stat.wildcards, stat.max_entries, stat.active_count,
                          stat.lookup_count, stat.matched_count))
        self.logger.debug('OFPTableStatsReply received: body=%s', stats)

OFPPortStatsReply

[OF1.0, OF1.2, OF1.3]

Physical port statistics.

attribute description
body Instance of OFPPortStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.5 (OF1.2), A.3.5.6 (OF1.3) of the OpenFlow spec.

Example [OF1.0, OF1.2]:

    @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
    def port_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body

        stats = []
        for stat in body:
            stats.append('port_no=%d rx_packets=%d tx_packets=%d '
                         'rx_bytes=%d tx_bytes=%d rx_dropped=%d tx_dropped=%d '
                         'rx_errors=%d tx_errors=%d '
                         'rx_frame_err=%d rx_over_err=%d rx_crc_err=%d '
                         'collisions=%d' % (stat.port_no, stat.rx_packets,
                                            stat.tx_packets, stat.rx_bytes,
                                            stat.tx_bytes, stat.rx_dropped,
                                            stat.tx_dropped, stat.rx_errors,
                                            stat.tx_errors, stat.rx_frame_err,
                                            stat.rx_over_err, stat.rx_crc_err,
                                            stat.collisions))
        self.logger.debug('OFPPortStatsReply received: body=%s', stats)

OFPQueueStatsReply

[OF1.0, OF1.2, OF1.3]

Queue statistics for a port.

attribute description
body Instance of OFPQueueStats

For more details, see section of 5.3.5 (OF1.0), A.3.5.6 (OF1.2), A.3.5.8 (OF1.3) of the OpenFlow spec.

Example [OF1.0, OF1.2]:

    @set_ev_cls(ofp_event.EventOFPQueueStatsReply, MAIN_DISPATCHER)
    def queue_stats_reply_handler(self, ev):
        msg = ev.msg
        body = msg.body

        stats = []
        for stat in body:
            stats.append('port_no=%d queue_id=%d '
                         'tx_bytes=%d tx_packets=%d tx_errors=%d' %
                         (stat.port_no, stat.queue_id, stat.tx_packets,
                          stat.tx_bytes, stat.tx_packets, stat.tx_errors))
        self.logger.debug('OFPQueueStatsReply received: body=%s', stats)

OFPGroupStatsReply

[OF1.2, OF1.3]

Group counter statistics.

attribute description
body Instance of OFPGroupStats

For more details, see section of A.3.5.7 (OF1.2), A.3.5.9 (OF1.3) of the OpenFlow spec.

OFPGroupDescStatsReply

[OF1.2, OF1.3]

Group counter statistics.

attribute description
body Instance of OFPGroupDescStats

For more details, see section of A.3.5.8 (OF1.2), A.3.5.10 (OF1.3) of the OpenFlow spec.

OFPGroupFeaturesStatsReply

[OF1.2, OF1.3]

Group features.

attribute description
body Instance of OFPGroupFeaturesStats

For more details, see section of A.3.5.9 (OF1.2), A.3.5.11 (OF1.3) of the OpenFlow spec.

OFPMeterStatsReply

[OF1.3]

Meter statistics.

attribute description
body Instance of OFPMeterStats

For more details, see section of A.3.5.12 of the OpenFlow spec.

OFPMeterConfigStatsReply

[OF1.3]

Meter configuration.

attribute description
body Instance of OFPMeterConfigStats

For more details, see section of A.3.5.13 of the OpenFlow spec.

OFPMeterFeaturesStatsReply

[OF1.3]

Meter features.

attribute description
body Instance of OFPMeterFeaturesStats

For more details, see section of A.3.5.14 of the OpenFlow spec.

Controller-to-Switch Messages

Ryu application can send these messages to the switch.

ryu.ofproto.ofproto_v1_0_parser.OFPFeaturesRequest

The controller sends this message to the switch upon session establishment.
OFPFeatureRequest message is handled by Ryu framework, so Ryu application does not need to process it typically.

class OFPFeaturesRequest(MsgBase):
    def __init__(self, datapath):
        super(OFPFeaturesRequest, self).__init__(datapath)
parameter description
datapath Instance of ryu.controller.controller.Datapath

Example:

    def send_features_request(self, datapath):
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPFeaturesRequest(datapath)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPGetConfigRequest

The controller sends this message to query configuration parameters in the switch.

class OFPGetConfigRequest(MsgBase):
    def __init__(self, datapath):
        super(OFPGetConfigRequest, self).__init__(datapath)
parameter description
datapath Instance of ryu.controller.controller.Datapath

Example:

    def send_get_config_request(self, datapath):
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPGetConfigRequest(datapath)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPSetConfig

The controller sends this message to set configuration parameters in the switch.

class OFPSetConfig(MsgBase):
    def __init__(self, datapath, flags=None, miss_send_len=None):
        super(OFPSetConfig, self).__init__(datapath)
        self.flags = flags
        self.miss_send_len = miss_send_len
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags One of the following configuration flags.
OFPC_FRAG_NORMAL
OFPC_FRAG_DROP
OFPC_FRAG_REASM
OFPC_FRAG_NX_MATCH
OFPC_FRAG_MASK
miss_send_len Max bytes of new flow that datapath should send to the controller

For more details, see section of 5.3.2 of the OpenFlow spec.

Example:

    def send_set_config(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPSetConfig(datapath, ofp.OFPC_FRAG_NORMAL, 256)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPPacketOut

The controller uses this message to send a packet out through the switch.

class OFPPacketOut(MsgBase):
    def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
                 data=None):
        super(OFPPacketOut, self).__init__(datapath)
        self.buffer_id = buffer_id
        self.in_port = in_port
        self.actions_len = None
        self.actions = actions
        self.data = data
parameter description
datapath Instance of ryu.controller.controller.Datapath
buffer_id ID assigned by datapath (0xffffffff if none)
in_port Packet's input port (OFPP_NONE if none)
actions An array of OpenFlow action class which is a subclass of OFPAction
data Packet data

Example:

    def send_packet_out(self, datapath, buffer_id, in_port):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
        req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id,
                                      in_port=in_port, actions=actions)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPFlowMod

The controller sends this message to modify the flow table.

class OFPFlowMod(MsgBase):
    def __init__(self, datapath, match, cookie, command,
                 idle_timeout=0, hard_timeout=0,
                 priority=ofproto_v1_0.OFP_DEFAULT_PRIORITY,
                 buffer_id=0xffffffff, out_port=ofproto_v1_0.OFPP_NONE,
                 flags=0, actions=None):
        if actions is None:
            actions = []
        super(OFPFlowMod, self).__init__(datapath)
        self.match = match
        self.cookie = cookie
        self.command = command
        self.idle_timeout = idle_timeout
        self.hard_timeout = hard_timeout
        self.priority = priority
        self.buffer_id = buffer_id
        self.out_port = out_port
        self.flags = flags
        self.actions = actions
parameter description
datapath Instance of ryu.controller.controller.Datapath
match Instance of OFPMatch
cookie Opaque controller-issued identifier
command One of the following values.
OFPFC_ADD
OFPFC_MODIFY
OFPFC_MODIFY_STRICT
OFPFC_DELETE
OFPFC_DELETE_STRICT
idle_timeout Idle time before discarding (seconds)
hard_timeout Max time before discarding (seconds)
priority Priority level of flow entry
buffer_id Buffered packet to apply to (or 0xffffffff)
out_port For OFPFC_DELETE* commands, require matching entries to include this as an output port
flags One of the following values.
OFPFF_SEND_FLOW_REM
OFPFF_CHECK_OVERLAP
OFPFF_EMERG
actions An array of OpenFlow action class which is a subclass of OFPAction

For more details, see section of 5.3.3 of the OpenFlow spec.

Example:

    def send_flow_mod(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        match = ofp_parser.OFPMatch(
            ofp.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL)]
        req = ofp_parser.OFPFlowMod(datapath=datapath, match=match, cookie=0,
                                    command=ofp.OFPFC_ADD,
                                    flags=ofp.OFPFF_SEND_FLOW_REM,
                                    actions=actions)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPPortMod

The controller sends this message to modify the behavior of the physical port.

class OFPPortMod(MsgBase):
    def __init__(self, datapath, port_no, hw_addr, config, mask, advertise):
        super(OFPPortMod, self).__init__(datapath)
        self.port_no = port_no
        self.hw_addr = hw_addr
        self.config = config
        self.mask = mask
        self.advertise = advertise
parameter description
datapath Instance of ryu.controller.controller.Datapath
port_no Port number to modify
hw_addr The hardware address that must be the same as hw_addr of OFPPhyPort of OFPSwitchFeatures
config Bitmap of configuration flags.
OFPPC_PORT_DOWN
OFPPC_NO_STP
OFPPC_NO_RECV
OFPPC_NO_RECV_STP
OFPPC_NO_FLOOD
OFPPC_NO_FWD
OFPPC_NO_PACKET_IN
mask Bitmap of configuration flags above to be changed
advertise Bitmap of the following flags.
OFPPF_10MB_HD
OFPPF_10MB_FD
OFPPF_100MB_HD
OFPPF_100MB_FD
OFPPF_1GB_HD
OFPPF_1GB_FD
OFPPF_10GB_FD
OFPPF_COPPER
OFPPF_FIBER
OFPPF_AUTONEG
OFPPF_PAUSE
OFPPF_PAUSE_ASYM

For more details, see section of 5.3.3 of the OpenFlow spec.

Example:

    def send_port_mod(self, datapath, port):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPPortMod(
            datapath=datapath, port_no=port.port_no, hw_addr=port.hw_addr,
            config=ofp.OFPPC_NO_STP,
            mask=(ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_STP | ofp.OFPPC_NO_RECV |
                  ofp.OFPPC_NO_RECV_STP | ofp.OFPPC_NO_FLOOD |
                  ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN),
            advertise=(ofp.OFPPF_10MB_FD | ofp.OFPPF_100MB_HD |
                       ofp.OFPPF_1GB_HD | ofp.OFPPF_COPPER |
                       ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
                       ofp.OFPPF_PAUSE_ASYM))
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPBarrierRequest

The controller sends this message to request a berrier reply.

class OFPBarrierRequest(MsgBase):
    def __init__(self, datapath):
        super(OFPBarrierRequest, self).__init__(datapath)
parameter description
datapath Instance of ryu.controller.controller.Datapath

Example:

    def send_barrier_request(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPBarrierRequest(datapath)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPQueueGetConfigRequest

The controller uses this message to query the switch for configured queues on a port.

class OFPQueueGetConfigRequest(MsgBase):
    def __init__(self, datapath, port):
        super(OFPQueueGetConfigRequest, self).__init__(datapath)
        self.port = port
parameter description
datapath Instance of ryu.controller.controller.Datapath
port Port to be queried

Example:

    def send_queue_get_config_request(self, datapath, port):
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPQueueGetConfigRequest(datapath, port.port_no)    
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPDescStatsRequest

Description of the OpenFlow switch.

class OFPDescStatsRequest(OFPStatsRequest):
    def __init__(self, datapath, flags):
        super(OFPDescStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero

Example:

    def send_desc_stats_request(self, datapath):
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPDescStatsRequest(datapath, 0)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPTableStatsRequest

Flow table statistics.

class OFPTableStatsRequest(OFPStatsRequest):
    def __init__(self, datapath, flags):
        super(OFPTableStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero

Example:

    def send_table_stats_request(self, datapath):
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPTableStatsRequest(datapath, 0)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPFlowStatsRequest

Individual flow statistics.

class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
    def __init__(self, datapath, flags, match, table_id, out_port):
        super(OFPFlowStatsRequest, self).__init__(
            datapath, flags, match, table_id, out_port)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero
match Instance of OFPMatch
table_id ID of table to read
out_port Require matching entries to include this as an output port

Example:

    def send_flow_stats_request(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPFlowStatsRequest(
            datapath=datapath, flags=0,
            match=ofp_parser.OFPMatch(
                ofp.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            table_id=0xff, out_port=ofp.OFPP_NONE)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPAggregateStatsRequest

Aggregate flow statistics.

class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
    def __init__(self, datapath, flags, match, table_id, out_port):
        super(OFPAggregateStatsRequest, self).__init__(
            datapath, flags, match, table_id, out_port)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero
match Instance of OFPMatch
table_id ID of table to read
out_port Require matching entries to include this as an output port

Example:

    def send_aggregate_stats_request(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPAggregateStatsRequest(
            datapath=datapath, flags=0,
            match=ofp_parser.OFPMatch(
                ofp.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
            table_id=0xff, out_port=ofp.OFPP_NONE)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPPortStatsRequest

This message is used to query information about physical port.

class OFPPortStatsRequest(OFPStatsRequest):
    def __init__(self, datapath, flags, port_no):
        super(OFPPortStatsRequest, self).__init__(datapath, flags)
        self.port_no = port_no
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero
port_no Port number to read

Example:

    def send_port_stats_request(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPPortStatsRequest(datapath, 0, ofp.OFPP_NONE)
        datapath.send_msg(req)

ryu.ofproto.ofproto_v1_0_parser.OFPQueueStatsRequest

This message is used to query queue statistics of one or more ports.

class OFPQueueStatsRequest(OFPStatsRequest):
    def __init__(self, datapath, flags, port_no, queue_id):
        super(OFPQueueStatsRequest, self).__init__(datapath, flags)
        self.port_no = port_no
        self.queue_id = queue_id
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Must be zero
port_no Port number to read
queue_id ID of queue to read

Example:

    def send_queue_stats_request(self, datapath):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        req = ofp_parser.OFPQueueStatsRequest(datapath=datapath, flags=0,
                                              port_no=ofp.OFPP_ALL,
                                              queue_id=ofp.OFPQ_ALL)
        datapath.send_msg(req)

OpenFlow Matchs

OpenFlow Match structure is defined in ryu.ofproto.ofproto_v1_0_parser.OFPMatch.

class OFPMatch(collections.namedtuple('OFPMatchBase', (
        'wildcards', 'in_port', 'dl_src', 'dl_dst', 'dl_vlan',
        'dl_vlan_pcp', 'dl_type', 'nw_tos', 'nw_proto',
        'nw_src', 'nw_dst', 'tp_src', 'tp_dst'))):
attribute description
wildcards Bitmap of wildcard flags
in_port Input switch port
dl_src Ethernet source address
dl_dst Ethernet destination address
dl_vlan Input VLAN ID
dl_vlan_pcp Input VLAN priority
dl_type Ethernet frame type
nw_tos IP ToS (DSCP field, 6 bits)
nw_proto IP protocol or lower 8 bits of ARP opcode
nw_src IP source address
nw_dst IP destination address
tp_src TCP/UDP source port
tp_dst TCP/UDP destination port

The wildcards can be set the combination of the following flags which is defined in ryu.ofproto.ofproto_v1_0.

definition description
OFPFW_IN_PORT Switch input port
OFPFW_DL_SRC Ethernet source address
OFPFW_DL_DST Ethernet destination address
OFPFW_DL_VLAN VLAN ID
OFPFW_DL_VLAN_PCP VLAN priority
OFPFW_DL_TYPE Ethernet frame type
OFPFW_NW_TOS IP ToS (DSCP field, 6 bits)
OFPFW_NW_PROTO IP protocol
OFPFW_TP_SRC TCP/UDP source port
OFPFW_TP_DST TCP/UDP destination port
OFPFW_ALL Wildcard all fields

In addition, the following definitions are used to set the source and destination netmasks.

definition description
OFPFW_NW_SRC_SHIFT Shift count to the field of an IP source address wildcard bit count
OFPFW_NW_SRC_BITS Bit length of an IP source address
OFPFW_NW_SRC_MASK Mask of the field of an IP source address wildcard bit count
OFPFW_NW_SRC_ALL Wildcard the entire field of the IP source address
OFPFW_NW_DST_SHIFT Shift count to the field of an IP destination address wildcard bit count
OFPFW_NW_DST_BITS Bit length of an IP destination address
OFPFW_NW_DST_MASK Mask of the field of an IP destination address wildcard bit count
OFPFW_NW_DST_ALL Wildcard the entire field of the IP destination address

The wildcard for IP addresses is interpreted similar of the CIDR suffix. However it is the opposite of the usual convention of the CIDR.
If a wildcard is set to "24", it means "255.0.0.0".

Example:

# Ethernet broadcast frame
dst = ryu.lib.mac.haddr_to_bin('ff:ff:ff:ff:ff:ff')
wildcards = ofp.OFPFW_ALL
wildcards &= ~(ofp.OFPFW_DL_DST)
match = ofp_parser.OFPMatch(wildcards, 0, 0, dst, 0, 0, 0, 0, 0, 0, 0, 0, 0)

# From port1 and source MAC address is '00:00:00:00:00:01'
src = ryu.lib.mac.haddr_to_bin('00:00:00:00:00:01')
wildcards = ofp.OFPFW_ALL
wildcards &= ~(ofp.OFPFW_IN_PORT | ofp.OFPFW_DL_SRC)
match = ofp_parser.OFPMatch(wildcards, 1, src, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

OpenFlow Actions

OpenFlow actions is defined in ryu.ofproto.ofproto_v1_0_parser.

For more details than the following, see section of 5.2.4 of the OpenFlow spec.

ryu.ofproto.ofproto_v1_0_parser.OFPActionOutput

This action indicates output a packet to the switch port.

class OFPActionOutput(OFPAction):
    def __init__(self, port, max_len=0):
        super(OFPActionOutput, self).__init__()
        self.port = port
        self.max_len = max_len
parameter description
port Output port
max_len Max length to send to controller

ryu.ofproto.ofproto_v1_0_parser.OFPActionVlanVid

This action indicates sets the 802.1q VLAN ID.

class OFPActionVlanVid(OFPAction):
    def __init__(self, vlan_vid):
        super(OFPActionVlanVid, self).__init__()
        self.vlan_vid = vlan_vid
parameter description
vlan_vid VLAN ID

ryu.ofproto.ofproto_v1_0_parser.OFPActionVlanPcp

This action indicates sets the 802.1q priority.

class OFPActionVlanPcp(OFPAction):
    def __init__(self, vlan_pcp):
        super(OFPActionVlanPcp, self).__init__()
        self.vlan_pcp = vlan_pcp
parameter description
vlan_pcp VLAN priority

ryu.ofproto.ofproto_v1_0_parser.OFPActionStripVlan

This action indicates strips the 802.1q header.

class OFPActionStripVlan(OFPAction):
    def __init__(self):
        super(OFPActionStripVlan, self).__init__()

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetDlSrc

This action indicates sets the Ethernet source address.

class OFPActionSetDlSrc(OFPActionDlAddr):
    def __init__(self, dl_addr):
        super(OFPActionSetDlSrc, self).__init__(dl_addr)
parameter description
dl_addr Ethernet source address

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetDlDst

This action indicates sets the Ethernet destination address.

class OFPActionSetDlDst(OFPActionDlAddr):
    def __init__(self, dl_addr):
        super(OFPActionSetDlDst, self).__init__(dl_addr)
parameter description
dl_addr Ethernet destination address

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetNwSrc

This action indicates sets the IPv4 source address.

class OFPActionSetNwSrc(OFPActionNwAddr):
    def __init__(self, nw_addr):
        super(OFPActionSetNwSrc, self).__init__(nw_addr)
parameter description
nw_addr IPv4 source address

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetNwDst

This action indicates sets the IPv4 destination address.

class OFPActionSetNwDst(OFPActionNwAddr):
    def __init__(self, nw_addr):
        super(OFPActionSetNwDst, self).__init__(nw_addr)
parameter description
nw_addr IPv4 destination address

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetNwTos

This action indicates sets the IPv4 ToS field.

class OFPActionSetNwTos(OFPAction):
    def __init__(self, tos):
        super(OFPActionSetNwTos, self).__init__()
        self.tos = tos
parameter description
tos IP ToS (DSCP field, 6 bits)

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetTpSrc

This action indicates sets the TCP/UDP source port.

class OFPActionSetTpSrc(OFPActionTpPort):
    def __init__(self, tp):
        super(OFPActionSetTpSrc, self).__init__(tp)
parameter description
tp TCP/UDP source port

ryu.ofproto.ofproto_v1_0_parser.OFPActionSetTpDst

This action indicates sets the TCP/UDP destination port.

class OFPActionSetTpDst(OFPActionTpPort):
    def __init__(self, tp):
        super(OFPActionSetTpDst, self).__init__(tp)
parameter description
tp TCP/UDP destination port

ryu.ofproto.ofproto_v1_0_parser.OFPActionEnqueue

This action indicates outputs a packet to the queue.

class OFPActionEnqueue(OFPAction):
    def __init__(self, port, queue_id):
        super(OFPActionEnqueue, self).__init__()
        self.port = port
        self.queue_id = queue_id
parameter description
port Port that queue belongs
queue_id Where to enqueue the packets

Nicira Extensions

Ryu supports Nicira Extensions of Open vSwitch, too.

Asymmetric Messages

class NXTPacketIn(NiciraHeader):
    def __init__(self, datapath, buffer_id, total_len, reason, table_id,
                 cookie, match_len, match, frame):
        super(NXTPacketIn, self).__init__(
            datapath, ofproto_v1_0.NXT_PACKET_IN)
        self.buffer_id = buffer_id
        self.total_len = total_len
        self.reason = reason
        self.table_id = table_id
        self.cookie = cookie
        self.match_len = match_len
        self.match = match
        self.frame = frame

class NXTFlowRemoved(NiciraHeader):
    def __init__(self, datapath, cookie, priority, reason,
                 duration_sec, duration_nsec, idle_timeout, match_len,
                 packet_count, byte_count, match):
        super(NXTFlowRemoved, self).__init__(
            datapath, ofproto_v1_0.NXT_FLOW_REMOVED)
        self.cookie = cookie
        self.priority = priority
        self.reason = reason
        self.duration_sec = duration_sec
        self.duration_nsec = duration_nsec
        self.idle_timeout = idle_timeout
        self.match_len = match_len
        self.packet_count = packet_count
        self.byte_count = byte_count
        self.match = match

class NXFlowStatsReply(NXStatsReply):
    def __init__(self, datapath):
        super(NXFlowStatsReply, self).__init__(datapath)

class NXTRoleReply(NiciraHeader):
    def __init__(self, datapath, role):
        super(NXTRoleReply, self).__init__(
            datapath, ofproto_v1_0.NXT_ROLE_REPLY)
        self.role = role

Controller-to-Switch Messages

class NXTSetAsyncConfig(NiciraHeader):
    def __init__(self, datapath, packet_in_mask, port_status_mask,
                 flow_removed_mask):
        super(NXTSetAsyncConfig, self).__init__(
            datapath, ofproto_v1_0.NXT_SET_ASYNC_CONFIG)
        self.packet_in_mask = packet_in_mask
        self.port_status_mask = port_status_mask
        self.flow_removed_mask = flow_removed_mask

class NXTSetPacketInFormat(NiciraHeader):
    def __init__(self, datapath, packet_in_format):
        super(NXTSetPacketInFormat, self).__init__(
            datapath, ofproto_v1_0.NXT_SET_PACKET_IN_FORMAT)
        self.format = packet_in_format

class NXTSetFlowFormat(NiciraHeader):
    def __init__(self, datapath, flow_format):
        super(NXTSetFlowFormat, self).__init__(
            datapath, ofproto_v1_0.NXT_SET_FLOW_FORMAT)
        self.format = flow_format

class NXTFlowAge(NiciraHeader):
    def __init__(self, datapath):
        super(NXTFlowAge, self).__init__(
            datapath, ofproto_v1_0.NXT_FLOW_AGE)

class NXTFlowMod(NiciraHeader):
    def __init__(self, datapath, cookie, command,
                 idle_timeout=0, hard_timeout=0,
                 priority=ofproto_v1_0.OFP_DEFAULT_PRIORITY,
                 buffer_id=0xffffffff, out_port=ofproto_v1_0.OFPP_NONE,
                 flags=0, rule=None, actions=None):

        # the argument, rule, is positioned at the one before the last due
        # to the layout struct nxt_flow_mod.
        # Although rule must be given, default argument to rule, None,
        # is given to allow other default value of argument before rule.
        assert rule is not None

        if actions is None:
            actions = []
        super(NXTFlowMod, self).__init__(datapath, ofproto_v1_0.NXT_FLOW_MOD)
        self.cookie = cookie
        self.command = command
        self.idle_timeout = idle_timeout
        self.hard_timeout = hard_timeout
        self.priority = priority
        self.buffer_id = buffer_id
        self.out_port = out_port
        self.flags = flags
        self.rule = rule
        self.actions = actions

class NXTFlowModTableId(NiciraHeader):
    def __init__(self, datapath, set_):
        super(NXTFlowModTableId, self).__init__(
            datapath, ofproto_v1_0.NXT_FLOW_MOD_TABLE_ID)
        self.set = set_

class NXFlowStatsRequest(NXStatsRequest):
    def __init__(self, datapath, flags, out_port, match_len,
                 table_id):
        super(NXFlowStatsRequest, self).__init__(datapath, flags,
                                                 ofproto_v1_0.NXST_FLOW)
        self.out_port = out_port
        self.match_len = match_len
        self.table_id = table_id

class NXTRoleRequest(NiciraHeader):
    def __init__(self, datapath, role):
        super(NXTRoleRequest, self).__init__(
            datapath, ofproto_v1_0.NXT_ROLE_REQUEST)
        self.role = role

class NXTSetControllerId(NiciraHeader):
    def __init__(self, datapath, controller_id):
        super(NXTSetControllerId, self).__init__(
            datapath, ofproto_v1_0.NXT_SET_CONTROLLER_ID)
        self.controller_id = controller_id

Actions

class NXActionResubmit(NXActionResubmitBase):
    def __init__(self, in_port=ofproto_v1_0.OFPP_IN_PORT):
        super(NXActionResubmit, self).__init__(
            ofproto_v1_0.NXAST_RESUBMIT, in_port, 0)

class NXActionResubmitTable(NXActionResubmitBase):
    def __init__(self, in_port=ofproto_v1_0.OFPP_IN_PORT, table=0xff):
        super(NXActionResubmitTable, self).__init__(
            ofproto_v1_0.NXAST_RESUBMIT_TABLE, in_port, table)

class NXActionSetTunnel(NXActionHeader):
    def __init__(self, tun_id_):
        self.tun_id = tun_id_
        super(NXActionSetTunnel, self).__init__(
            ofproto_v1_0.NXAST_SET_TUNNEL,
            ofproto_v1_0.NX_ACTION_SET_TUNNEL_SIZE)

class NXActionSetQueue(NXActionHeader):
    def __init__(self, queue_id):
        super(NXActionSetQueue, self).__init__(
            ofproto_v1_0.NXAST_SET_QUEUE,
            ofproto_v1_0.NX_ACTION_SET_QUEUE_SIZE)
        self.queue_id = queue_id

class NXActionPopQueue(NXActionHeader):
    def __init__(self):
        super(NXActionPopQueue, self).__init__(
            ofproto_v1_0.NXAST_POP_QUEUE,
            ofproto_v1_0.NX_ACTION_POP_QUEUE_SIZE)

class NXActionRegMove(NXActionHeader):
    def __init__(self, n_bits, src_ofs, dst_ofs, src, dst):
        super(NXActionRegMove, self).__init__(
            ofproto_v1_0.NXAST_REG_MOVE,
            ofproto_v1_0.NX_ACTION_REG_MOVE_SIZE)
        self.n_bits = n_bits
        self.src_ofs = src_ofs
        self.dst_ofs = dst_ofs
        self.src = src
        self.dst = dst

class NXActionRegLoad(NXActionHeader):
    def __init__(self, ofs_nbits, dst, value):
        super(NXActionRegLoad, self).__init__(
            ofproto_v1_0.NXAST_REG_LOAD,
            ofproto_v1_0.NX_ACTION_REG_LOAD_SIZE)
        self.ofs_nbits = ofs_nbits
        self.dst = dst
        self.value = value

class NXActionSetTunnel64(NXActionHeader):
    def __init__(self, tun_id_):
        self.tun_id = tun_id_
        super(NXActionSetTunnel64, self).__init__(
            ofproto_v1_0.NXAST_SET_TUNNEL64,
            ofproto_v1_0.NX_ACTION_SET_TUNNEL64_SIZE)

class NXActionMultipath(NXActionHeader):
    def __init__(self, fields, basis, algorithm, max_link, arg,
                 ofs_nbits, dst):
        super(NXActionMultipath, self).__init__(
            ofproto_v1_0.NXAST_MULTIPATH,
            ofproto_v1_0.NX_ACTION_MULTIPATH_SIZE)
        self.fields = fields
        self.basis = basis
        self.algorithm = algorithm
        self.max_link = max_link
        self.arg = arg
        self.ofs_nbits = ofs_nbits
        self.dst = dst

class NXActionNote(NXActionHeader):
    def __init__(self, note):
        # should check here if the note is valid (only hex values)
        pad = (len(note) + 10) % 8
        if pad:
            note += [0x0 for i in range(8 - pad)]
        self.note = note
        _len = len(note) + 10
        super(NXActionNote, self).__init__(
            ofproto_v1_0.NXAST_NOTE, _len)

class NXActionBundle(NXActionBundleBase):
    def __init__(self, algorithm, fields, basis, slave_type, n_slaves,
                 ofs_nbits, dst, slaves):
        super(NXActionBundle, self).__init__(
            ofproto_v1_0.NXAST_BUNDLE,
            algorithm, fields, basis, slave_type, n_slaves,
            ofs_nbits, dst, slaves)

class NXActionBundleLoad(NXActionBundleBase):
    def __init__(self, algorithm, fields, basis, slave_type, n_slaves,
                 ofs_nbits, dst, slaves):
        super(NXActionBundleLoad, self).__init__(
            ofproto_v1_0.NXAST_BUNDLE_LOAD,
            algorithm, fields, basis, slave_type, n_slaves,
            ofs_nbits, dst, slaves)

class NXActionAutopath(NXActionHeader):
    def __init__(self, ofs_nbits, dst, id_):
        super(NXActionAutopath, self).__init__(
            ofproto_v1_0.NXAST_AUTOPATH,
            ofproto_v1_0.NX_ACTION_AUTOPATH_SIZE)
        self.ofs_nbits = ofs_nbits
        self.dst = dst
        self.id = id_

class NXActionOutputReg(NXActionHeader):
    def __init__(self, ofs_nbits, src, max_len):
        super(NXActionOutputReg, self).__init__(
            ofproto_v1_0.NXAST_OUTPUT_REG,
            ofproto_v1_0.NX_ACTION_OUTPUT_REG_SIZE)
        self.ofs_nbits = ofs_nbits
        self.src = src
        self.max_len = max_len

class NXActionExit(NXActionHeader):
    def __init__(self):
        super(NXActionExit, self).__init__(
            ofproto_v1_0.NXAST_EXIT,
            ofproto_v1_0.NX_ACTION_HEADER_SIZE)

class NXActionDecTtl(NXActionHeader):
    def __init__(self):
        super(NXActionDecTtl, self).__init__(
            ofproto_v1_0.NXAST_DEC_TTL,
            ofproto_v1_0.NX_ACTION_HEADER_SIZE)

class NXActionLearn(NXActionHeader):
    def __init__(self, idle_timeout, hard_timeout, priority, cookie, flags,
                 table_id, fin_idle_timeout, fin_hard_timeout, spec):
        len_ = len(spec) + ofproto_v1_0.NX_ACTION_LEARN_SIZE
        pad_len = 8 - (len_ % 8)
                                                                                
        super(NXActionLearn, self).__init__(
            ofproto_v1_0.NXAST_LEARN, len_ + pad_len)
        self.idle_timeout = idle_timeout
        self.hard_timeout = hard_timeout
        self.priority = priority
        self.cookie = cookie
        self.flags = flags
        self.table_id = table_id
        self.fin_idle_timeout = fin_idle_timeout
        self.fin_hard_timeout = fin_hard_timeout
        self.spec = spec + bytearray('\x00' * pad_len)

class NXActionController(NXActionHeader):
    def __init__(self, max_len, controller_id, reason):
        super(NXActionController, self).__init__(
            ofproto_v1_0.NXAST_CONTROLLER,
            ofproto_v1_0.NX_ACTION_CONTROLLER_SIZE)
        self.max_len = max_len
        self.controller_id = controller_id
        self.reason = reason

class NXActionFinTimeout(NXActionHeader):
    def __init__(self, fin_idle_timeout, fin_hard_timeout):
        super(NXActionFinTimeout, self).__init__(
            ofproto_v1_0.NXAST_FIN_TIMEOUT,
            ofproto_v1_0.NX_ACTION_FIN_TIMEOUT_SIZE)
        self.fin_idle_timeout = fin_idle_timeout
        self.fin_hard_timeout = fin_hard_timeout