Skip to content

OpenFlowV1.3 in Ryu

KANEKO Yoshihiro edited this page May 8, 2013 · 5 revisions

OpenFlow V1.3 messages

Controller-to-Switch Messages

Ryu application can send these messages to the switch.

Handshake

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

OFPFeaturesRequest

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

OFPSwitchFeatures

attribute description
datapath_id Datapath unique ID (64bit integer)
n_buffers Max packets buffered at once
n_tables Number of tables supported by datapath
auxiliary_id Identify auxiliary connections
capabilities Bitmap of supported features
OFPC_FLOW_STATS
OFPC_TABLE_STATS
OFPC_PORT_STATS
OFPC_GROUP_STATS
OFPC_IP_REASM
OFPC_QUEUE_STATS
OFPC_PORT_BLOCKED
reserved N/A

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

Example:

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

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

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

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

Switch Configuration

The controller sends OFPSetConfig to set configuration parameters, and sends OFPGetConfigRequest to query configuration parameters in the switch.

OFPSetConfig

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_MASK
miss_send_len Max bytes of new flow that datapath should send to the controller

OFPGetConfigRequest

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

OFPGetConfigReply

attribute description
flags One of the following configuration flags
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 A.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)

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

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

    @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_MASK:
            flags = 'MASK'
        else:
            flags = 'unknown'
        self.logger.debug('OFPGetConfigReply received: '
                          'flags=%s miss_send_len=%d',
                          flags, msg.miss_send_len)

Flow Table Configuration

The controller sends OFPTableMod to configure table state in the switch.

OFPTableMod

class OFPTableMod(MsgBase):
    def __init__(self, datapath, table_id, config):
        super(OFPTableMod, self).__init__(datapath)
        self.table_id = table_id
        self.config = config
parameter description
datapath Instance of ryu.controller.controller.Datapath
table_id ID of the table, OFPTT_ALL indicates all tables
config One of the following values
OFPTC_DEPRECATED_MASK = 3

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

Example:

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

        req = ofp_parser.OFPTableMod(datapath, 1, 3)
        datapath.send_msg(req)

Modify State Messages

Modify Flow Entry Message

The controller sends OFPFlowMod to modify the flow table.

OFPFlowMod

class OFPFlowMod(MsgBase):
    def __init__(self, datapath, cookie, cookie_mask, table_id, command,
                 idle_timeout, hard_timeout, priority, buffer_id, out_port,
                 out_group, flags, match, instructions):
        super(OFPFlowMod, self).__init__(datapath)
        self.cookie = cookie
        self.cookie_mask = cookie_mask
        self.table_id = table_id
        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.out_group = out_group
        self.flags = flags
        self.match = match
        self.instructions = instructions
parameter description
datapath Instance of ryu.controller.controller.Datapath
match Instance of OFPMatch
cookie Opaque controller-issued identifier
cookie_mask Mask used to restrict the cookie bits that must match when the command is OFPFC_MODIFY* or OFPFC_DELETE*
table_id ID of the table to put the flow in
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
out_group For OFPFC_DELETE* commands, require matching entries to include this as an output group
flags One of the following values
OFPFF_SEND_FLOW_REM
OFPFF_CHECK_OVERLAP
OFPFF_RESET_COUNTS
OFPFF_NO_PKT_COUNTS
OFPFF_NO_BYT_COUNTS
instructions An array of OFPInstruction*

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

Example:

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

        match = ofp_parser.OFPMatch()
        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
        inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
                                                 actions)]
        req = ofp_parser.OFPFlowMod(datapath=datapath,
                                    cookie=0, cookie_mask=0,
                                    table_id=0, command=ofp.OFPFC_ADD,
                                    idle_timeout=0, hard_timeout=0,
                                    priority=32768,
                                    buffer_id=0xffffffff,
                                    out_port=ofp.OFPP_ANY,
                                    out_group=ofp.OFPG_ANY,
                                    flags=ofp.OFPFF_SEND_FLOW_REM,
                                    match=match, instructions=inst)
        datapath.send_msg(req)

Modify Group Entry Message

The controller sends OFPGroupMod to modify the group table.

OFPGroupMod

class OFPGroupMod(MsgBase):
    def __init__(self, datapath, command, type_, group_id, buckets):
        super(OFPGroupMod, self).__init__(datapath)
        self.command = command
        self.type = type_
        self.group_id = group_id
        self.buckets = buckets
parameter description
datapath Instance of ryu.controller.controller.Datapath
command One of the following values
OFPFC_ADD
OFPFC_MODIFY
OFPFC_DELETE
type_ One of the following values
OFPGT_ALL
OFPGT_SELECT
OFPGT_INDIRECT
OFPGT_FF
group_id Group identifier
buckets An array of OFPBucket

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

Example:

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

        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_NORMAL, 0)]
        buckets = [ofp_parser.OFPBucket(len_=0, weight=0, watch_port=0,
                                        watch_group=0, actions=actions)]
        req = ofp_parser.OFPGroupMod(datapath=datapath,
                                     command=ofp.OFPFC_ADD,
                                     type_=ofp.OFPGT_ALL,
                                     group_id=0,
                                     buckets=buckets)
        datapath.send_msg(req)

