OFPT_ERROR_MSG can return truncated messages. Some users want to see them in human-friendly format [1]. Catch exceptions caused by such truncated messages and reraise as OFPTruncatedMessage with incomplete ofpmsg in the exception class.
Not every exceptions are captured, and we should deal with other OpenFlow versions, too. [1] https://bugs.launchpad.net/dragonflow/+bug/1624826 Signed-off-by: IWAMOTO Toshihiro <iwam...@valinux.co.jp> --- ryu/exception.py | 13 +++++++ ryu/ofproto/ofproto_v1_3_parser.py | 71 +++++++++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/ryu/exception.py b/ryu/exception.py index 0a1e72c..1be4ba1 100644 --- a/ryu/exception.py +++ b/ryu/exception.py @@ -39,6 +39,19 @@ class OFPMalformedMessage(RyuException): message = 'malformed message' +class OFPTruncatedMessage(RyuException): + message = 'truncated message: %(orig_ex)s' + + def __init__(self, ofpmsg, residue, original_exception, + msg=None, **kwargs): + self.ofpmsg = ofpmsg + self.residue = residue + self.original_exception = original_exception + kwargs['orig_ex'] = str(original_exception) + + super(OFPTruncatedMessage, self).__init__(msg, **kwargs) + + class NetworkNotFound(RyuException): message = 'no such network id %(network_id)s' diff --git a/ryu/ofproto/ofproto_v1_3_parser.py b/ryu/ofproto/ofproto_v1_3_parser.py index 99c4a47..ab07f75 100644 --- a/ryu/ofproto/ofproto_v1_3_parser.py +++ b/ryu/ofproto/ofproto_v1_3_parser.py @@ -49,6 +49,7 @@ from ryu.lib import addrconv from ryu.lib import mac from ryu.lib.pack_utils import msg_pack_into from ryu.lib.packet import packet +from ryu import exception from ryu import utils from ryu.ofproto.ofproto_parser import StringifyMixin, MsgBase from ryu.ofproto import ether @@ -1269,17 +1270,28 @@ class OFPMatch(StringifyMixin): offset += 4 length -= 4 + exc = None + residue = None # XXXcompat - cls.parser_old(match, buf, offset, length) + try: + cls.parser_old(match, buf, offset, length) + except Exception as e: + exc = e fields = [] - while length > 0: - n, value, mask, field_len = ofproto.oxm_parse(buf, offset) - k, uv = ofproto.oxm_to_user(n, value, mask) - fields.append((k, uv)) - offset += field_len - length -= field_len + try: + while length > 0: + n, value, mask, field_len = ofproto.oxm_parse(buf, offset) + k, uv = ofproto.oxm_to_user(n, value, mask) + fields.append((k, uv)) + offset += field_len + length -= field_len + except Exception as e: + exc = e + residue = buf[offset:] match._fields2 = fields + if exc is not None: + raise exception.OFPTruncatedMessage(match, residue, exc) return match @staticmethod @@ -2696,14 +2708,31 @@ class OFPFlowMod(MsgBase): ofproto.OFP_HEADER_SIZE) offset = ofproto.OFP_FLOW_MOD_SIZE - ofproto.OFP_HEADER_SIZE - msg.match = OFPMatch.parser(buf, offset) + try: + msg.match = OFPMatch.parser(buf, offset) + except exception.OFPTruncatedMessage as e: + msg.match = e.ofpmsg + e.ofpmsg = msg + raise e + offset += utils.round_up(msg.match.length, 8) instructions = [] - while offset < msg_len: - i = OFPInstruction.parser(buf, offset) - instructions.append(i) - offset += i.len + try: + while offset < msg_len: + i = OFPInstruction.parser(buf, offset) + instructions.append(i) + offset += i.len + except exception.OFPTruncatedMessage as e: + instructions.append(e.ofpmsg) + msg.instructions = instructions + e.ofpmsg = msg + raise e + except Exception as e: + msg.instructions = instructions + raise exception.OFPTruncatedMessage(ofpmsg=msg, + residue=buf[offset:], + original_exception=e) msg.instructions = instructions return msg @@ -2830,14 +2859,22 @@ class OFPInstructionActions(OFPInstruction): offset += ofproto.OFP_INSTRUCTION_ACTIONS_SIZE actions = [] actions_len = len_ - ofproto.OFP_INSTRUCTION_ACTIONS_SIZE - while actions_len > 0: - a = OFPAction.parser(buf, offset) - actions.append(a) - actions_len -= a.len - offset += a.len + exc = None + try: + while actions_len > 0: + a = OFPAction.parser(buf, offset) + actions.append(a) + actions_len -= a.len + offset += a.len + except Exception as e: + exc = e inst = cls(type_, actions) inst.len = len_ + if exc is not None: + raise exception.OFPTruncatedMessage(ofpmsg=inst, + residue=buf[offset:], + original_exception=exc) return inst def serialize(self, buf, offset): -- 2.1.4 ------------------------------------------------------------------------------ _______________________________________________ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel