From: Max msuraev@sysmocom.de
Add function which adds specified number of bits from each element of array to the bit vector prefixing each addition with one and finishing entire sequence with adding 0. This is very common patter for various repetitive data structures described with CSN.1 in 3GPP standards.
Corresponding test vectors and doxygen headers are added too. --- include/osmocom/core/bitvec.h | 3 +++ src/bitvec.c | 40 ++++++++++++++++++++++++++++++++++++++++ tests/bitvec/bitvec_test.c | 43 +++++++++++++++++++++++++++++++++++++++++++ tests/bitvec/bitvec_test.ok | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+)
diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h index 5314cf2..c3c1153 100644 --- a/include/osmocom/core/bitvec.h +++ b/include/osmocom/core/bitvec.h @@ -91,5 +91,8 @@ void bitvec_zero(struct bitvec *bv); unsigned bitvec_rl(const struct bitvec *bv, bool b); void bitvec_shiftl(struct bitvec *bv, unsigned int n); int16_t bitvec_get_int16_msb(const struct bitvec *bv, unsigned int num_bits); +unsigned int bitvec_add_array(struct bitvec *bv, const uint32_t *array, + unsigned int array_len, bool dry_run, + unsigned int num_bits);
/*! @} */ diff --git a/src/bitvec.c b/src/bitvec.c index 00ae150..a92fd71 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -570,4 +570,44 @@ void bitvec_shiftl(struct bitvec *bv, unsigned n) bv->cur_bit -= n; }
+/*! \brief Add given array to bitvec + * \param[in,out] bv bit vector to work with + * \param[in] array elements to be added + * \param[in] array_len length of array + * \param[in] dry_run indicates whether to return number of bits required + * instead of adding anything to bv for real + * \param[in] num_bits number of bits to consider in each element of array + * \returns number of bits necessary to add array elements if dry_run is true, + * 0 otherwise (only in this case bv is actually changed) + * + * N. B: no length checks are performed on bv - it's caller's job to ensure + * enough space is available - for example by calling with dry_run = true first. + * + * Useful for common pattern in CSN.1 spec which looks like: + * { 1 < XXX : bit (num_bits) > } ** 0 + * which means repeat any times (between 0 and infinity), + * start each repetition with 1, mark end of repetitions with 0 bit + * see app. note in 3GPP TS 24.007 § B.2.1 Rule A2 + */ +unsigned int bitvec_add_array(struct bitvec *bv, const uint32_t *array, + unsigned int array_len, bool dry_run, + unsigned int num_bits) +{ + unsigned i, bits = 1; /* account for stop bit */ + for (i = 0; i < array_len; i++) { + if (dry_run) { + bits += (1 + num_bits); + } else { + bitvec_set_bit(bv, 1); + bitvec_set_uint(bv, array[i], num_bits); + } + } + + if (dry_run) + return bits; + + bitvec_set_bit(bv, 0); /* stop bit - end of the sequence */ + return 0; +} + /*! @} */ diff --git a/tests/bitvec/bitvec_test.c b/tests/bitvec/bitvec_test.c index 76d6773..a98a91c 100644 --- a/tests/bitvec/bitvec_test.c +++ b/tests/bitvec/bitvec_test.c @@ -132,6 +132,43 @@ static void test_unhex(const char *hex) printf("%s\n", hex); }
+static inline void test_array_item(unsigned t, struct bitvec *b, unsigned int n, + uint32_t *array, unsigned int p) +{ + unsigned int i, x, y; + bitvec_zero(b); + x = b->cur_bit; + i = bitvec_add_array(b, array, n, true, t); + y = b->cur_bit; + bitvec_add_array(b, array, n, false, t); + printf("\nbits: %u, est: %u, real: %u, x: %u, y: %u\n", + t, i, b->cur_bit, x, y); + for (i = 0; i < p; i++) { + printf(OSMO_BIT_SPEC " ", OSMO_BIT_PRINT(b->data[i])); + if (0 == (i + 1) % 15) + printf("\n"); + } +} + +static void test_array() +{ + struct bitvec b; + uint8_t d[4096]; + b.data = d; + b.data_len = sizeof(d); + + unsigned int i, n = 64; + uint32_t array[n]; + for (i = 0; i < n; i++) { + array[i] = i * i * i + i; + printf("0x%x ", array[i]); + } + + test_array_item(3, &b, n, array, n); + test_array_item(9, &b, n, array, n * 2); + test_array_item(17, &b, n, array, n * 3); +} + int main(int argc, char **argv) { struct bitvec bv; @@ -204,5 +241,11 @@ int main(int argc, char **argv) test_unhex("DEADFACE000000000000000000000000000000BEEFFEED"); test_unhex("FFFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
+ printf("arrr...\n"); + + test_array(); + + printf("\nbitvec ok.\n"); + return 0; } diff --git a/tests/bitvec/bitvec_test.ok b/tests/bitvec/bitvec_test.ok index 1c993d3..e256108 100644 --- a/tests/bitvec/bitvec_test.ok +++ b/tests/bitvec/bitvec_test.ok @@ -134,3 +134,36 @@ DEADFACE000000000000000000000000000000BEEFFEED 0 -=> cur_bit=512 fffffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa FFFFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +arrr... +0x0 0x2 0xa 0x1e 0x44 0x82 0xde 0x15e 0x208 0x2e2 0x3f2 0x53e 0x6cc 0x8a2 0xac6 0xd3e 0x1010 0x1342 0x16da 0x1ade 0x1f54 0x2442 0x29ae 0x2f9e 0x3618 0x3d22 0x44c2 0x4cfe 0x55dc 0x5f62 0x6996 0x747e 0x8020 0x8c82 0x99aa 0xa79e 0xb664 0xc602 0xd67e 0xe7de 0xfa28 0x10d62 0x12192 0x136be 0x14cec 0x16422 0x17c66 0x195be 0x1b030 0x1cbc2 0x1e87a 0x2065e 0x22574 0x245c2 0x2674e 0x28a1e 0x2ae38 0x2d3a2 0x2fa62 0x3227e 0x34bfc 0x376e2 0x3a336 0x3d0fe +bits: 3, est: 257, real: 257, x: 0, y: 0 +1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. 11..1.1. +111.111. 1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. 11..1.1. 111.111. 1...1.1. 1.1.111. +11..1.1. 111.111. ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ +bits: 9, est: 641, real: 641, x: 0, y: 0 +1....... ..1..... ..1.1... ..1.1.1. ...1111. 1..1...1 ..1.1... ..1.1.11 .1111.11 .1.1111. 1.....1. ..1.111. ..1.1111 11..1.11 ..11111. +1.11..11 ..1.1.1. ..1.1.11 ...11.11 ..11111. 1....1.. ..11.1.. ..1.1.11 .11.1.1. 11.1111. 11.1.1.1 ..1..1.. ..1.111. 1.111.11 1..1111. +1....11. ..11..1. ..1.1.11 ....1.1. 1111111. 1111.111 ..11.11. ..1.111. .1.11.1. .111111. 1...1... ..1.1... ..1.111. 1.1.1.11 1..1111. +1..11..1 ..1..... ..1.1..1 11111.11 11.1111. 1...1.1. ..11.11. ..1.111. .1..1.1. 1.11111. 1.111.11 ..1...1. ..1.1..1 1..11.11 1.11111. +1...11.. ..1111.. ..1.1..1 111.1.1. .1.1111. 11.111.1 ..1111.. ..1.11.1 ..111.1. ...1111. 1...111. ..111.1. ..1.1..1 1...1.1. .111111. +11111111 ..1.111. ..1.11.. 11.11.1. 1111111. ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ +bits: 17, est: 1153, real: 1153, x: 0, y: 0 +1....... ........ ..1..... ........ ..1.1... ........ ..1.1.1. ........ ...1111. 1....... ...1...1 ..1..... ....1... ..1.1... ......11 +.1111.1. .......1 .1.1111. 1....... 1.....1. ..1..... ..1.111. ..1.1... ....1111 11..1.1. .....1.1 ..11111. 1......1 1.11..11 ..1..... +1...1.1. ..1.1... ..1.1.11 ...11.1. ....11.1 ..11111. 1....1.. .....1.. ..1....1 ..11.1.. ..1.1... .1.11.11 .11.1.1. ...11.1. 11.1111. +1....111 11.1.1.1 ..1...1. .1...1.. ..1.1... 1.1..11. 1.111.1. ..1.1111 1..1111. 1...11.1 1....11. ..1...11 11.1..1. ..1.1..1 ...1..11 +....1.1. .1..11.. 1111111. 1..1.1.1 .111.111 ..1..1.1 1111.11. ..1.1..1 1.1..11. .1.11.1. .111.1.. .111111. 1.1..... ....1... ..1.1... +11..1... ..1.1.1. .11..11. 1.1.1.1. 1.1..111 1..1111. 1.1.11.1 1..11..1 ..1.11.. .11..... ..1.1.11 .1.11..1 11111.1. 111..111 11.1111. +1.11111. 1...1.1. ..11.... 11.1.11. ..1.11.. 1....11. .1..1.11 ..11.11. 1.11111. 11.1..11 ..111.11 ..11.11. .1....1. ..1.11.1 1111...1 +1..11.11 1..1.1.1 1.11111. 111.11.. ....11.. ..1111.. 1.1111.. ..1.1111 1.1....1 111.1.1. .....11. .1.1111. 1...1..1 .1.111.1 ..1..1.. +.1.111.. ..1.1..1 1..111.1 ..111.1. 1...1.1. ...1111. 1.1.1.11 1...111. ..1.11.1 ..111.1. ..1.1.11 111.1..1 1...1.11 ..1...1. .111111. +11.1..1. 11111111 ..11.111 .11.111. ..1.111. 1...11.. 11.11.11 11.1.... 1111111. ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ ........ +bitvec ok.
From: Max msuraev@sysmocom.de
Add structure representing group of EARFCNs with common priority, threshold etc. Add functions to populate this structure. --- include/osmocom/gsm/sysinfo.h | 32 ++++++++++++++++++++++++++- src/gsm/libosmogsm.map | 4 ++++ src/gsm/sysinfo.c | 50 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/include/osmocom/gsm/sysinfo.h b/include/osmocom/gsm/sysinfo.h index 7d1fe2b..346194e 100644 --- a/include/osmocom/gsm/sysinfo.h +++ b/include/osmocom/gsm/sysinfo.h @@ -3,6 +3,9 @@ #include <osmocom/core/utils.h> #include <osmocom/gsm/protocol/gsm_04_08.h>
+#define OSMO_EARFCN_INVALID 666 +#define OSMO_EARFCN_MEAS_INVALID 0xff + enum osmo_sysinfo_type { SYSINFO_TYPE_NONE, SYSINFO_TYPE_1, @@ -32,9 +35,36 @@ enum osmo_sysinfo_type { _MAX_SYSINFO_TYPE };
+struct earfcn { + /* EARFCN (16 bits) array */ + uint16_t *arfcn; + /* Measurement Bandwidth (3 bits), might be absent + (OSMO_EARFCN_MEAS_INVALID is stored in this case) */ + uint8_t *meas_bw; + /* length of arfcn and meas_bw arrays (got to be the same) */ + size_t length; + /* THRESH_E-UTRAN_high (5 bits) */ + uint8_t thresh_hi; + /* THRESH_E-UTRAN_low (5 bits) */ + uint8_t thresh_lo; + /* E-UTRAN_PRIORITY (3 bits) */ + uint8_t prio; + /* E-UTRAN_QRXLEVMIN */ + uint8_t qrxlm; + /* indicates whether thresh_lo value is valid + thresh_hi is mandatory and hence always considered valid */ + bool thresh_lo_valid; + /* indicates whether prio value is valid */ + bool prio_valid; + /* indicates whether qrxlm value is valid */ + bool qrxlm_valid; +}; + typedef uint8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
extern const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE]; - +int osmo_earfcn_add(struct earfcn *e, uint16_t arfcn, uint8_t meas_bw); +int osmo_earfcn_del(struct earfcn *e, uint16_t arfcn); +void osmo_earfcn_init(struct earfcn *e); uint8_t osmo_sitype2rsl(enum osmo_sysinfo_type si_type); enum osmo_sysinfo_type osmo_rsl2sitype(uint8_t rsl_si); diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 7eebe7f..9b6e8ea 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -29,6 +29,10 @@ osmo_sitype_strs; comp128; dbm2rxlev;
+osmo_earfcn_add; +osmo_earfcn_del; +osmo_earfcn_init; + gprs_cipher_gen_input_i; gprs_cipher_gen_input_ui; gprs_cipher_load; diff --git a/src/gsm/sysinfo.c b/src/gsm/sysinfo.c index 1408f6b..e4d0ddf 100644 --- a/src/gsm/sysinfo.c +++ b/src/gsm/sysinfo.c @@ -125,6 +125,56 @@ const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE] = { { 0, NULL } };
+/*! \brief Add pair of arfcn and measurement bandwith value to earfcn struct + * \param[in,out] e earfcn struct + * \param[in] arfcn EARFCN value, 16 bits + * \param[in] meas_bw measurement bandwith value + * \returns 0 on success, error otherwise + */ +int osmo_earfcn_add(struct earfcn *e, uint16_t arfcn, uint8_t meas_bw) +{ + size_t i; + for (i = 0; i < e->length; i++) { + if (OSMO_EARFCN_INVALID == e->arfcn[i]) { + e->arfcn[i] = arfcn; + e->meas_bw[i] = meas_bw; + return 0; + } + } + return -ENOMEM; +} + +/*! \brief Delete arfcn (and corresponding measurement bandwith) from earfcn + * struct + * \param[in,out] e earfcn struct + * \param[in] arfcn EARFCN value, 16 bits + * \returns 0 on success, error otherwise + */ +int osmo_earfcn_del(struct earfcn *e, uint16_t arfcn) +{ + size_t i; + for (i = 0; i < e->length; i++) { + if (arfcn == e->arfcn[i]) { + e->arfcn[i] = OSMO_EARFCN_INVALID; + e->meas_bw[i] = OSMO_EARFCN_MEAS_INVALID; + return 0; + } + } + return -ENOENT; +} + +/*! \brief Initialize earfcn struct + * \param[in,out] e earfcn struct + */ +void osmo_earfcn_init(struct earfcn *e) +{ + size_t i; + for (i = 0; i < e->length; i++) { + e->arfcn[i] = OSMO_EARFCN_INVALID; + e->meas_bw[i] = OSMO_EARFCN_MEAS_INVALID; + } +} + uint8_t osmo_sitype2rsl(enum osmo_sysinfo_type si_type) { return sitype2rsl[si_type];
Hi Max,
I have already merged the patch, but now have one more comment that should definitely be addressed ASAP:
On Thu, Mar 17, 2016 at 11:51:09AM +0100, msuraev@sysmocom.de wrote:
+struct earfcn {
1) this misses the osmo_ prefix which must be used for all new data types and symbols in the libraries
2) it is not just an EARFCN (which is an integer), but it is actually some SI-specific EARFCN parameters. So please let's give it a proper name. like osmo_earfcn_meas_pars (for measurement parameters) or the like.
Please provide a follow-up patch quickly so we can resolve this before any users rely on the old naming. Thanks.
Regards, Harald
Done - see Fix earfcn struct header https://patchwork.ozlabs.org/patch/599042/ patch.
On 03/17/2016 02:11 PM, Harald Welte wrote:
Hi Max,
I have already merged the patch, but now have one more comment that should definitely be addressed ASAP:
On Thu, Mar 17, 2016 at 11:51:09AM +0100, msuraev@sysmocom.de wrote:
+struct earfcn {
this misses the osmo_ prefix which must be used for all new data types and symbols in the libraries
it is not just an EARFCN (which is an integer), but it is actually some SI-specific EARFCN parameters. So please let's give it a proper name. like osmo_earfcn_meas_pars (for measurement parameters) or the like.
Please provide a follow-up patch quickly so we can resolve this before any users rely on the old naming. Thanks.
Regards, Harald
On 17 Mar 2016, at 11:51, msuraev@sysmocom.de wrote:
+struct earfcn {
- /* EARFCN (16 bits) array */
- uint16_t *arfcn;
Who do you write the comments for? If for a developer, have you checked they turn up in doxygen?
- bool thresh_lo_valid;
this breaks the osmo-bts build:
http://jenkins.osmocom.org/jenkins/job/osmo-bts/2029/
In file included from sysinfo.c:23: /home/builder/source/workspace/osmo-bts/FIRMWARE_VERSION/master/label/linux_i386_debian_squeeze/deps/libosmocore/../install/include/osmocom/gsm/sysinfo.h:56: error: expected specifier-qualifier-list before 'bool'
On 03/17/2016 03:50 PM, Holger Freyther wrote:
On 17 Mar 2016, at 11:51, msuraev@sysmocom.de wrote:
+struct earfcn {
- /* EARFCN (16 bits) array */
- uint16_t *arfcn;
Who do you write the comments for? If for a developer, have you checked they turn up in doxygen?
For myself mostly.
- bool thresh_lo_valid;
this breaks the osmo-bts build:
http://jenkins.osmocom.org/jenkins/job/osmo-bts/2029/
In file included from sysinfo.c:23: /home/builder/source/workspace/osmo-bts/FIRMWARE_VERSION/master/label/linux_i386_debian_squeeze/deps/libosmocore/../install/include/osmocom/gsm/sysinfo.h:56: error: expected specifier-qualifier-list before 'bool'
Fixed in "Fix earfcn struct header" patch.
I've forgot to add stdbool.h to header - fixed in separate patch already.
On 03/17/2016 04:33 PM, Neels Hofmeyr wrote:
On Thu, Mar 17, 2016 at 03:50:52PM +0100, Holger Freyther wrote:
- bool thresh_lo_valid;
why don't we have a bool type though? is there a bool in linux kernel code?
~Neels