<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/18231">View Change</a></p><div style="white-space:pre-wrap">Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gsm0808: Implement helper functions for CONFUSION BSSMAP message decoding.<br><br>Also add a test for an actual CONFUSION message parsing.<br><br>Change-Id: If8afd2d096fb66c6c2f255a08fc1129de3d09cec<br>---<br>M include/osmocom/gsm/gsm0808.h<br>M include/osmocom/gsm/protocol/gsm_08_08.h<br>M src/gsm/gsm0808.c<br>M src/gsm/libosmogsm.map<br>M tests/gsm0808/gsm0808_test.c<br>M tests/gsm0808/gsm0808_test.ok<br>6 files changed, 113 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h</span><br><span>index 5a33f60..34cec3c 100644</span><br><span>--- a/include/osmocom/gsm/gsm0808.h</span><br><span>+++ b/include/osmocom/gsm/gsm0808.h</span><br><span>@@ -319,6 +319,9 @@</span><br><span> * \returns Cause value */</span><br><span> enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> extern const struct value_string gsm0808_lcls_config_names[];</span><br><span> extern const struct value_string gsm0808_lcls_control_names[];</span><br><span> extern const struct value_string gsm0808_lcls_status_names[];</span><br><span>diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h</span><br><span>index d8a7773..1390f0e 100644</span><br><span>--- a/include/osmocom/gsm/protocol/gsm_08_08.h</span><br><span>+++ b/include/osmocom/gsm/protocol/gsm_08_08.h</span><br><span>@@ -663,3 +663,16 @@</span><br><span> GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04,</span><br><span> GSM0808_LCLS_STS_NA = 0xFF</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 48.008 3.2.2.32 Diagnostics */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gsm0808_diagnostics {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t error_pointer_octet;</span><br><span style="color: hsl(120, 100%, 40%);">+#if OSMO_IS_LITTLE_ENDIAN</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t error_pointer_bit_spare:4,</span><br><span style="color: hsl(120, 100%, 40%);">+ error_pointer_bit:4;</span><br><span style="color: hsl(120, 100%, 40%);">+#elif OSMO_IS_BIG_ENDIAN</span><br><span style="color: hsl(120, 100%, 40%);">+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t error_pointer_bit:4, error_pointer_bit_spare:4;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t msg[0]; /*! received message which provoked the error */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed));</span><br><span>diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c</span><br><span>index 788f6c3..23468c3 100644</span><br><span>--- a/src/gsm/gsm0808.c</span><br><span>+++ b/src/gsm/gsm0808.c</span><br><span>@@ -21,6 +21,8 @@</span><br><span> *</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include <osmocom/core/byteswap.h></span><br><span> #include <osmocom/gsm/gsm0808.h></span><br><span> #include <osmocom/gsm/gsm0808_utils.h></span><br><span>@@ -34,6 +36,9 @@</span><br><span> * message generation/encoding.</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Char buffer to return strings from functions */</span><br><span style="color: hsl(120, 100%, 40%);">+static __thread char str_buff[512];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Create "Complete L3 Info" for AoIP, legacy implementation.</span><br><span> * Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros.</span><br><span> * \param[in] msg_l3 msgb containing Layer 3 Message</span><br><span>@@ -1670,6 +1675,39 @@</span><br><span> return buf[0];</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (pointer) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ return "Error location not determined";</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ return "The first octet of the message received (i.e. the message type) was found erroneous (unknown)";</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0xfd:</span><br><span style="color: hsl(120, 100%, 40%);">+ return "The first octet of the BSSAP header (Discrimination) was found erroneous";</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0xfe:</span><br><span style="color: hsl(120, 100%, 40%);">+ return "(DTAP only) The DLCI (second) octet of the BSSAP header was found erroneous";</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0xff:</span><br><span style="color: hsl(120, 100%, 40%);">+ return "The last octet of the BSSAP header (length indicator) was found erroneous";</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(str_buff, sizeof(str_buff), "The %d octet of the message received was found erroneous", pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+ return str_buff;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bit_pointer == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return "No particular part of the octet is indicated";</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (bit_pointer > 8) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return "Reserved value";</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(str_buff, sizeof(str_buff),</span><br><span style="color: hsl(120, 100%, 40%);">+ "An error was provoked by the field whose most significant bit is in bit position %d",</span><br><span style="color: hsl(120, 100%, 40%);">+ bit_pointer);</span><br><span style="color: hsl(120, 100%, 40%);">+ return str_buff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const struct value_string gsm0808_lcls_config_names[] = {</span><br><span> { GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" },</span><br><span> { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL,</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index ce55746..70b3916 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -159,6 +159,8 @@</span><br><span> gsm0808_cause_name;</span><br><span> gsm0808_cause_class_name;</span><br><span> gsm0808_get_cause;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_diagnostics_octet_location_str;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_diagnostics_bit_location_str;</span><br><span> gsm0808_create_ass;</span><br><span> gsm0808_create_ass2;</span><br><span> gsm0808_create_assignment_completed;</span><br><span>diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c</span><br><span>index ce73390..d9640aa 100644</span><br><span>--- a/tests/gsm0808/gsm0808_test.c</span><br><span>+++ b/tests/gsm0808/gsm0808_test.c</span><br><span>@@ -379,6 +379,55 @@</span><br><span> msgb_free(msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void test_dec_confusion()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ static const uint8_t hex[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct tlv_parsed tp;</span><br><span style="color: hsl(120, 100%, 40%);">+ int diag_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum gsm0808_cause cause;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum gsm0808_cause_class cause_class;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm0808_diagnostics *diag;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("Testing decoding CONFUSION\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check for the Cause and Diagnostic mandatory elements */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("Either Cause or Diagnostic mandatory IE are not detected\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (diag_len < 5) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("Diagnostic length is too short: %d (expected > 5)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cause = gsm0808_get_cause(&tp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((int)cause < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause));</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ cause_class = gsm0808_cause_class(cause);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" Cause class %d/0x%x (%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ cause_class, cause_class, gsm0808_cause_class_name(cause_class));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" Cause %d/0x%x (%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ cause, cause, gsm0808_cause_name(cause));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" Diagnostics error octet location %d (%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ diag->error_pointer_octet,</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" Diagnostics error bit location %d (%s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ diag->error_pointer_bit,</span><br><span style="color: hsl(120, 100%, 40%);">+ gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit));</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" Diagnostics message that provoked the error: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_hexdump(diag->msg, diag_len-2));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void test_create_ass()</span><br><span> {</span><br><span> static const uint8_t res1[] =</span><br><span>@@ -2422,6 +2471,8 @@</span><br><span> </span><br><span> test_gsm0808_cell_id_to_from_cgi();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ test_dec_confusion();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> printf("Done\n");</span><br><span> return EXIT_SUCCESS;</span><br><span> }</span><br><span>diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok</span><br><span>index b620e36..eaae7a6 100644</span><br><span>--- a/tests/gsm0808/gsm0808_test.ok</span><br><span>+++ b/tests/gsm0808/gsm0808_test.ok</span><br><span>@@ -910,4 +910,10 @@</span><br><span> --> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777</span><br><span> --> gsm0808_cell_id{LAI} = LAI:777-007-7777</span><br><span> --> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777</span><br><span style="color: hsl(120, 100%, 40%);">+Testing decoding CONFUSION</span><br><span style="color: hsl(120, 100%, 40%);">+ Cause class 5/0x5 (Invalid message)</span><br><span style="color: hsl(120, 100%, 40%);">+ Cause 82/0x52 (INFORMATION ELEMENT OR FIELD MISSING)</span><br><span style="color: hsl(120, 100%, 40%);">+ Diagnostics error octet location 0 (Error location not determined)</span><br><span style="color: hsl(120, 100%, 40%);">+ Diagnostics error bit location 15 (Reserved value)</span><br><span style="color: hsl(120, 100%, 40%);">+ Diagnostics message that provoked the error: 00 03 25 03 25 </span><br><span> Done</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/18231">change 18231</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/18231"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If8afd2d096fb66c6c2f255a08fc1129de3d09cec </div>
<div style="display:none"> Gerrit-Change-Number: 18231 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: ipse <Alexander.Chemeris@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: ipse <Alexander.Chemeris@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-CC: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-CC: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>