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=e8363aff0…
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