Port Modification Message

The controller sends OFPPortMod to modify the behavior of the physical port.

OFPPortMod

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_RECV
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_40GB_FD
OFPPF_100GB_FD
OFPPF_1TB_FD
OFPPF_OTHER
OFPPF_COPPER
OFPPF_FIBER
OFPPF_AUTONEG
OFPPF_PAUSE
OFPPF_PAUSE_ASYM

For more details, see section of A.3.4.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=0,
            mask=(ofp.OFPPC_PORT_DOWN | ofp.OFPPC_NO_RECV |
                  ofp.OFPPC_NO_FWD | ofp.OFPPC_NO_PACKET_IN),
            advertise=(ofp.OFPPF_10MB_HD | ofp.OFPPF_100MB_FD |
                       ofp.OFPPF_1GB_FD | ofp.OFPPF_COPPER |
                       ofp.OFPPF_AUTONEG | ofp.OFPPF_PAUSE |
                       ofp.OFPPF_PAUSE_ASYM))
        datapath.send_msg(req)

Multipart Messages

Description Statistics

The controller uses OFPDescStatsRequest to query description of the OpenFlow switch.

OFPDescStatsRequest

class OFPPortDescStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags):
        super(OFPPortDescStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPMultipartReply

attribute description
body Instance of OFPDescStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_DESC:
            self.show_desc_stats(msg.body)

    def show_desc_stats(self, body):
        self.logger.debug('DescStats: 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))

Individual Flow Statistics

The controller uses OFPFlowStatsRequest to query individual flow statistics.

OFPFlowStatsRequest

class OFPFlowStatsRequest(OFPFlowStatsRequestBase):
    def __init__(self, datapath, flags, table_id, out_port, out_group,
                 cookie, cookie_mask, match):
        super(OFPFlowStatsRequest, self).__init__(datapath, flags, table_id,
                                                  out_port, out_group,
                                                  cookie, cookie_mask, match)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE
table_id ID of table to read
out_port Require matching entries to include this as an output port
out_group Require matching entries to include this as an output group
cookie Require matching entries to contain this cookie value
cookie_mask Mask used to restrict the cookie bits that must match
match Instance of OFPMatch

OFPMultipartReply

attribute description
body Instance of OFPFlowStats

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

Example:

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

        req = ofp_parser.OFPFlowStatsRequest(
            datapath=datapath, flags=0, table_id=ofp.OFPTT_ALL,
            out_port=ofp.OFPP_ANY, out_group=ofp.OFPG_ANY,
            cookie=0, cookie_mask=0,
            match=ofp_parser.OFPMatch())
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_FLOW:
            self.show_flow_stats(msg.body)

    def show_flow_stats(self, body):
        flows = []
        for stat in body:
            flows.append('length=%d table_id=%s '
                         'duration_sec=%d duration_nsec=%d '
                         'priority=%d '
                         'idle_timeout=%d hard_timeout=%d flags=0x%04x '
                         'cookie=%d packet_count=%d byte_count=%d '
                         'match=%s' %
                         (stat.length, stat.table_id,
                          stat.duration_sec, stat.duration_nsec,
                          stat.priority,
                          stat.idle_timeout, stat.hard_timeout, stat.flags,
                          stat.cookie, stat.packet_count, stat.byte_count,
                          stat.match))
        self.logger.debug('FlowStats: %s', flows)

Aggregate Flow Statistics

The controller uses OFPFlowStatsRequest to query aggregate flow statistics.

OFPAggregateStatsRequest

class OFPAggregateStatsRequest(OFPFlowStatsRequestBase):
    def __init__(self, datapath, flags, table_id, out_port, out_group,
                 cookie, cookie_mask, match):
        super(OFPAggregateStatsRequest, self).__init__(datapath,
                                                       table_id,
                                                       out_port,
                                                       out_group,
                                                       cookie,
                                                       cookie_mask,
                                                       match)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE
table_id ID of table to read
out_port Require matching entries to include this as an output port
out_group Require matching entries to include this as an output group
cookie Require matching entries to contain this cookie value
cookie_mask Mask used to restrict the cookie bits that must match
match Instance of OFPMatch

OFPMultipartReply

attribute description
body Instance of OFPAggregateStats

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

Example:

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

        req = ofp_parser.OFPAggregateStatsRequest(
            datapath=datapath, flags=0, table_id=ofp.OFPTT_ALL,
            out_port=ofp.OFPP_ANY, out_group=ofp.OFPG_ANY,
            cookie=0, cookie_mask=0,
            match=ofp_parser.OFPMatch())
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_AGGREGATE:
            self.show_aggregate_stats(msg.body)

    def show_aggregate_stats(self, body):
        aggregates = []
        for stat in body:
            aggregates.append('packet_count=%d byte_count=%d flow_count=%d' %
                              (stat.packet_count, stat.byte_count,
                               stat.flow_count))
        self.logger.debug('AggregateStats: %s', aggregates)

Table Statistics

The controller uses OFPTableStatsRequest to query flow table statistics.

OFPTableStatsRequest

class OFPTableStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags):
        super(OFPTableStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPMultipartReply

attribute description
body Instance of OFPTableStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_TABLE:
            self.show_table_stats(msg.body)

    def show_table_stats(self, body):
        tables = []
        for stat in body:
            tables.append('table_id=%d active_count=%d lookup_count=%d '
                          ' matched_count=%d' %
                          (stat.table_id, stat.active_count, stat.lookup_count,
                           stat.matched_count))
        self.logger.debug('TableStats: %s', tables)

Port Statistics

The controller uses OFPPortStatsRequest to query information about physical port.

OFPPortStatsRequest

class OFPPortStatsRequest(OFPMultipartRequest):
    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 Zero or OFPMPF_REQ_MORE
port_no Port number to read

OFPMultipartReply

attribute description
body Instance of OFPPortStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_PORT_STATS:
            self.show_port_stats(msg.body)

    def show_port_stats(self, body):
        ports = []
        for stat in body:
            ports.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 duration_sec=%d duration_nsec=%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,
                          stat.duration_sec, stat.duration_nsec))
        self.logger.debug('PortStats: %s', ports)

