Hey Harald,
did you have this in mind when mentioning that the parsing of the data derived informations could be driven by a struct?
z.
From 594cf586dedaecfc5e755a6d0fc9ac69dc513e91 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther zecke@selfish.org Date: Mon, 29 Jun 2009 17:21:37 +0200 Subject: [PATCH] Generic data derived informations parsing...
Declare what elements to parse in a struct and then trigger the generic parsing routine. --- openbsc/src/msc_mncc.c | 211 ++++++++++++++++++++--------------------------- 1 files changed, 90 insertions(+), 121 deletions(-)
diff --git a/openbsc/src/msc_mncc.c b/openbsc/src/msc_mncc.c index b54e184..5329fa1 100644 --- a/openbsc/src/msc_mncc.c +++ b/openbsc/src/msc_mncc.c @@ -112,6 +112,39 @@ static const char *cc_state_names[] = { "illegal state 31", };
+typedef int (*dd_decoder)(void* data, const u_int8_t *lv); + +struct dd_parser { + int information_element; + int mncc_field; + int offset; + dd_decoder decoder; +}; + +#define DECLARE_DECODER3(IE_NAME, M_NAME, name) \ + { .information_element = GSM48_IE_##IE_NAME, \ + .mncc_field = MNCC_F_##M_NAME, \ + .offset = offsetof(struct gsm_mncc, name), \ + .decoder = (dd_decoder)decode_##name, \ + } + + +#define DECLARE_DECODER(NAME, name) \ + DECLARE_DECODER3(NAME, NAME, name) + +static void parse_data_derived_information(struct dd_parser *parser, const int length, + struct tlv_parsed *tp, struct gsm_mncc *rel) +{ + int i; + + for (i = 0; i < length; ++i) { + if (TLVP_PRESENT(tp, parser[i].information_element)) { + rel->fields |= parser[i].mncc_field; + parser[i].decoder(rel + parser[i].offset, + TLVP_VAL(tp, parser[i].information_element)-1); + } + } +}
static int mncc_handle_lchan_signal(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) @@ -1420,31 +1453,15 @@ static int msc_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg) memset(&disc, 0, sizeof(struct gsm_mncc)); disc.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - disc.fields |= MNCC_F_CAUSE; - decode_cause(&disc.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - disc.fields |= MNCC_F_FACILITY; - decode_facility(&disc.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - disc.fields |= MNCC_F_USERUSER; - decode_useruser(&disc.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - disc.fields |= MNCC_F_SSVERSION; - decode_ssversion(&disc.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - }
+ static struct dd_parser parser[] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + }; + + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &disc); return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
} @@ -1509,30 +1526,15 @@ static int msc_cc_rx_release(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + + static struct dd_parser parser[] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + }; + + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &rel);
if (trans->state == GSM_CSTATE_RELEASE_REQ) { /* release collision 5.4.5 */ @@ -1598,30 +1600,15 @@ static int msc_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + + static struct dd_parser parser[] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + }; + + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &rel);
if (trans->callref) { switch (trans->state) { @@ -1684,19 +1671,13 @@ static int msc_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg) memset(&fac, 0, sizeof(struct gsm_mncc)); fac.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - fac.fields |= MNCC_F_FACILITY; - decode_facility(&fac.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - fac.fields |= MNCC_F_SSVERSION; - decode_ssversion(&fac.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - }
+ static struct dd_parser parser[] = { + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + }; + + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &fac); return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac); }
@@ -1807,12 +1788,11 @@ static int msc_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg) dtmf.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); /* keypad facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) { - dtmf.fields |= MNCC_F_KEYPAD; - decode_keypad(&dtmf.keypad, - TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1); - } + static struct dd_parser parser[] = { + DECLARE_DECODER3(KPD_FACILITY, KEYPAD, keypad), + };
+ parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &dtmf); return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf); }
@@ -1884,15 +1864,12 @@ static int msc_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } + static struct dd_parser parser[] = { + DECLARE_DECODER(BEARER_CAP, bearer_cap), + };
+ parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &modify); new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify); }
@@ -1928,15 +1905,12 @@ static int msc_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } + static struct dd_parser parser[] = { + DECLARE_DECODER(BEARER_CAP, bearer_cap), + };
+ parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &modify); new_cc_state(trans, GSM_CSTATE_ACTIVE); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify); }
@@ -1970,19 +1944,13 @@ static int msc_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= GSM48_IE_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - modify.fields |= MNCC_F_CAUSE; - decode_cause(&modify.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - }
+ + static struct dd_parser parser[] = { + DECLARE_DECODER(BEARER_CAP, bearer_cap), + DECLARE_DECODER(CAUSE, cause), + }; + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &modify); new_cc_state(trans, GSM_CSTATE_ACTIVE);
return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify); @@ -2070,12 +2038,13 @@ static int msc_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) memset(&user, 0, sizeof(struct gsm_mncc)); user.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0); - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - user.fields |= MNCC_F_USERUSER; - decode_useruser(&user.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } + + static struct dd_parser parser[] = { + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + }; + + parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &user); + /* more data */ if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA)) user.more = 1;
Hi Holger, On Mon, Jun 29, 2009 at 05:27:28PM +0200, Holger Freyther wrote:
did you have this in mind when mentioning that the parsing of the data derived informations could be driven by a struct?
yes, I had something like this in mind. It somehow reduces the readability of the code to those not familiar with this decoding scheme, but well, it reduces the number of lines quite significantly on the other side.
Also:
- static struct dd_parser parser[] = {
 DECLARE_DECODER(CAUSE, cause),DECLARE_DECODER(FACILITY, facility),DECLARE_DECODER3(USER_USER, USERUSER, useruser),DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion),- };
 - parse_data_derived_information(&parser[0], ARRAY_SIZE(parser), &tp, &disc);
 
