mirror of https://gerrit.osmocom.org/libosmocore
gsm0808: Implement helper functions for CONFUSION BSSMAP message decoding.
Also add a test for an actual CONFUSION message parsing. Change-Id: If8afd2d096fb66c6c2f255a08fc1129de3d09cec
This commit is contained in:
parent
bfeeb1c86c
commit
22630e6827
|
@ -319,6 +319,9 @@ const char *gsm0808_cause_class_name(enum gsm0808_cause_class class);
|
||||||
* \returns Cause value */
|
* \returns Cause value */
|
||||||
enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp);
|
enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp);
|
||||||
|
|
||||||
|
const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer);
|
||||||
|
const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer);
|
||||||
|
|
||||||
extern const struct value_string gsm0808_lcls_config_names[];
|
extern const struct value_string gsm0808_lcls_config_names[];
|
||||||
extern const struct value_string gsm0808_lcls_control_names[];
|
extern const struct value_string gsm0808_lcls_control_names[];
|
||||||
extern const struct value_string gsm0808_lcls_status_names[];
|
extern const struct value_string gsm0808_lcls_status_names[];
|
||||||
|
|
|
@ -663,3 +663,16 @@ enum gsm0808_lcls_status {
|
||||||
GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04,
|
GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04,
|
||||||
GSM0808_LCLS_STS_NA = 0xFF
|
GSM0808_LCLS_STS_NA = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 3GPP TS 48.008 3.2.2.32 Diagnostics */
|
||||||
|
struct gsm0808_diagnostics {
|
||||||
|
uint8_t error_pointer_octet;
|
||||||
|
#if OSMO_IS_LITTLE_ENDIAN
|
||||||
|
uint8_t error_pointer_bit_spare:4,
|
||||||
|
error_pointer_bit:4;
|
||||||
|
#elif OSMO_IS_BIG_ENDIAN
|
||||||
|
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||||
|
uint8_t error_pointer_bit:4, error_pointer_bit_spare:4;
|
||||||
|
#endif
|
||||||
|
uint8_t msg[0]; /*! received message which provoked the error */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <osmocom/core/byteswap.h>
|
#include <osmocom/core/byteswap.h>
|
||||||
#include <osmocom/gsm/gsm0808.h>
|
#include <osmocom/gsm/gsm0808.h>
|
||||||
#include <osmocom/gsm/gsm0808_utils.h>
|
#include <osmocom/gsm/gsm0808_utils.h>
|
||||||
|
@ -34,6 +36,9 @@
|
||||||
* message generation/encoding.
|
* message generation/encoding.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! Char buffer to return strings from functions */
|
||||||
|
static __thread char str_buff[512];
|
||||||
|
|
||||||
/*! Create "Complete L3 Info" for AoIP, legacy implementation.
|
/*! Create "Complete L3 Info" for AoIP, legacy implementation.
|
||||||
* Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros.
|
* Instead use gsm0808_create_layer3_aoip2(), which is capable of three-digit MNC with leading zeros.
|
||||||
* \param[in] msg_l3 msgb containing Layer 3 Message
|
* \param[in] msg_l3 msgb containing Layer 3 Message
|
||||||
|
@ -1670,6 +1675,39 @@ enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp)
|
||||||
return buf[0];
|
return buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer)
|
||||||
|
{
|
||||||
|
switch (pointer) {
|
||||||
|
case 0:
|
||||||
|
return "Error location not determined";
|
||||||
|
case 1:
|
||||||
|
return "The first octet of the message received (i.e. the message type) was found erroneous (unknown)";
|
||||||
|
case 0xfd:
|
||||||
|
return "The first octet of the BSSAP header (Discrimination) was found erroneous";
|
||||||
|
case 0xfe:
|
||||||
|
return "(DTAP only) The DLCI (second) octet of the BSSAP header was found erroneous";
|
||||||
|
case 0xff:
|
||||||
|
return "The last octet of the BSSAP header (length indicator) was found erroneous";
|
||||||
|
default:
|
||||||
|
snprintf(str_buff, sizeof(str_buff), "The %d octet of the message received was found erroneous", pointer);
|
||||||
|
return str_buff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer)
|
||||||
|
{
|
||||||
|
if (bit_pointer == 0) {
|
||||||
|
return "No particular part of the octet is indicated";
|
||||||
|
} else if (bit_pointer > 8) {
|
||||||
|
return "Reserved value";
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(str_buff, sizeof(str_buff),
|
||||||
|
"An error was provoked by the field whose most significant bit is in bit position %d",
|
||||||
|
bit_pointer);
|
||||||
|
return str_buff;
|
||||||
|
}
|
||||||
|
|
||||||
const struct value_string gsm0808_lcls_config_names[] = {
|
const struct value_string gsm0808_lcls_config_names[] = {
|
||||||
{ GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" },
|
{ GSM0808_LCLS_CFG_BOTH_WAY, "Connect both-way" },
|
||||||
{ GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL,
|
{ GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL,
|
||||||
|
|
|
@ -159,6 +159,8 @@ gsm0808_bssmap_name;
|
||||||
gsm0808_cause_name;
|
gsm0808_cause_name;
|
||||||
gsm0808_cause_class_name;
|
gsm0808_cause_class_name;
|
||||||
gsm0808_get_cause;
|
gsm0808_get_cause;
|
||||||
|
gsm0808_diagnostics_octet_location_str;
|
||||||
|
gsm0808_diagnostics_bit_location_str;
|
||||||
gsm0808_create_ass;
|
gsm0808_create_ass;
|
||||||
gsm0808_create_ass2;
|
gsm0808_create_ass2;
|
||||||
gsm0808_create_assignment_completed;
|
gsm0808_create_assignment_completed;
|
||||||
|
|
|
@ -379,6 +379,55 @@ static void test_create_sapi_reject()
|
||||||
msgb_free(msg);
|
msgb_free(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_dec_confusion()
|
||||||
|
{
|
||||||
|
static const uint8_t hex[] =
|
||||||
|
{ 0x26, 0x04, 0x01, 0x52, 0x1f, 0x07, 0x00, 0xff, 0x00, 0x03, 0x25, 0x03, 0x25 };
|
||||||
|
struct tlv_parsed tp;
|
||||||
|
int diag_len;
|
||||||
|
enum gsm0808_cause cause;
|
||||||
|
enum gsm0808_cause_class cause_class;
|
||||||
|
struct gsm0808_diagnostics *diag;
|
||||||
|
|
||||||
|
printf("Testing decoding CONFUSION\n");
|
||||||
|
|
||||||
|
tlv_parse(&tp, gsm0808_att_tlvdef(), hex+1, sizeof(hex)-1, 0, 0);
|
||||||
|
|
||||||
|
/* Check for the Cause and Diagnostic mandatory elements */
|
||||||
|
if (!TLVP_PRESENT(&tp, GSM0808_IE_CAUSE) || !TLVP_PRESENT(&tp, GSM0808_IE_DIAGNOSTIC)) {
|
||||||
|
printf("Either Cause or Diagnostic mandatory IE are not detected\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diag_len = TLVP_LEN(&tp, GSM0808_IE_DIAGNOSTIC);
|
||||||
|
if (diag_len < 5) {
|
||||||
|
printf("Diagnostic length is too short: %d (expected > 5)\n",
|
||||||
|
diag_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cause = gsm0808_get_cause(&tp);
|
||||||
|
if ((int)cause < 0) {
|
||||||
|
printf("ERROR: failed (%s) to extract Cause, aborting\n", strerror(-(int)cause));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cause_class = gsm0808_cause_class(cause);
|
||||||
|
printf(" Cause class %d/0x%x (%s)\n",
|
||||||
|
cause_class, cause_class, gsm0808_cause_class_name(cause_class));
|
||||||
|
printf(" Cause %d/0x%x (%s)\n",
|
||||||
|
cause, cause, gsm0808_cause_name(cause));
|
||||||
|
|
||||||
|
diag = (struct gsm0808_diagnostics *)TLVP_VAL(&tp, GSM0808_IE_DIAGNOSTIC);
|
||||||
|
printf(" Diagnostics error octet location %d (%s)\n",
|
||||||
|
diag->error_pointer_octet,
|
||||||
|
gsm0808_diagnostics_octet_location_str(diag->error_pointer_octet));
|
||||||
|
printf(" Diagnostics error bit location %d (%s)\n",
|
||||||
|
diag->error_pointer_bit,
|
||||||
|
gsm0808_diagnostics_bit_location_str(diag->error_pointer_bit));
|
||||||
|
printf(" Diagnostics message that provoked the error: %s\n",
|
||||||
|
osmo_hexdump(diag->msg, diag_len-2));
|
||||||
|
}
|
||||||
|
|
||||||
static void test_create_ass()
|
static void test_create_ass()
|
||||||
{
|
{
|
||||||
static const uint8_t res1[] =
|
static const uint8_t res1[] =
|
||||||
|
@ -2422,6 +2471,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
test_gsm0808_cell_id_to_from_cgi();
|
test_gsm0808_cell_id_to_from_cgi();
|
||||||
|
|
||||||
|
test_dec_confusion();
|
||||||
|
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -910,4 +910,10 @@ cid unknown 0x1a7:unknown 0x1a7 -> cgi 777-007-7777-7777 -> cid unknown 0x1a7:un
|
||||||
--> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777
|
--> gsm0808_cell_id{LAC-CI} = LAC-CI:7777-7777
|
||||||
--> gsm0808_cell_id{LAI} = LAI:777-007-7777
|
--> gsm0808_cell_id{LAI} = LAI:777-007-7777
|
||||||
--> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777
|
--> gsm0808_cell_id{CGI} = CGI:777-007-7777-7777
|
||||||
|
Testing decoding CONFUSION
|
||||||
|
Cause class 5/0x5 (Invalid message)
|
||||||
|
Cause 82/0x52 (INFORMATION ELEMENT OR FIELD MISSING)
|
||||||
|
Diagnostics error octet location 0 (Error location not determined)
|
||||||
|
Diagnostics error bit location 15 (Reserved value)
|
||||||
|
Diagnostics message that provoked the error: 00 03 25 03 25
|
||||||
Done
|
Done
|
||||||
|
|
Loading…
Reference in New Issue