This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Holger Freyther zecke at selfish.orgHey 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 at 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; -- 1.6.3.1