the parser[] arrays can and should be marked as const, I believe. Also, maybe another step of indirection, i.e. have the dd_parser[] structure static const but global for all IE, and then list in every function which IE's it expects to parse.
Regards,
On Thursday 02 July 2009 06:45:48 Harald Welte wrote:
Hi Holger,
On Mon, Jun 29, 2009 at 05:27:28PM +0200, Holger Freyther wrote:
did you have this in mind when mentioning that the parsing of the data derived informations could be driven by a struct?
yes, I had something like this in mind. It somehow reduces the readability of the code to those not familiar with this decoding scheme, but well, it reduces the number of lines quite significantly on the other side.
A revised patch. I have moved the struct with all known parsers to one place, created an enum of known decoders... I think this an improvement over the previous patch but we are not there yet.
Things that I think I should do: - Maybe nuke the PARSE_FLAG and flag attribute? If we get a response that contains an attribute that should not be there our tlvp_parse will have already parsed it. Does it hurt to copy the value to the gsm_mncc? In one way we would like to be strict, in another it can be nice to see what incorrect messages we receive?
- Kill the enum with the PARSE_ flags, I can use the MNCC ones directly..
comments are more than welcome z.
From 47f155d62b41df0bcd94c610617d39f9eb678f57 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther zecke@selfish.org Date: Mon, 29 Jun 2009 17:21:37 +0200 Subject: [PATCH] Generic data derived informations parsing...
Parse everything that was found during the tlvp_parse and assign it to members of the gsm_mncc. This would even parse elements that are not present/part of the specification. --- openbsc/src/msc_mncc.c | 304 ++++++++++++++---------------------------------- 1 files changed, 85 insertions(+), 219 deletions(-)
diff --git a/openbsc/src/msc_mncc.c b/openbsc/src/msc_mncc.c index 90354c0..3dcb6a0 100644 --- a/openbsc/src/msc_mncc.c +++ b/openbsc/src/msc_mncc.c @@ -587,6 +587,67 @@ static int encode_more(struct msgb *msg) return 0; }
+#define DECLARE_DECODER3(IE_NAME, M_NAME, name) \ + [PARSE_##M_NAME] = \ + { .information_element = GSM48_IE_##IE_NAME, \ + .mncc_field = MNCC_F_##M_NAME, \ + .offset = offsetof(struct gsm_mncc, name), \ + .decoder = (dd_decoder)decode_##name, \ + } + +#define DECLARE_DECODER(NAME, name) \ + DECLARE_DECODER3(NAME, NAME, name) + +typedef int (*dd_decoder)(void* data, const u_int8_t *lv); + +struct dd_parser { + int information_element; + int mncc_field; + int offset; + dd_decoder decoder; +}; + +enum { + PARSE_CAUSE, + PARSE_FACILITY, + PARSE_USERUSER, + PARSE_SSVERSION, + PARSE_KEYPAD, + PARSE_BEARER_CAP, + PARSE_CALLED, + PARSE_CCCAP, + PARSE_PROGRESS, + PARSE_LAST_ITEM, +}; + +#define PARSE_FLAG(flag) (1<<PARSE_##flag) + +static const struct dd_parser dd_parsers [PARSE_LAST_ITEM] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + DECLARE_DECODER3(KPD_FACILITY, KEYPAD, keypad), + DECLARE_DECODER(BEARER_CAP, bearer_cap), + DECLARE_DECODER3(CALLED_BCD, CALLED, called), + DECLARE_DECODER3(CC_CAP, CCCAP, cccap), + DECLARE_DECODER3(PROGR_IND, PROGRESS, progress), +}; + +static void parse_data_derived_information(struct tlv_parsed *tp, struct gsm_mncc *rel, int flags) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dd_parsers); ++i) { + if (flags & (1<<i) == (1<<i) && TLVP_PRESENT(tp, dd_parsers[i].information_element)) { + rel->fields |= dd_parsers[i].mncc_field; + dd_parsers[i].decoder(rel + dd_parsers[i].offset, + TLVP_VAL(tp, dd_parsers[i].information_element)-1); + } + } +} + + /* map two ipaccess RTP streams onto each other */ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { @@ -1013,48 +1074,16 @@ static int msc_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) strncpy(setup.imsi, trans->subscr->imsi, sizeof(setup.imsi)-1); } - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - setup.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&setup.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - setup.fields |= MNCC_F_FACILITY; - decode_facility(&setup.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* called party bcd number */ - if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) { - setup.fields |= MNCC_F_CALLED; - decode_called(&setup.called, - TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - setup.fields |= MNCC_F_USERUSER; - decode_useruser(&setup.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - setup.fields |= MNCC_F_SSVERSION; - decode_ssversion(&setup.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + + parse_data_derived_information(&tp, &setup, PARSE_FLAG(BEARER_CAP) | PARSE_FLAG(FACILITY) | + PARSE_FLAG(CALLED) | PARSE_FLAG(USERUSER) | PARSE_FLAG(SSVERSION) ); + /* CLIR suppression */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP)) setup.clir.sup = 1; /* CLIR invocation */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC)) setup.clir.inv = 1; - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - setup.fields |= MNCC_F_CCCAP; - decode_cccap(&setup.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - }
if (is_ipaccess_bts(msg->trx->bts)) rsl_ipacc_bind(msg->lchan); @@ -1171,24 +1200,9 @@ static int msc_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ)) call_conf.repeat = 2; #endif - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - call_conf.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&call_conf.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - call_conf.fields |= MNCC_F_CAUSE; - decode_cause(&call_conf.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - call_conf.fields |= MNCC_F_CCCAP; - decode_cccap(&call_conf.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - } + + parse_data_derived_information(&tp, &call_conf, PARSE_FLAG(BEARER_CAP) | PARSE_FLAG(CAUSE) | + PARSE_FLAG(CCCAP));
new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
@@ -1233,25 +1247,8 @@ static int msc_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg) memset(&alerting, 0, sizeof(struct gsm_mncc)); alerting.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - alerting.fields |= MNCC_F_FACILITY; - decode_facility(&alerting.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - - /* progress */ - if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) { - alerting.fields |= MNCC_F_PROGRESS; - decode_progress(&alerting.progress, - TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - alerting.fields |= MNCC_F_SSVERSION; - decode_ssversion(&alerting.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &alerting, PARSE_FLAG(FACILITY) | PARSE_FLAG(PROGRESS) | + PARSE_FLAG(SSVERSION));
new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
@@ -1353,25 +1350,9 @@ static int msc_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg) strncpy(connect.imsi, trans->subscr->imsi, sizeof(connect.imsi)-1); } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - connect.fields |= MNCC_F_FACILITY; - decode_facility(&connect.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - connect.fields |= MNCC_F_USERUSER; - decode_useruser(&connect.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - connect.fields |= MNCC_F_SSVERSION; - decode_ssversion(&connect.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - }
+ parse_data_derived_information(&tp, &connect, PARSE_FLAG(FACILITY) | PARSE_FLAG(USERUSER) | + PARSE_FLAG(SSVERSION)); new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect); @@ -1420,31 +1401,8 @@ static int msc_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg) memset(&disc, 0, sizeof(struct gsm_mncc)); disc.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - disc.fields |= MNCC_F_CAUSE; - decode_cause(&disc.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - disc.fields |= MNCC_F_FACILITY; - decode_facility(&disc.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - disc.fields |= MNCC_F_USERUSER; - decode_useruser(&disc.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - disc.fields |= MNCC_F_SSVERSION; - decode_ssversion(&disc.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &disc, PARSE_FLAG(CAUSE) | PARSE_FLAG(FACILITY) | + PARSE_FLAG(USERUSER) | PARSE_FLAG(SSVERSION)); return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
} @@ -1509,30 +1467,8 @@ static int msc_cc_rx_release(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, PARSE_FLAG(CAUSE) | PARSE_FLAG(FACILITY) | + PARSE_FLAG(USERUSER) | PARSE_FLAG(SSVERSION));
if (trans->state == GSM_CSTATE_RELEASE_REQ) { /* release collision 5.4.5 */ @@ -1598,30 +1534,8 @@ static int msc_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, PARSE_FLAG(CAUSE) | PARSE_FLAG(FACILITY) | + PARSE_FLAG(USERUSER) | PARSE_FLAG(SSVERSION));
if (trans->callref) { switch (trans->state) { @@ -1684,19 +1598,7 @@ static int msc_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg) memset(&fac, 0, sizeof(struct gsm_mncc)); fac.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - fac.fields |= MNCC_F_FACILITY; - decode_facility(&fac.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - fac.fields |= MNCC_F_SSVERSION; - decode_ssversion(&fac.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &fac, PARSE_FLAG(FACILITY) | PARSE_FLAG(SSVERSION)); return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac); }
@@ -1806,13 +1708,7 @@ static int msc_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg) memset(&dtmf, 0, sizeof(struct gsm_mncc)); dtmf.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* keypad facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) { - dtmf.fields |= MNCC_F_KEYPAD; - decode_keypad(&dtmf.keypad, - TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1); - } - + parse_data_derived_information(&tp, &dtmf, PARSE_FLAG(KEYPAD)); return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf); }
@@ -1884,15 +1780,8 @@ static int msc_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, PARSE_FLAG(BEARER_CAP)); new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify); }
@@ -1928,15 +1817,8 @@ static int msc_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, PARSE_FLAG(BEARER_CAP)); new_cc_state(trans, GSM_CSTATE_ACTIVE); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify); }
@@ -1970,19 +1852,7 @@ static int msc_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= GSM48_IE_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - modify.fields |= MNCC_F_CAUSE; - decode_cause(&modify.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - + parse_data_derived_information(&tp, &modify, PARSE_FLAG(BEARER_CAP) | PARSE_FLAG(CAUSE)); new_cc_state(trans, GSM_CSTATE_ACTIVE);
return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify); @@ -2070,12 +1940,8 @@ static int msc_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) memset(&user, 0, sizeof(struct gsm_mncc)); user.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0); - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - user.fields |= MNCC_F_USERUSER; - decode_useruser(&user.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } + parse_data_derived_information(&tp, &user, PARSE_FLAG(USERUSER)); + /* more data */ if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA)) user.more = 1;
On Friday 10 July 2009 19:08:40 Holger Freyther wrote:
On Thursday 02 July 2009 06:45:48 Harald Welte wrote:
Things that I think I should do:
- Maybe nuke the PARSE_FLAG and flag attribute? If we get a response that
 contains an attribute that should not be there our tlvp_parse will have already parsed it. Does it hurt to copy the value to the gsm_mncc? In one way we would like to be strict, in another it can be nice to see what incorrect messages we receive?
