Allow messages inside messages
Bundle Add Message and Request Forward Message, which is part of OpenFlow 1.4, encapsulates an OpenFlow message in side an OpenFlow message. This patch prepares for this by adding a MsgInMsgBase class, a subclass of MsgBase which allows its subclasses to include subclasses of either MsgInMsgBase or MsgBase when when parsing classes from JSON: The MsgBase class does not allow this. This change has three parts: * Remove the assertion in ofproto_parser.py:StringifyMixin::cls_from_jsondict_key() that cls is not a subclass of MsgBase. * Pass **additional_args to various stringify.py:StringifyMixin decoder methods to make the datapath available when instantiating MsgBase subclasses. * Override _decode_value() in MsgInMsgBase to pass **additional_args to decoder. The method in the parent class, StringifyMixin, does not pass **additional_args. The effect is to pass a datapath argument if the class is a subclass of MsgInMsgBase but not if the class is a direct subclass of MsgBase. By only making messages which allow messages inside them subclasses of MsgInMsgBase this allows the datapath argument to be passed to the decoder if and only if needed. Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
e04d1697e0
commit
5ba92e9ad2
@ -216,11 +216,11 @@ class StringifyMixin(object):
|
|||||||
return getattr(mod, k)
|
return getattr(mod, k)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def obj_from_jsondict(cls, jsondict):
|
def obj_from_jsondict(cls, jsondict, **additional_args):
|
||||||
assert len(jsondict) == 1
|
assert len(jsondict) == 1
|
||||||
for k, v in jsondict.iteritems():
|
for k, v in jsondict.iteritems():
|
||||||
obj_cls = cls.cls_from_jsondict_key(k)
|
obj_cls = cls.cls_from_jsondict_key(k)
|
||||||
return obj_cls.from_jsondict(v)
|
return obj_cls.from_jsondict(v, **additional_args)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_decoder(cls, k, decode_string):
|
def _get_decoder(cls, k, decode_string):
|
||||||
@ -230,19 +230,20 @@ class StringifyMixin(object):
|
|||||||
return cls._get_default_decoder(decode_string)
|
return cls._get_default_decoder(decode_string)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _decode_value(cls, k, json_value, decode_string=base64.b64decode):
|
def _decode_value(cls, k, json_value, decode_string=base64.b64decode,
|
||||||
|
**additional_args):
|
||||||
return cls._get_decoder(k, decode_string)(json_value)
|
return cls._get_decoder(k, decode_string)(json_value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_default_decoder(cls, decode_string):
|
def _get_default_decoder(cls, decode_string):
|
||||||
def _decode(json_value):
|
def _decode(json_value, **additional_args):
|
||||||
if isinstance(json_value, (bytes, unicode)):
|
if isinstance(json_value, (bytes, unicode)):
|
||||||
v = decode_string(json_value)
|
v = decode_string(json_value)
|
||||||
elif isinstance(json_value, list):
|
elif isinstance(json_value, list):
|
||||||
v = map(_decode, json_value)
|
v = map(_decode, json_value)
|
||||||
elif isinstance(json_value, dict):
|
elif isinstance(json_value, dict):
|
||||||
if cls._is_class(json_value):
|
if cls._is_class(json_value):
|
||||||
v = cls.obj_from_jsondict(json_value)
|
v = cls.obj_from_jsondict(json_value, **additional_args)
|
||||||
else:
|
else:
|
||||||
v = _mapdict(_decode, json_value)
|
v = _mapdict(_decode, json_value)
|
||||||
# XXXhack
|
# XXXhack
|
||||||
@ -287,7 +288,8 @@ class StringifyMixin(object):
|
|||||||
additional_args (Optional) Additional kwargs for constructor.
|
additional_args (Optional) Additional kwargs for constructor.
|
||||||
=============== =====================================================
|
=============== =====================================================
|
||||||
"""
|
"""
|
||||||
decode = lambda k, x: cls._decode_value(k, x, decode_string)
|
decode = lambda k, x: cls._decode_value(k, x, decode_string,
|
||||||
|
**additional_args)
|
||||||
kwargs = cls._restore_args(_mapdict_kv(decode, dict_))
|
kwargs = cls._restore_args(_mapdict_kv(decode, dict_))
|
||||||
try:
|
try:
|
||||||
return cls(**dict(kwargs, **additional_args))
|
return cls(**dict(kwargs, **additional_args))
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import base64
|
||||||
import collections
|
import collections
|
||||||
import logging
|
import logging
|
||||||
import struct
|
import struct
|
||||||
@ -115,7 +116,6 @@ class StringifyMixin(stringify.StringifyMixin):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def cls_from_jsondict_key(cls, k):
|
def cls_from_jsondict_key(cls, k):
|
||||||
obj_cls = super(StringifyMixin, cls).cls_from_jsondict_key(k)
|
obj_cls = super(StringifyMixin, cls).cls_from_jsondict_key(k)
|
||||||
assert not issubclass(obj_cls, MsgBase)
|
|
||||||
return obj_cls
|
return obj_cls
|
||||||
|
|
||||||
|
|
||||||
@ -204,6 +204,14 @@ class MsgBase(StringifyMixin):
|
|||||||
self._serialize_header()
|
self._serialize_header()
|
||||||
|
|
||||||
|
|
||||||
|
class MsgInMsgBase(MsgBase):
|
||||||
|
@classmethod
|
||||||
|
def _decode_value(cls, k, json_value, decode_string=base64.b64decode,
|
||||||
|
**additional_args):
|
||||||
|
return cls._get_decoder(k, decode_string)(json_value,
|
||||||
|
**additional_args)
|
||||||
|
|
||||||
|
|
||||||
def msg_pack_into(fmt, buf, offset, *args):
|
def msg_pack_into(fmt, buf, offset, *args):
|
||||||
if len(buf) < offset:
|
if len(buf) < offset:
|
||||||
buf += bytearray(offset - len(buf))
|
buf += bytearray(offset - len(buf))
|
||||||
|
Loading…
Reference in New Issue
Block a user