From 64c07d213c7bf09813a16a7aad8bacacfdc3011a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 15 Feb 2011 11:43:27 +0100 Subject: Allow configuration of SI5 neighbor list != SI2 neighbor list This introducecs the new VTY command "neighbor-list mode manual-si5" in combination with "si5 neighbor-list (add|del) arfcn <0-1024>", which allows you to (optionally) have neighbor channel lists that differ in SI5 and in SI2. --- openbsc/include/openbsc/gsm_data.h | 11 ++++++- openbsc/src/bsc_vty.c | 61 +++++++++++++++++++++++++++++++++----- openbsc/src/gsm_data.c | 3 ++ openbsc/src/system_information.c | 15 ++++++---- 4 files changed, 76 insertions(+), 14 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index f40bcbdd3..03e7a7c83 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -491,6 +491,12 @@ struct gsm_bts_gprs_nsvc { struct gsm_nm_state nm_state; }; +enum neigh_list_manual_mode { + NL_MODE_AUTOMATIC = 0, + NL_MODE_MANUAL = 1, + NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */ +}; + /* One BTS */ struct gsm_bts { /* list header in net->bts_list */ @@ -542,7 +548,7 @@ struct gsm_bts { struct gsm_nm_state nm_state; } site_mgr; - int neigh_list_manual_mode; + enum neigh_list_manual_mode neigh_list_manual_mode; /* parameters from which we build SYSTEM INFORMATION */ struct { struct gsm48_rach_control rach_control; @@ -553,10 +559,13 @@ struct gsm_bts { struct gsm48_control_channel_descr chan_desc; struct bitvec neigh_list; struct bitvec cell_alloc; + struct bitvec si5_neigh_list; struct { /* bitmask large enough for all possible ARFCN's */ u_int8_t neigh_list[1024/8]; u_int8_t cell_alloc[1024/8]; + /* If the user wants a different neighbor list in SI5 than in SI2 */ + u_int8_t si5_neigh_list[1024/8]; } data; } si_common; diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c index 55eeb1415..55a667cdf 100644 --- a/openbsc/src/bsc_vty.c +++ b/openbsc/src/bsc_vty.c @@ -76,6 +76,13 @@ static const struct value_string gprs_bssgp_cfg_strs[] = { { 0, NULL } }; +static const struct value_string bts_neigh_mode_strs[] = { + { NL_MODE_AUTOMATIC, "automatic" }, + { NL_MODE_MANUAL, "manual" }, + { NL_MODE_MANUAL_SI5SEP, "manual-si5" }, + { 0, NULL } +}; + struct cmd_node net_node = { GSMNET_NODE, "%s(network)#", @@ -495,14 +502,21 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE); vty_out(vty, " neighbor-list mode %s%s", - bts->neigh_list_manual_mode ? "manual" : "automatic", VTY_NEWLINE); - if (bts->neigh_list_manual_mode) { + get_value_string(bts_neigh_mode_strs, bts->neigh_list_manual_mode), VTY_NEWLINE); + if (bts->neigh_list_manual_mode != NL_MODE_AUTOMATIC) { for (i = 0; i < 1024; i++) { if (bitvec_get_bit_pos(&bts->si_common.neigh_list, i)) vty_out(vty, " neighbor-list add arfcn %u%s", i, VTY_NEWLINE); } } + if (bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP) { + for (i = 0; i < 1024; i++) { + if (bitvec_get_bit_pos(&bts->si_common.si5_neigh_list, i)) + vty_out(vty, " si5 neighbor-list add arfcn %u%s", + i, VTY_NEWLINE); + } + } config_write_bts_gprs(vty, bts); @@ -2136,21 +2150,28 @@ DEFUN(cfg_bts_si_static, cfg_bts_si_static_cmd, } DEFUN(cfg_bts_neigh_mode, cfg_bts_neigh_mode_cmd, - "neighbor-list mode (automatic|manual)", + "neighbor-list mode (automatic|manual|manual-si5)", "Neighbor List\n" "Mode of Neighbor List generation\n" - "Automatically from all BTS in this OpenBSC\n" "Manual\n") + "Automatically from all BTS in this OpenBSC\n" "Manual\n" + "Manual with different lists for SI2 and SI5\n") { struct gsm_bts *bts = vty->index; + int mode = get_string_value(bts_neigh_mode_strs, argv[0]); - if (!strcmp(argv[0], "manual")) { + switch (mode) { + case NL_MODE_MANUAL_SI5SEP: + case NL_MODE_MANUAL: /* make sure we clear the current list when switching to * manual mode */ if (bts->neigh_list_manual_mode == 0) memset(&bts->si_common.data.neigh_list, 0, sizeof(bts->si_common.data.neigh_list)); - bts->neigh_list_manual_mode = 1; - } else - bts->neigh_list_manual_mode = 0; + break; + default: + break; + } + + bts->neigh_list_manual_mode = mode; return CMD_SUCCESS; } @@ -2179,6 +2200,29 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd, + "si5 neighbor-list (add|del) arfcn <0-1024>", + "SI5 Neighbor List\n" "Add to manual SI5 neighbor list\n" + "Delete from SI5 manual neighbor list\n" "ARFCN of neighbor\n" + "ARFCN of neighbor\n") +{ + struct gsm_bts *bts = vty->index; + struct bitvec *bv = &bts->si_common.si5_neigh_list; + uint16_t arfcn = atoi(argv[1]); + + if (!bts->neigh_list_manual_mode) { + vty_out(vty, "%% Cannot configure neighbor list in " + "automatic mode%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strcmp(argv[0], "add")) + bitvec_set_bit_pos(bv, arfcn, 1); + else + bitvec_set_bit_pos(bv, arfcn, 0); + + return CMD_SUCCESS; +} #define TRX_TEXT "Radio Transceiver\n" @@ -2679,6 +2723,7 @@ int bsc_vty_init(void) install_element(BTS_NODE, &cfg_bts_si_static_cmd); install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd); install_element(BTS_NODE, &cfg_bts_neigh_cmd); + install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd); install_element(BTS_NODE, &cfg_trx_cmd); install_node(&trx_node, dummy_config_write); diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 3a532203b..f181fd162 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -214,6 +214,9 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type, bts->si_common.neigh_list.data = bts->si_common.data.neigh_list; bts->si_common.neigh_list.data_len = sizeof(bts->si_common.data.neigh_list); + bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list; + bts->si_common.si5_neigh_list.data_len = + sizeof(bts->si_common.data.si5_neigh_list); bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc; bts->si_common.cell_alloc.data_len = sizeof(bts->si_common.data.cell_alloc); diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c index 5079d81b7..1dc1bb0ea 100644 --- a/openbsc/src/system_information.c +++ b/openbsc/src/system_information.c @@ -199,16 +199,21 @@ static int generate_cell_chan_list(u_int8_t *chan_list, struct gsm_bts *bts) } /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ -static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts) +static int generate_bcch_chan_list(u_int8_t *chan_list, struct gsm_bts *bts, int si5) { struct gsm_bts *cur_bts; - struct bitvec *bv = &bts->si_common.neigh_list; + struct bitvec *bv; + + if (si5 && bts->neigh_list_manual_mode == NL_MODE_MANUAL_SI5SEP) + bv = &bts->si_common.si5_neigh_list; + else + bv = &bts->si_common.neigh_list; /* Zero-initialize the bit-vector */ memset(bv->data, 0, bv->data_len); /* Generate list of neighbor cells if we are in automatic mode */ - if (bts->neigh_list_manual_mode == 0) { + if (bts->neigh_list_manual_mode == NL_MODE_AUTOMATIC) { /* first we generate a bitvec of the BCCH ARFCN's in our BSC */ llist_for_each_entry(cur_bts, &bts->network->bts_list, list) { if (cur_bts == bts) @@ -259,7 +264,7 @@ static int generate_si2(u_int8_t *output, struct gsm_bts *bts) si2->header.skip_indicator = 0; si2->header.system_information = GSM48_MT_RR_SYSINFO_2; - rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts); + rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0); if (rc < 0) return rc; @@ -376,7 +381,7 @@ static int generate_si5(u_int8_t *output, struct gsm_bts *bts) si5->rr_protocol_discriminator = GSM48_PDISC_RR; si5->skip_indicator = 0; si5->system_information = GSM48_MT_RR_SYSINFO_5; - rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts); + rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1); if (rc < 0) return rc; -- cgit v1.2.3