- Kill the enum with the PARSE_ flags, I can use the MNCC onesdirectly..
to reply to myself... i think I have fixed the above and think the patch is good enough to be merged? what should I change?
From 6de565798996dfc18de0c2fda98e7365d13fd3bc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther zecke@selfish.org Date: Mon, 29 Jun 2009 17:21:37 +0200 Subject: [PATCH] Generic data derived informations parsing...
Parse everything that was found during the tlvp_parse and assign it to members of the gsm_mncc. This would even parse elements that are not present/part of the specification. --- openbsc/include/openbsc/mncc.h | 46 +++++-- openbsc/src/msc_mncc.c | 294 ++++++++++------------------------------ 2 files changed, 107 insertions(+), 233 deletions(-)
diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h index 6aa1917..d6df502 100644 --- a/openbsc/include/openbsc/mncc.h +++ b/openbsc/include/openbsc/mncc.h @@ -93,20 +93,38 @@ struct gsm_call { #define GSM_MAX_SSVERSION 128 #define GSM_MAX_USERUSER 128
-#define MNCC_F_BEARER_CAP 0x0001 -#define MNCC_F_CALLED 0x0002 -#define MNCC_F_CALLING 0x0004 -#define MNCC_F_REDIRECTING 0x0008 -#define MNCC_F_CONNECTED 0x0010 -#define MNCC_F_CAUSE 0x0020 -#define MNCC_F_USERUSER 0x0040 -#define MNCC_F_PROGRESS 0x0080 -#define MNCC_F_EMERGENCY 0x0100 -#define MNCC_F_FACILITY 0x0200 -#define MNCC_F_SSVERSION 0x0400 -#define MNCC_F_CCCAP 0x0800 -#define MNCC_F_KEYPAD 0x1000 -#define MNCC_F_SIGNAL 0x2000 +enum { + _MNCC_E_BEARER_CAP, + _MNCC_E_CALLED, + _MNCC_E_CALLING, + _MNCC_E_REDIRECTING, + _MNCC_E_CONNECTED, + _MNCC_E_CAUSE, + _MNCC_E_USERUSER, + _MNCC_E_PROGRESS, + _MNCC_E_EMERGENCY, + _MNCC_E_FACILITY, + _MNCC_E_SSVERSION, + _MNCC_E_CCCAP, + _MNCC_E_KEYPAD, + _MNCC_E_SIGNAL, + _MNCC_E_LAST_ITEM, +}; + +#define MNCC_F_BEARER_CAP (1 << _MNCC_E_BEARER_CAP) +#define MNCC_F_CALLED (1 << _MNCC_E_CALLED) +#define MNCC_F_CALLING (1 << _MNCC_E_CALLING) +#define MNCC_F_REDIRECTING (1 << _MNCC_E_REDIRECTING) +#define MNCC_F_CONNECTED (1 << _MNCC_E_CONNECTED) +#define MNCC_F_CAUSE (1 << _MNCC_E_CAUSE) +#define MNCC_F_USERUSER (1 << _MNCC_E_USERUSER) +#define MNCC_F_PROGRESS (1 << _MNCC_E_PROGRESS) +#define MNCC_F_EMERGENCY (1 << _MNCC_E_EMERGENCY) +#define MNCC_F_FACILITY (1 << _MNCC_E_FACILITY) +#define MNCC_F_SSVERSION (1 << _MNCC_E_SSVERSION) +#define MNCC_F_CCCAP (1 << _MNCC_E_CCCAP) +#define MNCC_F_KEYPAD (1 << _MNCC_E_KEYPAD) +#define MNCC_F_SIGNAL (1 << _MNCC_E_SIGNAL)
struct gsm_mncc_bearer_cap { int transfer; diff --git a/openbsc/src/msc_mncc.c b/openbsc/src/msc_mncc.c index 90354c0..41ffcc0 100644 --- a/openbsc/src/msc_mncc.c +++ b/openbsc/src/msc_mncc.c @@ -587,6 +587,55 @@ static int encode_more(struct msgb *msg) return 0; }
+#define DECLARE_DECODER3(IE_NAME, M_NAME, name) \ + [_MNCC_E_##M_NAME] = \ + { .information_element = GSM48_IE_##IE_NAME, \ + .mncc_field = MNCC_F_##M_NAME, \ + .offset = offsetof(struct gsm_mncc, name), \ + .decoder = (dd_decoder)decode_##name, \ + } + +#define DECLARE_DECODER(NAME, name) \ + DECLARE_DECODER3(NAME, NAME, name) + +typedef int (*dd_decoder)(void* data, const u_int8_t *lv); + +struct dd_parser { + int information_element; + int mncc_field; + int offset; + dd_decoder decoder; +}; + +static const struct dd_parser dd_parsers [_MNCC_E_LAST_ITEM] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + DECLARE_DECODER3(KPD_FACILITY, KEYPAD, keypad), + DECLARE_DECODER(BEARER_CAP, bearer_cap), + DECLARE_DECODER3(CALLED_BCD, CALLED, called), + DECLARE_DECODER3(CC_CAP, CCCAP, cccap), + DECLARE_DECODER3(PROGR_IND, PROGRESS, progress), +}; + +static void parse_data_derived_information(struct tlv_parsed *tp, struct gsm_mncc *rel, int flags) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dd_parsers); ++i) { + if ((flags & (1<<i)) == (1<<i) && + TLVP_PRESENT(tp, dd_parsers[i].information_element) && + dd_parsers[i].decoder) { + + rel->fields |= dd_parsers[i].mncc_field; + dd_parsers[i].decoder(rel + dd_parsers[i].offset, + TLVP_VAL(tp, dd_parsers[i].information_element)-1); + } + } +} + + /* map two ipaccess RTP streams onto each other */ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { @@ -1013,48 +1062,17 @@ static int msc_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) strncpy(setup.imsi, trans->subscr->imsi, sizeof(setup.imsi)-1); } - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - setup.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&setup.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - setup.fields |= MNCC_F_FACILITY; - decode_facility(&setup.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* called party bcd number */ - if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) { - setup.fields |= MNCC_F_CALLED; - decode_called(&setup.called, - TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - setup.fields |= MNCC_F_USERUSER; - decode_useruser(&setup.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - setup.fields |= MNCC_F_SSVERSION; - decode_ssversion(&setup.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + + parse_data_derived_information(&tp, &setup, MNCC_F_BEARER_CAP | MNCC_F_FACILITY | + MNCC_F_CALLED | MNCC_F_USERUSER | + MNCC_F_SSVERSION | MNCC_F_CCCAP); + /* CLIR suppression */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP)) setup.clir.sup = 1; /* CLIR invocation */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC)) setup.clir.inv = 1; - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - setup.fields |= MNCC_F_CCCAP; - decode_cccap(&setup.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - }
if (is_ipaccess_bts(msg->trx->bts)) rsl_ipacc_bind(msg->lchan); @@ -1171,24 +1189,9 @@ static int msc_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ)) call_conf.repeat = 2; #endif - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - call_conf.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&call_conf.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - call_conf.fields |= MNCC_F_CAUSE; - decode_cause(&call_conf.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - call_conf.fields |= MNCC_F_CCCAP; - decode_cccap(&call_conf.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - } + + parse_data_derived_information(&tp, &call_conf, MNCC_F_BEARER_CAP | + MNCC_F_CAUSE | MNCC_F_CCCAP);
new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
@@ -1233,25 +1236,8 @@ static int msc_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg) memset(&alerting, 0, sizeof(struct gsm_mncc)); alerting.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - alerting.fields |= MNCC_F_FACILITY; - decode_facility(&alerting.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - - /* progress */ - if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) { - alerting.fields |= MNCC_F_PROGRESS; - decode_progress(&alerting.progress, - TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - alerting.fields |= MNCC_F_SSVERSION; - decode_ssversion(&alerting.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &alerting, MNCC_F_FACILITY | + MNCC_F_PROGRESS | MNCC_F_SSVERSION);
new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
@@ -1353,25 +1339,9 @@ static int msc_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg) strncpy(connect.imsi, trans->subscr->imsi, sizeof(connect.imsi)-1); } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - connect.fields |= MNCC_F_FACILITY; - decode_facility(&connect.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - connect.fields |= MNCC_F_USERUSER; - decode_useruser(&connect.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - connect.fields |= MNCC_F_SSVERSION; - decode_ssversion(&connect.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - }
+ parse_data_derived_information(&tp, &connect, MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION); new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect); @@ -1420,31 +1390,9 @@ static int msc_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg) memset(&disc, 0, sizeof(struct gsm_mncc)); disc.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - disc.fields |= MNCC_F_CAUSE; - decode_cause(&disc.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - disc.fields |= MNCC_F_FACILITY; - decode_facility(&disc.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - disc.fields |= MNCC_F_USERUSER; - decode_useruser(&disc.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - disc.fields |= MNCC_F_SSVERSION; - decode_ssversion(&disc.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &disc, MNCC_F_CAUSE | + MNCC_F_FACILITY | MNCC_F_USERUSER | + MNCC_F_SSVERSION); return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
} @@ -1509,30 +1457,8 @@ static int msc_cc_rx_release(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, MNCC_F_CAUSE | MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION);
if (trans->state == GSM_CSTATE_RELEASE_REQ) { /* release collision 5.4.5 */ @@ -1598,30 +1524,8 @@ static int msc_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, MNCC_F_CAUSE | MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION);
if (trans->callref) { switch (trans->state) { @@ -1684,19 +1588,7 @@ static int msc_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg) memset(&fac, 0, sizeof(struct gsm_mncc)); fac.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - fac.fields |= MNCC_F_FACILITY; - decode_facility(&fac.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - fac.fields |= MNCC_F_SSVERSION; - decode_ssversion(&fac.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &fac, MNCC_F_FACILITY | MNCC_F_SSVERSION); return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac); }
@@ -1806,13 +1698,7 @@ static int msc_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg) memset(&dtmf, 0, sizeof(struct gsm_mncc)); dtmf.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* keypad facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) { - dtmf.fields |= MNCC_F_KEYPAD; - decode_keypad(&dtmf.keypad, - TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1); - } - + parse_data_derived_information(&tp, &dtmf, MNCC_F_KEYPAD); return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf); }
@@ -1884,15 +1770,8 @@ static int msc_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP); new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify); }
@@ -1928,15 +1807,8 @@ static int msc_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP); new_cc_state(trans, GSM_CSTATE_ACTIVE); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify); }
@@ -1970,19 +1842,7 @@ static int msc_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= GSM48_IE_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - modify.fields |= MNCC_F_CAUSE; - decode_cause(&modify.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP | MNCC_F_CAUSE); new_cc_state(trans, GSM_CSTATE_ACTIVE);
return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify); @@ -2070,12 +1930,8 @@ static int msc_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) memset(&user, 0, sizeof(struct gsm_mncc)); user.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0); - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - user.fields |= MNCC_F_USERUSER; - decode_useruser(&user.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } + parse_data_derived_information(&tp, &user, MNCC_F_USERUSER); + /* more data */ if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA)) user.more = 1;