Port Description

The controller uses OFPQueueStatsRequest to query description of all the ports.

OFPPortDescStatsRequest

class OFPPortDescStatsReply(OFPMultipartReply):
    def __init__(self, datapath):
        super(OFPPortDescStatsReply, self).__init__(datapath)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPMultipartReply

attribute description
body Instance of OFPPortDescStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_PORT_DESC:
            self.show_port_desc(msg.body, dp)

    def show_port_desc(self, body, datapath):
        ports = []
        for p in body:
            ports.append('port_no=%d hw_addr=%s name=%s config=0x%08x '
                         'state=0x%08x curr=0x%08x advertised=0x%08x '
                         'supported=0x%08x curr_speed=%d max_speed=%d' %
                         (p.port_no, mac.haddr_to_str(p.hw_addr),
                          p.name.rstrip('\0'), p.config,
                          p.state, p.curr, p.advertised,
                          p.supported, p.curr_speed, p.max_speed))
        self.logger.debug('OFPPortDescStatsReply received: %s', ports)

Queue Statistics

The controller uses OFPQueueStatsRequest to query statistics of one or more ports.

OFPQueueStatsRequest

class OFPQueueStatsRequest(OFPMultipartRequest):
    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 Zero or OFPMPF_REQ_MORE
port_no Port number to read
queue_id ID of queue to read

OFPMultipartReply

attribute description
body Instance of OFPQueueStats

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

Example:

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

        req = ofp_parser.OFPQueueStatsRequest(datapath, 0, ofp.OFPP_ANY,
                                              ofp.OFPQ_ALL)
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_QUEUE:
            self.show_queue_stats(msg.body)

    def show_queue_stats(self, body):
        queues = []
        for stat in body:
            queues.append('port_no=%d queue_id=%d '
                          'tx_bytes=%d tx_packets=%d tx_errors=%d '
                          'duration_sec=%d duration_nsec=%d' %
                          (stat.port_no, stat.queue_id,
                           stat.tx_bytes, stat.tx_packets, stat.tx_errors,
                           stat.duration_sec, stat.duration_nsec))
        self.logger.debug('QueueStats: %s', queues)

Group Statistics

The controller uses OFPGroupStatsRequest to query statistics of one or more groups.

OFPGroupStatsRequest

class OFPGroupStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags, group_id):
        super(OFPGroupStatsRequest, self).__init__(datapath, flags)
        self.group_id = group_id
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE
group_id ID of group to read. All groups if OFPG_ALL

OFPMultipartReply

attribute description
body Instance of OFPGroupStats

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

Example:

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

        req = ofp_parser.OFPGroupStatsRequest(datapath, 0, ofp.OFPG_ALL)
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_GROUP:
            self.show_group_stats(msg.body)

    def show_group_stats(self, body):
        groups = []
        for stat in body:
            groups.append('length=%d group_id=%d '
                          'ref_count=%d packet_count=%d byte_count=%d '
                          'duration_sec=%d duration_nsec=%d' %
                          (stat.length, stat.group_id,
                           stat.ref_count, stat.packet_count, stat.byte_count,
                           stat.duration_sec, stat.duration_nsec))
        self.logger.debug('GroupStats: %s', groups)

Group Description

The controller uses OFPGroupStatsRequest to list the set of groups on a switch.

OFPGroupDescStatsRequest

class OFPGroupDescStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags, port_no):
        super(OFPGroupDescStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPMultipartReply

attribute description
body Instance of OFPGroupDescStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_GROUP_DESC:
            self.show_group_desc_stats(msg.body)

    def show_group_desc_stats(self, body):
        descs = []
        for stat in body:
            descs.append('length=%d type=%d group_id=%d '
                         'buckets=%s' %
                         (stat.length, stat.type, stat.group_id,
                          stat.bucket))
        self.logger.debug('GroupDescStats: %s', groups)

Group Features

The controller uses OFPGroupFeaturesStatsRequest to list the capabilities of groups on a switch.

OFPGroupFeaturesStatsRequest

class OFPGroupFeaturesStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags, port_no):
        super(OFPGroupFeaturesRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPGroupFeaturesStatsReply

attribute description
body Instance of OFPGroupFeaturesStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_GROUP_FEATURES:
            self.show_group_features_stats(msg.body)

    def show_group_features_stats(self, body):
        features = []
        for stat in body:
            features.append('types=%d capabilities=0x%08x max_groups=%s '
                            'actions=%s' %
                            (stat.types, stat.capabilities, stat.max_groups,
                             stat.actions))
        self.logger.debug('GroupFeaturesStats: %s', features)

Meter Statistics

The controller uses OFPMeterStatsRequest to query statistics for one or more meters.

OFPMeterStatsRequest

class OFPMeterStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags, meter_id):
        super(OFPMeterStatsRequest, self).__init__(datapath, flags)
        self.meter_id = meter_id
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE
meter_id ID of meter to read, or OFPM_ALL

OFPMultipartReply

attribute description
body Instance of OFPMeterStats

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

Example:

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

        req = ofp_parser.OFPMeterStatsRequest(datapath, 0, ofp.OFPM_ALL)
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_METER:
            self.show_meter_stats(msg.body, dp)

    def show_meter_stats(self, body):
        meters = []
        for stat in body:
            meters.append('meter_id=0x%08x len=%d flow_count=%d '
                          'packet_in_count=%d byte_in_count=%d '
                          'duration_sec=%d duration_nsec=%d '
                          'band_stats=%s' %
                          (stat.meter_id, stat.len, stat.flow_count,
                           stat.packet_in_count, stat.byte_in_count,
                           stat.duration_sec, stat.duration_nsec,
                           stat.band_stats))
        self.logger.debug('MeterStats: %s', meters)

Meter Configuration Statistics

The controller uses OFPMeterConfigStatsRequest to query configuration for one or more meters.

OFPMeterConfigStatsRequest

class OFPMeterConfigStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags, meter_id):
        super(OFPMeterConfigStatsRequest, self).__init__(datapath, flags)
        self.meter_id = meter_id
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE
meter_id ID of meter to read, or OFPM_ALL

OFPMultipartReply

attribute description
body Instance of OFPMeterConfigStats

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

Example:

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

        req = ofp_parser.OFPMeterConfigStatsRequest(datapath, 0, ofp.OFPM_ALL)
        datapath.send_msg(req)

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_METER_CONFIG:
            self.show_meter_config_stats(msg.body, dp)

    def show_meter_config_stats(self, body):
        configs = []
        for stat in body:
            configs.append('length=%d flags=0x%04x meter_id=0x%08x '
                           'bands=%s' %
                           (stat.length, stat.flags, stat.meter_id,
                            stat.bands))
        self.logger.debug('MeterConfigStats: %s', configs)

Meter Features Statistics

The controller uses OFPMeterFeaturesStatsRequest to query the set of features of the metering subsystem.

OFPMeterFeaturesStatsRequest

class OFPMeterFeaturesStatsRequest(OFPMultipartRequest):
    def __init__(self, datapath, flags):
        super(OFPMeterFeaturesStatsRequest, self).__init__(datapath, flags)
parameter description
datapath Instance of ryu.controller.controller.Datapath
flags Zero or OFPMPF_REQ_MORE

OFPMultipartReply

attribute description
body Instance of OFPMeterFeaturesStats

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

Example:

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

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

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

        self.logger.debug('OFPMultipartReply received:')
        if msg.type == ofp.OFPMP_METER_FEATURES:
            self.show_meter_features_stats(msg.body, dp)

    def show_meter_features_stats(self, body):
        features = []
        for stat in body:
            features.append('max_meter=%d band_types=0x%08x '
                            'capabilities=0x%08x max_band=%d max_color=%d' %
                            (stat.max_meter, stat.band_types,
                             stat.capabilities, stat.max_band, stat.max_color))
        self.logger.debug('MeterFeaturesStats: %s', configs)

Queue Configuration Messages

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

OFPQueueGetConfigRequest

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

OFPQueueGetConfigReply

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

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

Example:

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

        req = ofp_parser.OFPQueueGetConfigRequest(datapath, ofp.OFPP_ANY)
        datapath.send_msg(req)

    @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)

Packet-Out Message

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

OFPPacketOut

class OFPPacketOut(MsgBase):
    def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
                 data=None):
        assert in_port is not None

        super(OFPPacketOut, self).__init__(datapath)
        self.buffer_id = buffer_id
        self.in_port = in_port
        self.actions_len = 0
        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 or OFPP_CONTROLLER
