The templates for GSUP in GSUP_Types.ttcn seem to expect the GSUP IEs in a specific order, which shouldn't be required.
Also I cannot easily define certain GSUP IEs as not mattering.
Particularly, I added Source Entity and Destination Entity IEs, and now I would have liked to just add some source_entity := *, destination_entity := *, to trivially make all tr_GSUP() pass, whether these IEs are present or not.
Instead I have to now add them to a listing of IEs everywhere. That means the test suite will only work with the new osmo-msc and even if "nightly" works out, we will see "latest" failing, etc.
I'd like to use the semantics I am used to in e.g. BSSMAP messages: - order doesn't matter - easy ':= *' for items in the root tr_GSUP() template
What would it take to make GSUP messages match in this way?
~N
Hi Neels,
On Mon, Mar 25, 2019 at 01:58:21AM +0100, Neels Hofmeyr wrote:
The templates for GSUP in GSUP_Types.ttcn seem to expect the GSUP IEs in a specific order, which shouldn't be required.
It shouldn't be required like in any of the protocols we deal with. The reality is different, at least for the 3GPP defined specs: Order is strictly required. You may not change the order of IEs, even though there are IEIs in the TLV structure that would allow for it.
In Osmocom C language (and likely other implementations) we don't care on the receiver side, but to be a compliant transmitter, we must use the correct order.
For GSUP now we can of course do something completely different, if we want to.
I'm not sure what the GSUP specification document which we publish says about it.
I would personally argue in favor of not permitting any random order of IEs.
If you look at the various protocol Modules that Ericsson wrote for TTCN3, they all require the spec-mandated fixed order, contary to those "possibly more elgant/generic" protocol implementations that we added but which don't enforce any order.
Also I cannot easily define certain GSUP IEs as not mattering.
Particularly, I added Source Entity and Destination Entity IEs, and now I would have liked to just add some source_entity := *, destination_entity := *, to trivially make all tr_GSUP() pass, whether these IEs are present or not.
Instead I have to now add them to a listing of IEs everywhere. That means the test suite will only work with the new osmo-msc and even if "nightly" works out, we will see "latest" failing, etc.
why is that? You can easily have a "*" inside the list of IE templates to allow for zero or more additional IEs of any kind.
The GSUP IEs are defined as "type record of GSUP_IE GSUP_IEs;" which enforces strict ordering. One could theoretically use "type set of GSUP_IE GSUP_IEs" which is an unordered set allowing any order. However, a "set of" also permits for duplicate elements. Not sure if that's what you want.
An alternative is the "permutation" qualifier for a "record of" template, which basically says "all of those elements must be present exactly once, in any order possible". See slide 176 of TTCN3_P.pdf
So something like the combination of the change "record of" -> "set of" and the addition of a single '*' to the list of IEs should turn a receive template into what you'd like.
There's also the "superset" qualifier. So if you define a set of IE templates and state you want to permit any superset on that set, then also any additional attributes beyond those minimally requierd ones in the set are accepted. See slide 175 of the "TTCN3_P.pdf" presentation.
I'd like to use the semantics I am used to in e.g. BSSMAP messages:
- order doesn't matter
 
