summaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc/rest_octets.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-05-08 23:25:31 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2016-05-09 00:26:01 +0200
commit6950d14c5bf301fbb3061f5a4fe67f5f57b76040 (patch)
tree1ae01412e3f15a6a7358ea5ad2a63cd6862a45f8 /openbsc/src/libbsc/rest_octets.c
parentcf2ca648e9f8b9ed753b4ffb588305b0a3430208 (diff)
parentcd5e52605cdb77bdc6f36fce81a6a1bac7fbda48 (diff)
Merge branch 'master' into sysmocom/iu, with tweakssysmocom/iu_orig_history
Numerous manual adjustments are included to make sense on the sysmocom/iu branch: * gsm_04_08_gprs.h has moved to libosmocore on the master branch, but sysmocom/iu has added some entries. Until it is clear whether to move the additions to libosmocore as well, keep gsm_04_08_gprs.h on sysmocom/iu with merely the additions. * Thus, keep using the old gsm_04_08_gprs.[hc] from openbsc in the Makefiles, but only where the sysmocom/iu additions are needed. * In openbsc's gsm_04_08_gprs.h, * include the libosmocore gsm_04_08_gprs.h, * use '#pragma once' instead of #ifndef and * add a TODO comment about moving the rest to libosmocore. * Apply the addition of an osmo_auth_vector to gsm_auth_tuple: in the Iu auth vector hacks, use the gsm_auth_tuple.vec instead of a local struct. See iu_hack__get_hardcoded_auth_tuple() and gsm48_rx_gmm_att_req(). * In the si2q tests, pass NULL as ctx to gsm_network_init(). * In cscn_main.c, add a debug log that was originally added to osmo-nitb. * openbsc/.gitignore: keep only one addition of 'writtenconfig' Conflicts: openbsc/include/openbsc/gprs_sgsn.h openbsc/include/openbsc/gsm_04_08_gprs.h openbsc/src/gprs/gsm_04_08_gprs.c openbsc/src/libmsc/gsm_04_08.c openbsc/src/osmo-cscn/cscn_main.c openbsc/tests/gsm0408/Makefile.am
Diffstat (limited to 'openbsc/src/libbsc/rest_octets.c')
-rw-r--r--openbsc/src/libbsc/rest_octets.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c
index 4545794a9..aa286e578 100644
--- a/openbsc/src/libbsc/rest_octets.c
+++ b/openbsc/src/libbsc/rest_octets.c
@@ -24,10 +24,15 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <stdbool.h>
+#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <osmocom/core/bitvec.h>
+#include <osmocom/gsm/bitvec_gsm.h>
#include <openbsc/rest_octets.h>
+#include <openbsc/arfcn_range_encode.h>
+#include <openbsc/system_information.h>
/* generate SI1 rest octets */
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
@@ -53,6 +58,255 @@ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
return bv.data_len;
}
+/* Append Repeated E-UTRAN Neighbour Cell to bitvec:
+ * see 3GPP TS 44.018 Table 10.5.2.33b.1
+ */
+static inline void append_eutran_neib_cell(struct bitvec *bv,
+ const struct osmo_earfcn_si2q *e)
+{
+ unsigned i;
+ for (i = 0; i < e->length; i++) {
+ if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
+ bitvec_set_bit(bv, 1); /* EARFCN: */
+ bitvec_set_uint(bv, e->arfcn[i], 16);
+
+ if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
+ bitvec_set_bit(bv, 0);
+ else {
+ /* Measurement Bandwidth: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->meas_bw[i], 3);
+ }
+ }
+ }
+
+ /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
+ bitvec_set_bit(bv, 0);
+
+ if (e->prio_valid) {
+ /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->prio, 3);
+ } else
+ bitvec_set_bit(bv, 0);
+
+ /* THRESH_E-UTRAN_high */
+ bitvec_set_uint(bv, e->thresh_hi, 5);
+
+ if (e->thresh_lo_valid) {
+ /* THRESH_E-UTRAN_low: */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->thresh_lo, 5);
+ } else
+ bitvec_set_bit(bv, 0);
+
+ if (e->qrxlm_valid) {
+ /* E-UTRAN_QRXLEVMIN: */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->qrxlm, 5);
+ } else
+ bitvec_set_bit(bv, 0);
+}
+
+static inline void append_earfcn(struct bitvec *bv,
+ const struct osmo_earfcn_si2q *e)
+{
+ /* Additions in Rel-5: */
+ bitvec_set_bit(bv, H);
+ /* No 3G Additional Measurement Param. Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-6: */
+ bitvec_set_bit(bv, H);
+ /* 3G_CCN_ACTIVE */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-7: */
+ bitvec_set_bit(bv, H);
+ /* No 700_REPORTING_OFFSET */
+ bitvec_set_bit(bv, 0);
+ /* No 810_REPORTING_OFFSET */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-8: */
+ bitvec_set_bit(bv, H);
+
+ /* Priority and E-UTRAN Parameters Description */
+ bitvec_set_bit(bv, 1);
+
+ /* No Serving Cell Priority Parameters Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No 3G Priority Parameters Description */
+ bitvec_set_bit(bv, 0);
+ /* E-UTRAN Parameters Description */
+ bitvec_set_bit(bv, 1);
+
+ /* E-UTRAN_CCN_ACTIVE */
+ bitvec_set_bit(bv, 0);
+ /* E-UTRAN_Start: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+ /* E-UTRAN_Stop: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+
+ /* No E-UTRAN Measurement Parameters Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No GPRS E-UTRAN Measurement Param. Descr. */
+ bitvec_set_bit(bv, 0);
+
+ /* Note: each of next 3 "repeated" structures might be repeated any
+ (0, 1, 2...) times - we only support 1 and 0 */
+
+ /* Repeated E-UTRAN Neighbour Cells */
+ bitvec_set_bit(bv, 1);
+
+ /* Note: we don't support different EARFCN arrays each with different
+ priority, threshold etc. */
+ append_eutran_neib_cell(bv, e);
+
+ /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
+ bitvec_set_bit(bv, 0);
+
+ /* Note: following 2 repeated structs are not supported ATM */
+ /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
+ bitvec_set_bit(bv, 0);
+ /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
+ bitvec_set_bit(bv, 0);
+
+ /* Priority and E-UTRAN Parameters Description ends here */
+ /* No 3G CSG Description */
+ bitvec_set_bit(bv, 0);
+ /* No E-UTRAN CSG Description */
+ bitvec_set_bit(bv, 0);
+ /* No Additions in Rel-9: */
+ bitvec_set_bit(bv, L);
+}
+
+static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u,
+ const uint16_t *sc, size_t length)
+{
+ int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length];
+ uint8_t chan_list[16] = {0};
+
+ /* 3G Neighbour Cell Description */
+ bitvec_set_bit(bv, 1);
+ /* No Index_Start_3G */
+ bitvec_set_bit(bv, 0);
+ /* No Absolute_Index_Start_EMR */
+ bitvec_set_bit(bv, 0);
+
+ /* UTRAN FDD Description */
+ bitvec_set_bit(bv, 1);
+ /* No Bandwidth_FDD */
+ bitvec_set_bit(bv, 0);
+
+ memset(w, 0, sizeof(w));
+ for (i = 0; i < length; i++)
+ a[i] = sc[i];
+
+ /* Note: we do not support repeating Neighbour Cells ATM */
+ /* Repeated UTRAN FDD Neighbour Cells */
+ bitvec_set_bit(bv, 1);
+
+ /* FDD-ARFCN */
+ bitvec_set_bit(bv, 0);
+ /* Note: we do not support multiple UARFCN values ATM: */
+ bitvec_set_uint(bv, u[0], 14);
+
+ arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc);
+ range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0);
+ range_enc_range1024(chan_list, 0, f0_inc, w);
+
+ /* FDD_Indic0: parameter value '0000000000' is not a member of the set */
+ bitvec_set_bit(bv, f0_inc);
+ /* NR_OF_FDD_CELLS */
+ bitvec_set_uint(bv, length, 5);
+
+ i = bv->cur_bit;
+ bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
+ bv->cur_bit = i + range1024_p(length);
+
+ /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
+ bitvec_set_bit(bv, 0);
+
+ /* UTRAN TDD Description */
+ bitvec_set_bit(bv, 0);
+}
+
+/* generate SI2quater rest octets: 3GPP TS 44.018 ยง 10.5.2.33b */
+int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
+ const uint16_t *u, const uint16_t *sc, size_t u_len)
+{
+ unsigned sz;
+ struct bitvec bv;
+ bv.data = data;
+ bv.data_len = 20;
+ bitvec_zero(&bv);
+
+ /* BA_IND */
+ bitvec_set_bit(&bv, 1);
+ /* 3G_BA_IND */
+ bitvec_set_bit(&bv, 1);
+ /* MP_CHANGE_MARK */
+ bitvec_set_bit(&bv, 0);
+
+ /* we do not support multiple si2quater messages at the moment: */
+ /* SI2quater_INDEX */
+ bitvec_set_uint(&bv, 0, 4);
+ /* SI2quater_COUNT */
+ bitvec_set_uint(&bv, 0, 4);
+
+ /* No Measurement_Parameters Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_Real Time Difference Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_BSIC Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_REPORT PRIORITY Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_MEASUREMENT_Parameters Description */
+ bitvec_set_bit(&bv, 0);
+ /* No NC Measurement Parameters */
+ bitvec_set_bit(&bv, 0);
+ /* No extension (length) */
+ bitvec_set_bit(&bv, 0);
+
+ if (u_len) {
+ sz = uarfcn_size(u, sc, u_len);
+ /* Even if we do not append EARFCN we still need to set 3 bits */
+ if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) {
+ LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to "
+ "add UARFCNs bits, current %u + required %u + "
+ "reminder %u > max %u\n", bv.cur_bit, sz, 3,
+ SI2Q_MAX_LEN);
+ return -ENOMEM;
+ }
+ append_uarfcn(&bv, u, sc, u_len);
+ } 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 (e) {
+ sz = earfcn_size(e);
+ if (sz + bv.cur_bit > SI2Q_MAX_LEN) {
+ LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to "
+ "add EARFCNs bits, current %u + required %u > max "
+ "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN);
+ return -ENOMEM;
+ }
+ append_earfcn(&bv, e);
+ } else {
+ /* No Additions in Rel-5: */
+ bitvec_set_bit(&bv, L);
+ }
+
+ bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
+ return bv.data_len;
+}
+
/* Append selection parameters to bitvec */
static void append_selection_params(struct bitvec *bv,
const struct gsm48_si_selection_params *sp)
@@ -129,6 +383,15 @@ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
/* GPRS Indicator */
append_gprs_ind(&bv, &si3->gprs_ind);
+ /* 3G Early Classmark Sending Restriction controlled by
+ * early_cm_ctrl above */
+ bitvec_set_bit(&bv, H);
+
+ if (si3->si2quater_indicator) {
+ bitvec_set_bit(&bv, H); /* indicator struct present */
+ bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
+ }
+
bitvec_spare_padding(&bv, (bv.data_len*8)-1);
return bv.data_len;
}