blob: b119dea8c35cb7c6bd4bf4ee34da32c91e08c1a1 [file] [log] [blame]
Harald Welte144e0292010-05-13 11:45:07 +02001/* VTY interface for our GPRS Networks Service (NS) implementation */
2
3/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdlib.h>
24#include <unistd.h>
25#include <errno.h>
26#include <stdint.h>
27
28#include <arpa/inet.h>
29
30#include <openbsc/gsm_data.h>
31#include <osmocore/msgb.h>
32#include <osmocore/tlv.h>
33#include <osmocore/talloc.h>
34#include <osmocore/select.h>
35#include <osmocore/rate_ctr.h>
36#include <openbsc/debug.h>
37#include <openbsc/signal.h>
38#include <openbsc/gprs_ns.h>
39#include <openbsc/gprs_bssgp.h>
Harald Welte804fc812010-05-14 18:59:17 +020040#include <openbsc/vty.h>
Harald Welte144e0292010-05-13 11:45:07 +020041
42#include <vty/vty.h>
43#include <vty/command.h>
44
45static struct gprs_ns_inst *vty_nsi = NULL;
46
47/* FIXME: this should go to some common file as it is copied
48 * in vty_interface.c of the BSC */
49static const struct value_string gprs_ns_timer_strs[] = {
50 { 0, "tns-block" },
51 { 1, "tns-block-retries" },
52 { 2, "tns-reset" },
53 { 3, "tns-reset-retries" },
54 { 4, "tns-test" },
55 { 5, "tns-alive" },
56 { 6, "tns-alive-retries" },
57 { 0, NULL }
58};
59
60static struct cmd_node ns_node = {
61 NS_NODE,
62 "%s(ns)#",
63 1,
64};
65
66static int config_write_ns(struct vty *vty)
67{
68 struct gprs_nsvc *nsvc;
69 unsigned int i;
70
71 vty_out(vty, "ns%s", VTY_NEWLINE);
72
73 llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) {
74 if (!nsvc->persistent)
75 continue;
76 vty_out(vty, " nse %u nsvci %u%s",
77 nsvc->nsei, nsvc->nsvci, VTY_NEWLINE);
78 vty_out(vty, " nse %u remote-role %s%s",
79 nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
80 VTY_NEWLINE);
81 if (nsvc->nsi->ll == GPRS_NS_LL_UDP) {
82 vty_out(vty, " nse %u remote-ip %s%s",
83 nsvc->nsei,
84 inet_ntoa(nsvc->ip.bts_addr.sin_addr),
85 VTY_NEWLINE);
86 vty_out(vty, " nse %u remote-port %u%s",
87 nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port),
88 VTY_NEWLINE);
89 }
90 }
91
92 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
93 vty_out(vty, " timer %s %u%s",
94 get_value_string(gprs_ns_timer_strs, i),
95 vty_nsi->timeout[i], VTY_NEWLINE);
96
97 return CMD_SUCCESS;
98}
99
100DEFUN(cfg_ns, cfg_ns_cmd,
101 "ns",
102 "Configure the GPRS Network Service")
103{
104 vty->node = NS_NODE;
105 return CMD_SUCCESS;
106}
107
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200108static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
Harald Welte144e0292010-05-13 11:45:07 +0200109{
Harald Welte144e0292010-05-13 11:45:07 +0200110 struct gprs_nsvc *nsvc;
111
112 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
Harald Weltedd1c83c2010-05-13 13:58:08 +0200113 if (nsvc == nsi->unknown_nsvc)
114 continue;
Harald Welte144e0292010-05-13 11:45:07 +0200115 vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
116 nsvc->nsei, nsvc->nsvci,
117 nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
118 nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
119 nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
120 if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
121 vty_out(vty, ", %15s:%u",
122 inet_ntoa(nsvc->ip.bts_addr.sin_addr),
123 ntohs(nsvc->ip.bts_addr.sin_port));
124 vty_out(vty, "%s", VTY_NEWLINE);
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200125 if (stats)
126 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
Harald Welte144e0292010-05-13 11:45:07 +0200127 }
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200128}
Harald Welte144e0292010-05-13 11:45:07 +0200129
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200130DEFUN(show_ns, show_ns_cmd, "show ns",
131 SHOW_STR "Display information about the NS protocol")
132{
133 struct gprs_ns_inst *nsi = vty_nsi;
134 dump_ns(vty, nsi, 0);
Harald Welte144e0292010-05-13 11:45:07 +0200135 return CMD_SUCCESS;
136}
137
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200138DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats",
139 SHOW_STR
140 "Display information about the NS protocol\n"
141 "Include statistics\n")
142{
143 struct gprs_ns_inst *nsi = vty_nsi;
144 dump_ns(vty, nsi, 1);
145 return CMD_SUCCESS;
146}
Harald Welte144e0292010-05-13 11:45:07 +0200147
148#define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n"
149
150DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
151 "nse <0-65535> nsvci <0-65534>",
152 NSE_CMD_STR
153 "NS Virtual Connection\n"
154 "NS Virtual Connection ID (NSVCI)\n"
155 )
156{
157 uint16_t nsei = atoi(argv[0]);
158 uint16_t nsvci = atoi(argv[1]);
159 struct gprs_nsvc *nsvc;
160
161 nsvc = nsvc_by_nsei(vty_nsi, nsei);
162 if (!nsvc) {
163 nsvc = nsvc_create(vty_nsi, nsvci);
164 nsvc->nsei = nsei;
165 }
166 nsvc->nsvci = nsvci;
167 /* All NSVCs that are explicitly configured by VTY are
168 * marked as persistent so we can write them to the config
169 * file at some later point */
170 nsvc->persistent = 1;
171
172 return CMD_SUCCESS;
173}
174
175DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
176 "nse <0-65535> remote-ip A.B.C.D",
177 NSE_CMD_STR
178 "Remote IP Address\n"
179 "Remote IP Address\n")
180{
181 uint16_t nsei = atoi(argv[0]);
182 struct gprs_nsvc *nsvc;
183
184 nsvc = nsvc_by_nsei(vty_nsi, nsei);
185 if (!nsvc) {
186 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
187 return CMD_WARNING;
188 }
189 inet_aton(argv[1], &nsvc->ip.bts_addr.sin_addr);
190
191 return CMD_SUCCESS;
192
193}
194
195DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
196 "nse <0-65535> remote-port <0-65535>",
197 NSE_CMD_STR
198 "Remote UDP Port\n"
199 "Remote UDP Port Number\n")
200{
201 uint16_t nsei = atoi(argv[0]);
202 uint16_t port = atoi(argv[1]);
203 struct gprs_nsvc *nsvc;
204
205 nsvc = nsvc_by_nsei(vty_nsi, nsei);
206 if (!nsvc) {
207 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
208 return CMD_WARNING;
209 }
210
211 nsvc->ip.bts_addr.sin_port = htons(port);
212
213 return CMD_SUCCESS;
214}
215
216DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
217 "nse <0-65535> remote-role (sgsn|bss)",
218 NSE_CMD_STR
219 "Remote NSE Role\n"
220 "Remote Peer is SGSN\n"
221 "Remote Peer is BSS\n")
222{
223 uint16_t nsei = atoi(argv[0]);
224 struct gprs_nsvc *nsvc;
225
226 nsvc = nsvc_by_nsei(vty_nsi, nsei);
227 if (!nsvc) {
228 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
229 return CMD_WARNING;
230 }
231
232 if (!strcmp(argv[1], "sgsn"))
233 nsvc->remote_end_is_sgsn = 1;
234 else
235 nsvc->remote_end_is_sgsn = 0;
236
237 return CMD_SUCCESS;
238}
239
240DEFUN(cfg_no_nse, cfg_no_nse_cmd,
241 "no nse <0-65535>",
242 "Delete NS Entity\n"
243 "Delete " NSE_CMD_STR)
244{
245 uint16_t nsei = atoi(argv[0]);
246 struct gprs_nsvc *nsvc;
247
248 nsvc = nsvc_by_nsei(vty_nsi, nsei);
249 if (!nsvc) {
250 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
251 return CMD_WARNING;
252 }
253
254 nsvc_delete(nsvc);
255
256 return CMD_SUCCESS;
257}
258
259DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
260 "timer " NS_TIMERS " <0-65535>",
261 "Network Service Timer\n"
262 NS_TIMERS_HELP "Timer Value\n")
263{
264 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
265 int val = atoi(argv[1]);
266
267 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
268 return CMD_WARNING;
269
270 vty_nsi->timeout[idx] = val;
271
272 return CMD_SUCCESS;
273}
274
Harald Welte43f3b692010-05-14 19:36:59 +0200275DEFUN(nsvc_nsei, nsvc_nsei_cmd,
276 "nsvc nsei <0-65535> (block|unblock|reset)",
277 "Perform an operation on a NSVC\n"
278 "NS-VC Identifier (NS-VCI)\n"
279 "Initiate BLOCK procedure\n"
280 "Initiate UNBLOCK procedure\n"
281 "Initiate RESET procedure\n")
282{
283 uint16_t nsvci = atoi(argv[0]);
284 const char *operation = argv[1];
285 struct gprs_nsvc *nsvc;
286
287 nsvc = nsvc_by_nsei(vty_nsi, nsvci);
288 if (!nsvc) {
289 vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE);
290 return CMD_WARNING;
291 }
292
293 if (!strcmp(operation, "block"))
294 gprs_ns_tx_block(nsvc, NS_CAUSE_OM_INTERVENTION);
295 else if (!strcmp(operation, "unblock"))
296 gprs_ns_tx_unblock(nsvc);
297 else if (!strcmp(operation, "reset"))
298 gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
299 else
300 return CMD_WARNING;
301
302 return CMD_SUCCESS;
303}
304
305
Harald Welte144e0292010-05-13 11:45:07 +0200306int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
307{
308 vty_nsi = nsi;
309
310 install_element_ve(&show_ns_cmd);
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200311 install_element_ve(&show_ns_stats_cmd);
Harald Welte144e0292010-05-13 11:45:07 +0200312
313 install_element(CONFIG_NODE, &cfg_ns_cmd);
314 install_node(&ns_node, config_write_ns);
315 install_default(NS_NODE);
Harald Welte804fc812010-05-14 18:59:17 +0200316 install_element(NS_NODE, &ournode_exit_cmd);
Harald Weltea52ff452010-05-14 19:11:04 +0200317 install_element(NS_NODE, &ournode_end_cmd);
Harald Welte144e0292010-05-13 11:45:07 +0200318 install_element(NS_NODE, &cfg_nse_nsvci_cmd);
319 install_element(NS_NODE, &cfg_nse_remoteip_cmd);
320 install_element(NS_NODE, &cfg_nse_remoteport_cmd);
321 install_element(NS_NODE, &cfg_nse_remoterole_cmd);
322 install_element(NS_NODE, &cfg_no_nse_cmd);
323 install_element(NS_NODE, &cfg_ns_timer_cmd);
324
Harald Welte43f3b692010-05-14 19:36:59 +0200325 install_element(ENABLE_NODE, &nsvc_nsei_cmd);
326
Harald Welte144e0292010-05-13 11:45:07 +0200327 return 0;
328}