Max has submitted this change and it was merged.

Change subject: Update SI data structures and generation
......................................................................


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
---
M openbsc/include/openbsc/gsm_data.h
M openbsc/include/openbsc/gsm_data_shared.h
M openbsc/include/openbsc/system_information.h
M openbsc/src/libbsc/bsc_init.c
M openbsc/src/libbsc/bsc_vty.c
M openbsc/src/libbsc/rest_octets.c
M openbsc/src/libbsc/system_information.c
M openbsc/tests/gsm0408/gsm0408_test.c
M openbsc/tests/gsm0408/gsm0408_test.ok
9 files changed, 353 insertions(+), 164 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/openbsc/include/openbsc/gsm_data.h 
b/openbsc/include/openbsc/gsm_data.h
index 05d834e..5ab7c3f 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -29,6 +29,13 @@
 
 #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 a507606..d3fd757 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 @@
                /* 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_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 @@
        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 21016b8..71bea26 100644
--- a/openbsc/include/openbsc/system_information.h
+++ b/openbsc/include/openbsc/system_information.h
@@ -14,6 +14,8 @@
 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 25f3fdc..b95c7b0 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -101,7 +101,7 @@
 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 @@
                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 b05d3d9..2fc39ab 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -2774,6 +2774,7 @@
        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 @@
        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;
+       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 (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;
-       }
-
-       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 @@
 
        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 a6fdf46..fdab70a 100644
--- a/openbsc/src/libbsc/rest_octets.c
+++ b/openbsc/src/libbsc/rest_octets.c
@@ -65,6 +65,12 @@
        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 @@
                        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_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 @@
        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 @@
        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 @@
        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 @@
        }
 
        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 @@
 
                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 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 @@
        /* 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 a074a78..dcabbbd 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -122,50 +122,73 @@
        }
 }
 
-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;
 
-       /* account for all the constant bits in append_earfcn() */
-       return 25 + osmo_earfcn_bit_size_ext(e, bts->e_offset);
+       if (!e)
+               return 0;
+
+       for (i = 0; i < e->length; i++)
+               if (e->arfcn[i] != OSMO_EARFCN_INVALID)
+                       ret++;
+
+       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;
+       int rc;
+       bool memory_exceeded = true;
+       struct gsm48_system_information_type_2quater *si2q;
 
-       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 */
+       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;
+       int rc = make_si2quaters(bts, true);
+       uint8_t num = bts->si2q_index + 1; /* number of SI2quater messages */
 
-       if (&bts->si_common.si2quater_neigh_list) /* EARFCN */
-               e_sz = earfcn_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;
 
-       if (bts->si_common.uarfcn_length) /* UARFCN */
-               u_sz = uarfcn_size(bts);
+       if (rc < 0)
+               return 0xFF; /* return impossible index as an indicator of 
error in generating SI2quater */
 
-       /* 2 bits are used in between UARFCN and EARFCN structs */
-       est = 1 + (e_sz + u_sz) / (SI2Q_MAX_LEN - (SI2Q_MIN_LEN + 2));
-
-       return est;
+       return num;
 }
 
 /* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */
@@ -174,6 +197,44 @@
        if (diversity)
                return scramble | (1 << 9);
        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)
@@ -237,8 +298,10 @@
        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 @@
        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);
+       bts->u_offset = 0;
+       bts->e_offset = 0;
+       bts->si2q_index = 0;
+       bts->si2q_count = si2q_num(bts) - 1;
 
-       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);
+       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 5a78505..5a8c6ca 100644
--- a/openbsc/tests/gsm0408/gsm0408_test.c
+++ b/openbsc/tests/gsm0408/gsm0408_test.c
@@ -89,25 +89,19 @@
 {
        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 @@
        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 @@
        _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 @@
 
        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 @@
        _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 @@
 
        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 @@
        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);
@@ -239,6 +238,54 @@
        add_earfcn_b(bts, 1965, OSMO_EARFCN_MEAS_INVALID);
        add_earfcn_b(bts, 1967, 4);
        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)
@@ -642,6 +689,9 @@
        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 5e0b9d5..d30f421 100644
--- a/openbsc/tests/gsm0408/gsm0408_test.ok
+++ b/openbsc/tests/gsm0408/gsm0408_test.ok
@@ -71,11 +71,11 @@
 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 @@
 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 @@
 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 @@
 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.

-- 
To view, visit https://gerrit.osmocom.org/2832
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic516ec9f0b821557d9461ae9f1c0afdd786f3b05
Gerrit-PatchSet: 6
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Max <msur...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msur...@sysmocom.de>

Reply via email to