6b99b1408b
Ryu crashes when it finds an unknown match field in OFPMatch. Instead, Ryu should just ignore it and continue to parse. With this patch, Ryu uses OFPmatchField class for an unknown match field and continue to parse. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Tested-by: Simon Horman <horms@verge.net.au>
2374 lines
81 KiB
Python
2374 lines
81 KiB
Python
# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
|
|
# Copyright (C) 2012 Isaku Yamahata <yamahata at valinux co jp>
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import collections
|
|
import struct
|
|
import itertools
|
|
|
|
from ryu.lib import mac
|
|
from ryu import utils
|
|
from ofproto_parser import MsgBase, msg_pack_into, msg_str_attr
|
|
from . import ofproto_parser
|
|
from . import ofproto_v1_2
|
|
|
|
import logging
|
|
LOG = logging.getLogger('ryu.ofproto.ofproto_v1_2_parser')
|
|
|
|
_MSG_PARSERS = {}
|
|
|
|
|
|
def _set_msg_type(msg_type):
|
|
def _set_cls_msg_type(cls):
|
|
cls.cls_msg_type = msg_type
|
|
return cls
|
|
return _set_cls_msg_type
|
|
|
|
|
|
def _register_parser(cls):
|
|
'''class decorator to register msg parser'''
|
|
assert cls.cls_msg_type is not None
|
|
assert cls.cls_msg_type not in _MSG_PARSERS
|
|
_MSG_PARSERS[cls.cls_msg_type] = cls.parser
|
|
return cls
|
|
|
|
|
|
@ofproto_parser.register_msg_parser(ofproto_v1_2.OFP_VERSION)
|
|
def msg_parser(datapath, version, msg_type, msg_len, xid, buf):
|
|
parser = _MSG_PARSERS.get(msg_type)
|
|
return parser(datapath, version, msg_type, msg_len, xid, buf)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_HELLO)
|
|
class OFPHello(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPHello, self).__init__(datapath)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_ERROR)
|
|
class OFPErrorMsg(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPErrorMsg, self).__init__(datapath)
|
|
self.type = None
|
|
self.code = None
|
|
self.data = None
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPErrorMsg, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.type, msg.code = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ERROR_MSG_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
msg.data = msg.buf[ofproto_v1_2.OFP_ERROR_MSG_SIZE:]
|
|
return msg
|
|
|
|
def _serialize_body(self):
|
|
assert self.data is not None
|
|
msg_pack_into(ofproto_v1_2.OFP_ERROR_MSG_PACK_STR, self.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE, self.type, self.code)
|
|
self.buf += self.data
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_ECHO_REQUEST)
|
|
class OFPEchoRequest(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPEchoRequest, self).__init__(datapath)
|
|
self.data = None
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPEchoRequest, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.data = msg.buf[ofproto_v1_2.OFP_HEADER_SIZE:]
|
|
return msg
|
|
|
|
def _serialize_body(self):
|
|
assert self.data is not None
|
|
self.buf += self.data
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_ECHO_REPLY)
|
|
class OFPEchoReply(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPEchoReply, self).__init__(datapath)
|
|
self.data = None
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPEchoReply, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.data = msg.buf[ofproto_v1_2.OFP_HEADER_SIZE:]
|
|
return msg
|
|
|
|
def _serialize_body(self):
|
|
assert self.data is not None
|
|
self.buf += self.data
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_EXPERIMENTER)
|
|
class OFPExperimenter(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPExperimenter, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPExperimenter, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
(msg.experimenter, msg.exp_type) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_EXPERIMENTER_HEADER_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
return msg
|
|
|
|
|
|
class OFPPort(collections.namedtuple('OFPPort', (
|
|
'port_no', 'hw_addr', 'name', 'config', 'state', 'curr',
|
|
'advertised', 'supported', 'peer', 'curr_speed', 'max_speed'))):
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
port = struct.unpack_from(ofproto_v1_2.OFP_PORT_PACK_STR, buf, offset)
|
|
return cls(*port)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_FEATURES_REQUEST)
|
|
class OFPFeaturesRequest(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPFeaturesRequest, self).__init__(datapath)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_FEATURES_REPLY)
|
|
class OFPSwitchFeatures(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPSwitchFeatures, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPSwitchFeatures, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
(msg.datapath_id,
|
|
msg.n_buffers,
|
|
msg.n_tables,
|
|
msg.capabilities,
|
|
msg.reserved) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_SWITCH_FEATURES_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
msg.ports = {}
|
|
n_ports = ((msg_len - ofproto_v1_2.OFP_SWITCH_FEATURES_SIZE) /
|
|
ofproto_v1_2.OFP_PORT_SIZE)
|
|
offset = ofproto_v1_2.OFP_SWITCH_FEATURES_SIZE
|
|
for i in range(n_ports):
|
|
port = OFPPort.parser(msg.buf, offset)
|
|
msg.ports[port.port_no] = port
|
|
offset += ofproto_v1_2.OFP_PORT_SIZE
|
|
|
|
return msg
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_GET_CONFIG_REQUEST)
|
|
class OFPGetConfigRequest(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPGetConfigRequest, self).__init__(datapath)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_GET_CONFIG_REPLY)
|
|
class OFPGetConfigReply(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPGetConfigReply, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPGetConfigReply, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.flags, msg.miss_send_len = struct.unpack_from(
|
|
ofproto_v1_2.OFP_SWITCH_CONFIG_PACK_STR, buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
return msg
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_SET_CONFIG)
|
|
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
|
|
|
|
def _serialize_body(self):
|
|
assert self.flags is not None
|
|
assert self.miss_send_len is not None
|
|
msg_pack_into(ofproto_v1_2.OFP_SWITCH_CONFIG_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.flags, self.miss_send_len)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_PACKET_IN)
|
|
class OFPPacketIn(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPPacketIn, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPPacketIn, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
(msg.buffer_id, msg.total_len, msg.reason,
|
|
msg.table_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_PACKET_IN_PACK_STR,
|
|
msg.buf, ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
msg.match = OFPMatch.parser(msg.buf, ofproto_v1_2.OFP_PACKET_IN_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
|
|
match_len = utils.round_up(msg.match.length, 8)
|
|
msg.data = msg.buf[(ofproto_v1_2.OFP_PACKET_IN_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE + match_len + 2):]
|
|
|
|
if msg.total_len < len(msg.data):
|
|
# discard padding for 8-byte alignment of OFP packet
|
|
msg.data = msg.data[:msg.total_len]
|
|
|
|
return msg
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_FLOW_REMOVED)
|
|
class OFPFlowRemoved(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPFlowRemoved, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPFlowRemoved, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
|
|
(msg.cookie, msg.priority, msg.reason,
|
|
msg.table_id, msg.duration_sec, msg.duration_nsec,
|
|
msg.idle_timeout, msg.hard_timeout, msg.packet_count,
|
|
msg.byte_count) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_FLOW_REMOVED_PACK_STR0,
|
|
msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
offset = (ofproto_v1_2.OFP_FLOW_REMOVED_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
|
|
msg.match = OFPMatch.parser(buf, offset)
|
|
|
|
return msg
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_PORT_STATUS)
|
|
class OFPPortStatus(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPPortStatus, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPPortStatus, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.reason = struct.unpack_from(
|
|
ofproto_v1_2.OFP_PORT_STATUS_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)[0]
|
|
msg.desc = OFPPort.parser(msg.buf,
|
|
ofproto_v1_2.OFP_PORT_STATUS_DESC_OFFSET)
|
|
return msg
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_PACKET_OUT)
|
|
class OFPPacketOut(MsgBase):
|
|
def __init__(self, datapath, buffer_id=None, in_port=None, actions=None,
|
|
data=None):
|
|
|
|
# The in_port field is the ingress port that must be associated
|
|
# with the packet for OpenFlow processing.
|
|
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
|
|
|
|
def _serialize_body(self):
|
|
self.actions_len = 0
|
|
offset = ofproto_v1_2.OFP_PACKET_OUT_SIZE
|
|
for a in self.actions:
|
|
a.serialize(self.buf, offset)
|
|
offset += a.len
|
|
self.actions_len += a.len
|
|
|
|
if self.data is not None:
|
|
assert self.buffer_id == 0xffffffff
|
|
self.buf += self.data
|
|
|
|
msg_pack_into(ofproto_v1_2.OFP_PACKET_OUT_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.buffer_id, self.in_port, self.actions_len)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_FLOW_MOD)
|
|
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
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_FLOW_MOD_PACK_STR0, self.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.cookie, self.cookie_mask, self.table_id,
|
|
self.command, self.idle_timeout, self.hard_timeout,
|
|
self.priority, self.buffer_id, self.out_port,
|
|
self.out_group, self.flags)
|
|
|
|
offset = (ofproto_v1_2.OFP_FLOW_MOD_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
|
|
match_len = self.match.serialize(self.buf, offset)
|
|
offset += match_len
|
|
|
|
for inst in self.instructions:
|
|
inst.serialize(self.buf, offset)
|
|
offset += inst.len
|
|
|
|
|
|
class OFPInstruction(object):
|
|
_INSTRUCTION_TYPES = {}
|
|
|
|
@staticmethod
|
|
def register_instruction_type(types):
|
|
def _register_instruction_type(cls):
|
|
for type_ in types:
|
|
OFPInstruction._INSTRUCTION_TYPES[type_] = cls
|
|
return cls
|
|
return _register_instruction_type
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from('!HH', buf, offset)
|
|
cls_ = cls._INSTRUCTION_TYPES.get(type_)
|
|
return cls_.parser(buf, offset)
|
|
|
|
|
|
@OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_GOTO_TABLE])
|
|
class OFPInstructionGotoTable(object):
|
|
def __init__(self, table_id):
|
|
super(OFPInstructionGotoTable, self).__init__()
|
|
self.type = ofproto_v1_2.OFPIT_GOTO_TABLE
|
|
self.len = ofproto_v1_2.OFP_INSTRUCTION_GOTO_TABLE_SIZE
|
|
self.table_id = table_id
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, table_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
|
|
buf, offset)
|
|
return cls(table_id)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_INSTRUCTION_GOTO_TABLE_PACK_STR,
|
|
buf, offset, self.type, self.len, self.table_id)
|
|
|
|
|
|
@OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_WRITE_METADATA])
|
|
class OFPInstructionWriteMetadata(object):
|
|
def __init__(self, metadata, metadata_mask):
|
|
super(OFPInstructionWriteMetadata, self).__init__()
|
|
self.type = ofproto_v1_2.OFPIT_WRITE_METADATA
|
|
self.len = ofproto_v1_2.OFP_INSTRUCTION_WRITE_METADATA_SIZE
|
|
self.metadata = metadata
|
|
self.metadata_mask = metadata_mask
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, metadata, metadata_mask) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
|
|
buf, offset)
|
|
return cls(metadata, metadata_mask)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_INSTRUCTION_WRITE_METADATA_PACK_STR,
|
|
buf, offset, self.type, self.len, self.metadata,
|
|
self.metadata_mask)
|
|
|
|
|
|
@OFPInstruction.register_instruction_type([ofproto_v1_2.OFPIT_WRITE_ACTIONS,
|
|
ofproto_v1_2.OFPIT_APPLY_ACTIONS,
|
|
ofproto_v1_2.OFPIT_CLEAR_ACTIONS])
|
|
class OFPInstructionActions(object):
|
|
def __init__(self, type_, actions=None):
|
|
super(OFPInstructionActions, self).__init__()
|
|
self.type = type_
|
|
self.actions = actions
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_PACK_STR,
|
|
buf, offset)
|
|
|
|
offset += ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_SIZE
|
|
actions = []
|
|
actions_len = len_ - ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_SIZE
|
|
while actions_len > 0:
|
|
a = OFPAction.parser(buf, offset)
|
|
actions.append(a)
|
|
actions_len -= a.len
|
|
offset += a.len
|
|
|
|
inst = cls(type_, actions)
|
|
inst.len = len_
|
|
return inst
|
|
|
|
def serialize(self, buf, offset):
|
|
action_offset = offset + ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_SIZE
|
|
if self.actions:
|
|
for a in self.actions:
|
|
a.serialize(buf, action_offset)
|
|
action_offset += a.len
|
|
|
|
self.len = action_offset - offset
|
|
pad_len = utils.round_up(self.len, 8) - self.len
|
|
ofproto_parser.msg_pack_into("%dx" % pad_len, buf, action_offset)
|
|
self.len += pad_len
|
|
|
|
msg_pack_into(ofproto_v1_2.OFP_INSTRUCTION_ACTIONS_PACK_STR,
|
|
buf, offset, self.type, self.len)
|
|
|
|
|
|
class OFPActionHeader(object):
|
|
def __init__(self, type_, len_):
|
|
self.type = type_
|
|
self.len = len_
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR,
|
|
buf, offset, self.type, self.len)
|
|
|
|
|
|
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_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
cls_ = cls._ACTION_TYPES.get(type_)
|
|
assert cls_ is not None
|
|
return cls_.parser(buf, offset)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf,
|
|
offset, self.type, self.len)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_OUTPUT,
|
|
ofproto_v1_2.OFP_ACTION_OUTPUT_SIZE)
|
|
class OFPActionOutput(OFPAction):
|
|
def __init__(self, port, max_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_2.OFP_ACTION_OUTPUT_PACK_STR, buf, offset)
|
|
return cls(port, max_len)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_OUTPUT_PACK_STR, buf,
|
|
offset, self.type, self.len, self.port, self.max_len)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_GROUP,
|
|
ofproto_v1_2.OFP_ACTION_GROUP_SIZE)
|
|
class OFPActionGroup(OFPAction):
|
|
def __init__(self, group_id):
|
|
super(OFPActionGroup, self).__init__()
|
|
self.group_id = group_id
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, group_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_GROUP_PACK_STR, buf, offset)
|
|
return cls(group_id)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_GROUP_PACK_STR, buf,
|
|
offset, self.type, self.len, self.group_id)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_SET_QUEUE,
|
|
ofproto_v1_2.OFP_ACTION_SET_QUEUE_SIZE)
|
|
class OFPActionSetQueue(OFPAction):
|
|
def __init__(self, queue_id):
|
|
super(OFPActionSetQueue, self).__init__()
|
|
self.queue_id = queue_id
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, queue_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_SET_QUEUE_PACK_STR, buf, offset)
|
|
return cls(queue_id)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_SET_QUEUE_PACK_STR, buf,
|
|
offset, self.type, self.len, self.queue_id)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_SET_MPLS_TTL,
|
|
ofproto_v1_2.OFP_ACTION_MPLS_TTL_SIZE)
|
|
class OFPActionSetMplsTtl(OFPAction):
|
|
def __init__(self, mpls_ttl):
|
|
super(OFPActionSetMplsTtl, self).__init__()
|
|
self.mpls_ttl = mpls_ttl
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, mpls_ttl) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_MPLS_TTL_PACK_STR, buf, offset)
|
|
return cls(mpls_ttl)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_MPLS_TTL_PACK_STR, buf,
|
|
offset, self.type, self.len, self.mpls_ttl)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_DEC_MPLS_TTL,
|
|
ofproto_v1_2.OFP_ACTION_HEADER_SIZE)
|
|
class OFPActionDecMplsTtl(OFPAction):
|
|
def __init__(self):
|
|
super(OFPActionDecMplsTtl, self).__init__()
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
return cls()
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_SET_NW_TTL,
|
|
ofproto_v1_2.OFP_ACTION_NW_TTL_SIZE)
|
|
class OFPActionSetNwTtl(OFPAction):
|
|
def __init__(self, nw_ttl):
|
|
super(OFPActionSetNwTtl, self).__init__()
|
|
self.nw_ttl = nw_ttl
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, nw_ttl) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_NW_TTL_PACK_STR, buf, offset)
|
|
return cls(nw_ttl)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_NW_TTL_PACK_STR, buf, offset,
|
|
self.type, self.len, self.nw_ttl)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_DEC_NW_TTL,
|
|
ofproto_v1_2.OFP_ACTION_HEADER_SIZE)
|
|
class OFPActionDecNwTtl(OFPAction):
|
|
def __init__(self):
|
|
super(OFPActionDecNwTtl, self).__init__()
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
return cls()
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_COPY_TTL_OUT,
|
|
ofproto_v1_2.OFP_ACTION_HEADER_SIZE)
|
|
class OFPActionCopyTtlOut(OFPAction):
|
|
def __init__(self):
|
|
super(OFPActionCopyTtlOut, self).__init__()
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
return cls()
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_COPY_TTL_IN,
|
|
ofproto_v1_2.OFP_ACTION_HEADER_SIZE)
|
|
class OFPActionCopyTtlIn(OFPAction):
|
|
def __init__(self):
|
|
super(OFPActionCopyTtlIn, self).__init__()
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
return cls()
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_PUSH_VLAN,
|
|
ofproto_v1_2.OFP_ACTION_PUSH_SIZE)
|
|
class OFPActionPushVlan(OFPAction):
|
|
def __init__(self, ethertype):
|
|
super(OFPActionPushVlan, self).__init__()
|
|
self.ethertype = ethertype
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, ethertype) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_PUSH_PACK_STR, buf, offset)
|
|
return cls(ethertype)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_PUSH_PACK_STR, buf, offset,
|
|
self.type, self.len, self.ethertype)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_PUSH_MPLS,
|
|
ofproto_v1_2.OFP_ACTION_PUSH_SIZE)
|
|
class OFPActionPushMpls(OFPAction):
|
|
def __init__(self, ethertype):
|
|
super(OFPActionPushMpls, self).__init__()
|
|
self.ethertype = ethertype
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, ethertype) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_PUSH_PACK_STR, buf, offset)
|
|
return cls(ethertype)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_PUSH_PACK_STR, buf, offset,
|
|
self.type, self.len, self.ethertype)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_POP_VLAN,
|
|
ofproto_v1_2.OFP_ACTION_HEADER_SIZE)
|
|
class OFPActionPopVlan(OFPAction):
|
|
def __init__(self):
|
|
super(OFPActionPopVlan, self).__init__()
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_HEADER_PACK_STR, buf, offset)
|
|
return cls()
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_POP_MPLS,
|
|
ofproto_v1_2.OFP_ACTION_POP_MPLS_SIZE)
|
|
class OFPActionPopMpls(OFPAction):
|
|
def __init__(self, ethertype):
|
|
super(OFPActionPopMpls, self).__init__()
|
|
self.ethertype = ethertype
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, ethertype) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset)
|
|
return cls(ethertype)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_POP_MPLS_PACK_STR, buf, offset,
|
|
self.type, self.len, self.ethertype)
|
|
|
|
|
|
@OFPAction.register_action_type(ofproto_v1_2.OFPAT_SET_FIELD,
|
|
ofproto_v1_2.OFP_ACTION_SET_FIELD_SIZE)
|
|
class OFPActionSetField(OFPAction):
|
|
def __init__(self, field):
|
|
super(OFPActionSetField, self).__init__()
|
|
self.field = field
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_) = struct.unpack_from('!HH', buf, offset)
|
|
field = OFPMatchField.parser(buf, offset + 4)
|
|
action = cls(field)
|
|
action.len = len_
|
|
return action
|
|
|
|
def serialize(self, buf, offset):
|
|
len_ = ofproto_v1_2.OFP_ACTION_SET_FIELD_SIZE + self.field.oxm_len()
|
|
self.len = utils.round_up(len_, 8)
|
|
pad_len = self.len - len_
|
|
|
|
msg_pack_into('!HH', buf, offset, self.type, self.len)
|
|
self.field.serialize(buf, offset + 4)
|
|
offset += len_
|
|
ofproto_parser.msg_pack_into("%dx" % pad_len, buf, offset)
|
|
|
|
|
|
@OFPAction.register_action_type(
|
|
ofproto_v1_2.OFPAT_EXPERIMENTER,
|
|
ofproto_v1_2.OFP_ACTION_EXPERIMENTER_HEADER_SIZE)
|
|
class OFPActionExperimenter(OFPAction):
|
|
def __init__(self, experimenter):
|
|
super(OFPActionExperimenter, self).__init__()
|
|
self.experimenter = experimenter
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(type_, len_, experimenter) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR, buf, offset)
|
|
return cls(experimenter)
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_ACTION_EXPERIMENTER_HEADER_PACK_STR,
|
|
buf, offset, self.type, self.len, self.experimenter)
|
|
|
|
|
|
class OFPBucket(object):
|
|
def __init__(self, len_, weight, watch_port, watch_group, actions):
|
|
super(OFPBucket, self).__init__()
|
|
self.len = len_
|
|
self.weight = weight
|
|
self.watch_port = watch_port
|
|
self.watch_group = watch_group
|
|
self.actions = actions
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(len_, weigth, watch_port, watch_group) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_BUCKET_PACK_STR, buf, offset)
|
|
|
|
length = ofproto_v1_2.OFP_BUCKET_SIZE
|
|
offset += ofproto_v1_2.OFP_BUCKET_SIZE
|
|
actions = []
|
|
while length < len_:
|
|
action = OFPAction.parser(buf, offset)
|
|
actions.append(action)
|
|
offset += action.len
|
|
length += action.len
|
|
|
|
return cls(len_, weigth, watch_port, watch_group, actions)
|
|
|
|
def serialize(self, buf, offset):
|
|
action_offset = offset + ofproto_v1_2.OFP_BUCKET_SIZE
|
|
action_len = 0
|
|
for a in self.actions:
|
|
a.serialize(buf, action_offset)
|
|
action_offset += a.len
|
|
action_len += a.len
|
|
|
|
self.len = utils.round_up(ofproto_v1_2.OFP_BUCKET_SIZE + action_len,
|
|
8)
|
|
msg_pack_into(ofproto_v1_2.OFP_BUCKET_PACK_STR, buf, offset,
|
|
self.len, self.weight, self.watch_port, self.watch_group)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_GROUP_MOD)
|
|
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
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_GROUP_MOD_PACK_STR, self.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.command, self.type, self.group_id)
|
|
|
|
offset = ofproto_v1_2.OFP_GROUP_MOD_SIZE
|
|
for b in self.buckets:
|
|
b.serialize(self.buf, offset)
|
|
offset += b.len
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_PORT_MOD)
|
|
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
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_PORT_MOD_PACK_STR, self.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.port_no, self.hw_addr, self.config,
|
|
self.mask, self.advertise)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_TABLE_MOD)
|
|
class OFPTableMod(MsgBase):
|
|
def __init__(self, datapath, table_id, config):
|
|
super(OFPTableMod, self).__init__(datapath)
|
|
self.table_id = table_id
|
|
self.config = config
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_TABLE_MOD_PACK_STR, self.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.table_id, self.config)
|
|
|
|
|
|
class OFPStatsRequest(MsgBase):
|
|
def __init__(self, datapath, type_):
|
|
super(OFPStatsRequest, self).__init__(datapath)
|
|
self.type = type_
|
|
self.flags = 0
|
|
|
|
def _serialize_stats_body(self):
|
|
pass
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_STATS_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.type, self.flags)
|
|
|
|
self._serialize_stats_body()
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REPLY)
|
|
class OFPStatsReply(MsgBase):
|
|
_STATS_TYPES = {}
|
|
|
|
@staticmethod
|
|
def register_stats_reply_type(type_, body_single_struct=False):
|
|
def _register_stats_reply_type(cls):
|
|
OFPStatsReply._STATS_TYPES[type_] = cls
|
|
cls.cls_body_single_struct = body_single_struct
|
|
return cls
|
|
return _register_stats_reply_type
|
|
|
|
def __init__(self, datapath):
|
|
super(OFPStatsReply, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPStatsReply, cls).parser(datapath, version, msg_type,
|
|
msg_len, xid, buf)
|
|
msg.type, msg.flags = struct.unpack_from(
|
|
ofproto_v1_2.OFP_STATS_REPLY_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
stats_type_cls = cls._STATS_TYPES.get(msg.type)
|
|
|
|
offset = ofproto_v1_2.OFP_STATS_REPLY_SIZE
|
|
body = []
|
|
while offset < msg_len:
|
|
r = stats_type_cls.parser(msg.buf, offset)
|
|
body.append(r)
|
|
offset += r.length
|
|
|
|
if stats_type_cls.cls_body_single_struct:
|
|
msg.body = body[0]
|
|
else:
|
|
msg.body = body
|
|
|
|
return msg
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPDescStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath):
|
|
super(OFPDescStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_DESC)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_DESC,
|
|
body_single_struct=True)
|
|
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_2.OFP_DESC_STATS_PACK_STR,
|
|
buf, offset)
|
|
stats = cls(*desc)
|
|
stats.length = ofproto_v1_2.OFP_DESC_STATS_SIZE
|
|
return stats
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPFlowStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath, table_id, out_port, out_group,
|
|
cookie, cookie_mask, match):
|
|
super(OFPFlowStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_FLOW)
|
|
self.table_id = table_id
|
|
self.out_port = out_port
|
|
self.out_group = out_group
|
|
self.cookie = cookie
|
|
self.cookie_mask = cookie_mask
|
|
self.match = match
|
|
|
|
def _serialize_stats_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_FLOW_STATS_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
|
|
self.table_id, self.out_port, self.out_group,
|
|
self.cookie, self.cookie_mask)
|
|
|
|
offset = (ofproto_v1_2.OFP_STATS_REQUEST_SIZE +
|
|
ofproto_v1_2.OFP_FLOW_STATS_REQUEST_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
|
|
self.match.serialize(self.buf, offset)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_FLOW)
|
|
class OFPFlowStats(object):
|
|
def __init__(self, length, table_id, duration_sec, duration_nsec,
|
|
priority, idle_timeout, hard_timeout, cookie, packet_count,
|
|
byte_count, match, instructions=None):
|
|
super(OFPFlowStats, self).__init__()
|
|
self.length = length
|
|
self.table_id = table_id
|
|
self.duration_sec = duration_sec
|
|
self.duration_nsec = duration_nsec
|
|
self.priority = priority
|
|
self.idle_timeout = idle_timeout
|
|
self.hard_timeout = hard_timeout
|
|
self.cookie = cookie
|
|
self.packet_count = packet_count
|
|
self.byte_count = byte_count
|
|
self.match = match
|
|
self.instructions = instructions
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(length, table_id, duration_sec,
|
|
duration_nsec, priority,
|
|
idle_timeout, hard_timeout,
|
|
cookie, packet_count, byte_count) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_FLOW_STATS_PACK_STR,
|
|
buf, offset)
|
|
offset += (ofproto_v1_2.OFP_FLOW_STATS_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
match = OFPMatch.parser(buf, offset)
|
|
|
|
match_length = utils.round_up(match.length, 8)
|
|
inst_length = (length - (ofproto_v1_2.OFP_FLOW_STATS_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE + match_length))
|
|
offset += match_length
|
|
instructions = []
|
|
while inst_length > 0:
|
|
inst = OFPInstruction.parser(buf, offset)
|
|
instructions.append(inst)
|
|
offset += inst.len
|
|
inst_length -= inst.len
|
|
|
|
return cls(length, table_id, duration_sec, duration_nsec, priority,
|
|
idle_timeout, hard_timeout, cookie, packet_count,
|
|
byte_count, match, instructions)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPAggregateStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath, table_id, out_port, out_group,
|
|
cookie, cookie_mask, match):
|
|
super(OFPAggregateStatsRequest, self).__init__(
|
|
datapath,
|
|
ofproto_v1_2.OFPST_AGGREGATE)
|
|
self.table_id = table_id
|
|
self.out_port = out_port
|
|
self.out_group = out_group
|
|
self.cookie = cookie
|
|
self.cookie_mask = cookie_mask
|
|
self.match = match
|
|
|
|
def _serialize_stats_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_AGGREGATE_STATS_REQUEST_PACK_STR,
|
|
self.buf,
|
|
ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
|
|
self.table_id, self.out_port, self.out_group,
|
|
self.cookie, self.cookie_mask)
|
|
|
|
offset = (ofproto_v1_2.OFP_STATS_REQUEST_SIZE +
|
|
ofproto_v1_2.OFP_AGGREGATE_STATS_REQUEST_SIZE -
|
|
ofproto_v1_2.OFP_MATCH_SIZE)
|
|
|
|
self.match.serialize(self.buf, offset)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_AGGREGATE,
|
|
body_single_struct=True)
|
|
class OFPAggregateStatsReply(collections.namedtuple('OFPAggregateStats',
|
|
('packet_count', 'byte_count', 'flow_count'))):
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
desc = struct.unpack_from(
|
|
ofproto_v1_2.OFP_AGGREGATE_STATS_REPLY_PACK_STR,
|
|
buf, offset)
|
|
stats = cls(*desc)
|
|
stats.length = ofproto_v1_2.OFP_AGGREGATE_STATS_REPLY_SIZE
|
|
return stats
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPTableStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath):
|
|
super(OFPTableStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_TABLE)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_TABLE)
|
|
class OFPTableStats(
|
|
collections.namedtuple('OFPTableStats',
|
|
('table_id', 'name', 'match', 'wildcards',
|
|
'write_actions', 'apply_actions',
|
|
'write_setfields', 'apply_setfields',
|
|
'metadata_match', 'metadata_write',
|
|
'instructions', 'config',
|
|
'max_entries', 'active_count',
|
|
'lookup_count', 'matched_count'))):
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
table = struct.unpack_from(
|
|
ofproto_v1_2.OFP_TABLE_STATS_PACK_STR,
|
|
buf, offset)
|
|
stats = cls(*table)
|
|
stats.length = ofproto_v1_2.OFP_TABLE_STATS_SIZE
|
|
return stats
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPPortStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath, port_no):
|
|
super(OFPPortStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_PORT)
|
|
self.port_no = port_no
|
|
|
|
def _serialize_stats_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_PORT_STATS_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
|
|
self.port_no)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_PORT)
|
|
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_2.OFP_PORT_STATS_PACK_STR,
|
|
buf, offset)
|
|
stats = cls(*port)
|
|
stats.length = ofproto_v1_2.OFP_PORT_STATS_SIZE
|
|
return stats
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPQueueStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath, port_no, queue_id):
|
|
super(OFPQueueStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_QUEUE)
|
|
self.port_no = port_no
|
|
self.queue_id = queue_id
|
|
|
|
def _serialize_stats_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_QUEUE_STATS_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
|
|
self.port_no, self.queue_id)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_QUEUE)
|
|
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_2.OFP_QUEUE_STATS_PACK_STR,
|
|
buf, offset)
|
|
stats = cls(*queue)
|
|
stats.length = ofproto_v1_2.OFP_QUEUE_STATS_SIZE
|
|
return stats
|
|
|
|
|
|
class OFPBucketCounter(object):
|
|
def __init__(self, packet_count, byte_count):
|
|
super(OFPBucketCounter, self).__init__()
|
|
self.packet_count = packet_count
|
|
self.byte_count = byte_count
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
packet, byte = struct.unpack_from(
|
|
ofproto_v1_2.OFP_BUCKET_COUNTER_PACK_STR,
|
|
buf, offset)
|
|
return cls(packet, byte)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPGroupStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath, group_id):
|
|
super(OFPGroupStatsRequest, self).__init__(datapath,
|
|
ofproto_v1_2.OFPST_GROUP)
|
|
self.group_id = group_id
|
|
|
|
def _serialize_stats_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_GROUP_STATS_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_STATS_REQUEST_SIZE,
|
|
self.group_id)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP)
|
|
class OFPGroupStats(object):
|
|
def __init__(self, length, group_id, ref_count, packet_count,
|
|
byte_count, bucket_counters):
|
|
super(OFPGroupStats, self).__init__()
|
|
self.length = length
|
|
self.group_id = group_id
|
|
self.ref_count = ref_count
|
|
self.packet_count = packet_count
|
|
self.byte_count = byte_count
|
|
self.bucket_counters = bucket_counters
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(length, group_id, ref_count, packet_count,
|
|
byte_count) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_GROUP_STATS_PACK_STR,
|
|
buf, offset)
|
|
|
|
bucket_len = length - ofproto_v1_2.OFP_GROUP_STATS_SIZE
|
|
offset += ofproto_v1_2.OFP_GROUP_STATS_SIZE
|
|
bucket_counters = []
|
|
while bucket_len > 0:
|
|
bucket_counters.append(OFPBucketCounter.parser(buf, offset))
|
|
offset += ofproto_v1_2.OFP_BUCKET_COUNTER_SIZE
|
|
bucket_len -= ofproto_v1_2.OFP_BUCKET_COUNTER_SIZE
|
|
|
|
return cls(length, group_id, ref_count, packet_count,
|
|
byte_count, bucket_counters)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPGroupDescStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath):
|
|
super(OFPGroupDescStatsRequest, self).__init__(
|
|
datapath,
|
|
ofproto_v1_2.OFPST_GROUP_DESC)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP_DESC)
|
|
class OFPGroupDescStats(object):
|
|
def __init__(self, length, type_, group_id, buckets):
|
|
self.length = length
|
|
self.type = type_
|
|
self.group_id = group_id
|
|
self.buckets = buckets
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(length, type_, group_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_GROUP_DESC_STATS_PACK_STR,
|
|
buf, offset)
|
|
|
|
bucket_len = length - ofproto_v1_2.OFP_GROUP_DESC_STATS_SIZE
|
|
offset += ofproto_v1_2.OFP_GROUP_DESC_STATS_SIZE
|
|
buckets = []
|
|
while bucket_len > 0:
|
|
buckets.append(OFPBucket.parser(buf, offset))
|
|
offset += ofproto_v1_2.OFP_BUCKET_SIZE
|
|
bucket_len -= ofproto_v1_2.OFP_BUCKET_SIZE
|
|
|
|
return cls(length, type_, group_id, buckets)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_STATS_REQUEST)
|
|
class OFPGroupFeaturesStatsRequest(OFPStatsRequest):
|
|
def __init__(self, datapath):
|
|
super(OFPGroupFeaturesStatsRequest, self).__init__(
|
|
datapath,
|
|
ofproto_v1_2.OFPST_GROUP_FEATURES)
|
|
|
|
|
|
@OFPStatsReply.register_stats_reply_type(ofproto_v1_2.OFPST_GROUP_FEATURES,
|
|
body_single_struct=True)
|
|
class OFPGroupFeaturesStats(object):
|
|
def __init__(self, types, capabilities, max_groups, actions):
|
|
self.types = types
|
|
self.capabilities = capabilities
|
|
self.max_groups = max_groups
|
|
self.actions = actions
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
stats = struct.unpack_from(
|
|
ofproto_v1_2.OFP_GROUP_FEATURES_STATS_PACK_STR, buf, offset)
|
|
types = stats[0]
|
|
capabilities = stats[1]
|
|
max_groups = stats[2:6]
|
|
actions = stats[6:10]
|
|
|
|
return cls(types, capabilities, max_groups, actions)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.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):
|
|
msg_pack_into(ofproto_v1_2.OFP_QUEUE_GET_CONFIG_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_HEADER_SIZE, self.port)
|
|
|
|
|
|
class OFPQueuePropHeader(object):
|
|
def __init__(self, property_, len_):
|
|
self.property = property_
|
|
self.len = len_
|
|
|
|
def serialize(self, buf, offset):
|
|
msg_pack_into(ofproto_v1_2.OFP_QUEUE_PROP_HEADER_PACK_STR,
|
|
buf, offset, self.property, self.len)
|
|
|
|
|
|
class OFPQueueProp(OFPQueuePropHeader):
|
|
_QUEUE_PROP_PROPERTIES = {}
|
|
|
|
@staticmethod
|
|
def register_property(property_, len_):
|
|
def _register_property(cls):
|
|
cls.cls_property = property_
|
|
cls.cls_len = len_
|
|
OFPQueueProp._QUEUE_PROP_PROPERTIES[cls.cls_property] = cls
|
|
return cls
|
|
return _register_property
|
|
|
|
def __init__(self):
|
|
cls = self.__class__
|
|
super(OFPQueueProp, self).__init__(cls.cls_property,
|
|
cls.cls_len)
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(property_, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_QUEUE_PROP_HEADER_PACK_STR,
|
|
buf, offset)
|
|
cls_ = cls._QUEUE_PROP_PROPERTIES.get(property_)
|
|
return cls_.parser(buf, offset)
|
|
|
|
|
|
class OFPPacketQueue(object):
|
|
def __init__(self, queue_id, port, len_, properties):
|
|
super(OFPPacketQueue, self).__init__()
|
|
self.queue_id = queue_id
|
|
self.port = port
|
|
self.len = len_
|
|
self.properties = properties
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(queue_id, port, len_) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_PACKET_QUEUE_PACK_STR, buf, offset)
|
|
length = ofproto_v1_2.OFP_PACKET_QUEUE_SIZE
|
|
offset += ofproto_v1_2.OFP_PACKET_QUEUE_SIZE
|
|
properties = []
|
|
while length < len_:
|
|
queue_prop = OFPQueueProp.parser(buf, offset)
|
|
properties.append(queue_prop)
|
|
offset += queue_prop.len
|
|
length += queue_prop.len
|
|
return cls(queue_id, port, len_, properties)
|
|
|
|
|
|
@OFPQueueProp.register_property(ofproto_v1_2.OFPQT_MIN_RATE,
|
|
ofproto_v1_2.OFP_QUEUE_PROP_MIN_RATE_SIZE)
|
|
class OFPQueuePropMinRate(OFPQueueProp):
|
|
def __init__(self, rate):
|
|
super(OFPQueuePropMinRate, self).__init__()
|
|
self.rate = rate
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(rate,) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_QUEUE_PROP_MIN_RATE_PACK_STR, buf, offset)
|
|
return cls(rate)
|
|
|
|
|
|
@OFPQueueProp.register_property(ofproto_v1_2.OFPQT_MAX_RATE,
|
|
ofproto_v1_2.OFP_QUEUE_PROP_MAX_RATE_SIZE)
|
|
class OFPQueuePropMaxRate(OFPQueueProp):
|
|
def __init__(self, rate):
|
|
super(OFPQueuePropMaxRate, self).__init__()
|
|
self.rate = rate
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(rate,) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_QUEUE_PROP_MAX_RATE_PACK_STR, buf, offset)
|
|
return cls(rate)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.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)
|
|
(msg.port,) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_QUEUE_GET_CONFIG_REPLY_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
msg.queues = []
|
|
length = ofproto_v1_2.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
|
|
offset = ofproto_v1_2.OFP_QUEUE_GET_CONFIG_REPLY_SIZE
|
|
while length < msg.msg_len:
|
|
queue = OFPPacketQueue.parser(msg.buf, offset)
|
|
msg.queues.append(queue)
|
|
|
|
offset += queue.len
|
|
length += queue.len
|
|
|
|
return msg
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_BARRIER_REQUEST)
|
|
class OFPBarrierRequest(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPBarrierRequest, self).__init__(datapath)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_BARRIER_REPLY)
|
|
class OFPBarrierReply(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPBarrierReply, self).__init__(datapath)
|
|
|
|
|
|
@_set_msg_type(ofproto_v1_2.OFPT_ROLE_REQUEST)
|
|
class OFPRoleRequest(MsgBase):
|
|
def __init__(self, datapath, role, generation_id):
|
|
super(OFPRoleRequest, self).__init__(datapath)
|
|
self.role = role
|
|
self.generation_id = generation_id
|
|
|
|
def _serialize_body(self):
|
|
msg_pack_into(ofproto_v1_2.OFP_ROLE_REQUEST_PACK_STR,
|
|
self.buf, ofproto_v1_2.OFP_HEADER_SIZE,
|
|
self.role, self.generation_id)
|
|
|
|
|
|
@_register_parser
|
|
@_set_msg_type(ofproto_v1_2.OFPT_ROLE_REPLY)
|
|
class OFPRoleReply(MsgBase):
|
|
def __init__(self, datapath):
|
|
super(OFPRoleReply, self).__init__(datapath)
|
|
|
|
@classmethod
|
|
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
|
|
msg = super(OFPRoleReply, cls).parser(datapath, version,
|
|
msg_type,
|
|
msg_len, xid, buf)
|
|
(msg.role, msg.generation_id) = struct.unpack_from(
|
|
ofproto_v1_2.OFP_ROLE_REQUEST_PACK_STR, msg.buf,
|
|
ofproto_v1_2.OFP_HEADER_SIZE)
|
|
|
|
return msg
|
|
|
|
|
|
UINT64_MAX = (1 << 64) - 1
|
|
UINT32_MAX = (1 << 32) - 1
|
|
UINT16_MAX = (1 << 16) - 1
|
|
|
|
|
|
class Flow(object):
|
|
def __init__(self):
|
|
self.in_port = 0
|
|
self.in_phy_port = 0
|
|
self.metadata = 0
|
|
self.dl_dst = mac.DONTCARE
|
|
self.dl_src = mac.DONTCARE
|
|
self.dl_type = 0
|
|
self.vlan_vid = 0
|
|
self.vlan_pcp = 0
|
|
self.ip_dscp = 0
|
|
self.ip_ecn = 0
|
|
self.ip_proto = 0
|
|
self.ipv4_src = 0
|
|
self.ipv4_dst = 0
|
|
self.tcp_src = 0
|
|
self.tcp_dst = 0
|
|
self.udp_src = 0
|
|
self.udp_dst = 0
|
|
self.sctp_src = 0
|
|
self.sctp_dst = 0
|
|
self.icmpv4_type = 0
|
|
self.icmpv4_code = 0
|
|
self.arp_op = 0
|
|
self.arp_spa = 0
|
|
self.arp_tpa = 0
|
|
self.arp_sha = 0
|
|
self.arp_tha = 0
|
|
self.ipv6_src = []
|
|
self.ipv6_dst = []
|
|
self.ipv6_flabel = 0
|
|
self.icmpv6_type = 0
|
|
self.icmpv6_code = 0
|
|
self.ipv6_nd_target = []
|
|
self.ipv6_nd_sll = 0
|
|
self.ipv6_nd_tll = 0
|
|
self.mpls_lable = 0
|
|
self.mpls_tc = 0
|
|
|
|
|
|
class FlowWildcards(object):
|
|
def __init__(self):
|
|
self.metadata_mask = 0
|
|
self.dl_dst_mask = 0
|
|
self.dl_src_mask = 0
|
|
self.vlan_vid_mask = 0
|
|
self.ipv4_src_mask = 0
|
|
self.ipv4_dst_mask = 0
|
|
self.arp_spa_mask = 0
|
|
self.arp_tpa_mask = 0
|
|
self.arp_sha_mask = 0
|
|
self.arp_tha_mask = 0
|
|
self.ipv6_src_mask = []
|
|
self.ipv6_dst_mask = []
|
|
self.ipv6_flabel_mask = 0
|
|
self.wildcards = (1 << 64) - 1
|
|
|
|
def ft_set(self, shift):
|
|
self.wildcards &= ~(1 << shift)
|
|
|
|
def ft_test(self, shift):
|
|
return not self.wildcards & (1 << shift)
|
|
|
|
|
|
class OFPMatch(object):
|
|
def __init__(self):
|
|
super(OFPMatch, self).__init__()
|
|
self.wc = FlowWildcards()
|
|
self.flow = Flow()
|
|
self.fields = []
|
|
|
|
def append_field(self, header, value, mask=None):
|
|
self.fields.append(OFPMatchField.make(header, value, mask))
|
|
|
|
def serialize(self, buf, offset):
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IN_PORT):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IN_PORT,
|
|
self.flow.in_port)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IN_PHY_PORT):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IN_PHY_PORT,
|
|
self.flow.in_phy_port)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_METADATA):
|
|
if self.wc.metadata_mask == UINT64_MAX:
|
|
header = ofproto_v1_2.OXM_OF_METADATA
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_METADATA_W
|
|
self.append_field(header, self.flow.metadata,
|
|
self.wc.metadata_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ETH_DST):
|
|
if self.wc.dl_dst_mask:
|
|
header = ofproto_v1_2.OXM_OF_ETH_DST_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ETH_DST
|
|
self.append_field(header, self.flow.dl_dst, self.wc.dl_dst_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ETH_SRC):
|
|
if self.wc.dl_src_mask:
|
|
header = ofproto_v1_2.OXM_OF_ETH_SRC_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ETH_SRC
|
|
self.append_field(header, self.flow.dl_src, self.wc.dl_src_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ETH_TYPE):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ETH_TYPE, self.flow.dl_type)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_VLAN_VID):
|
|
if self.wc.vlan_vid_mask == UINT16_MAX:
|
|
header = ofproto_v1_2.OXM_OF_VLAN_VID
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_VLAN_VID_W
|
|
self.append_field(header, self.flow.vlan_vid,
|
|
self.wc.vlan_vid_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_VLAN_PCP):
|
|
self.append_field(ofproto_v1_2.OXM_OF_VLAN_PCP, self.flow.vlan_pcp)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IP_DSCP):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IP_DSCP, self.flow.ip_dscp)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IP_ECN):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IP_ECN, self.flow.ip_ecn)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IP_PROTO):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IP_PROTO, self.flow.ip_proto)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV4_SRC):
|
|
if self.wc.ipv4_src_mask == UINT32_MAX:
|
|
header = ofproto_v1_2.OXM_OF_IPV4_SRC
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_IPV4_SRC_W
|
|
self.append_field(header, self.flow.ipv4_src,
|
|
self.wc.ipv4_src_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV4_DST):
|
|
if self.wc.ipv4_dst_mask == UINT32_MAX:
|
|
header = ofproto_v1_2.OXM_OF_IPV4_DST
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_IPV4_DST_W
|
|
self.append_field(header, self.flow.ipv4_dst,
|
|
self.wc.ipv4_dst_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_TCP_SRC):
|
|
self.append_field(ofproto_v1_2.OXM_OF_TCP_SRC, self.flow.tcp_src)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_TCP_DST):
|
|
self.append_field(ofproto_v1_2.OXM_OF_TCP_DST, self.flow.tcp_dst)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_UDP_SRC):
|
|
self.append_field(ofproto_v1_2.OXM_OF_UDP_SRC, self.flow.udp_src)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_UDP_DST):
|
|
self.append_field(ofproto_v1_2.OXM_OF_UDP_DST, self.flow.udp_dst)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_SCTP_SRC):
|
|
self.append_field(ofproto_v1_2.OXM_OF_SCTP_SRC, self.flow.sctp_src)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_SCTP_DST):
|
|
self.append_field(ofproto_v1_2.OXM_OF_SCTP_DST, self.flow.sctp_dst)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ICMPV4_TYPE):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ICMPV4_TYPE,
|
|
self.flow.icmpv4_type)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ICMPV4_CODE):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ICMPV4_CODE,
|
|
self.flow.icmpv4_code)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ARP_OP):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ARP_OP, self.flow.arp_op)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ARP_SPA):
|
|
if self.wc.arp_spa_mask == UINT32_MAX:
|
|
header = ofproto_v1_2.OXM_OF_ARP_SPA
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ARP_SPA_W
|
|
self.append_field(header, self.flow.arp_spa, self.wc.arp_spa_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ARP_TPA):
|
|
if self.wc.arp_tpa_mask == UINT32_MAX:
|
|
header = ofproto_v1_2.OXM_OF_ARP_TPA
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ARP_TPA_W
|
|
self.append_field(header, self.flow.arp_tpa, self.wc.arp_tpa_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ARP_SHA):
|
|
if self.wc.arp_sha_mask:
|
|
header = ofproto_v1_2.OXM_OF_ARP_SHA_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ARP_SHA
|
|
self.append_field(header, self.flow.arp_sha, self.wc.arp_sha_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ARP_THA):
|
|
if self.wc.arp_tha_mask:
|
|
header = ofproto_v1_2.OXM_OF_ARP_THA_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_ARP_THA
|
|
self.append_field(header, self.flow.arp_tha, self.wc.arp_tha_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_SRC):
|
|
if len(self.wc.ipv6_src_mask):
|
|
header = ofproto_v1_2.OXM_OF_IPV6_SRC_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_IPV6_SRC
|
|
self.append_field(header, self.flow.ipv6_src,
|
|
self.wc.ipv6_src_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_DST):
|
|
if len(self.wc.ipv6_dst_mask):
|
|
header = ofproto_v1_2.OXM_OF_IPV6_DST_W
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_IPV6_DST
|
|
self.append_field(header, self.flow.ipv6_dst,
|
|
self.wc.ipv6_dst_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_FLABEL):
|
|
if self.wc.ipv6_flabel_mask == UINT32_MAX:
|
|
header = ofproto_v1_2.OXM_OF_IPV6_FLABEL
|
|
else:
|
|
header = ofproto_v1_2.OXM_OF_IPV6_FLABEL_W
|
|
self.append_field(header, self.flow.ipv6_flabel,
|
|
self.wc.ipv6_flabel_mask)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ICMPV6_TYPE):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ICMPV6_TYPE,
|
|
self.flow.icmpv6_type)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_ICMPV6_CODE):
|
|
self.append_field(ofproto_v1_2.OXM_OF_ICMPV6_CODE,
|
|
self.flow.icmpv6_code)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_TARGET):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IPV6_ND_TARGET,
|
|
self.flow.ipv6_nd_target)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_SLL):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IPV6_ND_SLL,
|
|
self.flow.ipv6_nd_sll)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_TLL):
|
|
self.append_field(ofproto_v1_2.OXM_OF_IPV6_ND_TLL,
|
|
self.flow.ipv6_nd_tll)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_MPLS_LABEL):
|
|
self.append_field(ofproto_v1_2.OXM_OF_MPLS_LABEL,
|
|
self.flow.mpls_label)
|
|
|
|
if self.wc.ft_test(ofproto_v1_2.OFPXMT_OFB_MPLS_TC):
|
|
self.append_field(ofproto_v1_2.OXM_OF_MPLS_TC,
|
|
self.flow.mpls_tc)
|
|
|
|
field_offset = offset + 4
|
|
for f in self.fields:
|
|
f.serialize(buf, field_offset)
|
|
field_offset += f.length
|
|
|
|
length = field_offset - offset
|
|
msg_pack_into('!HH', buf, offset, ofproto_v1_2.OFPMT_OXM, length)
|
|
|
|
pad_len = utils.round_up(length, 8) - length
|
|
ofproto_parser.msg_pack_into("%dx" % pad_len, buf, field_offset)
|
|
|
|
return length + pad_len
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
match = OFPMatch()
|
|
type_, length = struct.unpack_from('!HH', buf, offset)
|
|
|
|
match.type = type_
|
|
match.length = length
|
|
|
|
# ofp_match adjustment
|
|
offset += 4
|
|
length -= 4
|
|
while length > 0:
|
|
field = OFPMatchField.parser(buf, offset)
|
|
offset += field.length
|
|
length -= field.length
|
|
match.fields.append(field)
|
|
|
|
return match
|
|
|
|
def set_in_port(self, port):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IN_PORT)
|
|
self.flow.in_port = port
|
|
|
|
def set_in_phy_port(self, phy_port):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IN_PHY_PORT)
|
|
self.flow.in_phy_port = phy_port
|
|
|
|
def set_metadata(self, metadata):
|
|
self.set_metadata_masked(metadata, UINT64_MAX)
|
|
|
|
def set_metadata_masked(self, metadata, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_METADATA)
|
|
self.wc.metadata_mask = mask
|
|
self.flow.metadata = metadata & mask
|
|
|
|
def set_dl_dst(self, dl_dst):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ETH_DST)
|
|
self.flow.dl_dst = dl_dst
|
|
|
|
def set_dl_dst_masked(self, dl_dst, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ETH_DST)
|
|
self.wc.dl_dst_mask = mask
|
|
# bit-wise and of the corresponding elements of dl_dst and mask
|
|
self.flow.dl_dst = mac.haddr_bitand(dl_dst, mask)
|
|
|
|
def set_dl_src(self, dl_src):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ETH_SRC)
|
|
self.flow.dl_src = dl_src
|
|
|
|
def set_dl_src_masked(self, dl_src, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ETH_SRC)
|
|
self.wc.dl_src_mask = mask
|
|
self.flow.dl_src = mac.haddr_bitand(dl_src, mask)
|
|
|
|
def set_dl_type(self, dl_type):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ETH_TYPE)
|
|
self.flow.dl_type = dl_type
|
|
|
|
def set_vlan_vid(self, vid):
|
|
self.set_vlan_vid_masked(vid, UINT16_MAX)
|
|
|
|
def set_vlan_vid_masked(self, vid, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_VLAN_VID)
|
|
self.wc.vlan_vid_mask = mask
|
|
self.flow.vlan_vid = vid
|
|
|
|
def set_vlan_pcp(self, pcp):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_VLAN_PCP)
|
|
self.flow.vlan_pcp = pcp
|
|
|
|
def set_ip_dscp(self, ip_dscp):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IP_DSCP)
|
|
self.flow.ip_dscp = ip_dscp
|
|
|
|
def set_ip_ecn(self, ip_ecn):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IP_ECN)
|
|
self.flow.ip_ecn = ip_ecn
|
|
|
|
def set_ip_proto(self, ip_proto):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IP_PROTO)
|
|
self.flow.ip_proto = ip_proto
|
|
|
|
def set_ipv4_src(self, ipv4_src):
|
|
self.set_ipv4_src_masked(ipv4_src, UINT32_MAX)
|
|
|
|
def set_ipv4_src_masked(self, ipv4_src, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV4_SRC)
|
|
self.flow.ipv4_src = ipv4_src
|
|
self.wc.ipv4_src_mask = mask
|
|
|
|
def set_ipv4_dst(self, ipv4_dst):
|
|
self.set_ipv4_dst_masked(ipv4_dst, UINT32_MAX)
|
|
|
|
def set_ipv4_dst_masked(self, ipv4_dst, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV4_DST)
|
|
self.flow.ipv4_dst = ipv4_dst
|
|
self.wc.ipv4_dst_mask = mask
|
|
|
|
def set_tcp_src(self, tcp_src):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_TCP_SRC)
|
|
self.flow.tcp_src = tcp_src
|
|
|
|
def set_tcp_dst(self, tcp_dst):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_TCP_DST)
|
|
self.flow.tcp_dst = tcp_dst
|
|
|
|
def set_udp_src(self, udp_src):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_UDP_SRC)
|
|
self.flow.udp_src = udp_src
|
|
|
|
def set_udp_dst(self, udp_dst):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_UDP_DST)
|
|
self.flow.udp_dst = udp_dst
|
|
|
|
def set_sctp_src(self, sctp_src):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_SCTP_SRC)
|
|
self.flow.sctp_src = sctp_src
|
|
|
|
def set_sctp_dst(self, sctp_dst):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_SCTP_DST)
|
|
self.flow.sctp_dst = sctp_dst
|
|
|
|
def set_icmpv4_type(self, icmpv4_type):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ICMPV4_TYPE)
|
|
self.flow.icmpv4_type = icmpv4_type
|
|
|
|
def set_icmpv4_code(self, icmpv4_code):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ICMPV4_CODE)
|
|
self.flow.icmpv4_code = icmpv4_code
|
|
|
|
def set_arp_opcode(self, arp_op):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_OP)
|
|
self.flow.arp_op = arp_op
|
|
|
|
def set_arp_spa(self, arp_spa):
|
|
self.set_arp_spa_masked(arp_spa, UINT32_MAX)
|
|
|
|
def set_arp_spa_masked(self, arp_spa, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_SPA)
|
|
self.wc.arp_spa_mask = mask
|
|
self.flow.arp_spa = arp_spa
|
|
|
|
def set_arp_tpa(self, arp_tpa):
|
|
self.set_arp_tpa_masked(arp_tpa, UINT32_MAX)
|
|
|
|
def set_arp_tpa_masked(self, arp_tpa, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_TPA)
|
|
self.wc.arp_tpa_mask = mask
|
|
self.flow.arp_tpa = arp_tpa
|
|
|
|
def set_arp_sha(self, arp_sha):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_SHA)
|
|
self.flow.arp_sha = arp_sha
|
|
|
|
def set_arp_sha_masked(self, arp_sha, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_SHA)
|
|
self.wc.arp_sha_mask = mask
|
|
self.flow.arp_sha = mac.haddr_bitand(arp_sha, mask)
|
|
|
|
def set_arp_tha(self, arp_tha):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_THA)
|
|
self.flow.arp_tha = arp_tha
|
|
|
|
def set_arp_tha_masked(self, arp_tha, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ARP_THA)
|
|
self.wc.arp_tha_mask = mask
|
|
self.flow.arp_tha = mac.haddr_bitand(arp_tha, mask)
|
|
|
|
def set_ipv6_src(self, src):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_SRC)
|
|
self.flow.ipv6_src = src
|
|
|
|
def set_ipv6_src_masked(self, src, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_SRC)
|
|
self.wc.ipv6_src_mask = mask
|
|
self.flow.ipv6_src = [x & y for (x, y) in itertools.izip(src, mask)]
|
|
|
|
def set_ipv6_dst(self, dst):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_DST)
|
|
self.flow.ipv6_dst = dst
|
|
|
|
def set_ipv6_dst_masked(self, dst, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_DST)
|
|
self.wc.ipv6_dst_mask = mask
|
|
self.flow.ipv6_dst = [x & y for (x, y) in itertools.izip(dst, mask)]
|
|
|
|
def set_ipv6_flabel(self, flabel):
|
|
self.set_ipv6_flabel_masked(flabel, UINT32_MAX)
|
|
|
|
def set_ipv6_flabel_masked(self, flabel, mask):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_FLABEL)
|
|
self.wc.ipv6_flabel_mask = mask
|
|
self.flow.ipv6_flabel = flabel
|
|
|
|
def set_icmpv6_type(self, icmpv6_type):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ICMPV6_TYPE)
|
|
self.flow.icmpv6_type = icmpv6_type
|
|
|
|
def set_icmpv6_code(self, icmpv6_code):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_ICMPV6_CODE)
|
|
self.flow.icmpv6_code = icmpv6_code
|
|
|
|
def set_ipv6_nd_target(self, target):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_TARGET)
|
|
self.flow.ipv6_nd_target = target
|
|
|
|
def set_ipv6_nd_sll(self, ipv6_nd_sll):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_SLL)
|
|
self.flow.ipv6_nd_sll = ipv6_nd_sll
|
|
|
|
def set_ipv6_nd_tll(self, ipv6_nd_tll):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_IPV6_ND_TLL)
|
|
self.flow.ipv6_nd_tll = ipv6_nd_tll
|
|
|
|
def set_mpls_label(self, mpls_label):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_MPLS_LABEL)
|
|
self.flow.mpls_label = mpls_label
|
|
|
|
def set_mpls_tc(self, mpls_tc):
|
|
self.wc.ft_set(ofproto_v1_2.OFPXMT_OFB_MPLS_TC)
|
|
self.flow.mpls_tc = mpls_tc
|
|
|
|
|
|
class OFPMatchField(object):
|
|
_FIELDS_HEADERS = {}
|
|
|
|
@staticmethod
|
|
def register_field_header(headers):
|
|
def _register_field_header(cls):
|
|
for header in headers:
|
|
OFPMatchField._FIELDS_HEADERS[header] = cls
|
|
return cls
|
|
return _register_field_header
|
|
|
|
def __init__(self, header):
|
|
self.header = header
|
|
hasmask = (header >> 8) & 1
|
|
if hasmask:
|
|
self.n_bytes = (header & 0xff) / 2
|
|
else:
|
|
self.n_bytes = header & 0xff
|
|
self.length = 0
|
|
|
|
@staticmethod
|
|
def make(header, value, mask=None):
|
|
cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
|
|
return cls_(header, value, mask)
|
|
|
|
@classmethod
|
|
def parser(cls, buf, offset):
|
|
(header,) = struct.unpack_from('!I', buf, offset)
|
|
cls_ = OFPMatchField._FIELDS_HEADERS.get(header)
|
|
if cls_:
|
|
field = cls_.field_parser(header, buf, offset)
|
|
else:
|
|
field = OFPMatchField(header)
|
|
field.length = (header & 0xff) + 4
|
|
return field
|
|
|
|
@classmethod
|
|
def field_parser(cls, header, buf, offset):
|
|
hasmask = (header >> 8) & 1
|
|
mask = None
|
|
if hasmask:
|
|
pack_str = '!' + cls.pack_str[1:] * 2
|
|
(value, mask) = struct.unpack_from(pack_str, buf, offset + 4)
|
|
else:
|
|
(value,) = struct.unpack_from(cls.pack_str, buf, offset + 4)
|
|
return cls(header, value, mask)
|
|
|
|
def serialize(self, buf, offset):
|
|
hasmask = (self.header >> 8) & 1
|
|
if hasmask:
|
|
self.put_w(buf, offset, self.value, self.mask)
|
|
else:
|
|
self.put(buf, offset, self.value)
|
|
|
|
def _put_header(self, buf, offset):
|
|
ofproto_parser.msg_pack_into('!I', buf, offset, self.header)
|
|
self.length += 4
|
|
|
|
def _put(self, buf, offset, value):
|
|
ofproto_parser.msg_pack_into(self.pack_str, buf, offset, value)
|
|
self.length += self.n_bytes
|
|
|
|
def put_w(self, buf, offset, value, mask):
|
|
self._put_header(buf, offset)
|
|
self._put(buf, offset + self.length, value)
|
|
self._put(buf, offset + self.length, mask)
|
|
|
|
def put(self, buf, offset, value):
|
|
self._put_header(buf, offset)
|
|
self._put(buf, offset + self.length, value)
|
|
|
|
def _putv6(self, buf, offset, value):
|
|
ofproto_parser.msg_pack_into(self.pack_str, buf, offset,
|
|
*value)
|
|
self.length += self.n_bytes
|
|
|
|
def putv6(self, buf, offset, value, mask=None):
|
|
self._put_header(buf, offset)
|
|
self._putv6(buf, offset + self.length, value)
|
|
if mask and len(mask):
|
|
self._putv6(buf, offset + self.length, mask)
|
|
|
|
def oxm_len(self):
|
|
return self.header & 0xff
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IN_PORT])
|
|
class MTInPort(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTInPort, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_METADATA,
|
|
ofproto_v1_2.OXM_OF_METADATA_W])
|
|
class MTMetadata(OFPMatchField):
|
|
pack_str = '!Q'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTMetadata, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IN_PHY_PORT])
|
|
class MTInPhyPort(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTInPhyPort, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ETH_DST,
|
|
ofproto_v1_2.OXM_OF_ETH_DST_W])
|
|
class MTEthDst(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTEthDst, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ETH_SRC,
|
|
ofproto_v1_2.OXM_OF_ETH_SRC_W])
|
|
class MTEthSrc(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTEthSrc, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ETH_TYPE])
|
|
class MTEthType(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTEthType, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_VLAN_VID,
|
|
ofproto_v1_2.OXM_OF_VLAN_VID_W])
|
|
class MTVlanVid(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTVlanVid, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_VLAN_PCP])
|
|
class MTVlanPcp(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTVlanPcp, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IP_DSCP])
|
|
class MTIPDscp(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPDscp, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IP_ECN])
|
|
class MTIPECN(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPECN, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IP_PROTO])
|
|
class MTIPProto(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPProto, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV4_SRC,
|
|
ofproto_v1_2.OXM_OF_IPV4_SRC_W])
|
|
class MTIPV4Src(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPV4Src, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV4_DST,
|
|
ofproto_v1_2.OXM_OF_IPV4_DST_W])
|
|
class MTIPV4Dst(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPV4Dst, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_TCP_SRC])
|
|
class MTTCPSrc(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTTCPSrc, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_TCP_DST])
|
|
class MTTCPDst(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTTCPDst, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_UDP_SRC])
|
|
class MTUDPSrc(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTUDPSrc, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_UDP_DST])
|
|
class MTUDPDst(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTUDPDst, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_SCTP_SRC])
|
|
class MTSCTPSrc(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTSCTPSrc, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_SCTP_DST])
|
|
class MTSCTPDst(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTSCTPDst, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ICMPV4_TYPE])
|
|
class MTICMPV4Type(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTICMPV4Type, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ICMPV4_CODE])
|
|
class MTICMPV4Code(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTICMPV4Code, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ARP_OP])
|
|
class MTArpOp(OFPMatchField):
|
|
pack_str = '!H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTArpOp, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ARP_SPA,
|
|
ofproto_v1_2.OXM_OF_ARP_SPA_W])
|
|
class MTArpSpa(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTArpSpa, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ARP_TPA,
|
|
ofproto_v1_2.OXM_OF_ARP_TPA_W])
|
|
class MTArpTpa(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTArpTpa, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ARP_SHA,
|
|
ofproto_v1_2.OXM_OF_ARP_SHA_W])
|
|
class MTArpSha(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTArpSha, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ARP_THA,
|
|
ofproto_v1_2.OXM_OF_ARP_THA_W])
|
|
class MTArpTha(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTArpTha, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
class MTIPv6(object):
|
|
@classmethod
|
|
def field_parser(cls, header, buf, offset):
|
|
hasmask = (header >> 8) & 1
|
|
if hasmask:
|
|
pack_str = '!' + cls.pack_str[1:] * 2
|
|
value = struct.unpack_from(pack_str, buf, offset + 4)
|
|
return cls(header, list(value[:8]), list(value[8:]))
|
|
else:
|
|
value = struct.unpack_from(cls.pack_str, buf, offset + 4)
|
|
return cls(header, list(value))
|
|
|
|
def serialize(self, buf, offset):
|
|
self.putv6(buf, offset, self.value, self.mask)
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_SRC,
|
|
ofproto_v1_2.OXM_OF_IPV6_SRC_W])
|
|
class MTIPv6Src(MTIPv6, OFPMatchField):
|
|
pack_str = '!8H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6Src, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_DST,
|
|
ofproto_v1_2.OXM_OF_IPV6_DST_W])
|
|
class MTIPv6Dst(MTIPv6, OFPMatchField):
|
|
pack_str = '!8H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6Dst, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_FLABEL,
|
|
ofproto_v1_2.OXM_OF_IPV6_FLABEL_W])
|
|
class MTIPv6Flabel(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6Flabel, self).__init__(header)
|
|
self.value = value
|
|
self.mask = mask
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_MPLS_LABEL])
|
|
class MTMplsLabel(OFPMatchField):
|
|
pack_str = '!I'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTMplsLabel, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ICMPV6_TYPE])
|
|
class MTICMPV6Type(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTICMPV6Type, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_ICMPV6_CODE])
|
|
class MTICMPV6Code(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTICMPV6Code, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_ND_TARGET])
|
|
class MTIPv6NdTarget(MTIPv6, OFPMatchField):
|
|
pack_str = '!8H'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6NdTarget, self).__init__(header)
|
|
self.value = value
|
|
|
|
def serialize(self, buf, offset):
|
|
self.putv6(buf, offset, self.value)
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_ND_SLL])
|
|
class MTIPv6NdSll(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6NdSll, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_IPV6_ND_TLL])
|
|
class MTIPv6NdTll(OFPMatchField):
|
|
pack_str = '!6s'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTIPv6NdTll, self).__init__(header)
|
|
self.value = value
|
|
|
|
|
|
@OFPMatchField.register_field_header([ofproto_v1_2.OXM_OF_MPLS_TC])
|
|
class MTMplsTc(OFPMatchField):
|
|
pack_str = '!B'
|
|
|
|
def __init__(self, header, value, mask=None):
|
|
super(MTMplsTc, self).__init__(header)
|
|
self.value = value
|