actions An array of OpenFlow action class
data Packet data

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

Example:

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

        in_port = 0
        for f in msg.match.fields:
            if isinstance(f, ofp_parser.MTInPort):
                in_port = f.value
        self.send_packet_out(dp, msg.buffer_id, in_port)

    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, 0)]
        req = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id,
                                      in_port=in_port, actions=actions)
        datapath.send_msg(req)

Barrier Message

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

OFPBarrierRequest

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

OFPBarrierReply

This class has no special attribute.

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

Example:

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

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

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

Role Request Message

The controller sends OFPRoleRequest to change its role.

OFPRoleRequest

class OFPRoleRequest(MsgBase):
    def __init__(self, datapath, role, generation_id):
        super(OFPRoleRequest, self).__init__(datapath)
        self.role = role
        self.generation_id = generation_id
parameter description
datapath Instance of ryu.controller.controller.Datapath
role One of the following values
OFPCR_ROLE_NOCHANGE
OFPCR_ROLE_EQUAL
OFPCR_ROLE_MASTER
OFPCR_ROLE_SLAVE
generation_id Master Election Generation ID

OFPRoleReply

This class has no special attribute.

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

Example:

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

        req = ofp_parser.OFPRoleRequest(datapath, ofp.OFPCR_ROLE_EQUAL, 0)
        datapath.send_msg(req)

    @set_ev_cls(ofp_event.EventOFPRoleReply, MAIN_DISPATCHER)
    def role_reply_handler(self, ev):
        self.logger.debug('OFPRoleReply received')

Set Asynchronous Configuration Message

The controller sends OFPSetAsync to set the asynchronous messages that it wants to receive on a given OpenFlow channel, sends OFPGetAsyncRequest to query the asynchronous configuration.

OFPSetAsync

class OFPSetAsync(MsgBase):                                                     
    def __init__(self, datapath,                                                
                 packet_in_mask, port_status_mask, flow_removed_mask):          
        super(OFPSetAsync, self).__init__(datapath)                             
        self.packet_in_mask = packet_in_mask                                    
        self.port_status_mask = port_status_mask                                
        self.flow_removed_mask = flow_removed_mask                              
parameter description
datapath Instance of ryu.controller.controller.Datapath
packet_in_mask 2-element array: element 0, when the controller has a OFPCR_ROLE_EQUAL or OFPCR_ROLE_MASTER role. element 1, when the controller has a OFPCR_ROLE_SLAVE role.
Bitmap of the following flags
OFPR_NO_MATCH
OFPR_ACTION
OFPR_INVALID_TTL
port_status_mask 2-element array.
Bitmap of the following flags
OFPPR_ADD
OFPPR_DELETE
OFPPR_MODIFY
flow_removed_mask 2-element array.
Bitmap of the following flags
OFPRR_IDLE_TIMEOUT
OFPRR_HARD_TIMEOUT
OFPRR_DELETE
OFPRR_GROUP_DELETE

OFPGetAsyncRequest

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

*OFPGetAsyncReply:

attribute description
packet_in_mask Bitmasks of following values
OFPR_NO_MATCH
OFPR_ACTION
OFPR_INVALID_TTL
port_status_mask Bitmasks of following values
OFPPR_ADD
OFPPR_DELETE
OFPPR_MODIFY
flow_removed_mask Bitmasks of following values
OFPRR_IDLE_TIMEOUT
OFPRR_HARD_TIMEOUT
OFPRR_DELETE
OFPRR_GROUP_DELETE

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

Example:

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

        req = ofp_parser.OFPSetAsync(
            datapath=datapath,
            packet_in_mask=[ofp.OFPR_ACTION|ofp.OFPR_INVALID_TTL, 0],
            port_status_mask=[
                ofp.OFPPR_ADD|ofp.OFPPR_DELETE|ofp.OFPPR_MODIFY, 0],
            flow_removed_mask=[
                ofp.OFPRR_IDLE_TIMEOUT|ofp.OFPRR_HARD_TIMEOUT|ofp.OFPRR_DELETE,
                0])
        datapath.send_msg(req)

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

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

    @set_ev_cls(ofp_event.EventOFPGetAsyncReply, MAIN_DISPATCHER)
    def get_async_reply_handler(self, ev):
        msg = ev.msg

        self.logger.debug('OFPGetAsyncReply received: '
                          'packet_in_mask=[0x%08x, 0x%08x] '
                          'port_status_mask=[0x%08x, 0x%08x] '
                          'flow_removed_mask=[0x%08x, 0x%08x]',
                          msg.packet_in_mask[0], msg.packet_in_mask[1],
                          msg.port_status_mask[0], msg.port_status_mask[1],
                          msg.flow_removed_mask[0], msg.flow_removed_mask[1])

Asynchronous Messages

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

Packet-In Message

The switch sends the packet that received to the controller by OFPPacketIn.

OFPPacketIn

