Home » Eclipse Projects » Eclipse Titan » Decoding NAS PDUs
Decoding NAS PDUs [message #1787575] |
Tue, 29 May 2018 11:12 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hi,
I am facing an issue in decoding NAS PDUs that are piggybacked in RRC messages in Titan. I believe there is an issue with the codec parametrization for those NAS PDU types but I seem to be unable to figure out the correct settings.
testcase nas_decoding_tests() runs on MTC {
// connection request original
var bitstring v_NasPduBitstring := oct2bit('07410108091010000000001002E06000040201D011'O);
log(v_NasPduBitstring);
var NAS_UL_Message_Type v_NAS_UL_Message;
var NasEmu_DecodedNasPduUL_Type v_DecodedNasPduUL;
if (f_NasEmu_Decvalue(v_NasPduBitstring, v_NAS_UL_Message) != 0) {
setverdict(fail);
} else {
v_DecodedNasPduUL.Msg := v_NAS_UL_Message;
}
log(v_DecodedNasPduUL);
setverdict(pass);
}
Below are the logs for the test and it seems like the first two nibbles are actually swapped, i.e. the securityHeaderType should be 0000 and the protocolDiscriminator 0111. Any idea how to correctly setup and configure the NAS decoding in Titan?
12:43:15.315968 EncodingTest.ttcn:157 Component type MTC_Component.MTC was initialized.
12:43:15.315998 EncodingTest.ttcn:162 '000001110100000100000001000010000000100100010000000100000000000000000000000000000000000000010000000000101110000001100000000000000000010000000010000000011101000000010001'B
12:43:15.316447 EncodingTest.ttcn:173 { Msg := { aTTACH_COMPLETE := { securityHeaderType := '0111'B, protocolDiscriminator := '0000'B, messageType := '01000001'B, esmMessage := { iei := '01'O, iel := '0809'O ("\b\t"), esmPdu := '1010000000001002E06000040201D011'O } } } }
12:43:15.316526 EncodingTest.ttcn:182 { securityHeaderType := '0000'B, protocolDiscriminator := '0111'B, messageType := <unbound>, esmMessage := <unbound> }
Thanks
Andre
|
|
| | | | | | | | | | | | |
Re: Decoding NAS PDUs [message #1790329 is a reply to message #1790157] |
Fri, 08 June 2018 11:50 |
|
Hi Andre,
could you do a 'make archive' on the project that contains
testcase nas_decoding_tests()
Please verify that the archive is compileable by unzipping it and running make.
If not , add whatever is missing to the Makefile, OTHER_FILES
And upload it here.
If for any reason you'd prefer not to upload, PM me on Twitter
https://twitter.com/jrama00
so we can find another solution.
BR
Elemer
|
|
| | | | |
Re: Decoding NAS PDUs [message #1790511 is a reply to message #1790448] |
Tue, 12 June 2018 07:59 |
|
Hi Andre ,
this module has an assumed codec that is not part of the package; it's referred as below:
module LibNAS_TypesAndValues {
.
.
.
} with {
encode "LibNAS"
}// End of module LibNAS_TypesAndValues
It can be coupled with the UE test suite but it has to be decorated with Titan -specific RAW codec instructions , which is probably more work than writing the TTCN-3 code from scratch.
I will publish soon some NAS protocol modules that use RAW encoding and have been tested with Titan.
We have several versions, maybe you could tell me which is the one you are aiming for so I can publish the closest.
Best regards
Elemer
|
|
|
Re: Decoding NAS PDUs [message #1790612 is a reply to message #1790511] |
Wed, 13 June 2018 14:54 |
Botond Baranyi Messages: 55 Registered: February 2016 |
Member |
|
|
Hi Andre,
the problem with the way you used the variant 'FIELDORDER(msb)' is that the field type 'ATTACH_COMPLETE.protocolDiscriminator' uses the user-defined codec 'NAS Types', not the RAW codec, because it has no 'encode' attribute of its own, and the referenced type's (ProtocolDiscriminator) encode "NAS Types" attribute takes precedence over the parent type's (ATTACH_COMPLETE) encode "RAW".
This means that the variant is treated as a user-defined encoding variant, not a RAW encoding variant, and is thus ignored by the compiler (there is even a warning displayed that it will be ignored).
To fix this you need to explicitly set the field's encoding to RAW, like this:
type record ATTACH_COMPLETE {
...
} with {
encode (protocolDiscriminator) "RAW";
variant (securityHeaderType, protocolDiscriminator) "FIELDORDER(msb)"
};
I've also noticed that the test case (nas_decoding_tests) expects the chosen field in the union to be 'aTTACH_REQUEST', but the chosen field after decoding is 'aTTACH_COMPLETE'. This is because the union has no variant attributes, so it has to pass the given data to every field (in the order of their declaration), and the first one to successfully decode it will be the chosen one (in this case 'aTTACH_COMPLETE' successfully decodes the data, so it becomes the chosen field, before decoding it as 'aTTACH_REQUEST' is even attempted).
I'm not familiar with this protocol, but I've noticed that all of the union's fields are records that start with the same 3 fields ('securityHeaderType', 'protocolDiscriminator' and 'messageType'). If the chosen field in the union depends on the values of these fields, then the 3 fields could be moved to a new top-level record, whose 4th field is the union, and the union could be given a 'CROSSTAG' variant attribute (to determine which union field to choose based on the 3 fields).
For example:
type record NAS_UL_Message_Type {
SecurityHeaderType securityHeaderType,
ProtocolDiscriminator protocolDiscriminator,
MessageType messageType,
NAS_UL_Message_Choice choice
}
with {
variant (choice) "CROSSTAG(aTTACH_COMPLETE, protocolDiscriminator = '0000'B;
aTTACH_REQUEST, protocolDiscriminator = '0001'B;
...
)"
}
type union NAS_UL_Message_Choice {
ATTACH_COMPLETE aTTACH_COMPLETE,
ATTACH_REQUEST aTTACH_REQUEST,
...
}
Hope this helps.
Best regards,
Botond Baranyi
[Updated on: Wed, 13 June 2018 15:43] Report message to a moderator
|
|
|
Re: Decoding NAS PDUs [message #1791003 is a reply to message #1790612] |
Thu, 21 June 2018 10:38 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hey Botond, all,
sorry for the delay and thanks for looking into the issue. I've now played around following your suggestions but still can't decode it properly with the built-in types.
I've followed your suggestions and decorated all union members (that have the fields) with:
type record ATTACH_COMPLETE {
...
} with {
encode (protocolDiscriminator) "RAW";
variant (securityHeaderType, protocolDiscriminator) "FIELDORDER(msb)"
};
That seemed to have worked ok and the fields are extracted ok (although the wrong type is selected).
12:27:57.444458 NAS_Codec_Test.ttcn:37 dec_3GPP_PDU_NAS_EPS(): Stream before decoding: '07417208991007000000994605F070C040180005025AD011D15C0A003103E5E0349011035758A65D0100C1'O
12:27:57.444484 NAS_Codec_Test.ttcn:37 dec_3GPP_PDU_NAS_EPS(): Decoded @EPS_NAS_MsgContainers.NAS_UL_Message_Type: { aTTACH_COMPLETE := { securityHeaderType := '0000'B, protocolDiscriminator := '0111'B, messageType := '01000001'B, esmMessage := { iei := '72'O ("r"), iel := '0899'O, esmPdu := '1007000000994605F070C040180005025AD011D15C0A003103E5E0349011035758A65D0100C1'O } } }
12:27:57.444507 NAS_Codec_Test.ttcn:38 { aTTACH_COMPLETE := { securityHeaderType := '0000'B, protocolDiscriminator := '0111'B, messageType := '01000001'B, esmMessage := { iei := '72'O ("r"), iel := '0899'O, esmPdu := '1007000000994605F070C040180005025AD011D15C0A003103E5E0349011035758A65D0100C1'O } } }
12:27:57.444546 NAS_Codec_Test.ttcn:49 { Msg := { aTTACH_COMPLETE := { securityHeaderType := '0000'B, protocolDiscriminator := '0111'B, messageType := '01000001'B, esmMessage := { iei := '72'O ("r"), iel := '0899'O, esmPdu := '1007000000994605F070C040180005025AD011D15C0A003103E5E0349011035758A65D0100C1'O } } } }
Your second suggestions, i.e. putting securityHeaderType, protocolDiscriminator and messageType into the parent record wont work for two reasons. First, not all NAS_UL_Message's have them (98% do but not all) and second because I'd really like to keep the types as much as possible like they are because each change also requires changes in the ETSI code which I'd like to avoid as much as possible.
Anyway, I've now carried on and decorated the NAS_UL_Message_Type union with the tag specifier like this (so messageType:='01000001'B shall decode to ATTACH_REQUEST).
type union NAS_UL_Message_Type { /* NAS message with direction 'UE to network ' or 'both' */
ATTACH_COMPLETE aTTACH_COMPLETE,
ATTACH_REQUEST aTTACH_REQUEST,
AUTHENTICATION_FAILURE aUTHENTICATION_FAILURE,
AUTHENTICATION_RESPONSE aUTHENTICATION_RESPONSE,
DETACH_ACCEPT dETACH_ACCEPT, /* direction: both */
DETACH_REQUEST_MO dETACH_REQUEST_MO,
EMM_STATUS eMM_STATUS, /* direction: both */
EXT_SERVICE_REQUEST eXT_SERVICE_REQUEST,
GUTI_REALLOCATION_COMPLETE gUTI_REALLOCATION_COMPLETE,
IDENTITY_RESPONSE iDENTITY_RESPONSE,
SECURITY_MODE_COMPLETE sECURITY_MODE_COMPLETE,
SECURITY_MODE_REJECT sECURITY_MODE_REJECT,
SECURITY_PROTECTED_NAS_MESSAGE sECURITY_PROTECTED_NAS_MESSAGE,
SERVICE_REQUEST sERVICE_REQUEST,
TRACKING_AREA_UPDATE_COMPLETE tRACKING_AREA_UPDATE_COMPLETE,
TRACKING_AREA_UPDATE_REQUEST tRACKING_AREA_UPDATE_REQUEST,
UL_NAS_TRANSPORT ul_NAS_TRANSPORT,
ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT aCTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT,
ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT aCTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT aCTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT aCTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT,
BEARER_RESOURCE_ALLOCATION_REQUEST bEARER_RESOURCE_ALLOCATION_REQUEST,
BEARER_RESOURCE_MODIFICATION_REQUEST bEARER_RESOURCE_MODIFICATION_REQUEST,
DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT dEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT,
ESM_INFORMATION_RESPONSE eSM_INFORMATION_RESPONSE,
ESM_STATUS eSM_STATUS, /* direction: both */
MODIFY_EPS_BEARER_CONTEXT_ACCEPT mODIFY_EPS_BEARER_CONTEXT_ACCEPT,
MODIFY_EPS_BEARER_CONTEXT_REJECT mODIFY_EPS_BEARER_CONTEXT_REJECT,
PDN_CONNECTIVITY_REQUEST pDN_CONNECTIVITY_REQUEST,
PDN_DISCONNECT_REQUEST pDN_DISCONNECT_REQUEST,
ACTIVATE_TEST_MODE_COMPLETE aCTIVATE_TEST_MODE_COMPLETE,
DEACTIVATE_TEST_MODE_COMPLETE dEACTIVATE_TEST_MODE_COMPLETE,
CLOSE_UE_TEST_LOOP_COMPLETE cLOSE_UE_TEST_LOOP_COMPLETE,
OPEN_UE_TEST_LOOP_COMPLETE oPEN_UE_TEST_LOOP_COMPLETE
} with {
variant "TAG(
sERVICE_REQUEST, securityHeaderType= '1100'B;
sERVICE_REQUEST, securityHeaderType= '1101'B;
sERVICE_REQUEST, securityHeaderType= '1110'B;
sERVICE_REQUEST, securityHeaderType= '1111'B;
sECURITY_PROTECTED_NAS_MESSAGE, securityHeaderType= '0001'B;
sECURITY_PROTECTED_NAS_MESSAGE, securityHeaderType= '0010'B;
sECURITY_PROTECTED_NAS_MESSAGE, securityHeaderType= '0011'B;
sECURITY_PROTECTED_NAS_MESSAGE, securityHeaderType= '0100'B;
sECURITY_PROTECTED_NAS_MESSAGE, securityHeaderType= '0101'B;
aTTACH_COMPLETE, messageType = '01000011'B;
aTTACH_REQUEST, messageType = '01000001'B;
aUTHENTICATION_FAILURE, messageType = '01011100'B;
aUTHENTICATION_RESPONSE, messageType = '01010011'B;
dETACH_ACCEPT, messageType = '01000110'B;
dETACH_REQUEST_MO, messageType = '01000101'B;
eMM_STATUS, messageType = '01100000'B;
eXT_SERVICE_REQUEST, messageType = '01001100'B;
gUTI_REALLOCATION_COMPLETE, messageType = '01010001'B;
iDENTITY_RESPONSE, messageType = '01010110'B;
sECURITY_MODE_COMPLETE, messageType = '01011110'B;
sECURITY_MODE_REJECT, messageType = '01011111'B;
tRACKING_AREA_UPDATE_COMPLETE, messageType = '01001010'B;
tRACKING_AREA_UPDATE_REQUEST, messageType = '01001000'B;
ul_NAS_TRANSPORT, messageType = '01100011'B;
aCTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT, messageType = '11000110'B;
aCTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT, messageType = '11000111'B;
aCTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT, messageType = '11000010'B;
aCTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT, messageType = '11000011'B;
bEARER_RESOURCE_ALLOCATION_REQUEST, messageType = '11010100'B;
bEARER_RESOURCE_MODIFICATION_REQUEST, messageType = '11010110'B;
dEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT, messageType = '11001110'B;
eSM_INFORMATION_RESPONSE, messageType = '11011010'B;
eSM_STATUS, messageType = '11101000'B;
mODIFY_EPS_BEARER_CONTEXT_ACCEPT, messageType = '11001010'B;
mODIFY_EPS_BEARER_CONTEXT_REJECT, messageType = '11001011'B;
pDN_CONNECTIVITY_REQUEST, messageType = '11010000'B;
pDN_DISCONNECT_REQUEST, messageType = '11010010'B;
aCTIVATE_TEST_MODE_COMPLETE, messageType = '11111111'B;
dEACTIVATE_TEST_MODE_COMPLETE, messageType = '11111101'B;
cLOSE_UE_TEST_LOOP_COMPLETE, messageType = '11111110'B;
oPEN_UE_TEST_LOOP_COMPLETE, messageType = '11111100'B;
aTTACH_REQUEST, OTHERWISE
)"
};
With this tag, however, the decoder isn't decoding anything and complains with:
12:17:35.833370 NAS_Codec_Test.ttcn:37 dec_3GPP_PDU_NAS_EPS(): Stream before decoding: '07417208991007000000994605F070C040180005025AD011D15C0A003103E5E0349011035758A65D0100C1'O
12:17:35.833429 NAS_Codec_Test.ttcn:37 Dynamic test case error: While RAW-decoding type '@EPS_NAS_MsgContainers.NAS_UL_Message_Type': Can not decode type '@EPS_NAS_MsgContainers.NAS_UL_Message_Type', because invalid message was received
12:17:35.833445 NAS_Codec_Test.ttcn:37 setverdict(error): none -> error
12:17:35.833459 NAS_Codec_Test.ttcn:37 Performing error recovery.
Any idea why this happens?
If I comment out any of the fields in the TAG it will decode the union to exactly this type (i.e. the first it finds not specified and therefore valid). Are there any restirctions on which element (and in which order) can serve as identifier for the choice of a union? Can I somehow make the RAW decoder a bit more verbose to follow the decision it makes?
Thanks
Andre
|
|
|
Re: Decoding NAS PDUs [message #1791022 is a reply to message #1791003] |
Thu, 21 June 2018 14:51 |
Botond Baranyi Messages: 55 Registered: February 2016 |
Member |
|
|
Hi Andre,
With the 'TAG' coding instruction the RAW codec now correctly identifies 'aTTACH_REQUEST' as the selected field, but it fails to decode the field.
The decoded field looks like this, when the decoder runs out of bits:
aTTACH_REQUEST := {
securityHeaderType := '0000'B,
protocolDiscriminator := '0111'B,
messageType := '01000001'B,
nasKeySetId := {
iei := '2'H,
tsc := '1'B,
nasKeySetId := '011'B
},
epsAttachType := {
spare := '0'B,
typeValue := '100'B
},
oldGutiOrImsi := {
iei := '90'O,
iel := '09'O (" "),
idDigit1 := '0001'B,
oddEvenInd := '1'B,
typeOfId := '011'B,
otherDigits := '000000906954000F070C84015020A0051D11CDA5001033500E4E031931708565DA150010'O
},
ueNetworkCapability := <unbound>,
esmMessage := <unbound>,
oldPtmsiSignature := <unbound>,
additionalGuti := <unbound>,
lastVisitedRegisteredTai := <unbound>,
drxParameter := <unbound>,
msNetworkCapability := <unbound>,
oldLai := <unbound>,
tmsiStatus := <unbound>,
msClassmark2 := <unbound>,
msClassmark3 := <unbound>,
supportedCodecList := <unbound>,
addUpdateType := <unbound>
}
It seems that the octetstring field 'aTTACH_REQUEST.oldGutiOrImsi.otherDigits' decodes everything until the buffer's end, since it has no coding instructions or a fixed length restriction (its length is restricted to 0..10, but the RAW codec only takes fixed length restrictions into consideration). I'm assuming this is not intentional.
As for the 'TAG' coding instruction: you can't have an 'OTHERWISE' condition and other conditions (with fixed values) for the same field. This causes the 'OTHERWISE' condition to be ignored. Since the 'OTHERWISE' condition covers both cases anyway, the fixed condition should simply be removed.
The other conditions look fine to me (you can have multiple conditions with fixed values for a field, these will be treated as if there was an 'or' operator between them).
To my knowledge there is no way to make the decoder more verbose (I've managed to extract the mentioned partially decoded data by modifying the generated C++ code).
Best regards,
Botond Baranyi
|
|
| | | | | |
Re: Decoding NAS PDUs [message #1791046 is a reply to message #1791036] |
Fri, 22 June 2018 06:17 |
|
Hi Andre,
what Gabor wrote is very important: you may need to augment the existing TTCN-3 structures to add fields to determine absence /presence of certain fields, length of payload fields etc.
These extra fields will be calculated automatically when encoding end returned by the decoder when decoding.
Also , don't trust the result to work at once, it has to be verified.
Typical test cycle consists of:
-writing a number of representative sample templates and encode/ decode them in a loop
-encode the above templates and decode them with an independent decoder, if available
-get some encoded samples and decode them
Assembling a large RAW coded protocol module may take a couple of days or even one or two weeks for an experienced developer..
However this is still considerably less then writing the codec e.g. in C/C++.
Best regards
Elemer
|
|
|
Re: Decoding NAS PDUs [message #1791245 is a reply to message #1791046] |
Tue, 26 June 2018 15:37 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hey guys,
thanks again for the input. I admit that making the NAS types work with the RAW codec seems to be a bit more effort than I actually expected but at the same time I agree it probably still easier than writing one from scratch.
Regarding Gabor's suggestion it actually turns out that I even need to decorate some of the mandatory fields, for example in a ATTACH_REQUEST, with PRESENCE or similar tags, because they use types, like the nasKeySetId that itself has an optional IEI, but is always present in an ATTACH_REQUEST type.
My approach for doing that is like this. Because there is no explicit keyword to define that a field is NOT present, I made its presence depend on a value that will not be set, i.e.
variant (nasKeySetId.iei) "PRESENCE(securityHeaderType = '1111'B)" .
That works ok but with the optional fields within the ATTACH_REQUEST it's a bit more difficult because it depends on the parent type and the value of the IEI whether the field is present or not. For example, the oldPtmsiSignature in the ATTACH_REQUEST: it's optional in an ATTACH_REQUEST and is present if the value of the first decoded octet is '19'O (oldPtmsiSignature.iei). How can I express this?
Further, I found debugging the RAW decoder very cumbersome because all modifications that I do in the generated C++ code are gone after recompilation. It would actually be very helpful to have the intermediate decoded output like in Botond's post generated on request.
type record ATTACH_REQUEST { /* 24.301 cl. 8.2.4
Significance: dual
Direction: UE to network */
SecurityHeaderType securityHeaderType, /* cl. 9.3.1 M V 1/2 */
ProtocolDiscriminator protocolDiscriminator, /* cl. 9.2 M V 1/2 */
MessageType messageType, /* cl. 9.8 M V 1 */
NAS_KeySetIdentifier nasKeySetId, /* cl. 9.9.3.21 M V 1/2 */
EPS_AttachType epsAttachType, /* cl. 9.9.3.11 M V 1/2 */
MobileIdentity oldGutiOrImsi, /* cl. 9.9.3.12 M LV 5-12 */
UE_NetworkCap ueNetworkCapability, /* cl. 9.9.3.34 M LV 3-14 */
ESM_MessageContainer esmMessage, /* cl. 9.9.3.15 M LV-E 2-n */
PTMSI_Signature oldPtmsiSignature optional, /* cl 10.5.5.8 of 24.008 O TV 4 IEI=Ox19*/
MobileIdentity additionalGuti optional, /* cl 9.9.3.12 O TLV 13 IEI=Ox50*/
TrackingAreaId lastVisitedRegisteredTai optional, /* cl. 9.9.3.32 O TV 6 IEI=0x52 */
DRXparameter drxParameter optional, /* cl. 9.9.3.8 O TV 3 IEI=Ox5c */
MS_NetworkCap msNetworkCapability optional, /* cl. 9.9.3.20 O TLV 4-10 IEI=Ox31 */
LocAreaId oldLai optional, /* cl. 9.9.2.2 O TV 6 IEI=0x13 */
TMSI_Status tmsiStatus optional, /* cl. 9.9.2.31 O TV 1 IEI=0x9- */
MS_Clsmk2 msClassmark2 optional, /* cl. 9.9.2.4 O TLV 5 IEI=0x11 */
MS_Clsmk3 msClassmark3 optional, /* cl. 9.9.2.5 O TLV 2-34 IEI=0x20 */
CodecList supportedCodecList optional, /* cl. 9.9.2.10 O TLV 5-n IEI=0x40 */
AdditionalUpdateType addUpdateType optional /* cl.9.9.3.0B O TV 1 IEI=0xF @sic R5s100135 sic@ */
} with {
encode (protocolDiscriminator) "RAW";
variant (securityHeaderType, protocolDiscriminator) "FIELDORDER(msb)"
variant (nasKeySetId.iei) "PRESENCE(securityHeaderType = '1111'B)"
variant (oldGutiOrImsi.iei) "PRESENCE(securityHeaderType = '1111'B)"
variant (ueNetworkCapability.iei) "PRESENCE(securityHeaderType = '1111'B)"
variant (esmMessage.iei) "PRESENCE(securityHeaderType = '1111'B)"
variant (oldPtmsiSignature) "PRESENCE(oldPtmsiSignature.iei = '19'O)"
};
Thanks
Andre
|
|
|
Re: Decoding NAS PDUs [message #1791544 is a reply to message #1791245] |
Mon, 02 July 2018 11:00 |
|
Hi Andre,
regarding your first question I looked into a similar NAS_EPS_Types file that has been written for RAW:
//Reference: 3GPP 24.301 v15.0.0 (24.008 v15.0.0, 24.011 v14.0.0, 24.161 v14.0.0
// 9.9.3.26 - 10.5.5.8/24.008
type record P_TMSISignatureTV
{
OCT1 elementIdentifier,
OCT3 valueField
} with { variant "PRESENCE (elementIdentifier = '19'O)"; }
:
type record DevicePropertiesTV
{
BIT1 lowPriority,
BIT3 spare,
BIT4 elementIdentifier
}
:
type record GPRSTimer2TLV
{
OCT1 elementIdentifier,
LIN1 lengthIndicator,
GPRSTimer2V gprsTimer2
} with {
variant (lengthIndicator) "LENGTHTO (gprsTimer2)"
}
:
:
type record PDU_NAS_EPS_AttachRequest
{
BIT4 securityHeaderType,
BIT8 messageType,
EPS_AttachTypeV ePS_attachType,
NAS_KeySetIdentifierV nasKeySetId,
EPS_MobileIdentityLV ePSMobileId,
UENetworkCapabilityLV uENetworkCapability,
ESM_MessageContainerLVE eSM_MessageContainer,
P_TMSISignatureTV old_P_TMSISignature optional,
EPS_MobileIdentityTLV additionalGUTI optional,
TrackingAreaIdentityTV lastVisitedRegisteredTAI optional,
DRXParameterTV dRXParameter optional,
MSNetworkCapabilityTLV mSNetworkCapability optional,
LocationAreaIdentificationTV oldLocationAreaIdentification optional,
TMSIStatusTV tMSIStatusTV optional,
MobileStationClassmark2_TLV mobileStationClassmark2 optional,
MobileStationClassmark3_TLV mobileStationClassmark3 optional,
SupportedCodecListTLV supportedCodecList optional,
AdditionalUpdateTypeTV additionalUpdateType optional,
VoiceDomainPrefandUEsettingsTLV voiceDomainPrefandUEsettings optional,
DevicePropertiesTV deviceProperties optional,
GUTI_TypeTV oldGUTI_Type optional,
MS_NetworkFeatureSupportTV mS_NetworkFeatureSupport optional,
NetworkResourceIdentifierContainerTLV tMSIBasedNRIContainer optional,
GPRSTimer2TLV t3324 optional,
GPRSTimer3TLV t3412_Extended optional,
ExtendedDRXParametersTLV extendedDRXParameters optional
} with {
variant "TAG (mS_NetworkFeatureSupport, elementIdentifier = '1100'B;
deviceProperties, elementIdentifier = '1101'B;
t3324, elementIdentifier = '6A'O;
t3412_Extended, elementIdentifier = '5E'O;)";
}
As you see, the PRESENCE variant appears one level lower, at
P_TMSISignatureTV. so you don't have to reiterate it in every restructure that contains a field of this type.
Regarding your second issue, your wish is noted, in fact it's since long time on our to-do list to have a debugger for RAW.
Two things stopped us from doing it so far:
it needs quite an amount of invested effort and, as soon as users get the hang of the codec, they don't feel it's so urgently needed anymore.
In general, for codecs we aim for speed and simplicity as opposed to sophistication and user friendliness. It pays at performance testing, where
encoding/decoding cycles are the most resource consuming.
Best regards
Elemer
|
|
|
Re: Decoding NAS PDUs [message #1791653 is a reply to message #1791544] |
Tue, 03 July 2018 10:45 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hey guys,
the problem is that the UE testsuite doesn't define different types for the MobileIdentity for example that can may or may not contain the IEI. In the attach request, for example, the first occurrence is MobileIdentity in LV mode only, so without T but with length and values. Then the second occurrence is MobileIdentity in TLV mode. Here is the record definition:
type record MobileIdentity {
IEI8_Type iei optional, // '00100011'B
Type4Length_Type iel,
BcdDigit_Bit idDigit1, // 1st identitity digit
B1_Type oddEvenInd, // Odd/even indicator
NAS_IdType typeOfId, // Type of identity
octetstring otherDigits length(0..10)// Other identity digits (10 octets rather than 8 to cover Guti as well)
};
I guess there are two possibilities, one is defining a second type called MobileIdentityV that doesn't have the iei. I tried that with the NAS_KeySetIdentifierV which has the same issue and can confirm that it works. The drawback is that there are a lot of changes needed in all templates etc.
The second option is to somehow tell the RAW decoder to not decode the iei field in case some condition is met. But I wasn't successfull in doing so, at least something like this
variant (oldGutiOrImsi.iei) "PRESENCE(securityHeaderType = '1111'B)"
didn't work. Any idea how to achieve this, i.e. telling the RAW decoder _not_ to decode a field, without rewriting the types themselves?
Regarding the second issue, for now I've simply extended the RAW code-generator to log partially decoded types, works well and can be turned off at compile-time without performance penalties.
diff --git a/compiler2/record.c b/compiler2/record.c
index 22ce77e6..3cca0261 100644
--- a/compiler2/record.c
+++ b/compiler2/record.c
@@ -5361,6 +5361,14 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef,
}
}
src = mputstr(src, ");\n");
+
+ // log partially decoded message
+ src = mputprintf(src, " TTCN_Logger::begin_event(TTCN_DEBUG);\n");
+ src = mputprintf(src, " TTCN_Logger::log_event_str(\"{ %s := \");\n", sdef->elements[i].name);
+ src = mputprintf(src, " field_%s%s.log();\n", sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "");
+ src = mputprintf(src, " TTCN_Logger::log_event_str(\" }\");\n");
+ src = mputprintf(src, " TTCN_Logger::end_event();\n");
+
if (delayed_decode) {
src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n",
sdef->elements[i].raw.length);
Thanks
Andre
|
|
|
Re: Decoding NAS PDUs [message #1791661 is a reply to message #1791653] |
Tue, 03 July 2018 12:54 |
|
Hi Andre,
"The second option is to somehow tell the RAW decoder to not decode the iei field in case some condition is met. "
Sorry, this is not currently supported, although it might be a good idea.
Although it sounds painful, I'd recommend you take the first route.
As for RAW decode logger, yes, this is the way to go, but of course for all types simple and structured.
Best regards
Elemer
|
|
| |
Re: Decoding NAS PDUs [message #1791767 is a reply to message #1791703] |
Thu, 05 July 2018 06:59 |
|
Hi Andre,
can you please write a proposal with a simple but complete example
demonstrating how this should work?
I don't think a new keyword should be necessary , we have OTHERWISE which works with TAG for instance,
semantically that should be equivalent.
Thank you and best regards
Elemer
|
|
|
Re: Decoding NAS PDUs [message #1791793 is a reply to message #1791767] |
Thu, 05 July 2018 11:33 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hey,
sure, I am happy to explain and document what would be needed. Just to make sure again, this is only needed if one wants to use the ETSI defined TTCN3 typedefs for NAS decoding. Needless to say that your approach with having separate types for "type" and "length and value" obviously works with the current RAW coded (as shown in the example you sent). But let's try to get the ETSI code work as well
Let's take this type for example:
type record ESM_MessageContainer { /* 24.301 cl. 9.9.3.15 */
IEI8_Type iei optional, /* present in case of TLV; omit in case of LV */
INT16b iel,
octetstring esmPdu optional /* ESM PDU without NAS security header;
type is FFS */
} with {
variant (iel) "LENGTHTO(esmPdu)";
};
This type contains the element identifier in some messages and in some not (in those in which this field is mandatory like in the attach request for example). So what happens is that the RAW decoder _always_ decodes the iei field.
What would be ideal, semantically, would be to express that condition, i.e. if the IEI is present or not, in the parent type, e.g. the attach request. I've made up something using the PRESENCE tag, trying to negate it.
type record ATTACH_REQUEST { /* 24.301 cl. 8.2.4
Significance: dual
Direction: UE to network */
SecurityHeaderType securityHeaderType, /* cl. 9.3.1 M V 1/2 */
ProtocolDiscriminator protocolDiscriminator, /* cl. 9.2 M V 1/2 */
MessageType messageType, /* cl. 9.8 M V 1 */
NAS_KeySetIdentifierV nasKeySetId, /* cl. 9.9.3.21 M V 1/2 */
EPS_AttachType epsAttachType, /* cl. 9.9.3.11 M V 1/2 */
MobileIdentityV oldGutiOrImsi, /* cl. 9.9.3.12 M LV 5-12 */
UE_NetworkCap ueNetworkCapability, /* cl. 9.9.3.34 M LV 3-14 */
ESM_MessageContainer esmMessage, /* cl. 9.9.3.15 M LV-E 2-n */
PTMSI_Signature oldPtmsiSignature optional, /* cl 10.5.5.8 of 24.008 O TV 4 IEI=Ox19*/
MobileIdentity additionalGuti optional, /* cl 9.9.3.12 O TLV 13 IEI=Ox50*/
TrackingAreaId lastVisitedRegisteredTai optional, /* cl. 9.9.3.32 O TV 6 IEI=0x52 */
DRXparameter drxParameter optional, /* cl. 9.9.3.8 O TV 3 IEI=Ox5c */
MS_NetworkCap msNetworkCapability optional, /* cl. 9.9.3.20 O TLV 4-10 IEI=Ox31 */
LocAreaId oldLai optional, /* cl. 9.9.2.2 O TV 6 IEI=0x13 */
TMSI_Status tmsiStatus optional, /* cl. 9.9.2.31 O TV 1 IEI=0x9- */
MS_Clsmk2 msClassmark2 optional, /* cl. 9.9.2.4 O TLV 5 IEI=0x11 */
MS_Clsmk3 msClassmark3 optional, /* cl. 9.9.2.5 O TLV 2-34 IEI=0x20 */
CodecList supportedCodecList optional, /* cl. 9.9.2.10 O TLV 5-n IEI=0x40 */
AdditionalUpdateType addUpdateType optional /* cl.9.9.3.0B O TV 1 IEI=0xF @sic R5s100135 sic@ */
} with {
encode (protocolDiscriminator, nasKeySetId, epsAttachType) "RAW";
variant (securityHeaderType, protocolDiscriminator, nasKeySetId,epsAttachType,oldGutiOrImsi,ueNetworkCapability) "FIELDORDER(msb)"
variant (esmMessage.iei) "PRESENCE(NULL)"
variant "TAG (oldPtmsiSignature, iei = '19'O;
additionalGuti, iei = '50'O;
lastVisitedRegisteredTai, iei = '52'O;
drxParameter, iei = '5c'O;)";
};
So basically don't decode esmMessage.iei in case it's an attach_accept.
Looking at the first part of the generated RAW decoder, we can see that there is only the limit check for the iei field.
int ESM__MessageContainer::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, boolean no_err, int, boolean)
{ (void)no_err;
int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);
limit-=prepaddlength;
size_t last_decoded_pos = p_buf.get_pos_bit();
int decoded_length = 0;
int decoded_field_length = 0;
raw_order_t local_top_order;
if(p_td.raw->top_bit_order==TOP_BIT_INHERITED)local_top_order=top_bit_ord;
else if(p_td.raw->top_bit_order==TOP_BIT_RIGHT)local_top_order=ORDER_MSB;
else local_top_order=ORDER_LSB;
int value_of_length_field1 = 0;
if (limit > 0){
size_t fl_start_pos = p_buf.get_pos_bit();
decoded_field_length = field_iei().RAW_decode(NAS__CommonTypeDefs::IEI8__Type_descr_, p_buf, limit, local_top_order, TRUE);
TTCN_Logger::begin_event(TTCN_DEBUG);
TTCN_Logger::log_event_str("{ iei := ");
field_iei().log();
TTCN_Logger::log_event_str(" }");
TTCN_Logger::end_event();
if (decoded_field_length < 1) {
field_iei = OMIT_VALUE;
p_buf.set_pos_bit(fl_start_pos);
} else {
decoded_length+=decoded_field_length;
limit-=decoded_field_length;
last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());
}
}
else field_iei=OMIT_VALUE;
I've checked the decoding is correct by commenting out the decoding in the generated C++.
Basically what would be needed is to have the check expressed above to skip the IEI decoding in case the above mentioned condition is matched. I assume the parent type is available in the AST to verify that PRESENCE condition.
Please let me know if anything is unclear or you need any further example.
Thanks in advance
Andre
|
|
|
Re: Decoding NAS PDUs [message #1791797 is a reply to message #1791793] |
Thu, 05 July 2018 12:37 |
|
Hi Andre,
so if I understand correctly, presence or absence of iei field in ESM_MessageContainer is a user decision, that you wan to indicate with the PRESENCE variant?
And it does not correlate with anything else.?
If this is correct , then why not set it simply to omit when encoding and decode it as it comes ( assuming that the other end encodes it properly in which case it will be set to omit) ?
Any error in encoding this will not be detected on codec or type level but on template level.
Or am I missing something here?
BR
Elemer
|
|
| |
Re: Decoding NAS PDUs [message #1791831 is a reply to message #1791813] |
Thu, 05 July 2018 19:58 |
Andre Puschmann Messages: 57 Registered: March 2018 |
Member |
|
|
Hi Elemer,
Quote:so if I understand correctly, presence or absence of iei field in ESM_MessageContainer is a user decision, that you wan to indicate with the PRESENCE variant?
And it does not correlate with anything else.?
That's right. Well, this would be one option to model this using the current type definitions. But what is important here is that is must not be per type but per field. This is because some types are actually present as mandatory fields (without IEI) and as optional field (with IEI) in the same record. For example, type MobileIdentity in ATTACH_REQUEST. But also note that it's not the entire record that is absent or present, but only one field inside the nested record.
So semantically, when decoding a field of type X, whether the IEI is decoded or not depends on the actual field and not solely on the type.
Quote:If this is correct , then why not set it simply to omit when encoding and decode it as it comes ( assuming that the other end encodes it properly in which case it will be set to omit) ?
I've not tried encoding it but I assume this would work, yes. But decoding does not, as you already assumed.
Another option would be to have a keyword to set the value of a field to a specific value if some condition is met or, in a parent record, to explicitly set the content of a nested field. In this case one could do this:
type record ATTACH_REQUEST { /* 24.301 cl. 8.2.4
Significance: dual
Direction: UE to network */
...
ESM_MessageContainer esmMessage, /* cl. 9.9.3.15 M LV-E 2-n */
...
} with {
variant (esmMessage.iei) "SETVALUE(omit)"
};
Thanks
Andre
|
|
|
Re: Decoding NAS PDUs [message #1791853 is a reply to message #1791831] |
Fri, 06 July 2018 08:45 |
|
Hi Andre,
I have a clear picture now;
I can confirm that currently RAW cannot handle this; but we will look into extending PRESENCE accordingly; I don't have an ETA yet, but I'll keep you posted.
Best regards
Elemer
|
|
| | | | |
Goto Forum:
Current Time: Wed Sep 25 22:54:30 GMT 2024
Powered by FUDForum. Page generated in 0.06545 seconds
|