diff options
author | Isaku Yamahata <yamahata@valinux.co.jp> | 2012-01-27 17:47:09 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2012-01-30 07:20:35 +0900 |
commit | 0bff34ca87af74b7eb13d9c996fd869172a7f0a4 (patch) | |
tree | a05ecf2989cf9a03ca806ff6580eca6b37c49836 | |
parent | 5ef02dfc55e816e0fa758b2386aab5fd66b2ae29 (diff) |
ofproto/ofproto_v1_0_parser: more parsers/serializers
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/ofproto/ofproto_v1_0_parser.py | 728 |
1 files changed, 717 insertions, 11 deletions
diff --git a/ryu/ofproto/ofproto_v1_0_parser.py b/ryu/ofproto/ofproto_v1_0_parser.py index d8664947..4d1e891b 100644 --- a/ryu/ofproto/ofproto_v1_0_parser.py +++ b/ryu/ofproto/ofproto_v1_0_parser.py @@ -1,5 +1,5 @@ # Copyright (C) 2011 Nippon Telegraph and Telephone Corporation. -# Copyright (C) 2011 Isaku Yamahata <yamahata at valinux co jp> +# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ _MSG_PARSERS = {} def _set_msg_type(msg_type): + '''Annotate corresponding OFP message type''' def _set_cls_msg_type(cls): cls.cls_msg_type = msg_type return cls @@ -48,6 +49,28 @@ def msg_parser(datapath, version, msg_type, msg_len, xid, buf): return parser(datapath, version, msg_type, msg_len, xid, buf) +# OFP_MSG_REPLY = { +# OFPFeaturesRequest: OFPSwitchFeatures, +# OFPBarrierRequest: OFPBarrierReplay, +# OFPQueueGetConfigRequest: OFPQueueGetConfigReply, +# +# # ofp_stats_request -> ofp_stats_reply +# OFPDescStatsRequest: OFPDescStatsReply, +# OFPFlowStatsRequest: OFPFlowStatsReply, +# OFPAggregateStatsRequest: OFPAggregateStatsReply, +# OFPTableStatsRequest: OFPTableStatsReply, +# OFPPortStatsRequest: OFPPortStatsReply, +# OFPQueueStatsRequest: OFPQueueStatsReply, +# OFPVendorStatsRequest: OFPVendorStatsReply, +# } +def _set_msg_reply(msg_reply): + '''Annotate OFP reply message class''' + def _set_cls_msg_reply(cls): + cls.cls_msg_reply = msg_reply + return cls + return _set_cls_msg_reply + + def _pack_into(fmt, buf, offset, *args): if len(buf) < offset: buf += bytearray().zfill(offset - len(buf)) @@ -115,30 +138,433 @@ class OFPMatch(collections.namedtuple('OFPMatchBase', ( class OFPActionHeader(object): - def __init__(self, type, len): - self.type = type - self.len = len + def __init__(self, type_, len_): + self.type = type_ + self.len = len_ def serlize(self, buf, offset): _pack_into(ofproto_v1_0.OFP_ACTION_HEADER_PACK_STR, buf, offset, self.type, self.len) -class OFPActionOutput(OFPActionHeader): +class OFPAction(OFPActionHeader): + _ACTION_TYPES = {} + + @staticmethod + def register_action_type(type_, len_): + def _register_action_type(cls): + cls.cls_action_type = type_ + cls.cls_action_len = len_ + OFPAction._ACTION_TYPES[cls.cls_action_type] = cls + return cls + return _register_action_type + + def __init__(self): + cls = self.__class__ + super(OFPAction, self).__init__(cls.cls_action_type, + cls.cls_action_len) + + @classmethod + def parser(cls, buf, offset): + type_, len_ = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_HEADER_PACK_STR, buf, offset) + offset += ofproto_v1_0.OFP_ACTION_HEADER_SIZE + return cls.parser(buf, offset) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_OUTPUT, + ofproto_v1_0.OFP_ACTION_OUTPUT_SIZE) +class OFPActionOutput(OFPAction): def __init__(self, port, max_len=0): - super(OFPActionOutput, - self).__init__(ofproto_v1_0.OFPAT_OUTPUT, - ofproto_v1_0.OFP_ACTION_OUTPUT_LEN) + super(OFPActionOutput, self).__init__() self.port = port self.max_len = max_len + @classmethod + def parser(cls, buf, offset): + type_, len_, port, max_len = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_OUTPUT_PACK_STR, buf, offset) + assert type_ == ofproto_v1_0.OFPAT_OUTPUT + assert len_ == ofproto_v1_0.OFP_ACTION_OUTPUT_SIZE + return cls(port, max_len) + def serialize(self, buf, offset): _pack_into(ofproto_v1_0.OFP_ACTION_OUTPUT_PACK_STR, buf, offset, self.type, self.len, self.port, self.max_len) -# TODO:XXX more actions +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_VLAN_VID, + ofproto_v1_0.OFP_ACTION_VLAN_VID_SIZE) +class OFPActionVlanVid(OFPAction): + def __init__(self, vlan_vid): + super(OFPActionVlanVid, self).__init__() + self.vlan_vid = vlan_vid + + @classmethod + def parser(cls, buf, offset): + type_, len_, vlan_vid = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_VLAN_VID_PACK_STR, buf, offset) + assert type_ == ofproto_v1_0.OFPAT_SET_VLAN_VID + assert len_ == ofproto_v1_0.OFP_ACTION_VLAN_VID_SIZE + return cls(vlan_vid) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_VLAN_VID_PACK_STR, + buf, offset, self.type, self.len, self.vlan_vid) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_VLAN_PCP, + ofproto_v1_0.OFP_ACTION_VLAN_PCP_SIZE) +class OFPActionVlanPcp(OFPAction): + def __init__(self, vlan_pcp): + super(OFPActionVlanPcp, self).__init__() + self.vlan_pcp = vlan_pcp + + @classmethod + def parser(cls, buf, offset): + type_, len_, vlan_pcp = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_VLAN_PCP_PACK_STR, buf, offset) + assert type_ == ofproto_v1_0.OFPAT_SET_VLAN_PCP + assert len_ == ofproto_v1_0.OFP_ACTION_VLAN_PCP_SIZE + return cls(vlan_pcp) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_VLAN_PCP_PACK_STR, + buf, offset, self.type, self.len, self.vlan_pcp) + + +class OFPActionDlAddr(OFPAction): + def __init__(self, dl_addr): + super(OFPActionDlAddr, self).__init__() + self.dl_addr = dl_addr + + @classmethod + def parser(cls, buf, offset): + type_, len_, dl_addr = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_DL_ADDR_PACK_STR, buf, offset) + assert type_ in (ofproto_v1_0.OFPAT_SET_DL_SRC, + ofproto_v1_0.OFPAT_SET_DL_DST) + assert len_ == ofproto_v1_0.OFP_ACTION_DL_ADDR_SIZE + return cls(dl_addr) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_DL_ADDR_PACK_STR, + buf, offset, self.type, self.len, self.dl_addr) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_DL_SRC, + ofproto_v1_0.OFP_ACTION_DL_ADDR_SIZE) +class OFPActionSetDlSrc(OFPActionDlAddr): + def __init__(self, dl_addr): + super(OFPActionSetDlSrc, self).__init__(dl_addr) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_DL_DST, + ofproto_v1_0.OFP_ACTION_DL_ADDR_SIZE) +class OFPActionSetDlDst(OFPActionDlAddr): + def __init__(self, dl_addr): + super(OFPActionSetDlDst, self).__init__(dl_addr) + + +class OFPActionNwAddr(OFPAction): + def __init__(self, nw_addr): + super(OFPActionNwAddr, self).__init__() + self.nw_addr = nw_addr + + @classmethod + def parser(cls, buf, offset): + type_, len_, nw_addr = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_NW_ADDR_PACK_STR, buf, offset) + assert type_ in (ofproto_v1_0.OFPAT_SET_NW_SRC, + ofproto_v1_0.OFPAT_SET_NW_DST) + assert len_ == ofproto_v1_0.OFP_ACTION_NW_ADDR_SIZE + return cls(nw_addr) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_NW_ADDR_PACK_STR, + buf, offset, self.type, self.len, self.nw_addr) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_NW_SRC, + ofproto_v1_0.OFP_ACTION_NW_ADDR_SIZE) +class OFPActionSetNwSrc(OFPActionNwAddr): + def __init__(self, nw_addr): + super(OFPActionSetNwSrc, self).__init__(nw_addr) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_NW_DST, + ofproto_v1_0.OFP_ACTION_NW_ADDR_SIZE) +class OFPActionSetNwDst(OFPActionNwAddr): + def __init__(self, nw_addr): + super(OFPActionSetNwDst, self).__init__(nw_addr) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_NW_TOS, + ofproto_v1_0.OFP_ACTION_NW_TOS_SIZE) +class OFPActionSetNwTos(OFPAction): + def __init__(self, tos): + super(OFPActionSetNwTos, self).__init__() + self.tos = tos + + @classmethod + def parser(cls, buf, offset): + type_, len_, tos = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_NW_TOS_PACK_STR, buf, offset) + assert type_ == ofproto_v1_0.OFPAT_SET_NW_TOS + assert len_ == ofproto_v1_0.OFP_ACTION_NW_TOS_SIZE + return cls(tos) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_NW_TOS_PACK_STR, + buf, offset, self.type, self.len, self.tos) + + +class OFPActionTpPort(OFPAction): + def __init__(self, tp): + super(OFPActionTpPort, self).__init__() + self.tp = tp + + @classmethod + def parser(cls, buf, offset): + type_, len_, tp = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_TP_PORT_PACK_STR, buf, offset) + assert type_ in (ofproto_v1_0.OFPAT_SET_TP_SRC, + ofproto_v1_0.OFPAT_SET_TP_DST) + assert len_ == ofproto_v1_0.OFP_ACTION_TP_PORT_SIZE + return cls(tp) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_TP_PORT_PACK_STR, + buf, offset, self.type, self.len, self.tp) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_TP_SRC, + ofproto_v1_0.OFP_ACTION_TP_PORT_SIZE) +class OFPActionSetTpSrc(OFPActionTpPort): + def __init__(self, tp): + super(OFPActionSetTpSrc, self).__init__(tp) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_SET_TP_DST, + ofproto_v1_0.OFP_ACTION_TP_PORT_SIZE) +class OFPActionSetTpDst(OFPActionTpPort): + def __init__(self, tp): + super(OFPActionSetTpDst, self).__init__(tp) + + +@OFPAction.register_action_type(ofproto_v1_0.OFPAT_ENQUEUE, + ofproto_v1_0.OFP_ACTION_ENQUEUE_SIZE) +class OFPActionEnqueue(OFPAction): + def __init__(self, port, queue_id): + super(OFPActionEnqueue, self).__init__() + self.port = port + self.queue_id = queue_id + + @classmethod + def parser(cls, buf, offset): + type_, len_, port, queue_id = struct.unpack_from( + ofproto_v1_0.OFP_ACTION_ENQUEUE_PACK_STR, buf, offset) + assert type_ == ofproto_v1_0.OFPAT_ENQUEUE + assert len_ == ofproto_v1_0.OFP_ACTION_ENQUEUE_SIZE + return cls(port, queue_id) + + def serialize(self, buf, offset): + _pack_into(ofproto_v1_0.OFP_ACTION_ENQUEUE_PACK_STR, + buf, offset, self.type, self.len, self.port, self.queue_id) + + +# TODO:XXX OFPActionVendor + + +class OFPDescStats(collections.namedtuple('OFPDescStats', + ('mfr_desc', 'hw_desc', 'sw_desc', 'serial_num', 'dp_desc'))): + @classmethod + def parser(cls, buf, offset): + desc = struct.unpack_from(ofproto_v1_0.OFP_DESC_STATS_PACK_STR, + buf, offset) + return cls(*desc) + + +class OFPFlowStats(object): + def __init__(self): + super(OFPFlowStats, self).__init__() + self.length = None + self.table_id = None + self.match = None + self.duration_sec = None + self.duration_nsec = None + self.priority = None + self.idle_timeout = None + self.hard_timeout = None + self.cookie = None + self.packet_count = None + self.byte_count = None + self.actions = None + + @classmethod + def parser(cls, buf, offset): + flow_stats = cls() + + flow_stats.length, flow_stats.table_id = struct.unpack( + ofproto_v1_0.OFP_FLOW_STATS_0_PACK_STR, buf, offset) + offset += ofproto_v1_0.OFP_FLOW_STATS_0_SIZE + + flow_stats.match = OFPMatch.parse(buf, offset) + offset += ofproto_v1_0.OFP_MATCH_SIZE + + (flow_stats.duration_sec, + flow_stats.duration_nsec, + flow_stats.priority, + flow_stats.idle_timeout, + flow_stats.hard_timeout, + flow_stats.cookie, + flow_stats.packet_count, + flow_stats.byte_conunt) = struct.unpack_from( + ofproto_v1_0.OFP_FLOW_STATS_1_PACK_STR, buf, offset) + + flow_stats.actions = [] + length = ofproto_v1_0.OFP_FLOW_STATS_SIZE + while length < flow_stats.length: + action = OFPAction.parser(buf, offset) + flow_stats.actions.append(action) + + offset += action.len + length += action.len + + return flow_stats + + +class OFPAggregateStats(collections.namedtuple('OFPAggregateStats', + ('packet_count', 'byte_count', 'flow_count'))): + @classmethod + def parser(cls, buf, offset): + agg = struct.unpack_from( + ofproto_v1_0.OFP_AGGREGATE_STATS_REPLY_PACK_STR, buf, offset) + return cls(*agg) + + +class OFPTableStats(collections.namedtuple('OFPTableStats', + ('table_id', 'name', 'wildcards', 'max_entries', 'active_count', + 'lookup_count', 'matched_count'))): + @classmethod + def parser(cls, buf, offset): + tbl = struct.unpack_from(ofproto_v1_0.OFP_TABLE_STATS_PACK_STR, + buf, offset) + return cls(*tbl) + + +class OFPPortStats(collections.namedtuple('OFPPortStats', + ('port_no', 'rx_packets', 'tx_packets', 'rx_bytes', 'tx_bytes', + 'rx_dropped', 'tx_dropped', 'rx_errors', 'tx_errors', + 'rx_frame_err', 'rx_over_err', 'rx_crc_err', 'collisions'))): + @classmethod + def parser(cls, buf, offset): + port = struct.unpack_from(ofproto_v1_0.OFP_PORT_STATS_PACK_STR, + buf, offset) + return cls(*port) + + +class OFPQueueStats(collections.namedtuple('OFPQueueStats', + ('port_no', 'queue_id', 'tx_bytes', 'tx_packets', 'tx_errors'))): + @classmethod + def parser(cls, buf, offset): + queue = struct.unpack_from(ofproto_v1_0.OFP_QUEUE_STATS_PACK_STR, + buf, offset) + return cls(*queue) + + +class OFPVendorStats(collections.namedtuple('OFPVendorStats', + ('specific_data'))): + @classmethod + def parser(cls, buf, offset): + return cls((buf[offset:], )) + + +class OFPQueuePropHeader(object): + _QUEUE_PROPERTIES = {} + + @staticmethod + def register_queue_property(prop_type, prop_len): + def _register_queue_propery(cls): + cls.cls_prop_type = prop_type + cls.cls_prop_len = prop_len + OFPQueuePropHeader._QUEUE_PROPERTIES[prop_type] = cls + return cls + return _register_queue_propery + + def __init__(self): + self.property = self.cls_prop_type + self.len = self.cls_prop_len + + def __str__(self): + buf = super(OFPQueuePropHeader, self).__str__() + return _str_attr(self, buf, ('property', 'len')) + + @classmethod + def parser(cls, buf, offset): + property_, len_ = struct.unpack_from( + ofproto_v1_0.OFP_QUEUE_PROP_HEADER_PACK_STR, buf, offset) + prop_cls = cls._QUEUEU_PROPERTIES[property_] + assert property_ == prop_cls.cls_prop_type + assert len_ == prop_cls.cls_prop_len + + offset += ofproto_v1_0.OFP_QUEUE_PROP_HEADER_SIZE + return prop_cls.parser(buf, offset) + + +@OFPQueuePropHeader.register_queue_property( + ofproto_v1_0.OFPQT_NONE, ofproto_v1_0.OFP_QUEUE_PROP_HEADER_SIZE) +class OFPQueuePropNone(OFPQueuePropHeader): + def __init__(self): + super(OFPQueuePropNone, self).__init__() + + @classmethod + def parser(cls, buf, offset): + return cls() + + +@OFPQueuePropHeader.register_queue_property( + ofproto_v1_0.OFPQT_MIN_RATE, ofproto_v1_0.OFP_QUEUE_PROP_MIN_RATE_SIZE) +class OFPQueuePropMinRate(OFPQueuePropHeader): + def __init__(self, rate): + super(OFPQueuePropMinRate, self).__init__() + self.rate = rate + + def __str__(self): + buf = super(OFPQueuePropMinRate, self).__str__() + return _str_attr(self, buf, ('rate')) + + @classmethod + def parser(cls, buf, offset): + rate = struct.pack_from(ofproto_v1_0.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, + buf, offset) + return cls(rate) + + +class OFPPacketQueue(object): + def __init__(self, queue_id, len_): + self.queue_id = queue_id + self.len = len_ + self.properties = None + + @classmethod + def parser(cls, buf, offset): + queue_id, len_ = struct.unpack_from( + ofproto_v1_0.OFP_PACKET_QUEUE_PQCK_STR, buf, offset) + packet_queue = cls(queue_id, len_) + + packet_queue.properties = [] + cur_len = ofproto_v1_0.OFP_PACKET_QUEUE_SIZE + offset += ofproto_v1_0.OFP_PACKET_QUEUE_SIZE + while (cur_len + ofproto_v1_0.OFP_QUEUE_PROP_HEADER_SIZE <= + packet_queue.len): + prop = OFPQueuePropHeader.parser(buf, offset) + offset.properties.append(prop) + + cur_len += prop.len + offset += prop.len + return packet_queue # # Symmetric messages @@ -223,6 +649,7 @@ class OFPVendor(MsgBase): def __init__(self, datapath): super(OFPVendor, self).__init__(datapath) self.data = None + self.vendor = None @classmethod def parser(cls, datapath, version, msg_type, msg_len, xid, buf): @@ -255,7 +682,7 @@ class OFPSwitchFeatures(MsgBase): def __str__(self): buf = super(OFPSwitchFeatures, self).__str__() + ' port' - for port_no, p in getattr(self, 'ports', {}).items(): + for _port_no, p in getattr(self, 'ports', {}).items(): buf += ' ' + str(p) return buf @@ -275,7 +702,7 @@ class OFPSwitchFeatures(MsgBase): n_ports = ((msg_len - ofproto_v1_0.OFP_SWITCH_FEATURES_SIZE) / ofproto_v1_0.OFP_PHY_PORT_SIZE) offset = ofproto_v1_0.OFP_SWITCH_FEATURES_SIZE - for i in range(n_ports): + for _i in range(n_ports): port = OFPPhyPort.parser(msg.buf, offset) # print 'port = %s' % str(port) msg.ports[port.port_no] = port @@ -383,12 +810,166 @@ class OFPFlowRemoved(MsgBase): return msg + +@_register_parser +@_set_msg_type(ofproto_v1_0.OFPT_QUEUE_GET_CONFIG_REPLY) +class OFPQueueGetConfigReply(MsgBase): + def __init__(self, datapath): + super(OFPQueueGetConfigReply, self).__init__(datapath) + + @classmethod + def parser(cls, datapath, version, msg_type, msg_len, xid, buf): + msg = super(OFPQueueGetConfigReply, cls).parser( + datapath, version, msg_type, msg_len, xid, buf) + + offset = ofproto_v1_0.OFP_HEADER_SIZE + msg.port = struct.unpack_from( + ofproto_v1_0.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf, offset) + + msg.queues = [] + offset = ofproto_v1_0.OFP_QUEUE_GET_CONFIG_REPLY_SIZE + while offset + ofproto_v1_0.OFP_PACKET_QUEUE_SIZE <= msg_len: + queue = OFPPacketQueue.parser(msg.buf, offset) + msg.queues.append(queue) + + offset += queue.len + + return msg + + +def _set_stats_type(stats_type, stats_body_cls): + def _set_cls_stats_type(cls): + cls.cls_stats_type = stats_type + cls.cls_stats_body_cls = stats_body_cls + return cls + return _set_cls_stats_type + + +@_register_parser +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPStatsReply(MsgBase): + _STATS_MSG_TYPES = {} + + @staticmethod + def register_stats_type(body_cls_size=0): + def _register_stats_type(cls): + assert cls.cls_stats_type is not None + assert cls.cls_stats_type not in OFPStatsReply._STATS_MSG_TYPES + assert cls.cls_stats_body_cls is not None + cls.cls_stats_body_cls_size = body_cls_size + OFPStatsReply._STATS_MSG_TYPES[cls.cls_stats_type] = cls + return cls + return _register_stats_type + + def __init__(self, datapath): + super(OFPStatsReply, self).__init__(datapath) + self.type = None + self.flags = None + self.body = None + + @classmethod + def parser_stats_body_array(cls, buf, msg_len, offset, entry_size): + body_cls = cls.cls_stats_body_cls + body = [] + while offset + entry_size <= msg_len: + entry = body_cls.parser(buf, offset) + body.append(entry) + offset += entry_size + return body + + @classmethod + def parser_stats_body(cls, buf, msg_len, offset): + if cls.cls_stats_body_cls_size == 0: + return cls.cls_stats_body_cls.parser(buf, offset) + + return cls.parser_stats_body_array(buf, msg_len, offset, + cls.cls_stats_body_cls_size) + + @classmethod + def parser_stats(cls, datapath, version, msg_type, msg_len, xid, buf): + # call MsgBase::parser, not OFPStatsReply::parser + msg = MsgBase.parser.__func__( + cls, datapath, version, msg_type, msg_len, xid, buf) + msg.body = msg.parser_stats_body(msg.buf, msg.msg_len, + ofproto_v1_0.OFP_STATS_MSG_SIZE) + return msg + + @classmethod + def parser(cls, datapath, version, msg_type, msg_len, xid, buf): + type_, flags = struct.unpack_from(ofproto_v1_0.OFP_STATS_MSG_PACK_STR, + buffer(buf), + ofproto_v1_0.OFP_HEADER_SIZE) + stats_type_cls = cls._STATS_MSG_TYPES.get(type_) + msg = stats_type_cls.parser_stats( + datapath, version, msg_type, msg_len, xid, buf) + msg.type = type_ + msg.flags = flags + return msg + + +@OFPStatsReply.register_stats_type() +@_set_stats_type(ofproto_v1_0.OFPST_DESC, OFPDescStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPDescStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPDescStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type(ofproto_v1_0.OFP_FLOW_STATS_SIZE) +@_set_stats_type(ofproto_v1_0.OFPST_FLOW, OFPFlowStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPFlowStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPFlowStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type(ofproto_v1_0.OFP_AGGREGATE_STATS_REPLY_SIZE) +@_set_stats_type(ofproto_v1_0.OFPST_AGGREGATE, OFPAggregateStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPAggregateStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPAggregateStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type(ofproto_v1_0.OFP_TABLE_STATS_SIZE) +@_set_stats_type(ofproto_v1_0.OFPST_TABLE, OFPTableStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPTableStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPTableStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type(ofproto_v1_0.OFP_PORT_STATS_SIZE) +@_set_stats_type(ofproto_v1_0.OFPST_PORT, OFPPortStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPPortStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPPortStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type(ofproto_v1_0.OFP_QUEUE_STATS_SIZE) +@_set_stats_type(ofproto_v1_0.OFPST_QUEUE, OFPQueueStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPQueueStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPQueueStatsReply, self).__init__(datapath) + + +@OFPStatsReply.register_stats_type() +@_set_stats_type(ofproto_v1_0.OFPST_VENDOR, OFPVendorStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REPLY) +class OFPVendorStatsReply(OFPStatsReply): + def __init__(self, datapath): + super(OFPVendorStatsReply, self).__init__(datapath) + + # # controller-to-switch message # serializer only # +@_set_msg_reply(OFPSwitchFeatures) @_set_msg_type(ofproto_v1_0.OFPT_FEATURES_REQUEST) class OFPFeaturesRequest(MsgBase): def __init__(self, datapath): @@ -485,7 +1066,132 @@ class OFPFlowMod(MsgBase): offset += a.len +@_set_msg_reply(OFPBarrierReply) @_set_msg_type(ofproto_v1_0.OFPT_BARRIER_REQUEST) class OFPBarrierRequest(MsgBase): def __init__(self, datapath): super(OFPBarrierRequest, self).__init__(datapath) + + +@_set_msg_reply(OFPQueueGetConfigReply) +@_set_msg_type(ofproto_v1_0.OFPT_QUEUE_GET_CONFIG_REQUEST) +class OFPQueueGetConfigRequest(MsgBase): + def __init__(self, datapath, port): + super(OFPQueueGetConfigRequest, self).__init__(datapath) + self.port = port + + def _serialize_body(self): + _pack_into(ofproto_v1_0.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR, + self.buf, ofproto_v1_0.OFP_HEADER_SIZE, self.port) + + +class OFPStatsRequest(MsgBase): + def __init__(self, datapath, flags): + assert flags == 0 # none yet defined + + super(OFPStatsRequest, self).__init__(datapath) + self.type = self.__class__.cls_stats_type + self.flags = flags + + def _serialize_stats_body(self): + pass + + def _serialize_body(self): + _pack_into(ofproto_v1_0.OFP_STATS_MSG_PACK_STR, + self.buf, ofproto_v1_0.OFP_HEADER_SIZE, + self.type, self.flags) + self._serialize_stats_body() + + +@_set_msg_reply(OFPDescStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_DESC, OFPDescStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPDescStatsRequest(OFPStatsRequest): + def __init__(self, datapath, flags): + super(OFPDescStatsRequest, self).__init__(datapath, flags) + + +class OFPFlowStatsRequestBase(OFPStatsRequest): + def __init__(self, datapath, flags, match, table_id, out_port): + super(OFPFlowStatsRequest. self).__init__(datapath, flags) + self.match = match + self.table_id = table_id + self.out_port = out_port + + def _serialize_stats_body(self): + offset = ofproto_v1_0.OFP_STATS_MSG_SIZE + self.match.serialize(self.buf, offset) + + offset += ofproto_v1_0.OFP_MATCH_SIZE + _pack_into(ofproto_v1_0.OFP_FLOW_STATS_REQUEST_ID_PORT_STR, + self.buf, offset, self.table_id, self.out_port) + + +@_set_msg_reply(OFPFlowStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_FLOW, OFPFlowStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPFlowStatsRequest(OFPFlowStatsRequestBase): + def __init__(self, datapath, flags, match, table_id, out_port): + super(OFPFlowStatsRequest, self).__init__( + datapath, flags, match, table_id, out_port) + + +@_set_msg_reply(OFPAggregateStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_AGGREGATE, OFPAggregateStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPAggregateStatsRequest(OFPFlowStatsRequestBase): + def __init__(self, datapath, flags, match, table_id, out_port): + super(OFPAggregateStatsRequest, self).__init__( + datapath, flags, match, table_id, out_port) + + +@_set_msg_reply(OFPTableStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_TABLE, OFPTableStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPTableStatsRequest(OFPStatsRequest): + def __init__(self, datapath, flags): + super(OFPTableStatsRequest, self).__init__(datapath, flags) + + +@_set_msg_reply(OFPPortStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_PORT, OFPPortStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPPortStatsRequest(OFPStatsRequest): + def __init__(self, datapath, flags, port_no): + super(OFPPortStatsRequest, self).__init__(datapath, flags) + self.port_no = port_no + + def _serialize_stats_body(self): + _pack_into(ofproto_v1_0.OFP_PORT_STATS_REQUEST_PACK_STR, + self.buf, ofproto_v1_0.OFP_STATS_MSG_SIZE, self.port_no) + + +@_set_msg_reply(OFPQueueStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_QUEUE, OFPQueueStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +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 + + def _serialize_stats_body(self): + _pack_into(ofproto_v1_0.OFP_QUEUE_STATS_REQUEST_PACK_STR, + self.buf, ofproto_v1_0.OFP_STATS_MSG_SIZE, + self.port_no, self.queue_id) + + +@_set_msg_reply(OFPVendorStatsReply) +@_set_stats_type(ofproto_v1_0.OFPST_VENDOR, OFPVendorStats) +@_set_msg_type(ofproto_v1_0.OFPT_STATS_REQUEST) +class OFPVendorStatsRequest(OFPStatsRequest): + def __init__(self, datapath, flags, vendor, specific_data): + super(OFPVendorStatsRequest, self).__init__(datapath, flags) + self.vendor = vendor + self.specific_data = specific_data + + def _serialize_stats_body(self): + _pack_into(ofproto_v1_0.OFP_VENDOR_STATS_MSG_PACK_STR, + self.buf, ofproto_v1_0.OFP_STATS_MSG_SIZE, + self.vendor) + self.buf += self.specific_data |