attribute description
buffer_id ID assigned by datapath
total_len Full length of frame
reason Reason packet is being sent
OFPR_NO_MATCH
OFPR_ACTION
OFPR_INVALID_TTL
table_id ID of the table that was looked up
match Instance of OFPMatch
data Ethernet frame

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

Example:

    @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

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

        field = []
        for f in msg.match.fields:
            field.append('%s: value=%s' % (f.__class__.__name__, f.value))

        self.logger.debug('OFPPacketIn received: '
                          'buffer_id=%x total_len=%d reason=%s table_id=%d '
                          'cookie=%d match.fields=%s data=%s',
                          msg.buffer_id, msg.total_len, reason, msg.table_id,
                          msg.cookie, field, utils.hex_array(msg.data))

Flow Removed Message

When flows time out, the switch notifies controller with OFPFlowRemoved.

OFPFlowRemoved

attribute description
cookie Opaque controller-issued identifier
priority Priority level of flow entry
reason One of the following values
OFPRR_IDLE_TIMEOUT
OFPRR_HARD_TIMEOUT
OFPRR_DELETE
OFPRR_GROUP_DELETE
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
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 A.4.2 of the OpenFlow spec.

Example:

    @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'
        elif msg.reason == ofp.OFPRR_GROUP_DELETE:
            reason = 'GROUP DELETE'
        else:
            reason = 'unknown'

        field = []
        for f in msg.match.fields:
            field.append('%s: value=%s' % (f.__class__.__name__, f.value))

        self.logger.debug('OFPFlowRemoved received: '
                          'cookie=%d priority=%d reason=%s table_id=%d '
                          'duration_sec=%d duration_nsec=%d '
                          'idle_timeout=%d hard_timeout=%d '
                          'packet_count=%d byte_count=%d match.fields=%s',
                          msg.cookie, msg.priority, reason, msg.table_id,
                          msg.duration_sec, msg.duration_nsec,
                          msg.idle_timeout, msg.hard_timeout,
                          msg.packet_count, msg.byte_count, field)

Port Status Message

The switch notifies controller of change of physical ports.

OFPPortStatus

attribute description
reason One of the following values
OFPPR_ADD
OFPPR_DELETE
OFPPR_MODIFY
desc An instance of OFPPort

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:
            reason = 'ADD'
        elif msg.reason == ofp.OFPPR_DELETE:
            reason = 'DELETE'
        elif msg.reason == ofp.OFPPR_MODIFY:
            reason = 'MODIFY'
        else:
            reason = 'unknown'

        self.logger.debug('OFPPortStatus received: reason=%s desc=%s',
                          reason, msg.desc)

Error Message

The switch notifies controller of problems by OFPErrorMsg.

OFPErrorMsg

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_3.

Type Code
OFPET_HELLO_FAILED OFPHFC_INCOMPATIBLE
OFPHFC_EPERM
OFPET_BAD_REQUEST 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
OFPET_BAD_ACTION 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
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
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 OFPFMFC_UNKNOWN
OFPFMFC_TABLE_FULL
OFPFMFC_BAD_TABLE_ID
OFPFMFC_OVERLAP
OFPFMFC_EPERM
OFPFMFC_BAD_TIMEOUT
OFPFMFC_BAD_COMMAND
OFPFMFC_BAD_FLAGS
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 OFPPMFC_BAD_PORT
OFPPMFC_BAD_HW_ADDR
OFPPMFC_BAD_CONFIG
OFPPMFC_BAD_ADVERTISE
OFPPMFC_EPERM
OFPET_TABLE_MOD_FAILED OFPTMFC_BAD_TABLE
OFPTMFC_BAD_CONFIG
OFPTMFC_EPERM
OFPET_QUEUE_OP_FAILED OFPQOFC_BAD_PORT
OFPQOFC_BAD_QUEUE
OFPQOFC_EPERM
OFPET_SWITCH_CONFIG_FAILED OFPSCFC_BAD_FLAGS
OFPSCFC_BAD_LEN
OFPQCFC_EPERM
OFPET_ROLE_REQUEST_FAILED OFPRRFC_STALE
OFPRRFC_UNSUP
OFPRRFC_BAD_ROLE
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
OFPET_TABLE_FEATURES_FAILED OFPTFFC_BAD_TABLE
OFPTFFC_BAD_METADATA
OFPTFFC_BAD_TYPE
OFPTFFC_BAD_LEN
OFPTFFC_BAD_ARGUMENT
OFPTFFC_EPERM
OFPET_EXPERIMENTER N/A

For more details, see section of A.4.4 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))

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.

Hello

OFPHello 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.

OFPHello

This class has no special attribute.

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

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)

Echo Request

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

OFPEchoRequest

Attribute Description
data An arbitrary length data

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

Example:

    @set_ev_cls(ofp_event.EventOFPEchoRequest,
                [HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
    def echo_request_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath

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

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

        req = ofp_parser.OFPEchoRequest(datapath)
        req.data = data
        datapath.send_msg(req)

Echo Reply

When OFPEchoRequest is received, you must return OFPEchoReply.

OFPEchoReply

attribute description
data The unmodified data of an echo request message

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

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))

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

        reply = ofp_parser.OFPEchoReply(datapath)
        reply.data = data
        datapath.send_msg(reply)

