blob: d285c2241346523bc1be994e0588d44b02369a7f [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;
Alexander Couzens6a161492020-07-12 13:45:50 +020065 bool frgre;
66
67 struct llist_head vtyvc;
68};
69
70struct ns2_vty_vc {
71 struct llist_head list;
72
73 struct osmo_sockaddr_str remote;
Alexander Couzens24a14ac2020-11-19 02:34:49 +010074 enum gprs_ns2_ll ll;
Alexander Couzens6a161492020-07-12 13:45:50 +020075
76 /* old vty code doesnt support multiple NSVCI per NSEI */
77 uint16_t nsei;
78 uint16_t nsvci;
79 uint16_t frdlci;
80
Alexander Couzens841817e2020-11-19 00:41:29 +010081 struct {
82 enum osmo_fr_role role;
83 } fr;
84
85 char netif[IF_NAMESIZE];
86
Alexander Couzens6a161492020-07-12 13:45:50 +020087 bool remote_end_is_sgsn;
88 bool configured;
89};
90
91static struct gprs_ns2_inst *vty_nsi = NULL;
92static struct ns2_vty_priv priv;
Alexander Couzens841817e2020-11-19 00:41:29 +010093static struct osmo_fr_network *vty_fr_network = NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +020094
95/* FIXME: this should go to some common file as it is copied
96 * in vty_interface.c of the BSC */
97static const struct value_string gprs_ns_timer_strs[] = {
98 { 0, "tns-block" },
99 { 1, "tns-block-retries" },
100 { 2, "tns-reset" },
101 { 3, "tns-reset-retries" },
102 { 4, "tns-test" },
103 { 5, "tns-alive" },
104 { 6, "tns-alive-retries" },
105 { 7, "tsns-prov" },
106 { 0, NULL }
107};
108
Daniel Willmann751977b2020-12-02 18:59:44 +0100109static void log_set_nse_filter(struct log_target *target,
110 struct gprs_ns2_nse *nse)
111{
112 if (nse) {
113 target->filter_map |= (1 << LOG_FLT_GB_NSE);
114 target->filter_data[LOG_FLT_GB_NSE] = nse;
115 } else if (target->filter_data[LOG_FLT_GB_NSE]) {
116 target->filter_map = ~(1 << LOG_FLT_GB_NSE);
117 target->filter_data[LOG_FLT_GB_NSE] = NULL;
118 }
119}
120
Alexander Couzens6a161492020-07-12 13:45:50 +0200121static void log_set_nsvc_filter(struct log_target *target,
122 struct gprs_ns2_vc *nsvc)
123{
124 if (nsvc) {
125 target->filter_map |= (1 << LOG_FLT_GB_NSVC);
126 target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
127 } else if (target->filter_data[LOG_FLT_GB_NSVC]) {
128 target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
129 target->filter_data[LOG_FLT_GB_NSVC] = NULL;
130 }
131}
132
133static struct cmd_node ns_node = {
134 L_NS_NODE,
135 "%s(config-ns)# ",
136 1,
137};
138
Harald Welte6d4db232020-11-25 19:33:42 +0100139static struct ns2_vty_vc *vtyvc_alloc(uint16_t nsei) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200140 struct ns2_vty_vc *vtyvc = talloc_zero(vty_nsi, struct ns2_vty_vc);
141 if (!vtyvc)
142 return vtyvc;
143
144 vtyvc->nsei = nsei;
145
146 llist_add(&vtyvc->list, &priv.vtyvc);
147
148 return vtyvc;
149}
150
151static void ns2_vc_free(struct ns2_vty_vc *vtyvc) {
152 if (!vtyvc)
153 return;
154
155 llist_del(&vtyvc->list);
156 talloc_free(vtyvc);
157}
158
Harald Welte6d4db232020-11-25 19:33:42 +0100159static struct ns2_vty_vc *vtyvc_by_nsei(uint16_t nsei, bool alloc_missing) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200160 struct ns2_vty_vc *vtyvc;
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200161
Alexander Couzens6a161492020-07-12 13:45:50 +0200162 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Harald Welte6d4db232020-11-25 19:33:42 +0100163 if (vtyvc->nsei == nsei)
Alexander Couzens6a161492020-07-12 13:45:50 +0200164 return vtyvc;
165 }
166
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200167 if (!alloc_missing)
168 return NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +0200169
Harald Welte6d4db232020-11-25 19:33:42 +0100170 vtyvc = vtyvc_alloc(nsei);
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200171 if (!vtyvc)
172 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200173
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200174 vtyvc->nsei = nsei;
175 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200176}
177
178static int config_write_ns(struct vty *vty)
179{
180 struct ns2_vty_vc *vtyvc;
181 unsigned int i;
182 struct osmo_sockaddr_str sockstr;
183
184 vty_out(vty, "ns%s", VTY_NEWLINE);
185
186 /* global configuration must be written first, as some of it may be
187 * relevant when creating the NSE/NSVC later below */
188
189 vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
190 priv.frgre ? 1 : 0, VTY_NEWLINE);
191
192 if (priv.frgre) {
193 if (strlen(priv.frgreaddr.ip)) {
194 vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
195 sockstr.ip, VTY_NEWLINE);
196 }
197 } else {
198 if (strlen(priv.udp.ip)) {
199 vty_out(vty, " encapsulation udp local-ip %s%s",
200 priv.udp.ip, VTY_NEWLINE);
201 }
202
203 if (priv.udp.port)
204 vty_out(vty, " encapsulation udp local-port %u%s",
205 priv.udp.port, VTY_NEWLINE);
206 }
207
208 if (priv.dscp)
209 vty_out(vty, " encapsulation udp dscp %d%s",
210 priv.dscp, VTY_NEWLINE);
211
212 vty_out(vty, " encapsulation udp use-reset-block-unblock %s%s",
213 priv.vc_mode == NS2_VC_MODE_BLOCKRESET ? "enabled" : "disabled", VTY_NEWLINE);
214
215 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
216 vty_out(vty, " nse %u nsvci %u%s",
217 vtyvc->nsei, vtyvc->nsvci, VTY_NEWLINE);
218
Harald Welte6d4db232020-11-25 19:33:42 +0100219 vty_out(vty, " nse %u remote-role %s%s",
220 vtyvc->nsei, vtyvc->remote_end_is_sgsn ? "sgsn" : "bss",
221 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200222
223 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100224 case GPRS_NS2_LL_UDP:
Harald Welte6d4db232020-11-25 19:33:42 +0100225 vty_out(vty, " nse %u encapsulation udp%s", vtyvc->nsei, VTY_NEWLINE);
226 vty_out(vty, " nse %u remote-ip %s%s",
227 vtyvc->nsei,
228 vtyvc->remote.ip,
Alexander Couzens6a161492020-07-12 13:45:50 +0200229 VTY_NEWLINE);
Harald Welte6d4db232020-11-25 19:33:42 +0100230 vty_out(vty, " nse %u remote-port %u%s",
231 vtyvc->nsei, vtyvc->remote.port,
232 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200233 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100234 case GPRS_NS2_LL_FR_GRE:
Harald Welte6d4db232020-11-25 19:33:42 +0100235 vty_out(vty, " nse %u encapsulation framerelay-gre%s",
236 vtyvc->nsei, VTY_NEWLINE);
237 vty_out(vty, " nse %u remote-ip %s%s",
238 vtyvc->nsei,
239 vtyvc->remote.ip,
240 VTY_NEWLINE);
241 vty_out(vty, " nse %u fr-dlci %u%s",
242 vtyvc->nsei, vtyvc->frdlci,
243 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200244 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100245 case GPRS_NS2_LL_FR:
Harald Welte6d4db232020-11-25 19:33:42 +0100246 vty_out(vty, " nse %u fr %s dlci %u%s",
247 vtyvc->nsei, vtyvc->netif, vtyvc->frdlci,
248 VTY_NEWLINE);
Alexander Couzens841817e2020-11-19 00:41:29 +0100249 break;
Alexander Couzens6a161492020-07-12 13:45:50 +0200250 default:
251 break;
252 }
253 }
254
255 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
256 vty_out(vty, " timer %s %u%s",
257 get_value_string(gprs_ns_timer_strs, i),
258 vty_nsi->timeout[i], VTY_NEWLINE);
259
260 return CMD_SUCCESS;
261}
262
263DEFUN(cfg_ns, cfg_ns_cmd,
264 "ns",
265 "Configure the GPRS Network Service")
266{
267 vty->node = L_NS_NODE;
268 return CMD_SUCCESS;
269}
270
271static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
272{
Harald Weltedc2d0802020-12-01 18:17:28 +0100273 char nsvci_str[32];
274
275 if (nsvc->nsvci_is_valid)
276 snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
277 else
278 snprintf(nsvci_str, sizeof(nsvci_str), "none");
279
280 vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
281 osmo_fsm_inst_state_name(nsvc->fi),
282 nsvc->persistent ? "PERSIST" : "DYNAMIC",
283 nsvc->data_weight, nsvc->sig_weight,
284 gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200285
286 if (stats) {
Harald Welte7aa60992020-12-01 17:53:17 +0100287 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
288 vty_out_stat_item_group(vty, " ", nsvc->statg);
Alexander Couzens6a161492020-07-12 13:45:50 +0200289 }
290}
291
292static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
293{
294 struct gprs_ns2_vc *nsvc;
295
Harald Welte0ff12ad2020-12-01 17:51:07 +0100296 vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
297 nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200298
299 gprs_ns2_sns_dump_vty(vty, nse, stats);
300 llist_for_each_entry(nsvc, &nse->nsvc, list) {
301 if (persistent_only) {
302 if (nsvc->persistent)
303 dump_nsvc(vty, nsvc, stats);
304 } else {
305 dump_nsvc(vty, nsvc, stats);
306 }
307 }
308}
309
Alexander Couzens22f34712020-10-02 02:34:39 +0200310static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
311{
312 if (bind->dump_vty)
313 bind->dump_vty(bind, vty, stats);
314}
315
Harald Welte2fce19a2020-12-01 17:52:55 +0100316static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +0200317{
Alexander Couzens22f34712020-10-02 02:34:39 +0200318 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6a161492020-07-12 13:45:50 +0200319
Alexander Couzens22f34712020-10-02 02:34:39 +0200320 llist_for_each_entry(bind, &nsi->binding, list) {
321 dump_bind(vty, bind, stats);
322 }
Harald Welte2fce19a2020-12-01 17:52:55 +0100323}
324
325
326static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
327{
328 struct gprs_ns2_nse *nse;
Alexander Couzens22f34712020-10-02 02:34:39 +0200329
Alexander Couzens6a161492020-07-12 13:45:50 +0200330 llist_for_each_entry(nse, &nsi->nse, list) {
331 dump_nse(vty, nse, stats, persistent_only);
Alexander Couzens6a161492020-07-12 13:45:50 +0200332 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200333}
334
Harald Welte25ee7552020-12-02 22:14:00 +0100335/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
336 * 'show ns' to output something about binds */
337DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
338 SHOW_STR SHOW_NS_STR)
339{
340 dump_ns_entities(vty, vty_nsi, false, false);
341 dump_ns_bind(vty, vty_nsi, false);
342 return CMD_SUCCESS;
343}
344
345
Harald Welte2fce19a2020-12-01 17:52:55 +0100346DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100347 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100348 "Display information about the NS protocol binds\n"
349 "Include statistic\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200350{
Harald Welte2fce19a2020-12-01 17:52:55 +0100351 bool stats = false;
352 if (argc > 0)
353 stats = true;
354
355 dump_ns_bind(vty, vty_nsi, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +0200356 return CMD_SUCCESS;
357}
358
Harald Welte2fce19a2020-12-01 17:52:55 +0100359DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100360 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100361 "Display information about the NS protocol entities (NSEs)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200362 "Include statistics\n")
363{
Harald Welte2fce19a2020-12-01 17:52:55 +0100364 bool stats = false;
365 if (argc > 0)
366 stats = true;
367
368 dump_ns_entities(vty, vty_nsi, stats, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200369 return CMD_SUCCESS;
370}
371
372DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100373 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200374 "Show only persistent NS\n")
375{
Harald Welte2fce19a2020-12-01 17:52:55 +0100376 dump_ns_entities(vty, vty_nsi, true, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200377 return CMD_SUCCESS;
378}
379
380DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100381 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200382 "Select one NSE by its NSE Identifier\n"
383 "Select one NSE by its NS-VC Identifier\n"
384 "The Identifier of selected type\n"
385 "Include Statistics\n")
386{
387 struct gprs_ns2_inst *nsi = vty_nsi;
388 struct gprs_ns2_nse *nse;
389 struct gprs_ns2_vc *nsvc;
390 uint16_t id = atoi(argv[1]);
391 bool show_stats = false;
392
393 if (argc >= 3)
394 show_stats = true;
395
396 if (!strcmp(argv[0], "nsei")) {
397 nse = gprs_ns2_nse_by_nsei(nsi, id);
398 if (!nse) {
399 return CMD_WARNING;
400 }
401
402 dump_nse(vty, nse, show_stats, false);
403 } else {
404 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
405
406 if (!nsvc) {
407 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
408 return CMD_WARNING;
409 }
410
411 dump_nsvc(vty, nsvc, show_stats);
412 }
413
414 return CMD_SUCCESS;
415}
416
Daniel Willmanndbab7142020-11-18 14:19:56 +0100417static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
418{
419 gprs_ns2_vc_force_unconfigured(nsvc);
420 return 0;
421}
422
423DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
424 "nsvc nsei <0-65535> force-unconfigured",
425 "NS Virtual Connection\n"
426 "The NSEI\n"
427 "Reset the NSVCs back to initial state\n"
428 )
429{
430 struct gprs_ns2_inst *nsi = vty_nsi;
431 struct gprs_ns2_nse *nse;
432
433 uint16_t id = atoi(argv[0]);
434
435 nse = gprs_ns2_nse_by_nsei(nsi, id);
436 if (!nse) {
437 vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
438 return CMD_WARNING;
439 }
440
441 /* Perform the operation for all nsvc */
442 gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
443
444 return CMD_SUCCESS;
445}
446
Alexander Couzens6a161492020-07-12 13:45:50 +0200447#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
448
Alexander Couzens841817e2020-11-19 00:41:29 +0100449DEFUN(cfg_nse_fr, cfg_nse_fr_cmd,
450 "nse <0-65535> nsvci <0-65535> (fr|frnet) NETIF dlci <0-1023>",
451 NSE_CMD_STR
452 "NS Virtual Connection\n"
453 "NS Virtual Connection ID (NSVCI)\n"
Harald Welte92049192020-11-25 20:56:06 +0100454 "Frame Relay User-Side\n"
455 "Frame Relay Network-Side\n"
Alexander Couzens841817e2020-11-19 00:41:29 +0100456 IFNAME_STR
457 "Data Link connection identifier\n"
458 "Data Link connection identifier\n"
459 )
460{
461 struct ns2_vty_vc *vtyvc;
462
463 uint16_t nsei = atoi(argv[0]);
464 uint16_t nsvci = atoi(argv[1]);
465 const char *role = argv[2];
466 const char *name = argv[3];
467 uint16_t dlci = atoi(argv[4]);
468
Harald Welte6d4db232020-11-25 19:33:42 +0100469 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens841817e2020-11-19 00:41:29 +0100470 if (!vtyvc) {
471 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
472 return CMD_WARNING;
473 }
474
475 if (!strcmp(role, "fr"))
476 vtyvc->fr.role = FR_ROLE_USER_EQUIPMENT;
477 else if (!strcmp(role, "frnet"))
478 vtyvc->fr.role = FR_ROLE_NETWORK_EQUIPMENT;
479
480 osmo_strlcpy(vtyvc->netif, name, sizeof(vtyvc->netif));
481 vtyvc->frdlci = dlci;
482 vtyvc->nsvci = nsvci;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100483 vtyvc->ll = GPRS_NS2_LL_FR;
Alexander Couzens841817e2020-11-19 00:41:29 +0100484
485 return CMD_SUCCESS;
486}
487
Alexander Couzens6a161492020-07-12 13:45:50 +0200488DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
489 "nse <0-65535> nsvci <0-65535>",
490 NSE_CMD_STR
491 "NS Virtual Connection\n"
492 "NS Virtual Connection ID (NSVCI)\n"
493 )
494{
495 struct ns2_vty_vc *vtyvc;
496
497 uint16_t nsei = atoi(argv[0]);
498 uint16_t nsvci = atoi(argv[1]);
499
Harald Welte6d4db232020-11-25 19:33:42 +0100500 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200501 if (!vtyvc) {
502 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
503 return CMD_WARNING;
504 }
505
506 vtyvc->nsvci = nsvci;
507
508 return CMD_SUCCESS;
509}
510
511DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100512 "nse <0-65535> remote-ip " VTY_IPV46_CMD,
Alexander Couzens6a161492020-07-12 13:45:50 +0200513 NSE_CMD_STR
514 "Remote IP Address\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200515 "Remote IPv4 Address\n"
516 "Remote IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200517{
518 uint16_t nsei = atoi(argv[0]);
519 struct ns2_vty_vc *vtyvc;
520
Harald Welte6d4db232020-11-25 19:33:42 +0100521 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200522 if (!vtyvc) {
523 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
524 return CMD_WARNING;
525 }
526
Harald Welte6d4db232020-11-25 19:33:42 +0100527 osmo_sockaddr_str_from_str2(&vtyvc->remote, argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200528
529 return CMD_SUCCESS;
530}
531
532DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100533 "nse <0-65535> remote-port <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200534 NSE_CMD_STR
535 "Remote UDP Port\n"
536 "Remote UDP Port Number\n")
537{
538 uint16_t nsei = atoi(argv[0]);
Harald Welte6d4db232020-11-25 19:33:42 +0100539 uint16_t port = atoi(argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200540 struct ns2_vty_vc *vtyvc;
541
Harald Welte6d4db232020-11-25 19:33:42 +0100542 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200543 if (!vtyvc) {
544 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
545 return CMD_WARNING;
546 }
547
548 vtyvc->remote.port = port;
549
550 return CMD_SUCCESS;
551}
552
553DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
Alexander Couzens841817e2020-11-19 00:41:29 +0100554 "nse <0-65535> nsvci <0-65535> fr-dlci <16-1007>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200555 NSE_CMD_STR
Harald Welte92049192020-11-25 20:56:06 +0100556 "NS Virtual Connection\n"
557 "NS Virtual Connection ID (NSVCI)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200558 "Frame Relay DLCI\n"
559 "Frame Relay DLCI Number\n")
560{
561 uint16_t nsei = atoi(argv[0]);
Alexander Couzens841817e2020-11-19 00:41:29 +0100562 uint16_t nsvci = atoi(argv[1]);
563 uint16_t dlci = atoi(argv[2]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200564 struct ns2_vty_vc *vtyvc;
565
Harald Welte6d4db232020-11-25 19:33:42 +0100566 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200567 if (!vtyvc) {
568 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
569 return CMD_WARNING;
570 }
571
Alexander Couzens6a161492020-07-12 13:45:50 +0200572 vtyvc->frdlci = dlci;
Harald Welte6d4db232020-11-25 19:33:42 +0100573 vtyvc->nsvci = nsvci;
Alexander Couzens6a161492020-07-12 13:45:50 +0200574
575 return CMD_SUCCESS;
576}
577
578DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100579 "nse <0-65535> encapsulation (udp|framerelay-gre)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200580 NSE_CMD_STR
581 "Encapsulation for NS\n"
582 "UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
583{
584 uint16_t nsei = atoi(argv[0]);
585 struct ns2_vty_vc *vtyvc;
586
Harald Welte6d4db232020-11-25 19:33:42 +0100587 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200588 if (!vtyvc) {
589 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
590 return CMD_WARNING;
591 }
592
Harald Welte6d4db232020-11-25 19:33:42 +0100593 if (!strcmp(argv[1], "udp"))
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100594 vtyvc->ll = GPRS_NS2_LL_UDP;
Alexander Couzens6a161492020-07-12 13:45:50 +0200595 else
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100596 vtyvc->ll = GPRS_NS2_LL_FR_GRE;
Alexander Couzens6a161492020-07-12 13:45:50 +0200597
598 return CMD_SUCCESS;
599}
600
601DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100602 "nse <0-65535> remote-role (sgsn|bss)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200603 NSE_CMD_STR
604 "Remote NSE Role\n"
605 "Remote Peer is SGSN\n"
606 "Remote Peer is BSS\n")
607{
608 uint16_t nsei = atoi(argv[0]);
609 struct ns2_vty_vc *vtyvc;
610
Harald Welte6d4db232020-11-25 19:33:42 +0100611 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200612 if (!vtyvc) {
613 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
614 return CMD_WARNING;
615 }
616
Harald Welte6d4db232020-11-25 19:33:42 +0100617 if (!strcmp(argv[1], "sgsn"))
Alexander Couzens6a161492020-07-12 13:45:50 +0200618 vtyvc->remote_end_is_sgsn = 1;
619 else
620 vtyvc->remote_end_is_sgsn = 0;
621
622 return CMD_SUCCESS;
623}
624
625DEFUN(cfg_no_nse, cfg_no_nse_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100626 "no nse <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200627 "Delete Persistent NS Entity\n"
628 "Delete " NSE_CMD_STR)
629{
630 uint16_t nsei = atoi(argv[0]);
631 struct ns2_vty_vc *vtyvc;
632
Harald Welte6d4db232020-11-25 19:33:42 +0100633 vtyvc = vtyvc_by_nsei(nsei, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200634 if (!vtyvc) {
635 vty_out(vty, "The NSE %d does not exists.%s", nsei, VTY_NEWLINE);
636 return CMD_WARNING;
637 }
638
639 ns2_vc_free(vtyvc);
640
641 return CMD_SUCCESS;
642}
643
644DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
645 "timer " NS_TIMERS " <0-65535>",
646 "Network Service Timer\n"
647 NS_TIMERS_HELP "Timer Value\n")
648{
649 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
650 int val = atoi(argv[1]);
651
652 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
653 return CMD_WARNING;
654
655 vty_nsi->timeout[idx] = val;
656
657 return CMD_SUCCESS;
658}
659
660#define ENCAPS_STR "NS encapsulation options\n"
661
662DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
663 "encapsulation udp local-ip " VTY_IPV46_CMD,
664 ENCAPS_STR "NS over UDP Encapsulation\n"
665 "Set the IP address on which we listen for NS/UDP\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200666 "IPv4 Address\n"
667 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200668{
669 osmo_sockaddr_str_from_str2(&priv.udp, argv[0]);
670
671 return CMD_SUCCESS;
672}
673
674DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
675 "encapsulation udp local-port <0-65535>",
676 ENCAPS_STR "NS over UDP Encapsulation\n"
677 "Set the UDP port on which we listen for NS/UDP\n"
678 "UDP port number\n")
679{
680 unsigned int port = atoi(argv[0]);
681
682 priv.udp.port = port;
683
684 return CMD_SUCCESS;
685}
686
687DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd,
688 "encapsulation udp dscp <0-255>",
689 ENCAPS_STR "NS over UDP Encapsulation\n"
690 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
691{
692 int dscp = atoi(argv[0]);
693 struct gprs_ns2_vc_bind *bind;
694
695 priv.dscp = dscp;
696
697 llist_for_each_entry(bind, &vty_nsi->binding, list) {
698 if (gprs_ns2_is_ip_bind(bind))
699 gprs_ns2_ip_bind_set_dscp(bind, dscp);
700 }
701
702 return CMD_SUCCESS;
703}
704
705DEFUN(cfg_nsip_res_block_unblock, cfg_nsip_res_block_unblock_cmd,
706 "encapsulation udp use-reset-block-unblock (enabled|disabled)",
707 ENCAPS_STR "NS over UDP Encapsulation\n"
708 "Use NS-{RESET,BLOCK,UNBLOCK} procedures in violation of 3GPP TS 48.016\n"
709 "Enable NS-{RESET,BLOCK,UNBLOCK}\n"
710 "Disable NS-{RESET,BLOCK,UNBLOCK}\n")
711{
712 enum gprs_ns2_vc_mode vc_mode;
Alexander Couzens6a161492020-07-12 13:45:50 +0200713
714 if (!strcmp(argv[0], "enabled"))
715 vc_mode = NS2_VC_MODE_BLOCKRESET;
716 else
717 vc_mode = NS2_VC_MODE_ALIVE;
718
Alexander Couzens6a161492020-07-12 13:45:50 +0200719 priv.vc_mode = vc_mode;
720
Alexander Couzens6a161492020-07-12 13:45:50 +0200721 return CMD_SUCCESS;
722}
723
724DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
725 "encapsulation framerelay-gre local-ip " VTY_IPV46_CMD,
726 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
727 "Set the IP address on which we listen for NS/FR/GRE\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200728 "IPv4 Address\n"
729 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200730{
731 osmo_sockaddr_str_from_str2(&priv.frgreaddr, argv[0]);
732
733 return CMD_SUCCESS;
734}
735
736DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
737 "encapsulation framerelay-gre enabled (1|0)",
738 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
739 "Enable or disable Frame Relay over GRE\n"
740 "Enable\n" "Disable\n")
741{
742 int enabled = atoi(argv[0]);
743
744 priv.frgre = enabled;
745
746 return CMD_SUCCESS;
747}
748
749/* TODO: allow vty to reset/block/unblock nsvc/nsei */
750
Daniel Willmann751977b2020-12-02 18:59:44 +0100751DEFUN(logging_fltr_nse,
752 logging_fltr_nse_cmd,
753 "logging filter nse nsei <0-65535>",
754 LOGGING_STR FILTER_STR
755 "Filter based on NS Entity\n"
756 "Identify NSE by NSEI\n"
757 "Numeric identifier\n")
758{
759 struct log_target *tgt;
760 struct gprs_ns2_nse *nse;
Daniel Willmann89106522020-12-04 01:36:59 +0100761 uint16_t id = atoi(argv[0]);
Daniel Willmann751977b2020-12-02 18:59:44 +0100762
763 log_tgt_mutex_lock();
764 tgt = osmo_log_vty2tgt(vty);
765 if (!tgt) {
766 log_tgt_mutex_unlock();
767 return CMD_WARNING;
768 }
769
770 nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
771 if (!nse) {
772 vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
773 log_tgt_mutex_unlock();
774 return CMD_WARNING;
775 }
776
777 log_set_nse_filter(tgt, nse);
778 log_tgt_mutex_unlock();
779 return CMD_SUCCESS;
780}
781
Alexander Couzens6a161492020-07-12 13:45:50 +0200782/* TODO: add filter for single connection by description */
783DEFUN(logging_fltr_nsvc,
784 logging_fltr_nsvc_cmd,
785 "logging filter nsvc nsvci <0-65535>",
786 LOGGING_STR FILTER_STR
787 "Filter based on NS Virtual Connection\n"
788 "Identify NS-VC by NSVCI\n"
789 "Numeric identifier\n")
790{
791 struct log_target *tgt;
792 struct gprs_ns2_vc *nsvc;
Daniel Willmann89106522020-12-04 01:36:59 +0100793 uint16_t id = atoi(argv[0]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200794
795 log_tgt_mutex_lock();
796 tgt = osmo_log_vty2tgt(vty);
797 if (!tgt) {
798 log_tgt_mutex_unlock();
799 return CMD_WARNING;
800 }
801
802 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
803 if (!nsvc) {
804 vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
805 log_tgt_mutex_unlock();
806 return CMD_WARNING;
807 }
808
809 log_set_nsvc_filter(tgt, nsvc);
810 log_tgt_mutex_unlock();
811 return CMD_SUCCESS;
812}
813
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200814/**
815 * gprs_ns2_vty_init initialize the vty
816 * \param[inout] nsi
817 * \param[in] default_bind set the default address to bind to. Can be NULL.
818 * \return 0 on success
819 */
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700820int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
821 const struct osmo_sockaddr_str *default_bind)
Alexander Couzens6a161492020-07-12 13:45:50 +0200822{
823 static bool vty_elements_installed = false;
824
825 vty_nsi = nsi;
826 memset(&priv, 0, sizeof(struct ns2_vty_priv));
827 INIT_LLIST_HEAD(&priv.vtyvc);
828 priv.vc_mode = NS2_VC_MODE_BLOCKRESET;
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200829 if (default_bind)
830 memcpy(&priv.udp, default_bind, sizeof(*default_bind));
Alexander Couzens6a161492020-07-12 13:45:50 +0200831
832 /* Regression test code may call this function repeatedly, so make sure
833 * that VTY elements are not duplicated, which would assert. */
834 if (vty_elements_installed)
835 return 0;
836 vty_elements_installed = true;
837
Harald Welte25ee7552020-12-02 22:14:00 +0100838 install_lib_element_ve(&show_ns_cmd);
Harald Welte2fce19a2020-12-01 17:52:55 +0100839 install_lib_element_ve(&show_ns_binds_cmd);
840 install_lib_element_ve(&show_ns_entities_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700841 install_lib_element_ve(&show_ns_pers_cmd);
842 install_lib_element_ve(&show_nse_cmd);
Daniel Willmann751977b2020-12-02 18:59:44 +0100843 install_lib_element_ve(&logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700844 install_lib_element_ve(&logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200845
Daniel Willmanndbab7142020-11-18 14:19:56 +0100846 install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
847
Daniel Willmann751977b2020-12-02 18:59:44 +0100848 install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700849 install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200850
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700851 install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200852 install_node(&ns_node, config_write_ns);
Alexander Couzens841817e2020-11-19 00:41:29 +0100853 install_lib_element(L_NS_NODE, &cfg_nse_fr_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700854 install_lib_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
855 install_lib_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
856 install_lib_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
857 install_lib_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
858 install_lib_element(L_NS_NODE, &cfg_nse_encaps_cmd);
859 install_lib_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
860 install_lib_element(L_NS_NODE, &cfg_no_nse_cmd);
861 install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
862 install_lib_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);
863 install_lib_element(L_NS_NODE, &cfg_nsip_local_port_cmd);
864 install_lib_element(L_NS_NODE, &cfg_nsip_dscp_cmd);
865 install_lib_element(L_NS_NODE, &cfg_nsip_res_block_unblock_cmd);
866 install_lib_element(L_NS_NODE, &cfg_frgre_enable_cmd);
867 install_lib_element(L_NS_NODE, &cfg_frgre_local_ip_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200868
869 /* TODO: nsvc/nsei command to reset states or reset/block/unblock nsei/nsvcs */
870
871 return 0;
872}
873
874/*!
875 * \brief gprs_ns2_vty_create parse the vty tree into ns nodes
876 * It has to be in different steps to ensure the bind is created before creating VCs.
877 * \return 0 on success
878 */
879int gprs_ns2_vty_create() {
880 struct ns2_vty_vc *vtyvc;
Alexander Couzens841817e2020-11-19 00:41:29 +0100881 struct gprs_ns2_vc_bind *bind, *fr;
Alexander Couzens6a161492020-07-12 13:45:50 +0200882 struct gprs_ns2_nse *nse;
883 struct gprs_ns2_vc *nsvc;
884 struct osmo_sockaddr sockaddr;
Alexander Couzensd923cff2020-12-01 01:03:52 +0100885 enum gprs_ns2_dialect dialect = NS2_DIALECT_UNDEF;
Alexander Couzens841817e2020-11-19 00:41:29 +0100886 int rc = 0;
Alexander Couzens6a161492020-07-12 13:45:50 +0200887
888 if (!vty_nsi)
889 return -1;
890
891 /* create binds, only support a single bind. either FR or UDP */
892 if (priv.frgre) {
893 /* TODO not yet supported !*/
894 return -1;
895 } else {
896 /* UDP */
897 osmo_sockaddr_str_to_sockaddr(&priv.udp, &sockaddr.u.sas);
Alexander Couzens477ffb02020-10-01 19:05:28 +0200898 if (gprs_ns2_ip_bind(vty_nsi, &sockaddr, priv.dscp, &bind)) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200899 /* TODO: could not bind on the specific address */
900 return -1;
901 }
Alexander Couzensd923cff2020-12-01 01:03:52 +0100902 bind->accept_ipaccess = true;
Alexander Couzens6a161492020-07-12 13:45:50 +0200903 }
904
905 /* create vcs */
906 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Alexander Couzens841817e2020-11-19 00:41:29 +0100907 /* validate settings */
908 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100909 case GPRS_NS2_LL_UDP:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100910 dialect = NS2_DIALECT_IPACCESS;
Alexander Couzens841817e2020-11-19 00:41:29 +0100911 if (strlen(vtyvc->remote.ip) == 0) {
912 /* Invalid IP for VC */
913 continue;
914 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200915
Alexander Couzens841817e2020-11-19 00:41:29 +0100916 if (!vtyvc->remote.port) {
917 /* Invalid port for VC */
918 continue;
919 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200920
Alexander Couzens841817e2020-11-19 00:41:29 +0100921 if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
922 /* Invalid sockaddr for VC */
923 continue;
924 }
925 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100926 case GPRS_NS2_LL_FR:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100927 dialect = NS2_DIALECT_STATIC_RESETBLOCK;
Alexander Couzens841817e2020-11-19 00:41:29 +0100928 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100929 case GPRS_NS2_LL_FR_GRE:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100930 dialect = NS2_DIALECT_STATIC_RESETBLOCK;
Alexander Couzens6a161492020-07-12 13:45:50 +0200931 continue;
932 }
933
934 nse = gprs_ns2_nse_by_nsei(vty_nsi, vtyvc->nsei);
935 if (!nse) {
Alexander Couzensd923cff2020-12-01 01:03:52 +0100936 nse = gprs_ns2_create_nse(vty_nsi, vtyvc->nsei, vtyvc->ll, dialect);
Alexander Couzens6a161492020-07-12 13:45:50 +0200937 if (!nse) {
938 /* Could not create NSE for VTY */
939 continue;
940 }
941 }
942 nse->persistent = true;
943
Alexander Couzens841817e2020-11-19 00:41:29 +0100944 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100945 case GPRS_NS2_LL_UDP:
Alexander Couzens841817e2020-11-19 00:41:29 +0100946 nsvc = gprs_ns2_ip_connect(bind,
947 &sockaddr,
948 nse,
949 vtyvc->nsvci);
950 if (!nsvc) {
951 /* Could not create NSVC, connect failed */
952 continue;
953 }
954 nsvc->persistent = true;
955 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100956 case GPRS_NS2_LL_FR: {
Alexander Couzens841817e2020-11-19 00:41:29 +0100957 if (vty_fr_network == NULL) {
958 /* TODO: add a switch for BSS/SGSN/gbproxy */
959 vty_fr_network = osmo_fr_network_alloc(vty_nsi);
960 }
961 fr = gprs_ns2_fr_bind_by_netif(
962 vty_nsi,
963 vtyvc->netif);
964 if (!fr) {
965 rc = gprs_ns2_fr_bind(vty_nsi, vtyvc->netif, vty_fr_network, vtyvc->fr.role, &fr);
966 if (rc < 0) {
967 LOGP(DLNS, LOGL_ERROR, "Can not create fr bind on device %s err: %d\n", vtyvc->netif, rc);
968 return rc;
969 }
970 }
971
972 nsvc = gprs_ns2_fr_connect(fr, vtyvc->nsei, vtyvc->nsvci, vtyvc->frdlci);
973 if (!nsvc) {
974 /* Could not create NSVC, connect failed */
975 continue;
976 }
977 nsvc->persistent = true;
978 break;
979 }
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100980 case GPRS_NS2_LL_FR_GRE:
Alexander Couzensd745a0e2020-10-07 00:50:00 +0200981 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200982 }
983 }
984
985
986 return 0;
987}