blob: b4102e44d949ccfccda5a05a794527c2fa168391 [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 Welte92883342010-05-15 23:04:03 +0200108static void dump_nse(struct vty *vty, struct gprs_nsvc *nsvc, int stats)
109{
110 vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
111 nsvc->nsei, nsvc->nsvci,
112 nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
113 nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
114 nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
115 if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
116 vty_out(vty, ", %15s:%u",
117 inet_ntoa(nsvc->ip.bts_addr.sin_addr),
118 ntohs(nsvc->ip.bts_addr.sin_port));
119 vty_out(vty, "%s", VTY_NEWLINE);
120 if (stats)
121 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
122}
123
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200124static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
Harald Welte144e0292010-05-13 11:45:07 +0200125{
Harald Welte144e0292010-05-13 11:45:07 +0200126 struct gprs_nsvc *nsvc;
127
128 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
Harald Weltedd1c83c2010-05-13 13:58:08 +0200129 if (nsvc == nsi->unknown_nsvc)
130 continue;
Harald Welte92883342010-05-15 23:04:03 +0200131 dump_nse(vty, nsvc, stats);
Harald Welte144e0292010-05-13 11:45:07 +0200132 }
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200133}
Harald Welte144e0292010-05-13 11:45:07 +0200134
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200135DEFUN(show_ns, show_ns_cmd, "show ns",
136 SHOW_STR "Display information about the NS protocol")
137{
138 struct gprs_ns_inst *nsi = vty_nsi;
139 dump_ns(vty, nsi, 0);
Harald Welte144e0292010-05-13 11:45:07 +0200140 return CMD_SUCCESS;
141}
142
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200143DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats",
144 SHOW_STR
145 "Display information about the NS protocol\n"
146 "Include statistics\n")
147{
148 struct gprs_ns_inst *nsi = vty_nsi;
149 dump_ns(vty, nsi, 1);
150 return CMD_SUCCESS;
151}
Harald Welte144e0292010-05-13 11:45:07 +0200152
Harald Welte92883342010-05-15 23:04:03 +0200153DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
154 SHOW_STR "Display information about the NS protocol\n"
155 "Select one NSE by its NSE Identifier\n"
156 "Select one NSE by its NS-VC Identifier\n"
157 "The Identifier of selected type\n"
158 "Include Statistics\n")
159{
160 struct gprs_ns_inst *nsi = vty_nsi;
161 struct gprs_nsvc *nsvc;
162 uint16_t id = atoi(argv[1]);
163 int show_stats = 0;
164
165 if (!strcmp(argv[0], "nsei"))
166 nsvc = nsvc_by_nsei(nsi, id);
167 else
168 nsvc = nsvc_by_nsvci(nsi, id);
169
170 if (!nsvc) {
171 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
172 return CMD_WARNING;
173 }
174
175 if (argc >= 3)
176 show_stats = 1;
177
178 dump_nse(vty, nsvc, show_stats);
179 return CMD_SUCCESS;
180}
181
Harald Welte144e0292010-05-13 11:45:07 +0200182#define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n"
183
184DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
185 "nse <0-65535> nsvci <0-65534>",
186 NSE_CMD_STR
187 "NS Virtual Connection\n"
188 "NS Virtual Connection ID (NSVCI)\n"
189 )
190{
191 uint16_t nsei = atoi(argv[0]);
192 uint16_t nsvci = atoi(argv[1]);
193 struct gprs_nsvc *nsvc;
194
195 nsvc = nsvc_by_nsei(vty_nsi, nsei);
196 if (!nsvc) {
197 nsvc = nsvc_create(vty_nsi, nsvci);
198 nsvc->nsei = nsei;
199 }
200 nsvc->nsvci = nsvci;
201 /* All NSVCs that are explicitly configured by VTY are
202 * marked as persistent so we can write them to the config
203 * file at some later point */
204 nsvc->persistent = 1;
205
206 return CMD_SUCCESS;
207}
208
209DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
210 "nse <0-65535> remote-ip A.B.C.D",
211 NSE_CMD_STR
212 "Remote IP Address\n"
213 "Remote IP Address\n")
214{
215 uint16_t nsei = atoi(argv[0]);
216 struct gprs_nsvc *nsvc;
217
218 nsvc = nsvc_by_nsei(vty_nsi, nsei);
219 if (!nsvc) {
220 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
221 return CMD_WARNING;
222 }
223 inet_aton(argv[1], &nsvc->ip.bts_addr.sin_addr);
224
225 return CMD_SUCCESS;
226
227}
228
229DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
230 "nse <0-65535> remote-port <0-65535>",
231 NSE_CMD_STR
232 "Remote UDP Port\n"
233 "Remote UDP Port Number\n")
234{
235 uint16_t nsei = atoi(argv[0]);
236 uint16_t port = atoi(argv[1]);
237 struct gprs_nsvc *nsvc;
238
239 nsvc = nsvc_by_nsei(vty_nsi, nsei);
240 if (!nsvc) {
241 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
242 return CMD_WARNING;
243 }
244
245 nsvc->ip.bts_addr.sin_port = htons(port);
246
247 return CMD_SUCCESS;
248}
249
250DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
251 "nse <0-65535> remote-role (sgsn|bss)",
252 NSE_CMD_STR
253 "Remote NSE Role\n"
254 "Remote Peer is SGSN\n"
255 "Remote Peer is BSS\n")
256{
257 uint16_t nsei = atoi(argv[0]);
258 struct gprs_nsvc *nsvc;
259
260 nsvc = nsvc_by_nsei(vty_nsi, nsei);
261 if (!nsvc) {
262 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
263 return CMD_WARNING;
264 }
265
266 if (!strcmp(argv[1], "sgsn"))
267 nsvc->remote_end_is_sgsn = 1;
268 else
269 nsvc->remote_end_is_sgsn = 0;
270
271 return CMD_SUCCESS;
272}
273
274DEFUN(cfg_no_nse, cfg_no_nse_cmd,
275 "no nse <0-65535>",
276 "Delete NS Entity\n"
277 "Delete " NSE_CMD_STR)
278{
279 uint16_t nsei = atoi(argv[0]);
280 struct gprs_nsvc *nsvc;
281
282 nsvc = nsvc_by_nsei(vty_nsi, nsei);
283 if (!nsvc) {
284 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
285 return CMD_WARNING;
286 }
287
288 nsvc_delete(nsvc);
289
290 return CMD_SUCCESS;
291}
292
293DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
294 "timer " NS_TIMERS " <0-65535>",
295 "Network Service Timer\n"
296 NS_TIMERS_HELP "Timer Value\n")
297{
298 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
299 int val = atoi(argv[1]);
300
301 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
302 return CMD_WARNING;
303
304 vty_nsi->timeout[idx] = val;
305
306 return CMD_SUCCESS;
307}
308
Harald Welte43f3b692010-05-14 19:36:59 +0200309DEFUN(nsvc_nsei, nsvc_nsei_cmd,
310 "nsvc nsei <0-65535> (block|unblock|reset)",
311 "Perform an operation on a NSVC\n"
312 "NS-VC Identifier (NS-VCI)\n"
313 "Initiate BLOCK procedure\n"
314 "Initiate UNBLOCK procedure\n"
315 "Initiate RESET procedure\n")
316{
317 uint16_t nsvci = atoi(argv[0]);
318 const char *operation = argv[1];
319 struct gprs_nsvc *nsvc;
320
321 nsvc = nsvc_by_nsei(vty_nsi, nsvci);
322 if (!nsvc) {
323 vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE);
324 return CMD_WARNING;
325 }
326
327 if (!strcmp(operation, "block"))
328 gprs_ns_tx_block(nsvc, NS_CAUSE_OM_INTERVENTION);
329 else if (!strcmp(operation, "unblock"))
330 gprs_ns_tx_unblock(nsvc);
331 else if (!strcmp(operation, "reset"))
332 gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
333 else
334 return CMD_WARNING;
335
336 return CMD_SUCCESS;
337}
338
339
Harald Welte144e0292010-05-13 11:45:07 +0200340int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
341{
342 vty_nsi = nsi;
343
344 install_element_ve(&show_ns_cmd);
Harald Welteaf1d4cb2010-05-13 12:32:30 +0200345 install_element_ve(&show_ns_stats_cmd);
Harald Welte92883342010-05-15 23:04:03 +0200346 install_element_ve(&show_nse_cmd);
Harald Welte144e0292010-05-13 11:45:07 +0200347
348 install_element(CONFIG_NODE, &cfg_ns_cmd);
349 install_node(&ns_node, config_write_ns);
350 install_default(NS_NODE);
Harald Welte804fc812010-05-14 18:59:17 +0200351 install_element(NS_NODE, &ournode_exit_cmd);
Harald Weltea52ff452010-05-14 19:11:04 +0200352 install_element(NS_NODE, &ournode_end_cmd);
Harald Welte144e0292010-05-13 11:45:07 +0200353 install_element(NS_NODE, &cfg_nse_nsvci_cmd);
354 install_element(NS_NODE, &cfg_nse_remoteip_cmd);
355 install_element(NS_NODE, &cfg_nse_remoteport_cmd);
356 install_element(NS_NODE, &cfg_nse_remoterole_cmd);
357 install_element(NS_NODE, &cfg_no_nse_cmd);
358 install_element(NS_NODE, &cfg_ns_timer_cmd);
359
Harald Welte43f3b692010-05-14 19:36:59 +0200360 install_element(ENABLE_NODE, &nsvc_nsei_cmd);
361
Harald Welte144e0292010-05-13 11:45:07 +0200362 return 0;
363}