From 144e0295c2c92470756cb2d386c136810fcd4a91 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 11:45:07 +0200 Subject: [GPRS] NS: Start to use rate_ctr_group code from libosmocore Every NS-VC now has a set of counters for incoming and outgoing number of packets and bytes. We also split the VTY part of the gprs_ns.c implementation into gprs_ns_vty.c to make sure the protocol can actually be used without the VTY code being present. --- openbsc/src/gprs/gprs_ns_vty.c | 275 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 openbsc/src/gprs/gprs_ns_vty.c (limited to 'openbsc/src/gprs/gprs_ns_vty.c') diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c new file mode 100644 index 00000000..6e98e44d --- /dev/null +++ b/openbsc/src/gprs/gprs_ns_vty.c @@ -0,0 +1,275 @@ +/* VTY interface for our GPRS Networks Service (NS) implementation */ + +/* (C) 2009-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static struct gprs_ns_inst *vty_nsi = NULL; + +/* FIXME: this should go to some common file as it is copied + * in vty_interface.c of the BSC */ +static const 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 cmd_node ns_node = { + NS_NODE, + "%s(ns)#", + 1, +}; + +static int config_write_ns(struct vty *vty) +{ + struct gprs_nsvc *nsvc; + unsigned int i; + + vty_out(vty, "ns%s", VTY_NEWLINE); + + llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) { + if (!nsvc->persistent) + continue; + vty_out(vty, " nse %u nsvci %u%s", + nsvc->nsei, nsvc->nsvci, VTY_NEWLINE); + vty_out(vty, " nse %u remote-role %s%s", + nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss", + VTY_NEWLINE); + if (nsvc->nsi->ll == GPRS_NS_LL_UDP) { + vty_out(vty, " nse %u remote-ip %s%s", + nsvc->nsei, + inet_ntoa(nsvc->ip.bts_addr.sin_addr), + VTY_NEWLINE); + vty_out(vty, " nse %u remote-port %u%s", + nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port), + VTY_NEWLINE); + } + } + + for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++) + vty_out(vty, " timer %s %u%s", + get_value_string(gprs_ns_timer_strs, i), + vty_nsi->timeout[i], VTY_NEWLINE); + + return CMD_SUCCESS; +} + +DEFUN(cfg_ns, cfg_ns_cmd, + "ns", + "Configure the GPRS Network Service") +{ + vty->node = NS_NODE; + return CMD_SUCCESS; +} + +DEFUN(show_ns, show_ns_cmd, "show ns", + SHOW_STR "Display information about the NS protocol") +{ + struct gprs_ns_inst *nsi = vty_nsi; + struct gprs_nsvc *nsvc; + + llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s", + nsvc->nsei, nsvc->nsvci, + nsvc->remote_end_is_sgsn ? "SGSN" : "BSS", + nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD", + nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED"); + if (nsvc->nsi->ll == GPRS_NS_LL_UDP) + vty_out(vty, ", %15s:%u", + inet_ntoa(nsvc->ip.bts_addr.sin_addr), + ntohs(nsvc->ip.bts_addr.sin_port)); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out_rate_ctr_group(vty, " ", nsvc->ctrg); + } + + return CMD_SUCCESS; +} + + +#define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n" + +DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd, + "nse <0-65535> nsvci <0-65534>", + NSE_CMD_STR + "NS Virtual Connection\n" + "NS Virtual Connection ID (NSVCI)\n" + ) +{ + uint16_t nsei = atoi(argv[0]); + uint16_t nsvci = atoi(argv[1]); + struct gprs_nsvc *nsvc; + + nsvc = nsvc_by_nsei(vty_nsi, nsei); + if (!nsvc) { + nsvc = nsvc_create(vty_nsi, nsvci); + nsvc->nsei = nsei; + } + nsvc->nsvci = nsvci; + /* All NSVCs that are explicitly configured by VTY are + * marked as persistent so we can write them to the config + * file at some later point */ + nsvc->persistent = 1; + + return CMD_SUCCESS; +} + +DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd, + "nse <0-65535> remote-ip A.B.C.D", + NSE_CMD_STR + "Remote IP Address\n" + "Remote IP Address\n") +{ + uint16_t nsei = atoi(argv[0]); + struct gprs_nsvc *nsvc; + + nsvc = nsvc_by_nsei(vty_nsi, nsei); + if (!nsvc) { + vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE); + return CMD_WARNING; + } + inet_aton(argv[1], &nsvc->ip.bts_addr.sin_addr); + + return CMD_SUCCESS; + +} + +DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd, + "nse <0-65535> remote-port <0-65535>", + NSE_CMD_STR + "Remote UDP Port\n" + "Remote UDP Port Number\n") +{ + uint16_t nsei = atoi(argv[0]); + uint16_t port = atoi(argv[1]); + struct gprs_nsvc *nsvc; + + nsvc = nsvc_by_nsei(vty_nsi, nsei); + if (!nsvc) { + vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE); + return CMD_WARNING; + } + + nsvc->ip.bts_addr.sin_port = htons(port); + + return CMD_SUCCESS; +} + +DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd, + "nse <0-65535> remote-role (sgsn|bss)", + NSE_CMD_STR + "Remote NSE Role\n" + "Remote Peer is SGSN\n" + "Remote Peer is BSS\n") +{ + uint16_t nsei = atoi(argv[0]); + struct gprs_nsvc *nsvc; + + nsvc = nsvc_by_nsei(vty_nsi, nsei); + if (!nsvc) { + vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strcmp(argv[1], "sgsn")) + nsvc->remote_end_is_sgsn = 1; + else + nsvc->remote_end_is_sgsn = 0; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_nse, cfg_no_nse_cmd, + "no nse <0-65535>", + "Delete NS Entity\n" + "Delete " NSE_CMD_STR) +{ + uint16_t nsei = atoi(argv[0]); + struct gprs_nsvc *nsvc; + + nsvc = nsvc_by_nsei(vty_nsi, nsei); + if (!nsvc) { + vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE); + return CMD_WARNING; + } + + nsvc_delete(nsvc); + + return CMD_SUCCESS; +} + +DEFUN(cfg_ns_timer, cfg_ns_timer_cmd, + "timer " NS_TIMERS " <0-65535>", + "Network Service Timer\n" + NS_TIMERS_HELP "Timer Value\n") +{ + int idx = get_string_value(gprs_ns_timer_strs, argv[0]); + int val = atoi(argv[1]); + + if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout)) + return CMD_WARNING; + + vty_nsi->timeout[idx] = val; + + return CMD_SUCCESS; +} + +int gprs_ns_vty_init(struct gprs_ns_inst *nsi) +{ + vty_nsi = nsi; + + install_element_ve(&show_ns_cmd); + + install_element(CONFIG_NODE, &cfg_ns_cmd); + install_node(&ns_node, config_write_ns); + install_default(NS_NODE); + install_element(NS_NODE, &cfg_nse_nsvci_cmd); + install_element(NS_NODE, &cfg_nse_remoteip_cmd); + install_element(NS_NODE, &cfg_nse_remoteport_cmd); + install_element(NS_NODE, &cfg_nse_remoterole_cmd); + install_element(NS_NODE, &cfg_no_nse_cmd); + install_element(NS_NODE, &cfg_ns_timer_cmd); + + return 0; +} -- cgit v1.2.3 From af1d4cb5a812092152c50f7373e1fa877dc8d060 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 12:32:30 +0200 Subject: [GPRS] NS: Show statistics on VTY only if requested --- openbsc/src/gprs/gprs_ns_vty.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'openbsc/src/gprs/gprs_ns_vty.c') diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c index 6e98e44d..08b0076c 100644 --- a/openbsc/src/gprs/gprs_ns_vty.c +++ b/openbsc/src/gprs/gprs_ns_vty.c @@ -104,10 +104,8 @@ DEFUN(cfg_ns, cfg_ns_cmd, return CMD_SUCCESS; } -DEFUN(show_ns, show_ns_cmd, "show ns", - SHOW_STR "Display information about the NS protocol") +static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats) { - struct gprs_ns_inst *nsi = vty_nsi; struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { @@ -121,12 +119,28 @@ DEFUN(show_ns, show_ns_cmd, "show ns", inet_ntoa(nsvc->ip.bts_addr.sin_addr), ntohs(nsvc->ip.bts_addr.sin_port)); vty_out(vty, "%s", VTY_NEWLINE); - vty_out_rate_ctr_group(vty, " ", nsvc->ctrg); + if (stats) + vty_out_rate_ctr_group(vty, " ", nsvc->ctrg); } +} +DEFUN(show_ns, show_ns_cmd, "show ns", + SHOW_STR "Display information about the NS protocol") +{ + struct gprs_ns_inst *nsi = vty_nsi; + dump_ns(vty, nsi, 0); return CMD_SUCCESS; } +DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats", + SHOW_STR + "Display information about the NS protocol\n" + "Include statistics\n") +{ + struct gprs_ns_inst *nsi = vty_nsi; + dump_ns(vty, nsi, 1); + return CMD_SUCCESS; +} #define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n" @@ -260,6 +274,7 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi) vty_nsi = nsi; install_element_ve(&show_ns_cmd); + install_element_ve(&show_ns_stats_cmd); install_element(CONFIG_NODE, &cfg_ns_cmd); install_node(&ns_node, config_write_ns); -- cgit v1.2.3 From dd1c83c52d66c28583e06ba3b930883b488689ea Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 13 May 2010 13:58:08 +0200 Subject: [GPRS] NS: Fix segfault when receiving message from unknown NS-VC In the previous code we used a static fake_nsvc structure in case we needed to send a message to an unknown NSVC for which we don't have a real 'struct nsvc'. However, since we now have a rate_ctr_group hanging off the nsvc, the fake structure didn't have that. So now we keep a nsi->unknown_nsvc around to be used whenever we need a nsvc but don't have a real one. The gprs_ns_vty.c code explicitly does not list that NSVC in 'show ns' --- openbsc/src/gprs/gprs_ns_vty.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'openbsc/src/gprs/gprs_ns_vty.c') diff --git a/openbsc/src/gprs/gprs_ns_vty.c b/openbsc/src/gprs/gprs_ns_vty.c index 08b0076c..8f0628af 100644 --- a/openbsc/src/gprs/gprs_ns_vty.c +++ b/openbsc/src/gprs/gprs_ns_vty.c @@ -109,6 +109,8 @@ static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats) struct gprs_nsvc *nsvc; llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) { + if (nsvc == nsi->unknown_nsvc) + continue; vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s", nsvc->nsei, nsvc->nsvci, nsvc->remote_end_is_sgsn ? "SGSN" : "BSS", -- cgit v1.2.3