diff options
author | Max <msuraev@sysmocom.de> | 2017-06-15 15:10:53 +0200 |
---|---|---|
committer | Max <msuraev@sysmocom.de> | 2017-06-15 16:39:55 +0200 |
commit | 70fdd24d04a37217724ec8f12873e292b10e5e4d (patch) | |
tree | 33b3ccae88db6dc2f2550a13e98777f78be0cef5 /openbsc/src/libbsc/rest_octets.c | |
parent | 9b97b007dfe96b8a74932ab101d5e341b5796f75 (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
Diffstat (limited to 'openbsc/src/libbsc/rest_octets.c')
-rw-r--r-- | openbsc/src/libbsc/rest_octets.c | 80 |
1 files changed, 50 insertions, 30 deletions
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; |