blob: 9c214a3dbb0c4309fb3026e49cd4fb43b7013243 [file] [log] [blame]
Alexander Couzens6a161492020-07-12 13:45:50 +02001/*! \file gprs_ns2_vty.c
2 * VTY interface for our GPRS Networks Service (NS) implementation. */
3
4/* (C) 2009-2014 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
6 * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
7 * Author: Alexander Couzens <lynxis@fe80.eu>
8 *
9 * All Rights Reserved
10 *
11 * SPDX-License-Identifier: GPL-2.0+
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27
28#include <stdlib.h>
29#include <unistd.h>
30#include <errno.h>
31#include <stdint.h>
32
33#include <arpa/inet.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010034#include <net/if.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020035
36#include <osmocom/core/msgb.h>
37#include <osmocom/core/byteswap.h>
Daniel Willmanndbab7142020-11-18 14:19:56 +010038#include <osmocom/core/fsm.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020039#include <osmocom/core/talloc.h>
40#include <osmocom/core/select.h>
41#include <osmocom/core/rate_ctr.h>
42#include <osmocom/core/socket.h>
43#include <osmocom/core/sockaddr_str.h>
44#include <osmocom/core/linuxlist.h>
45#include <osmocom/core/socket.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010046#include <osmocom/gprs/frame_relay.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020047#include <osmocom/gprs/gprs_ns2.h>
48#include <osmocom/gsm/tlv.h>
49#include <osmocom/vty/vty.h>
50#include <osmocom/vty/command.h>
51#include <osmocom/vty/logging.h>
52#include <osmocom/vty/telnet_interface.h>
53#include <osmocom/vty/misc.h>
54
55#include "gprs_ns2_internal.h"
56
Daniel Willmanncb3e9b52020-12-02 15:50:22 +010057#define SHOW_NS_STR "Display information about the NS protocol\n"
58
Alexander Couzens6a161492020-07-12 13:45:50 +020059struct ns2_vty_priv {
60 /* global listen */
61 struct osmo_sockaddr_str udp;
62 struct osmo_sockaddr_str frgreaddr;
63 int dscp;
64 enum gprs_ns2_vc_mode vc_mode;
65 /* force vc mode if another configuration forces
66 * the vc mode. E.g. SNS configuration */
67 bool force_vc_mode;
Daniel Willmann4fb27a82020-09-25 15:39:46 +020068 const char *force_vc_mode_reason;
Alexander Couzens6a161492020-07-12 13:45:50 +020069 bool frgre;
70
71 struct llist_head vtyvc;
72};
73
74struct ns2_vty_vc {
75 struct llist_head list;
76
77 struct osmo_sockaddr_str remote;
Alexander Couzens24a14ac2020-11-19 02:34:49 +010078 enum gprs_ns2_ll ll;
Alexander Couzens6a161492020-07-12 13:45:50 +020079
80 /* old vty code doesnt support multiple NSVCI per NSEI */
81 uint16_t nsei;
82 uint16_t nsvci;
83 uint16_t frdlci;
84
Alexander Couzens841817e2020-11-19 00:41:29 +010085 struct {
86 enum osmo_fr_role role;
87 } fr;
88
89 char netif[IF_NAMESIZE];
90
Alexander Couzens6a161492020-07-12 13:45:50 +020091 bool remote_end_is_sgsn;
92 bool configured;
93};
94
95static struct gprs_ns2_inst *vty_nsi = NULL;
96static struct ns2_vty_priv priv;
Alexander Couzens841817e2020-11-19 00:41:29 +010097static struct osmo_fr_network *vty_fr_network = NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +020098
99/* FIXME: this should go to some common file as it is copied
100 * in vty_interface.c of the BSC */
101static const struct value_string gprs_ns_timer_strs[] = {
102 { 0, "tns-block" },
103 { 1, "tns-block-retries" },
104 { 2, "tns-reset" },
105 { 3, "tns-reset-retries" },
106 { 4, "tns-test" },
107 { 5, "tns-alive" },
108 { 6, "tns-alive-retries" },
109 { 7, "tsns-prov" },
110 { 0, NULL }
111};
112
Daniel Willmann751977b2020-12-02 18:59:44 +0100113static void log_set_nse_filter(struct log_target *target,
114 struct gprs_ns2_nse *nse)
115{
116 if (nse) {
117 target->filter_map |= (1 << LOG_FLT_GB_NSE);
118 target->filter_data[LOG_FLT_GB_NSE] = nse;
119 } else if (target->filter_data[LOG_FLT_GB_NSE]) {
120 target->filter_map = ~(1 << LOG_FLT_GB_NSE);
121 target->filter_data[LOG_FLT_GB_NSE] = NULL;
122 }
123}
124
Alexander Couzens6a161492020-07-12 13:45:50 +0200125static void log_set_nsvc_filter(struct log_target *target,
126 struct gprs_ns2_vc *nsvc)
127{
128 if (nsvc) {
129 target->filter_map |= (1 << LOG_FLT_GB_NSVC);
130 target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
131 } else if (target->filter_data[LOG_FLT_GB_NSVC]) {
132 target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
133 target->filter_data[LOG_FLT_GB_NSVC] = NULL;
134 }
135}
136
137static struct cmd_node ns_node = {
138 L_NS_NODE,
139 "%s(config-ns)# ",
140 1,
141};
142
Harald Welte6d4db232020-11-25 19:33:42 +0100143static struct ns2_vty_vc *vtyvc_alloc(uint16_t nsei) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200144 struct ns2_vty_vc *vtyvc = talloc_zero(vty_nsi, struct ns2_vty_vc);
145 if (!vtyvc)
146 return vtyvc;
147
148 vtyvc->nsei = nsei;
149
150 llist_add(&vtyvc->list, &priv.vtyvc);
151
152 return vtyvc;
153}
154
155static void ns2_vc_free(struct ns2_vty_vc *vtyvc) {
156 if (!vtyvc)
157 return;
158
159 llist_del(&vtyvc->list);
160 talloc_free(vtyvc);
161}
162
Harald Welte6d4db232020-11-25 19:33:42 +0100163static struct ns2_vty_vc *vtyvc_by_nsei(uint16_t nsei, bool alloc_missing) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200164 struct ns2_vty_vc *vtyvc;
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200165
Alexander Couzens6a161492020-07-12 13:45:50 +0200166 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Harald Welte6d4db232020-11-25 19:33:42 +0100167 if (vtyvc->nsei == nsei)
Alexander Couzens6a161492020-07-12 13:45:50 +0200168 return vtyvc;
169 }
170
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200171 if (!alloc_missing)
172 return NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +0200173
Harald Welte6d4db232020-11-25 19:33:42 +0100174 vtyvc = vtyvc_alloc(nsei);
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200175 if (!vtyvc)
176 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200177
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200178 vtyvc->nsei = nsei;
179 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200180}
181
182static int config_write_ns(struct vty *vty)
183{
184 struct ns2_vty_vc *vtyvc;
185 unsigned int i;
186 struct osmo_sockaddr_str sockstr;
187
188 vty_out(vty, "ns%s", VTY_NEWLINE);
189
190 /* global configuration must be written first, as some of it may be
191 * relevant when creating the NSE/NSVC later below */
192
193 vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
194 priv.frgre ? 1 : 0, VTY_NEWLINE);
195
196 if (priv.frgre) {
197 if (strlen(priv.frgreaddr.ip)) {
198 vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
199 sockstr.ip, VTY_NEWLINE);
200 }
201 } else {
202 if (strlen(priv.udp.ip)) {
203 vty_out(vty, " encapsulation udp local-ip %s%s",
204 priv.udp.ip, VTY_NEWLINE);
205 }
206
207 if (priv.udp.port)
208 vty_out(vty, " encapsulation udp local-port %u%s",
209 priv.udp.port, VTY_NEWLINE);
210 }
211
212 if (priv.dscp)
213 vty_out(vty, " encapsulation udp dscp %d%s",
214 priv.dscp, VTY_NEWLINE);
215
216 vty_out(vty, " encapsulation udp use-reset-block-unblock %s%s",
217 priv.vc_mode == NS2_VC_MODE_BLOCKRESET ? "enabled" : "disabled", VTY_NEWLINE);
218
219 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
220 vty_out(vty, " nse %u nsvci %u%s",
221 vtyvc->nsei, vtyvc->nsvci, VTY_NEWLINE);
222
Harald Welte6d4db232020-11-25 19:33:42 +0100223 vty_out(vty, " nse %u remote-role %s%s",
224 vtyvc->nsei, vtyvc->remote_end_is_sgsn ? "sgsn" : "bss",
225 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200226
227 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100228 case GPRS_NS2_LL_UDP:
Harald Welte6d4db232020-11-25 19:33:42 +0100229 vty_out(vty, " nse %u encapsulation udp%s", vtyvc->nsei, VTY_NEWLINE);
230 vty_out(vty, " nse %u remote-ip %s%s",
231 vtyvc->nsei,
232 vtyvc->remote.ip,
Alexander Couzens6a161492020-07-12 13:45:50 +0200233 VTY_NEWLINE);
Harald Welte6d4db232020-11-25 19:33:42 +0100234 vty_out(vty, " nse %u remote-port %u%s",
235 vtyvc->nsei, vtyvc->remote.port,
236 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200237 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100238 case GPRS_NS2_LL_FR_GRE:
Harald Welte6d4db232020-11-25 19:33:42 +0100239 vty_out(vty, " nse %u encapsulation framerelay-gre%s",
240 vtyvc->nsei, VTY_NEWLINE);
241 vty_out(vty, " nse %u remote-ip %s%s",
242 vtyvc->nsei,
243 vtyvc->remote.ip,
244 VTY_NEWLINE);
245 vty_out(vty, " nse %u fr-dlci %u%s",
246 vtyvc->nsei, vtyvc->frdlci,
247 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200248 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100249 case GPRS_NS2_LL_FR:
Harald Welte6d4db232020-11-25 19:33:42 +0100250 vty_out(vty, " nse %u fr %s dlci %u%s",
251 vtyvc->nsei, vtyvc->netif, vtyvc->frdlci,
252 VTY_NEWLINE);
Alexander Couzens841817e2020-11-19 00:41:29 +0100253 break;
Alexander Couzens6a161492020-07-12 13:45:50 +0200254 default:
255 break;
256 }
257 }
258
259 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
260 vty_out(vty, " timer %s %u%s",
261 get_value_string(gprs_ns_timer_strs, i),
262 vty_nsi->timeout[i], VTY_NEWLINE);
263
264 return CMD_SUCCESS;
265}
266
267DEFUN(cfg_ns, cfg_ns_cmd,
268 "ns",
269 "Configure the GPRS Network Service")
270{
271 vty->node = L_NS_NODE;
272 return CMD_SUCCESS;
273}
274
275static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
276{
Harald Weltedc2d0802020-12-01 18:17:28 +0100277 char nsvci_str[32];
278
279 if (nsvc->nsvci_is_valid)
280 snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
281 else
282 snprintf(nsvci_str, sizeof(nsvci_str), "none");
283
284 vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
285 osmo_fsm_inst_state_name(nsvc->fi),
286 nsvc->persistent ? "PERSIST" : "DYNAMIC",
287 nsvc->data_weight, nsvc->sig_weight,
288 gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200289
290 if (stats) {
Harald Welte7aa60992020-12-01 17:53:17 +0100291 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
292 vty_out_stat_item_group(vty, " ", nsvc->statg);
Alexander Couzens6a161492020-07-12 13:45:50 +0200293 }
294}
295
296static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
297{
298 struct gprs_ns2_vc *nsvc;
299
Harald Welte0ff12ad2020-12-01 17:51:07 +0100300 vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
301 nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200302
303 gprs_ns2_sns_dump_vty(vty, nse, stats);
304 llist_for_each_entry(nsvc, &nse->nsvc, list) {
305 if (persistent_only) {
306 if (nsvc->persistent)
307 dump_nsvc(vty, nsvc, stats);
308 } else {
309 dump_nsvc(vty, nsvc, stats);
310 }
311 }
312}
313
Alexander Couzens22f34712020-10-02 02:34:39 +0200314static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
315{
316 if (bind->dump_vty)
317 bind->dump_vty(bind, vty, stats);
318}
319
Harald Welte2fce19a2020-12-01 17:52:55 +0100320static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +0200321{
Alexander Couzens22f34712020-10-02 02:34:39 +0200322 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6a161492020-07-12 13:45:50 +0200323
Alexander Couzens22f34712020-10-02 02:34:39 +0200324 llist_for_each_entry(bind, &nsi->binding, list) {
325 dump_bind(vty, bind, stats);
326 }
Harald Welte2fce19a2020-12-01 17:52:55 +0100327}
328
329
330static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
331{
332 struct gprs_ns2_nse *nse;
Alexander Couzens22f34712020-10-02 02:34:39 +0200333
Alexander Couzens6a161492020-07-12 13:45:50 +0200334 llist_for_each_entry(nse, &nsi->nse, list) {
335 dump_nse(vty, nse, stats, persistent_only);
Alexander Couzens6a161492020-07-12 13:45:50 +0200336 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200337}
338
Harald Welte25ee7552020-12-02 22:14:00 +0100339/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
340 * 'show ns' to output something about binds */
341DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
342 SHOW_STR SHOW_NS_STR)
343{
344 dump_ns_entities(vty, vty_nsi, false, false);
345 dump_ns_bind(vty, vty_nsi, false);
346 return CMD_SUCCESS;
347}
348
349
Harald Welte2fce19a2020-12-01 17:52:55 +0100350DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100351 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100352 "Display information about the NS protocol binds\n"
353 "Include statistic\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200354{
Harald Welte2fce19a2020-12-01 17:52:55 +0100355 bool stats = false;
356 if (argc > 0)
357 stats = true;
358
359 dump_ns_bind(vty, vty_nsi, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +0200360 return CMD_SUCCESS;
361}
362
Harald Welte2fce19a2020-12-01 17:52:55 +0100363DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100364 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100365 "Display information about the NS protocol entities (NSEs)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200366 "Include statistics\n")
367{
Harald Welte2fce19a2020-12-01 17:52:55 +0100368 bool stats = false;
369 if (argc > 0)
370 stats = true;
371
372 dump_ns_entities(vty, vty_nsi, stats, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200373 return CMD_SUCCESS;
374}
375
376DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100377 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200378 "Show only persistent NS\n")
379{
Harald Welte2fce19a2020-12-01 17:52:55 +0100380 dump_ns_entities(vty, vty_nsi, true, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200381 return CMD_SUCCESS;
382}
383
384DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100385 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200386 "Select one NSE by its NSE Identifier\n"
387 "Select one NSE by its NS-VC Identifier\n"
388 "The Identifier of selected type\n"
389 "Include Statistics\n")
390{
391 struct gprs_ns2_inst *nsi = vty_nsi;
392 struct gprs_ns2_nse *nse;
393 struct gprs_ns2_vc *nsvc;
394 uint16_t id = atoi(argv[1]);
395 bool show_stats = false;
396
397 if (argc >= 3)
398 show_stats = true;
399
400 if (!strcmp(argv[0], "nsei")) {
401 nse = gprs_ns2_nse_by_nsei(nsi, id);
402 if (!nse) {
403 return CMD_WARNING;
404 }
405
406 dump_nse(vty, nse, show_stats, false);
407 } else {
408 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
409
410 if (!nsvc) {
411 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
412 return CMD_WARNING;
413 }
414
415 dump_nsvc(vty, nsvc, show_stats);
416 }
417
418 return CMD_SUCCESS;
419}
420
Daniel Willmanndbab7142020-11-18 14:19:56 +0100421static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
422{
423 gprs_ns2_vc_force_unconfigured(nsvc);
424 return 0;
425}
426
427DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
428 "nsvc nsei <0-65535> force-unconfigured",
429 "NS Virtual Connection\n"
430 "The NSEI\n"
431 "Reset the NSVCs back to initial state\n"
432 )
433{
434 struct gprs_ns2_inst *nsi = vty_nsi;
435 struct gprs_ns2_nse *nse;
436
437 uint16_t id = atoi(argv[0]);
438
439 nse = gprs_ns2_nse_by_nsei(nsi, id);
440 if (!nse) {
441 vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
442 return CMD_WARNING;
443 }
444
445 /* Perform the operation for all nsvc */
446 gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
447
448 return CMD_SUCCESS;
449}
450
Alexander Couzens6a161492020-07-12 13:45:50 +0200451#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
452
Alexander Couzens841817e2020-11-19 00:41:29 +0100453DEFUN(cfg_nse_fr, cfg_nse_fr_cmd,
454 "nse <0-65535> nsvci <0-65535> (fr|frnet) NETIF dlci <0-1023>",
455 NSE_CMD_STR
456 "NS Virtual Connection\n"
457 "NS Virtual Connection ID (NSVCI)\n"
Harald Welte92049192020-11-25 20:56:06 +0100458 "Frame Relay User-Side\n"
459 "Frame Relay Network-Side\n"
Alexander Couzens841817e2020-11-19 00:41:29 +0100460 IFNAME_STR
461 "Data Link connection identifier\n"
462 "Data Link connection identifier\n"
463 )
464{
465 struct ns2_vty_vc *vtyvc;
466
467 uint16_t nsei = atoi(argv[0]);
468 uint16_t nsvci = atoi(argv[1]);
469 const char *role = argv[2];
470 const char *name = argv[3];
471 uint16_t dlci = atoi(argv[4]);
472
Harald Welte6d4db232020-11-25 19:33:42 +0100473 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens841817e2020-11-19 00:41:29 +0100474 if (!vtyvc) {
475 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
476 return CMD_WARNING;
477 }
478
479 if (!strcmp(role, "fr"))
480 vtyvc->fr.role = FR_ROLE_USER_EQUIPMENT;
481 else if (!strcmp(role, "frnet"))
482 vtyvc->fr.role = FR_ROLE_NETWORK_EQUIPMENT;
483
484 osmo_strlcpy(vtyvc->netif, name, sizeof(vtyvc->netif));
485 vtyvc->frdlci = dlci;
486 vtyvc->nsvci = nsvci;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100487 vtyvc->ll = GPRS_NS2_LL_FR;
Alexander Couzens841817e2020-11-19 00:41:29 +0100488
489 return CMD_SUCCESS;
490}
491
Alexander Couzens6a161492020-07-12 13:45:50 +0200492DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
493 "nse <0-65535> nsvci <0-65535>",
494 NSE_CMD_STR
495 "NS Virtual Connection\n"
496 "NS Virtual Connection ID (NSVCI)\n"
497 )
498{
499 struct ns2_vty_vc *vtyvc;
500
501 uint16_t nsei = atoi(argv[0]);
502 uint16_t nsvci = atoi(argv[1]);
503
Harald Welte6d4db232020-11-25 19:33:42 +0100504 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200505 if (!vtyvc) {
506 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
507 return CMD_WARNING;
508 }
509
510 vtyvc->nsvci = nsvci;
511
512 return CMD_SUCCESS;
513}
514
515DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100516 "nse <0-65535> remote-ip " VTY_IPV46_CMD,
Alexander Couzens6a161492020-07-12 13:45:50 +0200517 NSE_CMD_STR
518 "Remote IP Address\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200519 "Remote IPv4 Address\n"
520 "Remote IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200521{
522 uint16_t nsei = atoi(argv[0]);
523 struct ns2_vty_vc *vtyvc;
524
Harald Welte6d4db232020-11-25 19:33:42 +0100525 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200526 if (!vtyvc) {
527 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
528 return CMD_WARNING;
529 }
530
Harald Welte6d4db232020-11-25 19:33:42 +0100531 osmo_sockaddr_str_from_str2(&vtyvc->remote, argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200532
533 return CMD_SUCCESS;
534}
535
536DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100537 "nse <0-65535> remote-port <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200538 NSE_CMD_STR
539 "Remote UDP Port\n"
540 "Remote UDP Port Number\n")
541{
542 uint16_t nsei = atoi(argv[0]);
Harald Welte6d4db232020-11-25 19:33:42 +0100543 uint16_t port = atoi(argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200544 struct ns2_vty_vc *vtyvc;
545
Harald Welte6d4db232020-11-25 19:33:42 +0100546 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200547 if (!vtyvc) {
548 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
549 return CMD_WARNING;
550 }
551
552 vtyvc->remote.port = port;
553
554 return CMD_SUCCESS;
555}
556
557DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
Alexander Couzens841817e2020-11-19 00:41:29 +0100558 "nse <0-65535> nsvci <0-65535> fr-dlci <16-1007>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200559 NSE_CMD_STR
Harald Welte92049192020-11-25 20:56:06 +0100560 "NS Virtual Connection\n"
561 "NS Virtual Connection ID (NSVCI)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200562 "Frame Relay DLCI\n"
563 "Frame Relay DLCI Number\n")
564{
565 uint16_t nsei = atoi(argv[0]);
Alexander Couzens841817e2020-11-19 00:41:29 +0100566 uint16_t nsvci = atoi(argv[1]);
567 uint16_t dlci = atoi(argv[2]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200568 struct ns2_vty_vc *vtyvc;
569
Harald Welte6d4db232020-11-25 19:33:42 +0100570 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200571 if (!vtyvc) {
572 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
573 return CMD_WARNING;
574 }
575
Alexander Couzens6a161492020-07-12 13:45:50 +0200576 vtyvc->frdlci = dlci;
Harald Welte6d4db232020-11-25 19:33:42 +0100577 vtyvc->nsvci = nsvci;
Alexander Couzens6a161492020-07-12 13:45:50 +0200578
579 return CMD_SUCCESS;
580}
581
582DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100583 "nse <0-65535> encapsulation (udp|framerelay-gre)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200584 NSE_CMD_STR
585 "Encapsulation for NS\n"
586 "UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
587{
588 uint16_t nsei = atoi(argv[0]);
589 struct ns2_vty_vc *vtyvc;
590
Harald Welte6d4db232020-11-25 19:33:42 +0100591 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200592 if (!vtyvc) {
593 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
594 return CMD_WARNING;
595 }
596
Harald Welte6d4db232020-11-25 19:33:42 +0100597 if (!strcmp(argv[1], "udp"))
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100598 vtyvc->ll = GPRS_NS2_LL_UDP;
Alexander Couzens6a161492020-07-12 13:45:50 +0200599 else
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100600 vtyvc->ll = GPRS_NS2_LL_FR_GRE;
Alexander Couzens6a161492020-07-12 13:45:50 +0200601
602 return CMD_SUCCESS;
603}
604
605DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100606 "nse <0-65535> remote-role (sgsn|bss)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200607 NSE_CMD_STR
608 "Remote NSE Role\n"
609 "Remote Peer is SGSN\n"
610 "Remote Peer is BSS\n")
611{
612 uint16_t nsei = atoi(argv[0]);
613 struct ns2_vty_vc *vtyvc;
614
Harald Welte6d4db232020-11-25 19:33:42 +0100615 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200616 if (!vtyvc) {
617 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
618 return CMD_WARNING;
619 }
620
Harald Welte6d4db232020-11-25 19:33:42 +0100621 if (!strcmp(argv[1], "sgsn"))
Alexander Couzens6a161492020-07-12 13:45:50 +0200622 vtyvc->remote_end_is_sgsn = 1;
623 else
624 vtyvc->remote_end_is_sgsn = 0;
625
626 return CMD_SUCCESS;
627}
628
629DEFUN(cfg_no_nse, cfg_no_nse_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100630 "no nse <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200631 "Delete Persistent NS Entity\n"
632 "Delete " NSE_CMD_STR)
633{
634 uint16_t nsei = atoi(argv[0]);
635 struct ns2_vty_vc *vtyvc;
636
Harald Welte6d4db232020-11-25 19:33:42 +0100637 vtyvc = vtyvc_by_nsei(nsei, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200638 if (!vtyvc) {
639 vty_out(vty, "The NSE %d does not exists.%s", nsei, VTY_NEWLINE);
640 return CMD_WARNING;
641 }
642
643 ns2_vc_free(vtyvc);
644
645 return CMD_SUCCESS;
646}
647
648DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
649 "timer " NS_TIMERS " <0-65535>",
650 "Network Service Timer\n"
651 NS_TIMERS_HELP "Timer Value\n")
652{
653 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
654 int val = atoi(argv[1]);
655
656 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
657 return CMD_WARNING;
658
659 vty_nsi->timeout[idx] = val;
660
661 return CMD_SUCCESS;
662}
663
664#define ENCAPS_STR "NS encapsulation options\n"
665
666DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
667 "encapsulation udp local-ip " VTY_IPV46_CMD,
668 ENCAPS_STR "NS over UDP Encapsulation\n"
669 "Set the IP address on which we listen for NS/UDP\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200670 "IPv4 Address\n"
671 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200672{
673 osmo_sockaddr_str_from_str2(&priv.udp, argv[0]);
674
675 return CMD_SUCCESS;
676}
677
678DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
679 "encapsulation udp local-port <0-65535>",
680 ENCAPS_STR "NS over UDP Encapsulation\n"
681 "Set the UDP port on which we listen for NS/UDP\n"
682 "UDP port number\n")
683{
684 unsigned int port = atoi(argv[0]);
685
686 priv.udp.port = port;
687
688 return CMD_SUCCESS;
689}
690
691DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd,
692 "encapsulation udp dscp <0-255>",
693 ENCAPS_STR "NS over UDP Encapsulation\n"
694 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
695{
696 int dscp = atoi(argv[0]);
697 struct gprs_ns2_vc_bind *bind;
698
699 priv.dscp = dscp;
700
701 llist_for_each_entry(bind, &vty_nsi->binding, list) {
702 if (gprs_ns2_is_ip_bind(bind))
703 gprs_ns2_ip_bind_set_dscp(bind, dscp);
704 }
705
706 return CMD_SUCCESS;
707}
708
709DEFUN(cfg_nsip_res_block_unblock, cfg_nsip_res_block_unblock_cmd,
710 "encapsulation udp use-reset-block-unblock (enabled|disabled)",
711 ENCAPS_STR "NS over UDP Encapsulation\n"
712 "Use NS-{RESET,BLOCK,UNBLOCK} procedures in violation of 3GPP TS 48.016\n"
713 "Enable NS-{RESET,BLOCK,UNBLOCK}\n"
714 "Disable NS-{RESET,BLOCK,UNBLOCK}\n")
715{
716 enum gprs_ns2_vc_mode vc_mode;
717 struct gprs_ns2_vc_bind *bind;
718
719 if (!strcmp(argv[0], "enabled"))
720 vc_mode = NS2_VC_MODE_BLOCKRESET;
721 else
722 vc_mode = NS2_VC_MODE_ALIVE;
723
724 if (priv.force_vc_mode) {
725 if (priv.vc_mode != vc_mode)
726 {
727 vty_out(vty, "Ignoring use-reset-block because it's already set by %s.%s",
728 priv.force_vc_mode_reason, VTY_NEWLINE);
729 return CMD_WARNING;
730 }
731
732 return CMD_SUCCESS;
733 }
734
735 priv.vc_mode = vc_mode;
736
737 llist_for_each_entry(bind, &vty_nsi->binding, list) {
738 gprs_ns2_bind_set_mode(bind, priv.vc_mode);
739 }
740
741 return CMD_SUCCESS;
742}
743
744DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
745 "encapsulation framerelay-gre local-ip " VTY_IPV46_CMD,
746 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
747 "Set the IP address on which we listen for NS/FR/GRE\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200748 "IPv4 Address\n"
749 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200750{
751 osmo_sockaddr_str_from_str2(&priv.frgreaddr, argv[0]);
752
753 return CMD_SUCCESS;
754}
755
756DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
757 "encapsulation framerelay-gre enabled (1|0)",
758 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
759 "Enable or disable Frame Relay over GRE\n"
760 "Enable\n" "Disable\n")
761{
762 int enabled = atoi(argv[0]);
763
764 priv.frgre = enabled;
765
766 return CMD_SUCCESS;
767}
768
769/* TODO: allow vty to reset/block/unblock nsvc/nsei */
770
Daniel Willmann751977b2020-12-02 18:59:44 +0100771DEFUN(logging_fltr_nse,
772 logging_fltr_nse_cmd,
773 "logging filter nse nsei <0-65535>",
774 LOGGING_STR FILTER_STR
775 "Filter based on NS Entity\n"
776 "Identify NSE by NSEI\n"
777 "Numeric identifier\n")
778{
779 struct log_target *tgt;
780 struct gprs_ns2_nse *nse;
781 uint16_t id = atoi(argv[1]);
782
783 log_tgt_mutex_lock();
784 tgt = osmo_log_vty2tgt(vty);
785 if (!tgt) {
786 log_tgt_mutex_unlock();
787 return CMD_WARNING;
788 }
789
790 nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
791 if (!nse) {
792 vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
793 log_tgt_mutex_unlock();
794 return CMD_WARNING;
795 }
796
797 log_set_nse_filter(tgt, nse);
798 log_tgt_mutex_unlock();
799 return CMD_SUCCESS;
800}
801
Alexander Couzens6a161492020-07-12 13:45:50 +0200802/* TODO: add filter for single connection by description */
803DEFUN(logging_fltr_nsvc,
804 logging_fltr_nsvc_cmd,
805 "logging filter nsvc nsvci <0-65535>",
806 LOGGING_STR FILTER_STR
807 "Filter based on NS Virtual Connection\n"
808 "Identify NS-VC by NSVCI\n"
809 "Numeric identifier\n")
810{
811 struct log_target *tgt;
812 struct gprs_ns2_vc *nsvc;
813 uint16_t id = atoi(argv[1]);
814
815 log_tgt_mutex_lock();
816 tgt = osmo_log_vty2tgt(vty);
817 if (!tgt) {
818 log_tgt_mutex_unlock();
819 return CMD_WARNING;
820 }
821
822 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
823 if (!nsvc) {
824 vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
825 log_tgt_mutex_unlock();
826 return CMD_WARNING;
827 }
828
829 log_set_nsvc_filter(tgt, nsvc);
830 log_tgt_mutex_unlock();
831 return CMD_SUCCESS;
832}
833
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200834/**
835 * gprs_ns2_vty_init initialize the vty
836 * \param[inout] nsi
837 * \param[in] default_bind set the default address to bind to. Can be NULL.
838 * \return 0 on success
839 */
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700840int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
841 const struct osmo_sockaddr_str *default_bind)
Alexander Couzens6a161492020-07-12 13:45:50 +0200842{
843 static bool vty_elements_installed = false;
844
845 vty_nsi = nsi;
846 memset(&priv, 0, sizeof(struct ns2_vty_priv));
847 INIT_LLIST_HEAD(&priv.vtyvc);
848 priv.vc_mode = NS2_VC_MODE_BLOCKRESET;
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200849 if (default_bind)
850 memcpy(&priv.udp, default_bind, sizeof(*default_bind));
Alexander Couzens6a161492020-07-12 13:45:50 +0200851
852 /* Regression test code may call this function repeatedly, so make sure
853 * that VTY elements are not duplicated, which would assert. */
854 if (vty_elements_installed)
855 return 0;
856 vty_elements_installed = true;
857
Harald Welte25ee7552020-12-02 22:14:00 +0100858 install_lib_element_ve(&show_ns_cmd);
Harald Welte2fce19a2020-12-01 17:52:55 +0100859 install_lib_element_ve(&show_ns_binds_cmd);
860 install_lib_element_ve(&show_ns_entities_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700861 install_lib_element_ve(&show_ns_pers_cmd);
862 install_lib_element_ve(&show_nse_cmd);
Daniel Willmann751977b2020-12-02 18:59:44 +0100863 install_lib_element_ve(&logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700864 install_lib_element_ve(&logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200865
Daniel Willmanndbab7142020-11-18 14:19:56 +0100866 install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
867
Daniel Willmann751977b2020-12-02 18:59:44 +0100868 install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700869 install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200870
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700871 install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200872 install_node(&ns_node, config_write_ns);
Alexander Couzens841817e2020-11-19 00:41:29 +0100873 install_lib_element(L_NS_NODE, &cfg_nse_fr_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700874 install_lib_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
875 install_lib_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
876 install_lib_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
877 install_lib_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
878 install_lib_element(L_NS_NODE, &cfg_nse_encaps_cmd);
879 install_lib_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
880 install_lib_element(L_NS_NODE, &cfg_no_nse_cmd);
881 install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
882 install_lib_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);
883 install_lib_element(L_NS_NODE, &cfg_nsip_local_port_cmd);
884 install_lib_element(L_NS_NODE, &cfg_nsip_dscp_cmd);
885 install_lib_element(L_NS_NODE, &cfg_nsip_res_block_unblock_cmd);
886 install_lib_element(L_NS_NODE, &cfg_frgre_enable_cmd);
887 install_lib_element(L_NS_NODE, &cfg_frgre_local_ip_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200888
889 /* TODO: nsvc/nsei command to reset states or reset/block/unblock nsei/nsvcs */
890
891 return 0;
892}
893
894/*!
895 * \brief gprs_ns2_vty_create parse the vty tree into ns nodes
896 * It has to be in different steps to ensure the bind is created before creating VCs.
897 * \return 0 on success
898 */
899int gprs_ns2_vty_create() {
900 struct ns2_vty_vc *vtyvc;
Alexander Couzens841817e2020-11-19 00:41:29 +0100901 struct gprs_ns2_vc_bind *bind, *fr;
Alexander Couzens6a161492020-07-12 13:45:50 +0200902 struct gprs_ns2_nse *nse;
903 struct gprs_ns2_vc *nsvc;
904 struct osmo_sockaddr sockaddr;
Alexander Couzens841817e2020-11-19 00:41:29 +0100905 int rc = 0;
Alexander Couzens6a161492020-07-12 13:45:50 +0200906
907 if (!vty_nsi)
908 return -1;
909
910 /* create binds, only support a single bind. either FR or UDP */
911 if (priv.frgre) {
912 /* TODO not yet supported !*/
913 return -1;
914 } else {
915 /* UDP */
916 osmo_sockaddr_str_to_sockaddr(&priv.udp, &sockaddr.u.sas);
Alexander Couzens477ffb02020-10-01 19:05:28 +0200917 if (gprs_ns2_ip_bind(vty_nsi, &sockaddr, priv.dscp, &bind)) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200918 /* TODO: could not bind on the specific address */
919 return -1;
920 }
921 gprs_ns2_bind_set_mode(bind, priv.vc_mode);
922 }
923
924 /* create vcs */
925 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Alexander Couzens841817e2020-11-19 00:41:29 +0100926 /* validate settings */
927 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100928 case GPRS_NS2_LL_UDP:
Alexander Couzens841817e2020-11-19 00:41:29 +0100929 if (strlen(vtyvc->remote.ip) == 0) {
930 /* Invalid IP for VC */
931 continue;
932 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200933
Alexander Couzens841817e2020-11-19 00:41:29 +0100934 if (!vtyvc->remote.port) {
935 /* Invalid port for VC */
936 continue;
937 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200938
Alexander Couzens841817e2020-11-19 00:41:29 +0100939 if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
940 /* Invalid sockaddr for VC */
941 continue;
942 }
943 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100944 case GPRS_NS2_LL_FR:
Alexander Couzens841817e2020-11-19 00:41:29 +0100945 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100946 case GPRS_NS2_LL_FR_GRE:
Alexander Couzens6a161492020-07-12 13:45:50 +0200947 continue;
948 }
949
950 nse = gprs_ns2_nse_by_nsei(vty_nsi, vtyvc->nsei);
951 if (!nse) {
Alexander Couzensaac90162020-11-19 02:44:04 +0100952 nse = gprs_ns2_create_nse(vty_nsi, vtyvc->nsei, vtyvc->ll);
Alexander Couzens6a161492020-07-12 13:45:50 +0200953 if (!nse) {
954 /* Could not create NSE for VTY */
955 continue;
956 }
957 }
958 nse->persistent = true;
959
Alexander Couzens841817e2020-11-19 00:41:29 +0100960 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100961 case GPRS_NS2_LL_UDP:
Alexander Couzens841817e2020-11-19 00:41:29 +0100962 nsvc = gprs_ns2_ip_connect(bind,
963 &sockaddr,
964 nse,
965 vtyvc->nsvci);
966 if (!nsvc) {
967 /* Could not create NSVC, connect failed */
968 continue;
969 }
970 nsvc->persistent = true;
971 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100972 case GPRS_NS2_LL_FR: {
Alexander Couzens841817e2020-11-19 00:41:29 +0100973 if (vty_fr_network == NULL) {
974 /* TODO: add a switch for BSS/SGSN/gbproxy */
975 vty_fr_network = osmo_fr_network_alloc(vty_nsi);
976 }
977 fr = gprs_ns2_fr_bind_by_netif(
978 vty_nsi,
979 vtyvc->netif);
980 if (!fr) {
981 rc = gprs_ns2_fr_bind(vty_nsi, vtyvc->netif, vty_fr_network, vtyvc->fr.role, &fr);
982 if (rc < 0) {
983 LOGP(DLNS, LOGL_ERROR, "Can not create fr bind on device %s err: %d\n", vtyvc->netif, rc);
984 return rc;
985 }
986 }
987
988 nsvc = gprs_ns2_fr_connect(fr, vtyvc->nsei, vtyvc->nsvci, vtyvc->frdlci);
989 if (!nsvc) {
990 /* Could not create NSVC, connect failed */
991 continue;
992 }
993 nsvc->persistent = true;
994 break;
995 }
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100996 case GPRS_NS2_LL_FR_GRE:
Alexander Couzensd745a0e2020-10-07 00:50:00 +0200997 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200998 }
999 }
1000
1001
1002 return 0;
1003}
1004
1005/*!
1006 * \brief ns2_vty_bind_apply will be called when a new bind is created to apply vty settings
1007 * \param bind
1008 * \return
1009 */
1010void ns2_vty_bind_apply(struct gprs_ns2_vc_bind *bind)
1011{
1012 gprs_ns2_bind_set_mode(bind, priv.vc_mode);
1013}
1014
1015/*!
1016 * \brief ns2_vty_force_vc_mode force a mode and prevents the vty from overwriting it.
1017 * \param force if true mode and reason will be set. false to allow modification via vty.
1018 * \param mode
1019 * \param reason A description shown to the user when a vty command wants to change the mode.
1020 */
Daniel Willmann4fb27a82020-09-25 15:39:46 +02001021void gprs_ns2_vty_force_vc_mode(bool force, enum gprs_ns2_vc_mode mode, const char *reason)
Alexander Couzens6a161492020-07-12 13:45:50 +02001022{
1023 priv.force_vc_mode = force;
1024
1025 if (force) {
1026 priv.vc_mode = mode;
1027 priv.force_vc_mode_reason = reason;
1028 }
1029}