From 417093e247ca467bed947c757495c42753cab374 Mon Sep 17 00:00:00 2001 From: Li Cao Date: Fri, 8 May 2020 12:33:30 +0800 Subject: [PATCH] [tests] fix key_id_mode handling and add exception handle (#4927) This commit fixes key_id_mode handling and added exception handling when key_id_mode is 0. According to IEEE Std 802.15.4-2015, when Key Id Mode is 0x00: Key is determined implicitly from the originator and recipient(s) of the frame, as indicated in the frame header. Our test scripts cannot handle such packets. If we leave key_id_mode = 0 case unhandled, we would get some exceptions that may cause developers to think that something is wrong. However dropping packets in this case is a normal behavior. --- tests/scripts/thread-cert/mac802154.py | 13 ++++++- tests/scripts/thread-cert/message.py | 50 ++++++++++++++++---------- tests/scripts/thread-cert/simulator.py | 8 +++-- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/tests/scripts/thread-cert/mac802154.py b/tests/scripts/thread-cert/mac802154.py index 98488f7c3..ac9a8faa3 100644 --- a/tests/scripts/thread-cert/mac802154.py +++ b/tests/scripts/thread-cert/mac802154.py @@ -42,6 +42,15 @@ from net_crypto import ( ) +class KeyIdMode0Exception(Exception): + """ + Raised when key id mode of packet is 0. + Such packet wouldn't be handled in test scripts, + but it's not abnormal behavior. + """ + pass + + class DeviceDescriptors: """Class representing 802.15.4 Device Descriptors.""" @@ -377,11 +386,13 @@ class MacFrame: key_id_mode = (security_control & 0x18) >> 3 if key_id_mode == 0: - key_id = data.read(9) + raise KeyIdMode0Exception elif key_id_mode == 1: key_id = data.read(1) elif key_id_mode == 2: key_id = data.read(5) + elif key_id_mode == 3: + key_id = data.read(9) else: pass diff --git a/tests/scripts/thread-cert/message.py b/tests/scripts/thread-cert/message.py index b41ce8c07..a4166626c 100644 --- a/tests/scripts/thread-cert/message.py +++ b/tests/scripts/thread-cert/message.py @@ -41,6 +41,10 @@ import mle from enum import IntEnum +class DropPacketException(Exception): + pass + + class MessageType(IntEnum): MLE = 0 COAP = 1 @@ -598,30 +602,38 @@ class MessageFactory: self._lowpan_parser.set_lowpan_context(cid, prefix) def create(self, data): - message = Message() - message.channel = struct.unpack(">B", data.read(1)) + try: + message = Message() + message.channel = struct.unpack(">B", data.read(1)) - # Parse MAC header - mac_frame = self._parse_mac_frame(data) - message.mac_header = mac_frame.header + # Parse MAC header + mac_frame = self._parse_mac_frame(data) + message.mac_header = mac_frame.header - if message.mac_header.frame_type != mac802154.MacHeader.FrameType.DATA: - return [message] + if message.mac_header.frame_type != mac802154.MacHeader.FrameType.DATA: + return [message] - message_info = common.MessageInfo() - message_info.source_mac_address = message.mac_header.src_address - message_info.destination_mac_address = message.mac_header.dest_address + message_info = common.MessageInfo() + message_info.source_mac_address = message.mac_header.src_address + message_info.destination_mac_address = message.mac_header.dest_address - # Create stream with 6LoWPAN datagram - lowpan_payload = io.BytesIO(mac_frame.payload.data) + # Create stream with 6LoWPAN datagram + lowpan_payload = io.BytesIO(mac_frame.payload.data) - ipv6_packet = self._lowpan_parser.parse(lowpan_payload, message_info) - if ipv6_packet is None: - return [message] + ipv6_packet = self._lowpan_parser.parse(lowpan_payload, + message_info) + if ipv6_packet is None: + return [message] - message.ipv6_packet = ipv6_packet + message.ipv6_packet = ipv6_packet - if message.type == MessageType.MLE: - self._add_device_descriptors(message) + if message.type == MessageType.MLE: + self._add_device_descriptors(message) - return message.try_extract_dtls_messages() + return message.try_extract_dtls_messages() + + except mac802154.KeyIdMode0Exception: + print( + 'Received packet with key_id_mode = 0, cannot be handled in test scripts' + ) + raise DropPacketException diff --git a/tests/scripts/thread-cert/simulator.py b/tests/scripts/thread-cert/simulator.py index a7b856f78..36f1c3854 100644 --- a/tests/scripts/thread-cert/simulator.py +++ b/tests/scripts/thread-cert/simulator.py @@ -175,14 +175,18 @@ class VirtualTime(BaseSimulator): self.sock.close() self.sock = None - def _add_message(self, nodeid, message): + def _add_message(self, nodeid, message_obj): addr = ('127.0.0.1', self.port + nodeid) # Ignore any exceptions try: - messages = self._message_factory.create(io.BytesIO(message)) + messages = self._message_factory.create(io.BytesIO(message_obj)) self.devices[addr]['msgs'] += messages + except message.DropPacketException: + print( + 'Drop current packet because it cannot be handled in test scripts' + ) except Exception as e: # Just print the exception to the console print("EXCEPTION: %s" % e)