From: Holger Hans Peter Freyther zecke@selfish.org
The iPhone5 (US) appears to have some issues with the SIs generated, or the nanoBTS is not sending them correctly. Add a hack to put all bands into the SI2/SI5 message.
This is a quick change without much reflection and watching for side effects. I have verfied that a network with ARFCN 134 and neighbors ARFCN 130 and 512 do not get generate the SI2ter and announce everything inside the SI2. --- openbsc/src/libbsc/system_information.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index c901a4a..cb67011 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -44,6 +44,7 @@ * array. DCS1800 and PCS1900 can not be used at the same time so conserve * memory and do the below. */ +#if 0 static int band_compatible(const struct gsm_bts *bts, int arfcn) { enum gsm_band band = gsm_arfcn2band(arfcn); @@ -57,6 +58,7 @@ static int band_compatible(const struct gsm_bts *bts, int arfcn)
return 0; } +#endif
static int is_dcs_net(const struct gsm_bts *bts) { @@ -70,6 +72,11 @@ static int is_dcs_net(const struct gsm_bts *bts) static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, const int pgsm, const int arfcn) { + if (bis || ter) + return 0; + return 1; +#if 0 + Correct but somehow broken with either the nanoBTS or the iPhone5 if (!bis && !ter && band_compatible(bts, arfcn)) return 1; if (bis && pgsm && band_compatible(bts, arfcn) && (arfcn < 1 || arfcn > 124)) @@ -77,6 +84,7 @@ static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, if (ter && !band_compatible(bts, arfcn)) return 1; return 0; +#endif }
/* Frequency Lists as per TS 04.08 10.5.2.13 */
Currently the generation of SI2ter/SI2bis/SI5ter/SI5bis is always disabled (see former patch 'si: Add a hack to disable SI2ter/SI2bis/SI5ter/SI5bis messages').
This patch turns the hack into a configuration option, enabled by the bts VTY command 'force-combined-si'.
Ticket: OW#1062 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gsm_data_shared.h | 3 +++ openbsc/src/libbsc/bsc_vty.c | 27 +++++++++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 11 +++-------- openbsc/tests/vty_test_runner.py | 18 ++++++++++++++++++ 4 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index b49a539..0922f78 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -670,6 +670,9 @@ struct gsm_bts { int num_trx; struct llist_head trx_list;
+ /* SI compatibility hacks */ + int force_combined_si; + #ifdef ROLE_BSC /* Abis NM queue */ struct llist_head abis_queue; diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 7fa5ea7..4d09e15 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -636,6 +636,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) if (bts->excl_from_rf_lock) vty_out(vty, " rf-lock-exclude%s", VTY_NEWLINE);
+ vty_out(vty, " %sforce-combined-si%s", + bts->force_combined_si ? "" : "no ", VTY_NEWLINE); + config_write_bts_model(vty, bts); }
@@ -2658,6 +2661,28 @@ DEFUN(cfg_bts_no_excl_rf_lock, return CMD_SUCCESS; }
+#define FORCE_COMB_SI_STR "Force the generation of a single SI (no ter/bis)\n" + +DEFUN(cfg_bts_force_comb_si, + cfg_bts_force_comb_si_cmd, + "force-combined-si", + FORCE_COMB_SI_STR) +{ + struct gsm_bts *bts = vty->index; + bts->force_combined_si = 1; + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_no_force_comb_si, + cfg_bts_no_force_comb_si_cmd, + "no force-combined-si", + NO_STR FORCE_COMB_SI_STR) +{ + struct gsm_bts *bts = vty->index; + bts->force_combined_si = 0; + return CMD_SUCCESS; +} + #define TRX_TEXT "Radio Transceiver\n"
/* per TRX configuration */ @@ -3255,6 +3280,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); + install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); + install_element(BTS_NODE, &cfg_bts_no_force_comb_si_cmd);
install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index cb67011..5f46bf9 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -44,7 +44,6 @@ * array. DCS1800 and PCS1900 can not be used at the same time so conserve * memory and do the below. */ -#if 0 static int band_compatible(const struct gsm_bts *bts, int arfcn) { enum gsm_band band = gsm_arfcn2band(arfcn); @@ -58,7 +57,6 @@ static int band_compatible(const struct gsm_bts *bts, int arfcn)
return 0; } -#endif
static int is_dcs_net(const struct gsm_bts *bts) { @@ -72,19 +70,16 @@ static int is_dcs_net(const struct gsm_bts *bts) static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, const int pgsm, const int arfcn) { - if (bis || ter) - return 0; - return 1; -#if 0 - Correct but somehow broken with either the nanoBTS or the iPhone5 if (!bis && !ter && band_compatible(bts, arfcn)) return 1; + if (bts->force_combined_si) + return 0; + /* Correct but somehow broken with either the nanoBTS or the iPhone5 */ if (bis && pgsm && band_compatible(bts, arfcn) && (arfcn < 1 || arfcn > 124)) return 1; if (ter && !band_compatible(bts, arfcn)) return 1; return 0; -#endif }
/* Frequency Lists as per TS 04.08 10.5.2.13 */ diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 16eb213..47e1ad1 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -173,6 +173,24 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(res.find('periodic location update 60'), -1) self.assert_(res.find('no periodic location update') > 0)
+ def testEnableDisableSiHacks(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("bts 0") + + # Enable periodic lu.. + self.vty.verify("force-combined-si", ['']) + res = self.vty.command("write terminal") + self.assert_(res.find(' force-combined-si') > 0) + self.assertEquals(res.find('no force-combined-si'), -1) + + # Now disable it.. + self.vty.verify("no force-combined-si", ['']) + res = self.vty.command("write terminal") + self.assertEquals(res.find(' force-combined-si'), -1) + self.assert_(res.find('no force-combined-si') > 0) + def testRachAccessControlClass(self): self.vty.enable() self.vty.command("configure terminal")
On Tue, Jan 14, 2014 at 02:24:16PM +0100, Jacob Erlbeck wrote:
Currently the generation of SI2ter/SI2bis/SI5ter/SI5bis is always disabled (see former patch 'si: Add a hack to disable SI2ter/SI2bis/SI5ter/SI5bis messages').
I would like to squash 1/2. For later bi-section it makes sense to not disable a feature in just one commit.
On 14.01.2014 17:31, Holger Hans Peter Freyther wrote:
On Tue, Jan 14, 2014 at 02:24:16PM +0100, Jacob Erlbeck wrote:
Currently the generation of SI2ter/SI2bis/SI5ter/SI5bis is always disabled (see former patch 'si: Add a hack to disable SI2ter/SI2bis/SI5ter/SI5bis messages').
I would like to squash 1/2. For later bi-section it makes sense to not disable a feature in just one commit.
Ok, I'll squash it.
The current code only implements the bit packing for the range 512 encoding format.
This patch prefers the (implemenented) range512 above the (not yet implemented) other encodings. This means that range512 is used whenever possible, not only when it is optimal. Thus the encoding will only fail, when it not *possible* to use range512.
The patch has a similar effect like commit 10eb96e6b1e and replaces it.
Ticket: OW#1061 Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 6 ++++-- openbsc/tests/si/si_test.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index c52743e..d12c907 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -160,12 +160,14 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) max = arfcns[size - 1] - arfcns[0]; *f0 = arfcns[0];
+ if (max < 512 && size <= 18) + return ARFCN_RANGE_512; + + /* The following are nyi, so they are checked last */ if (max < 128 && size <= 29) return ARFCN_RANGE_128; if (max < 256 && size <= 22) return ARFCN_RANGE_256; - if (max < 512 && size <= 18) - return ARFCN_RANGE_512; if (max < 1024 && size <= 17) return ARFCN_RANGE_1024;
diff --git a/openbsc/tests/si/si_test.c b/openbsc/tests/si/si_test.c index fd840f3..695ae6d 100644 --- a/openbsc/tests/si/si_test.c +++ b/openbsc/tests/si/si_test.c @@ -137,11 +137,11 @@ int main(int argc, char **argv) }
i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); - VERIFY(i, ==, ARFCN_RANGE_128); + VERIFY(i, ==, ARFCN_RANGE_512); VERIFY(f0, ==, 1);
i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); - VERIFY(i, ==, ARFCN_RANGE_256); + VERIFY(i, ==, ARFCN_RANGE_512); VERIFY(f0, ==, 1);
i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0);
This commit adds test range encoding tests. They check the property decoding(encoding(L)) = L and optionally dump the results and encoded sequences to stdout.
There a 2 test modes:
- A list of fixed tests - A random number based test loop per ARFCN list size (only dumps the first failing test)
Sponsored-by: On-Waves ehf --- openbsc/tests/gsm0408/Makefile.am | 1 + openbsc/tests/gsm0408/gsm0408_test.c | 216 +++++++++++++++++++++++++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 48 ++++++++ 3 files changed, 265 insertions(+)
diff --git a/openbsc/tests/gsm0408/Makefile.am b/openbsc/tests/gsm0408/Makefile.am index b000c08..1c29ece 100644 --- a/openbsc/tests/gsm0408/Makefile.am +++ b/openbsc/tests/gsm0408/Makefile.am @@ -8,4 +8,5 @@ gsm0408_test_SOURCES = gsm0408_test.c gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 60a151f..721b283 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -27,6 +27,8 @@ #include <openbsc/gsm_04_08.h> #include <openbsc/gsm_subscriber.h> #include <openbsc/debug.h> +#include <openbsc/arfcn_range_encode.h> +#include <osmocom/core/application.h>
#define COMPARE(result, op, value) \ if (!((result) op (value))) {\ @@ -94,10 +96,224 @@ static void test_mi_functionality(void) COMPARE_STR(mi_parsed, imsi_even); }
+struct { + int range; + int arfcns_num; + int arfcns[RANGE_ENC_MAX_ARFCNS]; +} arfcn_test_ranges[] = { + {ARFCN_RANGE_512, 12, + { 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }}, + {ARFCN_RANGE_512, 17, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }}, + {ARFCN_RANGE_512, 18, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }}, + {ARFCN_RANGE_512, 18, + { 1, 17, 31, 45, 58, 79, 81, 97, + 113, 127, 213, 277, 287, 311, 331, 391, + 417, 511 }}, + {ARFCN_RANGE_512, 6, + { 1, 17, 31, 45, 58, 79 }}, + {ARFCN_RANGE_512, 6, + { 10, 17, 31, 45, 58, 79 }}, + {ARFCN_RANGE_1024, 17, + { 0, 17, 31, 45, 58, 79, 81, 97, + 113, 127, 213, 277, 287, 311, 331, 391, + 1023 }}, + {ARFCN_RANGE_1024, 16, + { 17, 31, 45, 58, 79, 81, 97, 113, + 127, 213, 277, 287, 311, 331, 391, 1023 }}, + {-1} +}; + +static int test_single_range_encoding(int range, const int *orig_arfcns, + int arfcns_num, int silent) +{ + int arfcns[RANGE_ENC_MAX_ARFCNS]; + int w[RANGE_ENC_MAX_ARFCNS]; + int f0_included = 0; + int rc, f0; + uint8_t chan_list[16] = {0}; + struct gsm_sysinfo_freq dec_freq[1024] = {{0}}; + int dec_arfcns[RANGE_ENC_MAX_ARFCNS] = {0}; + int dec_arfcns_count = 0; + int arfcns_used = 0; + int i; + + arfcns_used = arfcns_num; + memmove(arfcns, orig_arfcns, sizeof(arfcns)); + + f0 = arfcns[0]; + /* + * Manipulate the ARFCN list according to the rules in J4 depending + * on the selected range. + */ + arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + f0, &f0_included); + + memset(w, 0, sizeof(w)); + rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); + if (rc != 0) { + printf("Cannot compute range W(k), rc = %d\n", rc); + return 1; + } + + if (!silent) + fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", + range, arfcns_used, f0, f0_included); + + /* Select the range and the amount of bits needed */ + switch (range) { + case ARFCN_RANGE_128: + rc = range_enc_range128(chan_list, f0, w); + break; + case ARFCN_RANGE_256: + rc = range_enc_range256(chan_list, f0, w); + break; + case ARFCN_RANGE_512: + rc = range_enc_range512(chan_list, f0, w); + break; + case ARFCN_RANGE_1024: + rc = range_enc_range1024(chan_list, f0, f0_included, w); + break; + default: + return 1; + }; + if (rc != 0) { + printf("Cannot encode range, rc = %d\n", rc); + return 1; + } + + if (!silent) + printf("chan_list = %s\n", + osmo_hexdump(chan_list, sizeof(chan_list))); + + rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list), + 0xfe, 1); + if (rc != 0) { + printf("Cannot decode freq list, rc = %d\n", rc); + return 1; + } + + for (i = 0; i < ARRAY_SIZE(dec_freq); i++) { + if (dec_freq[i].mask && + dec_arfcns_count < ARRAY_SIZE(dec_arfcns)) + dec_arfcns[dec_arfcns_count++] = i; + } + + if (!silent) { + printf("Decoded freqs %d (expected %d)\n", + dec_arfcns_count, arfcns_num); + printf("Decoded: "); + for (i = 0; i < dec_arfcns_count; i++) { + printf("%d ", dec_arfcns[i]); + if (dec_arfcns[i] != orig_arfcns[i]) + printf("(!= %d) ", orig_arfcns[i]); + } + printf("\n"); + } + + if (dec_arfcns_count != arfcns_num) { + printf("Wrong number of arfcns\n"); + return 1; + } + + if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) { + printf("Decoding error, got wrong freqs\n"); + fprintf(stderr, " w = "); + for (i = 0; i < ARRAY_SIZE(w); i++) + fprintf(stderr, "%d ", w[i]); + fprintf(stderr, "\n"); + return 1; + } + + return 0; +} + +static void test_random_range_encoding(int range, int max_arfcn_num) +{ + int arfcns_num = 0; + int test_idx; + int rc, max_count; + int num_tests = 1024; + + printf("Random range test: range %d, max num ARFCNs %d\n", + range, max_arfcn_num); + + srandom(1); + + for (max_count = 1; max_count < max_arfcn_num; max_count++) { + for (test_idx = 0; test_idx < num_tests; test_idx++) { + int count; + int i; + int min_freq = 0; + + int rnd_arfcns[RANGE_ENC_MAX_ARFCNS] = {0}; + char rnd_arfcns_set[1024] = {0}; + + if (range < ARFCN_RANGE_1024) + min_freq = random() % (1023 - range); + + for (count = max_count; count; ) { + int arfcn = min_freq + random() % (range + 1); + OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set)); + + if (!rnd_arfcns_set[arfcn]) { + rnd_arfcns_set[arfcn] = 1; + count -= 1; + } + } + + arfcns_num = 0; + for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++) + if (rnd_arfcns_set[i]) + rnd_arfcns[arfcns_num++] = i; + + rc = test_single_range_encoding(range, rnd_arfcns, + arfcns_num, 1); + if (rc != 0) { + printf("Failed on test %d, range %d, num ARFCNs %d\n", + test_idx, range, max_count); + test_single_range_encoding(range, rnd_arfcns, + arfcns_num, 0); + return; + } + } + } +} + +static void test_range_encoding() +{ + int *arfcns; + int arfcns_num = 0; + int test_idx; + int range; + + for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++) + { + arfcns_num = arfcn_test_ranges[test_idx].arfcns_num; + arfcns = &arfcn_test_ranges[test_idx].arfcns[0]; + range = arfcn_test_ranges[test_idx].range; + + printf("Range test %d: range %d, num ARFCNs %d\n", + test_idx, range, arfcns_num); + + test_single_range_encoding(range, arfcns, arfcns_num, 0); + } + + test_random_range_encoding(ARFCN_RANGE_128, 29); + test_random_range_encoding(ARFCN_RANGE_256, 22); + test_random_range_encoding(ARFCN_RANGE_512, 18); + test_random_range_encoding(ARFCN_RANGE_1024, 16); +} + int main(int argc, char **argv) { + osmo_init_logging(&log_info); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + test_location_area_identifier(); test_mi_functionality(); + test_range_encoding();
printf("Done.\n"); return EXIT_SUCCESS; diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 52c601e..a92b879 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -2,4 +2,52 @@ Testing test location area identifier Testing parsing and generating TMSI/IMSI hex: 17 08 99 78 56 34 12 90 78 36 hex: 17 09 91 78 56 34 12 90 78 56 f4 +Range test 0: range 511, num ARFCNs 12 +chan_list = 88 00 98 34 85 36 7c 50 22 dc 5e ec 00 00 00 00 +Decoded freqs 12 (expected 12) +Decoded: 1 12 31 51 57 91 97 98 113 117 120 125 +Range test 1: range 511, num ARFCNs 17 +chan_list = 88 00 82 7f 01 3f 7e 04 0b ff ff fc 10 41 07 e0 +Decoded freqs 17 (expected 17) +Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +Range test 2: range 511, num ARFCNs 18 +chan_list = 88 00 82 7f 01 7f 7e 04 0b ff ff fc 10 41 07 ff +Decoded freqs 18 (expected 18) +Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +Range test 3: range 511, num ARFCNs 18 +chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 76 +Decoded freqs 18 (expected 18) +Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 507 (!= 511) +Decoding error, got wrong freqs +Range test 4: range 511, num ARFCNs 6 +chan_list = 88 00 8b 3c 88 b9 6b 00 00 00 00 00 00 00 00 00 +Decoded freqs 6 (expected 6) +Decoded: 1 17 31 45 58 79 +Range test 5: range 511, num ARFCNs 6 +chan_list = 88 05 08 fc 88 b9 6b 00 00 00 00 00 00 00 00 00 +Decoded freqs 6 (expected 6) +Decoded: 10 17 31 45 58 79 +Range test 6: range 1023, num ARFCNs 17 +Cannot encode range, rc = -1 +Range test 7: range 1023, num ARFCNs 16 +Cannot encode range, rc = -1 +Random range test: range 127, max num ARFCNs 29 +Cannot encode range, rc = -1 +Failed on test 0, range 127, num ARFCNs 1 +Cannot encode range, rc = -1 +Random range test: range 255, max num ARFCNs 22 +Cannot encode range, rc = -1 +Failed on test 0, range 255, num ARFCNs 1 +Cannot encode range, rc = -1 +Random range test: range 511, max num ARFCNs 18 +Decoding error, got wrong freqs +Failed on test 0, range 511, num ARFCNs 17 +chan_list = 88 21 55 fc da d7 76 03 31 2f ed 45 dc 93 d6 80 +Decoded freqs 17 (expected 17) +Decoded: 66 81 161 250 314 343 383 (!= 380) 395 396 397 409 429 505 506 516 518 545 +Decoding error, got wrong freqs +Random range test: range 1023, max num ARFCNs 16 +Cannot encode range, rc = -1 +Failed on test 0, range 1023, num ARFCNs 1 +Cannot encode range, rc = -1 Done.
Currently tests covering features of the GSM 04.08 specification are spread over the si and gsm0408 subdirs in tests.
This commit merges all tests from 'si' into 'gsm0408' and removes the 'si' test sub-directory.
Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 1 - openbsc/tests/Makefile.am | 2 +- openbsc/tests/gsm0408/gsm0408_test.c | 146 ++++++++++++++++++++++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 20 +++++ openbsc/tests/si/Makefile.am | 12 --- openbsc/tests/si/si_test.c | 156 --------------------------------- openbsc/tests/si/si_test.ok | 20 ----- openbsc/tests/testsuite.at | 6 -- 8 files changed, 167 insertions(+), 196 deletions(-) delete mode 100644 openbsc/tests/si/Makefile.am delete mode 100644 openbsc/tests/si/si_test.c delete mode 100644 openbsc/tests/si/si_test.ok
diff --git a/openbsc/configure.ac b/openbsc/configure.ac index fe99569..5d29af7 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -166,7 +166,6 @@ AC_OUTPUT( tests/mgcp/Makefile tests/gprs/Makefile tests/gbproxy/Makefile - tests/si/Makefile tests/abis/Makefile tests/smpp/Makefile tests/trau/Makefile diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index d4bb954..31b2bb4 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs si abis gbproxy trau +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau
if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 721b283..246e201 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -42,6 +42,16 @@ exit(-1); \ }
+#define DBG(...) + +#define VERIFY(res, cmp, wanted) \ + if (!(res cmp wanted)) { \ + printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \ + __FILE__, __LINE__, res, # cmp, wanted); \ + } + + + /* * Test Location Area Identifier formatting. Table 10.5.3 of 04.08 */ @@ -306,6 +316,138 @@ static void test_range_encoding() test_random_range_encoding(ARFCN_RANGE_1024, 16); }
+static int freqs1[] = { + 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980 +}; + +static int freqs2[] = { + 402, 460, 1, 67, 131, 197, 272, 347, +}; + +static int freqs3[] = { + 68, 128, 198, 279, 353, 398, 452, + +}; + +static int w_out[] = { + 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9, +}; + +static int range128[] = { + 1, 1 + 127, +}; + +static int range256[] = { + 1, 1 + 128, +}; + +static int range512[] = { + 1, 1+ 511, +}; + + +static void test_arfcn_filter() +{ + int arfcns[50], i, res, f0_included; + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + + /* check that the arfcn is taken out. f0_included is only set for Range1024 */ + f0_included = 24; + res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), + arfcns[0], &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); + VERIFY(f0_included, ==, 0); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1)); + + /* check with range1024 */ + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), + arfcns[0], &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); + VERIFY(f0_included, ==, 1); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); + + /* check with range1024, not included */ + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), + 11, &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns)); + VERIFY(f0_included, ==, 0); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1); +} + +static void test_print_encoding() +{ + int rc; + int w[17]; + uint8_t chan_list[16]; + memset(chan_list, 0x23, sizeof(chan_list)); + + for (rc = 0; rc < ARRAY_SIZE(w); ++rc) + switch (rc % 3) { + case 0: + w[rc] = 0xAAAA; + break; + case 1: + w[rc] = 0x5555; + break; + case 2: + w[rc] = 0x9696; + break; + } + + rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); + VERIFY(rc, ==, 0); + + printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); +} + +static void test_si_range_helpers() +{ + int ws[(sizeof(freqs1)/sizeof(freqs1[0]))]; + int i, f0 = 0xFFFFFF; + + memset(&ws[0], 0x23, sizeof(ws)); + + i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs1[i]); + VERIFY(i, ==, 2); + + i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs2[i]); + VERIFY(i, ==, 2); + + i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs3[i]); + VERIFY(i, ==, 0); + + i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); + VERIFY(i, ==, 0); + + for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { + printf("w[%d]=%d\n", i, ws[i]); + VERIFY(ws[i], ==, w_out[i]); + } + + i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); + VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(f0, ==, 1); + + i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); + VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(f0, ==, 1); + + i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0); + VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(f0, ==, 1); +} + int main(int argc, char **argv) { osmo_init_logging(&log_info); @@ -313,6 +455,10 @@ int main(int argc, char **argv)
test_location_area_identifier(); test_mi_functionality(); + + test_si_range_helpers(); + test_arfcn_filter(); + test_print_encoding(); test_range_encoding();
printf("Done.\n"); diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index a92b879..5458669 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -2,6 +2,26 @@ Testing test location area identifier Testing parsing and generating TMSI/IMSI hex: 17 08 99 78 56 34 12 90 78 36 hex: 17 09 91 78 56 34 12 90 78 56 f4 +Element is: 2 => freqs[i] = 121 +Element is: 2 => freqs[i] = 1 +Element is: 0 => freqs[i] = 68 +w[0]=122 +w[1]=2 +w[2]=69 +w[3]=204 +w[4]=75 +w[5]=66 +w[6]=60 +w[7]=70 +w[8]=83 +w[9]=3 +w[10]=24 +w[11]=67 +w[12]=54 +w[13]=64 +w[14]=70 +w[15]=9 +Range512: 89 4b 2a 95 65 95 55 2c a9 55 aa 55 6a 95 59 55 Range test 0: range 511, num ARFCNs 12 chan_list = 88 00 98 34 85 36 7c 50 22 dc 5e ec 00 00 00 00 Decoded freqs 12 (expected 12) diff --git a/openbsc/tests/si/Makefile.am b/openbsc/tests/si/Makefile.am deleted file mode 100644 index 795bd30..0000000 --- a/openbsc/tests/si/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS) - -EXTRA_DIST = si_test.ok - -noinst_PROGRAMS = si_test - -si_test_SOURCES = si_test.c - -si_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOCORE_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) diff --git a/openbsc/tests/si/si_test.c b/openbsc/tests/si/si_test.c deleted file mode 100644 index 695ae6d..0000000 --- a/openbsc/tests/si/si_test.c +++ /dev/null @@ -1,156 +0,0 @@ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <openbsc/arfcn_range_encode.h> - -#include <osmocom/core/utils.h> - -#define DBG(...) - -#define VERIFY(res, cmp, wanted) \ - if (!(res cmp wanted)) { \ - printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \ - __FILE__, __LINE__, res, # cmp, wanted); \ - } - - -static int freqs1[] = { - 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980 -}; - -static int freqs2[] = { - 402, 460, 1, 67, 131, 197, 272, 347, -}; - -static int freqs3[] = { - 68, 128, 198, 279, 353, 398, 452, - -}; - -static int w_out[] = { - 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9, -}; - -static int range128[] = { - 1, 1 + 127, -}; - -static int range256[] = { - 1, 1 + 128, -}; - -static int range512[] = { - 1, 1+ 511, -}; - - -static void test_arfcn_filter() -{ - int arfcns[50], i, res, f0_included; - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - - /* check that the arfcn is taken out. f0_included is only set for Range1024 */ - f0_included = 24; - res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 0); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1)); - - /* check with range1024 */ - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 1); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); - - /* check with range1024, not included */ - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - 11, &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns)); - VERIFY(f0_included, ==, 0); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1); -} - -static void test_print_encoding() -{ - int rc; - int w[17]; - uint8_t chan_list[16]; - memset(chan_list, 0x23, sizeof(chan_list)); - - for (rc = 0; rc < ARRAY_SIZE(w); ++rc) - switch (rc % 3) { - case 0: - w[rc] = 0xAAAA; - break; - case 1: - w[rc] = 0x5555; - break; - case 2: - w[rc] = 0x9696; - break; - } - - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); - - printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); -} - -int main(int argc, char **argv) -{ - int ws[(sizeof(freqs1)/sizeof(freqs1[0]))]; - int i, f0 = 0xFFFFFF; - - memset(&ws[0], 0x23, sizeof(ws)); - - i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs1[i]); - VERIFY(i, ==, 2); - - i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs2[i]); - VERIFY(i, ==, 2); - - i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs3[i]); - VERIFY(i, ==, 0); - - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); - - for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { - printf("w[%d]=%d\n", i, ws[i]); - VERIFY(ws[i], ==, w_out[i]); - } - - i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); - VERIFY(f0, ==, 1); - - i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); - VERIFY(f0, ==, 1); - - i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); - VERIFY(f0, ==, 1); - - - test_arfcn_filter(); - test_print_encoding(); - - return 0; -} diff --git a/openbsc/tests/si/si_test.ok b/openbsc/tests/si/si_test.ok deleted file mode 100644 index 6a3ee51..0000000 --- a/openbsc/tests/si/si_test.ok +++ /dev/null @@ -1,20 +0,0 @@ -Element is: 2 => freqs[i] = 121 -Element is: 2 => freqs[i] = 1 -Element is: 0 => freqs[i] = 68 -w[0]=122 -w[1]=2 -w[2]=69 -w[3]=204 -w[4]=75 -w[5]=66 -w[6]=60 -w[7]=70 -w[8]=83 -w[9]=3 -w[10]=24 -w[11]=67 -w[12]=54 -w[13]=64 -w[14]=70 -w[15]=9 -Range512: 89 4b 2a 95 65 95 55 2c a9 55 aa 55 6a 95 59 55 diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 652cfe9..b2c5518 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -57,12 +57,6 @@ cat $abs_srcdir/bsc-nat-trie/bsc_nat_trie_test.ok > expout AT_CHECK([$abs_top_builddir/tests/bsc-nat-trie/bsc_nat_trie_test], [], [expout], [ignore]) AT_CLEANUP
-AT_SETUP([si]) -AT_KEYWORDS([si]) -cat $abs_srcdir/si/si_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/si/si_test], [], [expout], [ignore]) -AT_CLEANUP - AT_SETUP([abis]) AT_KEYWORDS([abis]) cat $abs_srcdir/abis/abis_test.ok > expout
This patch fixes a bug in the range encoder that leads to wrong encoding when 17 or more ARFCNs are encoded.
Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 2 +- openbsc/tests/gsm0408/gsm0408_test.ok | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index d12c907..edd886f 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -258,7 +258,7 @@ int range_enc_range512(uint8_t *chan_list, int f0, int *w) range512->w15 = HIGH_BITS(w, 15, 6, 6); /* W(16) */ range512->w16_hi = HIGH_BITS(w, 16, 5, 2); - range512->w16_lo = HIGH_BITS(w, 16, 5, 3); + range512->w16_lo = LOW_BITS(w, 16, 5, 3); /* W(17) */ range512->w17 = HIGH_BITS(w, 17, 5, 5);
diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 5458669..dab495d 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -35,10 +35,9 @@ chan_list = 88 00 82 7f 01 7f 7e 04 0b ff ff fc 10 41 07 ff Decoded freqs 18 (expected 18) Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Range test 3: range 511, num ARFCNs 18 -chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 76 +chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 f6 Decoded freqs 18 (expected 18) -Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 507 (!= 511) -Decoding error, got wrong freqs +Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 511 Range test 4: range 511, num ARFCNs 6 chan_list = 88 00 8b 3c 88 b9 6b 00 00 00 00 00 00 00 00 00 Decoded freqs 6 (expected 6) @@ -60,12 +59,6 @@ Cannot encode range, rc = -1 Failed on test 0, range 255, num ARFCNs 1 Cannot encode range, rc = -1 Random range test: range 511, max num ARFCNs 18 -Decoding error, got wrong freqs -Failed on test 0, range 511, num ARFCNs 17 -chan_list = 88 21 55 fc da d7 76 03 31 2f ed 45 dc 93 d6 80 -Decoded freqs 17 (expected 17) -Decoded: 66 81 161 250 314 343 383 (!= 380) 395 396 397 409 429 505 506 516 518 545 -Decoding error, got wrong freqs Random range test: range 1023, max num ARFCNs 16 Cannot encode range, rc = -1 Failed on test 0, range 1023, num ARFCNs 1
f0 is currently set to arfcns[0] in range_enc_determine_range(), while GSM 04.08 requires f0 to be ARFCN 0 in range1024 encoding.
This patch modifies range_enc_determine_range() to force f0 to be 0 if this encoding is used. This way the case distinction in range_enc_filter_arfcns() is not longer necessary.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/arfcn_range_encode.h | 2 +- openbsc/src/libbsc/arfcn_range_encode.c | 44 +++++++++++--------------- openbsc/src/libbsc/system_information.c | 2 +- openbsc/tests/gsm0408/gsm0408_test.c | 24 +++++++------- 4 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/openbsc/include/openbsc/arfcn_range_encode.h b/openbsc/include/openbsc/arfcn_range_encode.h index 7a6fff0..bd85d6a 100644 --- a/openbsc/include/openbsc/arfcn_range_encode.h +++ b/openbsc/include/openbsc/arfcn_range_encode.h @@ -16,7 +16,7 @@ enum { int range_enc_determine_range(const int *arfcns, int size, int *f0_out); int range_enc_arfcns(const int rng, const int *arfcns, int sze, int *out, int idx); int range_enc_find_index(const int rng, const int *arfcns, int size); -int range_enc_filter_arfcns(const int rng, int *arfcns, const int sze, const int f0, int *f0_included); +int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included);
int range_enc_range128(uint8_t *chan_list, int f0, int *w); int range_enc_range256(uint8_t *chan_list, int f0, int *w); diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index edd886f..17c347f 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -144,7 +144,9 @@ int range_enc_arfcns(const int range, */ /** * This implements the range determination as described in GSM 04.08 J4. The - * result will be a base frequency f0 and the range to use. + * result will be a base frequency f0 and the range to use. Note that for range + * 1024 encoding f0 always refers to ARFCN 0 even if it is not an element of + * the arfcns list. * * \param[in] arfcns The input frequencies, they must be sorted, lowest number first * \param[in] size The length of the array @@ -168,8 +170,10 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) return ARFCN_RANGE_128; if (max < 256 && size <= 22) return ARFCN_RANGE_256; - if (max < 1024 && size <= 17) + if (max < 1024 && size <= 17) { + *f0 = 0; return ARFCN_RANGE_1024; + }
return ARFCN_RANGE_INVALID; } @@ -273,34 +277,24 @@ int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) return -1; }
-int range_enc_filter_arfcns(const int range, int *arfcns, - const int size, const int f0, int *f0_included) +int range_enc_filter_arfcns(int *arfcns, + const int size, const int f0, int *f0_included) { int i, j = 0; *f0_included = 0;
- if (range == ARFCN_RANGE_1024) { - for (i = 0; i < size; ++i) { - if (arfcns[i] == f0) { - *f0_included = 1; - continue; - } - - /* copy and subtract */ - arfcns[j++] = mod(arfcns[i] - 1, 1024); - } - } else { - for (i = 0; i < size; ++i) { - /* - * Appendix J.4 says the following: - * All frequencies except F(0), minus F(0) + 1. - * I assume we need to exclude it here. - */ - if (arfcns[i] == f0) - continue; - - arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024); + for (i = 0; i < size; ++i) { + /* + * Appendix J.4 says the following: + * All frequencies except F(0), minus F(0) + 1. + * I assume we need to exclude it here. + */ + if (arfcns[i] == f0) { + *f0_included = 1; + continue; } + + arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024); }
return j; diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 5f46bf9..95ac736 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -197,7 +197,7 @@ static int enc_freq_lst_range(uint8_t *chan_list, * Manipulate the ARFCN list according to the rules in J4 depending * on the selected range. */ - arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
memset(w, 0, sizeof(w)); diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 246e201..3218379 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -152,12 +152,12 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, arfcns_used = arfcns_num; memmove(arfcns, orig_arfcns, sizeof(arfcns));
- f0 = arfcns[0]; + f0 = range == ARFCN_RANGE_1024 ? 0 : arfcns[0]; /* * Manipulate the ARFCN list according to the rules in J4 depending * on the selected range. */ - arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
memset(w, 0, sizeof(w)); @@ -354,28 +354,28 @@ static void test_arfcn_filter()
/* check that the arfcn is taken out. f0_included is only set for Range1024 */ f0_included = 24; - res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), arfcns[0], &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 0); + VERIFY(f0_included, ==, 1); for (i = 0; i < res; ++i) VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
- /* check with range1024 */ + /* check with range1024, ARFCN 0 is included */ for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); + arfcns[i] = i * 2; + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), + 0, &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); VERIFY(f0_included, ==, 1); for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); + VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
- /* check with range1024, not included */ + /* check with range1024, ARFCN 0 not included */ for (i = 0; i < ARRAY_SIZE(arfcns); ++i) arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - 11, &f0_included); + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), + 0, &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns)); VERIFY(f0_included, ==, 0); for (i = 0; i < res; ++i)
Currently the encoding of the chan_list is done by a hard-coded sequence of macros that closely resembles figure 10.5.16 in 3GPP TS 04.08.
This patch replaces this by an algorithmic solution that can be used for all range encodings and is based on the property
W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present
(see section 10.5.2.13 in TS 04.08).
Ticket: OW#1061 Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 141 ++++++++++++++++++------------- 1 file changed, 83 insertions(+), 58 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index 17c347f..3e5b1fc 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -178,16 +178,6 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) return ARFCN_RANGE_INVALID; }
-/* - * The below is easier is to write in four methods than - * to use the max_bits. The encoding is so screwed.. as - * the bits need to be put in place in the wrong order.. - */ -#define HIGH_BITS(w, index, bits, offset) \ - (w[index - 1] >> (bits - offset)) -#define LOW_BITS(w, index, bits, offset) \ - (w[index - 1]) - static void write_orig_arfcn(uint8_t *chan_list, int f0) { chan_list[0] |= (f0 >> 9) & 1; @@ -195,6 +185,88 @@ static void write_orig_arfcn(uint8_t *chan_list, int f0) chan_list[2] = (f0 & 1) << 7; }
+static void write_all_wn(uint8_t *chan_list, int bit_offs, + int *w, int w_size, int w1_len) +{ + int octet_offs = 0; /* offset into chan_list */ + int wk_len = w1_len; /* encoding size in bits of w[k] */ + int k; /* 1 based */ + int level = 0; /* tree level, top level = 0 */ + int lvl_left = 1; /* nodes per tree level */ + + /* W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present */ + + for (k = 1; k <= w_size; k++) { + int wk_left = wk_len; + DEBUGP(DRR, + "k=%d, wk_len=%d, offs=%d:%d, level=%d, " + "lvl_left=%d\n", + k, wk_len, octet_offs, bit_offs, level, lvl_left); + + while (wk_left > 0) { + int cur_bits = 8 - bit_offs; + int cur_mask; + int wk_slice; + + if (cur_bits > wk_left) + cur_bits = wk_left; + + cur_mask = ((1 << cur_bits) - 1); + + DEBUGP(DRR, + " wk_left=%d, cur_bits=%d, offs=%d:%d\n", + wk_left, cur_bits, octet_offs, bit_offs); + + /* advance */ + wk_left -= cur_bits; + bit_offs += cur_bits; + + /* right aligned wk data for current out octet */ + wk_slice = (w[k-1] >> wk_left) & cur_mask; + + /* cur_bits now contains the number of bits + * that are to be copied from wk to the chan_list. + * wk_left is set to the number of bits that must + * not yet be copied. + * bit_offs points after the bit area that is going to + * be overwritten: + * + * wk_left + * | + * v + * wk: WWWWWWWWWWW + * |||||<-- wk_slice, cur_bits=5 + * --WWWWW- + * ^ + * | + * bit_offs + */ + + DEBUGP(DRR, + " wk=%02x, slice=%02x/%02x, cl=%02x\n", + w[k-1], wk_slice, cur_mask, wk_slice << (8 - bit_offs)); + + chan_list[octet_offs] &= ~(cur_mask << (8 - bit_offs)); + chan_list[octet_offs] |= wk_slice << (8 - bit_offs); + + /* adjust output */ + if (bit_offs == 8) { + bit_offs = 0; + octet_offs += 1; + } + } + + /* adjust bit sizes */ + lvl_left -= 1; + if (!lvl_left) { + /* completed tree level, advance to next */ + level += 1; + lvl_left = 1 << level; + wk_len -= 1; + } + } +} + int range_enc_range128(uint8_t *chan_list, int f0, int *w) { chan_list[0] = 0x8C; @@ -215,57 +287,10 @@ int range_enc_range256(uint8_t *chan_list, int f0, int *w)
int range_enc_range512(uint8_t *chan_list, int f0, int *w) { - struct gsm48_range_512 *range512; chan_list[0] = 0x88; write_orig_arfcn(chan_list, f0);
- range512 = (struct gsm48_range_512 *) &chan_list[0]; - - /* W(1) */ - range512->w1_hi = HIGH_BITS(w, 1, 9, 7); - range512->w1_lo = LOW_BITS (w, 1, 9, 2); - /* W(2) */ - range512->w2_hi = HIGH_BITS(w, 2, 8, 6); - range512->w2_lo = LOW_BITS (w, 2, 8, 2); - /* W(3) */ - range512->w3_hi = HIGH_BITS(w, 3, 8, 6); - range512->w3_lo = LOW_BITS (w, 3, 8, 2); - /* W(4) */ - range512->w4_hi = HIGH_BITS(w, 4, 7, 6); - range512->w4_lo = LOW_BITS (w, 4, 7, 1); - /* W(5) */ - range512->w5 = HIGH_BITS(w, 5, 7, 7); - /* W(6) */ - range512->w6 = HIGH_BITS(w, 6, 7, 7); - /* W(7) */ - range512->w7_hi = HIGH_BITS(w, 7, 7, 1); - range512->w7_lo = LOW_BITS (w, 7, 7, 6); - /* W(8) */ - range512->w8_hi = HIGH_BITS(w, 8, 6, 2); - range512->w8_lo = LOW_BITS (w, 8, 6, 4); - /* W(9) */ - range512->w9_hi = HIGH_BITS(w, 9, 6, 4); - range512->w9_lo = LOW_BITS(w, 9, 6, 2); - /* W(10) */ - range512->w10 = HIGH_BITS(w, 10, 6, 6); - /* W(11) */ - range512->w11 = HIGH_BITS(w, 11, 6, 6); - /* W(12) */ - range512->w12_hi = HIGH_BITS(w, 12, 6, 2); - range512->w12_lo = LOW_BITS (w, 12, 6, 4); - /* W(13) */ - range512->w13_hi = HIGH_BITS(w, 13, 6, 4); - range512->w13_lo = LOW_BITS(w, 13, 6, 2); - /* W(14) */ - range512->w14 = HIGH_BITS(w, 14, 6, 6); - /* W(15) */ - range512->w15 = HIGH_BITS(w, 15, 6, 6); - /* W(16) */ - range512->w16_hi = HIGH_BITS(w, 16, 5, 2); - range512->w16_lo = LOW_BITS(w, 16, 5, 3); - /* W(17) */ - range512->w17 = HIGH_BITS(w, 17, 5, 5); - + write_all_wn(&chan_list[2], 1, w, 17, 9); return 0; }
This commit adds the implementation of these range formats to the encoder. In addition, the work-around that tried range 512 first is removed, so that the selection is primarily based on the max distance between frequencies.
Ticket: OW#1061 Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 18 ++++++++---------- openbsc/tests/gsm0408/gsm0408_test.c | 4 ++-- openbsc/tests/gsm0408/gsm0408_test.ok | 17 ++++++----------- 3 files changed, 16 insertions(+), 23 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index 3e5b1fc..e67bf0a 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -162,14 +162,12 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) max = arfcns[size - 1] - arfcns[0]; *f0 = arfcns[0];
- if (max < 512 && size <= 18) - return ARFCN_RANGE_512; - - /* The following are nyi, so they are checked last */ if (max < 128 && size <= 29) return ARFCN_RANGE_128; if (max < 256 && size <= 22) return ARFCN_RANGE_256; + if (max < 512 && size <= 18) + return ARFCN_RANGE_512; if (max < 1024 && size <= 17) { *f0 = 0; return ARFCN_RANGE_1024; @@ -272,8 +270,8 @@ int range_enc_range128(uint8_t *chan_list, int f0, int *w) chan_list[0] = 0x8C; write_orig_arfcn(chan_list, f0);
- LOGP(DRR, LOGL_ERROR, "Range128 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[2], 1, w, 28, 7); + return 0; }
int range_enc_range256(uint8_t *chan_list, int f0, int *w) @@ -281,8 +279,8 @@ int range_enc_range256(uint8_t *chan_list, int f0, int *w) chan_list[0] = 0x8A; write_orig_arfcn(chan_list, f0);
- LOGP(DRR, LOGL_ERROR, "Range256 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[2], 1, w, 21, 8); + return 0; }
int range_enc_range512(uint8_t *chan_list, int f0, int *w) @@ -298,8 +296,8 @@ int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) { chan_list[0] = 0x80 | (f0_included << 2);
- LOGP(DRR, LOGL_ERROR, "Range1024 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[0], 6, w, 16, 10); + return 0; }
int range_enc_filter_arfcns(int *arfcns, diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 3218379..894eb0f 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -436,11 +436,11 @@ static void test_si_range_helpers() }
i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(i, ==, ARFCN_RANGE_128); VERIFY(f0, ==, 1);
i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(i, ==, ARFCN_RANGE_256); VERIFY(f0, ==, 1);
i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0); diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index dab495d..3d3c4e6 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -47,20 +47,15 @@ chan_list = 88 05 08 fc 88 b9 6b 00 00 00 00 00 00 00 00 00 Decoded freqs 6 (expected 6) Decoded: 10 17 31 45 58 79 Range test 6: range 1023, num ARFCNs 17 -Cannot encode range, rc = -1 +chan_list = 84 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f +Decoded freqs 17 (expected 17) +Decoded: 0 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 Range test 7: range 1023, num ARFCNs 16 -Cannot encode range, rc = -1 +chan_list = 80 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f +Decoded freqs 16 (expected 16) +Decoded: 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 Random range test: range 127, max num ARFCNs 29 -Cannot encode range, rc = -1 -Failed on test 0, range 127, num ARFCNs 1 -Cannot encode range, rc = -1 Random range test: range 255, max num ARFCNs 22 -Cannot encode range, rc = -1 -Failed on test 0, range 255, num ARFCNs 1 -Cannot encode range, rc = -1 Random range test: range 511, max num ARFCNs 18 Random range test: range 1023, max num ARFCNs 16 -Cannot encode range, rc = -1 -Failed on test 0, range 1023, num ARFCNs 1 -Cannot encode range, rc = -1 Done.
On Tue, Jan 14, 2014 at 02:24:23PM +0100, Jacob Erlbeck wrote:
This commit adds the implementation of these range formats to the encoder. In addition, the work-around that tried range 512 first is removed, so that the selection is primarily based on the max distance between frequencies.
I know you spent a lot of work on separating commits. Somehow I think we can skip the moving of the ARFCN_RANGE_512 code? What do you think?
On 14.01.2014 17:33, Holger Hans Peter Freyther wrote:
I know you spent a lot of work on separating commits. Somehow I think we can skip the moving of the ARFCN_RANGE_512 code? What do you think?
That's ok. I'm going to change that.
Jacob
From: Holger Hans Peter Freyther zecke@selfish.org
The iPhone5 (US) appears to have some issues with the SIs generated, or the nanoBTS is not sending them correctly.
Add a configurable hack to put all bands into the SI2/SI5 message. It is enabled by the bts VTY command 'force-combined-si'.
This is a quick change without much reflection and watching for side effects. I have verfied that a network with ARFCN 134 and neighbors ARFCN 130 and 512 do not get generate the SI2ter and announce everything inside the SI2.
This patch is based on 'si: Add a hack to disable SI2ter/SI2bis/SI5ter/SI5bis messages'.
Ticket: OW#1062 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gsm_data_shared.h | 3 +++ openbsc/src/libbsc/bsc_vty.c | 27 +++++++++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 3 +++ openbsc/tests/vty_test_runner.py | 18 ++++++++++++++++++ 4 files changed, 51 insertions(+)
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index b49a539..0922f78 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -670,6 +670,9 @@ struct gsm_bts { int num_trx; struct llist_head trx_list;
+ /* SI compatibility hacks */ + int force_combined_si; + #ifdef ROLE_BSC /* Abis NM queue */ struct llist_head abis_queue; diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 7fa5ea7..4d09e15 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -636,6 +636,9 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) if (bts->excl_from_rf_lock) vty_out(vty, " rf-lock-exclude%s", VTY_NEWLINE);
+ vty_out(vty, " %sforce-combined-si%s", + bts->force_combined_si ? "" : "no ", VTY_NEWLINE); + config_write_bts_model(vty, bts); }
@@ -2658,6 +2661,28 @@ DEFUN(cfg_bts_no_excl_rf_lock, return CMD_SUCCESS; }
+#define FORCE_COMB_SI_STR "Force the generation of a single SI (no ter/bis)\n" + +DEFUN(cfg_bts_force_comb_si, + cfg_bts_force_comb_si_cmd, + "force-combined-si", + FORCE_COMB_SI_STR) +{ + struct gsm_bts *bts = vty->index; + bts->force_combined_si = 1; + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_no_force_comb_si, + cfg_bts_no_force_comb_si_cmd, + "no force-combined-si", + NO_STR FORCE_COMB_SI_STR) +{ + struct gsm_bts *bts = vty->index; + bts->force_combined_si = 0; + return CMD_SUCCESS; +} + #define TRX_TEXT "Radio Transceiver\n"
/* per TRX configuration */ @@ -3255,6 +3280,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd); install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd); + install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd); + install_element(BTS_NODE, &cfg_bts_no_force_comb_si_cmd);
install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index c901a4a..5f46bf9 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -72,6 +72,9 @@ static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter, { if (!bis && !ter && band_compatible(bts, arfcn)) return 1; + if (bts->force_combined_si) + return 0; + /* Correct but somehow broken with either the nanoBTS or the iPhone5 */ if (bis && pgsm && band_compatible(bts, arfcn) && (arfcn < 1 || arfcn > 124)) return 1; if (ter && !band_compatible(bts, arfcn)) diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py index 16eb213..47e1ad1 100644 --- a/openbsc/tests/vty_test_runner.py +++ b/openbsc/tests/vty_test_runner.py @@ -173,6 +173,24 @@ class TestVTYNITB(TestVTYGenericBSC): self.assertEquals(res.find('periodic location update 60'), -1) self.assert_(res.find('no periodic location update') > 0)
+ def testEnableDisableSiHacks(self): + self.vty.enable() + self.vty.command("configure terminal") + self.vty.command("network") + self.vty.command("bts 0") + + # Enable periodic lu.. + self.vty.verify("force-combined-si", ['']) + res = self.vty.command("write terminal") + self.assert_(res.find(' force-combined-si') > 0) + self.assertEquals(res.find('no force-combined-si'), -1) + + # Now disable it.. + self.vty.verify("no force-combined-si", ['']) + res = self.vty.command("write terminal") + self.assertEquals(res.find(' force-combined-si'), -1) + self.assert_(res.find('no force-combined-si') > 0) + def testRachAccessControlClass(self): self.vty.enable() self.vty.command("configure terminal")
This commit adds test range encoding tests. They check the property decoding(encoding(L)) = L and optionally dump the results and encoded sequences to stdout.
There a 2 test modes:
- A list of fixed tests - A random number based test loop per ARFCN list size (only dumps the first failing test)
Sponsored-by: On-Waves ehf --- openbsc/tests/gsm0408/Makefile.am | 1 + openbsc/tests/gsm0408/gsm0408_test.c | 216 +++++++++++++++++++++++++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 48 ++++++++ 3 files changed, 265 insertions(+)
diff --git a/openbsc/tests/gsm0408/Makefile.am b/openbsc/tests/gsm0408/Makefile.am index b000c08..1c29ece 100644 --- a/openbsc/tests/gsm0408/Makefile.am +++ b/openbsc/tests/gsm0408/Makefile.am @@ -8,4 +8,5 @@ gsm0408_test_SOURCES = gsm0408_test.c gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 60a151f..721b283 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -27,6 +27,8 @@ #include <openbsc/gsm_04_08.h> #include <openbsc/gsm_subscriber.h> #include <openbsc/debug.h> +#include <openbsc/arfcn_range_encode.h> +#include <osmocom/core/application.h>
#define COMPARE(result, op, value) \ if (!((result) op (value))) {\ @@ -94,10 +96,224 @@ static void test_mi_functionality(void) COMPARE_STR(mi_parsed, imsi_even); }
+struct { + int range; + int arfcns_num; + int arfcns[RANGE_ENC_MAX_ARFCNS]; +} arfcn_test_ranges[] = { + {ARFCN_RANGE_512, 12, + { 1, 12, 31, 51, 57, 91, 97, 98, 113, 117, 120, 125 }}, + {ARFCN_RANGE_512, 17, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }}, + {ARFCN_RANGE_512, 18, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }}, + {ARFCN_RANGE_512, 18, + { 1, 17, 31, 45, 58, 79, 81, 97, + 113, 127, 213, 277, 287, 311, 331, 391, + 417, 511 }}, + {ARFCN_RANGE_512, 6, + { 1, 17, 31, 45, 58, 79 }}, + {ARFCN_RANGE_512, 6, + { 10, 17, 31, 45, 58, 79 }}, + {ARFCN_RANGE_1024, 17, + { 0, 17, 31, 45, 58, 79, 81, 97, + 113, 127, 213, 277, 287, 311, 331, 391, + 1023 }}, + {ARFCN_RANGE_1024, 16, + { 17, 31, 45, 58, 79, 81, 97, 113, + 127, 213, 277, 287, 311, 331, 391, 1023 }}, + {-1} +}; + +static int test_single_range_encoding(int range, const int *orig_arfcns, + int arfcns_num, int silent) +{ + int arfcns[RANGE_ENC_MAX_ARFCNS]; + int w[RANGE_ENC_MAX_ARFCNS]; + int f0_included = 0; + int rc, f0; + uint8_t chan_list[16] = {0}; + struct gsm_sysinfo_freq dec_freq[1024] = {{0}}; + int dec_arfcns[RANGE_ENC_MAX_ARFCNS] = {0}; + int dec_arfcns_count = 0; + int arfcns_used = 0; + int i; + + arfcns_used = arfcns_num; + memmove(arfcns, orig_arfcns, sizeof(arfcns)); + + f0 = arfcns[0]; + /* + * Manipulate the ARFCN list according to the rules in J4 depending + * on the selected range. + */ + arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + f0, &f0_included); + + memset(w, 0, sizeof(w)); + rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0); + if (rc != 0) { + printf("Cannot compute range W(k), rc = %d\n", rc); + return 1; + } + + if (!silent) + fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n", + range, arfcns_used, f0, f0_included); + + /* Select the range and the amount of bits needed */ + switch (range) { + case ARFCN_RANGE_128: + rc = range_enc_range128(chan_list, f0, w); + break; + case ARFCN_RANGE_256: + rc = range_enc_range256(chan_list, f0, w); + break; + case ARFCN_RANGE_512: + rc = range_enc_range512(chan_list, f0, w); + break; + case ARFCN_RANGE_1024: + rc = range_enc_range1024(chan_list, f0, f0_included, w); + break; + default: + return 1; + }; + if (rc != 0) { + printf("Cannot encode range, rc = %d\n", rc); + return 1; + } + + if (!silent) + printf("chan_list = %s\n", + osmo_hexdump(chan_list, sizeof(chan_list))); + + rc = gsm48_decode_freq_list(dec_freq, chan_list, sizeof(chan_list), + 0xfe, 1); + if (rc != 0) { + printf("Cannot decode freq list, rc = %d\n", rc); + return 1; + } + + for (i = 0; i < ARRAY_SIZE(dec_freq); i++) { + if (dec_freq[i].mask && + dec_arfcns_count < ARRAY_SIZE(dec_arfcns)) + dec_arfcns[dec_arfcns_count++] = i; + } + + if (!silent) { + printf("Decoded freqs %d (expected %d)\n", + dec_arfcns_count, arfcns_num); + printf("Decoded: "); + for (i = 0; i < dec_arfcns_count; i++) { + printf("%d ", dec_arfcns[i]); + if (dec_arfcns[i] != orig_arfcns[i]) + printf("(!= %d) ", orig_arfcns[i]); + } + printf("\n"); + } + + if (dec_arfcns_count != arfcns_num) { + printf("Wrong number of arfcns\n"); + return 1; + } + + if (memcmp(dec_arfcns, orig_arfcns, sizeof(dec_arfcns)) != 0) { + printf("Decoding error, got wrong freqs\n"); + fprintf(stderr, " w = "); + for (i = 0; i < ARRAY_SIZE(w); i++) + fprintf(stderr, "%d ", w[i]); + fprintf(stderr, "\n"); + return 1; + } + + return 0; +} + +static void test_random_range_encoding(int range, int max_arfcn_num) +{ + int arfcns_num = 0; + int test_idx; + int rc, max_count; + int num_tests = 1024; + + printf("Random range test: range %d, max num ARFCNs %d\n", + range, max_arfcn_num); + + srandom(1); + + for (max_count = 1; max_count < max_arfcn_num; max_count++) { + for (test_idx = 0; test_idx < num_tests; test_idx++) { + int count; + int i; + int min_freq = 0; + + int rnd_arfcns[RANGE_ENC_MAX_ARFCNS] = {0}; + char rnd_arfcns_set[1024] = {0}; + + if (range < ARFCN_RANGE_1024) + min_freq = random() % (1023 - range); + + for (count = max_count; count; ) { + int arfcn = min_freq + random() % (range + 1); + OSMO_ASSERT(arfcn < ARRAY_SIZE(rnd_arfcns_set)); + + if (!rnd_arfcns_set[arfcn]) { + rnd_arfcns_set[arfcn] = 1; + count -= 1; + } + } + + arfcns_num = 0; + for (i = 0; i < ARRAY_SIZE(rnd_arfcns_set); i++) + if (rnd_arfcns_set[i]) + rnd_arfcns[arfcns_num++] = i; + + rc = test_single_range_encoding(range, rnd_arfcns, + arfcns_num, 1); + if (rc != 0) { + printf("Failed on test %d, range %d, num ARFCNs %d\n", + test_idx, range, max_count); + test_single_range_encoding(range, rnd_arfcns, + arfcns_num, 0); + return; + } + } + } +} + +static void test_range_encoding() +{ + int *arfcns; + int arfcns_num = 0; + int test_idx; + int range; + + for (test_idx = 0; arfcn_test_ranges[test_idx].arfcns_num > 0; test_idx++) + { + arfcns_num = arfcn_test_ranges[test_idx].arfcns_num; + arfcns = &arfcn_test_ranges[test_idx].arfcns[0]; + range = arfcn_test_ranges[test_idx].range; + + printf("Range test %d: range %d, num ARFCNs %d\n", + test_idx, range, arfcns_num); + + test_single_range_encoding(range, arfcns, arfcns_num, 0); + } + + test_random_range_encoding(ARFCN_RANGE_128, 29); + test_random_range_encoding(ARFCN_RANGE_256, 22); + test_random_range_encoding(ARFCN_RANGE_512, 18); + test_random_range_encoding(ARFCN_RANGE_1024, 16); +} + int main(int argc, char **argv) { + osmo_init_logging(&log_info); + log_set_log_level(osmo_stderr_target, LOGL_INFO); + test_location_area_identifier(); test_mi_functionality(); + test_range_encoding();
printf("Done.\n"); return EXIT_SUCCESS; diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 52c601e..a92b879 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -2,4 +2,52 @@ Testing test location area identifier Testing parsing and generating TMSI/IMSI hex: 17 08 99 78 56 34 12 90 78 36 hex: 17 09 91 78 56 34 12 90 78 56 f4 +Range test 0: range 511, num ARFCNs 12 +chan_list = 88 00 98 34 85 36 7c 50 22 dc 5e ec 00 00 00 00 +Decoded freqs 12 (expected 12) +Decoded: 1 12 31 51 57 91 97 98 113 117 120 125 +Range test 1: range 511, num ARFCNs 17 +chan_list = 88 00 82 7f 01 3f 7e 04 0b ff ff fc 10 41 07 e0 +Decoded freqs 17 (expected 17) +Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +Range test 2: range 511, num ARFCNs 18 +chan_list = 88 00 82 7f 01 7f 7e 04 0b ff ff fc 10 41 07 ff +Decoded freqs 18 (expected 18) +Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 +Range test 3: range 511, num ARFCNs 18 +chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 76 +Decoded freqs 18 (expected 18) +Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 507 (!= 511) +Decoding error, got wrong freqs +Range test 4: range 511, num ARFCNs 6 +chan_list = 88 00 8b 3c 88 b9 6b 00 00 00 00 00 00 00 00 00 +Decoded freqs 6 (expected 6) +Decoded: 1 17 31 45 58 79 +Range test 5: range 511, num ARFCNs 6 +chan_list = 88 05 08 fc 88 b9 6b 00 00 00 00 00 00 00 00 00 +Decoded freqs 6 (expected 6) +Decoded: 10 17 31 45 58 79 +Range test 6: range 1023, num ARFCNs 17 +Cannot encode range, rc = -1 +Range test 7: range 1023, num ARFCNs 16 +Cannot encode range, rc = -1 +Random range test: range 127, max num ARFCNs 29 +Cannot encode range, rc = -1 +Failed on test 0, range 127, num ARFCNs 1 +Cannot encode range, rc = -1 +Random range test: range 255, max num ARFCNs 22 +Cannot encode range, rc = -1 +Failed on test 0, range 255, num ARFCNs 1 +Cannot encode range, rc = -1 +Random range test: range 511, max num ARFCNs 18 +Decoding error, got wrong freqs +Failed on test 0, range 511, num ARFCNs 17 +chan_list = 88 21 55 fc da d7 76 03 31 2f ed 45 dc 93 d6 80 +Decoded freqs 17 (expected 17) +Decoded: 66 81 161 250 314 343 383 (!= 380) 395 396 397 409 429 505 506 516 518 545 +Decoding error, got wrong freqs +Random range test: range 1023, max num ARFCNs 16 +Cannot encode range, rc = -1 +Failed on test 0, range 1023, num ARFCNs 1 +Cannot encode range, rc = -1 Done.
Currently tests covering features of the GSM 04.08 specification are spread over the si and gsm0408 subdirs in tests.
This commit merges all tests from 'si' into 'gsm0408' and removes the 'si' test sub-directory.
Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 1 - openbsc/tests/Makefile.am | 2 +- openbsc/tests/gsm0408/gsm0408_test.c | 146 ++++++++++++++++++++++++++++++ openbsc/tests/gsm0408/gsm0408_test.ok | 20 +++++ openbsc/tests/si/Makefile.am | 12 --- openbsc/tests/si/si_test.c | 156 --------------------------------- openbsc/tests/si/si_test.ok | 20 ----- openbsc/tests/testsuite.at | 6 -- 8 files changed, 167 insertions(+), 196 deletions(-) delete mode 100644 openbsc/tests/si/Makefile.am delete mode 100644 openbsc/tests/si/si_test.c delete mode 100644 openbsc/tests/si/si_test.ok
diff --git a/openbsc/configure.ac b/openbsc/configure.ac index fe99569..5d29af7 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -166,7 +166,6 @@ AC_OUTPUT( tests/mgcp/Makefile tests/gprs/Makefile tests/gbproxy/Makefile - tests/si/Makefile tests/abis/Makefile tests/smpp/Makefile tests/trau/Makefile diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index d4bb954..31b2bb4 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs si abis gbproxy trau +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau
if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 721b283..3a6bbdd 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -42,6 +42,16 @@ exit(-1); \ }
+#define DBG(...) + +#define VERIFY(res, cmp, wanted) \ + if (!(res cmp wanted)) { \ + printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \ + __FILE__, __LINE__, res, # cmp, wanted); \ + } + + + /* * Test Location Area Identifier formatting. Table 10.5.3 of 04.08 */ @@ -306,6 +316,138 @@ static void test_range_encoding() test_random_range_encoding(ARFCN_RANGE_1024, 16); }
+static int freqs1[] = { + 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980 +}; + +static int freqs2[] = { + 402, 460, 1, 67, 131, 197, 272, 347, +}; + +static int freqs3[] = { + 68, 128, 198, 279, 353, 398, 452, + +}; + +static int w_out[] = { + 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9, +}; + +static int range128[] = { + 1, 1 + 127, +}; + +static int range256[] = { + 1, 1 + 128, +}; + +static int range512[] = { + 1, 1+ 511, +}; + + +static void test_arfcn_filter() +{ + int arfcns[50], i, res, f0_included; + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + + /* check that the arfcn is taken out. f0_included is only set for Range1024 */ + f0_included = 24; + res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), + arfcns[0], &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); + VERIFY(f0_included, ==, 0); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1)); + + /* check with range1024 */ + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), + arfcns[0], &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); + VERIFY(f0_included, ==, 1); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); + + /* check with range1024, not included */ + for (i = 0; i < ARRAY_SIZE(arfcns); ++i) + arfcns[i] = (i + 1) * 2; + res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), + 11, &f0_included); + VERIFY(res, ==, ARRAY_SIZE(arfcns)); + VERIFY(f0_included, ==, 0); + for (i = 0; i < res; ++i) + VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1); +} + +static void test_print_encoding() +{ + int rc; + int w[17]; + uint8_t chan_list[16]; + memset(chan_list, 0x23, sizeof(chan_list)); + + for (rc = 0; rc < ARRAY_SIZE(w); ++rc) + switch (rc % 3) { + case 0: + w[rc] = 0xAAAA; + break; + case 1: + w[rc] = 0x5555; + break; + case 2: + w[rc] = 0x9696; + break; + } + + rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); + VERIFY(rc, ==, 0); + + printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); +} + +static void test_si_range_helpers() +{ + int ws[(sizeof(freqs1)/sizeof(freqs1[0]))]; + int i, f0 = 0xFFFFFF; + + memset(&ws[0], 0x23, sizeof(ws)); + + i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs1[i]); + VERIFY(i, ==, 2); + + i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs2[i]); + VERIFY(i, ==, 2); + + i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3)); + printf("Element is: %d => freqs[i] = %d\n", i, freqs3[i]); + VERIFY(i, ==, 0); + + i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); + VERIFY(i, ==, 0); + + for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { + printf("w[%d]=%d\n", i, ws[i]); + VERIFY(ws[i], ==, w_out[i]); + } + + i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); + VERIFY(i, ==, ARFCN_RANGE_128); + VERIFY(f0, ==, 1); + + i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); + VERIFY(i, ==, ARFCN_RANGE_256); + VERIFY(f0, ==, 1); + + i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0); + VERIFY(i, ==, ARFCN_RANGE_512); + VERIFY(f0, ==, 1); +} + int main(int argc, char **argv) { osmo_init_logging(&log_info); @@ -313,6 +455,10 @@ int main(int argc, char **argv)
test_location_area_identifier(); test_mi_functionality(); + + test_si_range_helpers(); + test_arfcn_filter(); + test_print_encoding(); test_range_encoding();
printf("Done.\n"); diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index a92b879..5458669 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -2,6 +2,26 @@ Testing test location area identifier Testing parsing and generating TMSI/IMSI hex: 17 08 99 78 56 34 12 90 78 36 hex: 17 09 91 78 56 34 12 90 78 56 f4 +Element is: 2 => freqs[i] = 121 +Element is: 2 => freqs[i] = 1 +Element is: 0 => freqs[i] = 68 +w[0]=122 +w[1]=2 +w[2]=69 +w[3]=204 +w[4]=75 +w[5]=66 +w[6]=60 +w[7]=70 +w[8]=83 +w[9]=3 +w[10]=24 +w[11]=67 +w[12]=54 +w[13]=64 +w[14]=70 +w[15]=9 +Range512: 89 4b 2a 95 65 95 55 2c a9 55 aa 55 6a 95 59 55 Range test 0: range 511, num ARFCNs 12 chan_list = 88 00 98 34 85 36 7c 50 22 dc 5e ec 00 00 00 00 Decoded freqs 12 (expected 12) diff --git a/openbsc/tests/si/Makefile.am b/openbsc/tests/si/Makefile.am deleted file mode 100644 index 795bd30..0000000 --- a/openbsc/tests/si/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSCCP_CFLAGS) $(COVERAGE_CFLAGS) - -EXTRA_DIST = si_test.ok - -noinst_PROGRAMS = si_test - -si_test_SOURCES = si_test.c - -si_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOCORE_LIBS) -lrt $(LIBOSMOSCCP_LIBS) $(LIBOSMOVTY_LIBS) diff --git a/openbsc/tests/si/si_test.c b/openbsc/tests/si/si_test.c deleted file mode 100644 index fd840f3..0000000 --- a/openbsc/tests/si/si_test.c +++ /dev/null @@ -1,156 +0,0 @@ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <openbsc/arfcn_range_encode.h> - -#include <osmocom/core/utils.h> - -#define DBG(...) - -#define VERIFY(res, cmp, wanted) \ - if (!(res cmp wanted)) { \ - printf("ASSERT failed: %s:%d Wanted: %d %s %d\n", \ - __FILE__, __LINE__, res, # cmp, wanted); \ - } - - -static int freqs1[] = { - 12, 70, 121, 190, 250, 320, 401, 475, 520, 574, 634, 700, 764, 830, 905, 980 -}; - -static int freqs2[] = { - 402, 460, 1, 67, 131, 197, 272, 347, -}; - -static int freqs3[] = { - 68, 128, 198, 279, 353, 398, 452, - -}; - -static int w_out[] = { - 122, 2, 69, 204, 75, 66, 60, 70, 83, 3, 24, 67, 54, 64, 70, 9, -}; - -static int range128[] = { - 1, 1 + 127, -}; - -static int range256[] = { - 1, 1 + 128, -}; - -static int range512[] = { - 1, 1+ 511, -}; - - -static void test_arfcn_filter() -{ - int arfcns[50], i, res, f0_included; - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - - /* check that the arfcn is taken out. f0_included is only set for Range1024 */ - f0_included = 24; - res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 0); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1)); - - /* check with range1024 */ - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 1); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); - - /* check with range1024, not included */ - for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - 11, &f0_included); - VERIFY(res, ==, ARRAY_SIZE(arfcns)); - VERIFY(f0_included, ==, 0); - for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 1) * 2) - 1); -} - -static void test_print_encoding() -{ - int rc; - int w[17]; - uint8_t chan_list[16]; - memset(chan_list, 0x23, sizeof(chan_list)); - - for (rc = 0; rc < ARRAY_SIZE(w); ++rc) - switch (rc % 3) { - case 0: - w[rc] = 0xAAAA; - break; - case 1: - w[rc] = 0x5555; - break; - case 2: - w[rc] = 0x9696; - break; - } - - rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w); - VERIFY(rc, ==, 0); - - printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list))); -} - -int main(int argc, char **argv) -{ - int ws[(sizeof(freqs1)/sizeof(freqs1[0]))]; - int i, f0 = 0xFFFFFF; - - memset(&ws[0], 0x23, sizeof(ws)); - - i = range_enc_find_index(1023, freqs1, ARRAY_SIZE(freqs1)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs1[i]); - VERIFY(i, ==, 2); - - i = range_enc_find_index(511, freqs2, ARRAY_SIZE(freqs2)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs2[i]); - VERIFY(i, ==, 2); - - i = range_enc_find_index(511, freqs3, ARRAY_SIZE(freqs3)); - printf("Element is: %d => freqs[i] = %d\n", i, freqs3[i]); - VERIFY(i, ==, 0); - - i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0); - VERIFY(i, ==, 0); - - for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) { - printf("w[%d]=%d\n", i, ws[i]); - VERIFY(ws[i], ==, w_out[i]); - } - - i = range_enc_determine_range(range128, ARRAY_SIZE(range128), &f0); - VERIFY(i, ==, ARFCN_RANGE_128); - VERIFY(f0, ==, 1); - - i = range_enc_determine_range(range256, ARRAY_SIZE(range256), &f0); - VERIFY(i, ==, ARFCN_RANGE_256); - VERIFY(f0, ==, 1); - - i = range_enc_determine_range(range512, ARRAY_SIZE(range512), &f0); - VERIFY(i, ==, ARFCN_RANGE_512); - VERIFY(f0, ==, 1); - - - test_arfcn_filter(); - test_print_encoding(); - - return 0; -} diff --git a/openbsc/tests/si/si_test.ok b/openbsc/tests/si/si_test.ok deleted file mode 100644 index 6a3ee51..0000000 --- a/openbsc/tests/si/si_test.ok +++ /dev/null @@ -1,20 +0,0 @@ -Element is: 2 => freqs[i] = 121 -Element is: 2 => freqs[i] = 1 -Element is: 0 => freqs[i] = 68 -w[0]=122 -w[1]=2 -w[2]=69 -w[3]=204 -w[4]=75 -w[5]=66 -w[6]=60 -w[7]=70 -w[8]=83 -w[9]=3 -w[10]=24 -w[11]=67 -w[12]=54 -w[13]=64 -w[14]=70 -w[15]=9 -Range512: 89 4b 2a 95 65 95 55 2c a9 55 aa 55 6a 95 59 55 diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 652cfe9..b2c5518 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -57,12 +57,6 @@ cat $abs_srcdir/bsc-nat-trie/bsc_nat_trie_test.ok > expout AT_CHECK([$abs_top_builddir/tests/bsc-nat-trie/bsc_nat_trie_test], [], [expout], [ignore]) AT_CLEANUP
-AT_SETUP([si]) -AT_KEYWORDS([si]) -cat $abs_srcdir/si/si_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/si/si_test], [], [expout], [ignore]) -AT_CLEANUP - AT_SETUP([abis]) AT_KEYWORDS([abis]) cat $abs_srcdir/abis/abis_test.ok > expout
This patch fixes a bug in the range encoder that leads to wrong encoding when 17 or more ARFCNs are encoded.
Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 2 +- openbsc/tests/gsm0408/gsm0408_test.ok | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index c52743e..9177546 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -256,7 +256,7 @@ int range_enc_range512(uint8_t *chan_list, int f0, int *w) range512->w15 = HIGH_BITS(w, 15, 6, 6); /* W(16) */ range512->w16_hi = HIGH_BITS(w, 16, 5, 2); - range512->w16_lo = HIGH_BITS(w, 16, 5, 3); + range512->w16_lo = LOW_BITS(w, 16, 5, 3); /* W(17) */ range512->w17 = HIGH_BITS(w, 17, 5, 5);
diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index 5458669..dab495d 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -35,10 +35,9 @@ chan_list = 88 00 82 7f 01 7f 7e 04 0b ff ff fc 10 41 07 ff Decoded freqs 18 (expected 18) Decoded: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Range test 3: range 511, num ARFCNs 18 -chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 76 +chan_list = 88 00 94 3a 44 32 d7 2a 43 2a 13 94 e5 38 39 f6 Decoded freqs 18 (expected 18) -Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 507 (!= 511) -Decoding error, got wrong freqs +Decoded: 1 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 417 511 Range test 4: range 511, num ARFCNs 6 chan_list = 88 00 8b 3c 88 b9 6b 00 00 00 00 00 00 00 00 00 Decoded freqs 6 (expected 6) @@ -60,12 +59,6 @@ Cannot encode range, rc = -1 Failed on test 0, range 255, num ARFCNs 1 Cannot encode range, rc = -1 Random range test: range 511, max num ARFCNs 18 -Decoding error, got wrong freqs -Failed on test 0, range 511, num ARFCNs 17 -chan_list = 88 21 55 fc da d7 76 03 31 2f ed 45 dc 93 d6 80 -Decoded freqs 17 (expected 17) -Decoded: 66 81 161 250 314 343 383 (!= 380) 395 396 397 409 429 505 506 516 518 545 -Decoding error, got wrong freqs Random range test: range 1023, max num ARFCNs 16 Cannot encode range, rc = -1 Failed on test 0, range 1023, num ARFCNs 1
f0 is currently set to arfcns[0] in range_enc_determine_range(), while GSM 04.08 requires f0 to be ARFCN 0 in range1024 encoding.
This patch modifies range_enc_determine_range() to force f0 to be 0 if this encoding is used. This way the case distinction in range_enc_filter_arfcns() is not longer necessary.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/arfcn_range_encode.h | 2 +- openbsc/src/libbsc/arfcn_range_encode.c | 44 +++++++++++--------------- openbsc/src/libbsc/system_information.c | 2 +- openbsc/tests/gsm0408/gsm0408_test.c | 24 +++++++------- 4 files changed, 33 insertions(+), 39 deletions(-)
diff --git a/openbsc/include/openbsc/arfcn_range_encode.h b/openbsc/include/openbsc/arfcn_range_encode.h index 7a6fff0..bd85d6a 100644 --- a/openbsc/include/openbsc/arfcn_range_encode.h +++ b/openbsc/include/openbsc/arfcn_range_encode.h @@ -16,7 +16,7 @@ enum { int range_enc_determine_range(const int *arfcns, int size, int *f0_out); int range_enc_arfcns(const int rng, const int *arfcns, int sze, int *out, int idx); int range_enc_find_index(const int rng, const int *arfcns, int size); -int range_enc_filter_arfcns(const int rng, int *arfcns, const int sze, const int f0, int *f0_included); +int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included);
int range_enc_range128(uint8_t *chan_list, int f0, int *w); int range_enc_range256(uint8_t *chan_list, int f0, int *w); diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index 9177546..a047a06 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -144,7 +144,9 @@ int range_enc_arfcns(const int range, */ /** * This implements the range determination as described in GSM 04.08 J4. The - * result will be a base frequency f0 and the range to use. + * result will be a base frequency f0 and the range to use. Note that for range + * 1024 encoding f0 always refers to ARFCN 0 even if it is not an element of + * the arfcns list. * * \param[in] arfcns The input frequencies, they must be sorted, lowest number first * \param[in] size The length of the array @@ -166,8 +168,10 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) return ARFCN_RANGE_256; if (max < 512 && size <= 18) return ARFCN_RANGE_512; - if (max < 1024 && size <= 17) + if (max < 1024 && size <= 17) { + *f0 = 0; return ARFCN_RANGE_1024; + }
return ARFCN_RANGE_INVALID; } @@ -271,34 +275,24 @@ int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) return -1; }
-int range_enc_filter_arfcns(const int range, int *arfcns, - const int size, const int f0, int *f0_included) +int range_enc_filter_arfcns(int *arfcns, + const int size, const int f0, int *f0_included) { int i, j = 0; *f0_included = 0;
- if (range == ARFCN_RANGE_1024) { - for (i = 0; i < size; ++i) { - if (arfcns[i] == f0) { - *f0_included = 1; - continue; - } - - /* copy and subtract */ - arfcns[j++] = mod(arfcns[i] - 1, 1024); - } - } else { - for (i = 0; i < size; ++i) { - /* - * Appendix J.4 says the following: - * All frequencies except F(0), minus F(0) + 1. - * I assume we need to exclude it here. - */ - if (arfcns[i] == f0) - continue; - - arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024); + for (i = 0; i < size; ++i) { + /* + * Appendix J.4 says the following: + * All frequencies except F(0), minus F(0) + 1. + * I assume we need to exclude it here. + */ + if (arfcns[i] == f0) { + *f0_included = 1; + continue; } + + arfcns[j++] = mod(arfcns[i] - (f0 + 1), 1024); }
return j; diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 5f46bf9..95ac736 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -197,7 +197,7 @@ static int enc_freq_lst_range(uint8_t *chan_list, * Manipulate the ARFCN list according to the rules in J4 depending * on the selected range. */ - arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
memset(w, 0, sizeof(w)); diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 3a6bbdd..894eb0f 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -152,12 +152,12 @@ static int test_single_range_encoding(int range, const int *orig_arfcns, arfcns_used = arfcns_num; memmove(arfcns, orig_arfcns, sizeof(arfcns));
- f0 = arfcns[0]; + f0 = range == ARFCN_RANGE_1024 ? 0 : arfcns[0]; /* * Manipulate the ARFCN list according to the rules in J4 depending * on the selected range. */ - arfcns_used = range_enc_filter_arfcns(range, arfcns, arfcns_used, + arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
memset(w, 0, sizeof(w)); @@ -354,28 +354,28 @@ static void test_arfcn_filter()
/* check that the arfcn is taken out. f0_included is only set for Range1024 */ f0_included = 24; - res = range_enc_filter_arfcns(ARFCN_RANGE_512, arfcns, ARRAY_SIZE(arfcns), + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), arfcns[0], &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); - VERIFY(f0_included, ==, 0); + VERIFY(f0_included, ==, 1); for (i = 0; i < res; ++i) VERIFY(arfcns[i], ==, ((i+2) * 2) - (2+1));
- /* check with range1024 */ + /* check with range1024, ARFCN 0 is included */ for (i = 0; i < ARRAY_SIZE(arfcns); ++i) - arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - arfcns[0], &f0_included); + arfcns[i] = i * 2; + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), + 0, &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns) - 1); VERIFY(f0_included, ==, 1); for (i = 0; i < res; ++i) - VERIFY(arfcns[i], ==, ((i + 2) * 2) - 1); + VERIFY(arfcns[i], ==, (i + 1) * 2 - 1);
- /* check with range1024, not included */ + /* check with range1024, ARFCN 0 not included */ for (i = 0; i < ARRAY_SIZE(arfcns); ++i) arfcns[i] = (i + 1) * 2; - res = range_enc_filter_arfcns(ARFCN_RANGE_1024, arfcns, ARRAY_SIZE(arfcns), - 11, &f0_included); + res = range_enc_filter_arfcns(arfcns, ARRAY_SIZE(arfcns), + 0, &f0_included); VERIFY(res, ==, ARRAY_SIZE(arfcns)); VERIFY(f0_included, ==, 0); for (i = 0; i < res; ++i)
Currently the encoding of the chan_list is done by a hard-coded sequence of macros that closely resembles figure 10.5.16 in 3GPP TS 04.08.
This patch replaces this by an algorithmic solution that can be used for all range encodings and is based on the property
W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present
(see section 10.5.2.13 in TS 04.08).
Ticket: OW#1061 Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 141 ++++++++++++++++++------------- 1 file changed, 83 insertions(+), 58 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index a047a06..1a26523 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -176,16 +176,6 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0) return ARFCN_RANGE_INVALID; }
-/* - * The below is easier is to write in four methods than - * to use the max_bits. The encoding is so screwed.. as - * the bits need to be put in place in the wrong order.. - */ -#define HIGH_BITS(w, index, bits, offset) \ - (w[index - 1] >> (bits - offset)) -#define LOW_BITS(w, index, bits, offset) \ - (w[index - 1]) - static void write_orig_arfcn(uint8_t *chan_list, int f0) { chan_list[0] |= (f0 >> 9) & 1; @@ -193,6 +183,88 @@ static void write_orig_arfcn(uint8_t *chan_list, int f0) chan_list[2] = (f0 & 1) << 7; }
+static void write_all_wn(uint8_t *chan_list, int bit_offs, + int *w, int w_size, int w1_len) +{ + int octet_offs = 0; /* offset into chan_list */ + int wk_len = w1_len; /* encoding size in bits of w[k] */ + int k; /* 1 based */ + int level = 0; /* tree level, top level = 0 */ + int lvl_left = 1; /* nodes per tree level */ + + /* W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present */ + + for (k = 1; k <= w_size; k++) { + int wk_left = wk_len; + DEBUGP(DRR, + "k=%d, wk_len=%d, offs=%d:%d, level=%d, " + "lvl_left=%d\n", + k, wk_len, octet_offs, bit_offs, level, lvl_left); + + while (wk_left > 0) { + int cur_bits = 8 - bit_offs; + int cur_mask; + int wk_slice; + + if (cur_bits > wk_left) + cur_bits = wk_left; + + cur_mask = ((1 << cur_bits) - 1); + + DEBUGP(DRR, + " wk_left=%d, cur_bits=%d, offs=%d:%d\n", + wk_left, cur_bits, octet_offs, bit_offs); + + /* advance */ + wk_left -= cur_bits; + bit_offs += cur_bits; + + /* right aligned wk data for current out octet */ + wk_slice = (w[k-1] >> wk_left) & cur_mask; + + /* cur_bits now contains the number of bits + * that are to be copied from wk to the chan_list. + * wk_left is set to the number of bits that must + * not yet be copied. + * bit_offs points after the bit area that is going to + * be overwritten: + * + * wk_left + * | + * v + * wk: WWWWWWWWWWW + * |||||<-- wk_slice, cur_bits=5 + * --WWWWW- + * ^ + * | + * bit_offs + */ + + DEBUGP(DRR, + " wk=%02x, slice=%02x/%02x, cl=%02x\n", + w[k-1], wk_slice, cur_mask, wk_slice << (8 - bit_offs)); + + chan_list[octet_offs] &= ~(cur_mask << (8 - bit_offs)); + chan_list[octet_offs] |= wk_slice << (8 - bit_offs); + + /* adjust output */ + if (bit_offs == 8) { + bit_offs = 0; + octet_offs += 1; + } + } + + /* adjust bit sizes */ + lvl_left -= 1; + if (!lvl_left) { + /* completed tree level, advance to next */ + level += 1; + lvl_left = 1 << level; + wk_len -= 1; + } + } +} + int range_enc_range128(uint8_t *chan_list, int f0, int *w) { chan_list[0] = 0x8C; @@ -213,57 +285,10 @@ int range_enc_range256(uint8_t *chan_list, int f0, int *w)
int range_enc_range512(uint8_t *chan_list, int f0, int *w) { - struct gsm48_range_512 *range512; chan_list[0] = 0x88; write_orig_arfcn(chan_list, f0);
- range512 = (struct gsm48_range_512 *) &chan_list[0]; - - /* W(1) */ - range512->w1_hi = HIGH_BITS(w, 1, 9, 7); - range512->w1_lo = LOW_BITS (w, 1, 9, 2); - /* W(2) */ - range512->w2_hi = HIGH_BITS(w, 2, 8, 6); - range512->w2_lo = LOW_BITS (w, 2, 8, 2); - /* W(3) */ - range512->w3_hi = HIGH_BITS(w, 3, 8, 6); - range512->w3_lo = LOW_BITS (w, 3, 8, 2); - /* W(4) */ - range512->w4_hi = HIGH_BITS(w, 4, 7, 6); - range512->w4_lo = LOW_BITS (w, 4, 7, 1); - /* W(5) */ - range512->w5 = HIGH_BITS(w, 5, 7, 7); - /* W(6) */ - range512->w6 = HIGH_BITS(w, 6, 7, 7); - /* W(7) */ - range512->w7_hi = HIGH_BITS(w, 7, 7, 1); - range512->w7_lo = LOW_BITS (w, 7, 7, 6); - /* W(8) */ - range512->w8_hi = HIGH_BITS(w, 8, 6, 2); - range512->w8_lo = LOW_BITS (w, 8, 6, 4); - /* W(9) */ - range512->w9_hi = HIGH_BITS(w, 9, 6, 4); - range512->w9_lo = LOW_BITS(w, 9, 6, 2); - /* W(10) */ - range512->w10 = HIGH_BITS(w, 10, 6, 6); - /* W(11) */ - range512->w11 = HIGH_BITS(w, 11, 6, 6); - /* W(12) */ - range512->w12_hi = HIGH_BITS(w, 12, 6, 2); - range512->w12_lo = LOW_BITS (w, 12, 6, 4); - /* W(13) */ - range512->w13_hi = HIGH_BITS(w, 13, 6, 4); - range512->w13_lo = LOW_BITS(w, 13, 6, 2); - /* W(14) */ - range512->w14 = HIGH_BITS(w, 14, 6, 6); - /* W(15) */ - range512->w15 = HIGH_BITS(w, 15, 6, 6); - /* W(16) */ - range512->w16_hi = HIGH_BITS(w, 16, 5, 2); - range512->w16_lo = LOW_BITS(w, 16, 5, 3); - /* W(17) */ - range512->w17 = HIGH_BITS(w, 17, 5, 5); - + write_all_wn(&chan_list[2], 1, w, 17, 9); return 0; }
This commit adds the implementation of these range formats to the encoder. In addition, the work-around that tried range 512 first is removed, so that the selection is primarily based on the max distance between frequencies.
Ticket: OW#1061 Sponsored-by: On-Waves ehf --- openbsc/src/libbsc/arfcn_range_encode.c | 12 ++++++------ openbsc/tests/gsm0408/gsm0408_test.ok | 17 ++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c index 1a26523..e67bf0a 100644 --- a/openbsc/src/libbsc/arfcn_range_encode.c +++ b/openbsc/src/libbsc/arfcn_range_encode.c @@ -270,8 +270,8 @@ int range_enc_range128(uint8_t *chan_list, int f0, int *w) chan_list[0] = 0x8C; write_orig_arfcn(chan_list, f0);
- LOGP(DRR, LOGL_ERROR, "Range128 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[2], 1, w, 28, 7); + return 0; }
int range_enc_range256(uint8_t *chan_list, int f0, int *w) @@ -279,8 +279,8 @@ int range_enc_range256(uint8_t *chan_list, int f0, int *w) chan_list[0] = 0x8A; write_orig_arfcn(chan_list, f0);
- LOGP(DRR, LOGL_ERROR, "Range256 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[2], 1, w, 21, 8); + return 0; }
int range_enc_range512(uint8_t *chan_list, int f0, int *w) @@ -296,8 +296,8 @@ int range_enc_range1024(uint8_t *chan_list, int f0, int f0_included, int *w) { chan_list[0] = 0x80 | (f0_included << 2);
- LOGP(DRR, LOGL_ERROR, "Range1024 encoding is not implemented.\n"); - return -1; + write_all_wn(&chan_list[0], 6, w, 16, 10); + return 0; }
int range_enc_filter_arfcns(int *arfcns, diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok index dab495d..3d3c4e6 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.ok +++ b/openbsc/tests/gsm0408/gsm0408_test.ok @@ -47,20 +47,15 @@ chan_list = 88 05 08 fc 88 b9 6b 00 00 00 00 00 00 00 00 00 Decoded freqs 6 (expected 6) Decoded: 10 17 31 45 58 79 Range test 6: range 1023, num ARFCNs 17 -Cannot encode range, rc = -1 +chan_list = 84 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f +Decoded freqs 17 (expected 17) +Decoded: 0 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 Range test 7: range 1023, num ARFCNs 16 -Cannot encode range, rc = -1 +chan_list = 80 71 e4 ab b9 58 05 cb 39 17 fd b0 75 62 0f 2f +Decoded freqs 16 (expected 16) +Decoded: 17 31 45 58 79 81 97 113 127 213 277 287 311 331 391 1023 Random range test: range 127, max num ARFCNs 29 -Cannot encode range, rc = -1 -Failed on test 0, range 127, num ARFCNs 1 -Cannot encode range, rc = -1 Random range test: range 255, max num ARFCNs 22 -Cannot encode range, rc = -1 -Failed on test 0, range 255, num ARFCNs 1 -Cannot encode range, rc = -1 Random range test: range 511, max num ARFCNs 18 Random range test: range 1023, max num ARFCNs 16 -Cannot encode range, rc = -1 -Failed on test 0, range 1023, num ARFCNs 1 -Cannot encode range, rc = -1 Done.
On Wed, Jan 15, 2014 at 02:46:09PM +0100, Jacob Erlbeck wrote:
From: Holger Hans Peter Freyther zecke@selfish.org
Dear Jacob,
small technical issue. These patches appear to depend on your MGCP work and I can't git am them right now (and -3 doesn't work due the missing old parent). Could you please publish your MGCP and SI branch?
I will merge them then.
holger