Closed elrandira closed 1 year ago
Is there a way to automatically decode containers as part of their parent messages/PDU?
Unfortunately no. For each container, you need to read the 3gpp spec, and see what structure is required for further decoding. Most of the container content correspond to ASN.1-defined structures, but not all (i.e. GSM and GPRS are not using ASN.1). Sometimes, the content of the container is even contextual... There are some issues already related to this, see for example:
If you wish to decode everything in a single pass, you will need to build enhanced ASN.1 modules gathering RRC3G, RRCLTE and RRCNR (and maybe more), and use table constraint and evolved ASN.1 features (which are not used in RRC specifications).
Thanks for your feedback, much appreciated.
partially answering my own question for people that might need it:
As I am working with PDU decoded in JSON, I can use the excellent jsonpath-ng to search through the message using JSONPath to look for PDU to decode and then decode them.
For example, with the RRC PDUs in the UeCapability message. the 3GPP 38.331 indeed doesn't decode these capability containers (called ue-CapabilityRAT-Container) directly inside the message. Each container is defined in the ASN.1 as an octet string and later in the ASN.1 definition the container is described but no link between these two are defined.
my function above becomes:
from binascii import unhexlify
from jsonpath_ng.ext.parser import parse as jp_parse
from pycrate_asn1dir.RRCNR import NR_RRC_Definitions
from pycrate_asn1dir.RRCLTE import EUTRA_RRC_Definitions
#for typing
from typing import Any, Optional, Union, Dict, List, Tuple
from pycrate_asn1rt.asnobj import ASN1Obj
jsonObj = Dict[str, Any]
SUB_PDUS_RRC: List[Tuple[str, ASN1Obj, str]] = [
# jsonPath, parser, method
('$..ue-CapabilityRAT-ContainerList[?(@.rat-Type == "nr")].ue-CapabilityRAT-Container', NR_RRC_Definitions.UE_NR_Capability, "from_uper"),
('$..ue-CapabilityRAT-ContainerList[?(@.rat-Type == "eutra")].ue-CapabilityRAT-Container', EUTRA_RRC_Definitions.UE_EUTRA_Capability, "from_uper"),
]
def decode_rrc(pdu: str, channel: str) -> jsonObj:
"""
Decode a RRC PDU from a specific channel (mandatory from 3GPP).
Allowed channel values are 'BCCH-BCH', 'BCCH-DL-SCH', 'DL-CCCH', 'DL-DCCH', 'PCCH',
'UL-CCCH', 'UL-CCCH1' and 'UL-DCCH'
Transfer syntax for RRC PDUs is derived from their ASN.1 definitions by use of Packed
Encoding Rules, unaligned specified by 3GPP 38.331 §8.1
:param
pdu (str): Packet Data Unit to decode
channel (str): channel providing the PDU
:return
dict[str, Any]: JSON representation of the decoded PDU
"""
_parsers_name = ['BCCH-BCH', 'BCCH-DL-SCH', 'DL-CCCH', 'DL-DCCH', 'PCCH', 'UL-CCCH', 'UL-CCCH1', 'UL-DCCH']
if channel not in _parsers_name:
raise Exception(f'Only channels supported are: {_parsers_name}')
# Just in case
pdu = pdu.replace(' ','').replace('\n', '')
# get parser from channel parameter
_msgParser = getattr(NR_RRC_Definitions, f"{channel}-Message".replace('-','_'))
buff = unhexlify(pdu)
_msgParser.from_uper(buff)
decoded= _msgParser._to_jval()
#Attempt decoding some PDUs inside the message
_decode_rrc_sub_pdus(decoded)
return decoded
def _decode_rrc_sub_pdus(message: jsonObj):
#search for specific IEs
for jp, parser, method in SUB_PDUS_RRC:
# apply jsonPath on jsonObj
rv= jp_parse(jp).find(message)
if len(rv) > 0:
# TODO: managed possible multiple elements of rv
sub_pdu=rv[0].value
# decode sub_pdu
getattr(parser, method)(unhexlify(sub_pdu))
# retrieve sub_pdu in json format
sub_dec_pdu=parser._to_jval()
# it might containt itself a new sub_PDU
_decode_rrc_sub_pdus(sub_dec_pdu)
# update with decoded value
# TODO: dangerous if more that one element in rv
jp_parse(jp).update(message, sub_dec_pdu)
It is a bit dirty but it gives the proper result and can still be improved. The downside is that list such as SUB_PDUS_RRC must be manually filled in.
Looks good to me. I wasn't aware of jsonpath_ng
but the syntax it supports seems to make it quite powerful. Thanks for your feedback.
Hi,
I am integrating your solution to decode 3GPP protocols (RRC, NAS, NGAP). I just found out that when I decode a RRC message for example, if a container is present, it won't be decoded but instead displayed as a PDU.
Is there a way to automatically decode containers as part of their parent messages/PDU? At least when it is the same protocol, this would exclude NAS container of RRC messages for example (but that could be customised depending on your answer).
Here's my call on your API
a ueCapability information message will return this for example:
when I call:
Thanks for your help,