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
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);