From 170619fef674a982d631d83d0c869cf99c56f711 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 11 May 2010 23:50:21 +0200 Subject: [gprs] NS/BSSGP: Make all timers configurable from VTY --- openbsc/include/openbsc/gsm_data.h | 2 + openbsc/src/bsc_init.c | 4 + openbsc/src/gsm_data.c | 8 ++ openbsc/src/vty_interface.c | 160 ++++++++++++++++++++++++++++++------- 4 files changed, 144 insertions(+), 30 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 4e73fd4f2..a3ebbbc9f 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -515,10 +515,12 @@ struct gsm_bts { struct { struct gsm_nm_state nm_state; u_int16_t nsei; + uint8_t timer[7]; } nse; struct { struct gsm_nm_state nm_state; u_int16_t bvci; + uint8_t timer[11]; } cell; struct gsm_bts_gprs_nsvc nsvc[2]; u_int8_t rac; diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index a2546808f..13d924ede 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -884,6 +884,10 @@ static void patch_nm_tables(struct gsm_bts *bts) /* patch NSEI */ nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8; nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff; + memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer, + ARRAY_SIZE(bts->gprs.nse.timer)); + memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer, + ARRAY_SIZE(bts->gprs.cell.timer)); /* patch NSVCI */ nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8; diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 0ac7041be..b54dd84cd 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -172,6 +172,10 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts) return trx; } +static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 }; +static const uint8_t bts_cell_timer_default[] = + { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 }; + struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type, u_int8_t tsc, u_int8_t bsic) { @@ -213,6 +217,10 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type, bts->gprs.nsvc[i].bts = bts; bts->gprs.nsvc[i].id = i; } + memcpy(&bts->gprs.nse.timer, bts_nse_timer_default, + sizeof(bts->gprs.nse.timer)); + memcpy(&bts->gprs.cell.timer, bts_cell_timer_default, + sizeof(bts->gprs.cell.timer)); /* create our primary TRX */ bts->c0 = gsm_bts_trx_alloc(bts); diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index d16cc61f3..0ee1f13cc 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -45,6 +45,32 @@ static struct gsm_network *gsmnet; +static struct value_string gprs_ns_timer_strs[] = { + { 0, "tns-block" }, + { 1, "tns-block-retries" }, + { 2, "tns-reset" }, + { 3, "tns-reset-retries" }, + { 4, "tns-test" }, + { 5, "tns-alive" }, + { 6, "tns-alive-retries" }, + { 0, NULL } +}; + +static struct value_string gprs_bssgp_cfg_strs[] = { + { 0, "blocking-timer" }, + { 1, "blocking-retries" }, + { 2, "unblocking-retries" }, + { 3, "reset-timer" }, + { 4, "reset-retries" }, + { 5, "suspend-timer" }, + { 6, "suspend-retries" }, + { 7, "resume-timer" }, + { 8, "resume-retries" }, + { 9, "capability-update-timer" }, + { 10, "capability-update-retries" }, + { 0, NULL } +}; + struct cmd_node net_node = { GSMNET_NODE, "%s(network)#", @@ -322,10 +348,48 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx) config_write_ts_single(vty, &trx->ts[i]); } +static void config_write_bts_gprs(struct vty *vty, struct gsm_bts *bts) +{ + unsigned int i; + vty_out(vty, " gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode), + VTY_NEWLINE); + if (bts->gprs.mode == BTS_GPRS_NONE) + return; + + vty_out(vty, " gprs routing area %u%s", bts->gprs.rac, + VTY_NEWLINE); + vty_out(vty, " gprs cell bvci %u%s", bts->gprs.cell.bvci, + VTY_NEWLINE); + for (i = 0; i < ARRAY_SIZE(bts->gprs.cell.timer); i++) + vty_out(vty, " gprs cell timer %s %u%s", + get_value_string(gprs_bssgp_cfg_strs, i), + bts->gprs.cell.timer[i], VTY_NEWLINE); + vty_out(vty, " gprs nsei %u%s", bts->gprs.nse.nsei, + VTY_NEWLINE); + for (i = 0; i < ARRAY_SIZE(bts->gprs.nse.timer); i++) + vty_out(vty, " gprs ns timer %s %u%s", + get_value_string(gprs_ns_timer_strs, i), + bts->gprs.nse.timer[i], VTY_NEWLINE); + for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) { + struct gsm_bts_gprs_nsvc *nsvc = + &bts->gprs.nsvc[i]; + struct in_addr ia; + + ia.s_addr = htonl(nsvc->remote_ip); + vty_out(vty, " gprs nsvc %u nsvci %u%s", i, + nsvc->nsvci, VTY_NEWLINE); + vty_out(vty, " gprs nsvc %u local udp port %u%s", i, + nsvc->local_port, VTY_NEWLINE); + vty_out(vty, " gprs nsvc %u remote udp port %u%s", i, + nsvc->remote_port, VTY_NEWLINE); + vty_out(vty, " gprs nsvc %u remote ip %s%s", i, + inet_ntoa(ia), VTY_NEWLINE); + } +} + static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) { struct gsm_bts_trx *trx; - int i; vty_out(vty, " bts %u%s", bts->nr, VTY_NEWLINE); vty_out(vty, " type %s%s", btstype2str(bts->type), VTY_NEWLINE); @@ -371,35 +435,12 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE); } + config_write_bts_gprs(vty, bts); + /* if we have a limit, write it */ if (bts->paging.free_chans_need >= 0) vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE); - vty_out(vty, " gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode), - VTY_NEWLINE); - if (bts->gprs.mode != BTS_GPRS_NONE) { - vty_out(vty, " gprs routing area %u%s", bts->gprs.rac, - VTY_NEWLINE); - vty_out(vty, " gprs cell bvci %u%s", bts->gprs.cell.bvci, - VTY_NEWLINE); - vty_out(vty, " gprs nsei %u%s", bts->gprs.nse.nsei, - VTY_NEWLINE); - for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) { - struct gsm_bts_gprs_nsvc *nsvc = - &bts->gprs.nsvc[i]; - struct in_addr ia; - - ia.s_addr = htonl(nsvc->remote_ip); - vty_out(vty, " gprs nsvc %u nsvci %u%s", i, - nsvc->nsvci, VTY_NEWLINE); - vty_out(vty, " gprs nsvc %u local udp port %u%s", i, - nsvc->local_port, VTY_NEWLINE); - vty_out(vty, " gprs nsvc %u remote udp port %u%s", i, - nsvc->remote_port, VTY_NEWLINE); - vty_out(vty, " gprs nsvc %u remote ip %s%s", i, - inet_ntoa(ia), VTY_NEWLINE); - } - } llist_for_each_entry(trx, &bts->trx_list, list) config_write_trx_single(vty, trx); @@ -1843,13 +1884,61 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd, return CMD_SUCCESS; } -DEFUN(cfg_bts_pag_free, cfg_bts_pag_free_cmd, - "paging free FREE_NR", - "Only page when having a certain amount of free slots. -1 to disable") +#define GPRS_TEXT "GPRS Packet Network\n" +#define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries)" +#define NS_TIMERS_HELP \ + "(un)blocking Timer (Tns-block) timeout\n" \ + "(un)blocking Timer (Tns-block) number of retries\n" \ + "Reset Timer (Tns-reset) timeout\n" \ + "Reset Timer (Tns-reset) number of retries\n" \ + "Test Timer (Tns-test) timeout\n" \ + +DEFUN(cfg_bts_gprs_ns_timer, cfg_bts_gprs_ns_timer_cmd, + "gprs ns timer " NS_TIMERS " <0-255>", + GPRS_TEXT "Network Service\n" + "Network Service Timer\n" + NS_TIMERS_HELP "Timer Value\n") { struct gsm_bts *bts = vty->index; + int idx = get_string_value(gprs_ns_timer_strs, argv[0]); + int val = atoi(argv[1]); + + if (bts->gprs.mode == BTS_GPRS_NONE) { + vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.nse.timer)) + return CMD_WARNING; + + bts->gprs.nse.timer[idx] = val; + + return CMD_SUCCESS; +} + +#define BSSGP_TIMERS "(blocking-timer|blocking-retries|unblocking-retries|reset-timer|reset-retries|suspend-timer|suspend-retries|resume-timer|resume-retries|capability-update-timer|capability-update-retries)" +#define BSSGP_TIMERS_HELP "" + +DEFUN(cfg_bts_gprs_cell_timer, cfg_bts_gprs_cell_timer_cmd, + "gprs cell timer " BSSGP_TIMERS " <0-255>", + GPRS_TEXT "Cell / BSSGP\n" + "Cell/BSSGP Timer\n" + BSSGP_TIMERS_HELP "Timer Value\n") +{ + struct gsm_bts *bts = vty->index; + int idx = get_string_value(gprs_bssgp_cfg_strs, argv[0]); + int val = atoi(argv[1]); + + if (bts->gprs.mode == BTS_GPRS_NONE) { + vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (idx < 0 || idx >= ARRAY_SIZE(bts->gprs.cell.timer)) + return CMD_WARNING; + + bts->gprs.cell.timer[idx] = val; - bts->paging.free_chans_need = atoi(argv[0]); return CMD_SUCCESS; } @@ -1880,6 +1969,15 @@ DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_pag_free, cfg_bts_pag_free_cmd, + "paging free FREE_NR", + "Only page when having a certain amount of free slots. -1 to disable") +{ + struct gsm_bts *bts = vty->index; + + bts->paging.free_chans_need = atoi(argv[0]); + return CMD_SUCCESS; +} /* per TRX configuration */ DEFUN(cfg_trx, @@ -2154,8 +2252,10 @@ int bsc_vty_init(struct gsm_network *net) install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd); install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd); install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd); + install_element(BTS_NODE, &cfg_bts_gprs_ns_timer_cmd); install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd); install_element(BTS_NODE, &cfg_bts_gprs_bvci_cmd); + install_element(BTS_NODE, &cfg_bts_gprs_cell_timer_cmd); install_element(BTS_NODE, &cfg_bts_gprs_nsei_cmd); install_element(BTS_NODE, &cfg_bts_gprs_nsvci_cmd); install_element(BTS_NODE, &cfg_bts_gprs_nsvc_lport_cmd); -- cgit v1.2.3