os-ken/ryu/ofproto/ofproto_parser.py
FUJITA Tomonori d7d4d8c1b5 fix 77effb29 regression
The following commit broke ofp_attrs():

commit 77effb29a6
Author: Isaku Yamahata <yamahata@valinux.co.jp>
Date:   Mon May 27 18:15:27 2013 +0900

    ofproto/ofproto_parser: pylint

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2013-06-02 20:12:49 +09:00

187 lines
5.2 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
import functools
import inspect
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)
def create_list_of_base_attributes(f):
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
ret = f(self, *args, **kwargs)
self._base_attributes = set(dir(self))
return ret
return wrapper
class StringifyMixin(object):
def __str__(self):
buf = ''
sep = ''
for k, v in ofp_attrs(self):
buf += sep
buf += "%s=%s" % (k, repr(v)) # repr() to escape binaries
sep = ','
return self.__class__.__name__ + '(' + buf + ')'
__repr__ = __str__ # note: str(list) uses __repr__ for elements
class MsgBase(StringifyMixin):
@create_list_of_base_attributes
def __init__(self, datapath):
super(MsgBase, self).__init__()
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):
buf = 'version: 0x%x msg_type 0x%x xid 0x%x ' % (self.version,
self.msg_type,
self.xid)
return buf + StringifyMixin.__str__(self)
@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(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(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(needed_len - len(buf))
struct.pack_into(fmt, buf, offset, *args)
def ofp_attrs(msg_):
base = getattr(msg_, '_base_attributes', [])
for k, v in inspect.getmembers(msg_):
if k.startswith('_'):
continue
if callable(v):
continue
if k in base:
continue
if hasattr(msg_.__class__, k):
continue
yield (k, v)
def msg_str_attr(msg_, buf, attr_list=None):
if attr_list is None:
attr_list = ofp_attrs(msg_)
for attr in attr_list:
val = getattr(msg_, attr, None)
if val is not None:
buf += ' %s %s' % (attr, val)
return buf