Closed dbressan2 closed 2 years ago
Thanks for your report.
Could you share the buffer corresponding to the UL_DCCH_Message
? That will ease the testing and providing the best answer.
Hi
Sure
Here you go:
00 c2 00 04 63 df 24 2b b0 10 7e 48 57 41 15 b7 5c d5 34 2c 0e bd c2 a8 fd 73 64 f1 ba c5 e7 a1 75 8d 53 43 ea d9 22 89 d5 30 44 08 91 21 1d 01 d6 1a c0 07 80 6b 26 4c 19 30 70 c1 8b 46 cd 19 da 75 80 04 a1 83 f6 16 6b 1b 38 0d 20 00 80 00
Best regards
D. Bressanelli
From: Benoit Michau @.> Sent: Friday, February 11, 2022 2:15 PM To: P1sec/pycrate @.> Cc: Dominique Bressanelli @.>; Author @.> Subject: Re: [P1sec/pycrate] Question on best way to chain decoding with 2 different grammars (Issue #179)
WARNING: This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.
Thanks for your report. Could you share the buffer corresponding to the UL_DCCH_Message ? That will ease the testing and providing the best answer.
— Reply to this email directly, view it on GitHubhttps://github.com/P1sec/pycrate/issues/179#issuecomment-1036202376, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHUUMPKDG4JQCRLRESGUE7DU2UDVBANCNFSM5OEB2JBA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.**@.>>
One way to manage it is at the ASN.1 level. OCTET STRING (and BIT STRING) can have a CONTAINING
constraint, which indicates another ASN.1 object to be decoded from the OCTET STRING (or BIT STRING) buffer.
E.g.:
ComplexObj ::= SEQUENCE {
...
}
OctStr ::= OCTET STRING (CONTAINING ComplexObj)
I believe the simplest, and maybe only, way to do what you ask for is to build such a construct with your ASN.1 definitions.
So you can modify your RRC NR specification, to enhance the definition of the locationTimestamp-r16
with such a (CONTAINING DisplacementTimeStamp-r15)
declaration. You will also need to manage properly the import of the LPP object in the RRC NR definition.
Otherwise, you can bind the LPP object to the RRC one within Python, doing something like this:
In [47]: M = NR_RRC_Definitions.UL_DCCH_Message
In [48]: D = LPP_PDU_Definitions.DisplacementTimeStamp_r15
In [49]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont = D # this corresponds to the (CONTAINING ...) constraint
In [50]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont_enc = None # this is to say the codec stays the same
In [51]: M.from_uper(b'\x00\xc2\x00\x04c\xdf$+\xb0\x10~HWA\x15\xb7\\\xd54,\x0e\xbd\xc2\xa8\xfdsd\xf1\xba\xc5\xe7\xa1u\x8dSC\xea\xd9"\x89\xd50D\x08\x91!\x1
...: d\x01\xd6\x1a\xc0\x07\x80k&L\x190p\xc1\x8bF\xcd\x19\xdau\x80\x04\xa1\x83\xf6\x16k\x1b8\r \x00\x80\x00')
In [52]: print(M.to_asn1())
{
message c1 : measurementReport : {
criticalExtensions measurementReport : {
measResults {
measId 3,
measResultServingMOList {
{
servCellId 0,
measResultServingCell {
physCellId 99,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 100,
rsrq 66,
sinr 93
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 1,
ssb-Results {
rsrp 100,
rsrq 66,
sinr 93
}
}
}
}
}
}
}
},
measResultNeighCells measResultListNR : {
{
physCellId 86,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 46,
rsrq 53,
sinr 38
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 0,
ssb-Results {
rsrp 47,
rsrq 56,
sinr 42
}
},
{
ssb-Index 7,
ssb-Results {
rsrp 46,
rsrq 54,
sinr 39
}
},
{
ssb-Index 6,
ssb-Results {
rsrp 44,
rsrq 47,
sinr 30
}
},
{
ssb-Index 2,
ssb-Results {
rsrp 44,
rsrq 53,
sinr 38
}
},
{
ssb-Index 3,
ssb-Results {
rsrp 43,
rsrq 50,
sinr 34
}
},
{
ssb-Index 4,
ssb-Results {
rsrp 42,
rsrq 48,
sinr 34
}
}
}
}
}
}
},
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 CHOICE: utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
locationCoordinate-r16 '4307EC2CD636701A40'H,
locationSource-r16 '00'H
}
}
}
}
}
}
That's it.
Many thanks
I was actually looking for a way to introduce the CONTAINING link programmatically, so binding the LPP object to the RRC one within Python is a good solution for me.
Thank you very much for your help
Best regards
Dominique
From: Benoit Michau @.> Sent: Friday, February 11, 2022 3:00 PM To: P1sec/pycrate @.> Cc: Dominique Bressanelli @.>; Author @.> Subject: Re: [P1sec/pycrate] Question on best way to chain decoding with 2 different grammars (Issue #179)
WARNING: This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.
One way to manage it is at the ASN.1 level. OCTET STRING (and BIT STRING) can have a CONTAINING constraint, which indicates another ASN.1 object to be decoded from the OCTET STRING (or BIT STRING) buffer.
E.g.:
ComplexObj ::= SEQUENCE {
...
}
OctStr ::= OCTET STRING (CONTAINING ComplexObj)
I believe the simplest, and maybe only, way to do what you ask for is to build such a construct with your ASN.1 definitions. So you can modify your RRC NR specification, to enhance the definition of the locationTimestamp-r16 with such a (CONTAINING DisplacementTimeStamp-r15) declaration. You will also need to manage properly the import of the LPP object in the RRC NR definition. Otherwise, you can bind the LPP object to the RRC one within Python, doing something like this:
In [47]: M = NR_RRC_Definitions.UL_DCCH_Message
In [48]: D = LPP_PDU_Definitions.DisplacementTimeStamp_r15
In [49]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont = D # this corresponds to the (CONTAINING ...) constraint
In [50]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont_enc = None # this is to say the codec stays the same
In [51]: M.from_uper(b'\x00\xc2\x00\x04c\xdf$+\xb0\x10~HWA\x15\xb7\\xd54,\x0e\xbd\xc2\xa8\xfdsd\xf1\xba\xc5\xe7\xa1u\x8dSC\xea\xd9"\x89\xd50D\x08\x91!\x1
...: d\x01\xd6\x1a\xc0\x07\x80k&L\x190p\xc1\x8bF\xcd\x19\xdau\x80\x04\xa1\x83\xf6\x16k\x1b8\r \x00\x80\x00')
In [52]: print(M.to_asn1())
{
message c1 : measurementReport : {
criticalExtensions measurementReport : {
measResults {
measId 3,
measResultServingMOList {
{
servCellId 0,
measResultServingCell {
physCellId 99,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 100,
rsrq 66,
sinr 93
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 1,
ssb-Results {
rsrp 100,
rsrq 66,
sinr 93
}
}
}
}
}
}
}
},
measResultNeighCells measResultListNR : {
{
physCellId 86,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 46,
rsrq 53,
sinr 38
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 0,
ssb-Results {
rsrp 47,
rsrq 56,
sinr 42
}
},
{
ssb-Index 7,
ssb-Results {
rsrp 46,
rsrq 54,
sinr 39
}
},
{
ssb-Index 6,
ssb-Results {
rsrp 44,
rsrq 47,
sinr 30
}
},
{
ssb-Index 2,
ssb-Results {
rsrp 44,
rsrq 53,
sinr 38
}
},
{
ssb-Index 3,
ssb-Results {
rsrp 43,
rsrq 50,
sinr 34
}
},
{
ssb-Index 4,
ssb-Results {
rsrp 42,
rsrq 48,
sinr 34
}
}
}
}
}
}
},
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 CHOICE: utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
locationCoordinate-r16 '4307EC2CD636701A40'H,
locationSource-r16 '00'H
}
}
}
}
}
}
That's it.
— Reply to this email directly, view it on GitHubhttps://github.com/P1sec/pycrate/issues/179#issuecomment-1036241970, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHUUMPLBIPV37RK7QPTMG23U2UI6VANCNFSM5OEB2JBA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.**@.>>
Hi
Small additional request
Is there a way that the leading ASN.1 tag (here CHOICE) may be omitted ?
Instead of
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 CHOICE: utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
I would like to get:
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
Thank you very much for your help
Best regards
Dominique
From: Dominique Bressanelli Sent: Friday, February 11, 2022 5:05 PM To: P1sec/pycrate @.>; P1sec/pycrate @.> Cc: Author @.***> Subject: RE: [P1sec/pycrate] Question on best way to chain decoding with 2 different grammars (Issue #179)
Many thanks
I was actually looking for a way to introduce the CONTAINING link programmatically, so binding the LPP object to the RRC one within Python is a good solution for me.
Thank you very much for your help
Best regards
Dominique
From: Benoit Michau @.**@.>> Sent: Friday, February 11, 2022 3:00 PM To: P1sec/pycrate @.**@.>> Cc: Dominique Bressanelli @.**@.>>; Author @.**@.>> Subject: Re: [P1sec/pycrate] Question on best way to chain decoding with 2 different grammars (Issue #179)
WARNING: This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.
One way to manage it is at the ASN.1 level. OCTET STRING (and BIT STRING) can have a CONTAINING constraint, which indicates another ASN.1 object to be decoded from the OCTET STRING (or BIT STRING) buffer.
E.g.:
ComplexObj ::= SEQUENCE {
...
}
OctStr ::= OCTET STRING (CONTAINING ComplexObj)
I believe the simplest, and maybe only, way to do what you ask for is to build such a construct with your ASN.1 definitions. So you can modify your RRC NR specification, to enhance the definition of the locationTimestamp-r16 with such a (CONTAINING DisplacementTimeStamp-r15) declaration. You will also need to manage properly the import of the LPP object in the RRC NR definition. Otherwise, you can bind the LPP object to the RRC one within Python, doing something like this:
In [47]: M = NR_RRC_Definitions.UL_DCCH_Message
In [48]: D = LPP_PDU_Definitions.DisplacementTimeStamp_r15
In [49]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont = D # this corresponds to the (CONTAINING ...) constraint
In [50]: M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo
...: -r16', 'locationTimestamp-r16'))._const_cont_enc = None # this is to say the codec stays the same
In [51]: M.from_uper(b'\x00\xc2\x00\x04c\xdf$+\xb0\x10~HWA\x15\xb7\\xd54,\x0e\xbd\xc2\xa8\xfdsd\xf1\xba\xc5\xe7\xa1u\x8dSC\xea\xd9"\x89\xd50D\x08\x91!\x1
...: d\x01\xd6\x1a\xc0\x07\x80k&L\x190p\xc1\x8bF\xcd\x19\xdau\x80\x04\xa1\x83\xf6\x16k\x1b8\r \x00\x80\x00')
In [52]: print(M.to_asn1())
{
message c1 : measurementReport : {
criticalExtensions measurementReport : {
measResults {
measId 3,
measResultServingMOList {
{
servCellId 0,
measResultServingCell {
physCellId 99,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 100,
rsrq 66,
sinr 93
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 1,
ssb-Results {
rsrp 100,
rsrq 66,
sinr 93
}
}
}
}
}
}
}
},
measResultNeighCells measResultListNR : {
{
physCellId 86,
measResult {
cellResults {
resultsSSB-Cell {
rsrp 46,
rsrq 53,
sinr 38
}
},
rsIndexResults {
resultsSSB-Indexes {
{
ssb-Index 0,
ssb-Results {
rsrp 47,
rsrq 56,
sinr 42
}
},
{
ssb-Index 7,
ssb-Results {
rsrp 46,
rsrq 54,
sinr 39
}
},
{
ssb-Index 6,
ssb-Results {
rsrp 44,
rsrq 47,
sinr 30
}
},
{
ssb-Index 2,
ssb-Results {
rsrp 44,
rsrq 53,
sinr 38
}
},
{
ssb-Index 3,
ssb-Results {
rsrp 43,
rsrq 50,
sinr 34
}
},
{
ssb-Index 4,
ssb-Results {
rsrp 42,
rsrq 48,
sinr 34
}
}
}
}
}
}
},
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 CHOICE: utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
locationCoordinate-r16 '4307EC2CD636701A40'H,
locationSource-r16 '00'H
}
}
}
}
}
}
That's it.
— Reply to this email directly, view it on GitHubhttps://github.com/P1sec/pycrate/issues/179#issuecomment-1036241970, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHUUMPLBIPV37RK7QPTMG23U2UI6VANCNFSM5OEB2JBA. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.**@.>>
OK, I guess I went to fast. We should actually better mimic the compiler to produce a similar construct, what is not the case with what I provided before as an example.
First, we need to build a wrapper around the DisplacementTimeStamp-r15
object:
In [69]: _cont_locationTimestamp_r16 = CHOICE(name='DisplacementTimeStamp-r15', mode=MODE_TYPE, typeref=ASN1RefType(('LPP-PDU-Definitions', 'DisplacementTimeStamp-r15')))
Then, we can bind the NR RRC object to it:
In [70]: S = M.get_at(('message', 'c1', 'measurementReport', 'criticalExtensions', 'measurementReport', 'measResults', 'locationInfo-r16', 'commonLocationInfo-r16', 'locationTimestamp-r16'))
In [71]: S._const_cont = _cont_locationTimestamp_r16
In [72]: S._const_cont_enc = None
Finally, we need to declare the new wrapper object into the ASN.1 module, and re-initialize the module:
In [73]: from pycrate_asn1rt.init import init_modules
In [74]: NR_RRC_Definitions._all_.append(_cont_locationTimestamp_r16)
In [75]: init_modules(NR_RRC_Definitions)
Now, we can use the NR RRC object as its inner definition would have been:
CommonLocationInfo-r16 ::= SEQUENCE {
gnss-TOD-msec-r16 OCTET STRING OPTIONAL,
locationTimestamp-r16 OCTET STRING (CONTAINING DisplacementTimeStamp-r15) OPTIONAL,
locationCoordinate-r16 OCTET STRING OPTIONAL,
locationError-r16 OCTET STRING OPTIONAL,
locationSource-r16 OCTET STRING OPTIONAL,
velocityEstimate-r16 OCTET STRING OPTIONAL
}
This leads to the following decoding:
In [77]: M.from_uper(b'\x00\xc2\x00\x04c\xdf$+\xb0\x10~HWA\x15\xb7\\\xd54,\x0e\xbd\xc2\xa8\xfdsd\xf1\xba\xc5\xe7\xa1u\x8dSC\xea\xd9"\x89\xd50D\x08\x91!\x1d\x01\xd6\x1a\xc0\x07\x80k&L\x190p\xc1\x8bF\xcd\x19\xdau\x80\x04\xa1\x83\xf6\x16k\x1b8\r \x00\x80\x00')
In [78]: print(M.to_asn1())
{
message c1 : measurementReport : {
criticalExtensions measurementReport : {
measResults {
measId 3,
measResultServingMOList {
[...]
measResultNeighCells measResultListNR : {
[...]
locationInfo-r16 {
commonLocationInfo-r16 {
gnss-TOD-msec-r16 'AC3580'H,
locationTimestamp-r16 DisplacementTimeStamp-r15: utcTime-r15 : {
utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --,
utcTime-ms-r15 470
},
locationCoordinate-r16 '4307EC2CD636701A40'H,
locationSource-r16 '00'H
}
}
}
}
}
}
In [79]: S._val
Out[79]:
('DisplacementTimeStamp-r15',
('utcTime-r15',
{'utcTime-r15': ('22', '02', '08', '01', '46', '43', 'Z'),
'utcTime-ms-r15': 470}))
Hi
I am wondering about the best way to chain decoding when a first ASN.1 specification declares an OCTET STRING whose actual encoding is defined in a second ASN.1 specification.
To take a practical example, NR5G MeasResult as specified in 3GPP 38.331 includes a IE locationTimestamp-r16 defined as an OCTET STRING. The way to decode the content of this OCTET STRING is defined as a DisplacementTimeStamp-r15 structure in another 3GPP specification, namely 37.355
I compiled NR5G ASN.1 from 38.331 as NR5G_Dec_2021, and LPP ASN.1 from 37.355 as LPP_Dec_2021.
I first decode a MeasReport the flowwing way: dcch = NR5G_Dec_2021.NR_RRC_Definitions.UL_DCCH_Message dcch.from_uper(bytes.fromhex(message))
I get:
{ message c1 : measurementReport : { criticalExtensions measurementReport : { measResults { measId 3, measResultServingMOList { {
} }
I can now extract locationTimestamp-r16 and decode it.
ts = dcch()['message'][1][1]['criticalExtensions'][1]['measResults']['locationInfo-r16']['commonLocationInfo-r16']['locationTimestamp-r16']
timestamp = LPP_Dec_2021.LPP_PDU_Definitions.DisplacementTimeStamp_r15 timestamp.from_uper(ts) print (timestamp.to_asn1()) I get
utcTime-r15 : { utcTime-r15 "220208014643Z" -- Tue Feb 8 01:46:43 2022 --, utcTime-ms-r15 470 }
My question is how to chain the decoding operations from 2 different grammars such as to obtain something like:
{ message c1 : measurementReport : { criticalExtensions measurementReport : { measResults { measId 3, measResultServingMOList { {
} }
3GPP specification references:
38.331
MeasResults ::= SEQUENCE { measId MeasId, measResultServingMOList MeasResultServMOList, measResultNeighCells CHOICE { measResultListNR MeasResultListNR, ..., measResultListEUTRA MeasResultListEUTRA, measResultListUTRA-FDD-r16 MeasResultListUTRA-FDD-r16 } OPTIONAL, ..., [[ measResultServFreqListEUTRA-SCG MeasResultServFreqListEUTRA-SCG OPTIONAL, measResultServFreqListNR-SCG MeasResultServFreqListNR-SCG OPTIONAL, measResultSFTD-EUTRA MeasResultSFTD-EUTRA OPTIONAL, measResultSFTD-NR MeasResultCellSFTD-NR OPTIONAL ]], [[ measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL ]], [[ measResultForRSSI-r16 MeasResultForRSSI-r16 OPTIONAL, locationInfo-r16 LocationInfo-r16 OPTIONAL, ul-PDCP-DelayValueResultList-r16 UL-PDCP-DelayValueResultList-r16 OPTIONAL, measResultsSL-r16 MeasResultsSL-r16 OPTIONAL, measResultCLI-r16 MeasResultCLI-r16 OPTIONAL ]]
}
LocationInfo-r16 ::= SEQUENCE { commonLocationInfo-r16 CommonLocationInfo-r16 OPTIONAL, bt-LocationInfo-r16 LogMeasResultListBT-r16 OPTIONAL, wlan-LocationInfo-r16 LogMeasResultListWLAN-r16 OPTIONAL, sensor-LocationInfo-r16 Sensor-LocationInfo-r16 OPTIONAL, ... }
CommonLocationInfo-r16 ::= SEQUENCE { gnss-TOD-msec-r16 OCTET STRING OPTIONAL, locationTimestamp-r16 OCTET STRING OPTIONAL, locationCoordinate-r16 OCTET STRING OPTIONAL, locationError-r16 OCTET STRING OPTIONAL, locationSource-r16 OCTET STRING OPTIONAL, velocityEstimate-r16 OCTET STRING OPTIONAL }
locationTimeStamp Parameter type DisplacementTimeStamp defined in TS 37.355 [49]. The first/leftmost bit of the first octet contains the most significant bit.
37.355
DisplacementTimeStamp-r15 ::= CHOICE { utcTime-r15 UTC-Time-r15, gnssTime-r15 MeasurementReferenceTime, systemFrameNumber-r15 SFN-r15, measurementSFN-r15 INTEGER(-8192..9214), ... }
Thanks in advance.
Best regards