blob: 8f0628afd3d033eede05351362c6a9ebf806f1ef [file] [log] [blame]
Harald Weltef2b4cd72010-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>
40
41#include <vty/vty.h>
42#include <vty/command.h>
43
44static struct gprs_ns_inst *vty_nsi = NULL;
45
46/* FIXME: this should go to some common file as it is copied
47 * in vty_interface.c of the BSC */
48static const struct value_string gprs_ns_timer_strs[] = {
49 { 0, "tns-block" },
50 { 1, "tns-block-retries" },
51 { 2, "tns-reset" },
52 { 3, "tns-reset-retries" },
53 { 4, "tns-test" },
54 { 5, "tns-alive" },
55 { 6, "tns-alive-retries" },
56 { 0, NULL }
57};
58
59static struct cmd_node ns_node = {
60 NS_NODE,
61 "%s(ns)#",
62 1,
63};
64
65static int config_write_ns(struct vty *vty)
66{
67 struct gprs_nsvc *nsvc;
68 unsigned int i;
69
70 vty_out(vty, "ns%s", VTY_NEWLINE);
71
72 llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) {
73 if (!nsvc->persistent)
74 continue;
75 vty_out(vty, " nse %u nsvci %u%s",
76 nsvc->nsei, nsvc->nsvci, VTY_NEWLINE);
77 vty_out(vty, " nse %u remote-role %s%s",
78 nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
79 VTY_NEWLINE);
80 if (nsvc->nsi->ll == GPRS_NS_LL_UDP) {
81 vty_out(vty, " nse %u remote-ip %s%s",
82 nsvc->nsei,
83 inet_ntoa(nsvc->ip.bts_addr.sin_addr),
84 VTY_NEWLINE);
85 vty_out(vty, " nse %u remote-port %u%s",
86 nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port),
87 VTY_NEWLINE);
88 }
89 }
90
91 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
92 vty_out(vty, " timer %s %u%s",
93 get_value_string(gprs_ns_timer_strs, i),
94 vty_nsi->timeout[i], VTY_NEWLINE);
95
96 return CMD_SUCCESS;
97}
98
99DEFUN(cfg_ns, cfg_ns_cmd,
100 "ns",
101 "Configure the GPRS Network Service")
102{
103 vty->node = NS_NODE;
104 return CMD_SUCCESS;
105}
106
Harald Welte73b23592010-05-13 12:32:30 +0200107static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
Harald Weltef2b4cd72010-05-13 11:45:07 +0200108{
Harald Weltef2b4cd72010-05-13 11:45:07 +0200109 struct gprs_nsvc *nsvc;
110
111 llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
Harald Welte9aa97fc2010-05-13 13:58:08 +0200112 if (nsvc == nsi->unknown_nsvc)
113 continue;
Harald Weltef2b4cd72010-05-13 11:45:07 +0200114 vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
115 nsvc->nsei, nsvc->nsvci,
116 nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
117 nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
118 nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
119 if (nsvc->nsi->ll == GPRS_NS_LL_UDP)
120 vty_out(vty, ", %15s:%u",
121 inet_ntoa(nsvc->ip.bts_addr.sin_addr),
122 ntohs(nsvc->ip.bts_addr.sin_port));
123 vty_out(vty, "%s", VTY_NEWLINE);
Harald Welte73b23592010-05-13 12:32:30 +0200124 if (stats)
125 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
Harald Weltef2b4cd72010-05-13 11:45:07 +0200126 }
Harald Welte73b23592010-05-13 12:32:30 +0200127}
Harald Weltef2b4cd72010-05-13 11:45:07 +0200128
Harald Welte73b23592010-05-13 12:32:30 +0200129DEFUN(show_ns, show_ns_cmd, "show ns",
130 SHOW_STR "Display information about the NS protocol")
131{
132 struct gprs_ns_inst *nsi = vty_nsi;
133 dump_ns(vty, nsi, 0);
Harald Weltef2b4cd72010-05-13 11:45:07 +0200134 return CMD_SUCCESS;
135}
136
Harald Welte73b23592010-05-13 12:32:30 +0200137DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats",
138 SHOW_STR
139 "Display information about the NS protocol\n"
140 "Include statistics\n")
141{
142 struct gprs_ns_inst *nsi = vty_nsi;
143 dump_ns(vty, nsi, 1);
144 return CMD_SUCCESS;
145}
Harald Weltef2b4cd72010-05-13 11:45:07 +0200146
147#define NSE_CMD_STR "NS Entity\n" "NS Entity ID (NSEI)\n"
148
149DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
150 "nse <0-65535> nsvci <0-65534>",
151 NSE_CMD_STR
152 "NS Virtual Connection\n"
153 "NS Virtual Connection ID (NSVCI)\n"
154 )
155{
156 uint16_t nsei = atoi(argv[0]);
157 uint16_t nsvci = atoi(argv[1]);
158 struct gprs_nsvc *nsvc;
159
160 nsvc = nsvc_by_nsei(vty_nsi, nsei);
161 if (!nsvc) {
162 nsvc = nsvc_create(vty_nsi, nsvci);
163 nsvc->nsei = nsei;
164 }
165 nsvc->nsvci = nsvci;
166 /* All NSVCs that are explicitly configured by VTY are
167 * marked as persistent so we can write them to the config
168 * file at some later point */
169 nsvc->persistent = 1;
170
171 return CMD_SUCCESS;
172}
173
174DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
175 "nse <0-65535> remote-ip A.B.C.D",
176 NSE_CMD_STR
177 "Remote IP Address\n"
178 "Remote IP Address\n")
179{
180 uint16_t nsei = atoi(argv[0]);
181 struct gprs_nsvc *nsvc;
182
183 nsvc = nsvc_by_nsei(vty_nsi, nsei);
184 if (!nsvc) {
185 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
186 return CMD_WARNING;
187 }
188 inet_aton(argv[1], &nsvc->ip.bts_addr.sin_addr);
189
190 return CMD_SUCCESS;
191
192}
193
194DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
195 "nse <0-65535> remote-port <0-65535>",
196 NSE_CMD_STR
197 "Remote UDP Port\n"
198 "Remote UDP Port Number\n")
199{
200 uint16_t nsei = atoi(argv[0]);
201 uint16_t port = atoi(argv[1]);
202 struct gprs_nsvc *nsvc;
203
204 nsvc = nsvc_by_nsei(vty_nsi, nsei);
205 if (!nsvc) {
206 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
207 return CMD_WARNING;
208 }
209
210 nsvc->ip.bts_addr.sin_port = htons(port);
211
212 return CMD_SUCCESS;
213}
214
215DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
216 "nse <0-65535> remote-role (sgsn|bss)",
217 NSE_CMD_STR
218 "Remote NSE Role\n"
219 "Remote Peer is SGSN\n"
220 "Remote Peer is BSS\n")
221{
222 uint16_t nsei = atoi(argv[0]);
223 struct gprs_nsvc *nsvc;
224
225 nsvc = nsvc_by_nsei(vty_nsi, nsei);
226 if (!nsvc) {
227 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
228 return CMD_WARNING;
229 }
230
231 if (!strcmp(argv[1], "sgsn"))
232 nsvc->remote_end_is_sgsn = 1;
233 else
234 nsvc->remote_end_is_sgsn = 0;
235
236 return CMD_SUCCESS;
237}
238
239DEFUN(cfg_no_nse, cfg_no_nse_cmd,
240 "no nse <0-65535>",
241 "Delete NS Entity\n"
242 "Delete " NSE_CMD_STR)
243{
244 uint16_t nsei = atoi(argv[0]);
245 struct gprs_nsvc *nsvc;
246
247 nsvc = nsvc_by_nsei(vty_nsi, nsei);
248 if (!nsvc) {
249 vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
250 return CMD_WARNING;
251 }
252
253 nsvc_delete(nsvc);
254
255 return CMD_SUCCESS;
256}
257
258DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
259 "timer " NS_TIMERS " <0-65535>",
260 "Network Service Timer\n"
261 NS_TIMERS_HELP "Timer Value\n")
262{
263 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
264 int val = atoi(argv[1]);
265
266 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
267 return CMD_WARNING;
268
269 vty_nsi->timeout[idx] = val;
270
271 return CMD_SUCCESS;
272}
273
274int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
275{
276 vty_nsi = nsi;
277
278 install_element_ve(&show_ns_cmd);
Harald Welte73b23592010-05-13 12:32:30 +0200279 install_element_ve(&show_ns_stats_cmd);
Harald Weltef2b4cd72010-05-13 11:45:07 +0200280
281 install_element(CONFIG_NODE, &cfg_ns_cmd);
282 install_node(&ns_node, config_write_ns);
283 install_default(NS_NODE);
284 install_element(NS_NODE, &cfg_nse_nsvci_cmd);
285 install_element(NS_NODE, &cfg_nse_remoteip_cmd);
286 install_element(NS_NODE, &cfg_nse_remoteport_cmd);
287 install_element(NS_NODE, &cfg_nse_remoterole_cmd);
288 install_element(NS_NODE, &cfg_no_nse_cmd);
289 install_element(NS_NODE, &cfg_ns_timer_cmd);
290
291 return 0;
292}