This is wrong. The BSSMAP dissector does not permit any order except the one specified in the specs!
Regards, Harald
Ok, wasn't actually aware that ordering is strict. But emphasizing ordering that much was actually the wrong angle in my prev mail.
I see now that what I need is template overlaying, and easier item access. It's like one layer of abstraction is missing.
If I want to get some value from a GSUP message, I have to use f_gsup_find_ie and further process the returned GSUP_IeValue.
For example, to get a source name from a received GSUP:
var GSUP_PDU prep_ho_req; GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST, pars.imsi, OSMO_GSUP_ENTITY_MSC_A, OSMO_GSUP_ENTITY_MSC_T, destination_name := remote_msc_name)) -> value prep_ho_req;
var GSUP_IeValue source_name_ie; f_gsup_find_ie(prep_ho_req, OSMO_GSUP_SOURCE_NAME_IE, source_name_ie); use(source_name_ie.source_name);
The last 3 lines would, when dealing with BSSAP, look more like:
use(prep_ho_req.source_name)
Composing GSUP templates is less flexible, because I can't easily build up on previous templates. In other PDU types I could do overlay like
template FOO_PDU tr_foo := { item := default_item, other := ?, other2 := omit }
template FOO_PDU tr_foo_xyz := tr_foo { other := special_variant }
But with GSUP it would have to be done like: traverse the list, find the position and work on that. This weird contraption illustrates the quirkiness:
private function f_gen_tr_ss_ies( template hexstring imsi, template OCT4 sid := ?, template GSUP_SessionState state := ?, template octetstring ss := ? ) return template GSUP_IEs { /* Mandatory IEs */ var template GSUP_IEs ies := { tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_SessionId(sid), tr_GSUP_IE_SessionState(state) }; var integer last_idx := 3;
/* Optional SS payload */ if (istemplatekind(ss, "*")) { ies[3] := *; last_idx := last_idx + 1; } else if (not istemplatekind(ss, "omit")) { ies[3] := tr_GSUP_IE_SSInfo(ss); last_idx := last_idx + 1; }
ies[last_idx] := tr_GSUP_IE_Source_Entity(OSMO_GSUP_ENTITY_MSC_USSD); last_idx := last_idx + 1; ies[last_idx] := tr_GSUP_IE_Destination_Entity(OSMO_GSUP_ENTITY_EUSE); last_idx := last_idx + 1;
return ies; }
Better would be
template tr_ss(imsi, sid, state, ss) := tr_GSUP { imsi := imsi, ... }
where things like '*' and 'omit' trivially just work TM, and some other layer should take care of composing a list of IEs from this record. In this way I would be able to add new IEs in one single place to make all code work again.
Compare this patch, where each and every GSUP composition has to be touched: http://git.osmocom.org/osmo-ttcn3-hacks/commit/?h=neels/ho&id=e8363aff0c...
Furthermore, what would be really nice for inter-MSC testing: if I could use templates for the inter-MSC BSSAP PDU included in the GSUP PDU directly. So far I have the PDU included in the GSUP as an octetstring, which means it can't intelligently match templates. I guess that could be simple enough to achieve, but one limitation is that the included PDU could actually be RANAP. We could model our GSUP AN-APDU in TTCN3 to always expect BSSAP messages, in practice would work fine, but it would be a bit of a cheat. Either way, I am not sure how to implicitly de-/encode the enclosed PDU.
An example of where this would help -- I am currently trying to see whether I can do some SMS negotiation across the E link:
On a BSSAP link it is simple:
var PDU_DTAP_MT dtap_mt; l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt)); BSSAP.receive(tr_PDU_DTAP_MT(l3_mt, spars.dlci)) -> value dtap_mt;
In inter-MSC GSUP the same thing becomes something like: (Not actually sure if this compiles etc.)
l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt)); var GSUP_PDU gsup_l3_mt; GSUP.receive(tr_GSUP_E_AN_APDU) -> value gsup_l3_mt; <--- receive *ANY* PDU var GSUP_IeValue an_apdu; f_gsup_find_ie(gsup_l3_mt, OSMO_GSUP_AN_APDU_IE, an_apdu); <--- look up in list
var PDU_ML3_NW_MS dtap_mt := dec_PDU_ML3_NW_MS(an_apdu.an_apdu.pdu); if (not match(dtap_mt, l3_mt)) { <--- match later setverdict(fail, "Unexpected DTAP from remote MSC:", dtap_mt); mtc.stop; }
I think I'll rather not grind through an entire SMS negotiation like that... (I guess I'll rather do a simpler *#100# for now)
On a meta level, I feel that getting the TTCN3 side to work out for what I want to test is a whole nother chapter, adding a complete new business item to the road towards reaching inter-MSC HO. Testing in TTCN3 saves time compared to testing with real hardware once the test exists, and produces nice tests for all of the future. But I am currently feeling side tracked by tweaking these things to work out nicely and would like to rather spend my time implementing the MNCC call forwarding.
Is there a chance that anyone else than me can work out inter-MSC testing in TTCN, or rather, spend time to work out above two issues in general, to make enhancing the tests easier for me?
A dream goal would be to be able to use other functions like f_mt_sms() 1:1, with some trivial switch that does all the BSSAP.send and BSSAP.receive via GSUP instead of direct BSSAP. I guess we can't do that though, can we?
You can easily have a "*" inside the list of IE templates to allow for zero or more additional IEs of any kind.
Ok, that could make it simpler, but that is semantically a different thing than *-ing single items in a record. Now suddenly I am allowing any and all garbage IEs.
The GSUP IEs are defined as "type record of GSUP_IE GSUP_IEs;" which enforces strict ordering. One could theoretically use "type set of GSUP_IE GSUP_IEs"
Ok, I see. Sorry to have emphasized ordering too much, it was actually a wrong perception of mine that the ordering is the pivotal point, wrote the mail after enhancing above f_gen_tr_ss_ies().
Permutation and superset also sound interesting, didn't know about them. Still I have a feeling that they are actually too permissive. And it's more about template overlaying and accessing members than ignoring new items.
I would rather avoid wildcard accepting any IEs, related or not. With a template record, we would explicitly add just the new items, and allow just them to be *. AFAICT that's not possible with an IE list?
~N
On Mon, Mar 25, 2019 at 10:51:01PM +0100, Neels Hofmeyr wrote:
where things like '*' and 'omit' trivially just work TM, and some other layer should take care of composing a list of IEs from this record.
To clarify, the idea is to not match the IE lists of incoming messages, but do all message matching on the template record level instead. Like it happens in BSSAP AFAICT.
~N