mirror of https://gerrit.osmocom.org/libosmocore
gsm: Introduce API osmo_gsm48_rest_octets_si13_decode
Related: SYS#5358 Change-Id: I74fb0a3afc1ac4aadbfc609b882d929401f790eb
This commit is contained in:
parent
74dddefcc7
commit
d7a209bce9
|
@ -120,7 +120,8 @@ struct osmo_gsm48_si13_info {
|
|||
uint8_t prio_acc_thr;
|
||||
};
|
||||
|
||||
/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
|
||||
/* Parse/Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
|
||||
int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data);
|
||||
int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si13_info *si13);
|
||||
|
||||
/* Parse SI3 Rest Octets */
|
||||
|
|
|
@ -749,6 +749,119 @@ int osmo_gsm48_rest_octets_si6_encode(uint8_t *data, const struct osmo_gsm48_si6
|
|||
return bv.data_len;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int decode_t3192(unsigned int t3192)
|
||||
{
|
||||
/* See also 3GPP TS 44.060
|
||||
Table 12.24.2: GPRS Cell Options information element details */
|
||||
static const unsigned int decode_t3192_tbl[8] = {500, 1000, 1500, 0, 80, 120, 160, 200};
|
||||
OSMO_ASSERT(t3192 <= 7);
|
||||
return decode_t3192_tbl[t3192];
|
||||
}
|
||||
|
||||
static unsigned int decode_drx_timer(unsigned int drx)
|
||||
{
|
||||
static const unsigned int decode_drx_timer_tbl[8] = {0, 1, 2, 4, 8, 16, 32, 64};
|
||||
OSMO_ASSERT(drx <= 7);
|
||||
return decode_drx_timer_tbl[drx];
|
||||
}
|
||||
|
||||
static int decode_gprs_cell_opt(struct osmo_gprs_cell_options *gco, struct bitvec *bv)
|
||||
{
|
||||
gco->nmo = bitvec_get_uint(bv, 2);
|
||||
gco->t3168 = (bitvec_get_uint(bv, 3) + 1) * 500;
|
||||
gco->t3192 = decode_t3192(bitvec_get_uint(bv, 3));
|
||||
gco->drx_timer_max = decode_drx_timer(bitvec_get_uint(bv, 3));
|
||||
|
||||
/* ACCESS_BURST_TYPE: */
|
||||
bitvec_get_uint(bv, 1);
|
||||
/* CONTROL_ACK_TYPE: */
|
||||
gco->ctrl_ack_type_use_block = bitvec_get_uint(bv, 1);
|
||||
gco->bs_cv_max = bitvec_get_uint(bv, 4);
|
||||
|
||||
if (bitvec_get_uint(bv, 1)) {
|
||||
bitvec_get_uint(bv, 3); /* DEC */
|
||||
bitvec_get_uint(bv, 3); /* INC */
|
||||
bitvec_get_uint(bv, 3); /* MAX */
|
||||
}
|
||||
|
||||
if (bitvec_get_uint(bv, 1)) {
|
||||
int ext_len = bitvec_get_uint(bv, 6);
|
||||
if (ext_len < 0)
|
||||
return ext_len;
|
||||
unsigned int cur_bit = bv->cur_bit;
|
||||
/* Extension Information */
|
||||
/* R99 extension: */
|
||||
gco->ext_info.egprs_supported = bitvec_get_uint(bv, 1);
|
||||
if (gco->ext_info.egprs_supported) {
|
||||
gco->ext_info.use_egprs_p_ch_req = !bitvec_get_uint(bv, 1);
|
||||
gco->ext_info.bep_period = bitvec_get_uint(bv, 4);
|
||||
}
|
||||
gco->ext_info.pfc_supported = bitvec_get_uint(bv, 1);
|
||||
gco->ext_info.dtm_supported = bitvec_get_uint(bv, 1);
|
||||
gco->ext_info.bss_paging_coordination = bitvec_get_uint(bv, 1);
|
||||
/* REL-4 extension: */
|
||||
gco->ext_info.ccn_active = bitvec_get_uint(bv, 1);
|
||||
bitvec_get_uint(bv, 1); /* NW_EXT_UTBF */
|
||||
bv->cur_bit = cur_bit + ext_len + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void decode_gprs_pwr_ctrl_pars(struct osmo_gprs_power_ctrl_pars *pcp, struct bitvec *bv)
|
||||
{
|
||||
pcp->alpha = bitvec_get_uint(bv, 4);
|
||||
pcp->t_avg_w = bitvec_get_uint(bv,5);
|
||||
pcp->t_avg_t = bitvec_get_uint(bv, 5);
|
||||
pcp->pc_meas_chan = bitvec_get_uint(bv, 1);
|
||||
pcp->n_avg_i = bitvec_get_uint(bv, 4);
|
||||
}
|
||||
|
||||
/*! Decode SI13 Rest Octests (04.08 Chapter 10.5.2.37b).
|
||||
* \param[out] si13 decoded SI13 rest octets
|
||||
* \param[in] encoded SI13 rest octets
|
||||
* \returns parsed bits on success, negative on error */
|
||||
int osmo_gsm48_rest_octets_si13_decode(struct osmo_gsm48_si13_info *si13, const uint8_t *data)
|
||||
{
|
||||
struct osmo_gprs_cell_options *co = &si13->cell_opts;
|
||||
struct osmo_gprs_power_ctrl_pars *pcp = &si13->pwr_ctrl_pars;
|
||||
struct bitvec bv;
|
||||
int rc;
|
||||
|
||||
memset(&bv, 0, sizeof(bv));
|
||||
bv.data = (uint8_t *) data;
|
||||
bv.data_len = 20;
|
||||
|
||||
memset(si13, 0, sizeof(*si13));
|
||||
|
||||
|
||||
if (bitvec_get_bit_high(&bv) == H) {
|
||||
si13->bcch_change_mark = bitvec_get_uint(&bv, 3);
|
||||
si13->si_change_field = bitvec_get_uint(&bv, 4);
|
||||
if (bitvec_get_uint(&bv, 1)) {
|
||||
si13->bcch_change_mark = bitvec_get_uint(&bv, 2);
|
||||
/* FIXME: implement parsing GPRS Mobile Allocation IE */
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (bitvec_get_uint(&bv, 1)) {
|
||||
/* PBCCH present in cell */
|
||||
/* FIXME: parse not implemented */
|
||||
return -ENOTSUP;
|
||||
} else {
|
||||
/* PBCCH not present in cell */
|
||||
si13->rac = bitvec_get_uint(&bv, 8);
|
||||
si13->spgc_ccch_sup = bitvec_get_uint(&bv, 1);
|
||||
si13->prio_acc_thr = bitvec_get_uint(&bv, 3);
|
||||
si13->net_ctrl_ord = bitvec_get_uint(&bv, 2);
|
||||
if ((rc = decode_gprs_cell_opt(co, &bv)) < 0)
|
||||
return rc;
|
||||
|
||||
decode_gprs_pwr_ctrl_pars(pcp, &bv);
|
||||
}
|
||||
}
|
||||
return bv.cur_bit;
|
||||
}
|
||||
|
||||
/* GPRS Mobile Allocation as per TS 04.60 Chapter 12.10a:
|
||||
< GPRS Mobile Allocation IE > ::=
|
||||
< HSN : bit (6) >
|
||||
|
|
|
@ -320,6 +320,7 @@ osmo_gsm48_rest_octets_si2quater_encode;
|
|||
osmo_gsm48_rest_octets_si6_encode;
|
||||
osmo_gsm48_rest_octets_si3_encode;
|
||||
osmo_gsm48_rest_octets_si4_encode;
|
||||
osmo_gsm48_rest_octets_si13_decode;
|
||||
osmo_gsm48_rest_octets_si13_encode;
|
||||
osmo_gsm48_rest_octets_si3_decode;
|
||||
osmo_gsm48_rest_octets_si4_decode;
|
||||
|
|
|
@ -42,6 +42,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
|
|||
bsslap/bsslap_test \
|
||||
bssmap_le/bssmap_le_test \
|
||||
it_q/it_q_test \
|
||||
gsm48/rest_octets_test \
|
||||
$(NULL)
|
||||
|
||||
if ENABLE_MSGFILE
|
||||
|
@ -139,6 +140,9 @@ gsm29205_gsm29205_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
|||
gsm0408_gsm0408_test_SOURCES = gsm0408/gsm0408_test.c
|
||||
gsm0408_gsm0408_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
||||
|
||||
gsm48_rest_octets_test_SOURCES = gsm48/rest_octets_test.c
|
||||
gsm48_rest_octets_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
||||
|
||||
gprs_gprs_test_SOURCES = gprs/gprs_test.c
|
||||
gprs_gprs_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
||||
|
||||
|
@ -399,6 +403,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
|
|||
bsslap/bsslap_test.ok \
|
||||
bssmap_le/bssmap_le_test.ok \
|
||||
it_q/it_q_test.ok \
|
||||
gsm48/rest_octets_test.ok \
|
||||
$(NULL)
|
||||
|
||||
if ENABLE_LIBSCTP
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
|
||||
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/gsm48_rest_octets.h>
|
||||
|
||||
struct si13_test {
|
||||
const char *name;
|
||||
const struct osmo_gsm48_si13_info si;
|
||||
int enc_rc;
|
||||
int dec_rc;
|
||||
void (*post_dec_cb)(const struct si13_test *test, const struct osmo_gsm48_si13_info* dec);
|
||||
};
|
||||
|
||||
void post_dec_cb_test_alpha(const struct si13_test *test, const struct osmo_gsm48_si13_info* dec)
|
||||
{
|
||||
OSMO_ASSERT(test->si.pwr_ctrl_pars.alpha == dec->pwr_ctrl_pars.alpha);
|
||||
}
|
||||
|
||||
static const struct si13_test test_si13_arr[] = {
|
||||
{
|
||||
.name = "test alpha",
|
||||
.si = {
|
||||
.cell_opts = {
|
||||
.nmo = GPRS_NMO_II,
|
||||
.t3168 = 2000,
|
||||
.t3192 = 1500,
|
||||
.drx_timer_max = 3,
|
||||
.bs_cv_max = 15,
|
||||
.ctrl_ack_type_use_block = true,
|
||||
.ext_info_present = 0,
|
||||
.ext_info = {
|
||||
.egprs_supported = 1,
|
||||
.use_egprs_p_ch_req = 1,
|
||||
.bep_period = 5,
|
||||
.pfc_supported = 0,
|
||||
.dtm_supported = 0,
|
||||
.bss_paging_coordination = 0,
|
||||
.ccn_active = true,
|
||||
},
|
||||
},
|
||||
.pwr_ctrl_pars = {
|
||||
.alpha = 5,
|
||||
.t_avg_w = 16,
|
||||
.t_avg_t = 16,
|
||||
.pc_meas_chan = 0,
|
||||
.n_avg_i = 8,
|
||||
},
|
||||
.bcch_change_mark = 1,
|
||||
.si_change_field = 0,
|
||||
.rac = 0x03,
|
||||
.spgc_ccch_sup = 0,
|
||||
.net_ctrl_ord = 0,
|
||||
.prio_acc_thr = 6,
|
||||
},
|
||||
.enc_rc = 20,
|
||||
.dec_rc = 71,
|
||||
.post_dec_cb = post_dec_cb_test_alpha,
|
||||
},
|
||||
};
|
||||
|
||||
static void test_si13()
|
||||
{
|
||||
int i, rc;
|
||||
uint8_t data[GSM_MACBLOCK_LEN];
|
||||
struct osmo_gsm48_si13_info si13;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_si13_arr); i++) {
|
||||
memset(data, 0, sizeof(data));
|
||||
rc = osmo_gsm48_rest_octets_si13_encode(data, &test_si13_arr[i].si);
|
||||
if (rc >= 0) {
|
||||
printf("si13_encode (%d): %s\n", rc, osmo_hexdump(data, rc));
|
||||
} else {
|
||||
printf("si13_encode failed (%d)\n", rc);
|
||||
}
|
||||
OSMO_ASSERT(rc == test_si13_arr[i].enc_rc);
|
||||
if (rc <= 0)
|
||||
continue;
|
||||
memset(&si13, 0 , sizeof(si13));
|
||||
rc = osmo_gsm48_rest_octets_si13_decode(&si13, data);
|
||||
if (rc >= 0) {
|
||||
printf("si13_decode (%d)\n", rc);
|
||||
} else {
|
||||
printf("si13_decode failed (%d)\n", rc);
|
||||
}
|
||||
OSMO_ASSERT(rc == test_si13_arr[i].dec_rc);
|
||||
if (test_si13_arr[i].post_dec_cb) {
|
||||
test_si13_arr[i].post_dec_cb(&test_si13_arr[i], &si13);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_si13();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
si13_encode (20): 90 00 d8 5a 6f c9 e5 84 10 ab 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
|
||||
si13_decode (71)
|
|
@ -156,6 +156,12 @@ cat $abs_srcdir/gsm0408/gsm0408_test.ok > expout
|
|||
AT_CHECK([$abs_top_builddir/tests/gsm0408/gsm0408_test], [0], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([gsm48_rest_octets])
|
||||
AT_KEYWORDS([gsm48_rest_octets])
|
||||
cat $abs_srcdir/gsm48/rest_octets_test.ok > expout
|
||||
AT_CHECK([$abs_top_builddir/tests/gsm48/rest_octets_test], [0], [expout], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([gprs])
|
||||
AT_KEYWORDS([gprs])
|
||||
cat $abs_srcdir/gprs/gprs_test.ok > expout
|
||||
|
|
Loading…
Reference in New Issue