Cleanup some parsing in the mncc.c code

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.org
Mon Jun 29 15:27:28 UTC 2009


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 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





More information about the OpenBSC mailing list