From 70fdd24d04a37217724ec8f12873e292b10e5e4d Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 15 Jun 2017 15:10:53 +0200 Subject: Update SI data structures and generation To support segmented SI2quater as per 3GPP TS 44.018 we'll have to support multiple SI messages (up to 16 for SI2q) for a given type in contrast to existing 1:1 mapping: * expand storage space to hold up to 16 SI messages (spec limit) * add assertions for budget calculations * generate multiple SI2q messages * adjust SI2q-related tests * use precise check for number of SIq messages instead of approximate estimation Change-Id: Ic516ec9f0b821557d9461ae9f1c0afdd786f3b05 Related: OS#1660 --- openbsc/include/openbsc/gsm_data.h | 7 ++ openbsc/include/openbsc/gsm_data_shared.h | 16 +-- openbsc/include/openbsc/system_information.h | 2 + openbsc/src/libbsc/bsc_init.c | 6 +- openbsc/src/libbsc/bsc_vty.c | 78 ++++++-------- openbsc/src/libbsc/rest_octets.c | 80 ++++++++------ openbsc/src/libbsc/system_information.c | 152 ++++++++++++++++++--------- openbsc/tests/gsm0408/gsm0408_test.c | 78 +++++++++++--- openbsc/tests/gsm0408/gsm0408_test.ok | 100 +++++++++++++++--- 9 files changed, 354 insertions(+), 165 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 05d834e31..5ab7c3fbd 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -29,6 +29,13 @@ struct bsc_subscr; #define tmsi_from_string(str) strtoul(str, NULL, 10) +/* 3-bit long values */ +#define EARFCN_PRIO_INVALID 8 +#define EARFCN_MEAS_BW_INVALID 8 +/* 5-bit long values */ +#define EARFCN_QRXLV_INVALID 32 +#define EARFCN_THRESH_LOW_INVALID 32 + enum gsm_security_event { GSM_SECURITY_NOAVAIL, GSM_SECURITY_AUTH_FAILED, diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index a507606e8..d3fd75700 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -26,7 +26,8 @@ #include -/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018: 4-bit index is used (2#1111 = 10#15) */ +/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1: + 4-bit index is used (2#1111 = 10#15) */ #define SI2Q_MAX_NUM 16 /* length in bits (for single SI2quater message) */ #define SI2Q_MAX_LEN 160 @@ -301,8 +302,9 @@ struct gsm_lchan { /* bitmask of all SI that are present/valid in si_buf */ uint32_t valid; uint32_t last; - /* buffers where we put the pre-computed SI */ - sysinfo_buf_t buf[_MAX_SYSINFO_TYPE]; + /* buffers where we put the pre-computed SI: + SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */ + sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; } si; struct { uint8_t flags; @@ -491,10 +493,10 @@ struct gsm_bts_trx { struct gsm_bts_trx_ts ts[TRX_NR_TS]; }; -#define GSM_BTS_SI2Q(bts) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater]) +#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i]) #define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i)) -#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i]) -#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i]) +#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0]) +#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0]) enum gsm_bts_type { GSM_BTS_TYPE_UNKNOWN, @@ -739,7 +741,7 @@ struct gsm_bts { uint8_t si2q_index; /* distinguish individual SI2quater messages */ uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */ /* buffers where we put the pre-computed SI */ - sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE]; + sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; /* offsets used while generating SI2quater */ size_t e_offset; size_t u_offset; diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h index 21016b8c6..71bea2660 100644 --- a/openbsc/include/openbsc/system_information.h +++ b/openbsc/include/openbsc/system_information.h @@ -14,6 +14,8 @@ unsigned range512_q(unsigned m); int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w, int f0, uint8_t *chan_list); uint8_t si2q_num(struct gsm_bts *bts); +int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio, + uint8_t qrx, uint8_t meas_bw); int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble); int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool diversity); diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 25f3fdcee..b95c7b08e 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -101,7 +101,7 @@ int bsc_shutdown_net(struct gsm_network *net) static int rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i, int si_len) { struct gsm_bts *bts = trx->bts; - int rc; + int rc, j; DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i), osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN)); @@ -114,6 +114,10 @@ static int rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i, int si_len) rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i), GSM_BTS_SI(bts, i), si_len); break; + case SYSINFO_TYPE_2quater: + for (j = 0; j <= bts->si2q_count; j++) + rc = rsl_bcch_info(trx, i, (const uint8_t *)GSM_BTS_SI2Q(bts, j), GSM_MACBLOCK_LEN); + break; default: rc = rsl_bcch_info(trx, osmo_sitype2rsl(i), GSM_BTS_SI(bts, i), si_len); diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index b05d3d9da..2fc39ab4c 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -2774,6 +2774,7 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } +/* help text should be kept in sync with EARFCN_*_INVALID defines */ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, "si2quater neighbor-list add earfcn <0-65535> thresh-hi <0-31> " "thresh-lo <0-32> prio <0-8> qrxlv <0-32> meas <0-8>", @@ -2791,54 +2792,37 @@ DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd, uint16_t arfcn = atoi(argv[0]); uint8_t thresh_hi = atoi(argv[1]), thresh_lo = atoi(argv[2]), prio = atoi(argv[3]), qrx = atoi(argv[4]), meas = atoi(argv[5]); - int r = osmo_earfcn_add(e, arfcn, - (meas < 8) ? meas : OSMO_EARFCN_MEAS_INVALID); + int r = bts_earfcn_add(bts, arfcn, thresh_hi, thresh_lo, prio, qrx, meas); - if (r < 0) { - vty_out(vty, "Unable to add ARFCN %u: %s%s", arfcn, strerror(-r), - VTY_NEWLINE); - return CMD_WARNING; - } - - if (e->thresh_hi && thresh_hi != e->thresh_hi) - vty_out(vty, "Warning: multiple threshold-high are not " - "supported, overriding previous threshold %u%s", - e->thresh_hi, VTY_NEWLINE); - - e->thresh_hi = thresh_hi; - - if (thresh_lo != 32) { - if (e->thresh_lo_valid && e->thresh_lo != thresh_lo) - vty_out(vty, "Warning: multiple threshold-low are not " - "supported, overriding previous threshold %u%s", - e->thresh_lo, VTY_NEWLINE); - e->thresh_lo = thresh_lo; - e->thresh_lo_valid = true; - } - - if (qrx != 32) { - if (e->qrxlm_valid && e->qrxlm != qrx) - vty_out(vty, "Warning: multiple QRXLEVMIN are not " - "supported, overriding previous value %u%s", - e->qrxlm, VTY_NEWLINE); - e->qrxlm = qrx; - e->qrxlm_valid = true; - } - - if (prio != 8) { - if (e->prio_valid && e->prio != prio) - vty_out(vty, "Warning: multiple priorities are not " - "supported, overriding previous value %u%s", - e->prio, VTY_NEWLINE); - e->prio = prio; - e->prio_valid = true; + switch (r) { + case 1: + vty_out(vty, "Warning: multiple threshold-high are not supported, overriding with %u%s", + thresh_hi, VTY_NEWLINE); + break; + case EARFCN_THRESH_LOW_INVALID: + vty_out(vty, "Warning: multiple threshold-low are not supported, overriding with %u%s", + thresh_lo, VTY_NEWLINE); + break; + case EARFCN_QRXLV_INVALID + 1: + vty_out(vty, "Warning: multiple QRXLEVMIN are not supported, overriding with %u%s", + qrx, VTY_NEWLINE); + break; + case EARFCN_PRIO_INVALID: + vty_out(vty, "Warning: multiple priorities are not supported, overriding with %u%s", + prio, VTY_NEWLINE); + break; + default: + if (r < 0) { + vty_out(vty, "Unable to add ARFCN %u: %s%s", arfcn, strerror(-r), VTY_NEWLINE); + return CMD_WARNING; + } } - if (si2q_num(bts) < 2) /* FIXME: use SI2Q_MAX_NUM */ + if (si2q_num(bts) <= SI2Q_MAX_NUM) return CMD_SUCCESS; vty_out(vty, "Warning: not enough space in SI2quater (%u/%u used) for a given EARFCN %u%s", - bts->si2q_count, 2, arfcn, VTY_NEWLINE); /* FIXME: use SI2Q_MAX_NUM */ + bts->si2q_count, SI2Q_MAX_NUM, arfcn, VTY_NEWLINE); osmo_earfcn_del(e, arfcn); return CMD_WARNING; @@ -2877,16 +2861,14 @@ DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd, switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) { case -ENOMEM: - vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) " - "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); + vty_out(vty, "Unable to add UARFCN: max number of UARFCNs (%u) reached%s", MAX_EARFCN_LIST, VTY_NEWLINE); return CMD_WARNING; case -ENOSPC: - vty_out(vty, "Warning: not enough space in si2quater for a " - "given arfcn%s", VTY_NEWLINE); + vty_out(vty, "Warning: not enough space in SI2quater for a given UARFCN (%u, %u)%s", + arfcn, scramble, VTY_NEWLINE); return CMD_WARNING; case -EADDRINUSE: - vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s", - arfcn, scramble, VTY_NEWLINE); + vty_out(vty, "Unable to add UARFCN: (%u, %u) is already added%s", arfcn, scramble, VTY_NEWLINE); return CMD_WARNING; } diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c index a6fdf46fe..fdab70a0c 100644 --- a/openbsc/src/libbsc/rest_octets.c +++ b/openbsc/src/libbsc/rest_octets.c @@ -65,6 +65,12 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, struct gsm_bts *bt unsigned i, skip = 0; size_t offset = bts->e_offset; uint8_t rem = budget - 6, earfcn_budget; /* account for mandatory stop bit and THRESH_E-UTRAN_high */ + + if (budget <= 6) + return; + + OSMO_ASSERT(budget <= SI2Q_MAX_LEN); + /* first we have to properly adjust budget requirements */ if (e->prio_valid) /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/ rem -= 4; @@ -87,16 +93,17 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, struct gsm_bts *bt if (skip < offset) { skip++; /* ignore EARFCNs added on previous calls */ } else { - earfcn_budget = 17; /* computer budget per-EARFCN */ + earfcn_budget = 17; /* compute budget per-EARFCN */ if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i]) earfcn_budget++; else earfcn_budget += 4; - if (rem - earfcn_budget < 0) { + if (rem - earfcn_budget < 0) break; - } else { + else { bts->e_offset++; + rem -= earfcn_budget; bitvec_set_bit(bv, 1); /* EARFCN: */ bitvec_set_uint(bv, e->arfcn[i], 16); @@ -143,6 +150,12 @@ static inline void append_eutran_neib_cell(struct bitvec *bv, struct gsm_bts *bt static inline void append_earfcn(struct bitvec *bv, struct gsm_bts *bts, uint8_t budget) { + int rem = budget - 25; + if (rem <= 0) + return; + + OSMO_ASSERT(budget <= SI2Q_MAX_LEN); + /* Additions in Rel-5: */ bitvec_set_bit(bv, H); /* No 3G Additional Measurement Param. Descr. */ @@ -191,7 +204,7 @@ static inline void append_earfcn(struct bitvec *bv, struct gsm_bts *bts, uint8_t bitvec_set_bit(bv, 1); /* N. B: 25 bits are set in append_earfcn() - keep it in sync with budget adjustment below: */ - append_eutran_neib_cell(bv, bts, budget - 25); + append_eutran_neib_cell(bv, bts, rem); /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */ bitvec_set_bit(bv, 0); @@ -267,7 +280,12 @@ static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t const uint16_t *u = bts->si_common.data.uarfcn_list, *sc = bts->si_common.data.scramble_list; int i, j, k, rc, st = 0, a[bts->si_common.uarfcn_length]; uint16_t cu = u[bts->u_offset]; /* caller ensures that length is positive */ - uint8_t rem = budget - 7; /* account for constant bits right away */ + uint8_t rem = budget - 7, offset_diff; /* account for constant bits right away */ + + OSMO_ASSERT(budget <= SI2Q_MAX_LEN); + + if (budget <= 7) + return -ENOMEM; /* 3G Neighbour Cell Description */ bitvec_set_bit(bv, 1); @@ -282,20 +300,22 @@ static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t bitvec_set_bit(bv, 0); for (i = bts->u_offset; i < bts->si_common.uarfcn_length; i++) { - for (j = st, k = 0; j < i; j++) + offset_diff = 0; + for (j = st, k = 0; j < i; j++) { a[k++] = sc[j]; /* copy corresponding SCs */ - + offset_diff++; /* compute proper offset step */ + } if (u[i] != cu) { /* we've reached new UARFCN */ rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k); if (rc < 0) { /* estimate bit length requirements */ return rc; } - if (rem - rc < 0) { + if (rem - rc <= 0) break; /* we have ran out of budget in current SI2q */ - } else { + else { rem -= append_utran_fdd(bv, cu, a, k); - bts->u_offset++; + bts->u_offset += offset_diff; } cu = u[i]; st = i; /* update start position */ @@ -303,9 +323,11 @@ static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t } if (rem > 22) { /* add last UARFCN not covered by previous cycle if it could possibly fit into budget */ - for (i = st, k = 0; i < bts->si_common.uarfcn_length; i++) + offset_diff = 0; + for (i = st, k = 0; i < bts->si_common.uarfcn_length; i++) { a[k++] = sc[i]; - + offset_diff++; + } rc = append_utran_fdd_length(cu, a, bts->si_common.uarfcn_length, k); if (rc < 0) { return rc; @@ -313,7 +335,7 @@ static inline int append_uarfcns(struct bitvec *bv, struct gsm_bts *bts, uint8_t if (rem - rc >= 0) { rem -= append_utran_fdd(bv, cu, a, k); - bts->u_offset++; + bts->u_offset += offset_diff; } } @@ -331,6 +353,10 @@ int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts) { int rc; struct bitvec bv; + + if (bts->si2q_count < bts->si2q_index) + return -EINVAL; + bv.data = data; bv.data_len = 20; bitvec_zero(&bv); @@ -362,34 +388,28 @@ int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts) /* No extension (length) */ bitvec_set_bit(&bv, 0); - if (bts->si_common.uarfcn_length) { - /* Even if we do not append EARFCN we still need to set 3 bits */ - rc = append_uarfcns(&bv, bts, SI2Q_MAX_LEN - (bv.cur_bit + 3)); + rc = SI2Q_MAX_LEN - (bv.cur_bit + 3); + if (rc > 0 && bts->si_common.uarfcn_length - bts->u_offset > 0) { + rc = append_uarfcns(&bv, bts, rc); if (rc < 0) { - LOGP(DRR, LOGL_ERROR, "SI2quater: failed to append %zu UARFCNs due to range encoding failure: %s\n", - bts->si_common.uarfcn_length, strerror(-rc)); + LOGP(DRR, LOGL_ERROR, "SI2quater [%u/%u]: failed to append %zu UARFCNs due to range encoding " + "failure: %s\n", + bts->si2q_index, bts->si2q_count, bts->si_common.uarfcn_length, strerror(-rc)); return rc; } - } else { /* No 3G Neighbour Cell Description */ + } else /* No 3G Neighbour Cell Description */ bitvec_set_bit(&bv, 0); - } /* No 3G Measurement Parameters Description */ bitvec_set_bit(&bv, 0); /* No GPRS_3G_MEASUREMENT Parameters Descr. */ bitvec_set_bit(&bv, 0); - if (si2q_earfcn_count(&bts->si_common.si2quater_neigh_list)) { - append_earfcn(&bv, bts, SI2Q_MAX_LEN - bv.cur_bit); - - /* FIXME: remove following check once multiple SI2q are properly supported */ - if ((bts->e_offset != si2q_earfcn_count(&bts->si_common.si2quater_neigh_list)) || - si2q_earfcn_count(&bts->si_common.si2quater_neigh_list) > 5) - return -ENOMEM; - } else { - /* No Additions in Rel-5: */ + rc = SI2Q_MAX_LEN - bv.cur_bit; + if (rc > 0 && si2q_earfcn_count(&bts->si_common.si2quater_neigh_list) - bts->e_offset > 0) + append_earfcn(&bv, bts, rc); + else /* No Additions in Rel-5: */ bitvec_set_bit(&bv, L); - } bitvec_spare_padding(&bv, (bv.data_len * 8) - 1); return bv.data_len; diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index a074a783a..dcabbbdd1 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -122,50 +122,73 @@ unsigned range512_q(unsigned m) } } -static inline unsigned earfcn_size(const struct gsm_bts *bts) +size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e) { - const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; /* EARFCN */ + unsigned i, ret = 0; + + if (!e) + return 0; + + for (i = 0; i < e->length; i++) + if (e->arfcn[i] != OSMO_EARFCN_INVALID) + ret++; - /* account for all the constant bits in append_earfcn() */ - return 25 + osmo_earfcn_bit_size_ext(e, bts->e_offset); + return ret; } -static inline unsigned uarfcn_size(const struct gsm_bts *bts) +/* generate SI2quater messages, return rest octets length of last generated message or negative error code */ +static int make_si2quaters(struct gsm_bts *bts, bool counting) { - const uint16_t *u = bts->si_common.data.uarfcn_list; - uint16_t cu = u[bts->u_offset]; /* UARFCN */ - /* account for all the constant bits in append_uarfcns() */ - unsigned s = 7, append = 22, r = 0, i, st = 0, j, k; - - for (i = bts->u_offset; i < bts->si_common.uarfcn_length; i++) { - for (j = st, k = 0; j < i; j++, k++); - if (u[i] != cu) { /* we've reached new UARFCN */ - r += (append + range1024_p(k)); - cu = u[i]; - st = i; /* update start position */ + int rc; + bool memory_exceeded = true; + struct gsm48_system_information_type_2quater *si2q; + + for (bts->si2q_index = 0; bts->si2q_index < SI2Q_MAX_NUM; bts->si2q_index++) { + si2q = GSM_BTS_SI2Q(bts, bts->si2q_index); + if (counting) { /* that's legitimate if we're called for counting purpose: */ + if (bts->si2q_count < bts->si2q_index) + bts->si2q_count = bts->si2q_index; + } else { + memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); + + si2q->header.l2_plen = GSM48_LEN2PLEN(22); + si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR; + si2q->header.skip_indicator = 0; + si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; + } + + rc = rest_octets_si2quater(si2q->rest_octets, bts); + if (rc < 0) + return rc; + + if (bts->u_offset >= bts->si_common.uarfcn_length && + bts->e_offset >= si2q_earfcn_count(&bts->si_common.si2quater_neigh_list)) { + memory_exceeded = false; + break; } } - /* add last UARFCN not covered by previous cycle */ - for (i = st, k = 0; i < bts->si_common.uarfcn_length; i++, k++); + if (memory_exceeded) + return -ENOMEM; - return s + r + append + range1024_p(k); + return rc; } +/* we generate SI2q rest octets twice to get proper estimation but it's one time cost anyway */ uint8_t si2q_num(struct gsm_bts *bts) { - size_t est, e_sz = 1, u_sz = 1; - - if (&bts->si_common.si2quater_neigh_list) /* EARFCN */ - e_sz = earfcn_size(bts); + int rc = make_si2quaters(bts, true); + uint8_t num = bts->si2q_index + 1; /* number of SI2quater messages */ - if (bts->si_common.uarfcn_length) /* UARFCN */ - u_sz = uarfcn_size(bts); + /* N. B: si2q_num() should NEVER be called during actualSI2q rest octets generation + we're not re-entrant because of the following code: */ + bts->u_offset = 0; + bts->e_offset = 0; - /* 2 bits are used in between UARFCN and EARFCN structs */ - est = 1 + (e_sz + u_sz) / (SI2Q_MAX_LEN - (SI2Q_MIN_LEN + 2)); + if (rc < 0) + return 0xFF; /* return impossible index as an indicator of error in generating SI2quater */ - return est; + return num; } /* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */ @@ -176,6 +199,44 @@ static inline uint16_t encode_fdd(uint16_t scramble, bool diversity) return scramble; } +int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio, + uint8_t qrx, uint8_t meas_bw) +{ + struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list; + int r = osmo_earfcn_add(e, earfcn, (meas_bw < EARFCN_MEAS_BW_INVALID) ? meas_bw : OSMO_EARFCN_MEAS_INVALID); + + if (r < 0) + return r; + + if (e->thresh_hi && thresh_hi != e->thresh_hi) + r = 1; + + e->thresh_hi = thresh_hi; + + if (thresh_lo != EARFCN_THRESH_LOW_INVALID) { + if (e->thresh_lo_valid && e->thresh_lo != thresh_lo) + r = EARFCN_THRESH_LOW_INVALID; + e->thresh_lo = thresh_lo; + e->thresh_lo_valid = true; + } + + if (qrx != EARFCN_QRXLV_INVALID) { + if (e->qrxlm_valid && e->qrxlm != qrx) + r = EARFCN_QRXLV_INVALID + 1; + e->qrxlm = qrx; + e->qrxlm_valid = true; + } + + if (prio != EARFCN_PRIO_INVALID) { + if (e->prio_valid && e->prio != prio) + r = EARFCN_PRIO_INVALID; + e->prio = prio; + e->prio_valid = true; + } + + return r; +} + int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble) { uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true), @@ -237,8 +298,10 @@ int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble, bool scl[k] = scr; bts->si_common.uarfcn_length++; - if (si2q_num(bts) < 2) /* FIXME: use SI2Q_MAX_NUM */ + if (si2q_num(bts) <= SI2Q_MAX_NUM) { + bts->si2q_count = si2q_num(bts) - 1; return 0; + } bts_uarfcn_del(bts, arfcn, scramble); return -ENOSPC; @@ -689,39 +752,26 @@ static inline bool si2quater_not_needed(struct gsm_bts *bts) return false; } -size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e) -{ - unsigned i, ret = 0; - - if (!e) - return 0; - - for (i = 0; i < e->length; i++) - if (e->arfcn[i] != OSMO_EARFCN_INVALID) - ret++; - - return ret; -} - static int generate_si2quater(enum osmo_sysinfo_type t, struct gsm_bts *bts) { int rc; - struct gsm48_system_information_type_2quater *si2q = GSM_BTS_SI2Q(bts); + struct gsm48_system_information_type_2quater *si2q; if (si2quater_not_needed(bts)) /* generate rest_octets for SI2q only when necessary */ return GSM_MACBLOCK_LEN; - memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); - - si2q->header.l2_plen = GSM48_LEN2PLEN(22); - si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR; - si2q->header.skip_indicator = 0; - si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater; + bts->u_offset = 0; + bts->e_offset = 0; + bts->si2q_index = 0; + bts->si2q_count = si2q_num(bts) - 1; - rc = rest_octets_si2quater(si2q->rest_octets, bts); + rc = make_si2quaters(bts, false); if (rc < 0) return rc; + OSMO_ASSERT(bts->si2q_count == bts->si2q_index); + OSMO_ASSERT(bts->si2q_count <= SI2Q_MAX_NUM); + return sizeof(*si2q) + rc; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 5a78505d6..5a8c6ca52 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -89,25 +89,19 @@ static inline void gen(struct gsm_bts *bts, const char *s) { int r; - bts->u_offset = 0; - bts->e_offset = 0; - bts->si2q_index = 0; - bts->si2q_count = 0; bts->si_valid = 0; bts->si_valid |= (1 << SYSINFO_TYPE_2quater); - /* should be no-op as entire buffer is filled with padding: */ - memset(GSM_BTS_SI(bts, SYSINFO_TYPE_2quater), 0xAE, GSM_MACBLOCK_LEN); - printf("generating SI2quater for %zu EARFCNs and %zu UARFCNs...\n", si2q_earfcn_count(&bts->si_common.si2quater_neigh_list), bts->si_common.uarfcn_length); r = gsm_generate_si(bts, SYSINFO_TYPE_2quater); if (r > 0) - printf("generated %s SI2quater [%02u/%02u]: [%d] %s\n", - GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) ? "valid" : "invalid", - bts->si2q_index, bts->si2q_count, r, - osmo_hexdump((void *)GSM_BTS_SI2Q(bts), GSM_MACBLOCK_LEN)); + for (bts->si2q_index = 0; bts->si2q_index < bts->si2q_count + 1; bts->si2q_index++) + printf("generated %s SI2quater [%02u/%02u]: [%d] %s\n", + GSM_BTS_HAS_SI(bts, SYSINFO_TYPE_2quater) ? "valid" : "invalid", + bts->si2q_index, bts->si2q_count, r, + osmo_hexdump((void *)GSM_BTS_SI2Q(bts, bts->si2q_index), GSM_MACBLOCK_LEN)); else printf("%s() failed to generate SI2quater: %s\n", s, strerror(-r)); } @@ -145,8 +139,10 @@ static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t r = bts_uarfcn_add(bts, arfcn, scramble, diversity); if (r < 0) printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r)); - else + else { + bts->si2q_count = si2q_num(bts) - 1; gen(bts, __func__); + } } static inline void test_si2q_segfault(void) @@ -181,7 +177,6 @@ static inline void test_si2q_mu(void) _bts_uarfcn_add(bts, 10613, 64, 0); _bts_uarfcn_add(bts, 10613, 164, 0); _bts_uarfcn_add(bts, 10613, 14, 0); - gen(bts, __func__); } static inline void test_si2q_u(void) @@ -192,10 +187,12 @@ static inline void test_si2q_u(void) if (!network) exit(1); + bts = gsm_bts_alloc(network); /* first generate invalid SI as no UARFCN added */ gen(bts, __func__); + /* subsequent calls should produce valid SI if there's enough memory */ _bts_uarfcn_add(bts, 1982, 13, 1); _bts_uarfcn_add(bts, 1982, 44, 0); @@ -208,7 +205,6 @@ static inline void test_si2q_u(void) _bts_uarfcn_add(bts, 1982, 223, 1); _bts_uarfcn_add(bts, 1982, 14, 0); _bts_uarfcn_add(bts, 1982, 88, 0); - gen(bts, __func__); } static inline void test_si2q_e(void) @@ -219,6 +215,7 @@ static inline void test_si2q_e(void) if (!network) exit(1); + bts = gsm_bts_alloc(network); bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list; @@ -227,8 +224,10 @@ static inline void test_si2q_e(void) bts->si_common.si2quater_neigh_list.thresh_hi = 5; osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); + /* first generate invalid SI as no EARFCN added */ gen(bts, __func__); + /* subsequent calls should produce valid SI if there's enough memory and EARFCNs */ add_earfcn_b(bts, 1917, 5); del_earfcn_b(bts, 1917); @@ -241,6 +240,54 @@ static inline void test_si2q_e(void) add_earfcn_b(bts, 1982, 3); } +static inline void test_si2q_long(void) +{ + struct gsm_bts *bts; + struct gsm_network *network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL); + printf("Testing SYSINFO_TYPE_2quater combined EARFCN & UARFCN generation:\n"); + + if (!network) + exit(1); + + bts = gsm_bts_alloc(network); + + bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list; + bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list; + bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST; + bts->si_common.si2quater_neigh_list.thresh_hi = 5; + + osmo_earfcn_init(&bts->si_common.si2quater_neigh_list); + + bts_earfcn_add(bts, 1922, 11, 22, 8,32, 8); + bts_earfcn_add(bts, 1922, 11, 22, 8, 32, 8); + bts_earfcn_add(bts, 1924, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 1923, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 1925, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 2111, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 2112, 11, 12, 6, 11, 4); + bts_earfcn_add(bts, 2113, 11, 12, 6, 11, 3); + bts_earfcn_add(bts, 2114, 11, 12, 6, 11, 2); + bts_earfcn_add(bts, 2131, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 2132, 11, 12, 6, 11, 4); + bts_earfcn_add(bts, 2133, 11, 12, 6, 11, 3); + bts_earfcn_add(bts, 2134, 11, 12, 6, 11, 2); + bts_earfcn_add(bts, 2121, 11, 12, 6, 11, 5); + bts_earfcn_add(bts, 2122, 11, 12, 6, 11, 4); + bts_earfcn_add(bts, 2123, 11, 12, 6, 11, 3); + bts_earfcn_add(bts, 2124, 11, 12, 6, 11, 2); + _bts_uarfcn_add(bts, 1976, 13, 1); + _bts_uarfcn_add(bts, 1976, 38, 1); + _bts_uarfcn_add(bts, 1976, 44, 1); + _bts_uarfcn_add(bts, 1976, 120, 1); + _bts_uarfcn_add(bts, 1976, 140, 1); + _bts_uarfcn_add(bts, 1976, 163, 1); + _bts_uarfcn_add(bts, 1976, 166, 1); + _bts_uarfcn_add(bts, 1976, 217, 1); + _bts_uarfcn_add(bts, 1976, 224, 1); + _bts_uarfcn_add(bts, 1976, 225, 1); + _bts_uarfcn_add(bts, 1976, 226, 1); +} + static void test_mi_functionality(void) { const char *imsi_odd = "987654321098763"; @@ -642,6 +689,9 @@ int main(int argc, char **argv) test_si2q_e(); test_si2q_u(); test_si2q_mu(); + test_si2q_long(); + printf("Done.\n"); + return EXIT_SUCCESS; } diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 5e0b9d50e..d30f42155 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -71,11 +71,11 @@ generating SI2quater for 0 EARFCNs and 2 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 0a 7f 52 88 0a 7e 0b 2b 2b 2b 2b 2b 2b 2b 2b Testing SYSINFO_TYPE_2quater EARFCN generation: generating SI2quater for 0 EARFCNs and 0 UARFCNs... -generated invalid SI2quater [00/00]: [23] ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae +generated invalid SI2quater [00/00]: [23] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 added EARFCN 1917 - generating SI2quater for 1 EARFCNs and 0 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be e8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b removed EARFCN 1917 - generating SI2quater for 0 EARFCNs and 0 UARFCNs... -generated invalid SI2quater [00/00]: [23] ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae +generated invalid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be e8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1917 - generating SI2quater for 1 EARFCNs and 0 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1932 - generating SI2quater for 2 EARFCNs and 0 UARFCNs... @@ -87,12 +87,14 @@ generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 0 added EARFCN 1965 - generating SI2quater for 5 EARFCNs and 0 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b added EARFCN 1967 - generating SI2quater for 6 EARFCNs and 0 UARFCNs... -add_earfcn_b() failed to generate SI2quater: Cannot allocate memory +generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b +generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 04 86 59 83 d7 e0 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b added EARFCN 1982 - generating SI2quater for 7 EARFCNs and 0 UARFCNs... -add_earfcn_b() failed to generate SI2quater: Cannot allocate memory +generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b +generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 04 86 59 83 d7 e4 1e fa c2 80 2b 2b 2b 2b 2b 2b 2b 2b Testing SYSINFO_TYPE_2quater UARFCN generation: generating SI2quater for 0 EARFCNs and 0 UARFCNs... -generated invalid SI2quater [00/00]: [23] ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae ae +generated invalid SI2quater [00/00]: [23] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 generating SI2quater for 0 EARFCNs and 1 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b generating SI2quater for 0 EARFCNs and 2 UARFCNs... @@ -111,10 +113,10 @@ generating SI2quater for 0 EARFCNs and 8 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 0b 2b 2b 2b 2b 2b generating SI2quater for 0 EARFCNs and 9 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 0b 2b 2b 2b 2b -failed to add UARFCN to SI2quater: No space left on device -failed to add UARFCN to SI2quater: No space left on device -generating SI2quater for 0 EARFCNs and 9 UARFCNs... -generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 0b 2b 2b 2b 2b +generating SI2quater for 0 EARFCNs and 10 UARFCNs... +generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 50 1c 3b 31 fa dd 88 85 7b c4 1c 2b 2b 2b 2b +generating SI2quater for 0 EARFCNs and 11 UARFCNs... +generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 0f 7c 58 1c 3b 25 7a ea 08 91 fb c4 1f b0 2b 2b 2b Test SI2quater multiple UARFCNs: generating SI2quater for 0 EARFCNs and 1 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 88 0a 7c 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b @@ -124,9 +126,79 @@ generating SI2quater for 0 EARFCNs and 3 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 12 7e e0 a9 44 05 3e 0b 2b 2b 2b 2b 2b 2b 2b generating SI2quater for 0 EARFCNs and 4 UARFCNs... generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 18 3f f4 90 54 a2 02 9f 03 2b 2b 2b 2b 2b 2b -failed to add UARFCN to SI2quater: No space left on device -failed to add UARFCN to SI2quater: No space left on device -failed to add UARFCN to SI2quater: No space left on device -generating SI2quater for 0 EARFCNs and 4 UARFCNs... -generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 e8 18 3f f4 90 54 a2 02 9f 03 2b 2b 2b 2b 2b 2b +generating SI2quater for 0 EARFCNs and 5 UARFCNs... +generated valid SI2quater [00/00]: [23] 59 06 07 c0 00 25 52 ea 08 81 52 e8 18 3f f4 90 54 a2 02 9f 03 2b 2b +generating SI2quater for 0 EARFCNs and 6 UARFCNs... +generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 25 52 ea 08 81 52 e8 10 3f f4 a9 75 04 a4 0b 2b 2b 2b +generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 25 52 e8 28 81 df 7f fa 32 d4 a2 02 9f 03 2b 2b 2b 2b +generating SI2quater for 0 EARFCNs and 7 UARFCNs... +generated valid SI2quater [00/01]: [23] 59 06 07 c0 20 25 52 ea 10 81 ce a9 74 08 1f fa 54 ba 82 52 03 2b 2b +generated valid SI2quater [01/01]: [23] 59 06 07 c2 20 25 52 e8 30 81 d3 7f fd b2 86 54 a2 02 9f 03 2b 2b 2b +Testing SYSINFO_TYPE_2quater combined EARFCN & UARFCN generation: +generating SI2quater for 17 EARFCNs and 1 UARFCNs... +generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 0c 1a 10 99 66 0f 04 83 c1 1c bb 2b 03 2b 2b +generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b +generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b +generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b +generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 2 UARFCNs... +generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 14 4d e7 00 44 b3 07 82 41 e0 8e 5d 95 83 2b +generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b +generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b +generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b +generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 3 UARFCNs... +generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 1c 4d e7 03 04 86 59 83 c1 20 f0 47 2e ca c1 +generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c2 6c 1e 0f 60 f0 bb 08 3f d7 2e ca c1 2b +generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 20 64 21 06 e1 08 55 08 53 d7 2e ca c1 2b +generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 2a 64 21 56 e1 0a d5 08 49 d7 2e ca c1 2b +generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 25 64 21 2e e1 09 94 e5 d9 58 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 4 UARFCNs... +generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 24 59 fa 26 73 84 86 59 83 c1 1c bb 2b 03 2b +generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c1 20 f0 9b 07 83 d8 3c 2e b9 76 56 0b 2b +generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 1f ec 21 03 21 08 37 08 42 a7 2e ca c1 2b +generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 29 ec 21 53 21 0a b7 08 56 a7 2e ca c1 2b +generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 24 ec 21 2b 21 09 77 08 4c a7 2e ca c1 2b +generating SI2quater for 17 EARFCNs and 5 UARFCNs... +generated valid SI2quater [00/04]: [23] 59 06 07 c0 80 25 0f 70 2c 59 fa 30 73 f6 04 86 59 83 c1 1c bb 2b 03 +generated valid SI2quater [01/04]: [23] 59 06 07 c2 80 04 86 59 83 c1 20 f0 9b 07 83 d8 3c 2e b9 76 56 0b 2b +generated valid SI2quater [02/04]: [23] 59 06 07 c4 80 04 86 59 84 1f ec 21 03 21 08 37 08 42 a7 2e ca c1 2b +generated valid SI2quater [03/04]: [23] 59 06 07 c6 80 04 86 59 84 29 ec 21 53 21 0a b7 08 56 a7 2e ca c1 2b +generated valid SI2quater [04/04]: [23] 59 06 07 c8 80 04 86 59 84 24 ec 21 2b 21 09 77 08 4c a7 2e ca c1 2b +generating SI2quater for 17 EARFCNs and 6 UARFCNs... +generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 34 f1 ae 15 f3 f4 83 04 86 59 72 ec ac 0b 2b +generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b +generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b +generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b +generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 7 UARFCNs... +generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 3c f1 ae 15 f3 f4 83 01 84 86 59 72 ec ac 0b +generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b +generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b +generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b +generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 8 UARFCNs... +generated valid SI2quater [00/02]: [23] 59 06 07 c0 40 25 0f 70 45 19 a0 0d 7d 7e a6 19 e7 00 44 b3 07 82 41 +generated valid SI2quater [01/02]: [23] 59 06 07 c2 40 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [02/02]: [23] 59 06 07 c4 40 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 9 UARFCNs... +generated valid SI2quater [00/02]: [23] 59 06 07 c0 40 25 0f 70 4d 19 a0 26 fd 66 a6 03 e7 fa 10 99 66 0f 04 +generated valid SI2quater [01/02]: [23] 59 06 07 c2 40 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [02/02]: [23] 59 06 07 c4 40 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 10 UARFCNs... +generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 55 47 89 1e fd 7c b0 00 e7 9b b0 04 12 c8 2b +generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b +generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b +generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b +generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b +generating SI2quater for 17 EARFCNs and 11 UARFCNs... +generated valid SI2quater [00/05]: [23] 59 06 07 c0 a0 25 0f 70 5d 47 89 1e fd 7c b0 01 67 9b b3 f8 2b 2b 2b +generated valid SI2quater [01/05]: [23] 59 06 07 c2 a0 04 86 59 83 c1 20 f0 48 3c 26 c1 e0 f5 cb b2 b0 2b 2b +generated valid SI2quater [02/05]: [23] 59 06 07 c4 a0 04 86 59 83 c2 ec 20 ff 61 08 19 08 41 b7 2e ca c1 2b +generated valid SI2quater [03/05]: [23] 59 06 07 c6 a0 04 86 59 84 21 54 21 4f 61 0a 99 08 55 b7 2e ca c1 2b +generated valid SI2quater [04/05]: [23] 59 06 07 c8 a0 04 86 59 84 2b 54 21 27 61 09 59 08 4b b7 2e ca c1 2b +generated valid SI2quater [05/05]: [23] 59 06 07 ca a0 04 86 59 84 26 53 97 65 60 2b 2b 2b 2b 2b 2b 2b 2b 2b Done. -- cgit v1.2.3