summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-07-07 08:13:22 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2013-07-29 12:45:09 +0200
commit437c80cab14629f7d2f451128c6414d5a8d5186a (patch)
treeedad3d18ed8795a275e71235eab67dae1aa50c3a
parent4f26f1ee4281916e98d9ddc6291d38a8fbaffc43 (diff)
HO: Move handover VTY commands, prepare for other HO algorithms
A special VTY command "handover algorithm x" is used to set the algorithm. A union of all handover option is provided, but depending on the selected algorithm, only the specific options are accepted, others are rejected. At VTY write, only the specific options are written to the config file.
-rw-r--r--openbsc/include/openbsc/gsm_data.h3
-rw-r--r--openbsc/include/openbsc/handover_decision.h7
-rw-r--r--openbsc/include/openbsc/vty.h2
-rw-r--r--openbsc/src/libbsc/Makefile.am3
-rw-r--r--openbsc/src/libbsc/bsc_vty.c329
-rw-r--r--openbsc/src/libbsc/handover_decision_1.c (renamed from openbsc/src/libbsc/handover_decision.c)2
-rw-r--r--openbsc/src/libbsc/handover_vty.c511
-rw-r--r--openbsc/src/osmo-nitb/bsc_hack.c1
8 files changed, 531 insertions, 327 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 17ca5df57..94bdfa1be 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -281,7 +281,8 @@ struct gsm_network {
/* control interface */
struct ctrl_handle *ctrl;
- /* congestion check timer */
+ /* global handover settings */
+ int ho_algorithm;
int ho_congest_timeout;
struct osmo_timer_list ho_congest_timer;
};
diff --git a/openbsc/include/openbsc/handover_decision.h b/openbsc/include/openbsc/handover_decision.h
index 81078b05d..2ea17f1be 100644
--- a/openbsc/include/openbsc/handover_decision.h
+++ b/openbsc/include/openbsc/handover_decision.h
@@ -1,7 +1,12 @@
#ifndef _HANDOVER_DECISION_H
#define _HANDOVER_DECISION_H
-void on_dso_load_ho_dec(void);
+void bts_dump_vty_handover(struct vty *vty, struct gsm_bts *bts);
+void config_write_bts_handover(struct vty *vty, struct gsm_bts *bts);
+void config_write_net_handover(struct vty *vty);
+void bsc_vty_init_handover(void);
+
+void init_ho_1(void);
#endif /* _HANDOVER_DECISION_H */
diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h
index 183fc2510..aa7060714 100644
--- a/openbsc/include/openbsc/vty.h
+++ b/openbsc/include/openbsc/vty.h
@@ -8,6 +8,8 @@
struct gsm_network;
struct vty;
+struct gsm_network *gsmnet_from_vty(struct vty *v);
+
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am
index 42fabab6d..fa5d6bdfe 100644
--- a/openbsc/src/libbsc/Makefile.am
+++ b/openbsc/src/libbsc/Makefile.am
@@ -16,7 +16,8 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \
bts_sysmobts.c \
chan_alloc.c \
gsm_subscriber_base.c \
- handover_decision.c handover_logic.c meas_rep.c \
+ handover_decision_1.c \
+ handover_vty.c handover_logic.c meas_rep.c \
rest_octets.c system_information.c \
e1_config.c \
bsc_api.c bsc_msc.c bsc_vty.c \
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index d9b8cebef..bc0f67953 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -50,6 +50,7 @@
#include <openbsc/abis_rsl.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/osmo_bsc_rf.h>
+#include <openbsc/handover_decision.h>
#include "../../bscconfig.h"
@@ -299,10 +300,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
e1isl_dump_vty(vty, bts->oml_link);
}
- vty_out(vty, " Handover: %s%s", bts->handover.ho_active ? "On" : "Off",
- VTY_NEWLINE);
- vty_out(vty, " Assignment: %s%s", bts->handover.as_active ? "On" : "Off",
- VTY_NEWLINE);
+
+ bts_dump_vty_handover(vty, bts);
/* FIXME: chan_desc */
memset(&pl, 0, sizeof(pl));
@@ -713,44 +712,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, "auto%s", VTY_NEWLINE);
}
- vty_out(vty, " handover enable handover %u%s",
- bts->handover.ho_active, VTY_NEWLINE);
- vty_out(vty, " handover enable assignment %u%s",
- bts->handover.as_active, VTY_NEWLINE);
- vty_out(vty, " handover set %s%s",
- (bts->handover.full) ? "full" : "sub", VTY_NEWLINE);
- vty_out(vty, " handover min rxlev %d%s",
- bts->handover.min_rxlev, VTY_NEWLINE);
- vty_out(vty, " handover window rxlev averaging %u%s",
- bts->handover.win_rxlev_avg, VTY_NEWLINE);
- vty_out(vty, " handover window rxlev neighbor averaging %u%s",
- bts->handover.win_rxlev_avg_neigh, VTY_NEWLINE);
- vty_out(vty, " handover power budget hysteresis %u%s",
- bts->handover.pwr_hysteresis, VTY_NEWLINE);
- vty_out(vty, " handover power budget interval %u%s",
- bts->handover.pwr_interval, VTY_NEWLINE);
- vty_out(vty, " handover afs rxlev improvement %u%s",
- bts->handover.afs_rxlev_improve, VTY_NEWLINE);
- vty_out(vty, " handover min rxqual %u%s",
- bts->handover.min_rxqual, VTY_NEWLINE);
- vty_out(vty, " handover window rxqual averaging %u%s",
- bts->handover.win_rxqual_avg, VTY_NEWLINE);
- vty_out(vty, " handover afs rxqual improvement %u%s",
- bts->handover.afs_rxqual_improve, VTY_NEWLINE);
- vty_out(vty, " handover maximum distance %u%s",
- bts->handover.max_distance, VTY_NEWLINE);
- vty_out(vty, " handover min free tch-f %u%s",
- bts->handover.min_free_tchf, VTY_NEWLINE);
- vty_out(vty, " handover min free tch-h %u%s",
- bts->handover.min_free_tchh, VTY_NEWLINE);
- vty_out(vty, " handover max unsync handovers %u%s",
- bts->handover.max_unsync_ho, VTY_NEWLINE);
- vty_out(vty, " handover penalty max distance %u%s",
- bts->handover.penalty_max_dist, VTY_NEWLINE);
- vty_out(vty, " handover penalty handover failure %u%s",
- bts->handover.penalty_ho_fail, VTY_NEWLINE);
- vty_out(vty, " handover penalty assignment failure %u%s",
- bts->handover.penalty_as_fail, VTY_NEWLINE);
+ config_write_bts_handover(vty, bts);
config_write_bts_gprs(vty, bts);
@@ -808,8 +770,7 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " dtx-used %u%s", gsmnet->dtx_enabled, VTY_NEWLINE);
vty_out(vty, " subscriber-keep-in-ram %d%s",
gsmnet->keep_subscr, VTY_NEWLINE);
- vty_out(vty, " handover congestion-check-timer %u%s",
- gsmnet->ho_congest_timeout, VTY_NEWLINE);
+ config_write_net_handover(vty);
return CMD_SUCCESS;
}
@@ -1491,18 +1452,6 @@ DEFUN(cfg_net_subscr_keep,
return CMD_SUCCESS;
}
-DEFUN(cfg_net_ho_congest_timer,
- cfg_net_ho_congest_timer_cmd,
- "handover congestion-check-timer <0-60>",
- "Global handover settings.\n"
- "Handover congestion check timer\n"
- "Time in seconds for congestion check interval (0 to disable)\n")
-{
- struct gsm_network *gsmnet = gsmnet_from_vty(vty);
- gsmnet->ho_congest_timeout = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
/* per-BTS configuration */
DEFUN(cfg_bts,
cfg_bts_cmd,
@@ -3221,252 +3170,6 @@ DEFUN(cfg_bts_amr_hr_hyst3, cfg_bts_amr_hr_hyst3_cmd,
return CMD_SUCCESS;
}
-#define HANDOVER_STR "Handover Options\n"
-#define HO_ENABLE_STR HANDOVER_STR "Enable or disable handover/assignment\n"
-
-DEFUN(cfg_bts_ho_handover, cfg_bts_ho_handover_cmd,
- "handover enable handover (0|1)",
- HO_ENABLE_STR
- "Enable or disable handover\n"
- "Don't perform in-call handover\n"
- "Perform in-call handover\n")
-{
- int enable = atoi(argv[0]);
- struct gsm_bts *bts = vty->index;
-
- if (enable && ipacc_rtp_direct) {
- vty_out(vty, "%% Cannot enable handover unless RTP Proxy mode "
- "is enabled by using the -P command line option%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- bts->handover.ho_active = enable;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_assignment, cfg_bts_ho_assignment_cmd,
- "handover enable assignment (0|1)",
- HO_ENABLE_STR
- "Enable or disable assignment\n"
- "Don't perform in-call assignment\n"
- "Perform in-call assignment\n")
-{
- int enable = atoi(argv[0]);
- struct gsm_bts *bts = vty->index;
-
- if (enable && ipacc_rtp_direct) {
- vty_out(vty, "%% Cannot enable assignment unless RTP Proxy mode "
- "is enabled by using the -P command line option%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- bts->handover.as_active = enable;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_set, cfg_bts_ho_set_cmd,
- "handover set (full|sub)",
- HANDOVER_STR
- "Define measuement set of TDMA frames\n"
- "Full set of 102/104 TDMA frames\n"
- "Sub set of 4 TDMA frames (SACCH)")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.full = (argv[0][0]=='f');
- return CMD_SUCCESS;
-}
-
-#define HO_MIN_STR HANDOVER_STR "Minimum Values\n"
-#define HO_MAX_STR HANDOVER_STR "Maximum Values\n"
-#define HO_MIN_FREE_STR HO_MIN_STR "Minimum free Slots\n"
-#define HO_WIN_STR HANDOVER_STR "Measurement Window\n"
-#define HO_WIN_RXLEV_STR HO_WIN_STR "Received Level Averaging\n"
-#define HO_WIN_RXQUAL_STR HO_WIN_STR "Received Quality Averaging\n"
-#define HO_PBUDGET_STR HANDOVER_STR "Power Budget\n"
-#define HO_AFS_STR HANDOVER_STR "AMR on TCH/F\n"
-#define HO_PENALTY_STR HANDOVER_STR "Penalty Time\n"
-#define HO_AVG_COUNT_STR "Amount to use for Averaging\n"
-
-DEFUN(cfg_bts_ho_min_rxlev, cfg_bts_ho_min_rxlev_cmd,
- "handover min rxlev <-110-50>",
- HO_MIN_STR
- "The minimum RxLev allowed in this cell\n"
- "Minimum RxLev in dBm")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.min_rxlev = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_win_rxlev_avg, cfg_bts_ho_win_rxlev_avg_cmd,
- "handover window rxlev averaging <1-10>",
- HO_WIN_RXLEV_STR
- "How many RxLev measurements are used for averaging\n"
- HO_AVG_COUNT_STR)
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.win_rxlev_avg = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_win_rxlev_neigh_avg, cfg_bts_ho_win_rxlev_avg_neigh_cmd,
- "handover window rxlev neighbor averaging <1-10>",
- HO_WIN_RXLEV_STR "Neighbor\n"
- "How many RxQual measurements are used for averaging\n"
- HO_AVG_COUNT_STR)
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.win_rxlev_avg_neigh = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_pwr_hysteresis, cfg_bts_ho_pwr_hysteresis_cmd,
- "handover power budget hysteresis <0-999>",
- HO_PBUDGET_STR
- "How many dB does a neighbor to be stronger to become a HO candidate\n"
- "Hysteresis\n" "Number\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.pwr_hysteresis = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_pwr_interval, cfg_bts_ho_pwr_interval_cmd,
- "handover power budget interval <1-99>",
- HO_PBUDGET_STR
- "How often to check if we have a better cell (SACCH frames)\n"
- "Interval\n" "Number\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.pwr_interval = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_afs_rxlev_improve, cfg_bts_ho_afs_rxlev_improve_cmd,
- "handover afs rxlev improvement <0-20>",
- HO_AFS_STR
- "RxLev\n"
- "Improvement of RxLev over other codecs\n"
- "RxLev in dB")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.afs_rxlev_improve = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_min_rxqual, cfg_bts_ho_min_rxqual_cmd,
- "handover min rxqual <0-7>",
- HO_MIN_STR
- "The minimum RxQual allowed in this cell\n"
- "Minimum RxQual in dBm")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.min_rxqual = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_win_rxqual_avg, cfg_bts_ho_win_rxqual_avg_cmd,
- "handover window rxqual averaging <1-10>",
- HO_WIN_RXQUAL_STR
- "How many RxQual measurements are used for averaging\n"
- HO_AVG_COUNT_STR)
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.win_rxqual_avg = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_afs_rxqual_improve, cfg_bts_ho_afs_rxqual_improve_cmd,
- "handover afs rxqual improvement <0-7>",
- HO_AFS_STR
- "RxQual\n"
- "Improvement of RxQual over other codecs\n"
- "RxQual in dB")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.afs_rxqual_improve = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_max_distance, cfg_bts_ho_max_distance_cmd,
- "handover maximum distance <0-9999>",
- HANDOVER_STR
- "How big is the maximum timing advance before HO is forced\n"
- "Distance\n" "Number\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.max_distance = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_min_free_tchf, cfg_bts_ho_min_free_tchf_cmd,
- "handover min free tch-f <0-9999>",
- HO_MIN_FREE_STR
- "Minimum free TCH/F timeslots before cell is congeted\n"
- "Slots\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.min_free_tchf = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_min_free_tchh, cfg_bts_ho_min_free_tchh_cmd,
- "handover min free tch-h <0-9999>",
- HO_MIN_FREE_STR
- "Minimum free TCH/H timeslots before cell is congeted\n"
- "Slots\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.min_free_tchh = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_max_unsync_ho, cfg_bts_ho_max_unsync_ho_cmd,
- "handover max unsync handovers <0-9999>",
- HO_MAX_STR
- "Maximum unsynchronous handovers\n"
- "Handovers\nNumber\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.max_unsync_ho = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_penalty_max_dist, cfg_bts_ho_penalty_max_dist_cmd,
- "handover penalty max distance <0-99999>",
- HO_PENALTY_STR
- "After leaving this cell due to exceeding the maximum allowed distance\n"
- "Distance\nTime in Seconds\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.penalty_max_dist = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_penalty_ho_fail, cfg_bts_ho_penalty_ho_fail_cmd,
- "handover penalty handover failure <0-99999>",
- HO_PENALTY_STR
- "After handover failure to this cell\n"
- "Failure\nTime in Seconds\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.penalty_ho_fail = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_bts_ho_penalty_as_fail, cfg_bts_ho_penalty_as_fail_cmd,
- "handover penalty assignment failure <0-99999>",
- HO_PENALTY_STR
- "After assignment failure in this cell\n"
- "Failure\nTime in Seconds\n")
-{
- struct gsm_bts *bts = vty->index;
- bts->handover.penalty_as_fail = atoi(argv[0]);
- return CMD_SUCCESS;
-}
-
#define TRX_TEXT "Radio Transceiver\n"
/* per TRX configuration */
@@ -3994,7 +3697,6 @@ int bsc_vty_init(const struct log_info *cat)
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
install_element(GSMNET_NODE, &cfg_net_dtx_cmd);
install_element(GSMNET_NODE, &cfg_net_subscr_keep_cmd);
- install_element(GSMNET_NODE, &cfg_net_ho_congest_timer_cmd);
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
@@ -4086,25 +3788,6 @@ int bsc_vty_init(const struct log_info *cat)
install_element(BTS_NODE, &cfg_bts_amr_hr_hyst2_cmd);
install_element(BTS_NODE, &cfg_bts_amr_hr_hyst3_cmd);
install_element(BTS_NODE, &cfg_bts_amr_hr_start_mode_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_handover_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_assignment_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_set_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_min_rxlev_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_win_rxlev_avg_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_win_rxlev_avg_neigh_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_pwr_hysteresis_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_pwr_interval_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_afs_rxlev_improve_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_min_rxqual_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_win_rxqual_avg_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_afs_rxqual_improve_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_max_distance_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_min_free_tchf_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_min_free_tchh_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_max_unsync_ho_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_penalty_max_dist_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_penalty_ho_fail_cmd);
- install_element(BTS_NODE, &cfg_bts_ho_penalty_as_fail_cmd);
install_element(BTS_NODE, &cfg_trx_cmd);
install_node(&trx_node, dummy_config_write);
@@ -4144,5 +3827,7 @@ int bsc_vty_init(const struct log_info *cat)
bsc_vty_init_extra();
+ bsc_vty_init_handover();
+
return 0;
}
diff --git a/openbsc/src/libbsc/handover_decision.c b/openbsc/src/libbsc/handover_decision_1.c
index 5f9a2c3af..aae56f0d1 100644
--- a/openbsc/src/libbsc/handover_decision.c
+++ b/openbsc/src/libbsc/handover_decision_1.c
@@ -299,7 +299,7 @@ static int ho_dec_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
-void on_dso_load_ho_dec(void)
+void init_ho_1(void)
{
osmo_signal_register_handler(SS_LCHAN, ho_dec_sig_cb, NULL);
}
diff --git a/openbsc/src/libbsc/handover_vty.c b/openbsc/src/libbsc/handover_vty.c
new file mode 100644
index 000000000..e20773353
--- /dev/null
+++ b/openbsc/src/libbsc/handover_vty.c
@@ -0,0 +1,511 @@
+/* OpenBSC interface to quagga VTY */
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ * 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/misc.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/vty.h>
+#include <openbsc/handover_decision.h>
+
+void bts_dump_vty_handover(struct vty *vty, struct gsm_bts *bts)
+{
+ int algorithm = bts->network->ho_algorithm;
+
+ if (algorithm == 1 || algorithm == 2)
+ vty_out(vty, " Handover: %s%s",
+ bts->handover.ho_active ? "On" : "Off", VTY_NEWLINE);
+ if (algorithm == 2)
+ vty_out(vty, " Assignment: %s%s",
+ bts->handover.as_active ? "On" : "Off", VTY_NEWLINE);
+}
+
+void config_write_bts_handover(struct vty *vty, struct gsm_bts *bts)
+{
+ int algorithm = bts->network->ho_algorithm;
+
+ if (algorithm == 1 || algorithm == 2)
+ vty_out(vty, " handover enable handover %u%s",
+ bts->handover.ho_active, VTY_NEWLINE);
+ if (algorithm == 2) {
+ vty_out(vty, " handover enable assignment %u%s",
+ bts->handover.as_active, VTY_NEWLINE);
+ vty_out(vty, " handover set %s%s",
+ (bts->handover.full) ? "full" : "sub", VTY_NEWLINE);
+ vty_out(vty, " handover min rxlev %d%s",
+ bts->handover.min_rxlev, VTY_NEWLINE);
+ }
+ if (algorithm == 1 || algorithm == 2) {
+ vty_out(vty, " handover window rxlev averaging %u%s",
+ bts->handover.win_rxlev_avg, VTY_NEWLINE);
+ vty_out(vty, " handover window rxlev neighbor averaging %u%s",
+ bts->handover.win_rxlev_avg_neigh, VTY_NEWLINE);
+ vty_out(vty, " handover power budget hysteresis %u%s",
+ bts->handover.pwr_hysteresis, VTY_NEWLINE);
+ vty_out(vty, " handover power budget interval %u%s",
+ bts->handover.pwr_interval, VTY_NEWLINE);
+ }
+ if (algorithm == 2) {
+ vty_out(vty, " handover afs rxlev improvement %u%s",
+ bts->handover.afs_rxlev_improve, VTY_NEWLINE);
+ vty_out(vty, " handover min rxqual %u%s",
+ bts->handover.min_rxqual, VTY_NEWLINE);
+ vty_out(vty, " handover window rxqual averaging %u%s",
+ bts->handover.win_rxqual_avg, VTY_NEWLINE);
+ vty_out(vty, " handover afs rxqual improvement %u%s",
+ bts->handover.afs_rxqual_improve, VTY_NEWLINE);
+ }
+ if (algorithm == 1 || algorithm == 2)
+ vty_out(vty, " handover maximum distance %u%s",
+ bts->handover.max_distance, VTY_NEWLINE);
+ if (algorithm == 2) {
+ vty_out(vty, " handover min free tch-f %u%s",
+ bts->handover.min_free_tchf, VTY_NEWLINE);
+ vty_out(vty, " handover min free tch-h %u%s",
+ bts->handover.min_free_tchh, VTY_NEWLINE);
+ vty_out(vty, " handover max unsync handovers %u%s",
+ bts->handover.max_unsync_ho, VTY_NEWLINE);
+ vty_out(vty, " handover penalty max distance %u%s",
+ bts->handover.penalty_max_dist, VTY_NEWLINE);
+ vty_out(vty, " handover penalty handover failure %u%s",
+ bts->handover.penalty_ho_fail, VTY_NEWLINE);
+ vty_out(vty, " handover penalty assignment failure %u%s",
+ bts->handover.penalty_as_fail, VTY_NEWLINE);
+ }
+}
+
+void config_write_net_handover(struct vty *vty)
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ int algorithm = gsmnet->ho_algorithm;
+
+ if (algorithm == 1 || algorithm == 2)
+ vty_out(vty, " handover algorithm %d%s", gsmnet->ho_algorithm,
+ VTY_NEWLINE);
+ if (algorithm == 2)
+ vty_out(vty, " handover congestion-check-timer %u%s",
+ gsmnet->ho_congest_timeout, VTY_NEWLINE);
+}
+
+/* check if given algorithm is set, otherwise reject command */
+int is_cmd_for_algorithm(struct vty *vty, int for_1, int for_2)
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ int algorithm = gsmnet->ho_algorithm;
+
+ switch (algorithm) {
+ case 1:
+ if (for_1)
+ break;
+ vty_out(vty, "%% Given command is not allowed for selected "
+ "handover algorithm 1%s\n", VTY_NEWLINE);
+ return -EINVAL;
+ case 2:
+ if (for_2)
+ break;
+ vty_out(vty, "%% Given command is not allowed for selected "
+ "handover algorithm 2%s\n", VTY_NEWLINE);
+ return -EINVAL;
+ default:
+ vty_out(vty, "%% Please define handover algorithm before "
+ "giving handover config command%s\n", VTY_NEWLINE);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Per network configuration */
+#define NET_HO_STR "Global handover settings.\n"
+DEFUN(cfg_net_ho_algorithm,
+ cfg_net_ho_algorithm_cmd,
+ "handover algorithm (1|2)",
+ NET_HO_STR
+ "Handover algorithm selection\n"
+ "Algorithm 1\nAlgorithm 2")
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
+ gsmnet->ho_algorithm = atoi(argv[0]);
+ switch (gsmnet->ho_algorithm) {
+ case 1:
+ init_ho_1();
+ break;
+ case 2:
+// init_ho_2();
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_ho_congest_timer,
+ cfg_net_ho_congest_timer_cmd,
+ "handover congestion-check-timer <0-60>",
+ NET_HO_STR
+ "Handover congestion check timer\n"
+ "Time in seconds for congestion check interval (0 to disable)\n")
+{
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ gsmnet->ho_congest_timeout = atoi(argv[0]);
+ switch (gsmnet->ho_algorithm) {
+ case 2:
+// init_ho_timer_2();
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+/* Per BTS configuration */
+#define HANDOVER_STR "Handover Options\n"
+#define HO_ENABLE_STR HANDOVER_STR "Enable or disable handover/assignment\n"
+
+DEFUN(cfg_bts_ho_handover, cfg_bts_ho_handover_cmd,
+ "handover enable handover (0|1)",
+ HO_ENABLE_STR
+ "Enable or disable handover\n"
+ "Don't perform in-call handover\n"
+ "Perform in-call handover\n")
+{
+ int enable = atoi(argv[0]);
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ if (enable && ipacc_rtp_direct) {
+ vty_out(vty, "%% Cannot enable handover unless RTP Proxy mode "
+ "is enabled by using the -P command line option%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ bts->handover.ho_active = enable;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_assignment, cfg_bts_ho_assignment_cmd,
+ "handover enable assignment (0|1)",
+ HO_ENABLE_STR
+ "Enable or disable assignment\n"
+ "Don't perform in-call assignment\n"
+ "Perform in-call assignment\n")
+{
+ int enable = atoi(argv[0]);
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ if (enable && ipacc_rtp_direct) {
+ vty_out(vty, "%% Cannot enable assignment unless RTP Proxy mode "
+ "is enabled by using the -P command line option%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ bts->handover.as_active = enable;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_set, cfg_bts_ho_set_cmd,
+ "handover set (full|sub)",
+ HANDOVER_STR
+ "Define measuement set of TDMA frames\n"
+ "Full set of 102/104 TDMA frames\n"
+ "Sub set of 4 TDMA frames (SACCH)")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.full = (argv[0][0]=='f');
+ return CMD_SUCCESS;
+}
+
+#define HO_MIN_STR HANDOVER_STR "Minimum Values\n"
+#define HO_MAX_STR HANDOVER_STR "Maximum Values\n"
+#define HO_MIN_FREE_STR HO_MIN_STR "Minimum free Slots\n"
+#define HO_WIN_STR HANDOVER_STR "Measurement Window\n"
+#define HO_WIN_RXLEV_STR HO_WIN_STR "Received Level Averaging\n"
+#define HO_WIN_RXQUAL_STR HO_WIN_STR "Received Quality Averaging\n"
+#define HO_PBUDGET_STR HANDOVER_STR "Power Budget\n"
+#define HO_AFS_STR HANDOVER_STR "AMR on TCH/F\n"
+#define HO_PENALTY_STR HANDOVER_STR "Penalty Time\n"
+#define HO_AVG_COUNT_STR "Amount to use for Averaging\n"
+
+DEFUN(cfg_bts_ho_min_rxlev, cfg_bts_ho_min_rxlev_cmd,
+ "handover min rxlev <-110-50>",
+ HO_MIN_STR
+ "The minimum RxLev allowed in this cell\n"
+ "Minimum RxLev in dBm")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.min_rxlev = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_win_rxlev_avg, cfg_bts_ho_win_rxlev_avg_cmd,
+ "handover window rxlev averaging <1-10>",
+ HO_WIN_RXLEV_STR
+ "How many RxLev measurements are used for averaging\n"
+ HO_AVG_COUNT_STR)
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ bts->handover.win_rxlev_avg = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_win_rxlev_neigh_avg, cfg_bts_ho_win_rxlev_avg_neigh_cmd,
+ "handover window rxlev neighbor averaging <1-10>",
+ HO_WIN_RXLEV_STR "Neighbor\n"
+ "How many RxQual measurements are used for averaging\n"
+ HO_AVG_COUNT_STR)
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ bts->handover.win_rxlev_avg_neigh = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_pwr_hysteresis, cfg_bts_ho_pwr_hysteresis_cmd,
+ "handover power budget hysteresis <0-999>",
+ HO_PBUDGET_STR
+ "How many dB does a neighbor to be stronger to become a HO candidate\n"
+ "Hysteresis\n" "Number\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ bts->handover.pwr_hysteresis = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_pwr_interval, cfg_bts_ho_pwr_interval_cmd,
+ "handover power budget interval <1-99>",
+ HO_PBUDGET_STR
+ "How often to check if we have a better cell (SACCH frames)\n"
+ "Interval\n" "Number\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ bts->handover.pwr_interval = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_afs_rxlev_improve, cfg_bts_ho_afs_rxlev_improve_cmd,
+ "handover afs rxlev improvement <0-20>",
+ HO_AFS_STR
+ "RxLev\n"
+ "Improvement of RxLev over other codecs\n"
+ "RxLev in dB")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.afs_rxlev_improve = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_min_rxqual, cfg_bts_ho_min_rxqual_cmd,
+ "handover min rxqual <0-7>",
+ HO_MIN_STR
+ "The minimum RxQual allowed in this cell\n"
+ "Minimum RxQual in dBm")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.min_rxqual = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_win_rxqual_avg, cfg_bts_ho_win_rxqual_avg_cmd,
+ "handover window rxqual averaging <1-10>",
+ HO_WIN_RXQUAL_STR
+ "How many RxQual measurements are used for averaging\n"
+ HO_AVG_COUNT_STR)
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.win_rxqual_avg = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_afs_rxqual_improve, cfg_bts_ho_afs_rxqual_improve_cmd,
+ "handover afs rxqual improvement <0-7>",
+ HO_AFS_STR
+ "RxQual\n"
+ "Improvement of RxQual over other codecs\n"
+ "RxQual in dB")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.afs_rxqual_improve = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_max_distance, cfg_bts_ho_max_distance_cmd,
+ "handover maximum distance <0-9999>",
+ HANDOVER_STR
+ "How big is the maximum timing advance before HO is forced\n"
+ "Distance\n" "Number\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 1, 1))
+ return CMD_WARNING;
+ bts->handover.max_distance = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_min_free_tchf, cfg_bts_ho_min_free_tchf_cmd,
+ "handover min free tch-f <0-9999>",
+ HO_MIN_FREE_STR
+ "Minimum free TCH/F timeslots before cell is congeted\n"
+ "Slots\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.min_free_tchf = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_min_free_tchh, cfg_bts_ho_min_free_tchh_cmd,
+ "handover min free tch-h <0-9999>",
+ HO_MIN_FREE_STR
+ "Minimum free TCH/H timeslots before cell is congeted\n"
+ "Slots\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.min_free_tchh = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_max_unsync_ho, cfg_bts_ho_max_unsync_ho_cmd,
+ "handover max unsync handovers <0-9999>",
+ HO_MAX_STR
+ "Maximum unsynchronous handovers\n"
+ "Handovers\nNumber\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.max_unsync_ho = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_penalty_max_dist, cfg_bts_ho_penalty_max_dist_cmd,
+ "handover penalty max distance <0-99999>",
+ HO_PENALTY_STR
+ "After leaving this cell due to exceeding the maximum allowed distance\n"
+ "Distance\nTime in Seconds\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.penalty_max_dist = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_penalty_ho_fail, cfg_bts_ho_penalty_ho_fail_cmd,
+ "handover penalty handover failure <0-99999>",
+ HO_PENALTY_STR
+ "After handover failure to this cell\n"
+ "Failure\nTime in Seconds\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.penalty_ho_fail = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_ho_penalty_as_fail, cfg_bts_ho_penalty_as_fail_cmd,
+ "handover penalty assignment failure <0-99999>",
+ HO_PENALTY_STR
+ "After assignment failure in this cell\n"
+ "Failure\nTime in Seconds\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (is_cmd_for_algorithm(vty, 0, 1))
+ return CMD_WARNING;
+ bts->handover.penalty_as_fail = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
+void bsc_vty_init_handover(void)
+{
+ install_element(GSMNET_NODE, &cfg_net_ho_algorithm_cmd);
+ install_element(GSMNET_NODE, &cfg_net_ho_congest_timer_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_handover_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_assignment_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_set_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_min_rxlev_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_win_rxlev_avg_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_win_rxlev_avg_neigh_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_pwr_hysteresis_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_pwr_interval_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_afs_rxlev_improve_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_min_rxqual_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_win_rxqual_avg_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_afs_rxqual_improve_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_max_distance_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_min_free_tchf_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_min_free_tchh_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_max_unsync_ho_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_penalty_max_dist_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_penalty_ho_fail_cmd);
+ install_element(BTS_NODE, &cfg_bts_ho_penalty_as_fail_cmd);
+}
+
diff --git a/openbsc/src/osmo-nitb/bsc_hack.c b/openbsc/src/osmo-nitb/bsc_hack.c
index 172fb8269..ea5d327a9 100644
--- a/openbsc/src/osmo-nitb/bsc_hack.c
+++ b/openbsc/src/osmo-nitb/bsc_hack.c
@@ -252,7 +252,6 @@ int main(int argc, char **argv)
talloc_ctx_init();
on_dso_load_token();
on_dso_load_rrlp();
- on_dso_load_ho_dec();
libosmo_abis_init(tall_bsc_ctx);
osmo_init_logging(&log_info);