blob: 742f181d112e2e2897142630ceeea74803414bd7 [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" },
Harald Welte33c3c062020-12-16 11:59:19 +0100106 { 8, "tsns-size-retries" },
107 { 9, "tsns-config-retries" },
Alexander Couzens6a161492020-07-12 13:45:50 +0200108 { 0, NULL }
109};
110
Daniel Willmann751977b2020-12-02 18:59:44 +0100111static void log_set_nse_filter(struct log_target *target,
112 struct gprs_ns2_nse *nse)
113{
114 if (nse) {
115 target->filter_map |= (1 << LOG_FLT_GB_NSE);
116 target->filter_data[LOG_FLT_GB_NSE] = nse;
117 } else if (target->filter_data[LOG_FLT_GB_NSE]) {
118 target->filter_map = ~(1 << LOG_FLT_GB_NSE);
119 target->filter_data[LOG_FLT_GB_NSE] = NULL;
120 }
121}
122
Alexander Couzens6a161492020-07-12 13:45:50 +0200123static void log_set_nsvc_filter(struct log_target *target,
124 struct gprs_ns2_vc *nsvc)
125{
126 if (nsvc) {
127 target->filter_map |= (1 << LOG_FLT_GB_NSVC);
128 target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
129 } else if (target->filter_data[LOG_FLT_GB_NSVC]) {
130 target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
131 target->filter_data[LOG_FLT_GB_NSVC] = NULL;
132 }
133}
134
135static struct cmd_node ns_node = {
136 L_NS_NODE,
137 "%s(config-ns)# ",
138 1,
139};
140
Harald Welte6d4db232020-11-25 19:33:42 +0100141static struct ns2_vty_vc *vtyvc_alloc(uint16_t nsei) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200142 struct ns2_vty_vc *vtyvc = talloc_zero(vty_nsi, struct ns2_vty_vc);
143 if (!vtyvc)
144 return vtyvc;
145
146 vtyvc->nsei = nsei;
147
148 llist_add(&vtyvc->list, &priv.vtyvc);
149
150 return vtyvc;
151}
152
153static void ns2_vc_free(struct ns2_vty_vc *vtyvc) {
154 if (!vtyvc)
155 return;
156
157 llist_del(&vtyvc->list);
158 talloc_free(vtyvc);
159}
160
Harald Welte6d4db232020-11-25 19:33:42 +0100161static struct ns2_vty_vc *vtyvc_by_nsei(uint16_t nsei, bool alloc_missing) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200162 struct ns2_vty_vc *vtyvc;
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200163
Alexander Couzens6a161492020-07-12 13:45:50 +0200164 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Harald Welte6d4db232020-11-25 19:33:42 +0100165 if (vtyvc->nsei == nsei)
Alexander Couzens6a161492020-07-12 13:45:50 +0200166 return vtyvc;
167 }
168
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200169 if (!alloc_missing)
170 return NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +0200171
Harald Welte6d4db232020-11-25 19:33:42 +0100172 vtyvc = vtyvc_alloc(nsei);
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200173 if (!vtyvc)
174 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200175
Alexander Couzens1f0625f2020-09-23 18:22:20 +0200176 vtyvc->nsei = nsei;
177 return vtyvc;
Alexander Couzens6a161492020-07-12 13:45:50 +0200178}
179
180static int config_write_ns(struct vty *vty)
181{
182 struct ns2_vty_vc *vtyvc;
183 unsigned int i;
184 struct osmo_sockaddr_str sockstr;
185
186 vty_out(vty, "ns%s", VTY_NEWLINE);
187
188 /* global configuration must be written first, as some of it may be
189 * relevant when creating the NSE/NSVC later below */
190
191 vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
192 priv.frgre ? 1 : 0, VTY_NEWLINE);
193
194 if (priv.frgre) {
195 if (strlen(priv.frgreaddr.ip)) {
196 vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
197 sockstr.ip, VTY_NEWLINE);
198 }
199 } else {
200 if (strlen(priv.udp.ip)) {
201 vty_out(vty, " encapsulation udp local-ip %s%s",
202 priv.udp.ip, VTY_NEWLINE);
203 }
204
205 if (priv.udp.port)
206 vty_out(vty, " encapsulation udp local-port %u%s",
207 priv.udp.port, VTY_NEWLINE);
208 }
209
210 if (priv.dscp)
211 vty_out(vty, " encapsulation udp dscp %d%s",
212 priv.dscp, VTY_NEWLINE);
213
214 vty_out(vty, " encapsulation udp use-reset-block-unblock %s%s",
215 priv.vc_mode == NS2_VC_MODE_BLOCKRESET ? "enabled" : "disabled", VTY_NEWLINE);
216
217 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
218 vty_out(vty, " nse %u nsvci %u%s",
219 vtyvc->nsei, vtyvc->nsvci, VTY_NEWLINE);
220
Harald Welte6d4db232020-11-25 19:33:42 +0100221 vty_out(vty, " nse %u remote-role %s%s",
222 vtyvc->nsei, vtyvc->remote_end_is_sgsn ? "sgsn" : "bss",
223 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200224
225 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100226 case GPRS_NS2_LL_UDP:
Harald Welte6d4db232020-11-25 19:33:42 +0100227 vty_out(vty, " nse %u encapsulation udp%s", vtyvc->nsei, VTY_NEWLINE);
228 vty_out(vty, " nse %u remote-ip %s%s",
229 vtyvc->nsei,
230 vtyvc->remote.ip,
Alexander Couzens6a161492020-07-12 13:45:50 +0200231 VTY_NEWLINE);
Harald Welte6d4db232020-11-25 19:33:42 +0100232 vty_out(vty, " nse %u remote-port %u%s",
233 vtyvc->nsei, vtyvc->remote.port,
234 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200235 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100236 case GPRS_NS2_LL_FR_GRE:
Harald Welte6d4db232020-11-25 19:33:42 +0100237 vty_out(vty, " nse %u encapsulation framerelay-gre%s",
238 vtyvc->nsei, VTY_NEWLINE);
239 vty_out(vty, " nse %u remote-ip %s%s",
240 vtyvc->nsei,
241 vtyvc->remote.ip,
242 VTY_NEWLINE);
243 vty_out(vty, " nse %u fr-dlci %u%s",
244 vtyvc->nsei, vtyvc->frdlci,
245 VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200246 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100247 case GPRS_NS2_LL_FR:
Harald Welte6d4db232020-11-25 19:33:42 +0100248 vty_out(vty, " nse %u fr %s dlci %u%s",
249 vtyvc->nsei, vtyvc->netif, vtyvc->frdlci,
250 VTY_NEWLINE);
Alexander Couzens841817e2020-11-19 00:41:29 +0100251 break;
Alexander Couzens6a161492020-07-12 13:45:50 +0200252 default:
253 break;
254 }
255 }
256
257 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
258 vty_out(vty, " timer %s %u%s",
259 get_value_string(gprs_ns_timer_strs, i),
260 vty_nsi->timeout[i], VTY_NEWLINE);
261
262 return CMD_SUCCESS;
263}
264
265DEFUN(cfg_ns, cfg_ns_cmd,
266 "ns",
267 "Configure the GPRS Network Service")
268{
269 vty->node = L_NS_NODE;
270 return CMD_SUCCESS;
271}
272
273static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
274{
Harald Weltedc2d0802020-12-01 18:17:28 +0100275 char nsvci_str[32];
276
277 if (nsvc->nsvci_is_valid)
278 snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
279 else
280 snprintf(nsvci_str, sizeof(nsvci_str), "none");
281
282 vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
283 osmo_fsm_inst_state_name(nsvc->fi),
284 nsvc->persistent ? "PERSIST" : "DYNAMIC",
285 nsvc->data_weight, nsvc->sig_weight,
286 gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200287
288 if (stats) {
Harald Welte7aa60992020-12-01 17:53:17 +0100289 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
290 vty_out_stat_item_group(vty, " ", nsvc->statg);
Alexander Couzens6a161492020-07-12 13:45:50 +0200291 }
292}
293
294static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
295{
296 struct gprs_ns2_vc *nsvc;
297
Harald Welte0ff12ad2020-12-01 17:51:07 +0100298 vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
299 nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +0200300
301 gprs_ns2_sns_dump_vty(vty, nse, stats);
302 llist_for_each_entry(nsvc, &nse->nsvc, list) {
303 if (persistent_only) {
304 if (nsvc->persistent)
305 dump_nsvc(vty, nsvc, stats);
306 } else {
307 dump_nsvc(vty, nsvc, stats);
308 }
309 }
310}
311
Alexander Couzens22f34712020-10-02 02:34:39 +0200312static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
313{
314 if (bind->dump_vty)
315 bind->dump_vty(bind, vty, stats);
316}
317
Harald Welte2fce19a2020-12-01 17:52:55 +0100318static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +0200319{
Alexander Couzens22f34712020-10-02 02:34:39 +0200320 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6a161492020-07-12 13:45:50 +0200321
Alexander Couzens22f34712020-10-02 02:34:39 +0200322 llist_for_each_entry(bind, &nsi->binding, list) {
323 dump_bind(vty, bind, stats);
324 }
Harald Welte2fce19a2020-12-01 17:52:55 +0100325}
326
327
328static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
329{
330 struct gprs_ns2_nse *nse;
Alexander Couzens22f34712020-10-02 02:34:39 +0200331
Alexander Couzens6a161492020-07-12 13:45:50 +0200332 llist_for_each_entry(nse, &nsi->nse, list) {
333 dump_nse(vty, nse, stats, persistent_only);
Alexander Couzens6a161492020-07-12 13:45:50 +0200334 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200335}
336
Harald Welte25ee7552020-12-02 22:14:00 +0100337/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
338 * 'show ns' to output something about binds */
339DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
340 SHOW_STR SHOW_NS_STR)
341{
342 dump_ns_entities(vty, vty_nsi, false, false);
343 dump_ns_bind(vty, vty_nsi, false);
344 return CMD_SUCCESS;
345}
346
347
Harald Welte2fce19a2020-12-01 17:52:55 +0100348DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100349 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100350 "Display information about the NS protocol binds\n"
351 "Include statistic\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200352{
Harald Welte2fce19a2020-12-01 17:52:55 +0100353 bool stats = false;
354 if (argc > 0)
355 stats = true;
356
357 dump_ns_bind(vty, vty_nsi, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +0200358 return CMD_SUCCESS;
359}
360
Harald Welte2fce19a2020-12-01 17:52:55 +0100361DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100362 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +0100363 "Display information about the NS protocol entities (NSEs)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200364 "Include statistics\n")
365{
Harald Welte2fce19a2020-12-01 17:52:55 +0100366 bool stats = false;
367 if (argc > 0)
368 stats = true;
369
370 dump_ns_entities(vty, vty_nsi, stats, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200371 return CMD_SUCCESS;
372}
373
374DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100375 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200376 "Show only persistent NS\n")
377{
Harald Welte2fce19a2020-12-01 17:52:55 +0100378 dump_ns_entities(vty, vty_nsi, true, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200379 return CMD_SUCCESS;
380}
381
382DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +0100383 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +0200384 "Select one NSE by its NSE Identifier\n"
385 "Select one NSE by its NS-VC Identifier\n"
386 "The Identifier of selected type\n"
387 "Include Statistics\n")
388{
389 struct gprs_ns2_inst *nsi = vty_nsi;
390 struct gprs_ns2_nse *nse;
391 struct gprs_ns2_vc *nsvc;
392 uint16_t id = atoi(argv[1]);
393 bool show_stats = false;
394
395 if (argc >= 3)
396 show_stats = true;
397
398 if (!strcmp(argv[0], "nsei")) {
399 nse = gprs_ns2_nse_by_nsei(nsi, id);
400 if (!nse) {
401 return CMD_WARNING;
402 }
403
404 dump_nse(vty, nse, show_stats, false);
405 } else {
406 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
407
408 if (!nsvc) {
409 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
410 return CMD_WARNING;
411 }
412
413 dump_nsvc(vty, nsvc, show_stats);
414 }
415
416 return CMD_SUCCESS;
417}
418
Daniel Willmanndbab7142020-11-18 14:19:56 +0100419static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
420{
421 gprs_ns2_vc_force_unconfigured(nsvc);
422 return 0;
423}
424
425DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
426 "nsvc nsei <0-65535> force-unconfigured",
427 "NS Virtual Connection\n"
428 "The NSEI\n"
429 "Reset the NSVCs back to initial state\n"
430 )
431{
432 struct gprs_ns2_inst *nsi = vty_nsi;
433 struct gprs_ns2_nse *nse;
434
435 uint16_t id = atoi(argv[0]);
436
437 nse = gprs_ns2_nse_by_nsei(nsi, id);
438 if (!nse) {
439 vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
440 return CMD_WARNING;
441 }
442
443 /* Perform the operation for all nsvc */
444 gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
445
446 return CMD_SUCCESS;
447}
448
Alexander Couzens6a161492020-07-12 13:45:50 +0200449#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
450
Alexander Couzens841817e2020-11-19 00:41:29 +0100451DEFUN(cfg_nse_fr, cfg_nse_fr_cmd,
452 "nse <0-65535> nsvci <0-65535> (fr|frnet) NETIF dlci <0-1023>",
453 NSE_CMD_STR
454 "NS Virtual Connection\n"
455 "NS Virtual Connection ID (NSVCI)\n"
Harald Welte92049192020-11-25 20:56:06 +0100456 "Frame Relay User-Side\n"
457 "Frame Relay Network-Side\n"
Alexander Couzens841817e2020-11-19 00:41:29 +0100458 IFNAME_STR
459 "Data Link connection identifier\n"
460 "Data Link connection identifier\n"
461 )
462{
463 struct ns2_vty_vc *vtyvc;
464
465 uint16_t nsei = atoi(argv[0]);
466 uint16_t nsvci = atoi(argv[1]);
467 const char *role = argv[2];
468 const char *name = argv[3];
469 uint16_t dlci = atoi(argv[4]);
470
Harald Welte6d4db232020-11-25 19:33:42 +0100471 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens841817e2020-11-19 00:41:29 +0100472 if (!vtyvc) {
473 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
474 return CMD_WARNING;
475 }
476
477 if (!strcmp(role, "fr"))
478 vtyvc->fr.role = FR_ROLE_USER_EQUIPMENT;
479 else if (!strcmp(role, "frnet"))
480 vtyvc->fr.role = FR_ROLE_NETWORK_EQUIPMENT;
481
482 osmo_strlcpy(vtyvc->netif, name, sizeof(vtyvc->netif));
483 vtyvc->frdlci = dlci;
484 vtyvc->nsvci = nsvci;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100485 vtyvc->ll = GPRS_NS2_LL_FR;
Alexander Couzens841817e2020-11-19 00:41:29 +0100486
487 return CMD_SUCCESS;
488}
489
Alexander Couzens6a161492020-07-12 13:45:50 +0200490DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
491 "nse <0-65535> nsvci <0-65535>",
492 NSE_CMD_STR
493 "NS Virtual Connection\n"
494 "NS Virtual Connection ID (NSVCI)\n"
495 )
496{
497 struct ns2_vty_vc *vtyvc;
498
499 uint16_t nsei = atoi(argv[0]);
500 uint16_t nsvci = atoi(argv[1]);
501
Harald Welte6d4db232020-11-25 19:33:42 +0100502 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200503 if (!vtyvc) {
504 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
505 return CMD_WARNING;
506 }
507
508 vtyvc->nsvci = nsvci;
509
510 return CMD_SUCCESS;
511}
512
513DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100514 "nse <0-65535> remote-ip " VTY_IPV46_CMD,
Alexander Couzens6a161492020-07-12 13:45:50 +0200515 NSE_CMD_STR
516 "Remote IP Address\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200517 "Remote IPv4 Address\n"
518 "Remote IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200519{
520 uint16_t nsei = atoi(argv[0]);
521 struct ns2_vty_vc *vtyvc;
522
Harald Welte6d4db232020-11-25 19:33:42 +0100523 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200524 if (!vtyvc) {
525 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
526 return CMD_WARNING;
527 }
528
Harald Welte6d4db232020-11-25 19:33:42 +0100529 osmo_sockaddr_str_from_str2(&vtyvc->remote, argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200530
531 return CMD_SUCCESS;
532}
533
534DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100535 "nse <0-65535> remote-port <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200536 NSE_CMD_STR
537 "Remote UDP Port\n"
538 "Remote UDP Port Number\n")
539{
540 uint16_t nsei = atoi(argv[0]);
Harald Welte6d4db232020-11-25 19:33:42 +0100541 uint16_t port = atoi(argv[1]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200542 struct ns2_vty_vc *vtyvc;
543
Harald Welte6d4db232020-11-25 19:33:42 +0100544 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200545 if (!vtyvc) {
546 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
547 return CMD_WARNING;
548 }
549
550 vtyvc->remote.port = port;
551
552 return CMD_SUCCESS;
553}
554
555DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
Alexander Couzens841817e2020-11-19 00:41:29 +0100556 "nse <0-65535> nsvci <0-65535> fr-dlci <16-1007>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200557 NSE_CMD_STR
Harald Welte92049192020-11-25 20:56:06 +0100558 "NS Virtual Connection\n"
559 "NS Virtual Connection ID (NSVCI)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +0200560 "Frame Relay DLCI\n"
561 "Frame Relay DLCI Number\n")
562{
563 uint16_t nsei = atoi(argv[0]);
Alexander Couzens841817e2020-11-19 00:41:29 +0100564 uint16_t nsvci = atoi(argv[1]);
565 uint16_t dlci = atoi(argv[2]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200566 struct ns2_vty_vc *vtyvc;
567
Harald Welte6d4db232020-11-25 19:33:42 +0100568 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200569 if (!vtyvc) {
570 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
571 return CMD_WARNING;
572 }
573
Alexander Couzens6a161492020-07-12 13:45:50 +0200574 vtyvc->frdlci = dlci;
Harald Welte6d4db232020-11-25 19:33:42 +0100575 vtyvc->nsvci = nsvci;
Alexander Couzens6a161492020-07-12 13:45:50 +0200576
577 return CMD_SUCCESS;
578}
579
580DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100581 "nse <0-65535> encapsulation (udp|framerelay-gre)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200582 NSE_CMD_STR
583 "Encapsulation for NS\n"
584 "UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
585{
586 uint16_t nsei = atoi(argv[0]);
587 struct ns2_vty_vc *vtyvc;
588
Harald Welte6d4db232020-11-25 19:33:42 +0100589 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200590 if (!vtyvc) {
591 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
592 return CMD_WARNING;
593 }
594
Harald Welte6d4db232020-11-25 19:33:42 +0100595 if (!strcmp(argv[1], "udp"))
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100596 vtyvc->ll = GPRS_NS2_LL_UDP;
Alexander Couzens6a161492020-07-12 13:45:50 +0200597 else
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100598 vtyvc->ll = GPRS_NS2_LL_FR_GRE;
Alexander Couzens6a161492020-07-12 13:45:50 +0200599
600 return CMD_SUCCESS;
601}
602
603DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100604 "nse <0-65535> remote-role (sgsn|bss)",
Alexander Couzens6a161492020-07-12 13:45:50 +0200605 NSE_CMD_STR
606 "Remote NSE Role\n"
607 "Remote Peer is SGSN\n"
608 "Remote Peer is BSS\n")
609{
610 uint16_t nsei = atoi(argv[0]);
611 struct ns2_vty_vc *vtyvc;
612
Harald Welte6d4db232020-11-25 19:33:42 +0100613 vtyvc = vtyvc_by_nsei(nsei, true);
Alexander Couzens6a161492020-07-12 13:45:50 +0200614 if (!vtyvc) {
615 vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
616 return CMD_WARNING;
617 }
618
Harald Welte6d4db232020-11-25 19:33:42 +0100619 if (!strcmp(argv[1], "sgsn"))
Alexander Couzens6a161492020-07-12 13:45:50 +0200620 vtyvc->remote_end_is_sgsn = 1;
621 else
622 vtyvc->remote_end_is_sgsn = 0;
623
624 return CMD_SUCCESS;
625}
626
627DEFUN(cfg_no_nse, cfg_no_nse_cmd,
Harald Welte6d4db232020-11-25 19:33:42 +0100628 "no nse <0-65535>",
Alexander Couzens6a161492020-07-12 13:45:50 +0200629 "Delete Persistent NS Entity\n"
630 "Delete " NSE_CMD_STR)
631{
632 uint16_t nsei = atoi(argv[0]);
633 struct ns2_vty_vc *vtyvc;
634
Harald Welte6d4db232020-11-25 19:33:42 +0100635 vtyvc = vtyvc_by_nsei(nsei, false);
Alexander Couzens6a161492020-07-12 13:45:50 +0200636 if (!vtyvc) {
637 vty_out(vty, "The NSE %d does not exists.%s", nsei, VTY_NEWLINE);
638 return CMD_WARNING;
639 }
640
641 ns2_vc_free(vtyvc);
642
643 return CMD_SUCCESS;
644}
645
646DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
647 "timer " NS_TIMERS " <0-65535>",
648 "Network Service Timer\n"
649 NS_TIMERS_HELP "Timer Value\n")
650{
651 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
652 int val = atoi(argv[1]);
653
654 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
655 return CMD_WARNING;
656
657 vty_nsi->timeout[idx] = val;
658
659 return CMD_SUCCESS;
660}
661
662#define ENCAPS_STR "NS encapsulation options\n"
663
664DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
665 "encapsulation udp local-ip " VTY_IPV46_CMD,
666 ENCAPS_STR "NS over UDP Encapsulation\n"
667 "Set the IP address on which we listen for NS/UDP\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200668 "IPv4 Address\n"
669 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200670{
671 osmo_sockaddr_str_from_str2(&priv.udp, argv[0]);
672
673 return CMD_SUCCESS;
674}
675
676DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
677 "encapsulation udp local-port <0-65535>",
678 ENCAPS_STR "NS over UDP Encapsulation\n"
679 "Set the UDP port on which we listen for NS/UDP\n"
680 "UDP port number\n")
681{
682 unsigned int port = atoi(argv[0]);
683
684 priv.udp.port = port;
685
686 return CMD_SUCCESS;
687}
688
689DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd,
690 "encapsulation udp dscp <0-255>",
691 ENCAPS_STR "NS over UDP Encapsulation\n"
692 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
693{
694 int dscp = atoi(argv[0]);
695 struct gprs_ns2_vc_bind *bind;
696
697 priv.dscp = dscp;
698
699 llist_for_each_entry(bind, &vty_nsi->binding, list) {
700 if (gprs_ns2_is_ip_bind(bind))
701 gprs_ns2_ip_bind_set_dscp(bind, dscp);
702 }
703
704 return CMD_SUCCESS;
705}
706
707DEFUN(cfg_nsip_res_block_unblock, cfg_nsip_res_block_unblock_cmd,
708 "encapsulation udp use-reset-block-unblock (enabled|disabled)",
709 ENCAPS_STR "NS over UDP Encapsulation\n"
710 "Use NS-{RESET,BLOCK,UNBLOCK} procedures in violation of 3GPP TS 48.016\n"
711 "Enable NS-{RESET,BLOCK,UNBLOCK}\n"
712 "Disable NS-{RESET,BLOCK,UNBLOCK}\n")
713{
714 enum gprs_ns2_vc_mode vc_mode;
Alexander Couzens6a161492020-07-12 13:45:50 +0200715
716 if (!strcmp(argv[0], "enabled"))
717 vc_mode = NS2_VC_MODE_BLOCKRESET;
718 else
719 vc_mode = NS2_VC_MODE_ALIVE;
720
Alexander Couzens6a161492020-07-12 13:45:50 +0200721 priv.vc_mode = vc_mode;
722
Alexander Couzens6a161492020-07-12 13:45:50 +0200723 return CMD_SUCCESS;
724}
725
726DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
727 "encapsulation framerelay-gre local-ip " VTY_IPV46_CMD,
728 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
729 "Set the IP address on which we listen for NS/FR/GRE\n"
Alexander Couzensc82c40a2020-09-24 05:55:48 +0200730 "IPv4 Address\n"
731 "IPv6 Address\n")
Alexander Couzens6a161492020-07-12 13:45:50 +0200732{
733 osmo_sockaddr_str_from_str2(&priv.frgreaddr, argv[0]);
734
735 return CMD_SUCCESS;
736}
737
738DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
739 "encapsulation framerelay-gre enabled (1|0)",
740 ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
741 "Enable or disable Frame Relay over GRE\n"
742 "Enable\n" "Disable\n")
743{
744 int enabled = atoi(argv[0]);
745
746 priv.frgre = enabled;
747
748 return CMD_SUCCESS;
749}
750
751/* TODO: allow vty to reset/block/unblock nsvc/nsei */
752
Daniel Willmann751977b2020-12-02 18:59:44 +0100753DEFUN(logging_fltr_nse,
754 logging_fltr_nse_cmd,
755 "logging filter nse nsei <0-65535>",
756 LOGGING_STR FILTER_STR
757 "Filter based on NS Entity\n"
758 "Identify NSE by NSEI\n"
759 "Numeric identifier\n")
760{
761 struct log_target *tgt;
762 struct gprs_ns2_nse *nse;
Daniel Willmann89106522020-12-04 01:36:59 +0100763 uint16_t id = atoi(argv[0]);
Daniel Willmann751977b2020-12-02 18:59:44 +0100764
765 log_tgt_mutex_lock();
766 tgt = osmo_log_vty2tgt(vty);
767 if (!tgt) {
768 log_tgt_mutex_unlock();
769 return CMD_WARNING;
770 }
771
772 nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
773 if (!nse) {
774 vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
775 log_tgt_mutex_unlock();
776 return CMD_WARNING;
777 }
778
779 log_set_nse_filter(tgt, nse);
780 log_tgt_mutex_unlock();
781 return CMD_SUCCESS;
782}
783
Alexander Couzens6a161492020-07-12 13:45:50 +0200784/* TODO: add filter for single connection by description */
785DEFUN(logging_fltr_nsvc,
786 logging_fltr_nsvc_cmd,
787 "logging filter nsvc nsvci <0-65535>",
788 LOGGING_STR FILTER_STR
789 "Filter based on NS Virtual Connection\n"
790 "Identify NS-VC by NSVCI\n"
791 "Numeric identifier\n")
792{
793 struct log_target *tgt;
794 struct gprs_ns2_vc *nsvc;
Daniel Willmann89106522020-12-04 01:36:59 +0100795 uint16_t id = atoi(argv[0]);
Alexander Couzens6a161492020-07-12 13:45:50 +0200796
797 log_tgt_mutex_lock();
798 tgt = osmo_log_vty2tgt(vty);
799 if (!tgt) {
800 log_tgt_mutex_unlock();
801 return CMD_WARNING;
802 }
803
804 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
805 if (!nsvc) {
806 vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
807 log_tgt_mutex_unlock();
808 return CMD_WARNING;
809 }
810
811 log_set_nsvc_filter(tgt, nsvc);
812 log_tgt_mutex_unlock();
813 return CMD_SUCCESS;
814}
815
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200816/**
817 * gprs_ns2_vty_init initialize the vty
818 * \param[inout] nsi
819 * \param[in] default_bind set the default address to bind to. Can be NULL.
820 * \return 0 on success
821 */
Vadim Yanitskiya07f25e2020-10-09 21:47:01 +0700822int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
823 const struct osmo_sockaddr_str *default_bind)
Alexander Couzens6a161492020-07-12 13:45:50 +0200824{
825 static bool vty_elements_installed = false;
826
827 vty_nsi = nsi;
828 memset(&priv, 0, sizeof(struct ns2_vty_priv));
829 INIT_LLIST_HEAD(&priv.vtyvc);
830 priv.vc_mode = NS2_VC_MODE_BLOCKRESET;
Alexander Couzens1fac6f72020-10-01 19:08:38 +0200831 if (default_bind)
832 memcpy(&priv.udp, default_bind, sizeof(*default_bind));
Alexander Couzens6a161492020-07-12 13:45:50 +0200833
834 /* Regression test code may call this function repeatedly, so make sure
835 * that VTY elements are not duplicated, which would assert. */
836 if (vty_elements_installed)
837 return 0;
838 vty_elements_installed = true;
839
Harald Welte25ee7552020-12-02 22:14:00 +0100840 install_lib_element_ve(&show_ns_cmd);
Harald Welte2fce19a2020-12-01 17:52:55 +0100841 install_lib_element_ve(&show_ns_binds_cmd);
842 install_lib_element_ve(&show_ns_entities_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700843 install_lib_element_ve(&show_ns_pers_cmd);
844 install_lib_element_ve(&show_nse_cmd);
Daniel Willmann751977b2020-12-02 18:59:44 +0100845 install_lib_element_ve(&logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700846 install_lib_element_ve(&logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200847
Daniel Willmanndbab7142020-11-18 14:19:56 +0100848 install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
849
Daniel Willmann751977b2020-12-02 18:59:44 +0100850 install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700851 install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200852
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700853 install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200854 install_node(&ns_node, config_write_ns);
Alexander Couzens841817e2020-11-19 00:41:29 +0100855 install_lib_element(L_NS_NODE, &cfg_nse_fr_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700856 install_lib_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
857 install_lib_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
858 install_lib_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
859 install_lib_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
860 install_lib_element(L_NS_NODE, &cfg_nse_encaps_cmd);
861 install_lib_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
862 install_lib_element(L_NS_NODE, &cfg_no_nse_cmd);
863 install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
864 install_lib_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);
865 install_lib_element(L_NS_NODE, &cfg_nsip_local_port_cmd);
866 install_lib_element(L_NS_NODE, &cfg_nsip_dscp_cmd);
867 install_lib_element(L_NS_NODE, &cfg_nsip_res_block_unblock_cmd);
868 install_lib_element(L_NS_NODE, &cfg_frgre_enable_cmd);
869 install_lib_element(L_NS_NODE, &cfg_frgre_local_ip_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +0200870
871 /* TODO: nsvc/nsei command to reset states or reset/block/unblock nsei/nsvcs */
872
873 return 0;
874}
875
876/*!
877 * \brief gprs_ns2_vty_create parse the vty tree into ns nodes
878 * It has to be in different steps to ensure the bind is created before creating VCs.
879 * \return 0 on success
880 */
881int gprs_ns2_vty_create() {
882 struct ns2_vty_vc *vtyvc;
Alexander Couzens841817e2020-11-19 00:41:29 +0100883 struct gprs_ns2_vc_bind *bind, *fr;
Alexander Couzens6a161492020-07-12 13:45:50 +0200884 struct gprs_ns2_nse *nse;
885 struct gprs_ns2_vc *nsvc;
886 struct osmo_sockaddr sockaddr;
Alexander Couzensd923cff2020-12-01 01:03:52 +0100887 enum gprs_ns2_dialect dialect = NS2_DIALECT_UNDEF;
Alexander Couzens841817e2020-11-19 00:41:29 +0100888 int rc = 0;
Alexander Couzens6a161492020-07-12 13:45:50 +0200889
890 if (!vty_nsi)
891 return -1;
892
893 /* create binds, only support a single bind. either FR or UDP */
894 if (priv.frgre) {
895 /* TODO not yet supported !*/
896 return -1;
897 } else {
898 /* UDP */
899 osmo_sockaddr_str_to_sockaddr(&priv.udp, &sockaddr.u.sas);
Alexander Couzensaaa55a62020-12-03 06:02:03 +0100900 if (gprs_ns2_ip_bind(vty_nsi, "vtybind", &sockaddr, priv.dscp, &bind)) {
Alexander Couzens6a161492020-07-12 13:45:50 +0200901 /* TODO: could not bind on the specific address */
902 return -1;
903 }
Alexander Couzensd923cff2020-12-01 01:03:52 +0100904 bind->accept_ipaccess = true;
Alexander Couzens6a161492020-07-12 13:45:50 +0200905 }
906
907 /* create vcs */
908 llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
Alexander Couzens841817e2020-11-19 00:41:29 +0100909 /* validate settings */
910 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100911 case GPRS_NS2_LL_UDP:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100912 dialect = NS2_DIALECT_IPACCESS;
Alexander Couzens841817e2020-11-19 00:41:29 +0100913 if (strlen(vtyvc->remote.ip) == 0) {
914 /* Invalid IP for VC */
915 continue;
916 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200917
Alexander Couzens841817e2020-11-19 00:41:29 +0100918 if (!vtyvc->remote.port) {
919 /* Invalid port for VC */
920 continue;
921 }
Alexander Couzens6a161492020-07-12 13:45:50 +0200922
Alexander Couzens841817e2020-11-19 00:41:29 +0100923 if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
924 /* Invalid sockaddr for VC */
925 continue;
926 }
927 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100928 case GPRS_NS2_LL_FR:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100929 dialect = NS2_DIALECT_STATIC_RESETBLOCK;
Alexander Couzens841817e2020-11-19 00:41:29 +0100930 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100931 case GPRS_NS2_LL_FR_GRE:
Alexander Couzensd923cff2020-12-01 01:03:52 +0100932 dialect = NS2_DIALECT_STATIC_RESETBLOCK;
Alexander Couzens6a161492020-07-12 13:45:50 +0200933 continue;
934 }
935
936 nse = gprs_ns2_nse_by_nsei(vty_nsi, vtyvc->nsei);
937 if (!nse) {
Alexander Couzensd923cff2020-12-01 01:03:52 +0100938 nse = gprs_ns2_create_nse(vty_nsi, vtyvc->nsei, vtyvc->ll, dialect);
Alexander Couzens6a161492020-07-12 13:45:50 +0200939 if (!nse) {
940 /* Could not create NSE for VTY */
941 continue;
942 }
943 }
944 nse->persistent = true;
945
Alexander Couzens841817e2020-11-19 00:41:29 +0100946 switch (vtyvc->ll) {
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100947 case GPRS_NS2_LL_UDP:
Alexander Couzens841817e2020-11-19 00:41:29 +0100948 nsvc = gprs_ns2_ip_connect(bind,
949 &sockaddr,
950 nse,
951 vtyvc->nsvci);
952 if (!nsvc) {
953 /* Could not create NSVC, connect failed */
954 continue;
955 }
956 nsvc->persistent = true;
957 break;
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100958 case GPRS_NS2_LL_FR: {
Alexander Couzens841817e2020-11-19 00:41:29 +0100959 if (vty_fr_network == NULL) {
960 /* TODO: add a switch for BSS/SGSN/gbproxy */
961 vty_fr_network = osmo_fr_network_alloc(vty_nsi);
962 }
963 fr = gprs_ns2_fr_bind_by_netif(
964 vty_nsi,
965 vtyvc->netif);
966 if (!fr) {
Alexander Couzensaaa55a62020-12-03 06:02:03 +0100967 rc = gprs_ns2_fr_bind(vty_nsi, vtyvc->netif, vtyvc->netif, vty_fr_network, vtyvc->fr.role, &fr);
Alexander Couzens841817e2020-11-19 00:41:29 +0100968 if (rc < 0) {
969 LOGP(DLNS, LOGL_ERROR, "Can not create fr bind on device %s err: %d\n", vtyvc->netif, rc);
970 return rc;
971 }
972 }
973
Alexander Couzensebcbd722020-12-03 06:11:39 +0100974 nsvc = gprs_ns2_fr_connect(fr, nse, vtyvc->nsvci, vtyvc->frdlci);
Alexander Couzens841817e2020-11-19 00:41:29 +0100975 if (!nsvc) {
976 /* Could not create NSVC, connect failed */
977 continue;
978 }
979 nsvc->persistent = true;
980 break;
981 }
Alexander Couzens24a14ac2020-11-19 02:34:49 +0100982 case GPRS_NS2_LL_FR_GRE:
Alexander Couzensd745a0e2020-10-07 00:50:00 +0200983 continue;
Alexander Couzens6a161492020-07-12 13:45:50 +0200984 }
985 }
986
987
988 return 0;
989}