Experimenter

This is an experimenter extension message.

OFPExperimenter

Attribute Description
experimenter Experimenter ID
exp_type Experimenter defined

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

OpenFlow Matchs

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

class OFPMatch(object):                                                         
    def __init__(self):                                                         
        super(OFPMatch, self).__init__()                                        
        self.wc = FlowWildcards()                                               
        self.flow = Flow()                                                      
        self.fields = []                                                        
Method Description
set_in_port(self, port) Switch input port
set_in_phy_port(self, phy_port) Switch physical input port
set_metadata(self, metadata) Metadata passed between tables
set_metadata_masked(self, metadata, mask) Metadata and its mask
set_dl_dst(self, dl_dst) Ethernet destination address
set_dl_dst_masked(self, dl_dst, mask) Ethernet destination address and its mask
set_dl_src(self, dl_src) Ethernet source address
set_dl_src_masked(self, dl_src, mask) Ethernet source address and its mask
set_dl_type(self, dl_type) Ethernet frame type
set_vlan_vid(self, vid) VLAN ID
set_vlan_vid_masked(self, vid, mask) VLAN ID and its mask
set_vlan_pcp(self, pcp) VLAN priority
set_ip_dscp(self, ip_dscp) IP DSCP (6 bits in ToS field)
set_ip_ecn(self, ip_ecn) IP ECN (2 bits in ToS field)
set_ip_proto(self, ip_proto) IP protocol
set_ipv4_src(self, ipv4_src) IPv4 source address
set_ipv4_src_masked(self, ipv4_src, mask) IPv4 source address and its mask
set_ipv4_dst(self, ipv4_dst) IPv4 destination address
set_ipv4_dst_masked(self, ipv4_dst, mask) IPv4 destination address and its mask
set_tcp_src(self, tcp_src) TCP source port
set_tcp_dst(self, tcp_dst) TCP destination port
set_udp_src(self, udp_src) UDP source port
set_udp_dst(self, udp_dst) UDP destination port
set_sctp_src(self, sctp_src) SCTP source port
set_sctp_dst(self, sctp_dst) SCTP destination port
set_icmpv4_type(self, icmpv4_type) ICMP type
set_icmpv4_code(self, icmpv4_code) ICMP code
set_arp_opcode(self, arp_op) ARP opcode
set_arp_spa(self, arp_spa) ARP source IPv4 address
set_arp_spa_masked(self, arp_spa, mask) ARP source IPv4 address and its mask
set_arp_tpa(self, arp_tpa) ARP target IPv4 address
set_arp_tpa_masked(self, arp_tpa, mask): ARP target IPv4 address and its mask
set_arp_sha(self, arp_sha) ARP source hardware address
set_arp_sha_masked(self, arp_sha, mask) ARP source hardware address and its mask
set_arp_tha(self, arp_tha) ARP target hardware address
set_arp_tha_masked(self, arp_tha, mask) ARP target hardware address and its mask
set_ipv6_src(self, src) IPv6 source address
set_ipv6_src_masked(self, src, mask) IPv6 source address and its mask
set_ipv6_dst(self, dst) IPv6 destination address
set_ipv6_dst_masked(self, dst, mask) IPv6 destination address and its mask
set_ipv6_flabel(self, flabel) IPv6 Flow Label
set_ipv6_flabel_masked(self, flabel, mask) IPv6 Flow Label and its mask
set_icmpv6_type(self, icmpv6_type) ICMPv6 type
set_icmpv6_code(self, icmpv6_code) ICMPv6 code
set_ipv6_nd_target(self, target) Target address for ND
set_ipv6_nd_sll(self, ipv6_nd_sll) Source link-layer for ND
set_ipv6_nd_tll(self, ipv6_nd_tll) Target link-layer for ND
set_mpls_label(self, mpls_label) MPLS label
set_mpls_tc(self, mpls_tc) MPLS TC
set_mpls_bos(self, bos) MPLS BoS bit
set_pbb_isid(self, isid) PBB I-SID
set_pbb_isid_masked(self, isid, mask) PBB I-SID and its mask
set_tunnel_id(self, tunnel_id) Logical Port Metadata
set_tunnel_id_masked(self, tunnel_id, mask) Logical Port Metadata and its mask
set_ipv6_exthdr(self, hdr) IPv6 Extension Header pseudo-field
set_ipv6_exthdr_masked(self, hdr, mask) IPv6 Extension Header pseudo-field and its mask

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

Example:

# Ethernet broadcat frame
match = ofp_parser.OFPMatch()
match.set_dl_dst(ryu.lib.mac.haddr_to_bin('ff:ff:ff:ff:ff:ff'))

