deb-ryu/ryu/ofproto/ofproto_parser.py
FUJITA Tomonori 4c2de66d32 stop import ofproto_v1_0 as ofproto
'from . import ofproto_v1_0 as ofproto' in ryu/ofproto/__init__.py is
a wrong assumption. We need to remove it.

This introduces ryu/ofproto/ofproto_common.py including only constatns
that OF version independent code must use. Note that I don't move data
structures there that multiple OF versions can share (like OVS does).

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2012-07-17 19:32:13 +09:00

145 lines
4.1 KiB
Python

# Copyright (C) 2011, 2012 Nippon Telegraph and Telephone Corporation.
# Copyright (C) 2011 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 logging
import struct
from ryu import exception
from . import ofproto_common
LOG = logging.getLogger('ryu.ofproto.ofproto_parser')
def header(buf):
assert len(buf) >= ofproto_common.OFP_HEADER_SIZE
#LOG.debug('len %d bufsize %d', len(buf), ofproto.OFP_HEADER_SIZE)
return struct.unpack_from(ofproto_common.OFP_HEADER_PACK_STR, buffer(buf))
_MSG_PARSERS = {}
def register_msg_parser(version):
def register(msg_parser):
_MSG_PARSERS[version] = msg_parser
return msg_parser
return register
def msg(datapath, version, msg_type, msg_len, xid, buf):
assert len(buf) >= msg_len
msg_parser = _MSG_PARSERS.get(version)
if msg_parser is None:
raise exception.OFPUnknownVersion(version=version)
return msg_parser(datapath, version, msg_type, msg_len, xid, buf)
class MsgBase(object):
def __init__(self, datapath):
self.datapath = datapath
self.version = None
self.msg_type = None
self.msg_len = None
self.xid = None
self.buf = None
def set_headers(self, version, msg_type, msg_len, xid):
assert msg_type == self.cls_msg_type
self.version = version
self.msg_type = msg_type
self.msg_len = msg_len
self.xid = xid
def set_xid(self, xid):
assert self.xid is None
self.xid = xid
def set_buf(self, buf):
self.buf = buffer(buf)
def __str__(self):
return 'version: 0x%x msg_type 0x%x xid 0x%x' % (self.version,
self.msg_type,
self.xid)
@classmethod
def parser(cls, datapath, version, msg_type, msg_len, xid, buf):
msg = cls(datapath)
msg.set_headers(version, msg_type, msg_len, xid)
msg.set_buf(buf)
return msg
def _serialize_pre(self):
assert self.version is None
assert self.msg_type is None
assert self.buf is None
self.version = self.datapath.ofproto.OFP_VERSION
self.msg_type = self.cls_msg_type
self.buf = bytearray().zfill(self.datapath.ofproto.OFP_HEADER_SIZE)
def _serialize_header(self):
# buffer length is determined after trailing data is formated.
assert self.version is not None
assert self.msg_type is not None
assert self.msg_len is None
assert self.buf is not None
assert len(self.buf) >= self.datapath.ofproto.OFP_HEADER_SIZE
self.msg_len = len(self.buf)
if self.xid is None:
self.xid = 0
struct.pack_into(self.datapath.ofproto.OFP_HEADER_PACK_STR,
self.buf, 0,
self.version, self.msg_type, self.msg_len, self.xid)
def _serialize_body(self):
pass
def serialize(self):
self._serialize_pre()
self._serialize_body()
self._serialize_header()
def msg_pack_into(fmt, buf, offset, *args):
if len(buf) < offset:
buf += bytearray().zfill(offset - len(buf))
if len(buf) == offset:
buf += struct.pack(fmt, *args)
return
needed_len = offset + struct.calcsize(fmt)
if len(buf) < needed_len:
buf += bytearray().zfill(needed_len - len(buf))
struct.pack_into(fmt, buf, offset, *args)
def msg_str_attr(msg, buf, attr_list):
for attr in attr_list:
val = getattr(msg, attr, None)
if val is not None:
buf += ' %s %s' % (attr, val)
return buf