aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2017-06-15 15:10:53 +0200
committerMax <msuraev@sysmocom.de>2017-06-15 16:39:55 +0200
commit70fdd24d04a37217724ec8f12873e292b10e5e4d (patch)
tree33b3ccae88db6dc2f2550a13e98777f78be0cef5
parent9b97b007dfe96b8a74932ab101d5e341b5796f75 (diff)
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
-rw-r--r--openbsc/include/openbsc/gsm_data.h7
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h16
-rw-r--r--openbsc/include/openbsc/system_information.h2
-rw-r--r--openbsc/src/libbsc/bsc_init.c6
-rw-r--r--openbsc/src/libbsc/bsc_vty.c78
-rw-r--r--openbsc/src/libbsc/rest_octets.c80
-rw-r--r--openbsc/src/libbsc/system_information.c152
-rw-r--r--openbsc/tests/gsm0408/gsm0408_test.c78
-rw-r--r--openbsc/tests/gsm0408/gsm0408_test.ok100
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 <openbsc/common_cs.h>
-/* 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.