# From port1 and source MAC address is '00:00:00:00:00:01'
match = ofp_parser.OFPMatch()
match.set_in_port(1)
match.set_dl_src(ryu.lib.mac.haddr_to_bin('00:00:00:00:00:01'))

OpenFlow Instructions and Actions

OpenFlow Instructions and Actions are defined in ryu.ofproto.ofproto_v1_3_parser.

OFPInstructionGotoTable

This instruction indicates the next table in the processing pipeline.

class OFPInstructionGotoTable(object):
    def __init__(self, table_id):
        super(OFPInstructionGotoTable, self).__init__()
        self.type = ofproto_v1_3.OFPIT_GOTO_TABLE
        self.len = ofproto_v1_3.OFP_INSTRUCTION_GOTO_TABLE_SIZE
        self.table_id = table_id
parameter description
table_id Next table

OFPInstructionWriteMetadata

This instruction writes the masked metadata value into the metadata field.

class OFPInstructionWriteMetadata(object):
    def __init__(self, metadata, metadata_mask):
        super(OFPInstructionWriteMetadata, self).__init__()
        self.type = ofproto_v1_3.OFPIT_WRITE_METADATA
        self.len = ofproto_v1_3.OFP_INSTRUCTION_WRITE_METADATA_SIZE
        self.metadata = metadata
        self.metadata_mask = metadata_mask
parameter description
metadata Metadata value to write
metadata_mask Metadata write bitmask

OFPInstructionAction

This instruction writes/applies/clears the actions.

class OFPInstructionActions(object):
    def __init__(self, type_, actions=None):
        super(OFPInstructionActions, self).__init__()
        self.type = type_
        self.actions = actions
parameter description
type_ One of following values
OFPIT_WRITE_ACTIONS
OFPIT_APPLY_ACTIONS
OFPIT_CLEAR_ACTIONS
actions An array of OpenFlow action class

OFPActionOutput

This action indicates output a packet to the switch port.

class OFPActionOutput(OFPAction):
    def __init__(self, port, max_len):
        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

OFPActionGroup

This action indicates the group used to process this packet.

class OFPActionGroup(OFPAction):
    def __init__(self, group_id):
        super(OFPActionGroup, self).__init__()
        self.group_id = group_id
parameter description
group_id Group identifier

OFPActionSetQueue

This action sets the queue id that will be used to map a flow to an already-configured queueu on a port.

class OFPActionSetQueue(OFPAction):
    def __init__(self, queue_id):
        super(OFPActionSetQueue, self).__init__()
        self.queue_id = queue_id
parameter description
queue_id Queue id for the packets

OFPActionSetMplsTtl

This action sets the MPLS TTL.

class OFPActionSetMplsTtl(OFPAction):
    def __init__(self, mpls_ttl):
        super(OFPActionSetMplsTtl, self).__init__()
        self.mpls_ttl = mpls_ttl
parameter description
mpls_ttl MPLS TTL

OFPActionDecMplsTtl

This action decrements the MPLS TTL.

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

OFPActionSetNwTtl

This action sets the IP TTL.

class OFPActionSetNwTtl(OFPAction):
    def __init__(self, nw_ttl):
        super(OFPActionSetNwTtl, self).__init__()
        self.nw_ttl = nw_ttl
parameter description
nw_ttl IP TTL

OFPActionDecNwTtl

This action decrements the IP TTL.

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

OFPActionCopyTtlOut

This action copies the TTL from the next-to-outermost header with TTL to the outermost header with TTL.

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

OFPActionCopyTtlIn

This action copies the TTL from the outermost header with TTL to the next-to-outermost header with TTL.

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

OFPActionPushVlan

This action pushes a new VLAN tag to the packet.

class OFPActionPushVlan(OFPAction):
    def __init__(self, ethertype):
        super(OFPActionPushVlan, self).__init__()
        self.ethertype = ethertype
parameter description
ethertype Ethertype

OFPActionPushMpls

This action pushes a new MPLS header to the packet.

class OFPActionPushMpls(OFPAction):
    def __init__(self, ethertype):
        super(OFPActionPushMpls, self).__init__()
        self.ethertype = ethertype
parameter description
ethertype Ethertype

OFPActionPopVlan

This action pops the outermost VLAN tag from the packet.

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

OFPActionPopMpls

This action pops the MPLS header from the packet.

class OFPActionPopMpls(OFPAction):
    def __init__(self, ethertype):
        super(OFPActionPopMpls, self).__init__()
        self.ethertype = ethertype
parameter description
ethertype Ethertype of the payload

OFPActionSetField

This action modifies a header field in the packet.

class OFPActionSetField(OFPAction):
    def __init__(self, field):
        super(OFPActionSetField, self).__init__()
        self.field = field
parameter description
field Instance of OFPMatchField

OFPActionExperimenter

This action is an extensible action for the experimenter.

class OFPActionExperimenter(OFPAction):
    def __init__(self, experimenter):
        super(OFPActionExperimenter, self).__init__()
        self.experimenter = experimenter
parameter description
experimenter Experimenter ID
Clone this wiki locally